我在GLSL片段着色器中具有以下奇怪的行为:我正在尝试传递带有结构数组的UBO(也尝试过SSBO),其中每个结构如下:
layout(location = 0) uniform uint u_index;
layout (std430, binding = 2) buffer MaterialBlock {
u64vec4 data[];
}material;
此处u64vec4
具有以下值:
x-uint64_t无边界纹理句柄A
y-uint64_t无边界纹理句柄B
z-uint64_t无边界纹理句柄C
w-将两个uint32_t压缩为带有一些额外数据的单个uint64_t。
我在片段着色器中有一个看起来像这样的代码(对不起,由于这是商业工作,我无法说明全部内容,但是此示例准确地解决了问题:
vec4 DoThing( sampler2D aTex, usampler2D cTex, float2 paramA, float4 paramB, float4 paramC)
{
uint4 cTexData= texelFetch(cTex, int2(paramA.x,paramA.y),0);
vec4 color = vec4(0.0);
for (int i= 0; i< int(cTexData.x); i++)
{
color += texelFetch(aTex, int2(paramB.x,paramB.y),0);
//continue doing smth with color ..
}
//some more code..
return color;
}
void main()
{
oColor = DoThing(sampler2D(material.data[u_index].x),usampler2D(material.data[u_index].z),..params...);
}
u_index-是一个常规的制服,在发出drawcall之前我将其传递给GPU,如您所见,它用于索引u64vec4数组以检索相关结构。但是当我使用它时:
uint4 cTexData= texelFetch(cTex, int2(paramA.x,paramA.y),0);
失败。当我说“失败”时,这意味着cTexData接收到错误的数据,这导致for()..内部非常长(某种无限循环),这会使显示冻结20-30秒,这使我相信垃圾中的样本。
但是,如果我以恒定值索引到SSBO或(UBO),则如下所示:
void main()
{
oColor = DoThing(sampler2D(material.data[0].x),usampler2D(material.data[0].z),..params...);
}
行!所有的纹理都是正确的样本
我一直在研究OpenGL规范,但找不到任何可以表明禁止统一索引到UBO的内容。但这是行不通的。而且我无法使用Nvidia Nsight / Graphics进行剖析,因为它们尚不支持此GPU模型,并且renderDoc不支持ARB_bindless_texture
我的系统规格: Win10 Pro,Nvidia Quadro P2000,OpenGL 4.5
PS:在SSBO之前也使用140布局的UBO,但是决定尝试SSBO看看问题是否可能与数据布局有关。在客户端,结构看起来像这样:
struct MaterialData
{
uint64_t data[4];
};
我还检查了着色器代码,以确保u_index
的值等于0。所以我不知道为什么动态索引在这里失败。
更新:偶然发现了this个问题,我确实使用了#extension GL_NV_gpu_shader5 : require
更新1:
经过几次测试,它看起来像NVIDIA驱动程序的实现错误。 一旦收到他们的驱动程序团队对此问题的答复,我将进行更新。