Skip to content

Commit 3136771

Browse files
cheneym2csyonghe
andauthored
Initial -embed-spirv support (shader-slang#4974)
* Initial -embed-spirv support Add support for SPIR-V precompilation using the framework established for DXIL. Work on shader-slang#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>
1 parent 33e8bfd commit 3136771

19 files changed

+214
-109
lines changed

include/slang.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -956,8 +956,7 @@ extern "C"
956956
GenerateWholeProgram, // bool
957957
UseUpToDateBinaryModule, // bool, when set, will only load
958958
// precompiled modules if it is up-to-date with its source.
959-
960-
EmbedDXIL, // bool
959+
EmbedDownstreamIR, // bool
961960
ForceDXLayout, // bool
962961
CountOf,
963962
};
@@ -4929,9 +4928,9 @@ namespace slang
49294928
int targetIndex,
49304929
bool value) = 0;
49314930

4932-
virtual SLANG_NO_THROW void SLANG_MCALL setEmbedDXIL(bool value) = 0;
4933-
49344931
virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceDXLayout(int targetIndex, bool value) = 0;
4932+
4933+
virtual SLANG_NO_THROW void SLANG_MCALL setTargetEmbedDownstreamIR(int targetIndex, bool value) = 0;
49354934
};
49364935

49374936
#define SLANG_UUID_ICompileRequest ICompileRequest::getTypeGuid()

source/slang/slang-compiler-tu.cpp

+13-16
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ namespace Slang
5454
* Precompile the module for the given target.
5555
*
5656
* This function creates a target program and emits the precompiled blob as
57-
* an embedded blob in the module IR, e.g. DXIL.
57+
* an embedded blob in the module IR, e.g. DXIL, SPIR-V.
5858
* Because the IR for the Slang Module may violate the restrictions of the
5959
* target language, the emitted target blob may not be able to include the
6060
* full module, but rather only the subset that can be precompiled. For
@@ -77,7 +77,7 @@ namespace Slang
7777
* in the linked IR which survived the additional pruning.
7878
*
7979
* Functions that are rejected after linking+legalization (inside
80-
* emitPrecompiled*):
80+
* emitPrecompiledDownstreamIR):
8181
* - (DXIL) Functions that return or take a HLSLStructuredBufferType
8282
* - (DXIL) Functions that return or take a Matrix type
8383
*
@@ -86,17 +86,13 @@ namespace Slang
8686
* phase of filtering.
8787
*
8888
* The original module IR functions matching those are then marked with
89-
* "AvailableIn*" (e.g. AvailableInDXILDecoration) to indicate to future
89+
* "AvailableInDownstreamIRDecoration" to indicate to future
9090
* module users which functions are present in the precompiled blob.
9191
*/
9292
SLANG_NO_THROW SlangResult SLANG_MCALL Module::precompileForTarget(
9393
SlangCompileTarget target,
9494
slang::IBlob** outDiagnostics)
9595
{
96-
if (target != SLANG_DXIL)
97-
{
98-
return SLANG_FAIL;
99-
}
10096
CodeGenTarget targetEnum = CodeGenTarget(target);
10197

10298
auto module = getIRModule();
@@ -130,10 +126,15 @@ namespace Slang
130126
{
131127
case CodeGenTarget::DXIL:
132128
tp.getOptionSet().add(CompilerOptionName::Profile, Profile::RawEnum::DX_Lib_6_6);
133-
tp.getOptionSet().add(CompilerOptionName::EmbedDXIL, true);
134129
break;
130+
case CodeGenTarget::SPIRV:
131+
break;
132+
default:
133+
return SLANG_FAIL;
135134
}
136135

136+
tp.getOptionSet().add(CompilerOptionName::EmbedDownstreamIR, true);
137+
137138
CodeGenContext::EntryPointIndices entryPointIndices;
138139

139140
entryPointIndices.setCount(entryPointCount);
@@ -166,7 +167,7 @@ namespace Slang
166167
}
167168

168169
ComPtr<IArtifact> outArtifact;
169-
SlangResult res = codeGenContext.emitPrecompiledDXIL(outArtifact);
170+
SlangResult res = codeGenContext.emitPrecompiledDownstreamIR(outArtifact);
170171

171172
sink.getBlobIfNeeded(outDiagnostics);
172173
if (res != SLANG_OK)
@@ -183,7 +184,8 @@ namespace Slang
183184
for (const auto& mangledName : metadata->getExportedFunctionMangledNames())
184185
{
185186
auto moduleInst = nameToFunction[mangledName];
186-
builder.addDecoration(moduleInst, kIROp_AvailableInDXILDecoration);
187+
builder.addDecoration(moduleInst, kIROp_AvailableInDownstreamIRDecoration,
188+
builder.getIntValue(builder.getIntType(), (int)targetReq->getTarget()));
187189
auto moduleDec = moduleInst->findDecoration<IRDownstreamModuleExportDecoration>();
188190
moduleDec->removeAndDeallocate();
189191
}
@@ -207,12 +209,7 @@ namespace Slang
207209
// Add the precompiled blob to the module
208210
builder.setInsertInto(module);
209211

