假设我在着色器中有一个数组变量,在着色器存储块中声明:
layout(std430, binding = 2) buffer MyBuffer
{
float lotsOfFloats[];
};
Run Code Online (Sandbox Code Playgroud)
和结构:
struct myStruct
{
float f1;
vec3 vf1;
}struct1;
Run Code Online (Sandbox Code Playgroud)
有没有办法使用缓冲区存储块中的数组中的值(在此示例中的lotsOfFloats数组中)在着色器中"快速"初始化此结构的对象?比方说,在C++中,可以将内存从数组复制到对象:
memcpy(&struct1, &lotsOfFloats[0], sizeof(myStruct) );
Run Code Online (Sandbox Code Playgroud)
或者可以通过赋值将数组值字节复制到对象:
struct1 = *(myStruct*)&lotsOfFloats[0];
Run Code Online (Sandbox Code Playgroud)
GLSL中有类似的方法吗?例如,将在GLSL中使用第二种方式(字节复制分配)吗?
您可以将其声明为结构的未大小数组,而不是将SSB视为非结构化的浮点数组:
struct myStruct
{ // Addresses Occupied
float f1; // 0N
vec3 vf1; // 1N,2N,3N
};
layout(std430, binding = 2) buffer MyBuffer
{
myStruct lotsOfStructs[];
};
Run Code Online (Sandbox Code Playgroud)
GPU不喜欢大多数3组件数据类型,并且通常必须将它们视为4组件才能正确对齐.因此,vec3具有相同的对齐规则vec4.
现在,你有一个vec3错误边界的开端.vec3并且vec4数据类型需要与4N的倍数对齐(其中N是a的大小float).
vf1和解决此问题f1:struct myStruct
{ // Addresses Occupied
vec3 vf1; // 0N,1N,2N
float f1; // 3N
};
Run Code Online (Sandbox Code Playgroud)
(单精度)标量可以在任何边界上对齐,因为它们的大小为1N,因此您可以f1在vf1没有问题的情况下立即放置.
您可能会发现有用的是std430,有一个额外的要求,即结构的大小必须是最大基本对齐的倍数.在这种情况下,此结构中任何成员的最大基本对齐方式是for vf1(vec3),其基本对齐方式为4N.
这意味着如果你没有f1在结构的末尾(它的大小将是3N),GL将自动添加1N值的填充到结构的末尾,你需要考虑GL在C代码中的行为.你的结构已经是4N对齐,所以你很高兴,但如果你不知道这一点,它可能会在以后出现意外.
您应该阅读7.6.2.2 Standard Uniform Block Layout,在处理着色器存储缓冲区和统一缓冲区时,对齐非常重要.
| 归档时间: |
|
| 查看次数: |
1265 次 |
| 最近记录: |