summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2021-05-14 18:38:08 -0400
committerGitHub <noreply@github.com>2021-05-14 18:38:08 -0400
commit1856b8ad85266ed66985b42bd2321a35f8573a00 (patch)
tree0b978ac765741c3a7b29493608d96915013fb571 /source
parentd4316c88457a32f1169b2d7d82053ccbc05fa7ed (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.cpp41
-rw-r--r--source/compiler-core/slang-downstream-compiler.h13
-rw-r--r--source/compiler-core/slang-dxc-compiler.cpp489
-rw-r--r--source/compiler-core/slang-dxc-compiler.h18
-rw-r--r--source/compiler-core/slang-fxc-compiler.cpp5
-rwxr-xr-xsource/slang/slang-compiler.cpp238
-rwxr-xr-xsource/slang/slang-dxc-support.cpp367
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
-
-
-