diff options
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/slang-compiler.cpp | 122 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.h | 3 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 24 | ||||
| -rw-r--r-- | source/slang/slang-emit.cpp | 32 | ||||
| -rw-r--r-- | source/slang/slang-ir-inline.cpp | 29 | ||||
| -rw-r--r-- | source/slang/slang-ir-inline.h | 3 | ||||
| -rw-r--r-- | source/slang/slang-spirv-opt.cpp | 66 | ||||
| -rw-r--r-- | source/slang/slang-spirv-opt.h | 10 |
8 files changed, 111 insertions, 178 deletions
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 9b14fd2f7..997466d49 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -953,6 +953,71 @@ namespace Slang return false; } + SlangResult passthroughDownstreamDiagnostics(DiagnosticSink* sink, IDownstreamCompiler* compiler, IArtifact* artifact) + { + auto diagnostics = findAssociatedRepresentation<IArtifactDiagnostics>(artifact); + + if (!diagnostics) + return SLANG_OK; + + if (diagnostics->getCount()) + { + StringBuilder compilerText; + DownstreamCompilerUtil::appendAsText(compiler->getDesc(), compilerText); + + StringBuilder builder; + + auto const diagnosticCount = diagnostics->getCount(); + for (Index i = 0; i < diagnosticCount; ++i) + { + const auto& diagnostic = *diagnostics->getAt(i); + + builder.clear(); + + const Severity severity = _getDiagnosticSeverity(diagnostic.severity); + + if (diagnostic.filePath.count == 0 && diagnostic.location.line == 0 && severity == Severity::Note) + { + // If theres no filePath line number and it's info, output severity and text alone + builder << getSeverityName(severity) << " : "; + } + else + { + if (diagnostic.filePath.count) + { + builder << asStringSlice(diagnostic.filePath); + } + + if (diagnostic.location.line) + { + builder << "(" << diagnostic.location.line << ")"; + } + + builder << ": "; + + if (diagnostic.stage == ArtifactDiagnostic::Stage::Link) + { + builder << "link "; + } + + builder << getSeverityName(severity); + builder << " " << asStringSlice(diagnostic.code) << ": "; + } + + builder << asStringSlice(diagnostic.text); + reportExternalCompileError(compilerText.getBuffer(), severity, SLANG_OK, builder.getUnownedSlice(), sink); + } + } + + // If any errors are emitted, then we are done + if (diagnostics->hasOfAtLeastSeverity(ArtifactDiagnostic::Severity::Error)) + { + return SLANG_FAIL; + } + + return SLANG_OK; + } + SlangResult CodeGenContext::emitWithDownstreamForEntryPoints(ComPtr<IArtifact>& outArtifact) { outArtifact.setNull(); @@ -1421,62 +1486,7 @@ namespace Slang (std::chrono::high_resolution_clock::now() - downstreamStartTime).count() * 0.000000001; getSession()->addDownstreamCompileTime(downstreamElapsedTime); - auto diagnostics = findAssociatedRepresentation<IArtifactDiagnostics>(artifact); - - if (diagnostics->getCount()) - { - StringBuilder compilerText; - DownstreamCompilerUtil::appendAsText(compiler->getDesc(), compilerText); - - StringBuilder builder; - - auto const diagnosticCount = diagnostics->getCount(); - for (Index i = 0; i < diagnosticCount; ++i) - { - const auto& diagnostic = *diagnostics->getAt(i); - - builder.clear(); - - const Severity severity = _getDiagnosticSeverity(diagnostic.severity); - - if (diagnostic.filePath.count == 0 && diagnostic.location.line == 0 && severity == Severity::Note) - { - // If theres no filePath line number and it's info, output severity and text alone - builder << getSeverityName(severity) << " : "; - } - else - { - if (diagnostic.filePath.count) - { - builder << asStringSlice(diagnostic.filePath); - } - - if (diagnostic.location.line) - { - builder << "(" << diagnostic.location.line <<")"; - } - - builder << ": "; - - if (diagnostic.stage == ArtifactDiagnostic::Stage::Link) - { - builder << "link "; - } - - builder << getSeverityName(severity); - builder << " " << asStringSlice(diagnostic.code) << ": "; - } - - builder << asStringSlice(diagnostic.text); - reportExternalCompileError(compilerText.getBuffer(), severity, SLANG_OK, builder.getUnownedSlice(), sink); - } - } - - // If any errors are emitted, then we are done - if (diagnostics->hasOfAtLeastSeverity(ArtifactDiagnostic::Severity::Error)) - { - return SLANG_FAIL; - } + SLANG_RETURN_ON_FAIL(passthroughDownstreamDiagnostics(getSink(), compiler, artifact)); // Copy over all of the information associated with the source into the output if (sourceArtifact) diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index c5bd3348c..c3f2d8e70 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -1197,6 +1197,7 @@ namespace Slang GenericCCpp = SLANG_PASS_THROUGH_GENERIC_C_CPP, ///< Generic C/C++ compiler NVRTC = SLANG_PASS_THROUGH_NVRTC, ///< NVRTC CUDA compiler LLVM = SLANG_PASS_THROUGH_LLVM, ///< LLVM 'compiler' + SpirvOpt = SLANG_PASS_THROUGH_SPIRV_OPT, ///< pass thorugh spirv to spirv-opt CountOf = SLANG_PASS_THROUGH_COUNT_OF, }; void printDiagnosticArg(StringBuilder& sb, PassThroughMode val); @@ -3153,6 +3154,8 @@ namespace Slang DiagnosticSink* sink, const LoadedModuleDictionary* additionalLoadedModules); + SlangResult passthroughDownstreamDiagnostics(DiagnosticSink* sink, IDownstreamCompiler* compiler, IArtifact* artifact); + // // The following functions are utilties to convert between // matching "external" (public API) and "internal" (implementation) diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 6d71f1a2c..16a88b8af 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -4815,18 +4815,22 @@ SlangResult emitSPIRVFromIR( (uint8_t const*) context.m_words.getBuffer(), context.m_words.getCount() * Index(sizeof(context.m_words[0]))); - const auto validationResult = debugValidateSPIRV(spirvOut); - // If validation isn't available, don't say it failed, it's just a debug - // feature so we can skip - if(SLANG_FAILED(validationResult) && validationResult != SLANG_E_NOT_AVAILABLE) + StringBuilder runSpirvValEnvVar; + PlatformUtil::getEnvironmentVariable(UnownedStringSlice("SLANG_RUN_SPIRV_VALIDATION"), runSpirvValEnvVar); + if (runSpirvValEnvVar.getUnownedSlice() == "1") { - codeGenContext->getSink()->diagnoseWithoutSourceView( - SourceLoc{}, - Diagnostics::spirvValidationFailed - ); - return validationResult; + const auto validationResult = debugValidateSPIRV(spirvOut); + // If validation isn't available, don't say it failed, it's just a debug + // feature so we can skip + if (SLANG_FAILED(validationResult) && validationResult != SLANG_E_NOT_AVAILABLE) + { + codeGenContext->getSink()->diagnoseWithoutSourceView( + SourceLoc{}, + Diagnostics::spirvValidationFailed + ); + return validationResult; + } } - return SLANG_OK; } diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 86136a010..57ca736e3 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -73,7 +73,6 @@ #include "slang-legalize-types.h" #include "slang-lower-to-ir.h" #include "slang-mangle.h" -#include "slang-spirv-opt.h" #include "slang-syntax.h" #include "slang-type-layout.h" #include "slang-visitor.h" @@ -931,8 +930,7 @@ Result linkAndOptimizeIR( if (isKhronosTarget(targetRequest) && targetRequest->shouldEmitSPIRVDirectly()) { - //performIntrinsicFunctionFunctionInlining(irModule); - performSpirvInlining(irModule); + performIntrinsicFunctionFunctionInlining(irModule); eliminateDeadCode(irModule); } eliminateMultiLevelBreak(irModule); @@ -1289,10 +1287,36 @@ SlangResult emitSPIRVForEntryPointsDirectly( spirv = _Move(outSpirv); } #endif - auto artifact = ArtifactUtil::createArtifactForCompileTarget(asExternal(codeGenContext->getTargetFormat())); artifact->addRepresentationUnknown(ListBlob::moveCreate(spirv)); + IDownstreamCompiler* compiler = codeGenContext->getSession()->getOrLoadDownstreamCompiler( + PassThroughMode::SpirvOpt, codeGenContext->getSink()); + if (compiler) + { + ComPtr<IArtifact> optimizedArtifact; + DownstreamCompileOptions downstreamOptions; + downstreamOptions.sourceArtifacts = makeSlice(artifact.readRef(), 1); + downstreamOptions.targetType = SLANG_SPIRV; + downstreamOptions.sourceLanguage = SLANG_SOURCE_LANGUAGE_SPIRV; + auto linkage = codeGenContext->getLinkage(); + switch (linkage->optimizationLevel) + { + case OptimizationLevel::None: downstreamOptions.optimizationLevel = DownstreamCompileOptions::OptimizationLevel::None; break; + case OptimizationLevel::Default: downstreamOptions.optimizationLevel = DownstreamCompileOptions::OptimizationLevel::Default; break; + case OptimizationLevel::High: downstreamOptions.optimizationLevel = DownstreamCompileOptions::OptimizationLevel::High; break; + case OptimizationLevel::Maximal: downstreamOptions.optimizationLevel = DownstreamCompileOptions::OptimizationLevel::Maximal; break; + default: SLANG_ASSERT(!"Unhandled optimization level"); break; + } + + if (SLANG_SUCCEEDED(compiler->compile(downstreamOptions, optimizedArtifact.writeRef()))) + { + artifact = _Move(optimizedArtifact); + } + + SLANG_RETURN_ON_FAIL(passthroughDownstreamDiagnostics(codeGenContext->getSink(), compiler, artifact)); + } + ArtifactUtil::addAssociated(artifact, linkedIR.metadata); outArtifact.swap(artifact); diff --git a/source/slang/slang-ir-inline.cpp b/source/slang/slang-ir-inline.cpp index 3b01d7dde..01dfdc42d 100644 --- a/source/slang/slang-ir-inline.cpp +++ b/source/slang/slang-ir-inline.cpp @@ -1019,33 +1019,4 @@ bool inlineCall(IRCall* call) return pass.considerCallSite(call); } - -struct SpirvInliningPass : InliningPassBase -{ - typedef InliningPassBase Super; - - SpirvInliningPass(IRModule* module) - : Super(module) - {} - - bool shouldInline(CallSiteInfo const& info) - { - if (!info.callee->findDecoration<IREntryPointDecoration>()) - return true; - return false; - } -}; - -void performSpirvInlining(IRModule* module) -{ - SLANG_PROFILE; - while (true) - { - SpirvInliningPass pass(module); - if (pass.considerAllCallSites()) - continue; - break; - } -} - } // namespace Slang diff --git a/source/slang/slang-ir-inline.h b/source/slang/slang-ir-inline.h index 5e888ad07..539bb26c0 100644 --- a/source/slang/slang-ir-inline.h +++ b/source/slang/slang-ir-inline.h @@ -34,9 +34,6 @@ namespace Slang /// Inline simple intrinsic functions whose definition is a single asm block. void performIntrinsicFunctionFunctionInlining(IRModule* module); - /// Inline all functions for SPIRV emit. - void performSpirvInlining(IRModule* module); - /// Inline a specific call. bool inlineCall(IRCall* call); } diff --git a/source/slang/slang-spirv-opt.cpp b/source/slang/slang-spirv-opt.cpp deleted file mode 100644 index 786358324..000000000 --- a/source/slang/slang-spirv-opt.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "slang-spirv-opt.h" -#include "slang-spirv-val.h" - -namespace Slang -{ - -struct RemoveFileRAII -{ - String fileName; - - RemoveFileRAII(String inFileName) - :fileName(inFileName) - {} - - ~RemoveFileRAII() - { - File::remove(fileName); - } -}; - -SlangResult optimizeSPIRV(const List<uint8_t>& spirv, String& outErr, List<uint8_t>& outSpv) -{ - // Set up our process - CommandLine commandLine; - commandLine.m_executableLocation.setName("spirv-opt"); - commandLine.addArg("--eliminate-dead-functions"); - commandLine.addArg("--eliminate-local-single-block"); - commandLine.addArg("--eliminate-local-single-store"); - commandLine.addArg("--eliminate-dead-code-aggressive"); - - commandLine.addArg("-o"); - String outFileName; - File::generateTemporary(UnownedStringSlice("out_spv"), outFileName); - RemoveFileRAII removeFile(outFileName); - - commandLine.addArg(outFileName); - - RefPtr<Process> p; - - // If we failed to even start the process, then spirv-opt isn't available - SLANG_RETURN_ON_FAIL(Process::create(commandLine, 0, p)); - const auto in = p->getStream(StdStreamType::In); - const auto out = p->getStream(StdStreamType::Out); - const auto err = p->getStream(StdStreamType::ErrorOut); - - List<Byte> outErrData; - SLANG_RETURN_ON_FAIL(StreamUtil::readAndWrite(in, spirv.getArrayView(), out, outSpv, err, outErrData)); - - outSpv.clear(); - File::readAllBytes(outFileName, outSpv); - - SLANG_RETURN_ON_FAIL(p->waitForTermination(3600000)); - - outErr = String( - reinterpret_cast<const char*>(outErrData.begin()), - reinterpret_cast<const char*>(outErrData.end()) - ); - - const auto ret = p->getReturnValue(); - if (ret != 0) - return SLANG_FAIL; - - return debugValidateSPIRV(outSpv); -} - -} diff --git a/source/slang/slang-spirv-opt.h b/source/slang/slang-spirv-opt.h deleted file mode 100644 index c7dfde157..000000000 --- a/source/slang/slang-spirv-opt.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include <cstdint> -#include "slang-compiler.h" - -namespace Slang -{ -SlangResult optimizeSPIRV(const List<uint8_t>& spirv, String& outErr, List<uint8_t>& outSpv); -} - |
