繁体   English   中英

将可变长度数组发送到 Vulkan 中的 GLSL 的 C++ 语法

[英]C++ Syntax for variable length array to be sent to GLSL in Vulkan

所以我读过有关存储缓冲区能够在末尾包含可变长度数组的信息:

SSBO 可以有可变的存储空间,直至为该特定缓冲区绑定的任何缓冲区范围; UBO 必须具有特定的、固定的存储大小。 这意味着您可以在 SSBO 中拥有任意长度的数组(而不是在最后)。 数组的实际大小,基于缓冲区绑定的范围,可以在运行时在着色器中使用 unbounded 数组变量上的 length 函数查询

我知道如何将存储缓冲区作为具有如下简单字段的结构传递:

struct GPUStorage {
   glm::vec3 mesh_pos;
   glm::vec4 mesh_rot;
};

并知道如何通过将存储缓冲区作为结构数组传递到vector ,并在vector.data()上执行memcpy ,复制长度为sizeof(GPUStorage) * vector.size()

但我还没有在任何地方找到 C++ 语法如何查找包含可变长度数组的结构?

struct GPUMesh {
    glm::vec3 mesh_pos;
    glm::vec4 mesh_rot;
};

struct GPUStorage {
    ???  // variable length array of GPUMesh 
};

你欺骗自己以非常有限的方式思考事情。 也就是说,从 C++ 使用资源缓冲区 (UBO/SSBO) 的唯一方法是定义一个 C++ 对象类型,其布局与资源的布局匹配。 它不是。

缓冲区支持的接口块的布局定义了 GLSL 将如何解释缓冲区提供的数据字节。 这些字节如何进入这些位置完全取决于您。

一个存储块定义为:

layout(binding = 0, std430) buffer Data
{
  vec2 first;
  vec4 array[];
};

该数据的布局使得前 8 个字节代表两个浮点值。 接下来是跳过的 8 个字节,然后是 16 个字节的倍数,每个 16 字节数据代表 4 个浮点值。

如何在缓冲区对象中创建它取决于您。 你可以这样做:

std::size_t numArrayEntries = <get number of array entries>;
glNamedBufferStorage(buff, 16 + (16 * numArrayEntries), nullptr, GL_DYNAMIC_STORAGE_BIT);

glm::vec2 first = <get first>;
glNamedBufferSubData(buff, 0, 8, glm::value_ptr(first));

for(std::size_t entry = 0; entry < numArrayEntries; ++entry)
{
  glm::vec4 entryValue = <get actual entry value>;
  glNamedBufferSubData(buff, 16, 16, glm::value_ptr(entryValue));
}

这显然是严厉的并且涉及大量上传,但它是有用的。 您还可以通过映射缓冲区来获取数据:

std::size_t numArrayEntries = <get number of array entries>;
std::size_t buffSize = 16 + (16 * numArrayEntries)
glNamedBufferStorage(buff, buffSize, nullptr, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);

unsigned char *data = (unsigned char*)glMapNamedBufferRange(buff, 0, buffSize, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);

glm::vec2 first = <get first>;
memcpy(data, glm::value_ptr(first), 8);

for(std::size_t entry = 0; entry < numArrayEntries; ++entry)
{
  data += 16
  glm::vec4 entryValue = <get actual entry value>;
  memcpy(data, glm::value_ptr(entryValue));
}

或者先构建一个临时内存缓冲区,然后在创建存储时进行复制。 或任何其他技术。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM