[ SPIR-V ] NonSemantic.Shader.DebugInfo.100 DebugDeclare: expected operand Variable must be a result id of OpVariable or OpFunctionParameter
We encountered the following error with one of our shaders when using -fspv-debug=vulkan-with-source to debug the shader in RenderDoc:
fatal error: generated SPIR-V is invalid: NonSemantic.Shader.DebugInfo.100 DebugDeclare: expected operand Variable must be a result id of OpVariable or OpFunctionParameter
%94 = OpExtInst %void %1 DebugDeclare %36 %92 %20
@jeremy-lunarg helped strip it down to a test case we could share (attached). You can reproduce the error with this shader and the following command-line:
dxc.exe -spirv -T vs_6_0 -E MainVs -fspv-debug=vulkan-with-source shaderdebug_simple.hlsl
fatal error: generated SPIR-V is invalid: NonSemantic.Shader.DebugInfo.100 DebugDeclare: expected operand Variable must be a result id of OpVariable or OpFunctionParameter
%94 = OpExtInst %void %1 DebugDeclare %36 %92 %20
note: please file a bug report on https://github.com/Microsoft/DirectXShaderCompiler/issues with source code if possible
I've done some investigating and it appears to be coming from the exhaustive inlining pass.
I've stumbled upon this problem myself recently, after investigation it appears to be a problem in EmitVisitor::visit functions for some SpirvDebug types such as SpirvDebugEntryPoint, SpirvDebugFunctionDefinition, SpirvDebugScope, SpirvDebugDeclare. The problem is that the finalizeInstruction call in these functions should be called with &richDebugInfo instead of &mainBinary. I changed it to &richDebugInfo locally and it fixed the issue for me. I don't know if it's the right way to fix this, but I can roll out a pull request with the fix.
I'm working on fix to the optimizer to convert access chain function call arguments to temporary OpVariables so the inlining pass can handle DebubDeclare correctly.
After discussing with @s-perron and @greg-lunarg, I believe the work that @llvm-beanz is doing will completely avoid this problem and it is the ideal way to fix this issue.
It will avoid it until we add reference to the language. We can wait until references are implemented to fix it. Otherwise we won't be able to test the fix.
As far as I see it, this problem still persists. I stumbled over it recently as well. In case you need a simple reproducer, see here: https://godbolt.org/z/nYeW4KrbE
Compile
void fn(inout int x) { x = 2; }
// Define some dummy entry point
[shader("raygeneration")]
void main() {
int2 v;
fn(v.x);
}
with options -T lib_6_4 -spirv -fspv-target-env=vulkan1.2 -enable-16bit-types -HV 2021 -fspv-debug=vulkan-with-source.
Actual Behavior DXC crashes with
fatal error: generated SPIR-V is invalid: NonSemantic.Shader.DebugInfo.100 DebugDeclare: expected operand Variable must be a result id of OpVariable or OpFunctionParameter
%63 = OpExtInst %void %1 DebugDeclare %29 %61 %15
Issue is still there. I got it in MANY different places, but this is my easiest reproduce: https://godbolt.org/z/zosPGqjWv
I have a PR that should fix some of the cases. Let me know if there are other.
@s-perron #7127 Fixed some cases, but, for example, this will still fail: https://godbolt.org/z/E8vWded94
struct SomeStruct
{
float a;
float getA(){ return a; }
};
cbuffer ConstBuffer {
SomeStruct str;
}
[numthreads(1, 1, 1)]
void computeMain()
{
float a = str.getA();
}
-E computeMain -T cs_6_6 -spirv -fspv-debug=vulkan-with-source
@s-perron #7127 Fixed some cases, but, for example, this will still fail: https://godbolt.org/z/E8vWded94
struct SomeStruct { float a; float getA(){ return a; } };
cbuffer ConstBuffer { SomeStruct str; }
[numthreads(1, 1, 1)] void computeMain() { float a = str.getA(); }
-E computeMain -T cs_6_6 -spirv -fspv-debug=vulkan-with-source
@kp-eagle btw the Godbolt instance still says fcbd2a18 when asked for --version
@s-perron #7127 Fixed some cases, but, for example, this will still fail: https://godbolt.org/z/E8vWded94 struct SomeStruct { float a; float getA(){ return a; } }; cbuffer ConstBuffer { SomeStruct str; } [numthreads(1, 1, 1)] void computeMain() { float a = str.getA(); }
-E computeMain -T cs_6_6 -spirv -fspv-debug=vulkan-with-source@kp-eagle btw the Godbolt instance still says
fcbd2a18when asked for--version
I didn't test it in Godbolt. Link is just for convenience. I built it locally with merged commit. So, if you think that it actually works after it - no, it doesn't =)
@s-perron #7127 Fixed some cases, but, for example, this will still fail: https://godbolt.org/z/E8vWded94 struct SomeStruct { float a; float getA(){ return a; } }; cbuffer ConstBuffer { SomeStruct str; } [numthreads(1, 1, 1)] void computeMain() { float a = str.getA(); }
-E computeMain -T cs_6_6 -spirv -fspv-debug=vulkan-with-source@kp-eagle btw the Godbolt instance still says
fcbd2a18when asked for--versionI didn't test it in Godbolt. Link is just for convenience. I built it locally with merged commit. So, if you think that it actually works after it - no, it doesn't =)
I see, I'm still waiting on Godbolt to see if my other stuff breaks because of inout being copy-in copy-out now
The new test case fails because the access chain in on the this pointer. The solution I implemented does not wok for the this pointer because we do not do a copy-in/copy-out for the this pointer. I'll need to find a new solution. I'm guessing I'll have to update the inlining pass in spirv-opt to generate valid debug instructions.
If that works, I'll revert my previous change. It won't be useful, and is a change in behaviour.
We still need to update the submodule.
Let me know if you still have issues. Both examples mentioned in https://github.com/microsoft/DirectXShaderCompiler/issues/5191#issuecomment-2674296229 now work.