Bindless image load not working

#1

I’m sorry to bother you again, but I’m having trouble with the bindless texture extension. This is the (compute) shader code I’m trying to compile without success:

#version 450 core

#extension GL_ARB_bindless_texture : require

/// Density map
uniform DensityMapBuffer
{
	layout(r32f) coherent image3D densityMap;
};

float test(coherent readonly image3D dmap)
{
	return imageLoad(dmap, ivec3(0)).r;
}

layout(local_size_x = 36, local_size_y = 1, local_size_z = 36) in;
void main()
{
	ivec3 index = ivec3(gl_GlobalInvocationID);
	float val = test(densityMap);
}

The compiler complains about:

error C1115: unable to find compatible overloaded function "imageLoad(struct image3D_bindless, ivec3)

And this works fine if I get rid of the function:

void main()
{
	ivec3 index = ivec3(gl_GlobalInvocationID);
	float val = imageLoad(densityMap, ivec3(0)).r;
}

I also tried using a bindless texture as a function parameter and fetching its data with texture and it works.

Since bindless images are essentially integer handles I assumed it should be possible to pass a bindless image to a function, shouldn’t it?

#2

In order to perform imageLoad operations, the image* variable needs to have a format layout quality. The variable in your uniform block does, but the variable in your function does not.

This may well be the problem.

#3

Yes, I figured it out after a few tries, I added layout(r32f) to the function argument as well and the code compiled correctly. I was waiting to have my entire shader work correctly in order to make sure that it was the correct solution :rofl:

Anyway, in my opinion things like these should be better documented in the OpenGL Shading Language specification. I read the relevant section of 4.5 and 4.6 where it is stated:

(pag. 114) Formal parameters can have parameter, precision, and memory qualifiers, but no other qualifiers.

And the function protoype syntax grammar doesn’t include layout qualifiers:

function-prototype :
precision-qualifier type function-name(parameter-qualifiers precision-qualifier type name
array-specifier, … )

parameter-qualifier :
const
in
out
inout
precise
memory qualifier
precision qualifier

1 Like
#4

Then the specification has a bug. Regardless of bindless, the GLSL specification has several places in it that implies strongly that image variables can have format layout qualifiers:

Format layout qualifiers can be used on image variable declarations

Note that there is no statement exempting parameters, which are still variable declarations.

Furthermore:

it is a compile-time error to pass an image uniform variable or function parameter declared without a format layout qualifier to an image load or atomic function.

That too strongly implies the ability to apply layout qualifiers to function parameters, since otherwise it would be impossible to use image load/atomics on such parameters.

That, coupled with the fact that ARB_bindless_texture itself didn’t seem to see a need to have a statement allowing layout qualifiers on parameters (that is, they assumed it was already permitted) means that the specification is contradicting itself.

Investigating the history of this functionality, you can even see where something went wrong. Back in ARB_image_load_store, we can see this example in the middle of the memory qualifiers section:

vec4 funcA(layout(rgba32f) image2D restrict a)   { ... }
vec4 funcB(layout(rgba32f) image2D a)            { ... }
layout(rgba32f) uniform image2D img1;
layout(rgba32f) coherent uniform image2D img2;

funcA(img1);              // OK, adding "restrict" is allowed
funcB(img2);              // illegal, stripping "coherent" is not

Here’s the really weird bit: immediately after this example is the line:

Layout qualifiers cannot be used on formal function parameters, but they are not included in parameter matching.

… huh?

Indeed, someone must have seen this line when they were transcribing ARB_image_load_store to GLSL 4.20, because it, and all subsequent versions, “fixes” the example:

vec4 funcA(restrict image2D a) { ... }
vec4 funcB(image2D a) { ... }
layout(rgba32f) uniform image2D img1;
layout(rgba32f) coherent uniform image2D img2;
funcA(img1); // OK, adding "restrict" is allowed
funcB(img2); // illegal, stripping "coherent" is not

Overall, it’s pretty clear that something is very confused in the specification. I would tell you to file a bug on it, but I just did that.

1 Like