Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 5 of 5

Thread: Bindless Textures + Instancing

  1. #1
    Newbie Newbie
    Join Date
    May 2013
    Posts
    2

    Bindless Textures + Instancing

    I would like to render instanced geometry with a per-instance texture. To do so, I want to create a Vertex Attrib (that is consumed in a per-instance basis) containing the texture handler and create the sampler2D in the shader using the bindless_texture NVIDIA extension. I want to do so because the number of instances is dynamic and they are created an destroyed during runtime so I cannot allocate an statically allocated array of textureHandles as in the example in the extension specification.

    Code :
    //Create the textures and obtain the handles
    foreach instance
    	glGenTextures(1, &this->gpuTextureId);
    	glBindTexture(GL_TEXTURE_2D, this->gpuTextureId);
     
    	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ResX, ResY, 0, GL_RGBA, GL_UNSIGNED_BYTE, info); 
    	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);	// Linear Filtering
    	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);	// Linear Filtering
     
    	// Get a handle for the texture.
    	this->gpuTextureHandlerId = glGetTextureHandleNV(this->gpuTextureId);
     
    	// Make the handle resident before using it.
    	glMakeTextureHandleResidentNV(this->gpuTextureHandlerId);
    endfor
    //Pass the handle to the buffer
    	#define INSTANCE_TEXTURE_LOCATION 6
     
    	glGenBuffers(1, &this->instanceTextureHandlerVboId);
    	glBindBuffer(this->instanceTextureHandlerVboId);
     
    	glEnableVertexAttribArray(INSTANCE_TEXTURE_LOCATION);
    	glVertexAttribPointer(INSTANCE_TEXTURE_LOCATION, 1, GL_UNSIGNED_INT64_NV, GL_FALSE, sizeof(GLuint64), 0); 
    	glVertexAttribDivisor(INSTANCE_TEXTURE_LOCATION, 1);
     
    	glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint64) * this->numElements, instanceTextureHandle, GL_DYNAMIC_DRAW); //instanceTextureHandle contains the texture handles for all the instances.

    As for the shader:
    Code :
    #version 430
    #extension GL_NV_bindless_texture : require
    #extension GL_NV_gpu_shader5 : require 
     
    in vec2 ex_textCoord;
    layout(location = 6) in  uint64_t in_textHandler;
     
    out vec4 out_Color;
     
    void main(void)
    {
    	sampler2D s = sampler2D(in_textHandler);
    	out_Color = texture(s, ex_textCoord);
    }
    The problem is that I cannot send the 64-bit pointer to the shader. If it was a Uniform I could use "glUniformHandleui64NV(location, instanceTextureHandle[i]);" I use GL_UNSIGNED_INT64_NV or GL_DOUBLE in the glVertexAttribPointer without success.

    Can it be done?

    Thanks in advance.

    Nicolau
    Last edited by nsunyer; 05-21-2013 at 07:43 AM.

  2. #2
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Posts
    645
    Since you want the vertex attribute to be an integer in the shader you'll want glVertexAttribIPointer (notice the "I"). On a quick glance the bindless texture extension does not add 64bit integer vertex attributes (may have missed it), but you could split the value into two 32bit values and pass them as a 2 element unsigned int vector.

  3. #3
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    I use GL_UNSIGNED_INT64_NV or GL_DOUBLE in the glVertexAttribPointer without success.
    Of course they don't work. `glVertexAttribPointer` can only feed floating-point attributes. Thus, whatever type you pass will be converted into a 32-bit float. All integers will be assumed to be either signed or unsigned normalized values. Doubles will be (likely at great performance cost) converted into 32-bit floats before the shader reads them.

    This is why `glVertexAttribIPointer` and `glVertexAttribLPointer` exist. The first feeds integer attributes and the second feeds double-precision attributes.

    Unfortunately, NVIDIA decided to be terribly inconsistent with how 64-bit integer attributes are treated. They're integer attributes, so they should have used IPointer. But because they're 64-bits in size, they decided to use LPointer. So you have to use that one with GL_UNSIGNED_INT64_NV.

  4. #4
    Newbie Newbie
    Join Date
    May 2013
    Posts
    2
    Lots of thanks, it worked!

    Just one note:
    Since we send our data to the fragment shader through the vertex shader, we also need to add the "flat" qualifier to the output variable of the vertex shader and also to the corresponding input variable of the fragment.
    Don't know why but it's explained in the extension specification:

    In the following example, the sampler to use is selected in a vertex
    shader, passed to the fragment shader as a (flat) input, and then used for
    a texture lookup.
    Without this qualifier it does not work.

  5. #5
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    The value is an integer. And interpolation isn't allowed for integers.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •