diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2021-05-14 18:38:08 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-14 18:38:08 -0400 |
| commit | 1856b8ad85266ed66985b42bd2321a35f8573a00 (patch) | |
| tree | 0b978ac765741c3a7b29493608d96915013fb571 /source | |
| parent | d4316c88457a32f1169b2d7d82053ccbc05fa7ed (diff) | |
DXC as DownstreamCompiler (#1845)
* #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.
Diffstat (limited to 'source')
| -rw-r--r-- | source/compiler-core/slang-downstream-compiler.cpp | 41 | ||||
| -rw-r--r-- | source/compiler-core/slang-downstream-compiler.h | 13 | ||||
| -rw-r--r-- | source/compiler-core/slang-dxc-compiler.cpp | 489 | ||||
| -rw-r--r-- | source/compiler-core/slang-dxc-compiler.h | 18 | ||||
| -rw-r--r-- | source/compiler-core/slang-fxc-compiler.cpp | 5 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.cpp | 238 | ||||
| -rwxr-xr-x | source/slang/slang-dxc-support.cpp | 367 |
7 files changed, 632 insertions, 539 deletions
diff --git a/source/compiler-core/slang-downstream-compiler.cpp b/source/compiler-core/slang-downstream-compiler.cpp index d89434896..9721b45d3 100644 --- a/source/compiler-core/slang-downstream-compiler.cpp +++ b/source/compiler-core/slang-downstream-compiler.cpp @@ -19,6 +19,7 @@ #include "slang-gcc-compiler-util.h" #include "slang-nvrtc-compiler.h" #include "slang-fxc-compiler.h" +#include "slang-dxc-compiler.h" namespace Slang { @@ -158,6 +159,26 @@ Index DownstreamDiagnostics::getCountBySeverity(Diagnostic::Severity severity) c return count; } +void DownstreamDiagnostics::requireErrorDiagnostic() +{ + // If we find an error, we don't need to add a generic diagnostic + for (const auto& msg : diagnostics) + { + if (Index(msg.severity) >= Index(DownstreamDiagnostic::Severity::Error)) + { + return; + } + } + + DownstreamDiagnostic diagnostic; + diagnostic.reset(); + diagnostic.severity = DownstreamDiagnostic::Severity::Error; + diagnostic.text = "Generic error during compilation"; + + // Add the diagnostic + diagnostics.add(diagnostic); +} + Int DownstreamDiagnostics::countByStage(Diagnostic::Stage stage, Index counts[Int(Diagnostic::Severity::CountOf)]) const { Int count = 0; @@ -655,24 +676,6 @@ const DownstreamCompiler::Desc& DownstreamCompilerUtil::getCompiledWithDesc() } } -static SlangResult _locateDXCCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) -{ - // First try dxil, so it's loaded from the same path if it's there - ComPtr<ISlangSharedLibrary> dxil; - DefaultSharedLibraryLoader::load(loader, path, "dxil", dxil.writeRef()); - - ComPtr<ISlangSharedLibrary> sharedLibrary; - if (SLANG_SUCCEEDED(DefaultSharedLibraryLoader::load(loader, path, "dxcompiler", sharedLibrary.writeRef()))) - { - // Can we determine the version? - DownstreamCompiler::Desc desc(SLANG_PASS_THROUGH_DXC); - RefPtr<DownstreamCompiler> compiler(new SharedLibraryDownstreamCompiler(desc, sharedLibrary)); - - set->addCompiler(compiler); - } - return SLANG_OK; -} - static SlangResult _locateGlslangCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) { #if SLANG_UNIX_FAMILY @@ -697,7 +700,7 @@ static SlangResult _locateGlslangCompilers(const String& path, ISlangSharedLibra outFuncs[int(SLANG_PASS_THROUGH_CLANG)] = &GCCDownstreamCompilerUtil::locateClangCompilers; outFuncs[int(SLANG_PASS_THROUGH_GCC)] = &GCCDownstreamCompilerUtil::locateGCCCompilers; outFuncs[int(SLANG_PASS_THROUGH_NVRTC)] = &NVRTCDownstreamCompilerUtil::locateCompilers; - outFuncs[int(SLANG_PASS_THROUGH_DXC)] = &_locateDXCCompilers; + outFuncs[int(SLANG_PASS_THROUGH_DXC)] = &DXCDownstreamCompilerUtil::locateCompilers; outFuncs[int(SLANG_PASS_THROUGH_FXC)] = &FXCDownstreamCompilerUtil::locateCompilers; outFuncs[int(SLANG_PASS_THROUGH_GLSLANG)] = &_locateGlslangCompilers; } diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h index b7f7b0cde..b3af8a506 100644 --- a/source/compiler-core/slang-downstream-compiler.h +++ b/source/compiler-core/slang-downstream-compiler.h @@ -93,6 +93,9 @@ struct DownstreamDiagnostics /// Add a note void addNote(const UnownedStringSlice& in); + /// If there are no error diagnostics, adds a generic error diagnostic + void requireErrorDiagnostic(); + static void addNote(const UnownedStringSlice& in, List<DownstreamDiagnostic>& ioDiagnostics); String rawDiagnostics; @@ -219,15 +222,6 @@ public: Precise, }; -#if 0 - enum TargetType - { - Executable, ///< Produce an executable - SharedLibrary, ///< Produce a shared library object/dll - Object, ///< Produce an object file - }; -#endif - enum PipelineType { Unknown, @@ -272,6 +266,7 @@ public: SlangSourceLanguage sourceLanguage = SLANG_SOURCE_LANGUAGE_CPP; FloatingPointMode floatingPointMode = FloatingPointMode::Default; PipelineType pipelineType = PipelineType::Unknown; + SlangMatrixLayoutMode matrixLayout = SLANG_MATRIX_LAYOUT_MODE_UNKNOWN; Flags flags = Flag::EnableExceptionHandling; diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp new file mode 100644 index 000000000..281b6173d --- /dev/null +++ b/source/compiler-core/slang-dxc-compiler.cpp @@ -0,0 +1,489 @@ +// slang-dxc-compiler.cpp +#include "slang-dxc-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 `dxc` to +// generate code on Windows. +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <Windows.h> +# include <Unknwn.h> +# include "../../external/dxc/dxcapi.h" +# undef WIN32_LEAN_AND_MEAN +# undef NOMINMAX + +# ifndef SLANG_ENABLE_DXIL_SUPPORT +# define SLANG_ENABLE_DXIL_SUPPORT 1 +# endif +#endif + +#ifndef SLANG_ENABLE_DXIL_SUPPORT +# define SLANG_ENABLE_DXIL_SUPPORT 0 +#endif + +namespace Slang +{ + +#if SLANG_ENABLE_DXIL_SUPPORT + +static UnownedStringSlice _getSlice(IDxcBlob* blob) { return StringUtil::getSlice((ISlangBlob*)blob); } + +// IDxcIncludeHandler +// 7f61fc7d-950d-467f-b3e3-3c02fb49187c +static const Guid IID_IDxcIncludeHandler = { 0x7f61fc7d, 0x950d, 0x467f, { 0x3c, 0x02, 0xfb, 0x49, 0x18, 0x7c } }; + +class DxcIncludeHandler : public IDxcIncludeHandler +{ +public: + // Implement IUnknown + SLANG_NO_THROW HRESULT SLANG_MCALL QueryInterface(const IID& uuid, void** out) + { + ISlangUnknown* intf = getInterface(reinterpret_cast<const Guid&>(uuid)); + if (intf) + { + *out = intf; + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; + } + SLANG_NO_THROW ULONG SLANG_MCALL AddRef() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW ULONG SLANG_MCALL Release() SLANG_OVERRIDE { return 1; } + + // Implement IDxcIncludeHandler + virtual HRESULT SLANG_MCALL LoadSource(LPCWSTR inFilename, IDxcBlob** outSource) SLANG_OVERRIDE + { + // Hmm DXC does something a bit odd - when it sees a path, it just passes that in with ./ in front!! + // NOTE! It doesn't make any difference if it is "" or <> quoted. + + // So we just do a work around where we strip if we see a path starting with ./ + String filePath = String::fromWString(inFilename); + + // If it starts with ./ then attempt to strip it + if (filePath.startsWith("./")) + { + String remaining(filePath.subString(2, filePath.getLength() - 2)); + + // Okay if we strip ./ and what we have is absolute, then it's the absolute path that we care about, + // otherwise we just leave as is. + if (Path::isAbsolute(remaining)) + { + filePath = remaining; + } + } + + ComPtr<ISlangBlob> blob; + PathInfo pathInfo; + SlangResult res = m_system.findAndLoadFile(filePath, String(), pathInfo, blob); + + // NOTE! This only works because ISlangBlob is *binary compatible* with IDxcBlob, if either + // change things could go boom + *outSource = (IDxcBlob*)blob.detach(); + return res; + } + + DxcIncludeHandler(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager = nullptr) : + m_system(searchDirectories, fileSystemExt, sourceManager) + { + } + +protected: + + // Used by QueryInterface for casting + ISlangUnknown* getInterface(const Guid& guid) + { + if (guid == ISlangUnknown::getTypeGuid() || guid == IID_IDxcIncludeHandler) + { + return (ISlangUnknown*)(static_cast<IDxcIncludeHandler*>(this)); + } + return nullptr; + } + + IncludeSystem m_system; +}; + +class DXCDownstreamCompiler : public DownstreamCompiler +{ +public: + typedef DownstreamCompiler Super; + + // 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 bool isFileBased() SLANG_OVERRIDE { return false; } + + /// Must be called before use + SlangResult init(ISlangSharedLibrary* library); + + DXCDownstreamCompiler() {} + +protected: + + DxcCreateInstanceProc m_createInstance = nullptr; + ComPtr<ISlangSharedLibrary> m_sharedLibrary; +}; + +SlangResult DXCDownstreamCompiler::init(ISlangSharedLibrary* library) +{ + m_sharedLibrary = library; + + m_createInstance = (DxcCreateInstanceProc)library->findFuncByName("DxcCreateInstance"); + if (!m_createInstance) + { + return SLANG_FAIL; + } + + m_desc = Desc(SLANG_PASS_THROUGH_DXC); + + return SLANG_OK; +} + +static SlangResult _parseDiagnosticLine(const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, DownstreamDiagnostic& outDiagnostic) +{ + /* tests/diagnostics/syntax-error-intrinsic.slang:14:2: error: expected expression */ + if (lineSlices.getCount() < 5) + { + return SLANG_FAIL; + } + + outDiagnostic.filePath = lineSlices[0]; + + SLANG_RETURN_ON_FAIL(StringUtil::parseInt(lineSlices[1], outDiagnostic.fileLine)); + + //Int lineCol; + //SLANG_RETURN_ON_FAIL(StringUtil::parseInt(lineSlices[2], lineCol)); + + UnownedStringSlice severitySlice = lineSlices[3].trim(); + + outDiagnostic.severity = DownstreamDiagnostic::Severity::Error; + if (severitySlice == UnownedStringSlice::fromLiteral("warning")) + { + outDiagnostic.severity = DownstreamDiagnostic::Severity::Warning; + } + + // The rest of the line + outDiagnostic.text = UnownedStringSlice(lineSlices[4].begin(), line.end()); + 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 + if (options.sourceFiles.getCount() > 0) + { + return SLANG_FAIL; + } + + if (options.sourceLanguage != SLANG_SOURCE_LANGUAGE_HLSL || options.targetType != SLANG_DXIL) + { + SLANG_ASSERT(!"Can only compile HLSL to DXIL"); + return SLANG_FAIL; + } + + ComPtr<IDxcCompiler> dxcCompiler; + SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcCompiler, __uuidof(dxcCompiler), (LPVOID*)dxcCompiler.writeRef())); + ComPtr<IDxcLibrary> dxcLibrary; + SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*)dxcLibrary.writeRef())); + + const auto& hlslSource = options.sourceContents; + + // Create blob from the string + ComPtr<IDxcBlobEncoding> dxcSourceBlob; + SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned( + (LPBYTE)hlslSource.getBuffer(), + (UINT32)hlslSource.getLength(), + 0, + dxcSourceBlob.writeRef())); + + WCHAR const* args[16]; + UINT32 argCount = 0; + + // TODO: deal with + bool treatWarningsAsErrors = false; + if (treatWarningsAsErrors) + { + args[argCount++] = L"-WX"; + } + + switch (options.matrixLayout) + { + default: + break; + + case SLANG_MATRIX_LAYOUT_ROW_MAJOR: + args[argCount++] = L"-Zpr"; + break; + } + + switch (options.floatingPointMode) + { + default: + break; + + case FloatingPointMode::Precise: + args[argCount++] = L"-Gis"; // "force IEEE strictness" + break; + } + + switch (options.optimizationLevel) + { + default: + break; + + case OptimizationLevel::None: args[argCount++] = L"-Od"; break; + case OptimizationLevel::Default: args[argCount++] = L"-O1"; break; + case OptimizationLevel::High: args[argCount++] = L"-O2"; break; + case OptimizationLevel::Maximal: args[argCount++] = L"-O3"; break; + } + + switch (options.debugInfoType) + { + case DebugInfoType::None: + break; + + default: + args[argCount++] = L"-Zi"; + break; + } + + // Slang strives to produce correct code, and by default + // we do not show the user warnings produced by a downstream + // compiler. When the downstream compiler *does* produce an + // error, then we dump its entire diagnostic log, which can + // include many distracting spurious warnings that have nothing + // to do with the user's code, and just relate to the idiomatic + // way that Slang outputs HLSL. + // + // It would be nice to use fine-grained flags to disable specific + // warnings here, so that we keep ourselves honest (e.g., only + // use `-Wno-parentheses` to eliminate that class of false positives), + // but alas dxc doesn't support these options even though they + // work on mainline Clang. Thus the only option we have available + // is the big hammer of turning off *all* warnings coming from dxc. + // + args[argCount++] = L"-no-warnings"; + + OSString wideEntryPointName = options.entryPointName.toWString(); + OSString wideProfileName = options.profileName.toWString(); + + if (options.flags & CompileOptions::Flag::EnableFloat16) + { + args[argCount++] = L"-enable-16bit-types"; + } + + SearchDirectoryList searchDirectories; + for (const auto& includePath : options.includePaths) + { + searchDirectories.searchDirectories.add(includePath); + } + + OSString sourcePath = options.sourceContentsPath.toWString(); + + DxcIncludeHandler includeHandler(&searchDirectories, options.fileSystemExt, options.sourceManager); + + ComPtr<IDxcOperationResult> dxcResult; + SLANG_RETURN_ON_FAIL(dxcCompiler->Compile(dxcSourceBlob, + sourcePath.begin(), + wideEntryPointName.begin(), + wideProfileName.begin(), + args, + argCount, + nullptr, // `#define`s + 0, // `#define` count + &includeHandler, // `#include` handler + dxcResult.writeRef())); + + // Retrieve result. + HRESULT resultCode = S_OK; + SLANG_RETURN_ON_FAIL(dxcResult->GetStatus(&resultCode)); + + // Note: it seems like the dxcompiler interface + // doesn't support querying diagnostic output + // *unless* the compile failed (no way to get + // warnings out!?). + + DownstreamDiagnostics diagnostics; + diagnostics.result = resultCode; + + // Try getting the error/diagnostics blob + ComPtr<IDxcBlobEncoding> dxcErrorBlob; + dxcResult->GetErrorBuffer(dxcErrorBlob.writeRef()); + + if (dxcErrorBlob) + { + const UnownedStringSlice diagnosticsSlice = _getSlice(dxcErrorBlob); + if (diagnosticsSlice.getLength()) + { + diagnostics.rawDiagnostics = String(diagnosticsSlice); + + SlangResult diagnosticParseRes = _parseDiagnostics(diagnosticsSlice, diagnostics.diagnostics); + SLANG_UNUSED(diagnosticParseRes); + SLANG_ASSERT(SLANG_SUCCEEDED(diagnosticParseRes)); + } + } + + ComPtr<IDxcBlob> dxcResultBlob; + + // If it failed, make sure we have an error in the diagnostics + if (SLANG_FAILED(resultCode)) + { + // In case the parsing failed, we still have an error -> so require there is one in the diagnostics + diagnostics.requireErrorDiagnostic(); + } + else + { + // Okay, the compile supposedly succeeded, so we + // just need to grab the buffer with the output DXIL. + SLANG_RETURN_ON_FAIL(dxcResult->GetResult(dxcResultBlob.writeRef())); + } + + outResult = new BlobDownstreamCompileResult(diagnostics, (ISlangBlob*)dxcResultBlob.get()); + return SLANG_OK; +} + +SlangResult DXCDownstreamCompiler::dissassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) +{ + // Can only disassemble blobs that are DXIL + if (sourceBlobTarget != SLANG_DXIL) + { + return SLANG_FAIL; + } + + ComPtr<IDxcCompiler> dxcCompiler; + SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcCompiler, __uuidof(dxcCompiler), (LPVOID*)dxcCompiler.writeRef())); + ComPtr<IDxcLibrary> dxcLibrary; + SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*)dxcLibrary.writeRef())); + + // Create blob from the input data + ComPtr<IDxcBlobEncoding> dxcSourceBlob; + SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned((LPBYTE)blob, (UINT32)blobSize, 0, dxcSourceBlob.writeRef())); + + ComPtr<IDxcBlobEncoding> dxcResultBlob; + SLANG_RETURN_ON_FAIL(dxcCompiler->Disassemble(dxcSourceBlob, dxcResultBlob.writeRef())); + + // Is compatible with ISlangBlob + *out = (ISlangBlob*)dxcResultBlob.detach(); + return SLANG_OK; +} + +/* static */SlangResult DXCDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +{ + ComPtr<ISlangSharedLibrary> library; + + // If the user supplies a path to their preferred version of DXC + // we just use this. + if (path.getLength() != 0) + { + // We *assume* path is the path to d3dcompiler. + ComPtr<ISlangSharedLibrary> dxil; + + // Attempt to load dxil from same path that d3dcompiler is located + const String parentPath = Path::getParentDirectory(path); + if (parentPath.getLength()) + { + String dxilPath = Path::combine(parentPath, "dxil"); + // Try to load dxil along this path first + // If it fails - then DXC may load from a different place and thats ok. + loader->loadSharedLibrary(dxilPath.getBuffer(), dxil.writeRef()); + } + + SLANG_RETURN_ON_FAIL(loader->loadSharedLibrary(path.getBuffer(), library.writeRef())); + } + else + { + SLANG_RETURN_ON_FAIL(loader->loadSharedLibrary("dxcompiler", library.writeRef())); + } + + SLANG_ASSERT(library); + if (!library) + { + return SLANG_FAIL; + } + + RefPtr<DXCDownstreamCompiler> compiler(new DXCDownstreamCompiler); + SLANG_RETURN_ON_FAIL(compiler->init(library)); + + set->addCompiler(compiler); + return SLANG_OK; +} + +#else // SLANG_ENABLE_DXIL_SUPPORT + +/* static */SlangResult DXCDownstreamCompilerUtil::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_DXIL_SUPPORT + +} diff --git a/source/compiler-core/slang-dxc-compiler.h b/source/compiler-core/slang-dxc-compiler.h new file mode 100644 index 000000000..a4e8eb4d7 --- /dev/null +++ b/source/compiler-core/slang-dxc-compiler.h @@ -0,0 +1,18 @@ +#ifndef SLANG_DXC_COMPILER_UTIL_H +#define SLANG_DXC_COMPILER_UTIL_H + +#include "slang-downstream-compiler.h" + +#include "../core/slang-platform.h" + +namespace Slang +{ + +struct DXCDownstreamCompilerUtil +{ + static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); +}; + +} + +#endif diff --git a/source/compiler-core/slang-fxc-compiler.cpp b/source/compiler-core/slang-fxc-compiler.cpp index 8e190bbca..60d50a13e 100644 --- a/source/compiler-core/slang-fxc-compiler.cpp +++ b/source/compiler-core/slang-fxc-compiler.cpp @@ -348,7 +348,10 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr { UnownedStringSlice diagnosticText = _getSlice(diagnosticsBlob); diagnostics.rawDiagnostics = diagnosticText; - _parseDiagnostics(diagnosticText, diagnostics.diagnostics); + + SlangResult diagnosticParseRes = _parseDiagnostics(diagnosticText, diagnostics.diagnostics); + SLANG_UNUSED(diagnosticParseRes); + SLANG_ASSERT(SLANG_SUCCEEDED(diagnosticParseRes)); } // ID3DBlob is compatible with ISlangBlob, so just cast away... diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 22e5bb61e..1cce38a94 100755 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -25,25 +25,7 @@ #include "slang-emit-cuda.h" #include "slang-serialize-container.h" - -// Enable calling through to `fxc` or `dxc` to -// generate code on Windows. -#ifdef _WIN32 - #define WIN32_LEAN_AND_MEAN - #define NOMINMAX - #include <Windows.h> - #undef WIN32_LEAN_AND_MEAN - #undef NOMINMAX - #include <d3dcompiler.h> - #ifndef SLANG_ENABLE_DXIL_SUPPORT - #define SLANG_ENABLE_DXIL_SUPPORT 1 - #endif -#endif // -// Otherwise, don't enable DXIL by default: -#ifndef SLANG_ENABLE_DXIL_SUPPORT - #define SLANG_ENABLE_DXIL_SUPPORT 0 -#endif // Enable calling through to `glslang` on // all platforms. @@ -68,9 +50,9 @@ #pragma warning(disable: 4996) #endif -#ifdef CreateDirectory -#undef CreateDirectory -#endif +//#ifdef CreateDirectory +//#undef CreateDirectory +//#endif namespace Slang { @@ -406,13 +388,9 @@ namespace Slang // If no pass through -> that will always work! return SLANG_OK; } -#if !SLANG_ENABLE_DXIL_SUPPORT - case PassThroughMode::Dxc: return SLANG_E_NOT_IMPLEMENTED; -#endif #if !SLANG_ENABLE_GLSLANG_SUPPORT case PassThroughMode::Glslang: return SLANG_E_NOT_IMPLEMENTED; #endif - default: break; } @@ -863,26 +841,6 @@ namespace Slang return *entryPointIndices.begin(); } -#if SLANG_ENABLE_DXIL_SUPPORT - -// Implementations in `dxc-support.cpp` - -SlangResult emitDXILForEntryPointUsingDXC( - ComponentType* program, - BackEndCompileRequest* compileRequest, - Int entryPointIndex, - TargetRequest* targetReq, - EndToEndCompileRequest* endToEndReq, - List<uint8_t>& outCode); - -SlangResult dissassembleDXILUsingDXC( - BackEndCompileRequest* compileRequest, - void const* data, - size_t size, - String& stringOut); - -#endif - #if SLANG_ENABLE_GLSLANG_SUPPORT SlangResult invokeGLSLCompiler( BackEndCompileRequest* slangCompileRequest, @@ -1002,6 +960,17 @@ SlangResult dissassembleDXILUsingDXC( return true; } + static Severity _getDiagnosticSeverity(DownstreamDiagnostic::Severity severity) + { + typedef DownstreamDiagnostic::Severity DownstreamSeverity; + switch (severity) + { + case DownstreamSeverity::Warning: return Severity::Warning; + case DownstreamSeverity::Info: return Severity::Note; + default: return Severity::Error; + } + } + SlangResult emitWithDownstreamForEntryPoints( ComponentType* program, BackEndCompileRequest* slangRequest, @@ -1027,12 +996,6 @@ SlangResult dissassembleDXILUsingDXC( { switch (target) { - case CodeGenTarget::PTX: - { - sourceTarget = CodeGenTarget::CUDASource; - sourceLanguage = SourceLanguage::CUDA; - break; - } case CodeGenTarget::HostCallable: case CodeGenTarget::SharedLibrary: case CodeGenTarget::Executable: @@ -1041,6 +1004,12 @@ SlangResult dissassembleDXILUsingDXC( sourceLanguage = SourceLanguage::CPP; break; } + case CodeGenTarget::PTX: + { + sourceTarget = CodeGenTarget::CUDASource; + sourceLanguage = SourceLanguage::CUDA; + break; + } case CodeGenTarget::DXBytecode: { sourceTarget = CodeGenTarget::HLSL; @@ -1048,6 +1017,13 @@ SlangResult dissassembleDXILUsingDXC( downstreamCompiler = PassThroughMode::Fxc; break; } + case CodeGenTarget::DXIL: + { + sourceTarget = CodeGenTarget::HLSL; + sourceLanguage = SourceLanguage::HLSL; + downstreamCompiler = PassThroughMode::Dxc; + break; + } default: break; } @@ -1205,7 +1181,8 @@ SlangResult dissassembleDXILUsingDXC( // Disable exceptions and security checks options.flags &= ~(CompileOptions::Flag::EnableExceptionHandling | CompileOptions::Flag::EnableSecurityChecks); - if (downstreamCompiler == PassThroughMode::Fxc) + if (downstreamCompiler == PassThroughMode::Fxc || + downstreamCompiler == PassThroughMode::Dxc) { if (entryPointIndices.getCount() != 1) { @@ -1219,10 +1196,41 @@ SlangResult dissassembleDXILUsingDXC( auto entryPoint = program->getEntryPoint(entryPointIndex); auto profile = getEffectiveProfile(entryPoint, targetReq); - // Set the profile - options.profileName = GetHLSLProfileName(profile); - + // Set the entry point name options.entryPointName = getText(entryPoint->getName()); + + if (downstreamCompiler == PassThroughMode::Dxc) + { + // We will enable the flag to generate proper code for 16 - bit types + // by default, as long as the user is requesting a sufficiently + // high shader model. + // + // TODO: Need to check that this is safe to enable in all cases, + // or if it will make a shader demand hardware features that + // aren't always present. + // + // TODO: Ideally the dxc back-end should be passed some information + // on the "capabilities" that were used and/or requested in the code. + // + if (profile.getVersion() >= ProfileVersion::DX_6_2) + { + options.flags |= CompileOptions::Flag::EnableFloat16; + } + + // Only set the profile if the stage is set + if (profile.getStage() != Stage::Unknown) + { + options.profileName = GetHLSLProfileName(profile); + } + + // Set the matrix layout + options.matrixLayout = targetReq->getDefaultMatrixLayoutMode(); + } + else + { + // Set the profile + options.profileName = GetHLSLProfileName(profile); + } } // For host callable we want downstream compile to produce a shared library @@ -1343,48 +1351,41 @@ SlangResult dissassembleDXILUsingDXC( StringBuilder builder; - typedef DownstreamDiagnostic Diagnostic; - for (const auto& diagnostic : diagnostics.diagnostics) { builder.Clear(); - builder << diagnostic.filePath << "(" << diagnostic.fileLine <<"): "; - - if (diagnostic.stage == Diagnostic::Stage::Link) + const Severity severity = _getDiagnosticSeverity(diagnostic.severity); + + if (diagnostic.filePath.getLength() == 0 && diagnostic.fileLine == 0 && severity == Severity::Note) { - builder << "link "; + // If theres no filePath line number and it's info, output severity and text alone + builder << getSeverityName(severity) << " : "; } - - // - Severity severity = Severity::Error; - - switch (diagnostic.severity) + else { - case Diagnostic::Severity::Unknown: - case Diagnostic::Severity::Error: + if (diagnostic.filePath.getLength()) { - severity = Severity::Error; - builder << "error"; - break; + builder << diagnostic.filePath; } - case Diagnostic::Severity::Warning: + + if (diagnostic.fileLine) { - severity = Severity::Warning; - builder << "warning"; - break; + builder << "(" << diagnostic.fileLine <<")"; } - case Diagnostic::Severity::Info: + + builder << ": "; + + if (diagnostic.stage == DownstreamDiagnostic::Stage::Link) { - severity = Severity::Note; - builder << "info"; - break; + builder << "link "; } - default: break; - } - builder << " " << diagnostic.code << ": " << diagnostic.text; + builder << getSeverityName(severity); + builder << " " << diagnostic.code << ": "; + } + builder << diagnostic.text; reportExternalCompileError(compilerText.getBuffer(), severity, SLANG_OK, builder.getUnownedSlice(), sink); } } @@ -1572,9 +1573,11 @@ SlangResult dissassembleDXILUsingDXC( switch (target) { case CodeGenTarget::DXBytecodeAssembly: + case CodeGenTarget::DXILAssembly: { RefPtr<DownstreamCompileResult> downstreamResult; - const CodeGenTarget intermediateTarget = CodeGenTarget::DXBytecode; + + const CodeGenTarget intermediateTarget = (target == CodeGenTarget::DXBytecodeAssembly) ? CodeGenTarget::DXBytecode : CodeGenTarget::DXIL; if (SLANG_SUCCEEDED(emitWithDownstreamForEntryPoints( program, @@ -1596,6 +1599,7 @@ SlangResult dissassembleDXILUsingDXC( } } break; + case CodeGenTarget::DXIL: case CodeGenTarget::DXBytecode: case CodeGenTarget::PTX: case CodeGenTarget::HostCallable: @@ -1637,51 +1641,6 @@ SlangResult dissassembleDXILUsingDXC( } break; -#if SLANG_ENABLE_DXIL_SUPPORT - case CodeGenTarget::DXIL: - { - List<uint8_t> code; - auto entryPointIndex = assertSingleEntryPoint(entryPointIndices); - if (SLANG_SUCCEEDED(emitDXILForEntryPointUsingDXC( - program, - compileRequest, - entryPointIndex, - targetReq, - endToEndReq, - code))) - { - maybeDumpIntermediate(compileRequest, code.getBuffer(), code.getCount(), target); - result = CompileResult(ListBlob::moveCreate(code)); - } - } - break; - - case CodeGenTarget::DXILAssembly: - { - List<uint8_t> code; - Int entryPointIndex = assertSingleEntryPoint(entryPointIndices); - if (SLANG_SUCCEEDED(emitDXILForEntryPointUsingDXC( - program, - compileRequest, - entryPointIndex, - targetReq, - endToEndReq, - code))) - { - String assembly; - dissassembleDXILUsingDXC( - compileRequest, - code.getBuffer(), - code.getCount(), - assembly); - - maybeDumpIntermediate(compileRequest, assembly.getBuffer(), target); - result = CompileResult(assembly); - } - } - break; -#endif - case CodeGenTarget::SPIRV: { List<uint8_t> code; @@ -1899,11 +1858,13 @@ SlangResult dissassembleDXILUsingDXC( switch (targetReq->getTarget()) { case CodeGenTarget::DXBytecodeAssembly: + case CodeGenTarget::DXILAssembly: { const UnownedStringSlice disassembly = StringUtil::getSlice(blob); writeOutputToConsole(writer, disassembly); } break; + case CodeGenTarget::DXIL: case CodeGenTarget::DXBytecode: { ComPtr<ISlangBlob> disassemblyBlob; @@ -1915,17 +1876,7 @@ SlangResult dissassembleDXILUsingDXC( } } break; - - #if SLANG_ENABLE_DXIL_SUPPORT - case CodeGenTarget::DXIL: - { - String assembly; - dissassembleDXILUsingDXC(backEndReq, blobData, blobSize, assembly); - writeOutputToConsole(writer, assembly); - } - break; - #endif - + case CodeGenTarget::SPIRV: { String assembly; @@ -2498,7 +2449,6 @@ SlangResult dissassembleDXILUsingDXC( } break; - #if SLANG_ENABLE_DXIL_SUPPORT case CodeGenTarget::DXILAssembly: dumpIntermediateText(compileRequest, data, size, ".dxil.asm"); break; @@ -2507,11 +2457,13 @@ SlangResult dissassembleDXILUsingDXC( dumpIntermediateBinary(compileRequest, data, size, ".dxil"); { String dxilAssembly; - dissassembleDXILUsingDXC(compileRequest, data, size, dxilAssembly); - dumpIntermediateText(compileRequest, dxilAssembly.begin(), dxilAssembly.getLength(), ".dxil.asm"); + ComPtr<ISlangBlob> disassemblyBlob; + if (SLANG_SUCCEEDED(dissassembleWithDownstream(compileRequest, target, data, size, disassemblyBlob.writeRef()))) + { + dumpIntermediateText(compileRequest, disassemblyBlob->getBufferPointer(), disassemblyBlob->getBufferSize(), ".dxil.asm"); + } } break; - #endif case CodeGenTarget::CSource: dumpIntermediateText(compileRequest, data, size, ".c"); diff --git a/source/slang/slang-dxc-support.cpp b/source/slang/slang-dxc-support.cpp deleted file mode 100755 index 4e5e4080e..000000000 --- a/source/slang/slang-dxc-support.cpp +++ /dev/null @@ -1,367 +0,0 @@ -// slang-dxc-support.cpp -#include "slang-compiler.h" - -// This file implements support for invoking the `dxcompiler` -// library to translate HLSL to DXIL. - -#if defined(_WIN32) -# if !defined(SLANG_ENABLE_DXIL_SUPPORT) -# define SLANG_ENABLE_DXIL_SUPPORT 1 -# endif -#endif - -#if !defined(SLANG_ENABLE_DXIL_SUPPORT) -# define SLANG_ENABLE_DXIL_SUPPORT 0 -#endif - -#if SLANG_ENABLE_DXIL_SUPPORT - -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX -#include <Windows.h> -#include <Unknwn.h> -#include "../../external/dxc/dxcapi.h" -#undef WIN32_LEAN_AND_MEAN -#undef NOMINMAX - -#include "../core/slang-platform.h" - -namespace Slang -{ - String GetHLSLProfileName(Profile profile); - - - SlangResult locateDXCCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); - - static UnownedStringSlice _getSlice(IDxcBlob* blob) - { - if (blob) - { - const char* chars = (const char*)blob->GetBufferPointer(); - size_t len = blob->GetBufferSize(); - len -= size_t(len > 0 && chars[len - 1] == 0); - return UnownedStringSlice(chars, len); - } - return UnownedStringSlice(); - } - - // IDxcIncludeHandler - // 7f61fc7d-950d-467f-b3e3-3c02fb49187c - static const Guid IID_IDxcIncludeHandler = { 0x7f61fc7d, 0x950d, 0x467f, { 0x3c, 0x02, 0xfb, 0x49, 0x18, 0x7c } }; - - class DxcIncludeHandler : public IDxcIncludeHandler - { - public: - // Implement IUnknown - SLANG_NO_THROW HRESULT SLANG_MCALL QueryInterface(const IID& uuid, void** out) - { - ISlangUnknown* intf = getInterface(reinterpret_cast<const Guid&>(uuid)); - if (intf) - { - *out = intf; - return SLANG_OK; - } - return SLANG_E_NO_INTERFACE; - } - SLANG_NO_THROW ULONG SLANG_MCALL AddRef() SLANG_OVERRIDE { return 1; } - SLANG_NO_THROW ULONG SLANG_MCALL Release() SLANG_OVERRIDE { return 1; } - - // Implement IDxcIncludeHandler - virtual HRESULT SLANG_MCALL LoadSource(LPCWSTR inFilename, IDxcBlob** outSource) SLANG_OVERRIDE - { - // Hmm DXC does something a bit odd - when it sees a path, it just passes that in with ./ in front!! - // NOTE! It doesn't make any difference if it is "" or <> quoted. - - // So we just do a work around where we strip if we see a path starting with ./ - String filePath = String::fromWString(inFilename); - - // If it starts with ./ then attempt to strip it - if (filePath.startsWith("./")) - { - String remaining(filePath.subString(2, filePath.getLength() - 2)); - - // Okay if we strip ./ and what we have is absolute, then it's the absolute path that we care about, - // otherwise we just leave as is. - if (Path::isAbsolute(remaining)) - { - filePath = remaining; - } - } - - ComPtr<ISlangBlob> blob; - PathInfo pathInfo; - SlangResult res = m_system.findAndLoadFile(filePath, String(), pathInfo, blob); - - // NOTE! This only works because ISlangBlob is *binary compatible* with IDxcBlob, if either - // change things could go boom - *outSource = (IDxcBlob*)blob.detach(); - return res; - } - - DxcIncludeHandler(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager = nullptr) : - m_system(searchDirectories, fileSystemExt, sourceManager) - { - } - - protected: - - // Used by QueryInterface for casting - ISlangUnknown* getInterface(const Guid& guid) - { - if (guid == ISlangUnknown::getTypeGuid() || guid == IID_IDxcIncludeHandler) - { - return (ISlangUnknown*)(static_cast<IDxcIncludeHandler*>(this)); - } - return nullptr; - } - - IncludeSystem m_system; - }; - - - SlangResult emitDXILForEntryPointUsingDXC( - ComponentType* program, - BackEndCompileRequest* compileRequest, - Int entryPointIndex, - TargetRequest* targetReq, - EndToEndCompileRequest* endToEndReq, - List<uint8_t>& outCode) - { - auto session = compileRequest->getSession(); - auto sink = compileRequest->getSink(); - - // First deal with all the rigamarole of loading - // the `dxcompiler` library, and creating the - // top-level COM objects that will be used to - // compile things. - - auto dxcCreateInstance = (DxcCreateInstanceProc)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Dxc_DxcCreateInstance, sink); - if (!dxcCreateInstance) - { - return SLANG_FAIL; - } - - ComPtr<IDxcCompiler> dxcCompiler; - SLANG_RETURN_ON_FAIL(dxcCreateInstance( - CLSID_DxcCompiler, - __uuidof(dxcCompiler), - (LPVOID*)dxcCompiler.writeRef())); - - ComPtr<IDxcLibrary> dxcLibrary; - SLANG_RETURN_ON_FAIL(dxcCreateInstance( - CLSID_DxcLibrary, - __uuidof(dxcLibrary), - (LPVOID*)dxcLibrary.writeRef())); - - // Now let's go ahead and generate HLSL for the entry - // point, since we'll need that to feed into dxc. - SourceResult source; - SLANG_RETURN_ON_FAIL(emitEntryPointSource(compileRequest, entryPointIndex, - targetReq, CodeGenTarget::HLSL, endToEndReq, source)); - - const auto& hlslCode = source.source; - - maybeDumpIntermediate(compileRequest, hlslCode.getBuffer(), CodeGenTarget::HLSL); - - // Wrap the - - // Create blob from the string - ComPtr<IDxcBlobEncoding> dxcSourceBlob; - SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned( - (LPBYTE)hlslCode.getBuffer(), - (UINT32)hlslCode.getLength(), - 0, - dxcSourceBlob.writeRef())); - - WCHAR const* args[16]; - UINT32 argCount = 0; - - // TODO: deal with - bool treatWarningsAsErrors = false; - if (treatWarningsAsErrors) - { - args[argCount++] = L"-WX"; - } - - switch( targetReq->getDefaultMatrixLayoutMode() ) - { - default: - break; - - case kMatrixLayoutMode_RowMajor: - args[argCount++] = L"-Zpr"; - break; - } - - switch( targetReq->getFloatingPointMode() ) - { - default: - break; - - case FloatingPointMode::Precise: - args[argCount++] = L"-Gis"; // "force IEEE strictness" - break; - } - - auto linkage = compileRequest->getLinkage(); - switch( linkage->optimizationLevel ) - { - default: - break; - - case OptimizationLevel::None: args[argCount++] = L"-Od"; break; - case OptimizationLevel::Default: args[argCount++] = L"-O1"; break; - case OptimizationLevel::High: args[argCount++] = L"-O2"; break; - case OptimizationLevel::Maximal: args[argCount++] = L"-O3"; break; - } - - switch( linkage->debugInfoLevel ) - { - case DebugInfoLevel::None: - break; - - default: - args[argCount++] = L"-Zi"; - break; - } - - // Slang strives to produce correct code, and by default - // we do not show the user warnings produced by a downstream - // compiler. When the downstream compiler *does* produce an - // error, then we dump its entire diagnostic log, which can - // include many distracting spurious warnings that have nothing - // to do with the user's code, and just relate to the idiomatic - // way that Slang outputs HLSL. - // - // It would be nice to use fine-grained flags to disable specific - // warnings here, so that we keep ourselves honest (e.g., only - // use `-Wno-parentheses` to eliminate that class of false positives), - // but alas dxc doesn't support these options even though they - // work on mainline Clang. Thus the only option we have available - // is the big hammer of turning off *all* warnings coming from dxc. - // - args[argCount++] = L"-no-warnings"; - - EntryPoint* entryPoint = program->getEntryPoint(entryPointIndex); - String entryPointName = getText(entryPoint->getName()); - OSString wideEntryPointName = entryPointName.toWString(); - - auto profile = getEffectiveProfile(entryPoint, targetReq); - String profileName = GetHLSLProfileName(profile); - OSString wideProfileName = profileName.toWString(); - - // We will enable the flag to generate proper code for 16-bit types - // by default, as long as the user is requesting a sufficiently - // high shader model. - // - // TODO: Need to check that this is safe to enable in all cases, - // or if it will make a shader demand hardware features that - // aren't always present. - // - // TODO: Ideally the dxc back-end should be passed some information - // on the "capabilities" that were used and/or requested in the code. - // - if( profile.getVersion() >= ProfileVersion::DX_6_2 ) - { - args[argCount++] = L"-enable-16bit-types"; - } - - const String sourcePath = calcSourcePathForEntryPoint(endToEndReq, entryPointIndex); - - DxcIncludeHandler includeHandler(&linkage->searchDirectories, linkage->getFileSystemExt(), compileRequest->getSourceManager()); - - ComPtr<IDxcOperationResult> dxcResult; - SLANG_RETURN_ON_FAIL(dxcCompiler->Compile(dxcSourceBlob, - sourcePath.toWString().begin(), - profile.getStage() == Stage::Unknown ? L"" : wideEntryPointName.begin(), - wideProfileName.begin(), - args, - argCount, - nullptr, // `#define`s - 0, // `#define` count - &includeHandler, // `#include` handler - dxcResult.writeRef())); - - // Retrieve result. - HRESULT resultCode = S_OK; - SLANG_RETURN_ON_FAIL(dxcResult->GetStatus(&resultCode)); - - // Note: it seems like the dxcompiler interface - // doesn't support querying diagnostic output - // *unless* the compile failed (no way to get - // warnings out!?). - - // Verify compile result - if (SLANG_FAILED(resultCode)) - { - // Compilation failed. - // Try to read any diagnostic output. - ComPtr<IDxcBlobEncoding> dxcErrorBlob; - SLANG_RETURN_ON_FAIL(dxcResult->GetErrorBuffer(dxcErrorBlob.writeRef())); - - // Note: the error blob returned by dxc doesn't always seem - // to be nul-terminated, so we should be careful and turn it - // into a string for safety. - // - - reportExternalCompileError("dxc", resultCode, _getSlice(dxcErrorBlob), compileRequest->getSink()); - return resultCode; - } - - // Okay, the compile supposedly succeeded, so we - // just need to grab the buffer with the output DXIL. - ComPtr<IDxcBlob> dxcResultBlob; - SLANG_RETURN_ON_FAIL(dxcResult->GetResult(dxcResultBlob.writeRef())); - - outCode.addRange( - (uint8_t const*)dxcResultBlob->GetBufferPointer(), - (int) dxcResultBlob->GetBufferSize()); - - return SLANG_OK; - } - - SlangResult dissassembleDXILUsingDXC( - BackEndCompileRequest* compileRequest, - void const* data, - size_t size, - String& stringOut) - { - stringOut = String(); - auto session = compileRequest->getSession(); - auto sink = compileRequest->getSink(); - - // First deal with all the rigamarole of loading - // the `dxcompiler` library, and creating the - // top-level COM objects that will be used to - // compile things. - - auto dxcCreateInstance = (DxcCreateInstanceProc)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Dxc_DxcCreateInstance, sink); - if (!dxcCreateInstance) - { - return SLANG_FAIL; - } - - ComPtr<IDxcCompiler> dxcCompiler; - SLANG_RETURN_ON_FAIL(dxcCreateInstance(CLSID_DxcCompiler, __uuidof(dxcCompiler), (LPVOID*) dxcCompiler.writeRef())); - ComPtr<IDxcLibrary> dxcLibrary; - SLANG_RETURN_ON_FAIL(dxcCreateInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*) dxcLibrary.writeRef())); - - // Create blob from the input data - ComPtr<IDxcBlobEncoding> dxcSourceBlob; - SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned((LPBYTE) data, (UINT32) size, 0, dxcSourceBlob.writeRef())); - - ComPtr<IDxcBlobEncoding> dxcResultBlob; - SLANG_RETURN_ON_FAIL(dxcCompiler->Disassemble(dxcSourceBlob, dxcResultBlob.writeRef())); - - stringOut = _getSlice(dxcResultBlob); - - return SLANG_OK; - } - - -} // namespace Slang - -#endif - - - |
