Hello,
I have implemented the Occlusion Culling Project based on NVIDIAs raster method with Vulkan, (based on GitHub - nvpro-samples/gl_occlusion_culling: OpenGL sample for shader-based occlusion culling
)
It has worked so far very well until driver version 397.31. The exe crashes now. After some research i found the cause. To my configuration:
I have an octree where the leaf nodes have geometries. Each leaf node has its NodeId and Bounding Box.
Bounding boxes are stored in a storage buffer that is big enough to store all leaf bounding boxes. (Num Leafs * size of bounding box representation).
Additionally i have a storage buffer (visibility buffer) of size numLeaves * sizeof(unsigned int). Before OC step the visibility buffer is set to zero. Then if the node is visible the fragment shader sets it to 1 (vis_node[node_id] = 1). Further steps evaluate and utilize the results.
After rendering the old visible pass I use point rendering and provide nodeIds as points to trigger vertex shader. Vertex shader passes through the nodeIds to the geometry shader. The geometry shader creates Bounding Box vertices (just like in the project on GitHub) and routes (unchanged) the nodeids to the fragment shader.
The Fragment shader looks something like that
...
layout (early_fragment_tests) in;
layout (binding = 0) buffer BB // storage buffer to mark visible nodes
{
uint node_vis[];
};
layout (location = 0) flat in uint node_id; // ==> input from geometry shader (vertex shader)
void main()
{
node_vis[node_id] = 1;
}
The error:
The shader crashes because the node_id gets some invalid values that cause access violation on the vis_buffer
It seems the robust buffer access feature is broken.
so if i do this
void main()
{
if (node_id >= 0 && node_id < max_num_leafs)
node_vis[node_id] = 1;
}
It does not crash. The bug seems to be fixed in 397.40 (beta). However there is another issue
with both driver versions (397.31 with the if in the main())
the node ids seems to be unstable:
Same scene, no camera movements , even if depth test is off (per pipeline and/or by removing early depth test flag).
Some object dont pass the visiblity test (e.g have 1000 NodeIds but visible are only 900 or it alternates)
The problem is that wrong objects are culled away.
This should not happen, actually in can not happen, particullary if the depth test is off.
Further debugging has shown, that the input NodeIds not only exceeds the max num of nodes, but does not provide correct ids:
Lets take 10 NodeIds = max_num_nodes (depth test off)
Correct behavior: NodeIds should be 0,1,2,3,4,5,6,7,8,9 and maybe more (but robust buffer access should catch it)
Behavior with the newest drivers: 0,1,50,4,88,7,8,100 and so on but the ids 2,5,6,9 seem never to appear (getting lost some how).
And sometimes its alternate (with large meshes with many nodeIds).
Even if the nodeIds output from geometry shader are hardcoded to some value (e.g. 0), the input nodeIds in the fragment shader have different random values.
It seems the error is somewhere between the geometry and the fragment shader and the data that should be passed between them is getting corrupt.
It works with older official drivers (tested some versions before the 397.31) and it also works with the 389.20 (.10)
Tested it on different hardware (680 GTX, 960 GTX, 1080 GTX). OS: Win10x64 (no issues with older driver, issues with the newest on every test set up)
Thanks
Update:
The newest driver 397.55 and 397.54 still have the issue (Official Beta Driver (397.55) crash; the vulkan beta driver (397.55) instable (described above)