Skip loading slang-glslang when no downstream SPIR-V work is needed#11797
Draft
nv-slang-bot[bot] wants to merge 1 commit into
Draft
Skip loading slang-glslang when no downstream SPIR-V work is needed#11797nv-slang-bot[bot] wants to merge 1 commit into
nv-slang-bot[bot] wants to merge 1 commit into
Conversation
The SPIR-V backend's createArtifactFromIR unconditionally loaded the slang-glslang downstream compiler (PassThroughMode::SpirvOpt) before deciding whether any downstream work was required. Because the diagnostic sink is non-null, a build without slang-glslang then failed with a fatal E00100 (failed-to-load-downstream-compiler) even for a single-module -O0 -target spirv compile, which needs no optimization, link, validation, or separate debug info. Slang emits and legalizes SPIR-V natively, so the natively emitted module is already complete and valid. Determine up front whether downstream work is actually needed -- optimization above None, a multi-module link, SPIR-V validation, or separate debug info -- and only load slang-glslang in that case. The link-candidate enumeration walks IR only, so it is hoisted ahead of the load and reused. When nothing downstream is required the natively emitted SPIR-V is returned as-is, so a default -O0 -target spirv compile no longer depends on slang-glslang. Add tests/bugs/gh-11662.slang covering the -O0 -target spirv path. Fixes #11662.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
A single-module
-O0 -target spirvcompile needs no downstream (slang-glslang / SPIRV-Tools) work: there is nothing to optimize, no second module to link, validation is off, and no separate debug info is requested. YetcreateArtifactFromIRinsource/slang/slang-emit.cppunconditionally loaded theslang-glslangdownstream compiler before deciding whether any of that work was actually needed:Because the diagnostic sink passed here is non-null, a build that does not ship the
slang-glslangmodule fails with a fatalE00100(failed-to-load-downstream-compiler) — even though, for a default-O0 -target spirvcompile, the natively emitted SPIR-V is already the final output and the module would never have done anything. This is the failure reported in #11662.Proposed solution
Decide whether any downstream work is actually required before loading the downstream compiler, and only load it when it is. Slang emits and legalizes SPIR-V natively, so the module added to the artifact immediately above the load is already a complete, valid SPIR-V module. The
slang-glslangcompiler is only needed to:None),When none of these apply, the natively emitted SPIR-V is returned as-is and
slang-glslangis never loaded — so a single-module-O0 -target spirvcompile has no dependency on the module.This is the runtime-gating approach. A companion PR implements the alternative config-time approach (a CMake option that compiles the registration out); the two are intended to be compared. This PR is the one that does not add a new build option.
Change summary
source/slang/slang-emit.cppcreateArtifactFromIR: hoist theisPrecompilationflag and the link-candidate enumeration (which walks IR only) above the downstream-compiler load; computeneedsLink/needsOptimization/needsValidation/needsSeparateDebugInfoand loadslang-glslangonly when one of them holds; guard the link block onneedsLinkand reuse the pre-collected module list.tests/bugs/gh-11662.slang-O0 -target spirvand FileCheck-ing a complete module (OpEntryPoint GLCompute,OpExecutionMode … LocalSize,OpStore).Concepts and vocabulary
PassThroughMode::SpirvOpt— theslang-glslangmodule, loaded viagetOrLoadDownstreamCompileranddlopen. It wraps SPIRV-Tools (optimize/validate/link/disassemble) plus glslang. It is loaded at runtime, not linked.emitSPIRVFromIRproduces the SPIR-V directly from Slang IR, including all legalization. The downstream optimizer is a perf/size pass, not part of producing a valid module.E00100—failed-to-load-downstream-compiler; raised (as an error, because the sink is non-null) whengetOrLoadDownstreamCompilercannot find the module.Process report
The load is the only thing that touched
slang-glslangon this path, and it was unconditional. IncreateArtifactFromIRthe optimizer compile (compiler->compile) ran unconditionally insideif (compiler), the link was already gated tospirvFiles.getCount() > 1, validation was gated toshouldRunSPIRVValidation, and disassembly is only reached on thespirv-asm/ IR-dump paths (not this binary-SPIR-V output path). So for a single-module-O0compile the only reference to the module was the unconditionalgetOrLoadDownstreamCompilercall — which is what raisedE00100. The fix moves the need-determination ahead of that call.Why this is behavior-preserving except for the intended case. Previously the compiler was always loaded and
compile()always ran, so even a single-module-O0compile went through a SPIRV-Tools optimize-at-Noneround-trip. The optimizer atOptimizationLevel::Noneis an identity copy (glslang_optimizeSPIRVreturns immediately and the wrapper copies the input SPIR-V to the output artifact), so skipping it in the no-work case only skips that identity round-trip; the resulting module is the same natively emitted, already-legal SPIR-V. For every case where the compiler is still loaded (optimization aboveNone, link, validation, separate debug info),compile()still runs exactly as before, so output is unchanged. The one changed output path is single-module-O0with validation off and no separate debug info, which now returns the native SPIR-V without the identity round-trip — the intended fix.Why
needsSeparateDebugInfois part of the gate. The separate-debug artifact is created after a successful downstreamcompile()(viastripDbgSpirvFromArtifact). If separate debug info were requested but we did not load the compiler, that output would be silently skipped — soshouldEmitSeparateDebugInfo()is included inneedsDownstreamCompiler.Why hoisting the enumeration is safe. The link-candidate enumeration (
program->enumerateIRModules) only walks IR and records embedded SPIR-V blobs; it needs no downstream compiler and mutates nothing, so it is safe to run before the load and reuse afterward. It adds negligible work to the no-downstream path.Input-shape check. No malformed input is being masked. The natively emitted SPIR-V is a correct, complete module by construction (legalization is native); the change only avoids an unnecessary downstream load. This is a consumer-side decision about when an optional downstream tool is required, not a workaround for a bad upstream representation.
Verification. Built
slangc+slang-test(debug); the new test passes; existing-O0 -target spirvtests (forceinline-basic-block,entry-point-array-return) pass; the fulltests/spirv/suite passes (470/470, 0 regressions). The test guards that the-O0 -target spirvpath still emits a complete module after the gating change; it cannot exercise the "module physically absent" scenario because the standard test build always bundlesslang-glslang(and the binary SPIR-V output is disassembled for FileCheck, which itself usesslang-glslang).Fixes #11662.