summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcheneym2 <acheney@nvidia.com>2024-09-05 14:59:28 -0400
committerGitHub <noreply@github.com>2024-09-05 11:59:28 -0700
commit313677160a186efebf83fab4df7d08dd119a5cd2 (patch)
treee12e159846f0b7b0e3567d028ad4a57cd9f001aa
parent33e8bfd43f66613f6f834fb0e1816ef43071f2e4 (diff)
Initial -embed-spirv support (#4974)
* Initial -embed-spirv support Add support for SPIR-V precompilation using the framework established for DXIL. Work on #4883 * SLANG_UNUSED * Add linkage attributes to exported spirv functions * Combine DXIL and SPIRV paths * Whitespace fix * Merge remaining precompiled spirv/dxil paths * Change inst accessors to return codegentarget * Add unit test for precompiled spirv --------- Co-authored-by: Yong He <yonghe@outlook.com>
-rw-r--r--include/slang.h7
-rw-r--r--source/slang/slang-compiler-tu.cpp29
-rw-r--r--source/slang/slang-compiler.cpp33
-rwxr-xr-xsource/slang/slang-compiler.h8
-rw-r--r--source/slang/slang-emit-spirv.cpp26
-rw-r--r--source/slang/slang-emit.cpp58
-rw-r--r--source/slang/slang-ir-inst-defs.h4
-rw-r--r--source/slang/slang-ir-insts.h16
-rw-r--r--source/slang/slang-ir-redundancy-removal.cpp29
-rw-r--r--source/slang/slang-ir-redundancy-removal.h3
-rw-r--r--source/slang/slang-ir.cpp6
-rw-r--r--source/slang/slang-options.cpp15
-rw-r--r--source/slang/slang.cpp27
-rw-r--r--tests/library/precompiled-dxil-generics.slang4
-rw-r--r--tests/library/precompiled-dxil-matrix.slang2
-rw-r--r--tests/library/precompiled-dxil.slang6
-rw-r--r--tests/library/precompiled-module-library-resource.slang14
-rw-r--r--tests/library/precompiled-spirv-generics.slang28
-rw-r--r--tools/gfx-unit-test/precompiled-module-2.cpp8
19 files changed, 214 insertions, 109 deletions
diff --git a/include/slang.h b/include/slang.h
index ed2966592..9755415b3 100644
--- a/include/slang.h
+++ b/include/slang.h
@@ -956,8 +956,7 @@ extern "C"
GenerateWholeProgram, // bool
UseUpToDateBinaryModule, // bool, when set, will only load
// precompiled modules if it is up-to-date with its source.
-
- EmbedDXIL, // bool
+ EmbedDownstreamIR, // bool
ForceDXLayout, // bool
CountOf,
};
@@ -4929,9 +4928,9 @@ namespace slang
int targetIndex,
bool value) = 0;
- virtual SLANG_NO_THROW void SLANG_MCALL setEmbedDXIL(bool value) = 0;
-
virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceDXLayout(int targetIndex, bool value) = 0;
+
+ virtual SLANG_NO_THROW void SLANG_MCALL setTargetEmbedDownstreamIR(int targetIndex, bool value) = 0;
};
#define SLANG_UUID_ICompileRequest ICompileRequest::getTypeGuid()
diff --git a/source/slang/slang-compiler-tu.cpp b/source/slang/slang-compiler-tu.cpp
index fe778148b..57a1133fc 100644
--- a/source/slang/slang-compiler-tu.cpp
+++ b/source/slang/slang-compiler-tu.cpp
@@ -54,7 +54,7 @@ namespace Slang
* Precompile the module for the given target.
*
* This function creates a target program and emits the precompiled blob as
- * an embedded blob in the module IR, e.g. DXIL.
+ * an embedded blob in the module IR, e.g. DXIL, SPIR-V.
* Because the IR for the Slang Module may violate the restrictions of the
* target language, the emitted target blob may not be able to include the
* full module, but rather only the subset that can be precompiled. For
@@ -77,7 +77,7 @@ namespace Slang
* in the linked IR which survived the additional pruning.
*
* Functions that are rejected after linking+legalization (inside
- * emitPrecompiled*):
+ * emitPrecompiledDownstreamIR):
* - (DXIL) Functions that return or take a HLSLStructuredBufferType
* - (DXIL) Functions that return or take a Matrix type
*
@@ -86,17 +86,13 @@ namespace Slang
* phase of filtering.
*
* The original module IR functions matching those are then marked with
- * "AvailableIn*" (e.g. AvailableInDXILDecoration) to indicate to future
+ * "AvailableInDownstreamIRDecoration" to indicate to future
* module users which functions are present in the precompiled blob.
*/
SLANG_NO_THROW SlangResult SLANG_MCALL Module::precompileForTarget(
SlangCompileTarget target,
slang::IBlob** outDiagnostics)
{
- if (target != SLANG_DXIL)
- {
- return SLANG_FAIL;
- }
CodeGenTarget targetEnum = CodeGenTarget(target);
auto module = getIRModule();
@@ -130,10 +126,15 @@ namespace Slang
{
case CodeGenTarget::DXIL:
tp.getOptionSet().add(CompilerOptionName::Profile, Profile::RawEnum::DX_Lib_6_6);
- tp.getOptionSet().add(CompilerOptionName::EmbedDXIL, true);
break;
+ case CodeGenTarget::SPIRV:
+ break;
+ default:
+ return SLANG_FAIL;
}
+ tp.getOptionSet().add(CompilerOptionName::EmbedDownstreamIR, true);
+
CodeGenContext::EntryPointIndices entryPointIndices;
entryPointIndices.setCount(entryPointCount);
@@ -166,7 +167,7 @@ namespace Slang
}
ComPtr<IArtifact> outArtifact;
- SlangResult res = codeGenContext.emitPrecompiledDXIL(outArtifact);
+ SlangResult res = codeGenContext.emitPrecompiledDownstreamIR(outArtifact);
sink.getBlobIfNeeded(outDiagnostics);
if (res != SLANG_OK)
@@ -183,7 +184,8 @@ namespace Slang
for (const auto& mangledName : metadata->getExportedFunctionMangledNames())
{
auto moduleInst = nameToFunction[mangledName];
- builder.addDecoration(moduleInst, kIROp_AvailableInDXILDecoration);
+ builder.addDecoration(moduleInst, kIROp_AvailableInDownstreamIRDecoration,
+ builder.getIntValue(builder.getIntType(), (int)targetReq->getTarget()));
auto moduleDec = moduleInst->findDecoration<IRDownstreamModuleExportDecoration>();
moduleDec->removeAndDeallocate();
}
@@ -207,12 +209,7 @@ namespace Slang
// Add the precompiled blob to the module
builder.setInsertInto(module);
- switch (targetReq->getTarget())
- {
- case CodeGenTarget::DXIL:
- builder.emitEmbeddedDXIL(blob);
- break;
- }
+ builder.emitEmbeddedDownstreamIR(targetReq->getTarget(), blob);
return SLANG_OK;
}
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index 7d2dbed0d..4bb420fa7 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -767,9 +767,9 @@ namespace Slang
# pragma warning(pop)
#endif
- SlangResult CodeGenContext::emitPrecompiledDXIL(ComPtr<IArtifact>& outArtifact)
+ SlangResult CodeGenContext::emitPrecompiledDownstreamIR(ComPtr<IArtifact>& outArtifact)
{
- return emitWithDownstreamForEntryPoints(outArtifact);
+ return _emitEntryPoints(outArtifact);
}
String GetHLSLProfileName(Profile profile)
@@ -1257,10 +1257,7 @@ namespace Slang
{
CodeGenContext sourceCodeGenContext(this, sourceTarget, extensionTracker);
- if (target == CodeGenTarget::DXILAssembly || target == CodeGenTarget::DXIL)
- {
- sourceCodeGenContext.removeAvailableInDXIL = true;
- }
+ sourceCodeGenContext.removeAvailableInDownstreamIR = true;
SLANG_RETURN_ON_FAIL(sourceCodeGenContext.emitEntryPointsSource(sourceArtifact));
sourceCodeGenContext.maybeDumpIntermediate(sourceArtifact);
@@ -1561,20 +1558,23 @@ namespace Slang
// Load embedded precompiled libraries from IR into library artifacts
program->enumerateIRModules([&](IRModule* irModule)
{
- for (auto inst : irModule->getModuleInst()->getChildren())
+ for (auto globalInst : irModule->getModuleInst()->getChildren())
{
if (target == CodeGenTarget::DXILAssembly || target == CodeGenTarget::DXIL)
{
- if (inst->getOp() == kIROp_EmbeddedDXIL)
+ if (auto inst = as<IREmbeddedDownstreamIR>(globalInst))
{
- auto slice = static_cast<IRBlobLit*>(inst->getOperand(0))->getStringSlice();
- ArtifactDesc desc = ArtifactDescUtil::makeDescForCompileTarget(SLANG_DXIL);
- desc.kind = ArtifactKind::Library;
+ if (inst->getTarget() == CodeGenTarget::DXIL)
+ {
+ auto slice = inst->getBlob()->getStringSlice();
+ ArtifactDesc desc = ArtifactDescUtil::makeDescForCompileTarget(SLANG_DXIL);
+ desc.kind = ArtifactKind::Library;
- auto library = ArtifactUtil::createArtifact(desc);
+ auto library = ArtifactUtil::createArtifact(desc);
- library->addRepresentationUnknown(StringBlob::create(slice));
- libraries.add(library);
+ library->addRepresentationUnknown(StringBlob::create(slice));
+ libraries.add(library);
+ }
}
}
}
@@ -2030,7 +2030,7 @@ namespace Slang
{
if (auto artifact = targetProgram->getExistingWholeProgramResult())
{
- if (!targetProgram->getOptionSet().getBoolOption(CompilerOptionName::EmbedDXIL))
+ if (!targetProgram->getOptionSet().getBoolOption(CompilerOptionName::EmbedDownstreamIR))
{
artifacts.add(ComPtr<IArtifact>(artifact));
}
@@ -2285,6 +2285,9 @@ namespace Slang
auto linkage = getLinkage();
for (auto targetReq : linkage->targets)
{
+ if (targetReq->getOptionSet().getBoolOption(CompilerOptionName::EmbedDownstreamIR))
+ continue;
+
auto targetProgram = program->getTargetProgram(targetReq);
generateOutput(targetProgram);
}
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index 267fdeaf5..b8ee4dc9c 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -2733,13 +2733,13 @@ namespace Slang
SlangResult emitEntryPoints(ComPtr<IArtifact>& outArtifact);
- SlangResult emitPrecompiledDXIL(ComPtr<IArtifact>& outArtifact);
+ SlangResult emitPrecompiledDownstreamIR(ComPtr<IArtifact>& outArtifact);
void maybeDumpIntermediate(IArtifact* artifact);
- // Used to cause instructions available in precompiled DXIL to be
+ // Used to cause instructions available in precompiled blobs to be
// removed between IR linking and target source generation.
- bool removeAvailableInDXIL = false;
+ bool removeAvailableInDownstreamIR = false;
protected:
CodeGenTarget m_targetFormat = CodeGenTarget::Unknown;
@@ -2816,7 +2816,7 @@ namespace Slang
virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceGLSLScalarBufferLayout(int targetIndex, bool value) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceDXLayout(int targetIndex, bool value) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setTargetGenerateWholeProgram(int targetIndex, bool value) SLANG_OVERRIDE;
- virtual SLANG_NO_THROW void SLANG_MCALL setEmbedDXIL(bool value) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW void SLANG_MCALL setTargetEmbedDownstreamIR(int targetIndex, bool value) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setMatrixLayoutMode(SlangMatrixLayoutMode mode) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setDebugInfoLevel(SlangDebugInfoLevel level) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setOptimizationLevel(SlangOptimizationLevel level) SLANG_OVERRIDE;
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index 9088e959a..a2da4801e 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -3933,6 +3933,17 @@ struct SPIRVEmitContext
}
break;
}
+ case kIROp_DownstreamModuleExportDecoration:
+ {
+ requireSPIRVCapability(SpvCapabilityLinkage);
+ auto name = decoration->getParent()->findDecoration<IRExportDecoration>()->getMangledName();
+ emitInst(getSection(SpvLogicalSectionID::Annotations),
+ decoration,
+ SpvOpDecorate,
+ dstID,
+ SpvDecorationLinkageAttributes, name, SpvLinkageTypeExport);
+ break;
+ }
// ...
}
@@ -6847,12 +6858,27 @@ SlangResult emitSPIRVFromIR(
#endif
auto shouldPreserveParams = codeGenContext->getTargetProgram()->getOptionSet().getBoolOption(CompilerOptionName::PreserveParameters);
+ auto generateWholeProgram = codeGenContext->getTargetProgram()->getOptionSet().getBoolOption(CompilerOptionName::GenerateWholeProgram);
for (auto inst : irModule->getGlobalInsts())
{
if (as<IRDebugSource>(inst))
+ {
context.ensureInst(inst);
+ }
if (shouldPreserveParams && as<IRGlobalParam>(inst))
+ {
context.ensureInst(inst);
+ }
+ if (generateWholeProgram)
+ {
+ if (auto func = as<IRFunc>(inst))
+ {
+ if (func->findDecoration<IRDownstreamModuleExportDecoration>())
+ {
+ context.ensureInst(inst);
+ }
+ }
+ }
}
// Emit source language info.
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index caa8ca8ea..ed9e90462 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -416,31 +416,47 @@ bool checkStaticAssert(IRInst* inst, DiagnosticSink* sink)
return false;
}
-static void unexportNonEmbeddableDXIL(IRModule* irModule)
+static void unexportNonEmbeddableIR(CodeGenTarget target, IRModule* irModule)
{
for (auto inst : irModule->getGlobalInsts())
{
if (inst->getOp() == kIROp_Func)
{
- // DXIL does not permit HLSLStructureBufferType in exported functions
- // or sadly Matrices (https://github.com/shader-slang/slang/issues/4880)
- auto type = as<IRFuncType>(inst->getFullType());
- auto argCount = type->getOperandCount();
- for (UInt aa = 0; aa < argCount; ++aa)
+ bool remove = false;
+ if (target == CodeGenTarget::HLSL)
{
- auto operand = type->getOperand(aa);
- if (operand->getOp() == kIROp_HLSLStructuredBufferType ||
- operand->getOp() == kIROp_MatrixType)
+ // DXIL does not permit HLSLStructureBufferType in exported functions
+ // or sadly Matrices (https://github.com/shader-slang/slang/issues/4880)
+ auto type = as<IRFuncType>(inst->getFullType());
+ auto argCount = type->getOperandCount();
+ for (UInt aa = 0; aa < argCount; ++aa)
{
- if (auto dec = inst->findDecoration<IRPublicDecoration>())
+ auto operand = type->getOperand(aa);
+ if (operand->getOp() == kIROp_HLSLStructuredBufferType ||
+ operand->getOp() == kIROp_MatrixType)
{
- dec->removeAndDeallocate();
+ remove = true;
+ break;
}
- if (auto dec = inst->findDecoration<IRDownstreamModuleExportDecoration>())
- {
- dec->removeAndDeallocate();
- }
- break;
+ }
+ }
+ else if (target == CodeGenTarget::SPIRV)
+ {
+ // SPIR-V does not allow exporting entry points
+ if (inst->findDecoration<IREntryPointDecoration>())
+ {
+ remove = true;
+ }
+ }
+ if (remove)
+ {
+ if (auto dec = inst->findDecoration<IRPublicDecoration>())
+ {
+ dec->removeAndDeallocate();
+ }
+ if (auto dec = inst->findDecoration<IRDownstreamModuleExportDecoration>())
+ {
+ dec->removeAndDeallocate();
}
}
}
@@ -778,9 +794,9 @@ Result linkAndOptimizeIR(
break;
}
- if (codeGenContext->removeAvailableInDXIL)
+ if (codeGenContext->removeAvailableInDownstreamIR)
{
- removeAvailableInDownstreamModuleDecorations(irModule);
+ removeAvailableInDownstreamModuleDecorations(target, irModule);
}
if (targetProgram->getOptionSet().shouldRunNonEssentialValidation())
@@ -1490,11 +1506,9 @@ Result linkAndOptimizeIR(
auto metadata = new ArtifactPostEmitMetadata;
outLinkedIR.metadata = metadata;
- if (targetProgram->getOptionSet().getBoolOption(CompilerOptionName::EmbedDXIL))
+ if (targetProgram->getOptionSet().getBoolOption(CompilerOptionName::EmbedDownstreamIR))
{
- // We need to make sure that we don't try to export any functions that can't
- // be part of a DXIL library interface, eg. with resources.
- unexportNonEmbeddableDXIL(irModule);
+ unexportNonEmbeddableIR(target, irModule);
}
collectMetadata(irModule, *metadata);
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index 5afca48b3..afc09f480 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -806,7 +806,7 @@ INST_RANGE(BindingQuery, GetRegisterIndex, GetRegisterSpace)
INST(NumThreadsDecoration, numThreads, 3, 0)
INST(WaveSizeDecoration, waveSize, 1, 0)
- INST(AvailableInDXILDecoration, availableInDXIL, 0, 0)
+ INST(AvailableInDownstreamIRDecoration, availableInDownstreamIR, 1, 0)
// Added to IRParam parameters to an entry point
/* GeometryInputPrimitiveTypeDecoration */
@@ -1244,7 +1244,7 @@ INST(DebugVar, DebugVar, 4, 0)
INST(DebugValue, DebugValue, 2, 0)
/* Embedded Precompiled Libraries */
-INST(EmbeddedDXIL, EmbeddedDXIL, 1, 0)
+INST(EmbeddedDownstreamIR, EmbeddedDownstreamIR, 2, 0)
/* Inline assembly */
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index fc963697a..a0ed8ff0e 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -432,9 +432,14 @@ IR_SIMPLE_DECORATION(NonCopyableTypeDecoration)
IR_SIMPLE_DECORATION(HLSLMeshPayloadDecoration)
IR_SIMPLE_DECORATION(GlobalInputDecoration)
IR_SIMPLE_DECORATION(GlobalOutputDecoration)
-IR_SIMPLE_DECORATION(AvailableInDXILDecoration)
IR_SIMPLE_DECORATION(DownstreamModuleExportDecoration)
+struct IRAvailableInDownstreamIRDecoration : IRDecoration
+{
+ IR_LEAF_ISA(AvailableInDownstreamIRDecoration)
+ CodeGenTarget getTarget() { return static_cast<CodeGenTarget>(cast<IRIntLit>(getOperand(0))->getValue()); }
+};
+
struct IRGLSLLocationDecoration : IRDecoration
{
IR_LEAF_ISA(GLSLLocationDecoration)
@@ -3340,6 +3345,13 @@ struct IRStaticAssert : IRInst
IR_LEAF_ISA(StaticAssert)
};
+struct IREmbeddedDownstreamIR : IRInst
+{
+ IR_LEAF_ISA(EmbeddedDownstreamIR)
+ CodeGenTarget getTarget() { return static_cast<CodeGenTarget>(cast<IRIntLit>(getOperand(0))->getValue()); }
+ IRBlobLit* getBlob() { return cast<IRBlobLit>(getOperand(1)); }
+};
+
struct IRBuilderSourceLocRAII;
struct IRBuilder
@@ -4053,7 +4065,7 @@ public:
IRInst* emitByteAddressBufferStore(IRInst* byteAddressBuffer, IRInst* offset, IRInst* value);
IRInst* emitByteAddressBufferStore(IRInst* byteAddressBuffer, IRInst* offset, IRInst* alignment, IRInst* value);
- IRInst* emitEmbeddedDXIL(ISlangBlob* blob);
+ IRInst* emitEmbeddedDownstreamIR(CodeGenTarget target, ISlangBlob* blob);
IRFunc* createFunc();
IRGlobalVar* createGlobalVar(
diff --git a/source/slang/slang-ir-redundancy-removal.cpp b/source/slang/slang-ir-redundancy-removal.cpp
index 038412fbf..79b88ebcf 100644
--- a/source/slang/slang-ir-redundancy-removal.cpp
+++ b/source/slang/slang-ir-redundancy-removal.cpp
@@ -159,26 +159,29 @@ bool removeRedundancyInFunc(IRGlobalValueWithCode* func)
return result;
}
-// Remove IR definitions from all [AvailableInDXIL] functions when compiling DXIL,
-// as these functions are already defined in the embedded precompiled DXIL library.
-void removeAvailableInDownstreamModuleDecorations(IRModule* module)
+// Remove IR definitions from all AvailableInDownstreamIR functions where the
+// languages match what we're currently targetting, as these functions are
+// already defined in the embedded precompiled library.
+void removeAvailableInDownstreamModuleDecorations(CodeGenTarget target, IRModule* module)
{
List<IRInst*> toRemove;
for (auto globalInst : module->getGlobalInsts())
{
- auto funcInst = as<IRFunc>(globalInst);
- if (!funcInst)
+ if (auto funcInst = as<IRFunc>(globalInst))
{
- continue;
- }
- if (globalInst->findDecoration<IRAvailableInDXILDecoration>())
- {
- // Gut the function definition, turning it into a declaration
- for (auto inst : funcInst->getChildren())
+ if (auto dec = globalInst->findDecoration<IRAvailableInDownstreamIRDecoration>())
{
- if (inst->getOp() == kIROp_Block)
+ if ((dec->getTarget() == CodeGenTarget::DXIL && target == CodeGenTarget::HLSL) ||
+ (dec->getTarget() == target))
{
- toRemove.add(inst);
+ // Gut the function definition, turning it into a declaration
+ for (auto inst : funcInst->getChildren())
+ {
+ if (inst->getOp() == kIROp_Block)
+ {
+ toRemove.add(inst);
+ }
+ }
}
}
}
diff --git a/source/slang/slang-ir-redundancy-removal.h b/source/slang/slang-ir-redundancy-removal.h
index 117f52708..8b006c683 100644
--- a/source/slang/slang-ir-redundancy-removal.h
+++ b/source/slang/slang-ir-redundancy-removal.h
@@ -1,5 +1,6 @@
// slang-ir-redundancy-removal.h
#pragma once
+#include "slang-compiler.h"
namespace Slang
{
@@ -11,5 +12,5 @@ namespace Slang
bool eliminateRedundantLoadStore(IRGlobalValueWithCode* func);
- void removeAvailableInDownstreamModuleDecorations(IRModule* module);
+ void removeAvailableInDownstreamModuleDecorations(CodeGenTarget target, IRModule* module);
}
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index d02c01105..9305d1783 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -3863,11 +3863,11 @@ namespace Slang
return nullptr;
}
- IRInst* IRBuilder::emitEmbeddedDXIL(ISlangBlob *blob)
+ IRInst* IRBuilder::emitEmbeddedDownstreamIR(CodeGenTarget target, ISlangBlob *blob)
{
- IRInst* args[] = { getBlobValue(blob) };
+ IRInst* args[] = { getIntValue(getIntType(), (int)target), getBlobValue(blob) };
- return emitIntrinsicInst(getVoidType(), kIROp_EmbeddedDXIL, 1, args);
+ return emitIntrinsicInst(getVoidType(), kIROp_EmbeddedDownstreamIR, 2, args);
}
enum class TypeCastStyle
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index f12a66790..c02a00957 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -354,8 +354,6 @@ void initCommandOptions(CommandOptions& options)
{ OptionKind::DisableShortCircuit, "-disable-short-circuit", nullptr, "Disable short-circuiting for \"&&\" and \"||\" operations" },
{ OptionKind::UnscopedEnum, "-unscoped-enum", nullptr, "Treat enums types as unscoped by default."},
{ OptionKind::PreserveParameters, "-preserve-params", nullptr, "Preserve all resource parameters in the output code, even if they are not used by the shader."},
- { OptionKind::EmbedDXIL, "-embed-dxil", nullptr,
- "Embed DXIL into emitted slang-modules for faster linking" },
};
_addOptions(makeConstArrayView(generalOpts), options);
@@ -431,6 +429,7 @@ void initCommandOptions(CommandOptions& options)
"A path to a specific spirv.core.grammar.json to use when generating SPIR-V output" },
{ OptionKind::IncompleteLibrary, "-incomplete-library", nullptr,
"Allow generating code from incomplete libraries with unresolved external functions" },
+ { OptionKind::EmbedDownstreamIR, "-embed-downstream-ir", nullptr, "Embed downstream IR into emitted slang IR" },
};
_addOptions(makeConstArrayView(targetOpts), options);
@@ -1931,7 +1930,11 @@ SlangResult OptionsParser::_parse(
linkage->m_optionSet.set(optionKind, compressionType);
break;
}
- case OptionKind::EmbedDXIL: m_compileRequest->setEmbedDXIL(true); break;
+ case OptionKind::EmbedDownstreamIR:
+ {
+ getCurrentTarget()->optionSet.add(CompilerOptionName::EmbedDownstreamIR, true);
+ break;
+ }
case OptionKind::Target:
{
CommandLineArg name;
@@ -2778,6 +2781,12 @@ SlangResult OptionsParser::_parse(
{
m_compileRequest->setTargetGenerateWholeProgram(targetID, true);
}
+
+ if (rawTarget.optionSet.getBoolOption(CompilerOptionName::EmbedDownstreamIR))
+ {
+ m_compileRequest->setTargetEmbedDownstreamIR(targetID, true);
+ }
+
}
// Next we need to sort out the output files specified with `-o`, and
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index b0898b1a0..91ed3de5f 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -3305,18 +3305,21 @@ SlangResult EndToEndCompileRequest::executeActionsInner()
return SLANG_OK;
}
- // If requested, attempt to compile the translation unit all the way down to the target language
- // and stash the result blob in an IR op.
- if (getOptionSet().getBoolOption(CompilerOptionName::EmbedDXIL))
+ // If requested, attempt to compile the translation unit all the way down to the target language(s)
+ // and stash the result blobs in IR.
+ for (auto target : getLinkage()->targets)
{
- auto frontEndReq = getFrontEndReq();
-
- for (auto translationUnit : frontEndReq->translationUnits)
+ SlangCompileTarget targetEnum = SlangCompileTarget(target->getTarget());
+ if (target->getOptionSet().getBoolOption(CompilerOptionName::EmbedDownstreamIR))
{
- SlangCompileTarget target = SlangCompileTarget(SlangCompileTarget::SLANG_DXIL);
- SLANG_RETURN_ON_FAIL(translationUnit->getModule()->precompileForTarget(
- target,
- nullptr));
+ auto frontEndReq = getFrontEndReq();
+
+ for (auto translationUnit : frontEndReq->translationUnits)
+ {
+ SLANG_RETURN_ON_FAIL(translationUnit->getModule()->precompileForTarget(
+ targetEnum,
+ nullptr));
+ }
}
}
@@ -5939,9 +5942,9 @@ void EndToEndCompileRequest::setTargetGenerateWholeProgram(int targetIndex, bool
getTargetOptionSet(targetIndex).set(CompilerOptionName::GenerateWholeProgram, value);
}
-void EndToEndCompileRequest::setEmbedDXIL(bool value)
+void EndToEndCompileRequest::setTargetEmbedDownstreamIR(int targetIndex, bool value)
{
- getOptionSet().set(CompilerOptionName::EmbedDXIL, value);
+ getTargetOptionSet(targetIndex).set(CompilerOptionName::EmbedDownstreamIR, value);
}
void EndToEndCompileRequest::setTargetLineDirectiveMode(
diff --git a/tests/library/precompiled-dxil-generics.slang b/tests/library/precompiled-dxil-generics.slang
index f01291a8e..a0b371519 100644
--- a/tests/library/precompiled-dxil-generics.slang
+++ b/tests/library/precompiled-dxil-generics.slang
@@ -1,12 +1,12 @@
// precompiled-dxil-generics.slang
// A test that uses slang-modules with embedded precompiled DXIL and a library containing generics.
-// The test compiles a library slang (export-library-generics.slang) with -embed-dxil then links the
+// The test compiles a library slang (export-library-generics.slang) with -embed-downstream-ir then links the
// library to entrypoint slang (this file).
// The test passes if there is no errror thrown.
// TODO: Check if final linkage used only the precompiled dxil.
-//TEST(windows):COMPILE: tests/library/export-library-generics.slang -o tests/library/export-library-generics.slang-module -embed-dxil -profile lib_6_6 -incomplete-library
+//TEST(windows):COMPILE: tests/library/export-library-generics.slang -o tests/library/export-library-generics.slang-module -target dxil -embed-downstream-ir -profile lib_6_6 -incomplete-library
//TEST(windows):COMPILE: tests/library/precompiled-dxil-generics.slang -target dxil -stage anyhit -entry anyhit -o tests/library/linked.dxil
import "export-library-generics";
diff --git a/tests/library/precompiled-dxil-matrix.slang b/tests/library/precompiled-dxil-matrix.slang
index 271a7e214..469eea7c6 100644
--- a/tests/library/precompiled-dxil-matrix.slang
+++ b/tests/library/precompiled-dxil-matrix.slang
@@ -3,7 +3,7 @@
// This test imports a precompiled module that exports a matrix type, which is known to
// cause https://github.com/shader-slang/slang/issues/4880 without driver mitigation.
-//TEST(windows):COMPILE: tests/library/module-library-matrix.slang -o tests/library/module-library-matrix.slang-module -embed-dxil -profile lib_6_6 -incomplete-library
+//TEST(windows):COMPILE: tests/library/module-library-matrix.slang -o tests/library/module-library-matrix.slang-module -target dxil -embed-downstream-ir -profile lib_6_6 -incomplete-library
//TEST(windows):COMPILE: tests/library/precompiled-dxil-matrix.slang -stage anyhit -entry shadow -target dxil -o precompiled-dxil-matrix.dxil
import "module-library-matrix";
diff --git a/tests/library/precompiled-dxil.slang b/tests/library/precompiled-dxil.slang
index 8cc25bab5..877472394 100644
--- a/tests/library/precompiled-dxil.slang
+++ b/tests/library/precompiled-dxil.slang
@@ -1,13 +1,13 @@
// precompiled-dxil.slang
// A test that uses slang-modules with embedded precompiled DXIL.
-// The test compiles both library slang (export-library.slang) and entrypoint slang (this file) to two slang-modules, each with -embed-dxil options.
-// The result is two slang-modules that are then linked together in a third slangc invocation.
+// The test compiles both library slang (export-library.slang) to a slang-module using -embed-downstream-ir.
+// The result is linked together with this module (precompiled-dxil.slang) in a second slangc invocation.
// Internally, slang does not use the IR in the modules to link, but rather their embedded DXIL.
// The test passes if there is no errror thrown.
// TODO: Check if final linkage used only the precompiled dxil.
-//TEST(windows):COMPILE: tests/library/export-library.slang -o tests/library/export-library.slang-module -embed-dxil -profile lib_6_6 -incomplete-library
+//TEST(windows):COMPILE: tests/library/export-library.slang -o tests/library/export-library.slang-module -target dxil -embed-downstream-ir -profile lib_6_6 -incomplete-library
//TEST(windows):COMPILE: tests/library/precompiled-dxil.slang tests/library/export-library.slang-module -target dxil -entry computeMain -profile cs_6_6 -o tests/library/linked.dxil
extern int foo(int a);
diff --git a/tests/library/precompiled-module-library-resource.slang b/tests/library/precompiled-module-library-resource.slang
index 3eeab39d8..35b83b72f 100644
--- a/tests/library/precompiled-module-library-resource.slang
+++ b/tests/library/precompiled-module-library-resource.slang
@@ -1,9 +1,11 @@
// precompiled-module-library-resource.slang
-// Compile this library source with -embed-dxil option. Tests that modules can be
-// precompiled to dxil despite having resource parameters or return types.
+// Compile this library source with embedded DXIL and SPIRV options.
+// Tests that modules can be precompiled to downstream IR despite having resource
+// parameters or return types.
-//TEST(windows):COMPILE: tests/library/precompiled-module-library-resource.slang -o tests/library/precompiled-module-library-resource.slang-module -embed-dxil -profile lib_6_6 -incomplete-library
+//TEST(windows):COMPILE: tests/library/precompiled-module-library-resource.slang -o tests/library/precompiled-module-library-resource-dxil.slang-module -target dxil -embed-downstream-ir -profile lib_6_6 -incomplete-library
+//TEST:COMPILE: tests/library/precompiled-module-library-resource.slang -o tests/library/precompiled-module-library-resource-spv.slang-module -target spirv -embed-downstream-ir -incomplete-library
module "precompiled-module-library-resource";
@@ -26,13 +28,13 @@ public int resource_in_struct_parameter(ResourceStruct rs)
return rs.buffer[0];
}
-internal int matrix_in_parameter_internal(int1x1 matrix)
+internal float matrix_in_parameter_internal(float2x2 matrix)
{
return matrix[0][0];
}
-public int matrix_in_parameter_public(int a)
+public float matrix_in_parameter_public(float a)
{
- int1x1 matrix = {a};
+ float2x2 matrix = {a, .2, .3, .4};
return matrix_in_parameter_internal(matrix);
}
diff --git a/tests/library/precompiled-spirv-generics.slang b/tests/library/precompiled-spirv-generics.slang
new file mode 100644
index 000000000..a55f58513
--- /dev/null
+++ b/tests/library/precompiled-spirv-generics.slang
@@ -0,0 +1,28 @@
+// precompiled-spirv-generics.slang
+
+// A test that uses slang-modules with embedded precompiled SPIRV and a library containing generics.
+// The test compiles a library slang (export-library-generics.slang) with -embed-downstream-ir then links the
+// library to entrypoint slang (this file).
+// The test passes if there is no errror thrown.
+// TODO: Check if final linkage used only the precompiled spirv.
+
+//TEST:COMPILE: tests/library/export-library-generics.slang -o tests/library/export-library-generics.slang-module -target spirv -embed-downstream-ir -profile lib_6_6 -incomplete-library
+//TEST:COMPILE: tests/library/precompiled-spirv-generics.slang -target spirv -stage anyhit -entry anyhit -o tests/library/linked.spirv
+
+import "export-library-generics";
+
+struct Payload
+{
+ int val;
+}
+
+struct Attributes
+{
+ float2 bary;
+}
+
+[shader("anyhit")]
+void anyhit(inout Payload payload, Attributes attrib)
+{
+ payload.val = normalFunc(x * y) + normalFuncUsesGeneric(y);
+}
diff --git a/tools/gfx-unit-test/precompiled-module-2.cpp b/tools/gfx-unit-test/precompiled-module-2.cpp
index 93b9d1b89..e8ceb6f45 100644
--- a/tools/gfx-unit-test/precompiled-module-2.cpp
+++ b/tools/gfx-unit-test/precompiled-module-2.cpp
@@ -43,6 +43,9 @@ namespace gfx_test
case gfx::DeviceType::DirectX12:
target = SLANG_DXIL;
break;
+ case gfx::DeviceType::Vulkan:
+ target = SLANG_SPIRV;
+ break;
default:
return SLANG_FAIL;
}
@@ -208,4 +211,9 @@ namespace gfx_test
runTestImpl(precompiledModule2TestImpl, unitTestContext, Slang::RenderApiFlag::Vulkan);
}
+ SLANG_UNIT_TEST(precompiledTargetModule2Vulkan)
+ {
+ runTestImpl(precompiledTargetModule2TestImpl, unitTestContext, Slang::RenderApiFlag::Vulkan);
+ }
+
}