Search code examples
c++openglgraphics3dopengl-4

How to specify UBO binding with bindless?


I create 2+ simple UBO's with vec4 colorA's and colorB's like so. I only get a black screen using the UBO creation / binding process with std140. How do I specify which index while using glCreate and get this mess to work so I can choose colorA or colorB?

//APP
glCreateBuffers(1, &testUBO);
glNamedBufferData(testUBO, sizeof(glm::vec4), 0, GL_DYNAMIC_DRAW);
glGetNamedBufferParameterui64vNV(testUBO, GL_BUFFER_GPU_ADDRESS_NV, &uboScene_64);
glMakeNamedBufferResidentNV(testUBO, GL_READ_ONLY);


glm::vec4 myVec4 = glm::vec4(0.f, 1.f, 0.f, 1.f); //add to structs.h
glNamedBufferSubData(testUBO, 0, sizeof(glm::vec4), &myVec4

//SHARED HEADER
typedef glm::vec4 vec4;

layout(std140, binding = 0) uniform sceneBuffer
{
    vec4 colorA;
};

layout(std140, binding = 1) uniform objectBuffer
{
    vec4 colorB;
};

//SHADER PROGRAM
void main()
{
    Ci = colorA;
    Ci = colorB;
}

Solution

  • Given this shader:

    //GLSL
    layout(std140, binding = 0) uniform sceneBuffer
    {
        vec4 colorA;
    };
    
    layout(std140, binding = 1) uniform objectBuffer
    {
        vec4 colorB;
    };
    

    And this C++ buffer initialization code:

    //Create scene buffer.
    glCreateBuffers(1, &sceneUbo);
    glNamedBufferStorage(sceneUbo, sizeof(glm::vec4), 0, GL_DYNAMIC_STORAGE_BIT);
    
    glm::vec4 myVec4 = glm::vec4(0.f, 1.f, 0.f, 1.f);
    glNamedBufferSubData(sceneUbo, 0, sizeof(glm::vec4), &myVec4);
    
    //Create object buffer
    glCreateBuffers(1, &objectUbo);
    glNamedBufferStorage(objectUbo, sizeof(glm::vec4), 0, GL_DYNAMIC_STORAGE_BIT);
    
    glm::vec4 myVec4 = glm::vec4(0.f, 1.f, 0.f, 1.f);
    glNamedBufferSubData(objectUbo, 0, sizeof(glm::vec4), &myVec4);
    

    Here is what the the NV_uniform_buffer_unified_memory "bindless" code looks like:

    //Get addresses
    GLuint64 sceneUboAddr;
    glGetNamedBufferParameterui64vNV(sceneUbo, GL_BUFFER_GPU_ADDRESS_NV, &sceneUboAddr);
    glMakeNamedBufferResidentNV(sceneUbo, GL_READ_ONLY);
    
    GLuint64 objectUboAddr;
    glGetNamedBufferParameterui64vNV(objectUbo, GL_BUFFER_GPU_ADDRESS_NV, &objectUboAddr);
    glMakeNamedBufferResidentNV(objectUbo, GL_READ_ONLY);
    
    //You have to call this to turn on bindless buffers.
    glEnableClientState(UNIFORM_BUFFER_UNIFIED_NV);
    
    //0 represents the scene UBO's `binding` from GLSL:
    glBufferAddressRangeNV(UNIFORM_BUFFER_ADDRESS_NV, 0, sceneUboAddr, sizeof(glm::vec4));
    //1 represents the object UBO's `binding` from GLSL:
    glBufferAddressRangeNV(UNIFORM_BUFFER_ADDRESS_NV, 1, objectUboAddr, sizeof(glm::vec4));
    

    Note that this extension effectively requires glEnable/DisableClientState, which is a function that was removed from the core profile. So you kind of need to use a compatibility profile to use it.

    And just to prove that the non-bindless code is hardly "needlessly complex", here it is:

    //The first 0 represents the scene UBO's `binding` from GLSL:
    glBindBufferRange(GL_UNIFORM_BUFFER, 0, sceneUbo, 0, sizeof(glm::vec4));
    //1 represents the object UBO's `binding` from GLSL:
    glBindBufferRange(GL_UNIFORM_BUFFER, 1, objectUbo, 0, sizeof(glm::vec4));