From fa8c11ebe8f9b1bf2174a5a4dbe92a34c16811c8 Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 12 Jun 2024 09:27:14 -0700 Subject: [PATCH] Add option to preserve shader parameter declaration in output SPIRV. (#4344) * Add option to preserve shader parameter declarations in output. * Add test. --- docs/command-line-slangc-reference.md | Bin 77996 -> 80334 bytes slang.h | 1 + source/slang/slang-emit-spirv.cpp | 3 +++ source/slang/slang-emit.cpp | 1 + source/slang/slang-ir-dce.cpp | 2 ++ source/slang/slang-ir-dce.h | 1 + source/slang/slang-ir-link.cpp | 8 +++++-- source/slang/slang-ir-specialize.cpp | 3 +-- source/slang/slang-ir-ssa-simplification.cpp | 21 +++++++++---------- source/slang/slang-ir-ssa-simplification.h | 3 +++ source/slang/slang-options.cpp | 2 ++ tests/spirv/preserve-param.slang | 19 +++++++++++++++++ 12 files changed, 49 insertions(+), 15 deletions(-) create mode 100644 tests/spirv/preserve-param.slang diff --git a/docs/command-line-slangc-reference.md b/docs/command-line-slangc-reference.md index 7c2beb7e034a19b3fad3274bf653d7214360ef73..594e2591271f637dec9285fd6da6005e1559831b 100644 GIT binary patch delta 1414 zcma)6OK4L;6rCw;Ok?u;k~D2Xs(rOB{u*ge#A=bM@w=!+MFi2BCanh3G$v_KQL7t4 z?V@@Y<4O_TC`HsP3NECI3m5hWZbhX{D=rEmxDd6TnUMIy&tm4y+|RjZ&fIx}Z;D4h z6yGa$dm=2xBCMPBV)$5+MOhG*!^}tiO&&5`c6+C6DIrZ>KbV`*zQ6dgQegzkQ-!anNRJfyd^2giR=Tlq_t@EG1y~Z*9m?}%rWFd z5Fdptt-cYU&p%jC%^P(8e?=opVo2O1z4E#G{+wm7?Q9nq7ApOi3wsjUh1e0Sf>;~a zNsb1vyVOoMiAlE+Tg0Va}Fh%Q%GlICz^irnk#sBwknjiZc|RbF3O zm5VD z(*2q%Z_TNqq5<0%s4UBq@}b+&Q?%i(w|WK22C$Re*o$LG8W9{ccbi@0Z?4GVep|AVwKG2*9rKGv4csiAdbvZ~wQ^ltTfjAHd8cI>M|bcC9ByXZ-_oZ7Mt^f7ypjA=8qW|vTG zdXQ$PEwI;-F_Qc0Gl9GYrScDwLfIruOnOR_SO=xTw0Y(O4Wr1*yKaoD?5N;nydFs=aaH46#ITK9L_p^a63iiHHNHx;mhpF@v5qgJ<5QYi41He2 H@7cZq;Y@mn delta 303 zcmW-bze@sP9LC?T9IwZr$6>!N5<8@VUJjRjOcp{^OBnP+f}-v(xG|#1F`~&Y^qq?4 zXgGL5SBHim5ewTKtgJ!w)La|VhKJ|F^I4v9UwL>}JjIlmspO0-rrbj;rXq6jMl4f( z2~^BHN9bY{4D|Xswt71L{^-)GCL!0+=*a?ea+htheYV5a*g88I2S0jHFSL~_oYaq$pctxsd)OL<6SF>(e@>tx8tb!XK1}@Sn>5-Cys8X zfub}=-Ux7XdYo1lhHt8xJnoifsVE>q?mQ$Y8w5^Inv%w4h0shN!!~g&Q diff --git a/slang.h b/slang.h index ce659b007d..d807efec47 100644 --- a/slang.h +++ b/slang.h @@ -865,6 +865,7 @@ extern "C" MinimumSlangOptimization, // bool DisableNonEssentialValidations, // bool DisableSourceMap, // bool + PreserveParameters, // bool: preserve all resource parameters in the output code. // Target diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index fd4b1d4918..10c2637932 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -6431,10 +6431,13 @@ SlangResult emitSPIRVFromIR( } #endif + auto shouldPreserveParams = codeGenContext->getTargetProgram()->getOptionSet().getBoolOption(CompilerOptionName::PreserveParameters); for (auto inst : irModule->getGlobalInsts()) { if (as(inst)) context.ensureInst(inst); + if (shouldPreserveParams && as(inst)) + context.ensureInst(inst); } // Emit source language info. diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 6d0ab1daac..38f066c6c9 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -585,6 +585,7 @@ Result linkAndOptimizeIR( IRDeadCodeEliminationOptions deadCodeEliminationOptions = IRDeadCodeEliminationOptions(); fastIRSimplificationOptions.minimalOptimization = defaultIRSimplificationOptions.minimalOptimization; deadCodeEliminationOptions.useFastAnalysis = fastIRSimplificationOptions.minimalOptimization; + deadCodeEliminationOptions.keepGlobalParamsAlive = targetProgram->getOptionSet().getBoolOption(CompilerOptionName::PreserveParameters); simplifyIR(targetProgram, irModule, defaultIRSimplificationOptions, sink); diff --git a/source/slang/slang-ir-dce.cpp b/source/slang/slang-ir-dce.cpp index 4eefeabd50..f414f7266e 100644 --- a/source/slang/slang-ir-dce.cpp +++ b/source/slang/slang-ir-dce.cpp @@ -423,6 +423,8 @@ bool shouldInstBeLiveIfParentIsLive(IRInst* inst, IRDeadCodeEliminationOptions o case kIROp_WitnessTableEntry: return true; + case kIROp_GlobalParam: + return options.keepGlobalParamsAlive; default: break; } diff --git a/source/slang/slang-ir-dce.h b/source/slang/slang-ir-dce.h index d52ec817e7..55eed1c925 100644 --- a/source/slang/slang-ir-dce.h +++ b/source/slang/slang-ir-dce.h @@ -12,6 +12,7 @@ namespace Slang bool keepExportsAlive = false; bool keepLayoutsAlive = false; bool useFastAnalysis = false; + bool keepGlobalParamsAlive = true; }; /// Eliminate "dead" code from the given IR module. diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp index eb660c8a78..5bb485b223 100644 --- a/source/slang/slang-ir-link.cpp +++ b/source/slang/slang-ir-link.cpp @@ -1830,12 +1830,16 @@ LinkedIR linkIR( } } + bool shouldCopyGlobalParams = linkage->m_optionSet.getBoolOption(CompilerOptionName::PreserveParameters); + for (IRModule* irModule : irModules) { for (auto inst : irModule->getGlobalInsts()) { - // Is it (HLSL) `export` clone - if (_isHLSLExported(inst)) + // We need to copy over exported symbols, + // and any global parameters if preserve-params option is set. + if (_isHLSLExported(inst) || + shouldCopyGlobalParams && as(inst)) { auto cloned = cloneValue(context, inst); if (!cloned->findDecorationImpl(kIROp_KeepAliveDecoration)) diff --git a/source/slang/slang-ir-specialize.cpp b/source/slang/slang-ir-specialize.cpp index 8fac31a2b1..5713b96399 100644 --- a/source/slang/slang-ir-specialize.cpp +++ b/source/slang/slang-ir-specialize.cpp @@ -49,7 +49,6 @@ struct SpecializationContext IRModule* module; DiagnosticSink* sink; TargetProgram* targetProgram; - bool changed = false; @@ -861,7 +860,7 @@ struct SpecializationContext if (iterChanged) { this->changed = true; - eliminateDeadCode(module->getModuleInst(), IRDeadCodeEliminationOptions()); + eliminateDeadCode(module->getModuleInst()); } // Once the work list has gone dry, we should have the invariant diff --git a/source/slang/slang-ir-ssa-simplification.cpp b/source/slang/slang-ir-ssa-simplification.cpp index 2a9c0da439..b8d6360add 100644 --- a/source/slang/slang-ir-ssa-simplification.cpp +++ b/source/slang/slang-ir-ssa-simplification.cpp @@ -24,6 +24,9 @@ namespace Slang else result.cfgOptions = CFGSimplificationOptions::getDefault(); result.peepholeOptions = PeepholeOptimizationOptions(); + if (targetProgram) + result.deadCodeElimOptions.keepGlobalParamsAlive = targetProgram->getOptionSet().getBoolOption(CompilerOptionName::PreserveParameters); + result.deadCodeElimOptions.useFastAnalysis = result.minimalOptimization; return result; } @@ -33,6 +36,9 @@ namespace Slang result.minimalOptimization = targetProgram ? targetProgram->getOptionSet().shouldPerformMinimumOptimizations() : false; result.cfgOptions = CFGSimplificationOptions::getFast(); result.peepholeOptions = PeepholeOptimizationOptions(); + if (targetProgram) + result.deadCodeElimOptions.keepGlobalParamsAlive = targetProgram->getOptionSet().getBoolOption(CompilerOptionName::PreserveParameters); + result.deadCodeElimOptions.useFastAnalysis = result.minimalOptimization; return result; } @@ -45,8 +51,6 @@ namespace Slang const int kMaxIterations = 8; const int kMaxFuncIterations = 16; int iterationCounter = 0; - IRDeadCodeEliminationOptions dceOptions = IRDeadCodeEliminationOptions(); - dceOptions.useFastAnalysis = options.minimalOptimization; while (changed && iterationCounter < kMaxIterations) { @@ -79,7 +83,7 @@ namespace Slang // Note: we disregard the `changed` state from dead code elimination pass since // SCCP pass could be generating temporarily evaluated constant values and never actually use them. // DCE will always remove those nearly generated consts and always returns true here. - eliminateDeadCode(func, dceOptions); + eliminateDeadCode(func, options.deadCodeElimOptions); if (funcIterationCount == 0) funcChanged |= constructSSA(func); changed |= funcChanged; @@ -88,7 +92,7 @@ namespace Slang } iterationCounter++; } - eliminateDeadCode(module, dceOptions); + eliminateDeadCode(module, options.deadCodeElimOptions); } void simplifyNonSSAIR(TargetProgram* target, IRModule* module, IRSimplificationOptions options) @@ -96,8 +100,6 @@ namespace Slang bool changed = true; const int kMaxIterations = 8; int iterationCounter = 0; - IRDeadCodeEliminationOptions dceOptions = IRDeadCodeEliminationOptions(); - dceOptions.useFastAnalysis = options.minimalOptimization; while (changed && iterationCounter < kMaxIterations) { @@ -111,7 +113,7 @@ namespace Slang // Note: we disregard the `changed` state from dead code elimination pass since // SCCP pass could be generating temporarily evaluated constant values and never actually use them. // DCE will always remove those nearly generated consts and always returns true here. - eliminateDeadCode(module, dceOptions); + eliminateDeadCode(module, options.deadCodeElimOptions); iterationCounter++; } } @@ -119,9 +121,6 @@ namespace Slang void simplifyFunc(TargetProgram* target, IRGlobalValueWithCode* func, IRSimplificationOptions options, DiagnosticSink* sink) { - IRDeadCodeEliminationOptions dceOptions = IRDeadCodeEliminationOptions(); - dceOptions.useFastAnalysis = options.minimalOptimization; - bool changed = true; const int kMaxIterations = 8; int iterationCounter = 0; @@ -140,7 +139,7 @@ namespace Slang // Note: we disregard the `changed` state from dead code elimination pass since // SCCP pass could be generating temporarily evaluated constant values and never actually use them. // DCE will always remove those nearly generated consts and always returns true here. - eliminateDeadCode(func, dceOptions); + eliminateDeadCode(func, options.deadCodeElimOptions); changed |= constructSSA(func); diff --git a/source/slang/slang-ir-ssa-simplification.h b/source/slang/slang-ir-ssa-simplification.h index 166f5a5f38..d524241ae5 100644 --- a/source/slang/slang-ir-ssa-simplification.h +++ b/source/slang/slang-ir-ssa-simplification.h @@ -3,6 +3,7 @@ #include "slang-ir-simplify-cfg.h" #include "slang-ir-peephole.h" +#include "slang-ir-dce.h" namespace Slang { @@ -15,6 +16,8 @@ namespace Slang { CFGSimplificationOptions cfgOptions; PeepholeOptimizationOptions peepholeOptions; + IRDeadCodeEliminationOptions deadCodeElimOptions; + bool minimalOptimization = false; static IRSimplificationOptions getDefault(TargetProgram* targetProgram); diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index 4bbd0dcafb..aefb14deb7 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -347,6 +347,7 @@ void initCommandOptions(CommandOptions& options) { OptionKind::SourceEmbedLanguage, "-source-embed-language", "-source-embed-language ", "The language to be used for source embedding. Defaults to C/C++. Currently only C/C++ are supported"}, { OptionKind::DisableShortCircuit, "-disable-short-circuit", nullptr, "Disable short-circuiting for \"&&\" and \"||\" operations" }, + { OptionKind::PreserveParameters, "-preserve-params", nullptr, "Preserve all resource parameters in the output code, even if they are not used by the shader."} }; _addOptions(makeConstArrayView(generalOpts), options); @@ -1704,6 +1705,7 @@ SlangResult OptionsParser::_parse( case OptionKind::NoHLSLBinding: case OptionKind::NoHLSLPackConstantBufferElements: case OptionKind::LoopInversion: + case OptionKind::PreserveParameters: linkage->m_optionSet.set(optionKind, true); break; break; case OptionKind::MatrixLayoutRow: diff --git a/tests/spirv/preserve-param.slang b/tests/spirv/preserve-param.slang new file mode 100644 index 0000000000..e9cc82291b --- /dev/null +++ b/tests/spirv/preserve-param.slang @@ -0,0 +1,19 @@ +//TEST:SIMPLE(filecheck=CHECK): -target spirv -preserve-params -O0 + +// Test that -preserve-params option preserves shader paraemter declarations in the output spirv code. + +// CHECK-DAG: OpDecorate %{{.*}} Binding 0 + +// CHECK-DAG: OpDecorate %{{.*}} Binding 1 + +RWStructuredBuffer buffer; + +struct TT +{ + Texture2D tex; +} +[numthreads(1, 1, 1)] +void f(ConstantBuffer t) +{ + return; +} \ No newline at end of file