diff options
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/slang-compiler.cpp | 6 | ||||
| -rw-r--r-- | source/slang/slang-compiler.h | 9 | ||||
| -rw-r--r-- | source/slang/slang-emit.cpp | 63 |
3 files changed, 76 insertions, 2 deletions
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 58cc55e71..3839e0722 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -2669,6 +2669,12 @@ bool CodeGenContext::shouldDumpIR() return getTargetProgram()->getOptionSet().getBoolOption(CompilerOptionName::DumpIr); } +bool CodeGenContext::shouldSkipDownstreamLinking() +{ + return getTargetProgram()->getOptionSet().getBoolOption( + CompilerOptionName::SkipDownstreamLinking); +} + bool CodeGenContext::shouldReportCheckpointIntermediates() { return getTargetProgram()->getOptionSet().getBoolOption( diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 10da32400..cfcbe816f 100644 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -1384,7 +1384,8 @@ enum class PassThroughMode : SlangPassThroughIntegral LLVM = SLANG_PASS_THROUGH_LLVM, ///< LLVM 'compiler' SpirvOpt = SLANG_PASS_THROUGH_SPIRV_OPT, ///< pass thorugh spirv to spirv-opt MetalC = SLANG_PASS_THROUGH_METAL, - Tint = SLANG_PASS_THROUGH_TINT, ///< pass through spirv to Tint API + Tint = SLANG_PASS_THROUGH_TINT, ///< pass through spirv to Tint API + SpirvLink = SLANG_PASS_THROUGH_SPIRV_LINK, ///< pass through spirv to spirv-link CountOf = SLANG_PASS_THROUGH_COUNT_OF, }; void printDiagnosticArg(StringBuilder& sb, PassThroughMode val); @@ -2886,6 +2887,12 @@ public: // removed between IR linking and target source generation. bool removeAvailableInDownstreamIR = false; + // Determines if program level compilation like getTargetCode() or getEntryPointCode() + // should return a fully linked downstream program or just the glue SPIR-V/DXIL that + // imports and uses the precompiled SPIR-V/DXIL from constituent modules. + // This is a no-op if modules are not precompiled. + bool shouldSkipDownstreamLinking(); + protected: CodeGenTarget m_targetFormat = CodeGenTarget::Unknown; ExtensionTracker* m_extensionTracker = nullptr; diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index ddb4ea67a..94ea66d71 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -2093,10 +2093,71 @@ SlangResult emitSPIRVForEntryPointsDirectly( if (compiler) { #if 0 - // Dump the unoptimized SPIRV after lowering from slang IR -> SPIRV + // Dump the unoptimized/unlinked SPIRV after lowering from slang IR -> SPIRV compiler->disassemble((uint32_t*)spirv.getBuffer(), int(spirv.getCount() / 4)); #endif + bool isPrecompilation = codeGenContext->getTargetProgram()->getOptionSet().getBoolOption( + CompilerOptionName::EmbedDownstreamIR); + + if (!isPrecompilation && !codeGenContext->shouldSkipDownstreamLinking()) + { + ComPtr<IArtifact> linkedArtifact; + + // collect spirv files + List<uint32_t*> spirvFiles; + List<uint32_t> spirvSizes; + + // Start with the SPIR-V we just generated. + // SPIRV-Tools-link expects the size in 32-bit words + // whereas the spirv blob size is in bytes. + spirvFiles.add((uint32_t*)spirv.getBuffer()); + spirvSizes.add(int(spirv.getCount()) / 4); + + // Iterate over all modules in the linkedIR. For each module, if it + // contains an embedded downstream ir instruction, add it to the list + // of spirv files. + auto program = codeGenContext->getProgram(); + + program->enumerateIRModules( + [&](IRModule* irModule) + { + for (auto globalInst : irModule->getModuleInst()->getChildren()) + { + if (auto inst = as<IREmbeddedDownstreamIR>(globalInst)) + { + if (inst->getTarget() == CodeGenTarget::SPIRV) + { + auto slice = inst->getBlob()->getStringSlice(); + spirvFiles.add((uint32_t*)slice.begin()); + spirvSizes.add(int(slice.getLength()) / 4); + } + } + } + }); + + SLANG_ASSERT(int(spirv.getCount()) % 4 == 0); + SLANG_ASSERT(spirvFiles.getCount() == spirvSizes.getCount()); + + if (spirvFiles.getCount() > 1) + { + SlangResult linkresult = compiler->link( + (const uint32_t**)spirvFiles.getBuffer(), + (const uint32_t*)spirvSizes.getBuffer(), + (uint32_t)spirvFiles.getCount(), + linkedArtifact.writeRef()); + + if (linkresult != SLANG_OK) + { + return SLANG_FAIL; + } + + ComPtr<ISlangBlob> blob; + linkedArtifact->loadBlob(ArtifactKeep::No, blob.writeRef()); + artifact = _Move(linkedArtifact); + } + } + if (!codeGenContext->shouldSkipSPIRVValidation()) { StringBuilder runSpirvValEnvVar; |
