Sign in to follow this  
AverageJoeSSU

My attempt at bindless textures not working....

Recommended Posts

Double EDIT: I have updated my renderer with a prototype to test this feature. and glMakeTextureHandleNonResident seems to not do anything.

 

I used the following code as a test to see how much memory i have (at the end of my Renderer::Draw() before unbinding the GLContext):

    GLint currentAvailableVideoMemory = -1;
    glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &currentAvailableVideoMemory);
    GLint totalAvailableVideoMemory = -1;
    glGetIntegerv(GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &totalAvailableVideoMemory);
    float percent = (float)currentAvailableVideoMemory/(float)totalAvailableVideoMemory * 100.0f;
    fprintf(stdout, "VRAM (%d MB) Usage: %f%% \n", totalAvailableVideoMemory/1024, 100.0f - percent);
    fflush(stdout);

which reports 95.xxx% always...

 

And in gDebugger i always have the same number of texture objects.

 

when i add 100 images. i get a couple of frames and then the renderer dies, asummingly because the textures are not actually made NonResident.

 

Is there something i need to be doing to ensure that non resident calls are executed? Could this be a bug in the nvidia linux driver?

 

 

 

EDIT: stupid shader in/out blocks didnt match... thanks compiler!

 

Here is the output for my program, i also checked in gDebugger and the texture loads just fine.

 

Vendor: 4.4.0 NVIDIA 343.36
Supported GLSL version is 4.40 NVIDIA via Cg compiler.
Aspect Ratio: 2.400000 
vbo: 1
index buffer: 2
Shader Source: #version 440
 
layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec2 TexCoords;
 
uniform mat4 worldMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
 
out block
{
    vec2 Texcoord;
} Out;
 
void main()
{
    mat4 mvp = projectionMatrix * viewMatrix * worldMatrix;
    Out.Texcoord = vec2(TexCoords.x, 1.0-TexCoords.y);
    gl_Position = mvp * vec4(VertexPosition, 1.0);
}
 
../shaders/simpleTexture.vert Compilation Successful 
Shader Source: #version 440
//#extension GL_NV_gpu_shader5 : require    // for 64-bit integer types
#extension GL_ARB_bindless_texture : require
 
in block
{
    vec2 texCoords;
} In;
 
layout (bindless_sampler) uniform sampler2D textureID;
 
layout (location = 0) out vec4 FragColor;
 
void main()
{
    FragColor = texture(textureID, In.texCoords);
}
 
../shaders/simpleTexture.frag Compilation Successful 
Linking Shader Program: simpleTexture.vert
Shader Link Successful
GL_ACTIVE_UNIFORMS = 4
  0) type:mat4 name:projectionMatrix location:0
  1) type:sampler2D name:textureID location:1
  2) type:mat4 name:viewMatrix location:2
  3) type:mat4 name:worldMatrix location:3
width: 500, height 331: 
Done Loading Texture... 
SOIL loading error: 'Image loaded'
texture handle pointer: 4294969856
 
 
My question is, given those shaders and the fact that glGetTextureHandleARB returns non 0, should it work? (of course given the correct geometry and uvs)
 

Share this post


Link to post
Share on other sites
I didn't use bindless so far, but I read into it.

My first question would be:

-Did you make the texture resident?
-Did you use the correct function to set the uniform (ProgramUniformHandleui64/ProgramUniformHandleui64ARB)?
-What does actually happen when you try to draw?

Share this post


Link to post
Share on other sites

Okay...

 

Texture Creation

