diff options
| -rw-r--r-- | examples/heterogeneous-hello-world/shader.slang | 3 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.cpp | 8 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-emit-c-like.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 8 | ||||
| -rw-r--r-- | source/slang/slang-emit.cpp | 33 | ||||
| -rw-r--r-- | source/slang/slang-emit.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir-glsl-legalize.cpp | 13 | ||||
| -rw-r--r-- | source/slang/slang-ir-glsl-legalize.h | 5 | ||||
| -rw-r--r-- | source/slang/slang-ir-link.cpp | 16 | ||||
| -rw-r--r-- | source/slang/slang-ir-link.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-options.cpp | 68 | ||||
| -rw-r--r-- | tests/diagnostics/command-line/unknown-output-format.slang.expected | 1 |
13 files changed, 96 insertions, 66 deletions
diff --git a/examples/heterogeneous-hello-world/shader.slang b/examples/heterogeneous-hello-world/shader.slang index b36a2d2c7..a032f66ac 100644 --- a/examples/heterogeneous-hello-world/shader.slang +++ b/examples/heterogeneous-hello-world/shader.slang @@ -3,9 +3,8 @@ //TEST_INPUT:ubuffer(random(float, 4096, -1.0, 1.0), stride=4):name=ioBuffer RWStructuredBuffer<float> ioBuffer; -[shader("compute")] [numthreads(4, 1, 1)] -void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +public void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) { uint tid = dispatchThreadID.x; diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 03fb39135..c643f825a 100755 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -622,7 +622,7 @@ namespace Slang } else { - return emitEntryPointSourceFromIR( + return emitEntryPointsSourceFromIR( compileRequest, entryPointIndices, target, @@ -1322,10 +1322,10 @@ SlangResult dissassembleDXILUsingDXC( /* This is more convoluted than the other scenarios, because when we invoke C/C++ compiler we would ideally like to use the original file. We want to do this because we want includes relative to the source file to work, and for that to work most easily we want to use the original file, if there is one */ - // Note also that we require there to be only one entry point to use a translation unit - // TODO(DG): Review this assertion later - if (isPassThroughEnabled(endToEndReq) && entryPointIndices.getCount() == 1) + if (isPassThroughEnabled(endToEndReq)) { + // TODO(DG): Review this assertion later + SLANG_ASSERT(entryPointIndices.getCount() == 1); auto translationUnit = getPassThroughTranslationUnit(endToEndReq, entryPointIndices[0]); // If it's pass through we accumulate the preprocessor definitions. for (auto& define : translationUnit->compileRequest->preprocessorDefinitions) diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index d3aaeb948..4ad449b54 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -108,6 +108,7 @@ DIAGNOSTIC( 62, Error, failedToFindFunctionForCompiler, "failed to find funct DIAGNOSTIC( 70, Error, cannotMatchOutputFileToEntryPoint, "the output path '$0' is not associated with any entry point; a '-o' option for a compiled kernel must follow the '-entry' option for its corresponding entry point") DIAGNOSTIC( 80, Error, duplicateOutputPathsForEntryPointAndTarget, "multiple output paths have been specified entry point '$0' on target '$1'") +DIAGNOSTIC( 81, Error, duplicateOutputPathsForTarget, "multiple output paths have been specified for target '$0'") DIAGNOSTIC( 82, Error, unableToWriteReproFile, "unable to write repro file '%0'") DIAGNOSTIC( 83, Error, unableToWriteModuleContainer, "unable to write module container '%0'") diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h index 7f91a7be4..d813a819e 100644 --- a/source/slang/slang-emit-c-like.h +++ b/source/slang/slang-emit-c-like.h @@ -362,7 +362,7 @@ public: // in some very specific cases to determine how a construct // should map to GLSL. // - Stage m_entryPointStage; + Stage m_entryPointStage = Stage::Unknown; // The target language we want to generate code for CodeGenTarget m_target; diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 0ca523ecf..915d963c0 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -1115,19 +1115,21 @@ struct SPIRVEmitContext SlangResult emitSPIRVFromIR( BackEndCompileRequest* compileRequest, IRModule* irModule, - IRFunc* irEntryPoint, + const List<IRFunc*>& irEntryPoints, List<uint8_t>& spirvOut) { SLANG_UNUSED(compileRequest); SLANG_UNUSED(irModule); - SLANG_UNUSED(irEntryPoint); spirvOut.clear(); SPIRVEmitContext context; context.m_irModule = irModule; context.emitFrontMatter(); - context.ensureInst(irEntryPoint); + for (auto irEntryPoint : irEntryPoints) + { + context.ensureInst(irEntryPoint); + } context.emitPhysicalLayout(); spirvOut.addRange( diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 63bf8f054..72b2e07c5 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -165,7 +165,6 @@ struct LinkingAndOptimizationOptions CLikeSourceEmitter* sourceEmitter = nullptr; }; -// TODO(DG): A bit tricky; this needs to be generalized to multiple entry points Result linkAndOptimizeIR( BackEndCompileRequest* compileRequest, const List<Int>& entryPointIndices, @@ -194,7 +193,7 @@ Result linkAndOptimizeIR( target, targetProgram); auto irModule = outLinkedIR.module; - auto irEntryPoint = outLinkedIR.entryPoint; + auto irEntryPoints = outLinkedIR.entryPoints; #if 0 dumpIRIfEnabled(compileRequest, irModule, "LINKED"); @@ -341,8 +340,7 @@ Result linkAndOptimizeIR( } // TODO(DG): There are multiple DCE steps here, which need to be changed - // CHECK: how to these modules work? - // so that they don't just throw out any non-entry point code + // so that they don't just throw out any non-entry point code // Debugging code for IR transformations... #if 0 dumpIRIfEnabled(compileRequest, irModule, "SPECIALIZED"); @@ -611,10 +609,10 @@ Result linkAndOptimizeIR( { auto glslExtensionTracker = as<GLSLExtensionTracker>(options.sourceEmitter->getExtensionTracker()); - legalizeEntryPointForGLSL( + legalizeEntryPointsForGLSL( session, irModule, - irEntryPoint, + irEntryPoints, compileRequest->getSink(), glslExtensionTracker); @@ -692,8 +690,7 @@ Result linkAndOptimizeIR( return SLANG_OK; } -// TODO(DG): This probably needs to be generalized to a list -SlangResult emitEntryPointSourceFromIR( +SlangResult emitEntryPointsSourceFromIR( BackEndCompileRequest* compileRequest, const List<Int>& entryPointIndices, CodeGenTarget target, @@ -705,10 +702,6 @@ SlangResult emitEntryPointSourceFromIR( auto sink = compileRequest->getSink(); auto program = compileRequest->getProgram(); - // Temporary assertion for checkpoint - SLANG_ASSERT(entryPointIndices.getCount() == 1); - auto entryPoint = program->getEntryPoint(entryPointIndices[0]); - auto lineDirectiveMode = compileRequest->getLineDirectiveMode(); // To try to make the default behavior reasonable, we will // always use C-style line directives (to give the user @@ -728,8 +721,12 @@ SlangResult emitEntryPointSourceFromIR( desc.compileRequest = compileRequest; desc.target = target; // TODO(DG): Can't assume a single entry point stage for multiple entry points - desc.entryPointStage = entryPoint->getStage(); - desc.effectiveProfile = getEffectiveProfile(entryPoint, targetRequest); + if (entryPointIndices.getCount() == 1) + { + auto entryPoint = program->getEntryPoint(entryPointIndices[0]); + desc.entryPointStage = entryPoint->getStage(); + desc.effectiveProfile = getEffectiveProfile(entryPoint, targetRequest); + } desc.sourceWriter = &sourceWriter; // Define here, because must be in scope longer than the sourceEmitter, as sourceEmitter might reference @@ -857,7 +854,7 @@ SlangResult emitEntryPointSourceFromIR( SlangResult emitSPIRVFromIR( BackEndCompileRequest* compileRequest, IRModule* irModule, - IRFunc* irEntryPoint, + const List<IRFunc*>& irEntryPoints, List<uint8_t>& spirvOut); SlangResult emitSPIRVForEntryPointsDirectly( @@ -866,8 +863,6 @@ SlangResult emitSPIRVForEntryPointsDirectly( TargetRequest* targetRequest, List<uint8_t>& spirvOut) { - // TODO(DG): Temporary assertion for checkpoint - SLANG_ASSERT(entryPointIndices.getCount() == 1); auto sink = compileRequest->getSink(); auto program = compileRequest->getProgram(); auto targetProgram = program->getTargetProgram(targetRequest); @@ -887,12 +882,12 @@ SlangResult emitSPIRVForEntryPointsDirectly( linkedIR); auto irModule = linkedIR.module; - auto irEntryPoint = linkedIR.entryPoint; + auto irEntryPoints = linkedIR.entryPoints; emitSPIRVFromIR( compileRequest, irModule, - irEntryPoint, + irEntryPoints, spirvOut); return SLANG_OK; diff --git a/source/slang/slang-emit.h b/source/slang/slang-emit.h index 2c36436ee..7d783d99c 100644 --- a/source/slang/slang-emit.h +++ b/source/slang/slang-emit.h @@ -36,7 +36,7 @@ namespace Slang /// generate different HLSL output if we know it /// will be used to generate SPIR-V). /// - SlangResult emitEntryPointSourceFromIR( + SlangResult emitEntryPointsSourceFromIR( BackEndCompileRequest* compileRequest, const List<Int>& entryPointIndices, CodeGenTarget target, diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp index 794024d46..2abd8ba66 100644 --- a/source/slang/slang-ir-glsl-legalize.cpp +++ b/source/slang/slang-ir-glsl-legalize.cpp @@ -1775,4 +1775,17 @@ void legalizeEntryPointForGLSL( // the way that things have been moved around. } +void legalizeEntryPointsForGLSL( + Session* session, + IRModule* module, + const List<IRFunc*>& funcs, + DiagnosticSink* sink, + GLSLExtensionTracker* glslExtensionTracker) +{ + for (auto func : funcs) + { + legalizeEntryPointForGLSL(session, module, func, sink, glslExtensionTracker); + } +} + } // namespace Slang diff --git a/source/slang/slang-ir-glsl-legalize.h b/source/slang/slang-ir-glsl-legalize.h index e525f2791..0c6bf5196 100644 --- a/source/slang/slang-ir-glsl-legalize.h +++ b/source/slang/slang-ir-glsl-legalize.h @@ -1,5 +1,6 @@ // slang-ir-glsl-legalize.h #pragma once +#include"../core/slang-list.h" namespace Slang { @@ -12,10 +13,10 @@ class GLSLExtensionTracker; struct IRFunc; struct IRModule; -void legalizeEntryPointForGLSL( +void legalizeEntryPointsForGLSL( Session* session, IRModule* module, - IRFunc* func, + const List<IRFunc*>& func, DiagnosticSink* sink, GLSLExtensionTracker* glslExtensionTracker); diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp index 704917629..9de2b5d1c 100644 --- a/source/slang/slang-ir-link.cpp +++ b/source/slang/slang-ir-link.cpp @@ -1346,7 +1346,6 @@ struct IRSpecializationState } }; -// TODO(DG): Generalize to multiple entry points LinkedIR linkIR( BackEndCompileRequest* compileRequest, const List<Int>& entryPointIndices, @@ -1448,12 +1447,13 @@ LinkedIR linkIR( // arguments which might end up affecting the mangled // entry point name. // - // TODO(DG): spot to generalize to multiple entry points - // Note that only stuff referenced by an entry point gets linked here - // Temporary assertion for checkpoint - SLANG_ASSERT(entryPointIndices.getCount() == 1); - auto entryPointMangledName = program->getEntryPointMangledName(entryPointIndices[0]); - auto irEntryPoint = specializeIRForEntryPoint(context, entryPointMangledName); + + List<IRFunc*> irEntryPoints; + for (auto entryPointIndex : entryPointIndices) + { + auto entryPointMangledName = program->getEntryPointMangledName(entryPointIndex); + irEntryPoints.add(specializeIRForEntryPoint(context, entryPointMangledName)); + } // Layout information for global shader parameters is also required, // and in particular every global parameter that is part of the layout @@ -1528,8 +1528,8 @@ LinkedIR linkIR( // LinkedIR linkedIR; linkedIR.module = state->irModule; - linkedIR.entryPoint = irEntryPoint; linkedIR.globalScopeVarLayout = irGlobalScopeVarLayout; + linkedIR.entryPoints = irEntryPoints; return linkedIR; } diff --git a/source/slang/slang-ir-link.h b/source/slang/slang-ir-link.h index ce2af64d8..92a301c5a 100644 --- a/source/slang/slang-ir-link.h +++ b/source/slang/slang-ir-link.h @@ -10,8 +10,8 @@ namespace Slang struct LinkedIR { RefPtr<IRModule> module; - IRFunc* entryPoint; IRVarLayout* globalScopeVarLayout; + List<IRFunc*> entryPoints; }; diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index 3f1adeb13..6b4d5adf2 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -149,6 +149,7 @@ struct OptionsParser CodeGenTarget impliedFormat = CodeGenTarget::Unknown; int targetIndex = -1; int entryPointIndex = -1; + bool isWholeProgram = false; }; List<RawOutput> rawOutputs; @@ -159,6 +160,7 @@ struct OptionsParser SlangTargetFlags targetFlags = 0; int targetID = -1; FloatingPointMode floatingPointMode = FloatingPointMode::Default; + bool isWholeProgramRequest = false; // State for tracking command-line errors bool conflictingProfilesSet = false; @@ -1421,13 +1423,8 @@ struct OptionsParser // for(auto& rawOutput : rawOutputs) { - // TODO(DG): As noted below, change support for output formats - // with multiple entry points - - // For now, all output formats need to be tightly bound to - // both a target and an entry point (down the road we will - // need to support output formats that can store multiple - // entry points in one file). + // For now, most output formats need to be tightly bound to + // both a target and an entry point. // If an output doesn't have a target associated with // it, then search for the target with the matching format. @@ -1459,14 +1456,24 @@ struct OptionsParser // with an entry point, since the case of a single entry // point was handled above, and the user is expected to // follow the ordering rules when using multiple entry points. - // - // TODO(DG): check if output format is left unassociated - // If (known format for that output && that format supports whole program) { - // set isWholeProgram bit on the TargetRequest } - // else { diagnose what happened } if( rawOutput.entryPointIndex == -1 ) { - sink->diagnose(SourceLoc(), Diagnostics::cannotMatchOutputFileToEntryPoint, rawOutput.path); + if (rawOutput.targetIndex != -1 ) + { + auto outputFormat = rawTargets[rawOutput.targetIndex].format; + // Here we check whether the given output format supports multiple entry points + // When we add targets with support for multiple entry points, + // we should update this switch with those new formats + switch (outputFormat) + { + case CodeGenTarget::CPPSource: + rawOutput.isWholeProgram = true; + break; + default: + sink->diagnose(SourceLoc(), Diagnostics::cannotMatchOutputFileToEntryPoint, rawOutput.path); + break; + } + } } } @@ -1479,15 +1486,8 @@ struct OptionsParser for(auto& rawOutput : rawOutputs) { if(rawOutput.targetIndex == -1) continue; - // TODO(DG): probably needs updating - if(rawOutput.entryPointIndex == -1) continue; - auto targetID = rawTargets[rawOutput.targetIndex].targetID; - Int entryPointID = rawEntryPoints[rawOutput.entryPointIndex].entryPointID; - auto target = requestImpl->getLinkage()->targets[targetID]; - auto entryPointReq = requestImpl->getFrontEndReq()->getEntryPointReqs()[entryPointID]; - RefPtr<EndToEndCompileRequest::TargetInfo> targetInfo; if( !requestImpl->targetInfos.TryGetValue(target, targetInfo) ) { @@ -1495,14 +1495,34 @@ struct OptionsParser requestImpl->targetInfos[target] = targetInfo; } - String outputPath; - if( targetInfo->entryPointOutputPaths.ContainsKey(entryPointID) ) + if (rawOutput.isWholeProgram) { - sink->diagnose(SourceLoc(), Diagnostics::duplicateOutputPathsForEntryPointAndTarget, entryPointReq->getName(), target->getTarget()); + if (targetInfo->wholeTargetOutputPath != "") + { + sink->diagnose(SourceLoc(), Diagnostics::duplicateOutputPathsForTarget, target->getTarget()); + } + else + { + target->isWholeProgramRequest = true; + targetInfo->wholeTargetOutputPath = rawOutput.path; + } } else { - targetInfo->entryPointOutputPaths[entryPointID] = rawOutput.path; + if (rawOutput.entryPointIndex == -1) continue; + + Int entryPointID = rawEntryPoints[rawOutput.entryPointIndex].entryPointID; + auto entryPointReq = requestImpl->getFrontEndReq()->getEntryPointReqs()[entryPointID]; + + //String outputPath; + if (targetInfo->entryPointOutputPaths.ContainsKey(entryPointID)) + { + sink->diagnose(SourceLoc(), Diagnostics::duplicateOutputPathsForEntryPointAndTarget, entryPointReq->getName(), target->getTarget()); + } + else + { + targetInfo->entryPointOutputPaths[entryPointID] = rawOutput.path; + } } } diff --git a/tests/diagnostics/command-line/unknown-output-format.slang.expected b/tests/diagnostics/command-line/unknown-output-format.slang.expected index c2f41fa71..c67f37ceb 100644 --- a/tests/diagnostics/command-line/unknown-output-format.slang.expected +++ b/tests/diagnostics/command-line/unknown-output-format.slang.expected @@ -1,7 +1,6 @@ result code = 1 standard error = { (0): error 60: cannot infer an output format from the output path 'cookies.jar' -(0): error 70: the output path 'cookies.jar' is not associated with any entry point; a '-o' option for a compiled kernel must follow the '-entry' option for its corresponding entry point } standard output = { } |
