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

C++ C++;Vulkan中发送给GLSL的可变长度数组的语法,c++,glsl,vulkan,C++,Glsl,Vulkan,所以我读过关于存储缓冲区能够在末尾包含可变长度数组的内容: SSBO可以具有可变存储,最多可存储为该特定缓冲区绑定的任何缓冲区范围;UBO必须具有特定的固定存储大小。这意味着您可以在SSBO中拥有任意长度的数组(而不是在最后)。基于缓冲区范围的数组的实际大小可以在运行时使用unbounded array变量上的length函数在着色器中查询 我知道如何使用以下简单字段将存储缓冲区作为结构传递: struct GPUStorage { glm::vec3 mesh_pos; glm::

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

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

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

struct GPUStorage {
   glm::vec3 mesh_pos;
   glm::vec4 mesh_rot;
};
并知道如何将存储缓冲区作为结构数组传递,方法是将它们推入
向量中,并在
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\u t numarayentries=;
glNamedBufferStorage(buff,16+(16*numarayentries),nullptr,GL_动态存储位);
glm::vec2 first=;
glNamedBufferSubData(buff,0,8,glm::value_ptr(first));
对于(std::size\u t entry=0;entry
这显然是一项繁重的工作,需要大量的上传,但它是可以使用的。您还可以通过映射缓冲区来获取数据:

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));
}
std::size\u t numarayentries=;
std::size\u t buffSize=16+(16*numarayentries)
glNamedBufferStorage(buff、buffSize、nullptr、GL_-MAP_-WRITE_-BIT | GL_-MAP_-PERSISTENT_-BIT | GL_-MAP_-COHERENT_-BIT);
无符号字符*数据=(无符号字符*)glMapNamedBufferRange(buff,0,buffSize,GL_-MAP_写入位| GL_-MAP_持久位| GL_-MAP_相干位);
glm::vec2 first=;
memcpy(数据,glm::value_ptr(第一),8);
对于(std::size\u t entry=0;entry

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

你欺骗自己,让自己以一种非常有限的方式思考问题。也就是说,使用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\u t numarayentries=;
glNamedBufferStorage(buff,16+(16*numarayentries),nullptr,GL_动态存储位);
glm::vec2 first=;
glNamedBufferSubData(buff,0,8,glm::value_ptr(first));
对于(std::size\u t entry=0;entry
这显然是一项繁重的工作,需要大量的上传,但它是可以使用的。您还可以通过映射缓冲区来获取数据:

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));
}
std::size\u t numarayentries=;
std::size\u t buffSize=16+(16*numarayentries)
glNamedBufferStorage(buff、buffSize、nullptr、GL_-MAP_-WRITE_-BIT | GL_-MAP_-PERSISTENT_-BIT | GL_-MAP_-COHERENT_-BIT);
无符号字符*数据=(无符号字符*)glMapNamedBufferRange(buff,0,buffSize,GL_-MAP_写入位| GL_-MAP_持久位| GL_-MAP_相干位);
glm::vec2 first=;
memcpy(数据,glm::value_ptr(第一),8);
对于(std::size\u t entry=0;entry

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

C++
没有VLA(非标准编译器扩展除外)
C
确实有VLA。“我知道如何将存储缓冲区作为具有以下简单字段的结构传递:“
alignas
如果放在
struct
的字段前面,它似乎可以正常工作,16字节对齐是否也适用于存储缓冲区?
C++
没有VLA。”(非标准编译器扩展除外)。
C
确实有VLA。“我知道如何将存储缓冲区作为具有以下简单字段的结构传递:”
alignas
如果你把它放在
struct
的字段前面,它似乎工作得很好,16字节的对齐方式也适用于存储缓冲区吗?我担心这一点。因此,基本上是抛弃
struct
包装器,用
memcpy
void*
中编写要传输的内容s@MacelaruTiberiu:嗯,想必,您想要有一个无界数组的原因是因为您在编译时不知道