diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2021-05-19 15:57:11 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-19 12:57:11 -0700 |
| commit | 61e9154cb797cffe19cfbf3205b4a5a614e8b552 (patch) | |
| tree | 94270d53c8189d25e6d11dee14860704759b7129 | |
| parent | d5e8044d0a9723bb0bbd7ae1738d1157265da783 (diff) | |
Glslang as DownstreamCompiler (#1846)
* #include an absolute path didn't work - because paths were taken to always be relative.
* WIP Fxc as downstream compiler.
* First pass FXC downstream compiler working.
* GCC compile fix.
* Fix FXC parsing issue.
* Special case filesystem access.
* Use StringUtil getSlice.
* Fix isses with not emitting source for FXC.
* WIP on DXC.
* Small fixes for DXBC handling.
* Removed DXC from ParseDiagnosticUtil (can use generic)
Try to improve output for notes from DXC.
* FIrst pass of Glslang as DownstreamCompiler
* Fix some problems with parsing for glslang replacement.
* Add slang-glslang-compiler.cpp/.h
* Fix downstream for spir-v output.
* dissassemble -> disassemble
* Fix typo and improve some naming/comments.
* Remove getSharedLibrary from DownstreamCompiler
* Removed some no longer used diagnostics.
| -rw-r--r-- | build/visual-studio/compiler-core/compiler-core.vcxproj | 2 | ||||
| -rw-r--r-- | build/visual-studio/compiler-core/compiler-core.vcxproj.filters | 6 | ||||
| -rw-r--r-- | source/compiler-core/slang-downstream-compiler.cpp | 72 | ||||
| -rw-r--r-- | source/compiler-core/slang-downstream-compiler.h | 40 | ||||
| -rw-r--r-- | source/compiler-core/slang-dxc-compiler.cpp | 57 | ||||
| -rw-r--r-- | source/compiler-core/slang-fxc-compiler.cpp | 63 | ||||
| -rw-r--r-- | source/compiler-core/slang-glslang-compiler.cpp | 300 | ||||
| -rw-r--r-- | source/compiler-core/slang-glslang-compiler.h | 18 | ||||
| -rw-r--r-- | source/compiler-core/slang-nvrtc-compiler.cpp | 1 | ||||
| -rw-r--r-- | source/slang/slang-check.cpp | 56 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.cpp | 509 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.h | 14 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 3 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 4 | ||||
| -rw-r--r-- | tools/slang-test/parse-diagnostic-util.cpp | 48 | ||||
| -rw-r--r-- | tools/slang-test/parse-diagnostic-util.h | 6 |
16 files changed, 574 insertions, 625 deletions
diff --git a/build/visual-studio/compiler-core/compiler-core.vcxproj b/build/visual-studio/compiler-core/compiler-core.vcxproj index aef6066fb..7e815d4fa 100644 --- a/build/visual-studio/compiler-core/compiler-core.vcxproj +++ b/build/visual-studio/compiler-core/compiler-core.vcxproj @@ -176,6 +176,7 @@ <ClInclude Include="..\..\..\source\compiler-core\slang-dxc-compiler.h" /> <ClInclude Include="..\..\..\source\compiler-core\slang-fxc-compiler.h" /> <ClInclude Include="..\..\..\source\compiler-core\slang-gcc-compiler-util.h" /> + <ClInclude Include="..\..\..\source\compiler-core\slang-glslang-compiler.h" /> <ClInclude Include="..\..\..\source\compiler-core\slang-include-system.h" /> <ClInclude Include="..\..\..\source\compiler-core\slang-lexer-diagnostic-defs.h" /> <ClInclude Include="..\..\..\source\compiler-core\slang-lexer.h" /> @@ -196,6 +197,7 @@ <ClCompile Include="..\..\..\source\compiler-core\slang-dxc-compiler.cpp" /> <ClCompile Include="..\..\..\source\compiler-core\slang-fxc-compiler.cpp" /> <ClCompile Include="..\..\..\source\compiler-core\slang-gcc-compiler-util.cpp" /> + <ClCompile Include="..\..\..\source\compiler-core\slang-glslang-compiler.cpp" /> <ClCompile Include="..\..\..\source\compiler-core\slang-include-system.cpp" /> <ClCompile Include="..\..\..\source\compiler-core\slang-lexer.cpp" /> <ClCompile Include="..\..\..\source\compiler-core\slang-name-convention-util.cpp" /> diff --git a/build/visual-studio/compiler-core/compiler-core.vcxproj.filters b/build/visual-studio/compiler-core/compiler-core.vcxproj.filters index bd10293c2..a4fc4e2c2 100644 --- a/build/visual-studio/compiler-core/compiler-core.vcxproj.filters +++ b/build/visual-studio/compiler-core/compiler-core.vcxproj.filters @@ -27,6 +27,9 @@ <ClInclude Include="..\..\..\source\compiler-core\slang-gcc-compiler-util.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\..\..\source\compiler-core\slang-glslang-compiler.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="..\..\..\source\compiler-core\slang-include-system.h"> <Filter>Header Files</Filter> </ClInclude> @@ -83,6 +86,9 @@ <ClCompile Include="..\..\..\source\compiler-core\slang-gcc-compiler-util.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="..\..\..\source\compiler-core\slang-glslang-compiler.cpp"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="..\..\..\source\compiler-core\slang-include-system.cpp"> <Filter>Source Files</Filter> </ClCompile> diff --git a/source/compiler-core/slang-downstream-compiler.cpp b/source/compiler-core/slang-downstream-compiler.cpp index 9721b45d3..f5f1b84c9 100644 --- a/source/compiler-core/slang-downstream-compiler.cpp +++ b/source/compiler-core/slang-downstream-compiler.cpp @@ -10,6 +10,7 @@ #include "../core/slang-io.h" #include "../core/slang-shared-library.h" #include "../core/slang-blob.h" +#include "../core/slang-char-util.h" #ifdef SLANG_VC # include "windows/slang-win-visual-studio-util.h" @@ -20,6 +21,7 @@ #include "slang-nvrtc-compiler.h" #include "slang-fxc-compiler.h" #include "slang-dxc-compiler.h" +#include "slang-glslang-compiler.h" namespace Slang { @@ -114,9 +116,57 @@ void DownstreamCompiler::Desc::appendAsText(StringBuilder& out) const return SLANG_OK; } +/* static */SlangResult DownstreamDiagnostic::splitColonDelimitedLine(const UnownedStringSlice& line, Int pathIndex, List<UnownedStringSlice>& outSlices) +{ + StringUtil::split(line, ':', outSlices); + + // Now we want to fix up a path as might have drive letter, and therefore : + // If this is the situation then we need to have a slice after the one at the index + if (outSlices.getCount() > pathIndex + 1) + { + const UnownedStringSlice pathStart = outSlices[pathIndex].trim(); + if (pathStart.getLength() == 1 && CharUtil::isAlpha(pathStart[0])) + { + // Splice back together + outSlices[pathIndex] = UnownedStringSlice(outSlices[pathIndex].begin(), outSlices[pathIndex + 1].end()); + outSlices.removeAt(pathIndex + 1); + } + } + + return SLANG_OK; +} + +/* static */SlangResult DownstreamDiagnostic::parseColonDelimitedDiagnostics(const UnownedStringSlice& inText, Int pathIndex, LineParser lineParser, List<DownstreamDiagnostic>& outDiagnostics) +{ + List<UnownedStringSlice> splitLine; + + UnownedStringSlice text(inText), line; + while (StringUtil::extractLine(text, line)) + { + SLANG_RETURN_ON_FAIL(splitColonDelimitedLine(line, pathIndex, splitLine)); + + DownstreamDiagnostic diagnostic; + diagnostic.severity = DownstreamDiagnostic::Severity::Error; + diagnostic.stage = DownstreamDiagnostic::Stage::Compile; + diagnostic.fileLine = 0; + + if (SLANG_SUCCEEDED(lineParser(line, splitLine, diagnostic))) + { + outDiagnostics.add(diagnostic); + } + else + { + // If couldn't parse, just add as a note + DownstreamDiagnostics::addNote(line, outDiagnostics); + } + } + + return SLANG_OK; +} + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompiler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ -SlangResult DownstreamCompiler::dissassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) +SlangResult DownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) { SLANG_UNUSED(sourceBlobTarget); SLANG_UNUSED(blob); @@ -676,24 +726,6 @@ const DownstreamCompiler::Desc& DownstreamCompilerUtil::getCompiledWithDesc() } } -static SlangResult _locateGlslangCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) -{ -#if SLANG_UNIX_FAMILY - // On unix systems we need to ensure pthread is loaded first. - ComPtr<ISlangSharedLibrary> pthreadLibrary; - DefaultSharedLibraryLoader::load(loader, path, "pthread", pthreadLibrary.writeRef()); -#endif - ComPtr<ISlangSharedLibrary> sharedLibrary; - if (SLANG_SUCCEEDED(DefaultSharedLibraryLoader::load(loader, path, "slang-glslang", sharedLibrary.writeRef()))) - { - // Can we determine the version? - DownstreamCompiler::Desc desc(SLANG_PASS_THROUGH_GLSLANG); - RefPtr<DownstreamCompiler> compiler(new SharedLibraryDownstreamCompiler(desc, sharedLibrary)); - set->addCompiler(compiler); - } - return SLANG_OK; -} - /* static */void DownstreamCompilerUtil::setDefaultLocators(DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]) { outFuncs[int(SLANG_PASS_THROUGH_VISUAL_STUDIO)] = &VisualStudioCompilerUtil::locateCompilers; @@ -702,7 +734,7 @@ static SlangResult _locateGlslangCompilers(const String& path, ISlangSharedLibra outFuncs[int(SLANG_PASS_THROUGH_NVRTC)] = &NVRTCDownstreamCompilerUtil::locateCompilers; outFuncs[int(SLANG_PASS_THROUGH_DXC)] = &DXCDownstreamCompilerUtil::locateCompilers; outFuncs[int(SLANG_PASS_THROUGH_FXC)] = &FXCDownstreamCompilerUtil::locateCompilers; - outFuncs[int(SLANG_PASS_THROUGH_GLSLANG)] = &_locateGlslangCompilers; + outFuncs[int(SLANG_PASS_THROUGH_GLSLANG)] = &GlslangDownstreamCompilerUtil::locateCompilers; } /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerSet !!!!!!!!!!!!!!!!!!!!!!*/ diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h index b3af8a506..22ad5e20c 100644 --- a/source/compiler-core/slang-downstream-compiler.h +++ b/source/compiler-core/slang-downstream-compiler.h @@ -59,6 +59,14 @@ struct DownstreamDiagnostic /// Given a path, that holds line number and potentially column number in () after path, writes result into outDiagnostic static SlangResult splitPathLocation(const UnownedStringSlice& pathLocation, DownstreamDiagnostic& outDiagnostic); + /// Split the line (separated by :), where a path is at pathIndex + static SlangResult splitColonDelimitedLine(const UnownedStringSlice& line, Int pathIndex, List<UnownedStringSlice>& outSlices); + + typedef SlangResult (*LineParser)(const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, DownstreamDiagnostic& outDiagnostic); + + /// Given diagnostics in inText that are colon delimited, use lineParser to do per line parsing. + static SlangResult parseColonDelimitedDiagnostics(const UnownedStringSlice& inText, Int pathIndex, LineParser lineParser, List<DownstreamDiagnostic>& outDiagnostics); + Severity severity; ///< The severity of error Stage stage; ///< The stage the error came from String text; ///< The text of the error @@ -241,6 +249,7 @@ public: enum class Kind { CUDASM, ///< What the version is for + SPIRV, }; Kind kind; SemanticVersion version; @@ -296,7 +305,10 @@ public: String entryPointName; /// Profile name to use, only required for compiles that need to compile against a a specific profiles. /// Profile names are tied to compilers and targets. - String profileName; + String profileName; + + /// The stage being compiled for + SlangStage stage = SLANG_STAGE_NONE; /// NOTE! Not all downstream compilers can use the fileSystemExt/sourceManager. This option will be ignored in those scenarios. ISlangFileSystemExt* fileSystemExt = nullptr; @@ -331,13 +343,10 @@ public: const Desc& getDesc() const { return m_desc; } /// Compile using the specified options. The result is in resOut virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) = 0; - /// Some downstream compilers are backed by a shared library. This allows access to the shared library to access internal functions. - virtual ISlangSharedLibrary* getSharedLibrary() { return nullptr; } - /// Some compilers have support converting a binary blob into disassembly. Output disassembly is held in the output blob - virtual SlangResult dissassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out); + virtual SlangResult disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out); - /// True if underlying compiler uses file system to pass source + /// True if underlying compiler uses file system to communicate source virtual bool isFileBased() = 0; /// Get info for a compiler type @@ -422,25 +431,6 @@ public: CommandLine m_cmdLine; }; -class SharedLibraryDownstreamCompiler: public DownstreamCompiler -{ -public: - typedef DownstreamCompiler Super; - - // DownstreamCompiler - virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE { SLANG_UNUSED(options); SLANG_UNUSED(outResult); return SLANG_E_NOT_IMPLEMENTED; } - virtual bool isFileBased() SLANG_OVERRIDE { return true; } - virtual ISlangSharedLibrary* getSharedLibrary() SLANG_OVERRIDE { return m_library; } - - SharedLibraryDownstreamCompiler(const Desc& desc, ISlangSharedLibrary* library): - Super(desc), - m_library(library) - { - } -protected: - ComPtr<ISlangSharedLibrary> m_library; -}; - class DownstreamCompilerSet : public RefObject { public: diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp index 281b6173d..7e7850780 100644 --- a/source/compiler-core/slang-dxc-compiler.cpp +++ b/source/compiler-core/slang-dxc-compiler.cpp @@ -126,8 +126,7 @@ public: // DownstreamCompiler virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; - virtual ISlangSharedLibrary* getSharedLibrary() SLANG_OVERRIDE { return m_sharedLibrary; } - virtual SlangResult dissassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; + virtual SlangResult disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; virtual bool isFileBased() SLANG_OVERRIDE { return false; } /// Must be called before use @@ -184,55 +183,6 @@ static SlangResult _parseDiagnosticLine(const UnownedStringSlice& line, List<Uno return SLANG_OK; } -static SlangResult _splitDiagnosticLine(const UnownedStringSlice& line, List<UnownedStringSlice>& outSlices) -{ - StringUtil::split(line, ':', outSlices); - const Int pathIndex = 0; - - // Now we want to fix up a path as might have drive letter, and therefore : - // If this is the situation then we need to have a slice after the one at the index - if (outSlices.getCount() > pathIndex + 1) - { - const UnownedStringSlice pathStart = outSlices[pathIndex].trim(); - if (pathStart.getLength() == 1 && CharUtil::isAlpha(pathStart[0])) - { - // Splice back together - outSlices[pathIndex] = UnownedStringSlice(outSlices[pathIndex].begin(), outSlices[pathIndex + 1].end()); - outSlices.removeAt(pathIndex + 1); - } - } - - return SLANG_OK; -} - -static SlangResult _parseDiagnostics(const UnownedStringSlice& inText, List<DownstreamDiagnostic>& outDiagnostics) -{ - List<UnownedStringSlice> splitLine; - - UnownedStringSlice text(inText), line; - while (StringUtil::extractLine(text, line)) - { - SLANG_RETURN_ON_FAIL(_splitDiagnosticLine(line, splitLine)); - - DownstreamDiagnostic diagnostic; - diagnostic.severity = DownstreamDiagnostic::Severity::Error; - diagnostic.stage = DownstreamDiagnostic::Stage::Compile; - diagnostic.fileLine = 0; - - if (SLANG_SUCCEEDED(_parseDiagnosticLine(line, splitLine, diagnostic))) - { - outDiagnostics.add(diagnostic); - } - else - { - // If couldn't parse, just add as a note - DownstreamDiagnostics::addNote(line, outDiagnostics); - } - } - - return SLANG_OK; -} - SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) { // This compiler doesn't read files, they should be read externally and stored in sourceContents/sourceContentsPath @@ -383,7 +333,8 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr { diagnostics.rawDiagnostics = String(diagnosticsSlice); - SlangResult diagnosticParseRes = _parseDiagnostics(diagnosticsSlice, diagnostics.diagnostics); + SlangResult diagnosticParseRes = DownstreamDiagnostic::parseColonDelimitedDiagnostics(diagnosticsSlice, 0, _parseDiagnosticLine, diagnostics.diagnostics); + SLANG_UNUSED(diagnosticParseRes); SLANG_ASSERT(SLANG_SUCCEEDED(diagnosticParseRes)); } @@ -408,7 +359,7 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr return SLANG_OK; } -SlangResult DXCDownstreamCompiler::dissassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) +SlangResult DXCDownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) { // Can only disassemble blobs that are DXIL if (sourceBlobTarget != SLANG_DXIL) diff --git a/source/compiler-core/slang-fxc-compiler.cpp b/source/compiler-core/slang-fxc-compiler.cpp index 60d50a13e..b0a117d1a 100644 --- a/source/compiler-core/slang-fxc-compiler.cpp +++ b/source/compiler-core/slang-fxc-compiler.cpp @@ -114,8 +114,7 @@ public: // DownstreamCompiler virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; - virtual ISlangSharedLibrary* getSharedLibrary() SLANG_OVERRIDE { return m_sharedLibrary; } - virtual SlangResult dissassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; + virtual SlangResult disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; virtual bool isFileBased() SLANG_OVERRIDE { return false; } /// Must be called before use @@ -176,60 +175,6 @@ static SlangResult _parseDiagnosticLine(const UnownedStringSlice& line, List<Uno return SLANG_OK; } -static SlangResult _splitDiagnosticLine(const UnownedStringSlice& line, List<UnownedStringSlice>& outSlices) -{ - StringUtil::split(line, ':', outSlices); - - /* - tests/diagnostics/syntax-error-intrinsic.slang(14,2): error X3000: syntax error: unexpected token '@' - */ - - const Int pathIndex = 0; - - // Now we want to fix up a path as might have drive letter, and therefore : - // If this is the situation then we need to have a slice after the one at the index - if (outSlices.getCount() > pathIndex + 1) - { - const UnownedStringSlice pathStart = outSlices[pathIndex].trim(); - if (pathStart.getLength() == 1 && CharUtil::isAlpha(pathStart[0])) - { - // Splice back together - outSlices[pathIndex] = UnownedStringSlice(outSlices[pathIndex].begin(), outSlices[pathIndex + 1].end()); - outSlices.removeAt(pathIndex + 1); - } - } - - return SLANG_OK; -} - -static SlangResult _parseDiagnostics(const UnownedStringSlice& inText, List<DownstreamDiagnostic>& outDiagnostics) -{ - List<UnownedStringSlice> splitLine; - - UnownedStringSlice text(inText), line; - while (StringUtil::extractLine(text, line)) - { - SLANG_RETURN_ON_FAIL(_splitDiagnosticLine(line, splitLine)); - - DownstreamDiagnostic diagnostic; - diagnostic.severity = DownstreamDiagnostic::Severity::Error; - diagnostic.stage = DownstreamDiagnostic::Stage::Compile; - diagnostic.fileLine = 0; - - if (SLANG_SUCCEEDED(_parseDiagnosticLine(line, splitLine, diagnostic))) - { - outDiagnostics.add(diagnostic); - } - else - { - // If couldn't parse, just add as a note - DownstreamDiagnostics::addNote(line, outDiagnostics); - } - } - - return SLANG_OK; -} - SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) { // This compiler doesn't read files, they should be read externally and stored in sourceContents/sourceContentsPath @@ -348,8 +293,8 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr { UnownedStringSlice diagnosticText = _getSlice(diagnosticsBlob); diagnostics.rawDiagnostics = diagnosticText; - - SlangResult diagnosticParseRes = _parseDiagnostics(diagnosticText, diagnostics.diagnostics); + + SlangResult diagnosticParseRes = DownstreamDiagnostic::parseColonDelimitedDiagnostics(diagnosticText, 0, _parseDiagnosticLine, diagnostics.diagnostics); SLANG_UNUSED(diagnosticParseRes); SLANG_ASSERT(SLANG_SUCCEEDED(diagnosticParseRes)); } @@ -361,7 +306,7 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr return SLANG_OK; } -SlangResult FXCDownstreamCompiler::dissassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) +SlangResult FXCDownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) { // Can only disassemble blobs that are DXBC if (sourceBlobTarget != SLANG_DXBC) diff --git a/source/compiler-core/slang-glslang-compiler.cpp b/source/compiler-core/slang-glslang-compiler.cpp new file mode 100644 index 000000000..8a8712024 --- /dev/null +++ b/source/compiler-core/slang-glslang-compiler.cpp @@ -0,0 +1,300 @@ +// slang-glslang-compiler.cpp +#include "slang-glslang-compiler.h" + +#include "../core/slang-common.h" +#include "../../slang-com-helper.h" + +#include "../core/slang-blob.h" + +#include "../core/slang-string-util.h" +#include "../core/slang-string-slice-pool.h" + +#include "../core/slang-io.h" +#include "../core/slang-shared-library.h" +#include "../core/slang-semantic-version.h" +#include "../core/slang-char-util.h" + +#include "slang-include-system.h" +#include "slang-source-loc.h" + +#include "../core/slang-shared-library.h" + +// Enable calling through to `glslang` on +// all platforms. +#ifndef SLANG_ENABLE_GLSLANG_SUPPORT +# define SLANG_ENABLE_GLSLANG_SUPPORT 1 +#endif + +#if SLANG_ENABLE_GLSLANG_SUPPORT +# include "../slang-glslang/slang-glslang.h" +#endif + +namespace Slang +{ + +#if SLANG_ENABLE_GLSLANG_SUPPORT + +class GlslangDownstreamCompiler : public DownstreamCompiler +{ +public: + typedef DownstreamCompiler Super; + + // DownstreamCompiler + virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; + virtual SlangResult disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; + virtual bool isFileBased() SLANG_OVERRIDE { return false; } + + /// Must be called before use + SlangResult init(ISlangSharedLibrary* library); + + GlslangDownstreamCompiler() {} + +protected: + + SlangResult _invoke(glslang_CompileRequest_1_1& request); + + glslang_CompileFunc_1_0 m_compile_1_0 = nullptr; + glslang_CompileFunc_1_1 m_compile_1_1 = nullptr; + + ComPtr<ISlangSharedLibrary> m_sharedLibrary; +}; + +SlangResult GlslangDownstreamCompiler::init(ISlangSharedLibrary* library) +{ + m_compile_1_0 = (glslang_CompileFunc_1_0)library->findFuncByName("glslang_compile"); + m_compile_1_1 = (glslang_CompileFunc_1_1)library->findFuncByName("glslang_compile_1_1"); + + if (m_compile_1_0 == nullptr && m_compile_1_1 == nullptr) + { + return SLANG_FAIL; + } + + m_sharedLibrary = library; + + // It's not clear how to query for a version, but we can get a version number from the header + m_desc = Desc(SLANG_PASS_THROUGH_GLSLANG); + + return SLANG_OK; +} + +SlangResult GlslangDownstreamCompiler::_invoke(glslang_CompileRequest_1_1& request) +{ + int err = 1; + if (m_compile_1_1) + { + err = m_compile_1_1(&request); + } + else if (m_compile_1_0) + { + glslang_CompileRequest_1_0 request_1_0; + request_1_0.set(request); + err = m_compile_1_0(&request_1_0); + } + + return err ? SLANG_FAIL : SLANG_OK; +} + +static SlangResult _parseDiagnosticLine(const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, DownstreamDiagnostic& outDiagnostic) +{ + /* ERROR: tests/diagnostics/syntax-error-intrinsic.slang:13: '@' : unexpected token */ + + if (lineSlices.getCount() < 4) + { + return SLANG_FAIL; + } + { + const UnownedStringSlice severitySlice = lineSlices[0].trim(); + + outDiagnostic.severity = DownstreamDiagnostic::Severity::Error; + if (severitySlice.caseInsensitiveEquals(UnownedStringSlice::fromLiteral("warning"))) + { + outDiagnostic.severity = DownstreamDiagnostic::Severity::Warning; + } + } + + outDiagnostic.filePath = lineSlices[1]; + + SLANG_RETURN_ON_FAIL(StringUtil::parseInt(lineSlices[2], outDiagnostic.fileLine)); + outDiagnostic.text = UnownedStringSlice(lineSlices[3].begin(), line.end()); + return SLANG_OK; +} + + + +SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) +{ + // This compiler doesn't read files, they should be read externally and stored in sourceContents/sourceContentsPath + if (options.sourceFiles.getCount() > 0) + { + return SLANG_FAIL; + } + + if (options.sourceLanguage != SLANG_SOURCE_LANGUAGE_GLSL || options.targetType != SLANG_SPIRV) + { + SLANG_ASSERT(!"Can only compile GLSL to SPIR-V"); + return SLANG_FAIL; + } + + StringBuilder diagnosticOutput; + auto diagnosticOutputFunc = [](void const* data, size_t size, void* userData) + { + (*(StringBuilder*)userData).append((char const*)data, (char const*)data + size); + }; + List<uint8_t> spirv; + auto outputFunc = [](void const* data, size_t size, void* userData) + { + ((List<uint8_t>*)userData)->addRange((uint8_t*)data, size); + }; + + + glslang_CompileRequest_1_1 request; + memset(&request, 0, sizeof(request)); + request.sizeInBytes = sizeof(request); + + request.action = GLSLANG_ACTION_COMPILE_GLSL_TO_SPIRV; + request.sourcePath = options.sourceContentsPath.getBuffer(); + + request.slangStage = options.stage; + + request.inputBegin = options.sourceContents.begin(); + request.inputEnd = options.sourceContents.end(); + + // Find the SPIR-V version if set + SemanticVersion spirvVersion; + for (const auto& capabilityVersion : options.requiredCapabilityVersions) + { + if (capabilityVersion.kind == DownstreamCompiler::CapabilityVersion::Kind::SPIRV) + { + if (capabilityVersion.version > spirvVersion) + { + spirvVersion = capabilityVersion.version; + } + } + } + + request.spirvVersion.major = spirvVersion.m_major; + request.spirvVersion.minor = spirvVersion.m_minor; + request.spirvVersion.patch = spirvVersion.m_patch; + + request.outputFunc = outputFunc; + request.outputUserData = &spirv; + + request.diagnosticFunc = diagnosticOutputFunc; + request.diagnosticUserData = &diagnosticOutput; + + request.optimizationLevel = (unsigned)options.optimizationLevel; + request.debugInfoType = (unsigned)options.debugInfoType; + + const SlangResult invokeResult = _invoke(request); + + DownstreamDiagnostics diagnostics; + + // Set the diagnostics result + diagnostics.result = invokeResult; + + if (SLANG_FAILED(invokeResult)) + { + diagnostics.rawDiagnostics = diagnosticOutput; + + SlangResult diagnosticParseRes = DownstreamDiagnostic::parseColonDelimitedDiagnostics(diagnosticOutput.getUnownedSlice(), 1, _parseDiagnosticLine, diagnostics.diagnostics); + SLANG_UNUSED(diagnosticParseRes); + + diagnostics.requireErrorDiagnostic(); + + outResult = new BlobDownstreamCompileResult(diagnostics, nullptr); + return SLANG_OK; + } + + RefPtr<ListBlob> spirvBlob = ListBlob::moveCreate(spirv); + outResult = new BlobDownstreamCompileResult(diagnostics, spirvBlob); + + return SLANG_OK; +} + +SlangResult GlslangDownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) +{ + // Can only disassemble blobs that are DXBC + if (sourceBlobTarget != SLANG_SPIRV) + { + return SLANG_FAIL; + } + + StringBuilder builder; + + String output; + auto outputFunc = [](void const* data, size_t size, void* userData) + { + (*(StringBuilder*)userData).append((char const*)data, (char const*)data + size); + }; + + glslang_CompileRequest_1_1 request; + memset(&request, 0, sizeof(request)); + request.sizeInBytes = sizeof(request); + + request.action = GLSLANG_ACTION_DISSASSEMBLE_SPIRV; + + request.sourcePath = nullptr; + + request.inputBegin = blob; + request.inputEnd = (char*)blob + blobSize; + + request.outputFunc = outputFunc; + request.outputUserData = &output; + + SLANG_RETURN_ON_FAIL(_invoke(request)); + + ComPtr<ISlangBlob> disassemblyBlob = StringUtil::createStringBlob(builder); + *out = disassemblyBlob.detach(); + + return SLANG_OK; +} + +/* static */SlangResult GlslangDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +{ + ComPtr<ISlangSharedLibrary> library; + +#if SLANG_UNIX_FAMILY + // On unix systems we need to ensure pthread is loaded first. + // TODO(JS): + // There is an argument that this should be performed through the loader.... + ComPtr<ISlangSharedLibrary> pthreadLibrary; + DefaultSharedLibraryLoader::load(loader, path, "pthread", pthreadLibrary.writeRef()); +#endif + + // If the user supplies a path to their preferred version of FXC, + // we just use this. + if (path.getLength() != 0) + { + SLANG_RETURN_ON_FAIL(loader->loadSharedLibrary(path.getBuffer(), library.writeRef())); + } + else + { + SLANG_RETURN_ON_FAIL(loader->loadSharedLibrary("slang-glslang", library.writeRef())); + } + + SLANG_ASSERT(library); + if (!library) + { + return SLANG_FAIL; + } + + RefPtr<GlslangDownstreamCompiler> compiler(new GlslangDownstreamCompiler); + SLANG_RETURN_ON_FAIL(compiler->init(library)); + + set->addCompiler(compiler); + return SLANG_OK; +} + +#else // SLANG_ENABLE_GLSLANG_SUPPORT + +/* static */SlangResult GlslangDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +{ + SLANG_UNUSED(path); + SLANG_UNUSED(loader); + SLANG_UNUSED(set); + return SLANG_E_NOT_AVAILABLE; +} + +#endif // SLANG_ENABLE_GLSLANG_SUPPORT + +} diff --git a/source/compiler-core/slang-glslang-compiler.h b/source/compiler-core/slang-glslang-compiler.h new file mode 100644 index 000000000..917315af8 --- /dev/null +++ b/source/compiler-core/slang-glslang-compiler.h @@ -0,0 +1,18 @@ +#ifndef SLANG_GLSLANG_COMPILER_UTIL_H +#define SLANG_GLSLANG_COMPILER_UTIL_H + +#include "slang-downstream-compiler.h" + +#include "../core/slang-platform.h" + +namespace Slang +{ + +struct GlslangDownstreamCompilerUtil +{ + static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); +}; + +} + +#endif diff --git a/source/compiler-core/slang-nvrtc-compiler.cpp b/source/compiler-core/slang-nvrtc-compiler.cpp index 029f3c71b..f5014acbc 100644 --- a/source/compiler-core/slang-nvrtc-compiler.cpp +++ b/source/compiler-core/slang-nvrtc-compiler.cpp @@ -99,7 +99,6 @@ public: // DownstreamCompiler virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; - virtual ISlangSharedLibrary* getSharedLibrary() SLANG_OVERRIDE { return m_sharedLibrary; } virtual bool isFileBased() SLANG_OVERRIDE { return false; } /// Must be called before use diff --git a/source/slang/slang-check.cpp b/source/slang/slang-check.cpp index a5701aa90..55306a0da 100644 --- a/source/slang/slang-check.cpp +++ b/source/slang/slang-check.cpp @@ -62,18 +62,6 @@ namespace Slang } // anonymous - static FunctionInfo _getFunctionInfo(Session::SharedLibraryFuncType funcType) - { - typedef Session::SharedLibraryFuncType FuncType; - - switch (funcType) - { - case FuncType::Glslang_Compile_1_0: return { "glslang_compile", PassThroughMode::Glslang} ; - case FuncType::Glslang_Compile_1_1: return { "glslang_compile_1_1", PassThroughMode::Glslang} ; - case FuncType::Dxc_DxcCreateInstance: return { "DxcCreateInstance", PassThroughMode::Dxc }; - default: return { nullptr, PassThroughMode::None }; - } - } void Session::_setSharedLibraryLoader(ISlangSharedLibraryLoader* loader) { @@ -88,9 +76,6 @@ namespace Slang m_downstreamCompilers[i].setNull(); } - // Clear all of the functions - ::memset(m_sharedLibraryFunctions, 0, sizeof(m_sharedLibraryFunctions)); - // Set the loader m_sharedLibraryLoader = loader; } @@ -179,47 +164,6 @@ namespace Slang return compiler; } - SlangFuncPtr Session::getSharedLibraryFunc(SharedLibraryFuncType type, DiagnosticSink* sink) - { - if (m_sharedLibraryFunctions[int(type)]) - { - return m_sharedLibraryFunctions[int(type)]; - } - // do we have the library - FunctionInfo info = _getFunctionInfo(type); - if (info.name == nullptr) - { - return nullptr; - } - // Try loading the library - DownstreamCompiler* compiler = getOrLoadDownstreamCompiler(info.compilerType, sink); - if (!compiler) - { - return nullptr; - } - ISlangSharedLibrary* sharedLibrary = compiler->getSharedLibrary(); - if (!sharedLibrary) - { - return nullptr; - } - - // Okay now access the func - SlangFuncPtr func = sharedLibrary->findFuncByName(info.name); - if (!func) - { - if (sink) - { - UnownedStringSlice compilerName = TypeTextUtil::getPassThroughName(SlangPassThrough(info.compilerType)); - sink->diagnose(SourceLoc(), Diagnostics::failedToFindFunctionForCompiler, info.name, compilerName); - } - return nullptr; - } - - // Store in the function cache - m_sharedLibraryFunctions[int(type)] = func; - return func; - } - void checkTranslationUnit( TranslationUnitRequest* translationUnit) { diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 1cce38a94..3850615b4 100755 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -27,15 +27,6 @@ #include "slang-serialize-container.h" // -// Enable calling through to `glslang` on -// all platforms. -#ifndef SLANG_ENABLE_GLSLANG_SUPPORT - #define SLANG_ENABLE_GLSLANG_SUPPORT 1 -#endif - -#if SLANG_ENABLE_GLSLANG_SUPPORT -#include "../slang-glslang/slang-glslang.h" -#endif // Includes to allow us to control console // output when writing assembly dumps. @@ -50,10 +41,6 @@ #pragma warning(disable: 4996) #endif -//#ifdef CreateDirectory -//#undef CreateDirectory -//#endif - namespace Slang { @@ -841,99 +828,15 @@ namespace Slang return *entryPointIndices.begin(); } -#if SLANG_ENABLE_GLSLANG_SUPPORT - SlangResult invokeGLSLCompiler( - BackEndCompileRequest* slangCompileRequest, - glslang_CompileRequest_1_1& request) - { - Session* session = slangCompileRequest->getSession(); - auto sink = slangCompileRequest->getSink(); - auto linkage = slangCompileRequest->getLinkage(); - - auto glslang_compile_1_0 = (glslang_CompileFunc_1_0)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Glslang_Compile_1_0, nullptr); - auto glslang_compile_1_1 = (glslang_CompileFunc_1_1)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Glslang_Compile_1_1, nullptr); - - if(glslang_compile_1_0 == nullptr && glslang_compile_1_1 == nullptr) - { - // Try again and put diagnostic to the sink - session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Glslang_Compile_1_0, sink); - session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Glslang_Compile_1_1, sink); - return SLANG_FAIL; - } - - StringBuilder diagnosticOutput; - - auto diagnosticOutputFunc = [](void const* data, size_t size, void* userData) - { - (*(StringBuilder*)userData).append((char const*)data, (char const*)data + size); - }; - - request.diagnosticFunc = diagnosticOutputFunc; - request.diagnosticUserData = &diagnosticOutput; - - request.optimizationLevel = (unsigned)linkage->optimizationLevel; - request.debugInfoType = (unsigned)linkage->debugInfoLevel; - - int err = 1; - if (glslang_compile_1_1) - { - err = glslang_compile_1_1(&request); - } - else if (glslang_compile_1_0) - { - glslang_CompileRequest_1_0 request_1_0; - request_1_0.set(request); - err = glslang_compile_1_0(&request_1_0); - } - - if (err) - { - reportExternalCompileError("glslang", SLANG_FAIL, diagnosticOutput.getUnownedSlice(), sink); - return SLANG_FAIL; - } - - return SLANG_OK; - } - - SlangResult dissassembleSPIRV( - BackEndCompileRequest* slangRequest, - void const* data, - size_t size, - String& stringOut) - { - stringOut = String(); - - String output; - auto outputFunc = [](void const* data, size_t size, void* userData) - { - (*(String*)userData).append((char const*)data, (char const*)data + size); - }; - - glslang_CompileRequest_1_1 request; - memset(&request, 0, sizeof(request)); - request.sizeInBytes = sizeof(request); - - - request.action = GLSLANG_ACTION_DISSASSEMBLE_SPIRV; - - request.sourcePath = nullptr; - - request.inputBegin = data; - request.inputEnd = (char*)data + size; - - request.outputFunc = outputFunc; - request.outputUserData = &output; - - SLANG_RETURN_ON_FAIL(invokeGLSLCompiler(slangRequest, request)); - - stringOut = output; - return SLANG_OK; - } - - // True if the downstream compiler will need to emit source to make compilation work - // That it may be desirable to not emit source if it is available as is on the file system - // and the downstream compiler accesses files through the file system. - static bool _isEmittedSourceRequired(DownstreamCompiler* compiler, TranslationUnitRequest* translationUnit) + // True if it's best to use 'emitted' source for complication. For a downstream compiler + // that is not file based, this is always ok. + /// + /// If the downstream compiler is file system based, we may want to just use the file that was passed to be compiled. + /// That the downstream compiler can determine if it will then save the file or not based on if it's a match - + /// and generally there will not be a match with emitted source. + /// + /// This test is only used for pass through mode. + static bool _useEmittedSource(DownstreamCompiler* compiler, TranslationUnitRequest* translationUnit) { // We only bother if it's a file based compiler. if (compiler->isFileBased()) @@ -1024,6 +927,13 @@ namespace Slang downstreamCompiler = PassThroughMode::Dxc; break; } + case CodeGenTarget::SPIRV: + { + sourceTarget = CodeGenTarget::GLSL; + sourceLanguage = SourceLanguage::GLSL; + downstreamCompiler = PassThroughMode::Glslang; + break; + } default: break; } @@ -1118,12 +1028,11 @@ namespace Slang sourceTarget = CodeGenTarget(DownstreamCompiler::getCompileTarget(SlangSourceLanguage(sourceLanguage))); // If emitted source is required, emit and set the path - if (_isEmittedSourceRequired(compiler, translationUnit)) + if (_useEmittedSource(compiler, translationUnit)) { // If it's not file based we can set an appropriate path name, and it doesn't matter if it doesn't // exist on the file system - const String originalSourcePath = calcSourcePathForEntryPoints(endToEndReq, entryPointIndices); - options.sourceContentsPath = originalSourcePath; + options.sourceContentsPath = calcSourcePathForEntryPoints(endToEndReq, entryPointIndices); SourceResult source; SLANG_RETURN_ON_FAIL(emitEntryPointsSource(slangRequest, entryPointIndices, targetReq, sourceTarget, endToEndReq, source)); @@ -1131,7 +1040,7 @@ namespace Slang } else { - // Special case if we have a single file, so that we pass the path, and the contents + // Special case if we have a single file, so that we pass the path, and the contents as is. const auto& sourceFiles = translationUnit->getSourceFiles(); SLANG_ASSERT(sourceFiles.getCount() == 1); @@ -1165,6 +1074,14 @@ namespace Slang options.flags |= CompileOptions::Flag::EnableFloat16; } } + else if (GLSLExtensionTracker* tracker = as<GLSLExtensionTracker>(source.extensionTracker.Ptr())) + { + DownstreamCompiler::CapabilityVersion version; + version.kind = DownstreamCompiler::CapabilityVersion::Kind::SPIRV; + version.version = tracker->getSPIRVVersion(); + + options.requiredCapabilityVersions.add(version); + } options.sourceContents = source.source; @@ -1182,7 +1099,8 @@ namespace Slang options.flags &= ~(CompileOptions::Flag::EnableExceptionHandling | CompileOptions::Flag::EnableSecurityChecks); if (downstreamCompiler == PassThroughMode::Fxc || - downstreamCompiler == PassThroughMode::Dxc) + downstreamCompiler == PassThroughMode::Dxc || + downstreamCompiler == PassThroughMode::Glslang) { if (entryPointIndices.getCount() != 1) { @@ -1196,6 +1114,8 @@ namespace Slang auto entryPoint = program->getEntryPoint(entryPointIndex); auto profile = getEffectiveProfile(entryPoint, targetReq); + options.stage = SlangStage(profile.getStage()); + // Set the entry point name options.entryPointName = getText(entryPoint->getName()); @@ -1218,7 +1138,7 @@ namespace Slang } // Only set the profile if the stage is set - if (profile.getStage() != Stage::Unknown) + if (options.stage != SLANG_STAGE_NONE) { options.profileName = GetHLSLProfileName(profile); } @@ -1428,7 +1348,7 @@ namespace Slang } ComPtr<ISlangBlob> dissassemblyBlob; - SLANG_RETURN_ON_FAIL(compiler->dissassemble(SlangCompileTarget(target), data, dataSizeInBytes, dissassemblyBlob.writeRef())); + SLANG_RETURN_ON_FAIL(compiler->disassemble(SlangCompileTarget(target), data, dataSizeInBytes, dissassemblyBlob.writeRef())); *outBlob = dissassemblyBlob.detach(); return SLANG_OK; @@ -1452,111 +1372,86 @@ namespace Slang TargetRequest* targetReq, List<uint8_t>& spirvOut); - SlangResult emitSPIRVForEntryPointsViaGLSL( - ComponentType* program, - BackEndCompileRequest* slangRequest, - const List<Int>& entryPointIndices, - TargetRequest* targetReq, - EndToEndCompileRequest* endToEndReq, - List<uint8_t>& spirvOut) + static CodeGenTarget _getIntermediateTarget(CodeGenTarget target) { - spirvOut.clear(); - - SourceResult source; - - SLANG_RETURN_ON_FAIL(emitEntryPointsSource(slangRequest, entryPointIndices, targetReq, CodeGenTarget::GLSL, endToEndReq, source)); - - const auto& rawGLSL = source.source; - - maybeDumpIntermediate(slangRequest, rawGLSL.getBuffer(), CodeGenTarget::GLSL); - - auto outputFunc = [](void const* data, size_t size, void* userData) - { - ((List<uint8_t>*)userData)->addRange((uint8_t*)data, size); - }; - - const String sourcePath = calcSourcePathForEntryPoint(endToEndReq, assertSingleEntryPoint(entryPointIndices)); - - glslang_CompileRequest_1_1 request; - memset(&request, 0, sizeof(request)); - request.sizeInBytes = sizeof(request); - - request.action = GLSLANG_ACTION_COMPILE_GLSL_TO_SPIRV; - request.sourcePath = sourcePath.getBuffer(); - auto entryPoint = program->getEntryPoint(assertSingleEntryPoint(entryPointIndices)); - request.slangStage = (SlangStage)entryPoint->getStage(); - - request.inputBegin = rawGLSL.begin(); - request.inputEnd = rawGLSL.end(); - - if (GLSLExtensionTracker* tracker = as<GLSLExtensionTracker>(source.extensionTracker.Ptr())) + switch (target) { - request.spirvTargetName = nullptr; - auto spirvLanguageVersion = tracker->getSPIRVVersion(); - - request.spirvVersion.major = spirvLanguageVersion.m_major; - request.spirvVersion.minor = spirvLanguageVersion.m_minor; - request.spirvVersion.patch = spirvLanguageVersion.m_patch; + case CodeGenTarget::DXBytecodeAssembly: return CodeGenTarget::DXBytecode; + case CodeGenTarget::DXILAssembly: return CodeGenTarget::DXIL; + case CodeGenTarget::SPIRVAssembly: return CodeGenTarget::SPIRV; + default: return CodeGenTarget::None; } - - request.outputFunc = outputFunc; - request.outputUserData = &spirvOut; - - SLANG_RETURN_ON_FAIL(invokeGLSLCompiler(slangRequest, request)); - return SLANG_OK; } - SlangResult emitSPIRVForEntryPoints( + /// Function to simplify the logic around emitting, and dissassembling + static SlangResult _emitEntryPoints( ComponentType* program, - BackEndCompileRequest* slangRequest, + BackEndCompileRequest* compileRequest, const List<Int>& entryPointIndices, TargetRequest* targetReq, + CodeGenTarget target, EndToEndCompileRequest* endToEndReq, - List<uint8_t>& spirvOut) + RefPtr<DownstreamCompileResult>& outDownstreamResult) { - if( slangRequest->shouldEmitSPIRVDirectly ) - { - return emitSPIRVForEntryPointsDirectly( - slangRequest, - entryPointIndices, - targetReq, - spirvOut); - } - else + switch (target) { - return emitSPIRVForEntryPointsViaGLSL( - program, - slangRequest, - entryPointIndices, - targetReq, - endToEndReq, - spirvOut); - } - } + case CodeGenTarget::SPIRVAssembly: + case CodeGenTarget::DXBytecodeAssembly: + case CodeGenTarget::DXILAssembly: + { + RefPtr<DownstreamCompileResult> code; - SlangResult emitSPIRVAssemblyForEntryPoints( - ComponentType* program, - BackEndCompileRequest* slangRequest, - const List<Int>& entryPointIndices, - TargetRequest* targetReq, - EndToEndCompileRequest* endToEndReq, - String& assemblyOut) - { - List<uint8_t> spirv; - SLANG_RETURN_ON_FAIL(emitSPIRVForEntryPoints( - program, - slangRequest, - entryPointIndices, - targetReq, - endToEndReq, - spirv)); + // Compile the intermediate target + const CodeGenTarget intermediateTarget = _getIntermediateTarget(target); + SLANG_RETURN_ON_FAIL(_emitEntryPoints(program, compileRequest, entryPointIndices, targetReq, intermediateTarget, endToEndReq, code)); - if (spirv.getCount() == 0) - return SLANG_FAIL; + maybeDumpIntermediate(compileRequest, code, intermediateTarget); + + // Output the disassembly + ComPtr<ISlangBlob> disassemblyBlob; + SLANG_RETURN_ON_FAIL(dissassembleWithDownstream(compileRequest, intermediateTarget, code, disassemblyBlob.writeRef())); + + outDownstreamResult = new BlobDownstreamCompileResult(DownstreamDiagnostics(), disassemblyBlob); + return SLANG_OK; + } + case CodeGenTarget::SPIRV: + case CodeGenTarget::DXIL: + case CodeGenTarget::DXBytecode: + case CodeGenTarget::PTX: + case CodeGenTarget::HostCallable: + case CodeGenTarget::SharedLibrary: + case CodeGenTarget::Executable: + { + RefPtr<DownstreamCompileResult> downstreamResult; - return dissassembleSPIRV(slangRequest, spirv.begin(), spirv.getCount(), assemblyOut); + if (target == CodeGenTarget::SPIRV && compileRequest->shouldEmitSPIRVDirectly) + { + List<uint8_t> spirv; + SLANG_RETURN_ON_FAIL(emitSPIRVForEntryPointsDirectly(compileRequest, entryPointIndices, targetReq, spirv)); + auto spirvBlob = ListBlob::moveCreate(spirv); + downstreamResult = new BlobDownstreamCompileResult(DownstreamDiagnostics(), spirvBlob); + } + else + { + SLANG_RETURN_ON_FAIL(emitWithDownstreamForEntryPoints( + program, + compileRequest, + entryPointIndices, + targetReq, + target, + endToEndReq, + downstreamResult)); + } + + outDownstreamResult = downstreamResult; + return SLANG_OK; + } + + default: break; + } + + return SLANG_FAIL; } -#endif // Do emit logic for a zero or more entry points CompileResult emitEntryPoints( @@ -1572,33 +1467,10 @@ namespace Slang switch (target) { + case CodeGenTarget::SPIRVAssembly: case CodeGenTarget::DXBytecodeAssembly: case CodeGenTarget::DXILAssembly: - { - RefPtr<DownstreamCompileResult> downstreamResult; - - const CodeGenTarget intermediateTarget = (target == CodeGenTarget::DXBytecodeAssembly) ? CodeGenTarget::DXBytecode : CodeGenTarget::DXIL; - - if (SLANG_SUCCEEDED(emitWithDownstreamForEntryPoints( - program, - compileRequest, - entryPointIndices, - targetReq, - intermediateTarget, - endToEndReq, - downstreamResult))) - { - maybeDumpIntermediate(compileRequest, downstreamResult, target); - - ComPtr<ISlangBlob> disassemblyBlob; - if (SLANG_SUCCEEDED(dissassembleWithDownstream(compileRequest, intermediateTarget, downstreamResult, disassemblyBlob.writeRef()))) - { - // Return the disassembly blob - result = CompileResult(disassemblyBlob); - } - } - } - break; + case CodeGenTarget::SPIRV: case CodeGenTarget::DXIL: case CodeGenTarget::DXBytecode: case CodeGenTarget::PTX: @@ -1608,14 +1480,13 @@ namespace Slang { RefPtr<DownstreamCompileResult> downstreamResult; - if (SLANG_SUCCEEDED(emitWithDownstreamForEntryPoints( - program, - compileRequest, - entryPointIndices, - targetReq, - target, - endToEndReq, - downstreamResult))) + if (SLANG_SUCCEEDED(_emitEntryPoints(program, + compileRequest, + entryPointIndices, + targetReq, + target, + endToEndReq, + downstreamResult))) { maybeDumpIntermediate(compileRequest, downstreamResult, target); result = CompileResult(downstreamResult); @@ -1641,40 +1512,6 @@ namespace Slang } break; - case CodeGenTarget::SPIRV: - { - List<uint8_t> code; - if (SLANG_SUCCEEDED(emitSPIRVForEntryPoints( - program, - compileRequest, - entryPointIndices, - targetReq, - endToEndReq, - code))) - { - maybeDumpIntermediate(compileRequest, code.getBuffer(), code.getCount(), target); - result = CompileResult(ListBlob::moveCreate(code)); - } - } - break; - - case CodeGenTarget::SPIRVAssembly: - { - String code; - if (SLANG_SUCCEEDED(emitSPIRVAssemblyForEntryPoints( - program, - compileRequest, - entryPointIndices, - targetReq, - endToEndReq, - code))) - { - maybeDumpIntermediate(compileRequest, code.getBuffer(), target); - result = CompileResult(code); - } - } - break; - case CodeGenTarget::None: // The user requested no output break; @@ -1857,6 +1694,7 @@ namespace Slang switch (targetReq->getTarget()) { + case CodeGenTarget::SPIRVAssembly: case CodeGenTarget::DXBytecodeAssembly: case CodeGenTarget::DXILAssembly: { @@ -1864,6 +1702,7 @@ namespace Slang writeOutputToConsole(writer, disassembly); } break; + case CodeGenTarget::SPIRV: case CodeGenTarget::DXIL: case CodeGenTarget::DXBytecode: { @@ -1876,15 +1715,6 @@ namespace Slang } } break; - - case CodeGenTarget::SPIRV: - { - String assembly; - dissassembleSPIRV(backEndReq, blobData, blobSize, assembly); - writeOutputToConsole(writer, assembly); - } - break; - case CodeGenTarget::PTX: // For now we just dump PTX out as hex @@ -2393,6 +2223,30 @@ namespace Slang } } + static const char* _getTargetExtension(CodeGenTarget target) + { + switch (target) + { + case CodeGenTarget::HLSL: return ".hlsl"; + case CodeGenTarget::GLSL: return ".glsl"; + case CodeGenTarget::SPIRV: return ".spv"; + case CodeGenTarget::DXBytecode: return ".dxbc"; + case CodeGenTarget::DXIL: return ".dxil"; + case CodeGenTarget::SPIRVAssembly: return ".spv.asm"; + case CodeGenTarget::DXBytecodeAssembly: return ".dxbc.asm"; + case CodeGenTarget::DXILAssembly: return ".dxil.asm"; + case CodeGenTarget::CSource: return ".c"; + case CodeGenTarget::CPPSource: return ".cpp"; + // What these should be called is target specific, but just use these exts to make clear for now + // for now + case CodeGenTarget::Executable: return ".exe"; + case CodeGenTarget::HostCallable: + case CodeGenTarget::SharedLibrary: return ".shared-lib"; + default: break; + } + return nullptr; + } + void maybeDumpIntermediate( BackEndCompileRequest* compileRequest, void const* data, @@ -2403,84 +2257,53 @@ namespace Slang return; switch (target) - { - default: - break; - - case CodeGenTarget::HLSL: - dumpIntermediateText(compileRequest, data, size, ".hlsl"); - break; - - case CodeGenTarget::GLSL: - dumpIntermediateText(compileRequest, data, size, ".glsl"); - break; - - case CodeGenTarget::SPIRVAssembly: - dumpIntermediateText(compileRequest, data, size, ".spv.asm"); - break; + { + case CodeGenTarget::CPPSource: + case CodeGenTarget::CSource: + case CodeGenTarget::DXILAssembly: + case CodeGenTarget::DXBytecodeAssembly: + case CodeGenTarget::SPIRVAssembly: + case CodeGenTarget::GLSL: + case CodeGenTarget::HLSL: + { + dumpIntermediateText(compileRequest, data, size, _getTargetExtension(target)); + break; + } #if 0 - case CodeGenTarget::SlangIRAssembly: - dumpIntermediateText(compileRequest, data, size, ".slang-ir.asm"); - break; -#endif - - case CodeGenTarget::SPIRV: - dumpIntermediateBinary(compileRequest, data, size, ".spv"); + case CodeGenTarget::SlangIRAssembly: { - String spirvAssembly; - dissassembleSPIRV(compileRequest, data, size, spirvAssembly); - dumpIntermediateText(compileRequest, spirvAssembly.begin(), spirvAssembly.getLength(), ".spv.asm"); + dumpIntermediateText(compileRequest, data, size, ".slang-ir.asm"); + break; } - break; - - case CodeGenTarget::DXBytecodeAssembly: - dumpIntermediateText(compileRequest, data, size, ".dxbc.asm"); - break; +#endif - case CodeGenTarget::DXBytecode: - dumpIntermediateBinary(compileRequest, data, size, ".dxbc"); + case CodeGenTarget::DXIL: + case CodeGenTarget::DXBytecode: + case CodeGenTarget::SPIRV: { + const char* ext = _getTargetExtension(target); + SLANG_ASSERT(ext); + + dumpIntermediateBinary(compileRequest, data, size, ext); ComPtr<ISlangBlob> disassemblyBlob; if (SLANG_SUCCEEDED(dissassembleWithDownstream(compileRequest, target, data, size, disassemblyBlob.writeRef()))) { - dumpIntermediateText(compileRequest, disassemblyBlob->getBufferPointer(), disassemblyBlob->getBufferSize(), ".dxbc.asm"); + StringBuilder buf; + buf << ext << ".asm"; + dumpIntermediateText(compileRequest, disassemblyBlob->getBufferPointer(), disassemblyBlob->getBufferSize(), buf.getBuffer()); } + break; } - break; - - case CodeGenTarget::DXILAssembly: - dumpIntermediateText(compileRequest, data, size, ".dxil.asm"); - break; - case CodeGenTarget::DXIL: - dumpIntermediateBinary(compileRequest, data, size, ".dxil"); + case CodeGenTarget::HostCallable: + case CodeGenTarget::SharedLibrary: + case CodeGenTarget::Executable: { - String dxilAssembly; - ComPtr<ISlangBlob> disassemblyBlob; - if (SLANG_SUCCEEDED(dissassembleWithDownstream(compileRequest, target, data, size, disassemblyBlob.writeRef()))) - { - dumpIntermediateText(compileRequest, disassemblyBlob->getBufferPointer(), disassemblyBlob->getBufferSize(), ".dxil.asm"); - } + dumpIntermediateBinary(compileRequest, data, size, _getTargetExtension(target)); + break; } - break; - - case CodeGenTarget::CSource: - dumpIntermediateText(compileRequest, data, size, ".c"); - break; - case CodeGenTarget::CPPSource: - dumpIntermediateText(compileRequest, data, size, ".cpp"); - break; - - case CodeGenTarget::Executable: - // What these should be called is target specific, but just use these exts to make clear for now - // for now - dumpIntermediateBinary(compileRequest, data, size, ".exe"); - break; - case CodeGenTarget::HostCallable: - case CodeGenTarget::SharedLibrary: - dumpIntermediateBinary(compileRequest, data, size, ".shared-lib"); - break; + default: break; } } diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 52f3b9465..08eb93b41 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -2226,16 +2226,6 @@ namespace Slang /// Get the default compiler for a language DownstreamCompiler* getDefaultDownstreamCompiler(SourceLanguage sourceLanguage); - enum class SharedLibraryFuncType - { - Glslang_Compile_1_0, - Glslang_Compile_1_1, - Dxc_DxcCreateInstance, - CountOf, - }; - - // - RefPtr<Scope> baseLanguageScope; RefPtr<Scope> coreLanguageScope; RefPtr<Scope> hlslLanguageScope; @@ -2289,8 +2279,6 @@ namespace Slang /// Will unload the specified shared library if it's currently loaded void resetDownstreamCompiler(PassThroughMode type); - SlangFuncPtr getSharedLibraryFunc(SharedLibraryFuncType type, DiagnosticSink* sink); - /// Get the prelude associated with the language const String& getPreludeForLanguage(SourceLanguage language) { return m_languagePreludes[int(language)]; } @@ -2307,8 +2295,6 @@ namespace Slang ComPtr<ISlangSharedLibraryLoader> m_sharedLibraryLoader; ///< The shared library loader (never null) - SlangFuncPtr m_sharedLibraryFunctions[int(SharedLibraryFuncType::CountOf)]; ///< Functions from shared libraries - int m_downstreamCompilerInitialized = 0; RefPtr<DownstreamCompilerSet> m_downstreamCompilerSet; ///< Information about all available downstream compilers. diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index ef5a94501..668b42b2a 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -104,8 +104,6 @@ DIAGNOSTIC( 50, Error, duplicateTargets, "the target '$0' has been specified DIAGNOSTIC( 60, Error, cannotDeduceOutputFormatFromPath, "cannot infer an output format from the output path '$0'") DIAGNOSTIC( 61, Error, cannotMatchOutputFileToTarget, "no specified '-target' option matches the output path '$0', which implies the '$1' format") -DIAGNOSTIC( 62, Error, failedToFindFunctionForCompiler, "failed to find function '$0' for downstream compiler '$1'") - 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'") @@ -540,7 +538,6 @@ DIAGNOSTIC(52000, Error, multiLevelBreakUnsupported, "control flow appears to re DIAGNOSTIC(52001, Warning, dxilNotFound, "dxil shared library not found, so 'dxc' output cannot be signed! Shader code will not be runnable in non-development environments.") DIAGNOSTIC(52002, Error, passThroughCompilerNotFound, "Could not find a suitable pass-through compiler for '$0'.") -DIAGNOSTIC(52003, Error, cppCompilerNotFound, "Could not find a suitable C/C++ compiler for '$0'.") DIAGNOSTIC(52004, Error, unableToWriteFile, "Unable to write file '$0'") DIAGNOSTIC(52005, Error, unableToReadFile, "Unable to read file '$0'") diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index d315570f5..ab717536c 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -125,9 +125,7 @@ void Session::init() getNamePool()->setRootNamePool(getRootNamePool()); m_sharedLibraryLoader = DefaultSharedLibraryLoader::getSingleton(); - // Set all the shared library function pointers to nullptr - ::memset(m_sharedLibraryFunctions, 0, sizeof(m_sharedLibraryFunctions)); - + // Set up shared AST builder m_sharedASTBuilder = new SharedASTBuilder; m_sharedASTBuilder->init(this); diff --git a/tools/slang-test/parse-diagnostic-util.cpp b/tools/slang-test/parse-diagnostic-util.cpp index c3c1669f1..552a0924b 100644 --- a/tools/slang-test/parse-diagnostic-util.cpp +++ b/tools/slang-test/parse-diagnostic-util.cpp @@ -15,30 +15,7 @@ using namespace Slang; -/* static */ SlangResult ParseDiagnosticUtil::parseGlslangLine(const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, DownstreamDiagnostic& outDiagnostic) -{ - /* ERROR: tests/diagnostics/syntax-error-intrinsic.slang:13: '@' : unexpected token */ - - if (lineSlices.getCount() < 4) - { - return SLANG_FAIL; - } - { - const UnownedStringSlice severitySlice = lineSlices[0].trim(); - outDiagnostic.severity = DownstreamDiagnostic::Severity::Error; - if (severitySlice.caseInsensitiveEquals(UnownedStringSlice::fromLiteral("warning"))) - { - outDiagnostic.severity = DownstreamDiagnostic::Severity::Warning; - } - } - - outDiagnostic.filePath = lineSlices[1]; - - SLANG_RETURN_ON_FAIL(StringUtil::parseInt(lineSlices[2], outDiagnostic.fileLine)); - outDiagnostic.text = UnownedStringSlice(lineSlices[3].begin(), line.end()); - return SLANG_OK; -} /* static */SlangResult ParseDiagnosticUtil::parseGenericLine(const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, DownstreamDiagnostic& outDiagnostic) { @@ -183,8 +160,8 @@ static bool _isSlangDiagnostic(const UnownedStringSlice& line) tests/diagnostics/accessors.slang(11): error 31101: accessors other than 'set' must not have parameters */ - // Need to determine where the path is located, and that depends on the compiler - const Int pathIndex = (compilerIdentity == CompilerIdentity::make(SLANG_PASS_THROUGH_GLSLANG)) ? 1 : 0; + // The index where the path starts + const Int pathIndex = 0; // Now we want to fix up a path as might have drive letter, and therefore : // If this is the situation then we need to have a slice after the one at the index @@ -254,19 +231,12 @@ static SlangResult _findDownstreamCompiler(const UnownedStringSlice& slice, Slan /* static */ParseDiagnosticUtil::LineParser ParseDiagnosticUtil::getLineParser(const CompilerIdentity& compilerIdentity) { - if (compilerIdentity.m_type == CompilerIdentity::Slang) - { - return &parseSlangLine; - } - else if (compilerIdentity.m_type == CompilerIdentity::DownstreamCompiler) + switch (compilerIdentity.m_type) { - switch (compilerIdentity.m_downstreamCompiler) - { - case SLANG_PASS_THROUGH_GLSLANG: return &parseGlslangLine; - default: return &parseGenericLine; - } + case CompilerIdentity::Slang: return &parseSlangLine; + case CompilerIdentity::DownstreamCompiler: return &parseGenericLine; + default: return nullptr; } - return nullptr; } static bool _isWhitespace(const UnownedStringSlice& slice) @@ -290,16 +260,10 @@ static bool _isWhitespace(const UnownedStringSlice& slice) return SLANG_OK; } - // TODO(JS): - // As it stands output of downstream compilers isn't standardized. This can be improved upon - and if so - // we should have a function that will parse the standardized output - // Currently dxc/fxc/glslang, use a different downstream path - CompilerIdentity compilerIdentity; SLANG_RETURN_ON_FAIL(ParseDiagnosticUtil::identifyCompiler(inText, compilerIdentity)); UnownedStringSlice linePrefix; - if (compilerIdentity.m_type == CompilerIdentity::Type::DownstreamCompiler) { linePrefix = TypeTextUtil::getPassThroughAsHumanText(compilerIdentity.m_downstreamCompiler); diff --git a/tools/slang-test/parse-diagnostic-util.h b/tools/slang-test/parse-diagnostic-util.h index 4c4aaa75c..b9f81bfe8 100644 --- a/tools/slang-test/parse-diagnostic-util.h +++ b/tools/slang-test/parse-diagnostic-util.h @@ -60,12 +60,6 @@ struct ParseDiagnosticUtil /// Given a compiler identity returns a line parsing function. static LineParser getLineParser(const CompilerIdentity& compilerIdentity); - /// For DXC lines - static SlangResult parseDXCLine(const Slang::UnownedStringSlice& line, Slang::List<Slang::UnownedStringSlice>& lineSlices, Slang::DownstreamDiagnostic& outDiagnostic); - - /// For GLSL lines - static SlangResult parseGlslangLine(const Slang::UnownedStringSlice& line, Slang::List<Slang::UnownedStringSlice>& lineSlices, Slang::DownstreamDiagnostic& outDiagnostic); - /// For a 'generic' (as in uses DownstreamCompiler mechanism) line parsing static SlangResult parseGenericLine(const Slang::UnownedStringSlice& line, Slang::List<Slang::UnownedStringSlice>& lineSlices, Slang::DownstreamDiagnostic& outDiagnostic); |
