I have “finished” porting a pathtracer I made 5 years ago in DirectX11 to Vulkan. However, there are some very significant performance differences, where the execution time of the compute shader (measured with NVIDIA NSight) is in some cases 4 times slower (traversing complex scenes using BVH on the GPU).
Even when pathtracing a scene of 9 spheres (hard-coded in the shader), the vulkan compute shader is almost 2 times slower. I was initially using glslangvalidator.exe to compile my shaders, so I have tried compiling with glslc.exe using the -O flag, which actually reduced performance by a further 20% (???).
I then realized I was comparing to optimized HLSL shaders, so I disabled the optimization for those. I found that this runs approximately at the same speed as the SPIR-V shaders. In the complex scenes the HLSL is still faster (35 vs 40 fps), but at least this difference is not a factor 4.
I have made a few small changes to the shaders to fix some old problems, so the first thing I will do is make sure the shaders are are similar as possible. Some differences are unavoidable, e.g. those to fix alignment issues or the fact that glsl does not support logical operators on bvec types (a bit odd, but well).
This large difference begs a few questions:
- Are there some common pittfalls I may have fallen into when porting the HLSL code?
- Why could the optimized SPIR-V be performing so much worse?
- Is it possible this type of issue may lie outside of the shader?
- Are the optimized DX11 shaders simply outperforming SPIR-V in this case and is it out of my hands?