summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-04-21 13:47:18 -0400
committerGitHub <noreply@github.com>2022-04-21 13:47:18 -0400
commit3638e7735be67c8f4dae3f4544134441aa1e029d (patch)
treef59c6965321ddcc5991df2bab3ea507b3ce50292 /source
parent34f8b5e722aede018e275324c43055cad9a9ca5a (diff)
`export` support in HLSL (#2188)
* #include an absolute path didn't work - because paths were taken to always be relative. * Compile to a dxil library. * Added CompileProduct. * Support handling of ModuleLibrary. * CacheBehavior -> Cache * Use CompileProduct for -r references. * CompileProduct -> Artifact. * Determining an artifact type on binding. * Determine binary linkability. * Added Artifact::exists. * Added ArtifactKeep. * Small fixes. * Small improvements to Artifact. * Add zip extension. * Fix some comments. * Fix multiple adding of PublicDecoration. Make public output export for DXIL/lib. Add checking for simpleDecorations such that only added once. * Use 'whole program' to identify library build. * Add -target dxil so test infrastructure knows it needs DXC.
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-artifact.cpp11
-rw-r--r--source/slang/slang-compiler.cpp28
-rw-r--r--source/slang/slang-diagnostic-defs.h3
-rw-r--r--source/slang/slang-emit-hlsl.cpp22
-rw-r--r--source/slang/slang-ir-insts.h4
-rw-r--r--source/slang/slang-ir.cpp40
-rw-r--r--source/slang/slang-lower-to-ir.cpp7
7 files changed, 105 insertions, 10 deletions
diff --git a/source/slang/slang-artifact.cpp b/source/slang/slang-artifact.cpp
index 612c2365d..770f2202a 100644
--- a/source/slang/slang-artifact.cpp
+++ b/source/slang/slang-artifact.cpp
@@ -148,6 +148,13 @@ static const KindExtension g_cpuKindExts[] =
{
switch (payload)
{
+ case Payload::DXBC:
+ {
+ // It seems as if DXBC is potentially linkable from
+ // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-appendix-keywords#export
+ return true;
+ }
+
case Payload::DXIL:
case Payload::PTX:
case Payload::SPIRV:
@@ -397,16 +404,18 @@ SlangResult Artifact::requireFilePath(Keep keep, String& outFilePath)
auto parentDir = Path::getParentDirectory(path);
if (parentDir.getLength())
{
- // Prefix the lib
+ // Combine the name with path if their is a parent
path = Path::combine(parentDir, buf);
}
else
{
+ // Just use the name as is
path = buf;
}
}
}
+ // If there is an extension append it
if (ext.getLength())
{
path.appendChar('.');
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index 80899e69e..881194bcb 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -1203,11 +1203,26 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
auto targetReq = getTargetReq();
const auto entryPointIndicesCount = entryPointIndices.getCount();
-
- if (entryPointIndicesCount == 0 && compilerType == PassThroughMode::Dxc)
+
+ // Whole program means
+ // * can have 0-N entry points
+ // * 'doesn't build into an executable/kernel'
+ //
+ // So in some sense it is a library
+ if (targetReq->isWholeProgramRequest())
{
- // Can support no entry points on DXC because we can build libraries
- profile = targetReq->getTargetProfile();
+ if (compilerType == PassThroughMode::Dxc)
+ {
+ // Can support no entry points on DXC because we can build libraries
+ profile = targetReq->getTargetProfile();
+ }
+ else
+ {
+ auto downstreamCompilerName = TypeTextUtil::getPassThroughName((SlangPassThrough)compilerType);
+
+ sink->diagnose(SourceLoc(), Diagnostics::downstreamCompilerDoesntSupportWholeProgramCompilation, downstreamCompilerName);
+ return SLANG_FAIL;
+ }
}
else if (entryPointIndicesCount == 1)
{
@@ -1909,11 +1924,12 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
// The current logic of `emitEntryPoints` takes a list of entry-point indices to
// emit code for, so we construct such a list first.
List<Int> entryPointIndices;
+
m_entryPointResults.setCount(m_program->getEntryPointCount());
entryPointIndices.setCount(m_program->getEntryPointCount());
for (Index i = 0; i < entryPointIndices.getCount(); i++)
entryPointIndices[i] = i;
-
+
auto& result = m_wholeProgramResult;
CodeGenContext::Shared sharedCodeGenContext(this, entryPointIndices, sink, endToEndReq);
@@ -1929,7 +1945,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
DiagnosticSink* sink,
EndToEndCompileRequest* endToEndReq)
{
- // It is possible that entry points goot added to the `Program`
+ // It is possible that entry points got added to the `Program`
// *after* we created this `TargetProgram`, so there might be
// a request for an entry point that we didn't allocate space for.
//
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 6500bd1a0..e23d88fa4 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -135,6 +135,9 @@ DIAGNOSTIC( 97, Error, libraryDoesNotExist, "library '$0' does not exist")
//
DIAGNOSTIC( 100, Error, failedToLoadDownstreamCompiler, "failed to load downstream compiler '$0'")
+DIAGNOSTIC( 101, Error, downstreamCompilerDoesntSupportWholeProgramCompilation, "downstream compiler '$0' doesn't support whole program compilation")
+
+
DIAGNOSTIC(99999, Note, noteFailedToLoadDynamicLibrary, "failed to load dynamic library '$0'")
//
diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp
index 09749546a..059a3f641 100644
--- a/source/slang/slang-emit-hlsl.cpp
+++ b/source/slang/slang-emit-hlsl.cpp
@@ -731,6 +731,28 @@ void HLSLSourceEmitter::emitFuncDecorationImpl(IRDecoration* decoration)
{
switch( decoration->getOp() )
{
+ case kIROp_PublicDecoration:
+ {
+ auto profile = m_effectiveProfile;
+
+ const auto family = profile.getFamily();
+ const auto stage = profile.getStage();
+ const auto version = profile.getVersion();
+
+ // I would perhaps ideally know that this was being compiled for 'library' stage.
+ // Stage::Unknown is currently also used for lib profiles.
+
+ // TODO(JS): Potentially can do export for fxc too, but for now we don't add.
+
+ if (family == ProfileFamily::DX &&
+ version >= ProfileVersion::DX_6_1 &&
+ stage == Stage::Unknown)
+ {
+ m_writer->emit("export\n");
+ }
+ break;
+ }
+
case kIROp_NoInlineDecoration:
m_writer->emit("[noinline]\n");
break;
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index e4318177f..717e1be59 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -196,6 +196,8 @@ struct IRTypeConstraintDecoration : IRDecoration
}; \
/**/
+bool isSimpleDecoration(IROp op);
+
/// A decoration that indicates that a variable represents
/// a vulkan ray payload, and should have a location assigned
/// to it.
@@ -2833,7 +2835,7 @@ public:
void addPublicDecoration(IRInst* value)
{
- addDecoration(value, kIROp_PublicDecoration);
+ addDecoration(value, kIROp_PublicDecoration);
}
void addNVAPIMagicDecoration(IRInst* value, UnownedStringSlice const& name)
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index 09a28e394..b53c247c3 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -23,8 +23,36 @@ namespace Slang
sb << nameHint->getName();
}
- // !!!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticSink Impls !!!!!!!!!!!!!!!!!!!!!
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+ bool isSimpleDecoration(IROp op)
+ {
+ switch (op)
+ {
+ case kIROp_EarlyDepthStencilDecoration: return true;
+ case kIROp_GloballyCoherentDecoration: return true;
+ case kIROp_KeepAliveDecoration: return true;
+ case kIROp_LineAdjInputPrimitiveTypeDecoration: return true;
+ case kIROp_LineInputPrimitiveTypeDecoration: return true;
+ case kIROp_NoInlineDecoration: return true;
+ case kIROp_PointInputPrimitiveTypeDecoration: return true;
+ case kIROp_PreciseDecoration: return true;
+ case kIROp_PublicDecoration: return true;
+ case kIROp_ReadNoneDecoration: return true;
+ case kIROp_RequiresNVAPIDecoration: return true;
+ case kIROp_TriangleAdjInputPrimitiveTypeDecoration: return true;
+ case kIROp_TriangleInputPrimitiveTypeDecoration: return true;
+ case kIROp_UnsafeForceInlineEarlyDecoration: return true;
+ case kIROp_VulkanCallablePayloadDecoration: return true;
+ case kIROp_VulkanHitAttributesDecoration: return true;
+ case kIROp_VulkanRayPayloadDecoration: return true;
+ default: break;
+ }
+ return false;
+ }
+
IRInst* cloneGlobalValueWithLinkage(
IRSpecContext* context,
IRInst* originalVal,
@@ -4172,6 +4200,16 @@ namespace Slang
IRDecoration* IRBuilder::addDecoration(IRInst* value, IROp op, IRInst* const* operands, Int operandCount)
{
+ // If it's a simple (ie stateless) decoration, don't add it again.
+ if (operandCount == 0 && isSimpleDecoration(op))
+ {
+ auto decoration = value->findDecorationImpl(op);
+ if (decoration)
+ {
+ return decoration;
+ }
+ }
+
auto decoration = createInstWithTrailingArgs<IRDecoration>(
this,
op,
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 842a1ce5f..7a99faa58 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -7424,9 +7424,14 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
getBuilder()->addSimpleDecoration<IRNoInlineDecoration>(irFunc);
}
- if (decl->findModifier<PublicModifier>()) {
+#if 0
+ // Not needed as added as part of adding linkage decoration.
+ // Ie in call to addLinkageDecoration
+ if (decl->findModifier<PublicModifier>())
+ {
getBuilder()->addSimpleDecoration<IRPublicDecoration>(irFunc);
}
+#endif
if (auto attr = decl->findModifier<InstanceAttribute>())
{