Texture &tex = (*textures)[desc.filename];
    if (tex.name.compare(desc.filename) == 0) {
        return tex;
    }

    if (desc.width < 1 && desc.height < 1)
    {
        //bad input
    }
    int width, height, channels;
    unsigned char *textureData = SOIL_load_image
            (
                    std::string(TEXTURE_DIRECTORY).append(desc.filename).c_str(),
                    &width, &height, &channels,
                    SOIL_LOAD_AUTO
            );

    fprintf(stdout, "width: %d, height %d: \n" , width, height);
    fprintf(stdout, "Done Loading Texture... \n");
    printf( "SOIL loading error: '%s'\n", SOIL_last_result() );
    fflush(stdout);

    GLuint textureHandle;
    glGenTextures(1, &textureHandle);

    glBindTexture(GL_TEXTURE_2D, textureHandle);

    glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, textureData);

    //set texture parameters
    glTexParameteri(textureHandle, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(textureHandle, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(textureHandle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(textureHandle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glGenerateMipmap(GL_TEXTURE_2D);

    //get GPU PTR
    GLuint64 textureGPU_ptr = glGetTextureHandleARB(textureHandle);

    fprintf(stdout, "texture pointer: %lu \n", textureGPU_ptr);
    fflush(stdout);


    //Make the handle resident on the GPU before using it.
    //Here we assume that we are creating a texture because we want to display it.
    //If we didnt want to display it right away, we wouldnt make it resident.
    //We can also move textures off the GPU by calling glMakeTextureHandleNonResidentARB
    glMakeTextureHandleResidentARB(textureGPU_ptr);


    tex.TextureID = textureGPU_ptr;
    tex.width = desc.width;
    tex.height = desc.height;

    //if everything checks out, assign the name so it becomes valid in the hashmap.
    tex.name = desc.filename;
    glBindTexture(GL_TEXTURE_2D, 0);
    return tex;

Square mesh data...

    
    struct Vertex {
    float x, y, z;
    float u0, v0;
};

    name = "square";

    vertexBufferSize = 4;
    indexBufferSize = 6;

    meshData = new Vertex[vertexBufferSize];
    for(int i = 0; i < vertexBufferSize; i++)

    meshData[0].x = -0.5f;
    meshData[0].y = -0.5f;
    meshData[0].z = 0.0f;
    meshData[0].u0 = 0.0f;
    meshData[0].v0 = 0.0f;

    meshData[1].x = -0.5f;
    meshData[1].y = 0.5f;
    meshData[1].z = 0.0f;
    meshData[1].u0 = 0.0f;
    meshData[1].v0 = 1.0f;

    meshData[2].x = 0.5f;
    meshData[2].y = 0.5f;
    meshData[2].z = 0.0f;
    meshData[2].u0 = 0.0f;
    meshData[2].v0 = 1.0f;

    meshData[3].x = 0.5;
    meshData[3].y = -0.5;
    meshData[3].z = 0.0;
    meshData[3].u0 = 1.0;
    meshData[3].v0 = 0.0;

    indexData = new unsigned short[indexBufferSize];
    indexData[0] = 0;
    indexData[1] = 1;
    indexData[2] = 2;
    indexData[3] = 0;
    indexData[4] = 2;
    indexData[5] = 3;


}

the setUniformTextureHandle64NV call above actually calls glUniformHandle64ARB

void Shader::setUniformTextureHandle64NV(GLuint location, GLuint64 value) {
//Runtime function
glProgramUniformHandleui64ARB(this->ShaderProgram, location, value);
}

and the shaders again:

#version 440

layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec2 TexCoords;

uniform mat4 worldMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;

out block
{
    vec2 Texcoord;
} Out;

void main()
{
    mat4 mvp = projectionMatrix * viewMatrix * worldMatrix;
    Out.Texcoord = vec2(TexCoords.x, 1.0-TexCoords.y);
    gl_Position = mvp * vec4(VertexPosition, 1.0);
}

#version 440
//#extension GL_NV_gpu_shader5 : require    // for 64-bit integer types
#extension GL_ARB_bindless_texture : require

in block
{
    vec2 texCoords;
} In;

layout (bindless_sampler) uniform sampler2D textureID;

layout (location = 0) out vec4 FragColor;

void main()
{
    FragColor = texture(textureID, In.texCoords);
}

Here are images:

 

[attachment=25574:bindlessNotWorking.png]

 

[attachment=25575:textureAndStack.png]

Edited by AverageJoeSSU

Share this post


Link to post
Share on other sites

I actually tried just doing regular binding and i get the same result.

 

Do i NEED to bind a "sampler"?

 

maybe its my VAO... it's pretty straightforward

vertexBufferSize = desc.vertexBufferSize;
    indexBufferSize = desc.indexBufferSize;

    glGenVertexArrays(1, &vaoID);
    glBindVertexArray(vaoID);

    glGenBuffers(1, &vboID);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*vertexBufferSize, &desc.meshData[0].x, GL_STATIC_DRAW);

    glGenBuffers(1, &indexID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*indexBufferSize, desc.indexData, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(12));     

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexID);

    fprintf(stdout, "vbo: %d\n", vboID);
    fprintf(stdout, "index buffer: %d\n", indexID);
    fflush(stdout);

    glBindVertexArray(0); // Disable our Vertex Array Object
}

Share this post


Link to post
Share on other sites

I wanted to keep my issues with bindless in the same thread, as to keep things somewhat tied together.

See latest edit at the top for details.

 

I could post more detailed code if needed, But it seems like a simple thing.

 

What are the requirements for making a resident texture non resident? By definition, what does making a texture non resident actually do?

 

A comment in the spec says that if the texture isnt going to be used "for a while" it can be made non resident, maybe the GPU won't specifically release the memory if it has plenty? Perhaps the crashing i am seeing is when it actually starts releasing and adding textures from VRAM.

Edited by AverageJoeSSU

Share this post


Link to post
Share on other sites

So I think it actually is working.... what throws me off is that vram seems to stabilize... so the driver must keep residency memory reserved using a data structure of some sort (makes sense).

 

i can handle 80 high rez images w/ mipmaps (basically camera animates over them (by 2s).

Share this post


Link to post
Share on other sites

Phew, I grossly misunderstood bindless texturing. Residency is only for the texture handles. Sparse Texture support is for residency of texture memory. Luckily the two work together quite well, so if I add sparse texture immutable storage I can leverage the same querys of determining bindless residency to deal with sparse residency.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this