从 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 以正确对齐。因此,vec3
与vec4
具有相同的对齐规则。
现在,您的 vec3
从错误的边界开始。 vec3
和 vec4
数据类型需要对齐到 4N 的倍数(其中 N 是 float
的大小)。
以下更改通过重新排列 vf1
和 f1
来解决此问题:
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 中的数组初始化结构的主要内容,如果未能解决你的问题,请参考以下文章