Frage

Suppose I have an array variable in a shader, declared in a shader storage block:

layout(std430, binding = 2) buffer MyBuffer
{
  float lotsOfFloats[];
};

and a struct:

struct myStruct
{
 float f1;
 vec3 vf1;
}struct1;

Is there a way to "quickly" initialize an object of this structure in a shader using the values in the array in a buffer storage block ( in the lotsOfFloats array in this example)? Say, in C++ one can copy memory from the array to the object:

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

Or one can byte copy array values to the object through assignment:

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

Is there a similar way in GLSL? E.g. will work the second way (byte copy assignment) in GLSL?

War es hilfreich?

Lösung

Rather than treating your SSB as an unstructured array of floats, you can actually declare it as an unsized array of your structure:

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

layout(std430, binding = 2) buffer MyBuffer
{
  myStruct lotsOfStructs[];
};

There is one minor problem with your struct the way it is currently written:

GPUs do not like most 3-component data types and generally have to treat them like 4-component for proper alignment. Thus, vec3 has the same alignment rules as vec4.

Right now, you have a vec3 beginning on the wrong boundary. vec3 and vec4 data types need to be aligned to a multiple of 4N (where N is the size of a float).

The following change addresses this issue by re-arranging vf1 and f1:

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

(Single-precision) scalars can be aligned on any boundary since they have a size 1N, so you can put f1 right after vf1 with no problems.


You might find it useful to know that with std430, there is one additional requirement that says the size of the struct must be a multiple of the largest base alignment. In this case the largest base alignment of any member in this struct is for vf1 (vec3), which has a base alignment of 4N.

That means that if you did not have f1 at the end of the structure (its size would be 3N), GL would automatically add 1N worth of padding to the end of the structure and you would need to account for GL's behavior in your C code. Your structure is already 4N aligned, so you are good to go, but if you did not know this it could come a surprise later on.

You should read up on 7.6.2.2 Standard Uniform Block Layout, alignment is very important when dealing with Shader Storage Buffers and Uniform Buffers.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top