从 GLSL 中的数组初始化结构

Posted

技术标签:

【中文标题】从 GLSL 中的数组初始化结构【英文标题】:Initializing structures from arrays in GLSL 【发布时间】:2014-05-02 16:52:01 【问题描述】:

假设我在着色器中有一个数组变量,在着色器存储块中声明:

layout(std430, binding = 2) buffer MyBuffer

  float lotsOfFloats[];
;

还有一个结构:

struct myStruct

 float f1;
 vec3 vf1;
struct1;

有没有办法使用缓冲区存储块中数组中的值(在本例中为 lotOfFloats 数组)在着色器中“快速”初始化此结构的对象?比如说,在 C++ 中,可以将内存从数组复制到对象:

memcpy(&struct1, &lotsOfFloats[0], sizeof(myStruct) );

或者可以通过赋值将数组值字节复制到对象:

struct1 = *(myStruct*)&lotsOfFloats[0];

GLSL 中是否有类似的方法?例如。将在 GLSL 中使用第二种方式(字节复制分配)吗?

【问题讨论】:

你知道你可以在你的 SSB 声明中使用一个大小不一的结构数组,对吧? (例如 myStruct lotsOfStructs [];)。这通常是这种事情的完成方式。请注意对齐 - 如果您交换 f1 和 @ 987654328@ 它将正确对齐。 @Andon,谢谢!这条评论可以算作答案。 【参考方案1】:

您实际上可以将 SSB 声明为结构的无大小数组,而不是将您的 SSB 视为非结构化的浮点数组:

struct myStruct
              // Addresses Occupied
  float f1;    // 0N
  vec3  vf1;   // 1N,2N,3N
;

layout(std430, binding = 2) buffer MyBuffer

  myStruct lotsOfStructs[];
;

您的结构目前的编写方式存在一个小问题:

GPU 不喜欢大多数 3-component 数据类型,通常必须将它们视为 4-component 以正确对齐。因此,vec3vec4 具有相同的对齐规则。

现在,您的 vec3 从错误的边界开始。 vec3vec4 数据类型需要对齐到 4N 的倍数(其中 N 是 float 的大小)。

以下更改通过重新排列 vf1f1 来解决此问题:

struct myStruct
              // Addresses Occupied
  vec3  vf1;   // 0N,1N,2N
  float f1;    // 3N
;

(单精度)标量可以在任何边界上对齐,因为它们的大小为 1N,因此您可以将 f1 紧跟在 vf1 之后。


知道std430 有一个额外的要求,即结构的大小必须是最大基本对齐的倍数,您可能会发现这很有用。在这种情况下,此结构中任何成员的最大基本对齐是针对vf1 (vec3),其基本对齐为 4N。

这意味着如果你在结构的末尾没有f1(它的大小为 3N),GL 会自动在结构的末尾添加 1N 的填充,你需要考虑 GL C 代码中的行为。你的结构已经是 4N 对齐的,所以你很高兴,但如果你不知道这一点,以后可能会出人意料。

您应该阅读7.6.2.2 Standard Uniform Block Layout,在处理着色器存储缓冲区和统一缓冲区时对齐非常重要。

【讨论】:

以上是关于从 GLSL 中的数组初始化结构的主要内容,如果未能解决你的问题,请参考以下文章

c语言,结构体数组怎么初始化

GLSL 结构数组 - 内存分配/对齐

C语言结构体数组的初始化

结构或类中的数组初始化

c语言中,结构体初始化和数组初始化的写法是否一样的?求解,谢谢

C++ 如何将一个静态结构体数组初始化?