首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >变长数组在Vulkan中发送到GLSL的C++语法

变长数组在Vulkan中发送到GLSL的C++语法
EN

Stack Overflow用户
提问于 2019-12-06 20:19:52
回答 1查看 668关注 0票数 1

因此,我已经了解到存储缓冲区能够在末尾包含可变长度数组:

UBO可以有可变的存储,最多可以绑定到该特定缓冲区的任何缓冲区;

必须具有特定的、固定的存储大小。这意味着SSBO中可以有一个任意长度的数组(最后)。数组的实际大小,基于缓冲区绑定的范围,可以在运行时使用无界数组变量的length函数在着色器中查询。

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

代码语言:javascript
复制
struct GPUStorage {
   glm::vec3 mesh_pos;
   glm::vec4 mesh_rot;
};

并知道如何将存储缓冲区作为结构数组传递,方法是将存储缓冲区推入vector,并以复制长度作为sizeof(GPUStorage) * vector.size()vector.data()上执行sizeof(GPUStorage) * vector.size()操作。

但是,我还没有发现C++语法如何查找包含可变长度数组的结构?

代码语言:javascript
复制
struct GPUMesh {
    glm::vec3 mesh_pos;
    glm::vec4 mesh_rot;
};

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

回答 1

Stack Overflow用户

发布于 2019-12-06 21:00:54

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

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

定义为:

代码语言:javascript
复制
layout(binding = 0, std430) buffer Data
{
  vec2 first;
  vec4 array[];
};

这个数据的布局是这样的,前8个字节表示两个浮点值.后面是跳过的8个字节,后面是16个字节的倍数,每个16字节的数据代表4个浮点值。

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

代码语言:javascript
复制
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));
}

这显然是沉重的和涉及很多上传,但它是有用的。您还可以通过映射缓冲区获得数据:

代码语言:javascript
复制
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));
}

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

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59219828

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档