Search code examples
openglglslshader-storage-buffer

How to get shader storage block's variable offset when using layout(packed) or layout(shared) in OpenGL?


If I have a shader storage block defined in GLSL like this:

buffer test_block
{
    type1 var1;
    type2 var2;
    type3 var3;
};

How to get the offset of one of the variable in this block?

We know that if it is a uniform block just like this:

uniform test_block
{
    type1 var1;
    type2 var2;
    type3 var3;
};

we can get offset in this way, for example get the offset of var2:

char[] var2_name = "var2";
int var2_index;
glGetUniformIndices(program_id, 1, &var2_name, &var2_index);

int var2_offset;
glGetActiveUniformsiv(program_id, 1, &var2_index, GL_UNIFORM_OFFSET, &var2_offset);

// then var2_offset is what you want

This is for uniform block. But I can't find any tutorial of getting offset of shader storeage block variable's offset.

(Don't tell me to use std140 or std430, I know this way. I want to write program don't depend on specific memory layout. Just get the offset programmatically.)

I tried to find functions jusk like glGetUniformIndices and glGetActiveUniformsiv which is suite for shader storage block. But there is no such functions.

I expect one way to get shader storage block variable's offset programmatically just like getting uniform block variable's offset.


Solution

  • The program interface query API is a generic tool for querying any of the external interface components of a program. Inputs, outputs, uniforms, and yes, storage buffers. There are separate APIs for many of these interfaces (like glGetUniformIndices), but a generic one was created that accounts for all of the existing ones.

    As well as SSBOs.

    The different kinds of queryable properties are called "interfaces". Properties about uniform blocks are queried through the GL_UNIFORM_BLOCK interface, but the members of a uniform block are queried through the GL_UNIFORM interface. Similarly, the GL_SHADER_STORAGE_BLOCK is for querying properties of a storage block, but properties of the actual members of the block are queried through the GL_BUFFER_VARIABLE interface.

    So the program interface query equivalent of your uniform querying code would be:

    GLuint var2_index = glGetProgramResourceIndex(program_id, GL_UNIFORM, "var2");
    
    GLenum props[] = {GL_OFFSET};
    GLint var2_offset;
    
    glGetProgramResourceiv(program_id, GL_UNIFORM, var2_index, 1, props, 1, nullptr, &var2_offset);
    

    The SSBO equivalent would be:

    GLuint var2_index = glGetProgramResourceIndex(program_id, GL_BUFFER_VARIABLE, "var2");
    
    GLenum props[] = {GL_OFFSET};
    GLint var2_offset;
    
    glGetProgramResourceiv(program_id, GL_BUFFER_VARIABLE, var2_index, 1, props, 1, nullptr, &var2_offset);