Issue with using bindless textures in UBOs

From my understanding OpenGL 4.5 (with glsl 450) supports using bindless texture samplers in UBOs. I believe it replaces sampler2D with a 64-bit unsigned integer that should store the GPU address of the texture. However, I am having an issue where all of my sampler values are zero inside my UBO. I am checking the values via the NVidia Linux Graphics Debugger tool.

Here is what my UBO code looks like:


layout(bindless_sampler) uniform;

layout(std140,binding=0) uniform TestUniforms
{
  sampler2D      someTexture;
  sampler2D      someOtherTexture;
  samplerBuffer someSamplerBuffer;
};

Here is how I am copying the data to the UBO:


void *p = glMapNamedBufferRangeEXT( ubo_handle, offset, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT );
memcpy( p, &bindless_gpu_addr, size );
glUnmapNamedBufferEXT( ubo_handle );

Am I misunderstanding how this is supposed to works?

After some further debugging, I discovered that the value displayed by the NVidia Graphics Debugger is being displayed incorrectly. The debugger by default was reading the sampler value as a hexadecimal and then casting it as an integer. I manually changed how to display the raw data values in the debugger and got the values that I was expecting. So now I know that my samplers in my uniform buffers are being set to the 64-bit unsigned integer of the bindless textures GPU address. However, I’m still seeing an issue with my bindless textures in UBOs. So is something wrong with my approach or am I misunderstanding something?

From my understanding OpenGL 4.5 (with glsl 450) supports using bindless texture samplers in UBOs.

No. ARB_bindless_texture supports bindless texture samplers in UBOs. They’re not a core features. So unless you enable that extension in GLSL, you can’t (or at least, shouldn’t be able to) use them.

I believe it replaces sampler2D with a 64-bit unsigned integer that should store the GPU address of the texture.

Also no. The C++ type of a sampler is a 64-bit unsigned integer handle. But it isn’t “replacing” anything; that’s simply the analogous C++ type for the GLSL type.

Oh, and texture/image handles are not GPU addresses. They’re just opaque handles.

However, I’m still seeing an issue with my bindless textures in UBOs. So is something wrong with my approach or am I misunderstanding something?

There’s no way to tell, since we don’t know what the “issue” you’re having is. Perhaps if you could provide details on exactly what’s happening, as well as the code that provides the data that gets transferred to the buffer, we might be able to help.

Sorry, I forgot to add that I am using ARB_bindless_texture. So you agree that ARB_bindless_texture does support bindless texture samplers in UBOs.

So what should I be setting the sampler value to when I do the memcpy() for the UBO data? I use to use UniformHandleui64ARB() to set my bindless textures. However, I would imagine that doesn’t work with UBOs. Since there isn’t a handle to the uniform. Just an offset in the UBO buffer.

Yep, ARB_bindless_texture, a non-core extension released at the same time as GL4.4, provides UBO support for texture handles.

As an aside, you can also put the texture handle in an SSBO but some architectures do not support dynamic addressing of textures (I believe on Nvidia Maxwell GPUs do). That means you can’t do ‘texture(ssbo[ index ].tex_handle)’ where index isn’t dynamically uniform (ie, will not work if index is a fragment shader input). But UBOs should be okay.

So what should I be setting the sampler value to when I do the memcpy() for the UBO data? I use to use UniformHandleui64ARB() to set my bindless textures. However, I would imagine that doesn’t work with UBOs. Since there isn’t a handle to the uniform. Just an offset in the UBO buffer.

A memcpy() from the GLuint64 to the offset within your buffer will work. Or use glBufferSubData() if you’re only updating that one handle.

Thanks, that was what I wanted to clarify. My problem ended up being somewhere else in my code. Once I fixed my other issue. This approach worked as I expected.