C++ GLSL计算着色器使用查找表设置缓冲区不会导致数据写入,使用其他数据设置相同的缓冲区会起作用
我正在尝试在计算着色器中实现一个稍微修改的版本。 我已经达到了使用C++ GLSL计算着色器使用查找表设置缓冲区不会导致数据写入,使用其他数据设置相同的缓冲区会起作用,c++,opengl,glsl,compute-shader,C++,Opengl,Glsl,Compute Shader,我正在尝试在计算着色器中实现一个稍微修改的版本。 我已经达到了使用triTable将正确的顶点索引插入缓冲区的阶段,并将表修改为一维(const int triTable[4096]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,3…}) 下面的代码显示了我遇到的错误(这并没有实现算法,但它充分说明了当前问题): 此代码生成预期值:顶点缓冲区充满数据,原子计数器递增 更改此行: vertices[index] = vec4(tGet); 到 或
triTable
将正确的顶点索引插入缓冲区的阶段,并将表修改为一维(const int triTable[4096]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,3…}
)
下面的代码显示了我遇到的错误(这并没有实现算法,但它充分说明了当前问题):
此代码生成预期值:顶点缓冲区充满数据,原子计数器递增
更改此行:
vertices[index] = vec4(tGet);
到
或
(证明triTable不会同时返回零)
导致着色器出现完全故障:缓冲区充满零,原子计数器不递增。编译着色器时不会输出错误消息tGet
小于4096
以下测试用例也会产生正确的输出:
vertices[index] = vec4(triTable[3]); //-1
vertices[index] = vec4(triTable[4095]); //also -1
表明triTable实际上是正确实现的
是什么导致着色器在这些非常特殊的情况下出现问题?我更惊讶的是
const int triTable[4096]={…}代码>完全可以编译。如果实际需要,该数组的大小为16KB。这对于着色器来说非常重要,即使数组位于共享内存中
最可能发生的情况是,每当编译器检测到此数组的使用情况时,它无法将其优化为一个简单值(triTable[3]
将始终为1
,因此编译器不需要存储整个表),编译要么失败,要么导致非功能着色器
最好将此表作为一个统一的缓冲区。SSBO可能也可以工作,但某些硬件通过专用内存而不是全局内存获取来实现统一块。“编译着色器时不会输出错误消息。”这是否意味着您正在检查着色器编译/链接错误,或者您希望glGetError
返回发生错误的消息?因为glGetError
不报告着色器编译失败;只有编译/链接状态查询可以做到这一点。@Nicolas我正在使用glGetShaderInfoLog
检测编译器错误,这解决了测试用例中的问题,尽管我还没有用实际代码测试它。有没有办法查询硬编码数组的大小限制?16KB看起来并不是一个无法管理的量,特别是考虑到它在我的CPU实现中使用相同的代码。这一限制是否适用于源代码大小或实际编译数组占用的内存大小?@jcg:“特别是考虑到它在我的CPU实现中对同一代码起作用。”你说的是一个更为有限的执行环境。
vertices[index] = vec4(triTable[tGet]);
vertices[index] = vec4(triTable[tGet]+1);
vertices[index] = vec4(triTable[3]); //-1
vertices[index] = vec4(triTable[4095]); //also -1