I am currently investigating the possibilities of bindless uniform buffers in our renderer. The GL_NV_shader_buffer_load extension made it possible to upload a uvec2 or uint64_t address handle of a buffer and in GLSL, declare the uniform variable as a pointer that can be used to access the bindless buffer. This also works when storing multiple handles in another buffer. For example:
struct BufferStruct
{
int* a;
int* b;
};
uniform restrict readonly BufferStruct* myBuffers;
myBuffers is a shader storage buffer of type GLuint64 (buffer address handles), the translation from address handles to SSBOs a and b is done by OpenGL. This all works like a charm, but:
It does not work with uniform buffer objects. If I change the code to
struct BufferStruct
{
int* a;
int* b;
};
layout(std140) uniform TestBlock
{
BufferStruct myBuffers;
};
I get the linker error (0) : fatal error C9999: unhandled type category 9 in CreateDag. As with my other pending bug report regarding bindless buffers, I find the number of nondescript linker errors disturbing when it comes to this extension.
The thing is, it is no problem to declare
struct TestStruct
{
layout(bindless_sampler) sampler2D a;
layout(bindless_sampler) sampler2D b;
};
so bindless textures are not a problem, only bindless buffers. It is also no problem to declare
struct BufferStruct
{
int* a;
};
so the trouble only starts when using two or more.
Please note that for this bug, no host code is involved. It does not depend on any actual data in the buffers, the shader is not even executed, but fails upon linking.
The system is Windows 8.1 Pro 64 bit, the video card is a GeForce GTX 680, the driver version is 364.51, the requested OpenGL context is 4.5 compatibility profile.
The entire fragment shader code for reproducibility:
#version 450
#extension GL_ARB_bindless_texture : enable
#extension GL_ARB_gpu_shader5 : enable
#extension GL_NV_shader_buffer_load : enable
out vec4 fragment_color;
struct TestStruct
{
//uint64_t a; // Good
//uint64_t b; // Good
//layout(bindless_sampler) sampler2D a; // Good
//layout(bindless_sampler) sampler2D b; // Good
//int* a; // Good
int* a; // Nono
int* b; // Nono
};
layout(std140) uniform TestBlock
{
TestStruct test;
};
void main()
{
fragment_color = vec4(1.0);
if (test.a[0] > 0) // just so it is not removed as optimization
{
discard;
}
}