Accessing array using number index causes strange crash in my HLSL shader

Hi all,

So I have been implementing my toy Vulkan renderer for a while now, but recently ran into a really strange bug

In one of my fragment shader (using HLSL, if that matters), if I access some data with an explicit number index (i.e. 0), then my program crashes on startup:
printf("L %v3f", normalize(-lightUBO.dirLights[0].direction));

However, if I access it inside a for loop like this, then it’s fine:
for (uint j = 0; j < lightUBO.dirLightNum; j++)
printf(“L %v3f”, normalize(-lightUBO.dirLights[j].direction));
(using printf only for illustration here, the actual light direction is used to calculate bias for shadow PCF)

I can confirm that:

  • dirLightNum is exactly 1 (verified on the CPU side, and on GPU side with RenderDoc and debug printf)
  • lightUBO.dirLights[j].direction (j = 0) holds the correct data (verified on the CPU side, and on GPU side with RenderDoc and debug printf)
  • After countless tests on the shader side, the culprit can only be this line of code

I have tried:

  • Hardcoding the light direction on shader side, works fine
  • (Shown above) Accessing the data in a for loop, works fine
  • Integrating Nsight Aftermath, no minidump generated
  • Integrating the shader printf feature, the program crashes during drawing so no output
  • Changing things around in other parts of my shader code, no effect

Other relevant info:

  • The VS debugger throws an exception at the first drawIndexed call of the first frame (so first invocation of the fragment shader). Message is Exception thrown at 0x00007FFC5089522D (nvoglv64.dll) in utah.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
  • Using Nsight Graphics to run my program somehow will not trigger the crash. But using VS/.exe/RenderDoc will
  • My project: GitHub Repo (Pretty messy code I know)
    . The shader is /shaders/blinn_phong_frag.hlsl. LightUBO definition is in /src/Render/GPUTypes.h.

Even though I know the final version of my shader will still use a for loop, but this bug is just too strange for me to wrap my head around. I have spent the past two days trying to figure this one out, and I would appreciate any insight or pointers anyone can share!

You’ve not mentioned it: is your program clean wrt validation layers?
Another thing you could look at the SPIR-V difference between the working and not working versions of the shader.

Ah my bad, but yes I do have validation layers enabled and no logs are relevant/caused by my shader crash here.

And for the assembly generated, the working version has:
%139 = OpAccessChain %_ptr_Uniform_v3float %lightUBO %int_5 %132 %int_0

While the non working version has:
%139 = OpAccessChain %_ptr_Uniform_v3float %lightUBO %int_5 %int_0 %int_0

To minimize the difference I only edited the index, so both versions are in a loop, one uses [j] and one uses [0]. But this line is the only difference between the two and it looks pretty normal to me

I have only used OpenGL and GLSL, so this is just my attempt to offer a guess/input more than a solution. I don’t think I have ever had a crash due to something happening in GLSL, even very wrong things. Perhaps the uniform block is in some sort of invalid state and only because of this use is that invalid state being invoked.

0xFFFFFFFFFFFFFFFF is a very interesting address to ever appear in an error message. It makes me suspect something uninitialized. It should be noted that trying to access “-1” will result in that address being dereferenced.