shader-slang / slang

Making it easier to work with shaders
http://shader-slang.com
MIT License
2.13k stars 180 forks source link

Shader debugging via RenderDoc #2552

Closed NickDriscoll closed 1 year ago

NickDriscoll commented 1 year ago

I'm trying to debug the execution of one of my fragment shaders using RenderDoc, but I can't seem to deduce the required incantation to make slangc produce debug output. I have added the -g3, -O0, and "-Xglslang gVS" args to no avail.

Does slang not support source-level debugging or am I just missing something?

Thank you.

jsmall-zzz commented 1 year ago

Hi Nick,

On slangc you should be able to use -O0 and -g3 with SPIR-V. Doing some quick tests the SPIR-V output does change with varying -g0 and -g3 which means that the value is at least getting passed through to GLSLANG.

By default slang will output #line into output GLSL such that it relates to the original slang code. If you want debug information that relates to the intermediate GLSL, you can get that via -line-directive none.

On looking at slang-glslang adding the option adds two passes, which seem appropriate.

Can you provide more information about what you are seeing/not seeing?

NickDriscoll commented 1 year ago

So I'm trying to follow the steps outlined here: https://renderdoc.org/docs/how/how_debug_shader.html

As I understand it, with the proper flags, debug output is included directly in the SPIR-V bytecode, and so RenderDoc should be able to debug it using the original source no problem.

Instead, in RenderDoc I see clearly decompiled shader code in the debugger, along with the message "Source debugging Unavailable"

It is possible I'm just using RenderDoc incorrectly as well, but I don't think so.

jsmall-zzz commented 1 year ago

Thanks for the additional information. As you may know Slang uses a shared library slang-glslang that contains the GLSLANG compiler. As it stands it doesn't honor any GLSLANG specific command line options, so unfortunately -Xglslang -gVS will not work.

On looking into what that option actually does, it seems to lead to two changes passed to the glslang::SpvOptions to glslang::GlslangToSpv. You could enable them both yourself in a build of slang-glslang by editing the slang-glslang.cpp file and adding...

        copySpvOptions.emitNonSemanticShaderDebugInfo = true;
        copySpvOptions.emitNonSemanticShaderDebugSource = true;

It's fairly easy to do this if you are used to premake and building slang from source. Just make the source code changes, and then do (for windows)

premake vs2019 --build-glslang=true

Will build slang-glslang when the VS project is built.

Alternatively you could make Slang output glsl, and then compile with glslang with the -gVS option perhaps.

Adding support to the Slang compiler - these options could perhaps be enabled with high enough debug information. Alternatively we add support by honoring some glslang command line options, although doing so would require a new glslang_CompileRequest_1_2 that supported the additional args.

jsmall-zzz commented 1 year ago

I did just try the change out by adding the lines above to slang-glslang.cpp and it does appear to add (NonSemantic.Shader.DebugInfo.100) insts.

NickDriscoll commented 1 year ago

When I add those two lines and rebuild, slangc fails to output the .spv file. I don't see any errors or additional warnings in my log either.

NickDriscoll commented 1 year ago

Actually... If I try to run the command a dozen or so times, it will output a file.

NickDriscoll commented 1 year ago

Ok when I try to use the .spv's that eventually come out it turns out they aren't valid.

UNASSIGNED-CoreValidation-Shader-InconsistentSpirv(ERROR / SPEC): msgNum: 7060244 - Validation Error: [ UNASSIGNED-CoreValidation-Shader-InconsistentSpirv ] Object 0: handle = 0x24c9893e8b0, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x6bbb14 | SPIR-V module not valid: Invalid word count: OpString starting at word 461 says it has 4 words, but found 5 words instead.

NickDriscoll commented 1 year ago

The compiler will emit valid SPIR-V if either one of the two flags is set, but if both are set it will almost always silently emit nothing, with the occasional emission of invalid SPIR-V.

jsmall-zzz commented 1 year ago

Hi Nick,

I looked into this a little more this afternoon. If I enable both flags I end with

Validation: error 0: Validation Error: [ UNASSIGNED-CoreValidation-Shader-InconsistentSpirv ] Object 0: handle = 0x17a8bffb060, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x6bbb14 | SPIR-V module not valid: Id is 0

Validation: error 0: Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-04147 ] Object 0: handle = 0x17a8bffb060, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x3d492883 | vkCreateShaderModule(): The SPIR-V Extension (SPV_KHR_non_semantic_info) was declared, but none of the requirements were met to use it. The Vulkan spec states: If pCode declares any of the SPIR-V extensions listed in the SPIR-V Environment appendix, one of the corresponding requirements must be satisfied (https://vulkan.lunarg.com/doc/view/1.2.182.0/windows/1.2-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-04147)

From the vk validation layer.

If I enable just emitNonSemanticShaderDebugSource the output doesn't have the extra instructions (it's identical to no flags set). If I just enable emitNonSemanticShaderDebugInfo I get the same error as above.

I did wonder if the issue you saw around strings being invalidly encoded might be due to #line directives in glsl, so I disabled with -line-directive-mode none.

Note I only enabled the flags when no optimization, and debug info was enabled - the worry there is that optimization via spirv-opt may not appropriately honor the debug info instructions.

So I'm not sure what this means. Slang creates valid glsl that we pass to glslang. If we don't do any optimization, then spirv-opt is not being run at all. So that implies glslang is outputting something invalid, or the validation layer is claiming something is invalid, which is not.