Bug report: Constructor image2D(uvec2) for bindless images missing

To use bindless images in OpenGL, you need to create a GLuint64 handle using glGetImageHandleARB. You can then set this handle to a uniform image2D variable and use the image as if you had bound it the old way. No problems with that. With textures/samplers, it is further possible to set the (texture) handle not to a sampler2D, but to a plain uniform uint64_t variable. This handle can then be used to “construct” a sampler object at runtime with the constructor sampler2D(handle).

The extension description says:

Samplers are represented using 64-bit integer handles, and may be converted to and from 64-bit integers using constructors.

any sampler type(uvec2) // Converts a pair of 32-bit unsigned integers to a sampler type

and

Images are represented using 64-bit integer handles, and may be converted to and from 64-bit integers using constructors.

any image type(uvec2) // Converts a pair of 32-bit unsigned integers to an image type

So I would assume that the construction for images works the same way as it does for samplers, but this is not the case. Sample code:

#version 450
#extension GL_ARB_bindless_texture : enable
#extension GL_NV_gpu_shader5 : enable

layout(bindless_image, rgba8) uniform image2D myBindlessImage;

uniform uint64_t textureHandle;
uniform uint64_t imageHandle;

void main()
{
    sampler2D mySampler = sampler2D(textureHandle); // works like a charm
    ... = texture(mySampler, texCoord);

    ... = imageLoad(myBindlessImage, texCoordI); // works like a charm

    layout(rgba8) image2D myImage = image2D(imageHandle); // error C7011: implicit cast from "uint64_t" to "int"
    ... = imageLoad(myImage, texCoordI);

    layout(rgba8) image2D myImage2 = image2D(uvec2(0u)); // error C7011: implicit cast from "uint64_t" to "int"
}

Apparently, neither the image2D(uint64_t) constructor nor the image2D(uvec2) constructor mentioned in the extension description are known to the compiler. Even stranger, when I try to use the uvec2 constructor instead of the uint64_t constructor, I get the same error message from the compiler, namely that an uint64_t is being cast.

The video driver I am using right now is 355.82. To reproduce this error, simply put image2D(0lu); or image2D(uvec2(0u)); in a shader and try to compile it (you will need the NV_gpu_shader5 extension for uint64_t).

Bump with the note that this issue persists in driver version 355.98.

Thanks for reporting this. I have filed an NVIDIA internal bug for this issue.

Is there any development regarding this issue? I have just updated to driver 362.00 and it still persists.

The missing image constructors have quite an impact on development, as you cannot write to arbitrary mipmap levels of a texture in a shader (for example for a min/max-map). As you have to create a separate image handle for each mipmap level of a texture, you end up with a shader storage buffer of image handles that you provide to the shader. But in the shader, you cannot construct an image2D from the handle you retrieve, because the constructor is missing. The alternative is to explicitly declare n uniform image2Ds in your shaders for the n levels of the texture. This is tedious because the texture size might change, and it makes the GLSL code quite ugly.

Turns out using

layout(rgba8) image2D myImage = layout(rgba8) image2D(imageHandle);

instead of

layout(rgba8) image2D myImage = image2D(imageHandle);

solves the problem.

It’s not very intuitive that you have to specify the layout as a part of the type, but I can deal with that. The bigger problem is the error message error C7011: implicit cast from “uint64_t” to “int” that did not give me a clue what the real problem was.

I am glad you are able to root cause the problem. Thanks for the suggestion for the error message, we plan to fix the error message as suggested.