210-
switch (targetReq->getTarget())
211-
{
212-
case CodeGenTarget::DXIL:
213-
builder.emitEmbeddedDXIL(blob);
214-
break;
215-
}
212+
builder.emitEmbeddedDownstreamIR(targetReq->getTarget(), blob);
216213

217214
return SLANG_OK;
218215
}

source/slang/slang-compiler.cpp

+18-15
Original file line numberDiff line numberDiff line change
@@ -767,9 +767,9 @@ namespace Slang
767767
# pragma warning(pop)
768768
#endif
769769

770-
SlangResult CodeGenContext::emitPrecompiledDXIL(ComPtr<IArtifact>& outArtifact)
770+
SlangResult CodeGenContext::emitPrecompiledDownstreamIR(ComPtr<IArtifact>& outArtifact)
771771
{
772-
return emitWithDownstreamForEntryPoints(outArtifact);
772+
return _emitEntryPoints(outArtifact);
773773
}
774774

775775
String GetHLSLProfileName(Profile profile)
@@ -1257,10 +1257,7 @@ namespace Slang
12571257
{
12581258
CodeGenContext sourceCodeGenContext(this, sourceTarget, extensionTracker);
12591259

1260-
if (target == CodeGenTarget::DXILAssembly || target == CodeGenTarget::DXIL)
1261-
{
1262-
sourceCodeGenContext.removeAvailableInDXIL = true;
1263-
}
1260+
sourceCodeGenContext.removeAvailableInDownstreamIR = true;
12641261

12651262
SLANG_RETURN_ON_FAIL(sourceCodeGenContext.emitEntryPointsSource(sourceArtifact));
12661263
sourceCodeGenContext.maybeDumpIntermediate(sourceArtifact);
@@ -1561,20 +1558,23 @@ namespace Slang
15611558
// Load embedded precompiled libraries from IR into library artifacts
15621559
program->enumerateIRModules([&](IRModule* irModule)
15631560
{
1564-
for (auto inst : irModule->getModuleInst()->getChildren())
1561+
for (auto globalInst : irModule->getModuleInst()->getChildren())
15651562
{
15661563
if (target == CodeGenTarget::DXILAssembly || target == CodeGenTarget::DXIL)
15671564
{
1568-
if (inst->getOp() == kIROp_EmbeddedDXIL)
1565+
if (auto inst = as<IREmbeddedDownstreamIR>(globalInst))
15691566
{
1570-
auto slice = static_cast<IRBlobLit*>(inst->getOperand(0))->getStringSlice();
1571-
ArtifactDesc desc = ArtifactDescUtil::makeDescForCompileTarget(SLANG_DXIL);
1572-
desc.kind = ArtifactKind::Library;
1567+
if (inst->getTarget() == CodeGenTarget::DXIL)
1568+
{
1569+
auto slice = inst->getBlob()->getStringSlice();
1570+
ArtifactDesc desc = ArtifactDescUtil::makeDescForCompileTarget(SLANG_DXIL);
1571+
desc.kind = ArtifactKind::Library;
15731572

1574-
auto library = ArtifactUtil::createArtifact(desc);
1573+
auto library = ArtifactUtil::createArtifact(desc);
15751574

1576-
library->addRepresentationUnknown(StringBlob::create(slice));
1577-
libraries.add(library);
1575+
library->addRepresentationUnknown(StringBlob::create(slice));
1576+
libraries.add(library);
1577+
}
15781578
}
15791579
}
15801580
}
@@ -2030,7 +2030,7 @@ namespace Slang
20302030
{
20312031
if (auto artifact = targetProgram->getExistingWholeProgramResult())
20322032
{
2033-
if (!targetProgram->getOptionSet().getBoolOption(CompilerOptionName::EmbedDXIL))
2033+
if (!targetProgram->getOptionSet().getBoolOption(CompilerOptionName::EmbedDownstreamIR))
20342034
{
20352035
artifacts.add(ComPtr<IArtifact>(artifact));
20362036
}
@@ -2285,6 +2285,9 @@ namespace Slang
22852285
auto linkage = getLinkage();
22862286
for (auto targetReq : linkage->targets)
22872287
{
2288+
if (targetReq->getOptionSet().getBoolOption(CompilerOptionName::EmbedDownstreamIR))
2289+
continue;
2290+
22882291
auto targetProgram = program->getTargetProgram(targetReq);
22892292
generateOutput(targetProgram);
22902293
}

source/slang/slang-compiler.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -2733,13 +2733,13 @@ namespace Slang
27332733

27342734
SlangResult emitEntryPoints(ComPtr<IArtifact>& outArtifact);
27352735

2736-
SlangResult emitPrecompiledDXIL(ComPtr<IArtifact>& outArtifact);
2736+
SlangResult emitPrecompiledDownstreamIR(ComPtr<IArtifact>& outArtifact);
27372737

27382738
void maybeDumpIntermediate(IArtifact* artifact);
27392739

2740-
// Used to cause instructions available in precompiled DXIL to be
2740+
// Used to cause instructions available in precompiled blobs to be
27412741
// removed between IR linking and target source generation.
2742-
bool removeAvailableInDXIL = false;
2742+
bool removeAvailableInDownstreamIR = false;
27432743

27442744
protected:
27452745
CodeGenTarget m_targetFormat = CodeGenTarget::Unknown;
@@ -2816,7 +2816,7 @@ namespace Slang
28162816
virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceGLSLScalarBufferLayout(int targetIndex, bool value) SLANG_OVERRIDE;
28172817
virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceDXLayout(int targetIndex, bool value) SLANG_OVERRIDE;
28182818
virtual SLANG_NO_THROW void SLANG_MCALL setTargetGenerateWholeProgram(int targetIndex, bool value) SLANG_OVERRIDE;
2819-
virtual SLANG_NO_THROW void SLANG_MCALL setEmbedDXIL(bool value) SLANG_OVERRIDE;
2819+
virtual SLANG_NO_THROW void SLANG_MCALL setTargetEmbedDownstreamIR(int targetIndex, bool value) SLANG_OVERRIDE;
28202820
virtual SLANG_NO_THROW void SLANG_MCALL setMatrixLayoutMode(SlangMatrixLayoutMode mode) SLANG_OVERRIDE;
28212821
virtual SLANG_NO_THROW void SLANG_MCALL setDebugInfoLevel(SlangDebugInfoLevel level) SLANG_OVERRIDE;
28222822
virtual SLANG_NO_THROW void SLANG_MCALL setOptimizationLevel(SlangOptimizationLevel level) SLANG_OVERRIDE;

source/slang/slang-emit-spirv.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -3933,6 +3933,17 @@ struct SPIRVEmitContext
39333933
}
39343934
break;
39353935
}
3936+
case kIROp_DownstreamModuleExportDecoration:
3937+
{
3938+
requireSPIRVCapability(SpvCapabilityLinkage);
3939+
auto name = decoration->getParent()->findDecoration<IRExportDecoration>()->getMangledName();
3940+
emitInst(getSection(SpvLogicalSectionID::Annotations),
3941+
decoration,
3942+
SpvOpDecorate,
3943+
dstID,
3944+
SpvDecorationLinkageAttributes, name, SpvLinkageTypeExport);
3945+
break;
3946+
}
39363947
// ...
39373948
}
39383949

@@ -6847,12 +6858,27 @@ SlangResult emitSPIRVFromIR(
68476858
#endif
68486859

68496860
auto shouldPreserveParams = codeGenContext->getTargetProgram()->getOptionSet().getBoolOption(CompilerOptionName::PreserveParameters);
6861+
auto generateWholeProgram = codeGenContext->getTargetProgram()->getOptionSet().getBoolOption(CompilerOptionName::GenerateWholeProgram);
68506862
for (auto inst : irModule->getGlobalInsts())
68516863
{
68526864
if (as<IRDebugSource>(inst))
6865+
{
68536866
context.ensureInst(inst);
6867+
}
68546868
if (shouldPreserveParams && as<IRGlobalParam>(inst))
6869+
{
68556870
context.ensureInst(inst);
6871+
}
6872+
if (generateWholeProgram)
6873+
{
6874+
if (auto func = as<IRFunc>(inst))
6875+
{
6876+
if (func->findDecoration<IRDownstreamModuleExportDecoration>())
6877+
{
6878+
context.ensureInst(inst);
6879+
}
6880+
}
6881+
}
68566882
}
68576883

68586884
// Emit source language info.

source/slang/slang-emit.cpp

+36-22
Original file line numberDiff line numberDiff line change
@@ -416,31 +416,47 @@ bool checkStaticAssert(IRInst* inst, DiagnosticSink* sink)
416416
return false;
417417
}
418418

419-
static void unexportNonEmbeddableDXIL(IRModule* irModule)
419+
static void unexportNonEmbeddableIR(CodeGenTarget target, IRModule* irModule)
420420
{
421421
for (auto inst : irModule->getGlobalInsts())
422422
{
423423
if (inst->getOp() == kIROp_Func)
424424
{
425-
// DXIL does not permit HLSLStructureBufferType in exported functions
426-
// or sadly Matrices (https://github.com/shader-slang/slang/issues/4880)
427-
auto type = as<IRFuncType>(inst->getFullType());
428-
auto argCount = type->getOperandCount();
429-
for (UInt aa = 0; aa < argCount; ++aa)
425+
bool remove = false;
426+
if (target == CodeGenTarget::HLSL)
430427
{
431-
auto operand = type->getOperand(aa);
432-
if (operand->getOp() == kIROp_HLSLStructuredBufferType ||
433-
operand->getOp() == kIROp_MatrixType)
428+
// DXIL does not permit HLSLStructureBufferType in exported functions
429+
// or sadly Matrices (https://github.com/shader-slang/slang/issues/4880)
430+
auto type = as<IRFuncType>(inst->getFullType());
431+
auto argCount = type->getOperandCount();
432+
for (UInt aa = 0; aa < argCount; ++aa)
434433
{
435-
if (auto dec = inst->findDecoration<IRPublicDecoration>())
434+
auto operand = type->getOperand(aa);
435+
if (operand->getOp() == kIROp_HLSLStructuredBufferType ||
436+
operand->getOp() == kIROp_MatrixType)
436437
{
437-
dec->removeAndDeallocate();
438+
remove = true;
439+
break;
438440
}
439-
if (auto dec = inst->findDecoration<IRDownstreamModuleExportDecoration>())
440-
{
441-
dec->removeAndDeallocate();
442-
}
443-
break;
441+
}
442+
}
443+
else if (target == CodeGenTarget::SPIRV)
444+
{
445+
// SPIR-V does not allow exporting entry points
446+
if (inst->findDecoration<IREntryPointDecoration>())
447+
{
448+
remove = true;
449+
}
450+
}
451+
if (remove)
452+
{
453+
if (auto dec = inst->findDecoration<IRPublicDecoration>())
454+
{
455+
dec->removeAndDeallocate();
456+
}
457+
if (auto dec = inst->findDecoration<IRDownstreamModuleExportDecoration>())
458+
{
459+
dec->removeAndDeallocate();
444460
}
445461
}
446462
}
@@ -778,9 +794,9 @@ Result linkAndOptimizeIR(
778794
break;
779795
}
780796

781-
if (codeGenContext->removeAvailableInDXIL)
797+
if (codeGenContext->removeAvailableInDownstreamIR)
782798
{
783-
removeAvailableInDownstreamModuleDecorations(irModule);
799+
removeAvailableInDownstreamModuleDecorations(target, irModule);
784800
}
785801

786802
if (targetProgram->getOptionSet().shouldRunNonEssentialValidation())
@@ -1490,11 +1506,9 @@ Result linkAndOptimizeIR(
14901506
auto metadata = new ArtifactPostEmitMetadata;
14911507
outLinkedIR.metadata = metadata;
14921508

1493-
if (targetProgram->getOptionSet().getBoolOption(CompilerOptionName::EmbedDXIL))
1509+
if (targetProgram->getOptionSet().getBoolOption(CompilerOptionName::EmbedDownstreamIR))
14941510
{
1495-
// We need to make sure that we don't try to export any functions that can't
1496-
// be part of a DXIL library interface, eg. with resources.
1497-
unexportNonEmbeddableDXIL(irModule);
1511+
unexportNonEmbeddableIR(target, irModule);
14981512
}
14991513

15001514
collectMetadata(irModule, *metadata);

source/slang/slang-ir-inst-defs.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ INST_RANGE(BindingQuery, GetRegisterIndex, GetRegisterSpace)
806806
INST(NumThreadsDecoration, numThreads, 3, 0)
807807
INST(WaveSizeDecoration, waveSize, 1, 0)
808808

809-
INST(AvailableInDXILDecoration, availableInDXIL, 0, 0)
809+
INST(AvailableInDownstreamIRDecoration, availableInDownstreamIR, 1, 0)
810810

811811
// Added to IRParam parameters to an entry point
812812
/* GeometryInputPrimitiveTypeDecoration */
@@ -1244,7 +1244,7 @@ INST(DebugVar, DebugVar, 4, 0)
12441244
INST(DebugValue, DebugValue, 2, 0)
12451245

12461246
/* Embedded Precompiled Libraries */
1247-
INST(EmbeddedDXIL, EmbeddedDXIL, 1, 0)
1247+
INST(EmbeddedDownstreamIR, EmbeddedDownstreamIR, 2, 0)
12481248

12491249
/* Inline assembly */
12501250

0 commit comments

Comments
 (0)