GLSL 计算着色器 使用查找表设置缓冲区会导致不写入任何数据,与其他数据设置相同的缓冲区有效
GLSL Compute Shader Setting buffer with lookup table results in no data written, setting the same buffer with other data works
我正在尝试在计算着色器中实现此标准行进立方体算法的略微修改版本。 我已经到了使用triTable
将正确的顶点索引插入缓冲区的阶段,并将表格修改为 1 维 (const int triTable[4096]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,3...}
)
以下代码显示了我遇到的错误(这没有实现算法,但它完全演示了当前问题):
layout(binding=1) buffer Grid
{
float GridData[]; //contains 512*512*512 data volume previously generated, unused in this test case
};
uniform uint marchableCount;
uniform uint pointCount;
layout(std430, binding = 4) buffer X {uvec4 marchableList[];}; //format is x,y,z,cubeIndex
layout(std430, binding = 5) buffer v {vec4 vertices[];};
layout(std430,binding = 6) buffer n {vec4 normals[];};
layout(binding = 7) uniform atomic_uint triCount;
void main()
{
uvec3 gid = marchableList[gl_GlobalInvocationID.x].xyz; //xyz of grid cell
int E = int(edgeTable[marchableList[gl_GlobalInvocationID.x].w]);
if (E != 0)
{
uint cubeIndex = marchableList[gl_GlobalInvocationID.x].w;
uint index = atomicCounterIncrement(triCount);
int tCount = 0;//unused in this test, used for iteration in actual algorithm
int tGet = tCount+16*int(cubeIndex); //correction from converting 2d array to 1d array
vertices[index] = vec4(tGet);
}
}
此代码生成预期值:顶点缓冲区填充数据,原子计数器增量
更改此行:
vertices[index] = vec4(tGet);
自
vertices[index] = vec4(triTable[tGet]);
或
vertices[index] = vec4(triTable[tGet]+1);
(证明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 也可能有效,但某些硬件通过专用内存而不是全局内存提取来实现统一块。
相关文章:
- 嵌套在类中时无法设置成员数据
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- 为什么将一个结构的引用设置为等于另一个结构只会更改一个数据成员?
- 在 lldb 中为大型数据结构设置观察点
- 如何在引用上设置数据断点
- MySQL c++ 连接器:使用 SetBlob() 在查询中设置多个 blob 数据的正确方法是什么?
- 在C++中设置仅包含每个类的一个外观的数据结构
- 在 C++ 中设置的用户定义数据类型
- 在主函数中设置私有数据
- GLSL 计算着色器 使用查找表设置缓冲区会导致不写入任何数据,与其他数据设置相同的缓冲区有效
- 设置数据结构引用
- 通过将基类强制转换为派生类并设置数据来扩展基类
- 在数组中设置数据时程序崩溃
- 如何使用 MSTest 为C++测试设置数据驱动测试
- 使用泛型资源库设置数据成员
- 正在设置数据类型
- 如何在c++中设置数据为0
- 在UWP应用程序中使用DataTemplate时的问题(崩溃,未设置数据)
- 在 std::map 的元素上设置数据断点
- 在 Visual Studio 2005 中对取消引用的指针的地址设置数据断点