summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2021-05-14 17:50:00 -0400
committerGitHub <noreply@github.com>2021-05-14 17:50:00 -0400
commitd4316c88457a32f1169b2d7d82053ccbc05fa7ed (patch)
treecbc87350b9ef2f5be31ebc20783e08b895767779 /source
parent79d106fac18f5792fcac448a0b037aa834fa6042 (diff)
FXC as DownstreamCompiler (#1844)
* #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. * Small fixes for DXBC handling.
Diffstat (limited to 'source')
-rw-r--r--source/compiler-core/slang-downstream-compiler.cpp93
-rw-r--r--source/compiler-core/slang-downstream-compiler.h35
-rw-r--r--source/compiler-core/slang-fxc-compiler.cpp417
-rw-r--r--source/compiler-core/slang-fxc-compiler.h18
-rw-r--r--source/compiler-core/slang-gcc-compiler-util.cpp14
-rw-r--r--source/compiler-core/slang-include-system.cpp (renamed from source/slang/slang-include-system.cpp)0
-rw-r--r--source/compiler-core/slang-include-system.h (renamed from source/slang/slang-include-system.h)0
-rw-r--r--source/compiler-core/slang-nvrtc-compiler.cpp1
-rw-r--r--source/compiler-core/slang-visual-studio-compiler-util.cpp12
-rw-r--r--source/core/slang-string-util.cpp13
-rw-r--r--source/core/slang-string-util.h1
-rw-r--r--source/slang/slang-check.cpp2
-rwxr-xr-xsource/slang/slang-compiler.cpp598
-rwxr-xr-xsource/slang/slang-compiler.h5
-rw-r--r--source/slang/slang-preprocessor.h3
15 files changed, 776 insertions, 436 deletions
diff --git a/source/compiler-core/slang-downstream-compiler.cpp b/source/compiler-core/slang-downstream-compiler.cpp
index 696376b49..d89434896 100644
--- a/source/compiler-core/slang-downstream-compiler.cpp
+++ b/source/compiler-core/slang-downstream-compiler.cpp
@@ -18,6 +18,7 @@
#include "slang-visual-studio-compiler-util.h"
#include "slang-gcc-compiler-util.h"
#include "slang-nvrtc-compiler.h"
+#include "slang-fxc-compiler.h"
namespace Slang
{
@@ -74,8 +75,56 @@ void DownstreamCompiler::Desc::appendAsText(StringBuilder& out) const
}
}
+/* static */SlangResult DownstreamDiagnostic::splitPathLocation(const UnownedStringSlice& pathLocation, DownstreamDiagnostic& outDiagnostic)
+{
+ const Index lineStartIndex = pathLocation.lastIndexOf('(');
+ if (lineStartIndex >= 0)
+ {
+ outDiagnostic.filePath = UnownedStringSlice(pathLocation.head(lineStartIndex).trim());
+
+ const UnownedStringSlice tail = pathLocation.tail(lineStartIndex + 1);
+ const Index lineEndIndex = tail.indexOf(')');
+
+ if (lineEndIndex >= 0)
+ {
+ // Extract the location info
+ UnownedStringSlice locationSlice(tail.begin(), tail.begin() + lineEndIndex);
+
+ UnownedStringSlice slices[2];
+ const Index numSlices = StringUtil::split(locationSlice, ',', 2, slices);
+
+ // NOTE! FXC actually outputs a range of columns in the form of START-END in the column position
+ // We don't need to parse here, because we only care about the line number
+
+ Int lineNumber = 0;
+ if (numSlices > 0)
+ {
+ SLANG_RETURN_ON_FAIL(StringUtil::parseInt(slices[0], lineNumber));
+ }
+
+ // Store the line
+ outDiagnostic.fileLine = lineNumber;
+ }
+ }
+ else
+ {
+ outDiagnostic.filePath = pathLocation;
+ }
+ return SLANG_OK;
+}
+
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompiler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+SlangResult DownstreamCompiler::dissassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out)
+{
+ SLANG_UNUSED(sourceBlobTarget);
+ SLANG_UNUSED(blob);
+ SLANG_UNUSED(blobSize);
+ SLANG_UNUSED(out);
+
+ return SLANG_E_NOT_AVAILABLE;
+}
+
/* static */bool DownstreamCompiler::canCompile(SlangPassThrough compiler, SlangSourceLanguage sourceLanguage)
{
@@ -92,6 +141,7 @@ void DownstreamCompiler::Desc::appendAsText(StringBuilder& out) const
case SLANG_SOURCE_LANGUAGE_C: return SLANG_C_SOURCE;
case SLANG_SOURCE_LANGUAGE_CPP: return SLANG_CPP_SOURCE;
case SLANG_SOURCE_LANGUAGE_CUDA: return SLANG_CUDA_SOURCE;
+
default: return SLANG_TARGET_UNKNOWN;
}
}
@@ -196,6 +246,34 @@ void DownstreamDiagnostics::removeBySeverity(Diagnostic::Severity severity)
}
}
+/* static */void DownstreamDiagnostics::addNote(const UnownedStringSlice& in, List<DownstreamDiagnostic>& ioDiagnostics)
+{
+ // Don't bother adding an empty line
+ if (in.trim().getLength() == 0)
+ {
+ return;
+ }
+
+ // If there's nothing previous, we'll ignore too, as note should be in addition to
+ // a pre-existing error/warning
+ if (ioDiagnostics.getCount() == 0)
+ {
+ return;
+ }
+
+ // Make it a note on the output
+ DownstreamDiagnostic diagnostic;
+ diagnostic.reset();
+ diagnostic.severity = DownstreamDiagnostic::Severity::Info;
+ diagnostic.text = in;
+ ioDiagnostics.add(diagnostic);
+}
+
+void DownstreamDiagnostics::addNote(const UnownedStringSlice& in)
+{
+ addNote(in, diagnostics);
+}
+
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CommandLineDownstreamCompileResult !!!!!!!!!!!!!!!!!!!!!!*/
SlangResult CommandLineDownstreamCompileResult::getHostCallableSharedLibrary(ComPtr<ISlangSharedLibrary>& outLibrary)
@@ -595,19 +673,6 @@ static SlangResult _locateDXCCompilers(const String& path, ISlangSharedLibraryLo
return SLANG_OK;
}
-static SlangResult _locateFXCCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set)
-{
- ComPtr<ISlangSharedLibrary> sharedLibrary;
- if (SLANG_SUCCEEDED(DefaultSharedLibraryLoader::load(loader, path, "d3dcompiler_47", sharedLibrary.writeRef())))
- {
- // Can we determine the version?
- DownstreamCompiler::Desc desc(SLANG_PASS_THROUGH_FXC);
- 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
@@ -633,7 +698,7 @@ static SlangResult _locateGlslangCompilers(const String& path, ISlangSharedLibra
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_FXC)] = &_locateFXCCompilers;
+ 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 def13993e..b7f7b0cde 100644
--- a/source/compiler-core/slang-downstream-compiler.h
+++ b/source/compiler-core/slang-downstream-compiler.h
@@ -16,6 +16,8 @@
namespace Slang
{
+struct SourceManager;
+
struct DownstreamDiagnostic
{
typedef DownstreamDiagnostic ThisType;
@@ -54,6 +56,9 @@ struct DownstreamDiagnostic
static UnownedStringSlice getSeverityText(Severity severity);
+ /// 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);
+
Severity severity; ///< The severity of error
Stage stage; ///< The stage the error came from
String text; ///< The text of the error
@@ -85,6 +90,11 @@ struct DownstreamDiagnostics
/// Remove all diagnostics of the type
void removeBySeverity(Diagnostic::Severity severity);
+ /// Add a note
+ void addNote(const UnownedStringSlice& in);
+
+ static void addNote(const UnownedStringSlice& in, List<DownstreamDiagnostic>& ioDiagnostics);
+
String rawDiagnostics;
SlangResult result;
@@ -209,12 +219,14 @@ 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
{
@@ -256,7 +268,7 @@ public:
OptimizationLevel optimizationLevel = OptimizationLevel::Default;
DebugInfoType debugInfoType = DebugInfoType::Standard;
- TargetType targetType = TargetType::Executable;
+ SlangCompileTarget targetType = SLANG_EXECUTABLE;
SlangSourceLanguage sourceLanguage = SLANG_SOURCE_LANGUAGE_CPP;
FloatingPointMode floatingPointMode = FloatingPointMode::Default;
PipelineType pipelineType = PipelineType::Unknown;
@@ -284,6 +296,16 @@ public:
List<String> libraryPaths;
List<CapabilityVersion> requiredCapabilityVersions;
+
+ /// For compilers/compiles that require an entry point name, else can be empty
+ 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;
+
+ /// NOTE! Not all downstream compilers can use the fileSystemExt/sourceManager. This option will be ignored in those scenarios.
+ ISlangFileSystemExt* fileSystemExt = nullptr;
+ SourceManager* sourceManager = nullptr;
};
typedef uint32_t ProductFlags;
@@ -317,6 +339,12 @@ public:
/// 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);
+
+ /// True if underlying compiler uses file system to pass source
+ virtual bool isFileBased() = 0;
+
/// Get info for a compiler type
static const Info& getInfo(SlangPassThrough compiler) { return s_infos.infos[int(compiler)]; }
/// True if this compiler can compile the specified language
@@ -369,7 +397,8 @@ public:
// DownstreamCompiler
virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE;
-
+ virtual bool isFileBased() SLANG_OVERRIDE { return true; }
+
// Functions to be implemented for a specific CommandLine
/// Given the compilation options and the module name, determines the actual file name used for output
@@ -405,6 +434,7 @@ public:
// 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):
@@ -461,7 +491,6 @@ struct DownstreamCompilerBaseUtil
{
typedef DownstreamCompiler::CompileOptions CompileOptions;
typedef DownstreamCompiler::OptimizationLevel OptimizationLevel;
- typedef DownstreamCompiler::TargetType TargetType;
typedef DownstreamCompiler::DebugInfoType DebugInfoType;
typedef DownstreamDiagnostics::Diagnostic Diagnostic;
diff --git a/source/compiler-core/slang-fxc-compiler.cpp b/source/compiler-core/slang-fxc-compiler.cpp
new file mode 100644
index 000000000..8e190bbca
--- /dev/null
+++ b/source/compiler-core/slang-fxc-compiler.cpp
@@ -0,0 +1,417 @@
+// slang-fxc-compiler.cpp
+#include "slang-fxc-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 `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_DXBC_SUPPORT
+# define SLANG_ENABLE_DXBC_SUPPORT 1
+# endif
+#endif
+
+#ifndef SLANG_ENABLE_DXBC_SUPPORT
+# define SLANG_ENABLE_DXBC_SUPPORT 0
+#endif
+
+#if SLANG_ENABLE_DXBC_SUPPORT
+ // Some of the `D3DCOMPILE_*` constants aren't available in all
+ // versions of `d3dcompiler.h`, so we define them here just in case
+# ifndef D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES
+# define D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES (1 << 20)
+# endif
+
+# ifndef D3DCOMPILE_ALL_RESOURCES_BOUND
+# define D3DCOMPILE_ALL_RESOURCES_BOUND (1 << 21)
+# endif
+#endif
+
+namespace Slang
+{
+
+#if SLANG_ENABLE_DXBC_SUPPORT
+
+static UnownedStringSlice _getSlice(ID3DBlob* blob) { return StringUtil::getSlice((ISlangBlob*)blob); }
+
+struct FxcIncludeHandler : ID3DInclude
+{
+
+ STDMETHOD(Open)(D3D_INCLUDE_TYPE includeType, LPCSTR fileName, LPCVOID parentData, LPCVOID* outData, UINT* outSize) override
+ {
+ SLANG_UNUSED(includeType);
+ // NOTE! The pParentData means the *text* of any previous include.
+ // In order to work out what *path* that came from, we need to seach which source file it came from, and
+ // use it's path
+
+ // Assume the root pathInfo initially
+ PathInfo includedFromPathInfo = m_rootPathInfo;
+
+ // Lets try and find the parent source if there is any
+ if (parentData)
+ {
+ SourceFile* foundSourceFile = m_system.getSourceManager()->findSourceFileByContentRecursively((const char*)parentData);
+ if (foundSourceFile)
+ {
+ includedFromPathInfo = foundSourceFile->getPathInfo();
+ }
+ }
+
+ String path(fileName);
+ PathInfo pathInfo;
+ ComPtr<ISlangBlob> blob;
+
+ SLANG_RETURN_ON_FAIL(m_system.findAndLoadFile(path, includedFromPathInfo.foundPath, pathInfo, blob));
+
+ // Return the data
+ *outData = blob->getBufferPointer();
+ *outSize = (UINT)blob->getBufferSize();
+
+ return S_OK;
+ }
+
+ STDMETHOD(Close)(LPCVOID pData) override
+ {
+ SLANG_UNUSED(pData);
+ return S_OK;
+ }
+ FxcIncludeHandler(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager) :
+ m_system(searchDirectories, fileSystemExt, sourceManager)
+ {
+ }
+
+ PathInfo m_rootPathInfo;
+ IncludeSystem m_system;
+};
+
+class FXCDownstreamCompiler : 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);
+
+ FXCDownstreamCompiler() {}
+
+protected:
+
+ pD3DCompile m_compile = nullptr;
+ pD3DDisassemble m_disassemble = nullptr;
+
+ ComPtr<ISlangSharedLibrary> m_sharedLibrary;
+};
+
+SlangResult FXCDownstreamCompiler::init(ISlangSharedLibrary* library)
+{
+ m_compile = (pD3DCompile)library->findFuncByName("D3DCompile");
+ m_disassemble = (pD3DDisassemble)library->findFuncByName("D3DDisassemble");
+
+ if (!m_compile || !m_disassemble)
+ {
+ 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_FXC, D3D_COMPILER_VERSION);
+
+ return SLANG_OK;
+}
+
+static SlangResult _parseDiagnosticLine(const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, DownstreamDiagnostic& outDiagnostic)
+{
+ /* tests/diagnostics/syntax-error-intrinsic.slang(14,2): error X3000: syntax error: unexpected token '@' */
+ if (lineSlices.getCount() < 3)
+ {
+ return SLANG_FAIL;
+ }
+
+ SLANG_RETURN_ON_FAIL(DownstreamDiagnostic::splitPathLocation(lineSlices[0], outDiagnostic));
+
+ {
+ const UnownedStringSlice severityAndCodeSlice = lineSlices[1].trim();
+ const UnownedStringSlice severitySlice = StringUtil::getAtInSplit(severityAndCodeSlice, ' ', 0);
+
+ outDiagnostic.code = StringUtil::getAtInSplit(severityAndCodeSlice, ' ', 1);
+
+ outDiagnostic.severity = DownstreamDiagnostic::Severity::Error;
+ if (severitySlice == "warning")
+ {
+ outDiagnostic.severity = DownstreamDiagnostic::Severity::Warning;
+ }
+ }
+
+ outDiagnostic.text = UnownedStringSlice(lineSlices[2].begin(), line.end());
+ 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
+ if (options.sourceFiles.getCount() > 0)
+ {
+ return SLANG_FAIL;
+ }
+
+ if (options.sourceLanguage != SLANG_SOURCE_LANGUAGE_HLSL || options.targetType != SLANG_DXBC)
+ {
+ SLANG_ASSERT(!"Can only compile HLSL to DXBC");
+ return SLANG_FAIL;
+ }
+
+ // If we have been invoked in a pass-through mode, then we need to make sure
+ // that the downstream compiler sees whatever options were passed to Slang
+ // via the command line or API.
+ //
+ // TODO: more pieces of information should be added here as needed.
+ //
+
+ SearchDirectoryList searchDirectories;
+ for (const auto& includePath : options.includePaths)
+ {
+ searchDirectories.searchDirectories.add(includePath);
+ }
+
+ // Use the default fileSystemExt is not set
+ ID3DInclude* includeHandler = nullptr;
+
+ FxcIncludeHandler fxcIncludeHandlerStorage(&searchDirectories, options.fileSystemExt, options.sourceManager);
+ if (options.fileSystemExt)
+ {
+ if (options.sourceContentsPath.getLength() > 0)
+ {
+ fxcIncludeHandlerStorage.m_rootPathInfo = PathInfo::makePath(options.sourceContentsPath);
+ }
+ includeHandler = &fxcIncludeHandlerStorage;
+ }
+
+ List<D3D_SHADER_MACRO> dxMacrosStorage;
+ D3D_SHADER_MACRO const* dxMacros = nullptr;
+
+ if (options.defines.getCount() > 0)
+ {
+ for (const auto& define : options.defines)
+ {
+ D3D_SHADER_MACRO dxMacro;
+ dxMacro.Name = define.nameWithSig.getBuffer();
+ dxMacro.Definition = define.value.getBuffer();
+ dxMacrosStorage.add(dxMacro);
+ }
+ D3D_SHADER_MACRO nullTerminator = { 0, 0 };
+ dxMacrosStorage.add(nullTerminator);
+
+ dxMacros = dxMacrosStorage.getBuffer();
+ }
+
+ DWORD flags = 0;
+
+ switch (options.floatingPointMode)
+ {
+ default:
+ break;
+
+ case FloatingPointMode::Precise:
+ flags |= D3DCOMPILE_IEEE_STRICTNESS;
+ break;
+ }
+
+ flags |= D3DCOMPILE_ENABLE_STRICTNESS;
+ flags |= D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES;
+
+ switch (options.optimizationLevel)
+ {
+ default:
+ break;
+
+ case OptimizationLevel::None: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0; break;
+ case OptimizationLevel::Default: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL1; break;
+ case OptimizationLevel::High: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL2; break;
+ case OptimizationLevel::Maximal: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3; break;
+ }
+
+ switch (options.debugInfoType)
+ {
+ case DebugInfoType::None:
+ break;
+
+ default:
+ flags |= D3DCOMPILE_DEBUG;
+ break;
+ }
+
+ ComPtr<ID3DBlob> codeBlob;
+ ComPtr<ID3DBlob> diagnosticsBlob;
+ HRESULT hr = m_compile(
+ options.sourceContents.begin(),
+ options.sourceContents.getLength(),
+ options.sourceContentsPath.getBuffer(),
+ dxMacros,
+ includeHandler,
+ options.entryPointName.getBuffer(),
+ options.profileName.getBuffer(),
+ flags,
+ 0, // unused: effect flags
+ codeBlob.writeRef(),
+ diagnosticsBlob.writeRef());
+
+ DownstreamDiagnostics diagnostics;
+
+ // HRESULT is compatible with SlangResult
+ diagnostics.result = hr;
+
+ if (diagnosticsBlob)
+ {
+ UnownedStringSlice diagnosticText = _getSlice(diagnosticsBlob);
+ diagnostics.rawDiagnostics = diagnosticText;
+ _parseDiagnostics(diagnosticText, diagnostics.diagnostics);
+ }
+
+ // ID3DBlob is compatible with ISlangBlob, so just cast away...
+ ISlangBlob* slangCodeBlob = (ISlangBlob*)codeBlob.get();
+
+ outResult = new BlobDownstreamCompileResult(diagnostics, slangCodeBlob);
+ return SLANG_OK;
+}
+
+SlangResult FXCDownstreamCompiler::dissassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out)
+{
+ // Can only disassemble blobs that are DXBC
+ if (sourceBlobTarget != SLANG_DXBC)
+ {
+ return SLANG_FAIL;
+ }
+
+ ComPtr<ID3DBlob> codeBlob;
+ SLANG_RETURN_ON_FAIL(m_disassemble(blob, blobSize, 0, nullptr, codeBlob.writeRef()));
+
+ // ISlangBlob is compatible with ID3DBlob
+ *out = (ISlangBlob*)codeBlob.detach();
+ return SLANG_OK;
+}
+
+/* static */SlangResult FXCDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set)
+{
+ ComPtr<ISlangSharedLibrary> library;
+
+ // 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("d3dcompiler_47", library.writeRef()));
+ }
+
+ SLANG_ASSERT(library);
+ if (!library)
+ {
+ return SLANG_FAIL;
+ }
+
+ RefPtr<FXCDownstreamCompiler> compiler(new FXCDownstreamCompiler);
+ SLANG_RETURN_ON_FAIL(compiler->init(library));
+
+ set->addCompiler(compiler);
+ return SLANG_OK;
+}
+
+#else // SLANG_ENABLE_DXBC_SUPPORT
+
+/* static */SlangResult FXCDownstreamCompilerUtil::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_DXBC_SUPPORT
+
+}
diff --git a/source/compiler-core/slang-fxc-compiler.h b/source/compiler-core/slang-fxc-compiler.h
new file mode 100644
index 000000000..0718f6db4
--- /dev/null
+++ b/source/compiler-core/slang-fxc-compiler.h
@@ -0,0 +1,18 @@
+#ifndef SLANG_FXC_COMPILER_UTIL_H
+#define SLANG_FXC_COMPILER_UTIL_H
+
+#include "slang-downstream-compiler.h"
+
+#include "../core/slang-platform.h"
+
+namespace Slang
+{
+
+struct FXCDownstreamCompilerUtil
+{
+ static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set);
+};
+
+}
+
+#endif
diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp
index a51d5735f..971416ddb 100644
--- a/source/compiler-core/slang-gcc-compiler-util.cpp
+++ b/source/compiler-core/slang-gcc-compiler-util.cpp
@@ -377,18 +377,18 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse
switch (options.targetType)
{
- case TargetType::SharedLibrary:
+ case SLANG_SHARED_LIBRARY:
{
outPath << SharedLibrary::calcPlatformPath(options.modulePath.getUnownedSlice());
return SLANG_OK;
}
- case TargetType::Executable:
+ case SLANG_EXECUTABLE:
{
outPath << options.modulePath;
outPath << ProcessUtil::getExecutableSuffix();
return SLANG_OK;
}
- case TargetType::Object:
+ case SLANG_OBJECT_CODE:
{
#if __CYGWIN__
outPath << options.modulePath << ".obj";
@@ -509,7 +509,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse
switch (options.targetType)
{
- case TargetType::SharedLibrary:
+ case SLANG_SHARED_LIBRARY:
{
// Shared library
cmdLine.addArg("-shared");
@@ -521,11 +521,11 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse
}
break;
}
- case TargetType::Executable:
+ case SLANG_EXECUTABLE:
{
break;
}
- case TargetType::Object:
+ case SLANG_OBJECT_CODE:
{
// Don't link, just produce object file
cmdLine.addArg("-c");
@@ -563,7 +563,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse
//cmdLine.addArg(linkOptions);
}
- if (options.targetType == TargetType::SharedLibrary)
+ if (options.targetType == SLANG_SHARED_LIBRARY)
{
if (!PlatformUtil::isFamily(PlatformFamily::Apple, platformKind))
{
diff --git a/source/slang/slang-include-system.cpp b/source/compiler-core/slang-include-system.cpp
index 891d376f6..891d376f6 100644
--- a/source/slang/slang-include-system.cpp
+++ b/source/compiler-core/slang-include-system.cpp
diff --git a/source/slang/slang-include-system.h b/source/compiler-core/slang-include-system.h
index 70f6dd81e..70f6dd81e 100644
--- a/source/slang/slang-include-system.h
+++ b/source/compiler-core/slang-include-system.h
diff --git a/source/compiler-core/slang-nvrtc-compiler.cpp b/source/compiler-core/slang-nvrtc-compiler.cpp
index 79280e033..029f3c71b 100644
--- a/source/compiler-core/slang-nvrtc-compiler.cpp
+++ b/source/compiler-core/slang-nvrtc-compiler.cpp
@@ -100,6 +100,7 @@ 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
SlangResult init(ISlangSharedLibrary* library);
diff --git a/source/compiler-core/slang-visual-studio-compiler-util.cpp b/source/compiler-core/slang-visual-studio-compiler-util.cpp
index fd879e63f..e2c488ee9 100644
--- a/source/compiler-core/slang-visual-studio-compiler-util.cpp
+++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp
@@ -23,17 +23,17 @@ namespace Slang
switch (options.targetType)
{
- case TargetType::SharedLibrary:
+ case SLANG_SHARED_LIBRARY:
{
outPath << options.modulePath << ".dll";
return SLANG_OK;
}
- case TargetType::Executable:
+ case SLANG_EXECUTABLE:
{
outPath << options.modulePath << ".exe";
return SLANG_OK;
}
- case TargetType::Object:
+ case SLANG_OBJECT_CODE:
{
outPath << options.modulePath << ".obj";
return SLANG_OK;
@@ -60,7 +60,7 @@ namespace Slang
{
outPaths.add(options.modulePath + ".ilk");
- if (options.targetType == TargetType::SharedLibrary)
+ if (options.targetType == SLANG_SHARED_LIBRARY)
{
outPaths.add(options.modulePath + ".exp");
outPaths.add(options.modulePath + ".lib");
@@ -190,7 +190,7 @@ namespace Slang
switch (options.targetType)
{
- case TargetType::SharedLibrary:
+ case SLANG_SHARED_LIBRARY:
{
// Create dynamic link library
if (options.debugInfoType == DebugInfoType::None)
@@ -205,7 +205,7 @@ namespace Slang
cmdLine.addPrefixPathArg("/Fe", options.modulePath, ".dll");
break;
}
- case TargetType::Executable:
+ case SLANG_EXECUTABLE:
{
cmdLine.addPrefixPathArg("/Fe", options.modulePath, ".exe");
break;
diff --git a/source/core/slang-string-util.cpp b/source/core/slang-string-util.cpp
index cddee4bc4..7a142f643 100644
--- a/source/core/slang-string-util.cpp
+++ b/source/core/slang-string-util.cpp
@@ -293,7 +293,7 @@ UnownedStringSlice StringUtil::getAtInSplit(const UnownedStringSlice& in, char s
return builder;
}
-/* static */String StringUtil::getString(ISlangBlob* blob)
+/* static */UnownedStringSlice StringUtil::getSlice(ISlangBlob* blob)
{
if (blob)
{
@@ -301,15 +301,20 @@ UnownedStringSlice StringUtil::getAtInSplit(const UnownedStringSlice& in, char s
if (size > 0)
{
const char* contents = (const char*)blob->getBufferPointer();
- // Check it has terminating 0, if not we must construct as if it does
+ // Check it has terminating 0, if it has we skip it, because slices do not need zero termination
if (contents[size - 1] == 0)
{
size--;
}
- return String(contents, contents + size);
+ return UnownedStringSlice(contents, contents + size);
}
}
- return String();
+ return UnownedStringSlice();
+}
+
+/* static */String StringUtil::getString(ISlangBlob* blob)
+{
+ return getSlice(blob);
}
ComPtr<ISlangBlob> StringUtil::createStringBlob(const String& string)
diff --git a/source/core/slang-string-util.h b/source/core/slang-string-util.h
index 5b375a09e..2b30120b7 100644
--- a/source/core/slang-string-util.h
+++ b/source/core/slang-string-util.h
@@ -69,6 +69,7 @@ struct StringUtil
/// Given a string held in a blob, returns as a String
/// Returns an empty string if blob is nullptr
static String getString(ISlangBlob* blob);
+ static UnownedStringSlice getSlice(ISlangBlob* blob);
/// Given a string or slice, replaces all instances of fromChar with toChar
static String calcCharReplaced(const UnownedStringSlice& slice, char fromChar, char toChar);
diff --git a/source/slang/slang-check.cpp b/source/slang/slang-check.cpp
index 600578297..a5701aa90 100644
--- a/source/slang/slang-check.cpp
+++ b/source/slang/slang-check.cpp
@@ -70,8 +70,6 @@ namespace Slang
{
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::Fxc_D3DCompile: return { "D3DCompile", PassThroughMode::Fxc};
- case FuncType::Fxc_D3DDisassemble: return { "D3DDisassemble", PassThroughMode::Fxc };
case FuncType::Dxc_DxcCreateInstance: return { "DxcCreateInstance", PassThroughMode::Dxc };
default: return { nullptr, PassThroughMode::None };
}
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index 736250219..22e5bb61e 100755
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -35,18 +35,12 @@
#undef WIN32_LEAN_AND_MEAN
#undef NOMINMAX
#include <d3dcompiler.h>
- #ifndef SLANG_ENABLE_DXBC_SUPPORT
- #define SLANG_ENABLE_DXBC_SUPPORT 1
- #endif
#ifndef SLANG_ENABLE_DXIL_SUPPORT
#define SLANG_ENABLE_DXIL_SUPPORT 1
#endif
#endif
//
-// Otherwise, don't enable DXBC/DXIL by default:
-#ifndef SLANG_ENABLE_DXBC_SUPPORT
- #define SLANG_ENABLE_DXBC_SUPPORT 0
-#endif
+// Otherwise, don't enable DXIL by default:
#ifndef SLANG_ENABLE_DXIL_SUPPORT
#define SLANG_ENABLE_DXIL_SUPPORT 0
#endif
@@ -415,9 +409,6 @@ namespace Slang
#if !SLANG_ENABLE_DXIL_SUPPORT
case PassThroughMode::Dxc: return SLANG_E_NOT_IMPLEMENTED;
#endif
-#if !SLANG_ENABLE_DXBC_SUPPORT
- case PassThroughMode::Fxc: return SLANG_E_NOT_IMPLEMENTED;
-#endif
#if !SLANG_ENABLE_GLSLANG_SUPPORT
case PassThroughMode::Glslang: return SLANG_E_NOT_IMPLEMENTED;
#endif
@@ -522,7 +513,8 @@ namespace Slang
bool isPassThroughEnabled(
EndToEndCompileRequest* endToEndReq)
- { // If there isn't an end-to-end compile going on,
+ {
+ // If there isn't an end-to-end compile going on,
// there can be no pass-through.
//
if (!endToEndReq) return false;
@@ -556,23 +548,11 @@ namespace Slang
return nullptr;
}
- static void _appendEscapedPath(const UnownedStringSlice& path, StringBuilder& outBuilder)
- {
- for (auto c : path)
- {
- // TODO(JS): Probably want more sophisticated handling...
- if (c == '\\')
- {
- outBuilder.appendChar(c);
- }
- outBuilder.appendChar(c);
- }
- }
-
static void _appendCodeWithPath(const UnownedStringSlice& filePath, const UnownedStringSlice& fileContent, StringBuilder& outCodeBuilder)
{
outCodeBuilder << "#line 1 \"";
- _appendEscapedPath(filePath, outCodeBuilder);
+ auto handler = StringEscapeUtil::getHandler(StringEscapeUtil::Style::Cpp);
+ handler->appendEscaped(filePath, outCodeBuilder);
outCodeBuilder << "\"\n";
outCodeBuilder << fileContent << "\n";
}
@@ -883,276 +863,6 @@ namespace Slang
return *entryPointIndices.begin();
}
-#if SLANG_ENABLE_DXBC_SUPPORT
-
- static UnownedStringSlice _getSlice(ID3DBlob* 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();
- }
-
- struct FxcIncludeHandler : ID3DInclude
- {
-
- STDMETHOD(Open)(D3D_INCLUDE_TYPE includeType, LPCSTR fileName, LPCVOID parentData, LPCVOID* outData, UINT* outSize) override
- {
- SLANG_UNUSED(includeType);
- // NOTE! The pParentData means the *text* of any previous include.
- // In order to work out what *path* that came from, we need to seach which source file it came from, and
- // use it's path
-
- // Assume the root pathInfo initially
- PathInfo includedFromPathInfo = m_rootPathInfo;
-
- // Lets try and find the parent source if there is any
- if (parentData)
- {
- SourceFile* foundSourceFile = m_system.getSourceManager()->findSourceFileByContentRecursively((const char*)parentData);
- if (foundSourceFile)
- {
- includedFromPathInfo = foundSourceFile->getPathInfo();
- }
- }
-
- String path(fileName);
- PathInfo pathInfo;
- ComPtr<ISlangBlob> blob;
-
- SLANG_RETURN_ON_FAIL(m_system.findAndLoadFile(path, includedFromPathInfo.foundPath, pathInfo, blob));
-
- // Return the data
- *outData = blob->getBufferPointer();
- *outSize = (UINT) blob->getBufferSize();
-
- return S_OK;
- }
-
- STDMETHOD(Close)(LPCVOID pData) override
- {
- SLANG_UNUSED(pData);
- return S_OK;
- }
- FxcIncludeHandler(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager):
- m_system(searchDirectories, fileSystemExt, sourceManager)
- {
- }
-
- PathInfo m_rootPathInfo;
- IncludeSystem m_system;
- };
-
- SlangResult emitDXBytecodeForEntryPoint(
- ComponentType* program,
- BackEndCompileRequest* compileRequest,
- Int entryPointIndex,
- TargetRequest* targetReq,
- EndToEndCompileRequest* endToEndReq,
- List<uint8_t>& byteCodeOut)
- {
- byteCodeOut.clear();
-
- auto session = compileRequest->getSession();
- auto sink = compileRequest->getSink();
-
- auto compileFunc = (pD3DCompile)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Fxc_D3DCompile, sink);
- if (!compileFunc)
- {
- return SLANG_FAIL;
- }
-
- 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);
-
- auto entryPoint = program->getEntryPoint(entryPointIndex);
- auto profile = getEffectiveProfile(entryPoint, targetReq);
-
- auto linkage = compileRequest->getLinkage();
-
- // If we have been invoked in a pass-through mode, then we need to make sure
- // that the downstream compiler sees whatever options were passed to Slang
- // via the command line or API.
- //
- // TODO: more pieces of information should be added here as needed.
- //
- List<D3D_SHADER_MACRO> dxMacrosStorage;
- D3D_SHADER_MACRO const* dxMacros = nullptr;
-
- FxcIncludeHandler fxcIncludeHandlerStorage(&linkage->searchDirectories, linkage->getFileSystemExt(), sink->getSourceManager());
- FxcIncludeHandler* fxcIncludeHandler = &fxcIncludeHandlerStorage;
-
- if(auto translationUnit = findPassThroughTranslationUnit(endToEndReq, entryPointIndex))
- {
- for( auto& define : translationUnit->compileRequest->preprocessorDefinitions )
- {
- D3D_SHADER_MACRO dxMacro;
- dxMacro.Name = define.Key.getBuffer();
- dxMacro.Definition = define.Value.getBuffer();
- dxMacrosStorage.add(dxMacro);
- }
- for( auto& define : translationUnit->preprocessorDefinitions )
- {
- D3D_SHADER_MACRO dxMacro;
- dxMacro.Name = define.Key.getBuffer();
- dxMacro.Definition = define.Value.getBuffer();
- dxMacrosStorage.add(dxMacro);
- }
- D3D_SHADER_MACRO nullTerminator = { 0, 0 };
- dxMacrosStorage.add(nullTerminator);
-
- dxMacros = dxMacrosStorage.getBuffer();
-
- fxcIncludeHandler = &fxcIncludeHandlerStorage;
- fxcIncludeHandlerStorage.m_rootPathInfo = translationUnit->m_sourceFiles[0]->getPathInfo();
- }
-
- DWORD flags = 0;
-
- switch( targetReq->getFloatingPointMode() )
- {
- default:
- break;
-
- case FloatingPointMode::Precise:
- flags |= D3DCOMPILE_IEEE_STRICTNESS;
- break;
- }
-
- // Some of the `D3DCOMPILE_*` constants aren't available in all
- // versions of `d3dcompiler.h`, so we define them here just in case
- #ifndef D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES
- #define D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES (1 << 20)
- #endif
-
- #ifndef D3DCOMPILE_ALL_RESOURCES_BOUND
- #define D3DCOMPILE_ALL_RESOURCES_BOUND (1 << 21)
- #endif
-
- flags |= D3DCOMPILE_ENABLE_STRICTNESS;
- flags |= D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES;
-
- switch( linkage->optimizationLevel )
- {
- default:
- break;
-
- case OptimizationLevel::None: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0; break;
- case OptimizationLevel::Default: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL1; break;
- case OptimizationLevel::High: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL2; break;
- case OptimizationLevel::Maximal: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3; break;
- }
-
- switch( linkage->debugInfoLevel )
- {
- case DebugInfoLevel::None:
- break;
-
- default:
- flags |= D3DCOMPILE_DEBUG;
- break;
- }
-
- const String sourcePath = calcSourcePathForEntryPoint(endToEndReq, entryPointIndex);
-
- ComPtr<ID3DBlob> codeBlob;
- ComPtr<ID3DBlob> diagnosticsBlob;
- HRESULT hr = compileFunc(
- hlslCode.begin(),
- hlslCode.getLength(),
- sourcePath.getBuffer(),
- dxMacros,
- fxcIncludeHandler,
- getText(entryPoint->getName()).begin(),
- GetHLSLProfileName(profile).getBuffer(),
- flags,
- 0, // unused: effect flags
- codeBlob.writeRef(),
- diagnosticsBlob.writeRef());
-
- if (codeBlob && SLANG_SUCCEEDED(hr))
- {
- byteCodeOut.addRange((uint8_t const*)codeBlob->GetBufferPointer(), (int)codeBlob->GetBufferSize());
- }
-
- if (FAILED(hr))
- {
- reportExternalCompileError("fxc", hr, _getSlice(diagnosticsBlob), sink);
- }
-
- return hr;
- }
-
- SlangResult dissassembleDXBC(
- BackEndCompileRequest* compileRequest,
- void const* data,
- size_t size,
- String& assemOut)
- {
- assemOut = String();
-
- auto session = compileRequest->getSession();
- auto sink = compileRequest->getSink();
-
- auto disassembleFunc = (pD3DDisassemble)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Fxc_D3DDisassemble, sink);
- if (!disassembleFunc)
- {
- return SLANG_E_NOT_FOUND;
- }
-
- if (!data || !size)
- {
- return SLANG_FAIL;
- }
-
- ComPtr<ID3DBlob> codeBlob;
- SlangResult res = disassembleFunc(data, size, 0, nullptr, codeBlob.writeRef());
-
- if (codeBlob)
- {
- assemOut = _getSlice(codeBlob);
- }
- if (FAILED(res))
- {
- // TODO(tfoley): need to figure out what to diagnose here...
- reportExternalCompileError("fxc", res, UnownedStringSlice(), sink);
- }
-
- return res;
- }
-
- SlangResult emitDXBytecodeAssemblyForEntryPoint(
- ComponentType* program,
- BackEndCompileRequest* compileRequest,
- Int entryPointIndex,
- TargetRequest* targetReq,
- EndToEndCompileRequest* endToEndReq,
- String& assemOut)
- {
-
- List<uint8_t> dxbc;
- SLANG_RETURN_ON_FAIL(emitDXBytecodeForEntryPoint(
- program,
- compileRequest,
- entryPointIndex,
- targetReq,
- endToEndReq,
- dxbc));
- if (!dxbc.getCount())
- {
- return SLANG_FAIL;
- }
- return dissassembleDXBC(compileRequest, dxbc.getBuffer(), dxbc.getCount(), assemOut);
- }
-#endif
-
#if SLANG_ENABLE_DXIL_SUPPORT
// Implementations in `dxc-support.cpp`
@@ -1262,10 +972,42 @@ SlangResult dissassembleDXILUsingDXC(
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)
+ {
+ // We only bother if it's a file based compiler.
+ if (compiler->isFileBased())
+ {
+ // It can only have *one* source file as otherwise we have to combine to make a new source file anyway
+ const auto& sourceFiles = translationUnit->getSourceFiles();
+
+ // The *assumption* here is that if it's file based that assuming it can find the file with the same contents
+ // it can compile directly without having to save off as a file
+ if (sourceFiles.getCount() == 1)
+ {
+ const SourceFile* sourceFile = sourceFiles[0];
+ // We need the path to be found and set
+ //
+ // NOTE! That the downstream compiler can determine if the path and contents match such that it can be used
+ // without writing file
+ const PathInfo& pathInfo = sourceFile->getPathInfo();
+ if ((pathInfo.type == PathInfo::Type::FoundPath || pathInfo.type == PathInfo::Type::Normal) && pathInfo.foundPath.getLength())
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
SlangResult emitWithDownstreamForEntryPoints(
+ ComponentType* program,
BackEndCompileRequest* slangRequest,
const List<Int>& entryPointIndices,
TargetRequest* targetReq,
+ CodeGenTarget target,
EndToEndCompileRequest* endToEndReq,
RefPtr<DownstreamCompileResult>& outResult)
{
@@ -1275,8 +1017,6 @@ SlangResult dissassembleDXILUsingDXC(
auto session = slangRequest->getSession();
- const String originalSourcePath = calcSourcePathForEntryPoints(endToEndReq, entryPointIndices);
-
CodeGenTarget sourceTarget = CodeGenTarget::None;
SourceLanguage sourceLanguage = SourceLanguage::Unknown;
@@ -1285,7 +1025,6 @@ SlangResult dissassembleDXILUsingDXC(
// If we are not in pass through, lookup the default compiler for the emitted source type
if (downstreamCompiler == PassThroughMode::None)
{
- auto target = targetReq->getTarget();
switch (target)
{
case CodeGenTarget::PTX:
@@ -1302,26 +1041,34 @@ SlangResult dissassembleDXILUsingDXC(
sourceLanguage = SourceLanguage::CPP;
break;
}
+ case CodeGenTarget::DXBytecode:
+ {
+ sourceTarget = CodeGenTarget::HLSL;
+ sourceLanguage = SourceLanguage::HLSL;
+ downstreamCompiler = PassThroughMode::Fxc;
+ break;
+ }
default: break;
}
- downstreamCompiler = PassThroughMode(session->getDefaultDownstreamCompiler(SlangSourceLanguage(sourceLanguage)));
+ // Try looking up based on the language if one isn't set
+ if (downstreamCompiler == PassThroughMode::None)
+ {
+ downstreamCompiler = PassThroughMode(session->getDefaultDownstreamCompiler(SlangSourceLanguage(sourceLanguage)));
+ }
}
+
+ // We should have a downstream compiler set at this point
+ SLANG_ASSERT(downstreamCompiler != PassThroughMode::None);
+
// Get the required downstream compiler
DownstreamCompiler* compiler = session->getOrLoadDownstreamCompiler(downstreamCompiler, sink);
if (!compiler)
{
auto compilerName = TypeTextUtil::getPassThroughAsHumanText((SlangPassThrough)downstreamCompiler);
- if (downstreamCompiler != PassThroughMode::None)
- {
- sink->diagnose(SourceLoc(), Diagnostics::passThroughCompilerNotFound, compilerName);
- }
- else
- {
- sink->diagnose(SourceLoc(), Diagnostics::cppCompilerNotFound, compilerName);
- }
+ sink->diagnose(SourceLoc(), Diagnostics::passThroughCompilerNotFound, compilerName);
return SLANG_FAIL;
}
@@ -1383,27 +1130,40 @@ SlangResult dissassembleDXILUsingDXC(
// We are just passing thru, so it's whatever it originally was
sourceLanguage = translationUnit->sourceLanguage;
- sourceTarget = CodeGenTarget(DownstreamCompiler::getCompileTarget(SlangSourceLanguage(sourceLanguage)));
- // Special case if we have a single file, so that we pass the path, and the contents
- const auto& sourceFiles = translationUnit->getSourceFiles();
- if (sourceFiles.getCount() == 1)
+ // TODO(JS): This seems like a bit of a hack
+ // That if a pass-through is being performed and the source language is Slang
+ // no downstream compiler knows how to deal with that, so probably means 'HLSL'
+ if (sourceLanguage == SourceLanguage::Slang)
{
- const SourceFile* sourceFile = sourceFiles[0];
- const PathInfo& pathInfo = sourceFile->getPathInfo();
- if (pathInfo.type == PathInfo::Type::FoundPath || pathInfo.type == PathInfo::Type::Normal)
- {
- options.sourceContentsPath = pathInfo.foundPath;
- }
- options.sourceContents = sourceFile->getContent();
+ sourceLanguage = SourceLanguage::HLSL;
}
- else
+
+ sourceTarget = CodeGenTarget(DownstreamCompiler::getCompileTarget(SlangSourceLanguage(sourceLanguage)));
+
+ // If emitted source is required, emit and set the path
+ if (_isEmittedSourceRequired(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;
+
SourceResult source;
SLANG_RETURN_ON_FAIL(emitEntryPointsSource(slangRequest, entryPointIndices, targetReq, sourceTarget, endToEndReq, source));
-
options.sourceContents = source.source;
}
+ else
+ {
+ // Special case if we have a single file, so that we pass the path, and the contents
+ const auto& sourceFiles = translationUnit->getSourceFiles();
+ SLANG_ASSERT(sourceFiles.getCount() == 1);
+
+ const SourceFile* sourceFile = sourceFiles[0];
+
+ options.sourceContentsPath = sourceFile->getPathInfo().foundPath;
+ options.sourceContents = sourceFile->getContent();
+ }
}
else
{
@@ -1435,36 +1195,44 @@ SlangResult dissassembleDXILUsingDXC(
maybeDumpIntermediate(slangRequest, options.sourceContents.getBuffer(), sourceTarget);
}
+ // Set the file sytem and source manager, as *may* be used by downstream compiler
+ options.fileSystemExt = slangRequest->getFileSystemExt();
+ options.sourceManager = slangRequest->getSourceManager();
+
// Set the source type
options.sourceLanguage = SlangSourceLanguage(sourceLanguage);
-
+
// Disable exceptions and security checks
options.flags &= ~(CompileOptions::Flag::EnableExceptionHandling | CompileOptions::Flag::EnableSecurityChecks);
- // Set what kind of target we should build
- switch (targetReq->getTarget())
+ if (downstreamCompiler == PassThroughMode::Fxc)
{
- case CodeGenTarget::HostCallable:
- case CodeGenTarget::SharedLibrary:
- {
- options.targetType = DownstreamCompiler::TargetType::SharedLibrary;
- break;
- }
- case CodeGenTarget::Executable:
- {
- options.targetType = DownstreamCompiler::TargetType::Executable;
- break;
- }
- case CodeGenTarget::PTX:
+ if (entryPointIndices.getCount() != 1)
{
- // TODO(JS): Not clear what to do here.
- // For example should 'Kernel' be distinct from 'Executable'. For now just use executable.
- options.targetType = DownstreamCompiler::TargetType::Executable;
- break;
+ // We only support a single entry point on this target
+ SLANG_ASSERT(!"Can only compile with a single entry point on this target");
+ return SLANG_FAIL;
}
- default: break;
+
+ const Index entryPointIndex = entryPointIndices[0];
+
+ auto entryPoint = program->getEntryPoint(entryPointIndex);
+ auto profile = getEffectiveProfile(entryPoint, targetReq);
+
+ // Set the profile
+ options.profileName = GetHLSLProfileName(profile);
+
+ options.entryPointName = getText(entryPoint->getName());
}
+ // For host callable we want downstream compile to produce a shared library
+ if (target == CodeGenTarget::HostCallable)
+ {
+ target = CodeGenTarget::SharedLibrary;
+ }
+
+ options.targetType = (SlangCompileTarget)target;
+
// Need to configure for the compilation
{
@@ -1543,8 +1311,7 @@ SlangResult dissassembleDXILUsingDXC(
options.pipelineType = DownstreamCompiler::PipelineType::RayTracing;
break;
}
- }
-
+ }
}
// Add all the search paths (as calculated earlier - they will only be set if this is a pass through else will be empty)
@@ -1569,6 +1336,7 @@ SlangResult dissassembleDXILUsingDXC(
const auto& diagnostics = downstreamCompileResult->getDiagnostics();
+ if (diagnostics.diagnostics.getCount())
{
StringBuilder compilerText;
compiler->getDesc().appendAsText(compilerText);
@@ -1631,6 +1399,52 @@ SlangResult dissassembleDXILUsingDXC(
return SLANG_OK;
}
+ SlangResult dissassembleWithDownstream(
+ BackEndCompileRequest* slangRequest,
+ CodeGenTarget target,
+ const void* data,
+ size_t dataSizeInBytes,
+ ISlangBlob** outBlob)
+ {
+ auto session = slangRequest->getSession();
+ auto sink = slangRequest->getSink();
+
+ // Get the downstream compiler that can be used for this target
+
+ // TODO(JS):
+ // This could perhaps be performed in some other manner if there was more than one way to produce
+ // disassembly from a binary.
+ auto downstreamCompiler = getDownstreamCompilerRequiredForTarget(target);
+
+ // Get the required downstream compiler
+ DownstreamCompiler* compiler = session->getOrLoadDownstreamCompiler(downstreamCompiler, sink);
+
+ if (!compiler)
+ {
+ auto compilerName = TypeTextUtil::getPassThroughAsHumanText((SlangPassThrough)downstreamCompiler);
+ sink->diagnose(SourceLoc(), Diagnostics::passThroughCompilerNotFound, compilerName);
+ return SLANG_FAIL;
+ }
+
+ ComPtr<ISlangBlob> dissassemblyBlob;
+ SLANG_RETURN_ON_FAIL(compiler->dissassemble(SlangCompileTarget(target), data, dataSizeInBytes, dissassemblyBlob.writeRef()));
+
+ *outBlob = dissassemblyBlob.detach();
+ return SLANG_OK;
+ }
+
+ SlangResult dissassembleWithDownstream(
+ BackEndCompileRequest* slangRequest,
+ CodeGenTarget target,
+ DownstreamCompileResult* downstreamResult,
+ ISlangBlob** outBlob)
+ {
+
+ ComPtr<ISlangBlob> codeBlob;
+ SLANG_RETURN_ON_FAIL(downstreamResult->getBinary(codeBlob));
+ return dissassembleWithDownstream(slangRequest, target, codeBlob->getBufferPointer(), codeBlob->getBufferSize(), outBlob);
+ }
+
SlangResult emitSPIRVForEntryPointsDirectly(
BackEndCompileRequest* compileRequest,
const List<Int>& entryPointIndices,
@@ -1757,6 +1571,32 @@ SlangResult dissassembleDXILUsingDXC(
switch (target)
{
+ case CodeGenTarget::DXBytecodeAssembly:
+ {
+ RefPtr<DownstreamCompileResult> downstreamResult;
+ const CodeGenTarget intermediateTarget = CodeGenTarget::DXBytecode;
+
+ 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::DXBytecode:
case CodeGenTarget::PTX:
case CodeGenTarget::HostCallable:
case CodeGenTarget::SharedLibrary:
@@ -1765,14 +1605,15 @@ SlangResult dissassembleDXILUsingDXC(
RefPtr<DownstreamCompileResult> downstreamResult;
if (SLANG_SUCCEEDED(emitWithDownstreamForEntryPoints(
+ program,
compileRequest,
entryPointIndices,
targetReq,
+ target,
endToEndReq,
downstreamResult)))
{
maybeDumpIntermediate(compileRequest, downstreamResult, target);
-
result = CompileResult(downstreamResult);
}
}
@@ -1796,47 +1637,6 @@ SlangResult dissassembleDXILUsingDXC(
}
break;
-#if SLANG_ENABLE_DXBC_SUPPORT
- case CodeGenTarget::DXBytecode:
- {
- // Assert only one entry point case -- move out of this function
- List<uint8_t> code;
- auto entryPointIndex = assertSingleEntryPoint(entryPointIndices);
- if (SLANG_SUCCEEDED(emitDXBytecodeForEntryPoint(
- program,
- compileRequest,
- entryPointIndex,
- targetReq,
- endToEndReq,
- code)))
- {
- maybeDumpIntermediate(compileRequest, code.getBuffer(), code.getCount(), target);
-
- result = CompileResult(ListBlob::moveCreate(code));
- }
- }
- break;
-
- case CodeGenTarget::DXBytecodeAssembly:
- {
- // Assert only one entry point case
- String code;
- auto entryPointIndex = assertSingleEntryPoint(entryPointIndices);
- if (SLANG_SUCCEEDED(emitDXBytecodeAssemblyForEntryPoint(
- program,
- compileRequest,
- entryPointIndex,
- targetReq,
- endToEndReq,
- code)))
- {
- maybeDumpIntermediate(compileRequest, code.getBuffer(), target);
- result = CompileResult(code);
- }
- }
- break;
-#endif
-
#if SLANG_ENABLE_DXIL_SUPPORT
case CodeGenTarget::DXIL:
{
@@ -2098,16 +1898,24 @@ SlangResult dissassembleDXILUsingDXC(
switch (targetReq->getTarget())
{
- #if SLANG_ENABLE_DXBC_SUPPORT
- case CodeGenTarget::DXBytecode:
+ case CodeGenTarget::DXBytecodeAssembly:
{
- String assembly;
- dissassembleDXBC(backEndReq, blobData, blobSize, assembly);
- writeOutputToConsole(writer, assembly);
+ const UnownedStringSlice disassembly = StringUtil::getSlice(blob);
+ writeOutputToConsole(writer, disassembly);
}
break;
- #endif
+ case CodeGenTarget::DXBytecode:
+ {
+ ComPtr<ISlangBlob> disassemblyBlob;
+ if (SLANG_SUCCEEDED(dissassembleWithDownstream(backEndReq, targetReq->getTarget(), blobData, blobSize, disassemblyBlob.writeRef())))
+ {
+ const UnownedStringSlice disassembly = StringUtil::getSlice(disassemblyBlob);
+ writeOutputToConsole(writer, disassembly);
+ }
+ }
+ break;
+
#if SLANG_ENABLE_DXIL_SUPPORT
case CodeGenTarget::DXIL:
{
@@ -2675,7 +2483,6 @@ SlangResult dissassembleDXILUsingDXC(
}
break;
- #if SLANG_ENABLE_DXBC_SUPPORT
case CodeGenTarget::DXBytecodeAssembly:
dumpIntermediateText(compileRequest, data, size, ".dxbc.asm");
break;
@@ -2683,12 +2490,13 @@ SlangResult dissassembleDXILUsingDXC(
case CodeGenTarget::DXBytecode:
dumpIntermediateBinary(compileRequest, data, size, ".dxbc");
{
- String dxbcAssembly;
- dissassembleDXBC(compileRequest, data, size, dxbcAssembly);
- dumpIntermediateText(compileRequest, dxbcAssembly.begin(), dxbcAssembly.getLength(), ".dxbc.asm");
+ ComPtr<ISlangBlob> disassemblyBlob;
+ if (SLANG_SUCCEEDED(dissassembleWithDownstream(compileRequest, target, data, size, disassemblyBlob.writeRef())))
+ {
+ dumpIntermediateText(compileRequest, disassemblyBlob->getBufferPointer(), disassemblyBlob->getBufferSize(), ".dxbc.asm");
+ }
}
break;
- #endif
#if SLANG_ENABLE_DXIL_SUPPORT
case CodeGenTarget::DXILAssembly:
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index e57c1683a..52f3b9465 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -8,6 +8,7 @@
#include "../compiler-core/slang-downstream-compiler.h"
#include "../compiler-core/slang-name.h"
+#include "../compiler-core/slang-include-system.h"
#include "../core/slang-std-writers.h"
@@ -21,7 +22,6 @@
#include "slang-syntax.h"
-#include "slang-include-system.h"
#include "slang-serialize-ir-types.h"
@@ -76,6 +76,7 @@ namespace Slang
HostCallable = SLANG_HOST_CALLABLE,
CUDASource = SLANG_CUDA_SOURCE,
PTX = SLANG_PTX,
+ ObjectCode = SLANG_OBJECT_CODE,
CountOf = SLANG_TARGET_COUNT_OF,
};
@@ -2229,8 +2230,6 @@ namespace Slang
{
Glslang_Compile_1_0,
Glslang_Compile_1_1,
- Fxc_D3DCompile,
- Fxc_D3DDisassemble,
Dxc_DxcCreateInstance,
CountOf,
};
diff --git a/source/slang/slang-preprocessor.h b/source/slang/slang-preprocessor.h
index 9de82b9f2..9f3940d29 100644
--- a/source/slang/slang-preprocessor.h
+++ b/source/slang/slang-preprocessor.h
@@ -5,8 +5,7 @@
#include "../core/slang-basic.h"
#include "../compiler-core/slang-lexer.h"
-
-#include "slang-include-system.h"
+#include "../compiler-core/slang-include-system.h"
namespace Slang {