因此,我已经了解到存储缓冲区能够在末尾包含可变长度数组:
UBO可以有可变的存储,最多可以绑定到该特定缓冲区的任何缓冲区;
必须具有特定的、固定的存储大小。这意味着SSBO中可以有一个任意长度的数组(最后)。数组的实际大小,基于缓冲区绑定的范围,可以在运行时使用无界数组变量的length函数在着色器中查询。
我知道如何将存储缓冲区作为带有以下简单字段的结构传递:
struct GPUStorage {
glm::vec3 mesh_pos;
glm::vec4 mesh_rot;
};并知道如何将存储缓冲区作为结构数组传递,方法是将存储缓冲区推入vector,并以复制长度作为sizeof(GPUStorage) * vector.size()在vector.data()上执行sizeof(GPUStorage) * vector.size()操作。
但是,我还没有发现C++语法如何查找包含可变长度数组的结构?
struct GPUMesh {
glm::vec3 mesh_pos;
glm::vec4 mesh_rot;
};
struct GPUStorage {
??? // variable length array of GPUMesh
};发布于 2019-12-06 21:00:54
你以一种非常有限的方式欺骗自己去思考事情。也就是说,从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));
}或者先构建一个临时内存缓冲区,然后在创建存储时执行副本。或者其他任何技术。
https://stackoverflow.com/questions/59219828
复制相似问题