diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2022-04-21 13:47:18 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-04-21 13:47:18 -0400 |
| commit | 3638e7735be67c8f4dae3f4544134441aa1e029d (patch) | |
| tree | f59c6965321ddcc5991df2bab3ea507b3ce50292 /source | |
| parent | 34f8b5e722aede018e275324c43055cad9a9ca5a (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.cpp | 11 | ||||
| -rw-r--r-- | source/slang/slang-compiler.cpp | 28 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 3 | ||||
| -rw-r--r-- | source/slang/slang-emit-hlsl.cpp | 22 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 4 | ||||
| -rw-r--r-- | source/slang/slang-ir.cpp | 40 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 7 |
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>()) { |
