summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-01-16 13:31:42 -0500
committerGitHub <noreply@github.com>2019-01-16 13:31:42 -0500
commit86e11e0e111fab60b9517056ac049bfac6e3bd25 (patch)
treef34a8343fb6a949235f1973dc873814f408987ef /source
parentc260e6aa3a7dc3e6794442daacde3ae23f029e0b (diff)
Feature/external compiler reporting (#776)
* Added support for converting SlangResult to string in PlatformUtil. * * Added reportExternalCompilerError * Made external compilers use this * Made DiagnosticSink accept UnownedStringSlice * Made emitXXX compiler functions return SlangError * Use smart pointers to handle life of Com interfaces * * Make SlangResult compatible with HRESULT for some common cases. * Make PlatformUtil::appendResult return SlangResult * Compile check SLANG_RESULT. * Add tests for checking diagnostics from external compilers. * * Make external compiler tests only run on windows for now. * Added 'windows' and 'unix' categories * Added categories based on what backends are available. Will make more tests run on linux and handle case where dxcompiler is not available on appveyor. * * Added spSessionCheckPassThroughSupport * Use to determine whats available for categories for tests * Add support for outputting source filename/s when using pass through.
Diffstat (limited to 'source')
-rw-r--r--source/core/platform.cpp38
-rw-r--r--source/core/platform.h9
-rw-r--r--source/slang/compiler.cpp336
-rw-r--r--source/slang/compiler.h18
-rw-r--r--source/slang/diagnostics.cpp9
-rw-r--r--source/slang/diagnostics.h3
-rw-r--r--source/slang/dxc-support.cpp121
-rw-r--r--source/slang/slang.cpp8
8 files changed, 342 insertions, 200 deletions
diff --git a/source/core/platform.cpp b/source/core/platform.cpp
index d160fd37c..ff7d8e231 100644
--- a/source/core/platform.cpp
+++ b/source/core/platform.cpp
@@ -27,6 +27,39 @@ namespace Slang
#ifdef _WIN32
+// Make sure SlangResult match for common standard window HRESULT
+SLANG_COMPILE_TIME_ASSERT(E_FAIL == SLANG_FAIL);
+SLANG_COMPILE_TIME_ASSERT(E_NOINTERFACE == SLANG_E_NO_INTERFACE);
+SLANG_COMPILE_TIME_ASSERT(E_HANDLE == SLANG_E_INVALID_HANDLE);
+SLANG_COMPILE_TIME_ASSERT(E_NOTIMPL == SLANG_E_NOT_IMPLEMENTED);
+SLANG_COMPILE_TIME_ASSERT(E_INVALIDARG == SLANG_E_INVALID_ARG);
+SLANG_COMPILE_TIME_ASSERT(E_OUTOFMEMORY == SLANG_E_OUT_OF_MEMORY);
+
+/* static */SlangResult PlatformUtil::appendResult(SlangResult res, StringBuilder& builderOut)
+{
+ if (SLANG_FAILED(res) && res != SLANG_FAIL)
+ {
+ LPWSTR buffer = nullptr;
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ nullptr,
+ res,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPWSTR)&buffer,
+ 0,
+ nullptr);
+
+ if (buffer)
+ {
+ builderOut << " ";
+ // Convert to string
+ builderOut.Append(String::FromWString(buffer));
+ LocalFree(buffer);
+ return SLANG_OK;
+ }
+ }
+ return SLANG_FAIL;
+}
+
/* static */SlangResult SharedLibrary::loadWithPlatformFilename(char const* platformFileName, SharedLibrary::Handle& handleOut)
{
handleOut = nullptr;
@@ -78,6 +111,11 @@ namespace Slang
#else // _WIN32
+/* static */SlangResult PlatformUtil::appendResult(SlangResult res, StringBuilder& builderOut)
+{
+ return SLANG_E_NOT_IMPLEMENTED;
+}
+
/* static */SlangResult SharedLibrary::loadWithPlatformFilename(char const* platformFileName, Handle& handleOut)
{
handleOut = nullptr;
diff --git a/source/core/platform.h b/source/core/platform.h
index a545d139d..544ae8c16 100644
--- a/source/core/platform.h
+++ b/source/core/platform.h
@@ -47,6 +47,15 @@ namespace Slang
SharedLibrary();
};
+ struct PlatformUtil
+ {
+ /// Appends a text interpretation of a result (as defined by supporting OS)
+ /// @param res Result to produce a string for
+ /// @param builderOut Append the string produced to builderOut
+ /// @return SLANG_OK if string is found and appended. Fail otherwise. SLANG_E_NOT_IMPLEMENTED if there is no impl for this platform.
+ static SlangResult appendResult(SlangResult res, StringBuilder& builderOut);
+ };
+
#ifndef _MSC_VER
#define _fileno fileno
#define _isatty isatty
diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp
index a9711310b..895c8d159 100644
--- a/source/slang/compiler.cpp
+++ b/source/slang/compiler.cpp
@@ -179,64 +179,92 @@ namespace Slang
return Stage::Unknown;
}
+ SlangResult checkExternalCompilerSupport(Session* session, PassThroughMode passThrough)
+ {
+ switch (passThrough)
+ {
+ case PassThroughMode::None:
+ {
+ // If no pass through -> that will always work!
+ return SLANG_OK;
+ }
+ case PassThroughMode::dxc:
+ {
+#if SLANG_ENABLE_DXIL_SUPPORT
+ // Must have dxc
+ return (session->getOrLoadSharedLibrary(SharedLibraryType::Dxc, nullptr) &&
+ session->getOrLoadSharedLibrary(SharedLibraryType::Dxil, nullptr)) ? SLANG_OK : SLANG_E_NOT_FOUND;
+#endif
+ break;
+ }
+ case PassThroughMode::fxc:
+ {
+#if SLANG_ENABLE_DXBC_SUPPORT
+ // Must have fxc
+ return session->getOrLoadSharedLibrary(SharedLibraryType::Fxc, nullptr) ? SLANG_OK : SLANG_E_NOT_FOUND;
+#endif
+ break;
+ }
+ case PassThroughMode::glslang:
+ {
+#if SLANG_ENABLE_GLSLANG_SUPPORT
+ return session->getOrLoadSharedLibrary(Slang::SharedLibraryType::Glslang, nullptr) ? SLANG_OK : SLANG_E_NOT_FOUND;
+#endif
+ break;
+ }
+ }
+ return SLANG_E_NOT_IMPLEMENTED;
+ }
- SlangResult checkCompileTargetSupport(Session* session, CodeGenTarget target)
+ static PassThroughMode _getExternalCompilerRequiredForTarget(CodeGenTarget target)
{
switch (target)
{
case CodeGenTarget::None:
{
- return SLANG_OK;
+ return PassThroughMode::None;
}
case CodeGenTarget::GLSL:
case CodeGenTarget::GLSL_Vulkan:
case CodeGenTarget::GLSL_Vulkan_OneDesc:
{
// Can always output GLSL
- return SLANG_OK;
+ return PassThroughMode::None;
}
case CodeGenTarget::HLSL:
{
// Can always output HLSL
- return SLANG_OK;
+ return PassThroughMode::None;
}
case CodeGenTarget::SPIRVAssembly:
case CodeGenTarget::SPIRV:
{
-#if SLANG_ENABLE_GLSLANG_SUPPORT
- return session->getOrLoadSharedLibrary(Slang::SharedLibraryType::Glslang, nullptr) ? SLANG_OK : SLANG_E_NOT_FOUND;
-#else
- return SLANG_E_NOT_IMPLEMENTED;
-#endif
- }
+ return PassThroughMode::glslang;
+ }
case CodeGenTarget::DXBytecode:
case CodeGenTarget::DXBytecodeAssembly:
{
-#if SLANG_ENABLE_DXBC_SUPPORT
- // Must have fxc
- return session->getOrLoadSharedLibrary(SharedLibraryType::Fxc, nullptr) ? SLANG_OK : SLANG_E_NOT_FOUND;
-#else
- return SLANG_E_NOT_IMPLEMENTED;
-#endif
+ return PassThroughMode::fxc;
}
-
case CodeGenTarget::DXIL:
case CodeGenTarget::DXILAssembly:
{
-#if SLANG_ENABLE_DXIL_SUPPORT
- // Must have dxc
- return (session->getOrLoadSharedLibrary(SharedLibraryType::Dxc, nullptr) &&
- session->getOrLoadSharedLibrary(SharedLibraryType::Dxil, nullptr)) ? SLANG_OK : SLANG_E_NOT_FOUND;
-#else
- return SLANG_E_NOT_IMPLEMENTED;
-#endif
+ return PassThroughMode::dxc;
}
-
+
default: break;
}
SLANG_ASSERT(!"Unhandled target");
- return SLANG_FAIL;
+ return PassThroughMode::None;
+ }
+
+ SlangResult checkCompileTargetSupport(Session* session, CodeGenTarget target)
+ {
+ const PassThroughMode mode = _getExternalCompilerRequiredForTarget(target);
+ return (mode != PassThroughMode::None) ?
+ checkExternalCompilerSupport(session, mode) :
+ SLANG_OK;
}
//
@@ -416,18 +444,93 @@ namespace Slang
return result;
}
+ void reportExternalCompileError(const char* compilerName, SlangResult res, const UnownedStringSlice& diagnostic, DiagnosticSink* sink)
+ {
+ StringBuilder builder;
+ if (compilerName)
+ {
+ builder << compilerName << ": ";
+ }
+
+ if (diagnostic.size() > 0)
+ {
+ builder.Append(diagnostic);
+ }
+
+ if (SLANG_FAILED(res) && res != SLANG_FAIL)
+ {
+ {
+ char tmp[17];
+ sprintf_s(tmp, SLANG_COUNT_OF(tmp), "0x%08x", uint32_t(res));
+ builder << "Result(" << tmp << ") ";
+ }
+
+ PlatformUtil::appendResult(res, builder);
+ }
+
+ // TODO(tfoley): need a better policy for how we translate diagnostics
+ // back into the Slang world (although we should always try to generate
+ // HLSL that doesn't produce any diagnostics...)
+ sink->diagnoseRaw(SLANG_FAILED(res) ? Severity::Error : Severity::Warning, builder.getUnownedSlice());
+ }
+
+ String calcTranslationUnitSourcePath(TranslationUnitRequest* translationUnitRequest)
+ {
+ CompileRequest* compileRequest = translationUnitRequest->compileRequest;
+ if (compileRequest->passThrough == PassThroughMode::None)
+ {
+ return "slang-generated";
+ }
+
+ const auto& sourceFiles = translationUnitRequest->sourceFiles;
+
+ const int numSourceFiles = int(sourceFiles.Count());
+
+ switch (numSourceFiles)
+ {
+ case 0: return "unknown";
+ case 1: return sourceFiles[0]->getPathInfo().foundPath;
+ default:
+ {
+ StringBuilder builder;
+ builder << sourceFiles[0]->getPathInfo().foundPath;
+ for (int i = 1; i < numSourceFiles; ++i)
+ {
+ builder << ";" << sourceFiles[i]->getPathInfo().foundPath;
+ }
+
+ return builder;
+ }
+ }
+ }
+
#if SLANG_ENABLE_DXBC_SUPPORT
-
- List<uint8_t> EmitDXBytecodeForEntryPoint(
+
+ 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();
+ }
+
+ SlangResult emitDXBytecodeForEntryPoint(
EntryPointRequest* entryPoint,
- TargetRequest* targetReq)
+ TargetRequest* targetReq,
+ List<uint8_t>& byteCodeOut)
{
+ byteCodeOut.Clear();
+
auto session = entryPoint->compileRequest->mSession;
auto compileFunc = (pD3DCompile)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Fxc_D3DCompile, &entryPoint->compileRequest->mSink);
if (!compileFunc)
{
- return List<uint8_t>();
+ return SLANG_FAIL;
}
auto hlslCode = emitHLSLForEntryPoint(entryPoint, targetReq);
@@ -490,61 +593,43 @@ namespace Slang
flags |= D3DCOMPILE_ENABLE_STRICTNESS;
flags |= D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES;
- ID3DBlob* codeBlob;
- ID3DBlob* diagnosticsBlob;
+ const String sourcePath = calcTranslationUnitSourcePath(entryPoint->getTranslationUnit());
+
+ ComPtr<ID3DBlob> codeBlob;
+ ComPtr<ID3DBlob> diagnosticsBlob;
HRESULT hr = compileFunc(
hlslCode.begin(),
hlslCode.Length(),
- "slang",
+ sourcePath.Buffer(),
dxMacros,
nullptr,
getText(entryPoint->name).begin(),
GetHLSLProfileName(profile).Buffer(),
flags,
0, // unused: effect flags
- &codeBlob,
- &diagnosticsBlob);
+ codeBlob.writeRef(),
+ diagnosticsBlob.writeRef());
- List<uint8_t> data;
- if (codeBlob)
+ if (codeBlob && SLANG_SUCCEEDED(hr))
{
- data.AddRange((uint8_t const*)codeBlob->GetBufferPointer(), (int)codeBlob->GetBufferSize());
- codeBlob->Release();
+ byteCodeOut.AddRange((uint8_t const*)codeBlob->GetBufferPointer(), (int)codeBlob->GetBufferSize());
}
- // Note: we will only output diagnostics coming from a downstream
- // compiler in the event of an error (although in that case we will
- // end up including any warning diagnostics that are produced as well).
- //
- // TODO: some day we should aspire to make Slang's output always compile
- // cleanly without warnings on downstream compilers (or else suppress those
- // warnings), but this is difficult to do in practice without a lot of
- // tailoring for the quirks of each compiler (version).
- //
- if (diagnosticsBlob && FAILED(hr))
- {
- // TODO(tfoley): need a better policy for how we translate diagnostics
- // back into the Slang world (although we should always try to generate
- // HLSL that doesn't produce any diagnostics...)
- entryPoint->compileRequest->mSink.diagnoseRaw(
- FAILED(hr) ? Severity::Error : Severity::Warning,
- (char const*) diagnosticsBlob->GetBufferPointer());
- diagnosticsBlob->Release();
- }
if (FAILED(hr))
{
- return List<uint8_t>();
+ reportExternalCompileError("fxc", hr, _getSlice(diagnosticsBlob), &entryPoint->compileRequest->mSink);
}
- return data;
+
+ return hr;
}
SlangResult dissassembleDXBC(
CompileRequest* compileRequest,
void const* data,
size_t size,
- String& stringOut)
+ String& assemOut)
{
- stringOut = String();
+ assemOut = String();
auto session = compileRequest->mSession;
@@ -564,33 +649,30 @@ namespace Slang
if (codeBlob)
{
- char const* codeBegin = (char const*)codeBlob->GetBufferPointer();
- char const* codeEnd = codeBegin + codeBlob->GetBufferSize() - 1;
- stringOut = String(codeBegin, codeEnd);
+ assemOut = _getSlice(codeBlob);
}
if (FAILED(res))
{
// TODO(tfoley): need to figure out what to diagnose here...
+ reportExternalCompileError("fxc", res, UnownedStringSlice(), &compileRequest->mSink);
}
return res;
}
- String EmitDXBytecodeAssemblyForEntryPoint(
+ SlangResult emitDXBytecodeAssemblyForEntryPoint(
EntryPointRequest* entryPoint,
- TargetRequest* targetReq)
+ TargetRequest* targetReq,
+ String& assemOut)
{
- List<uint8_t> dxbc = EmitDXBytecodeForEntryPoint(entryPoint, targetReq);
+ List<uint8_t> dxbc;
+ SLANG_RETURN_ON_FAIL(emitDXBytecodeForEntryPoint(entryPoint, targetReq, dxbc));
if (!dxbc.Count())
{
- return String();
+ return SLANG_FAIL;
}
-
- String result;
- dissassembleDXBC(entryPoint->compileRequest, dxbc.Buffer(), dxbc.Count(), result);
-
- return result;
+ return dissassembleDXBC(entryPoint->compileRequest, dxbc.Buffer(), dxbc.Count(), assemOut);
}
#endif
@@ -612,7 +694,7 @@ SlangResult dissassembleDXILUsingDXC(
#endif
#if SLANG_ENABLE_GLSLANG_SUPPORT
- int invokeGLSLCompiler(
+ SlangResult invokeGLSLCompiler(
CompileRequest* slangCompileRequest,
glslang_CompileRequest& request)
{
@@ -621,13 +703,14 @@ SlangResult dissassembleDXILUsingDXC(
auto glslang_compile = (glslang_CompileFunc)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Glslang_Compile, &slangCompileRequest->mSink);
if (!glslang_compile)
{
- return 1;
+ return SLANG_FAIL;
}
- String diagnosticOutput;
+ StringBuilder diagnosticOutput;
+
auto diagnosticOutputFunc = [](void const* data, size_t size, void* userData)
{
- (*(String*)userData).append((char const*)data, (char const*)data + size);
+ (*(StringBuilder*)userData).append((char const*)data, (char const*)data + size);
};
request.diagnosticFunc = diagnosticOutputFunc;
@@ -637,13 +720,11 @@ SlangResult dissassembleDXILUsingDXC(
if (err)
{
- slangCompileRequest->mSink.diagnoseRaw(
- Severity::Error,
- diagnosticOutput.begin());
- return err;
+ reportExternalCompileError("glslang", SLANG_FAIL, diagnosticOutput.getUnownedSlice(), &slangCompileRequest->mSink);
+ return SLANG_FAIL;
}
- return 0;
+ return SLANG_OK;
}
SlangResult dissassembleSPIRV(
@@ -663,67 +744,64 @@ SlangResult dissassembleDXILUsingDXC(
glslang_CompileRequest request;
request.action = GLSLANG_ACTION_DISSASSEMBLE_SPIRV;
+ request.sourcePath = nullptr;
+
request.inputBegin = data;
request.inputEnd = (char*)data + size;
request.outputFunc = outputFunc;
request.outputUserData = &output;
- int err = invokeGLSLCompiler(slangRequest, request);
- if (err)
- {
- return SLANG_FAIL;
- }
+ SLANG_RETURN_ON_FAIL(invokeGLSLCompiler(slangRequest, request));
stringOut = output;
return SLANG_OK;
}
- List<uint8_t> emitSPIRVForEntryPoint(
+ SlangResult emitSPIRVForEntryPoint(
EntryPointRequest* entryPoint,
- TargetRequest* targetReq)
+ TargetRequest* targetReq,
+ List<uint8_t>& spirvOut)
{
+ spirvOut.Clear();
+
String rawGLSL = emitGLSLForEntryPoint(entryPoint, targetReq);
maybeDumpIntermediate(entryPoint->compileRequest, rawGLSL.Buffer(), CodeGenTarget::GLSL);
- List<uint8_t> output;
auto outputFunc = [](void const* data, size_t size, void* userData)
{
((List<uint8_t>*)userData)->AddRange((uint8_t*)data, size);
};
+ const String sourcePath = calcTranslationUnitSourcePath(entryPoint->getTranslationUnit());
+
glslang_CompileRequest request;
request.action = GLSLANG_ACTION_COMPILE_GLSL_TO_SPIRV;
- request.sourcePath = "slang";
+ request.sourcePath = sourcePath.Buffer();
request.slangStage = (SlangStage)entryPoint->getStage();
request.inputBegin = rawGLSL.begin();
request.inputEnd = rawGLSL.end();
request.outputFunc = outputFunc;
- request.outputUserData = &output;
-
- int err = invokeGLSLCompiler(entryPoint->compileRequest, request);
-
- if (err)
- {
- return List<uint8_t>();
- }
+ request.outputUserData = &spirvOut;
- return output;
+ SLANG_RETURN_ON_FAIL(invokeGLSLCompiler(entryPoint->compileRequest, request));
+ return SLANG_OK;
}
- String emitSPIRVAssemblyForEntryPoint(
+ SlangResult emitSPIRVAssemblyForEntryPoint(
EntryPointRequest* entryPoint,
- TargetRequest* targetReq)
+ TargetRequest* targetReq,
+ String& assemblyOut)
{
- List<uint8_t> spirv = emitSPIRVForEntryPoint(entryPoint, targetReq);
+ List<uint8_t> spirv;
+ SLANG_RETURN_ON_FAIL(emitSPIRVForEntryPoint(entryPoint, targetReq, spirv));
+
if (spirv.Count() == 0)
- return String();
+ return SLANG_FAIL;
- String result;
- dissassembleSPIRV(entryPoint->compileRequest, spirv.begin(), spirv.Count(), result);
- return result;
+ return dissassembleSPIRV(entryPoint->compileRequest, spirv.begin(), spirv.Count(), assemblyOut);
}
#endif
@@ -758,17 +836,23 @@ SlangResult dissassembleDXILUsingDXC(
#if SLANG_ENABLE_DXBC_SUPPORT
case CodeGenTarget::DXBytecode:
{
- List<uint8_t> code = EmitDXBytecodeForEntryPoint(entryPoint, targetReq);
- maybeDumpIntermediate(compileRequest, code.Buffer(), code.Count(), target);
- result = CompileResult(code);
+ List<uint8_t> code;
+ if (SLANG_SUCCEEDED(emitDXBytecodeForEntryPoint(entryPoint, targetReq, code)))
+ {
+ maybeDumpIntermediate(compileRequest, code.Buffer(), code.Count(), target);
+ result = CompileResult(code);
+ }
}
break;
case CodeGenTarget::DXBytecodeAssembly:
{
- String code = EmitDXBytecodeAssemblyForEntryPoint(entryPoint, targetReq);
- maybeDumpIntermediate(compileRequest, code.Buffer(), target);
- result = CompileResult(code);
+ String code;
+ if (SLANG_SUCCEEDED(emitDXBytecodeAssemblyForEntryPoint(entryPoint, targetReq, code)))
+ {
+ maybeDumpIntermediate(compileRequest, code.Buffer(), target);
+ result = CompileResult(code);
+ }
}
break;
#endif
@@ -777,8 +861,7 @@ SlangResult dissassembleDXILUsingDXC(
case CodeGenTarget::DXIL:
{
List<uint8_t> code;
- int err = emitDXILForEntryPointUsingDXC(entryPoint, targetReq, code);
- if (!err)
+ if (SLANG_SUCCEEDED(emitDXILForEntryPointUsingDXC(entryPoint, targetReq, code)))
{
maybeDumpIntermediate(compileRequest, code.Buffer(), code.Count(), target);
result = CompileResult(code);
@@ -789,8 +872,7 @@ SlangResult dissassembleDXILUsingDXC(
case CodeGenTarget::DXILAssembly:
{
List<uint8_t> code;
- int err = emitDXILForEntryPointUsingDXC(entryPoint, targetReq, code);
- if (!err)
+ if (SLANG_SUCCEEDED(emitDXILForEntryPointUsingDXC(entryPoint, targetReq, code)))
{
String assembly;
dissassembleDXILUsingDXC(
@@ -809,17 +891,23 @@ SlangResult dissassembleDXILUsingDXC(
case CodeGenTarget::SPIRV:
{
- List<uint8_t> code = emitSPIRVForEntryPoint(entryPoint, targetReq);
- maybeDumpIntermediate(compileRequest, code.Buffer(), code.Count(), target);
- result = CompileResult(code);
+ List<uint8_t> code;
+ if (SLANG_SUCCEEDED(emitSPIRVForEntryPoint(entryPoint, targetReq, code)))
+ {
+ maybeDumpIntermediate(compileRequest, code.Buffer(), code.Count(), target);
+ result = CompileResult(code);
+ }
}
break;
case CodeGenTarget::SPIRVAssembly:
{
- String code = emitSPIRVAssemblyForEntryPoint(entryPoint, targetReq);
- maybeDumpIntermediate(compileRequest, code.Buffer(), target);
- result = CompileResult(code);
+ String code;
+ if (SLANG_SUCCEEDED(emitSPIRVAssemblyForEntryPoint(entryPoint, targetReq, code)))
+ {
+ maybeDumpIntermediate(compileRequest, code.Buffer(), target);
+ result = CompileResult(code);
+ }
}
break;
diff --git a/source/slang/compiler.h b/source/slang/compiler.h
index 2c5d217e6..1cfb9201d 100644
--- a/source/slang/compiler.h
+++ b/source/slang/compiler.h
@@ -528,8 +528,24 @@ namespace Slang
char const* text,
CodeGenTarget target);
- /* Returns true if a codeGen target is available. */
+ /* Returns SLANG_OK if a codeGen target is available. */
SlangResult checkCompileTargetSupport(Session* session, CodeGenTarget target);
+ /* Returns SLANG_OK if pass through support is available */
+ SlangResult checkExternalCompilerSupport(Session* session, PassThroughMode passThrough);
+
+ /* Report an error appearing from external compiler to the diagnostic sink error to the diagnostic sink.
+ @param compilerName The name of the compiler the error came for (or nullptr if not known)
+ @param res Result associated with the error. The error code will be reported. (Can take HRESULT - and will expand to string if known)
+ @param diagnostic The diagnostic string associated with the compile failure
+ @param sink The diagnostic sink to report to */
+ void reportExternalCompileError(const char* compilerName, SlangResult res, const UnownedStringSlice& diagnostic, DiagnosticSink* sink);
+
+ /* Given a translationUnitRequest determines a filename that is most suitable to identify the input.
+ If the translation is a pass through will attempt to get the source file pathname. If the source is slang generated
+ there is no equivalent name so will return 'slang-generated'
+ @param translationUnitRequest The request to find an appropriate source path for
+ @return the appropriate source filename */
+ String calcTranslationUnitSourcePath(TranslationUnitRequest* translationUnitRequest);
struct TypeCheckingCache;
//
diff --git a/source/slang/diagnostics.cpp b/source/slang/diagnostics.cpp
index 4000fd967..4cad7ce94 100644
--- a/source/slang/diagnostics.cpp
+++ b/source/slang/diagnostics.cpp
@@ -263,6 +263,13 @@ void DiagnosticSink::diagnoseRaw(
Severity severity,
char const* message)
{
+ return diagnoseRaw(severity, UnownedStringSlice(message));
+}
+
+void DiagnosticSink::diagnoseRaw(
+ Severity severity,
+ const UnownedStringSlice& message)
+{
if (severity >= Severity::Error)
{
errorCount++;
@@ -272,7 +279,7 @@ void DiagnosticSink::diagnoseRaw(
if(writer)
{
// If so, pass the error string along to them
- writer->write(message, ::strlen(message));
+ writer->write(message.begin(), message.size());
}
else
{
diff --git a/source/slang/diagnostics.h b/source/slang/diagnostics.h
index 420b936a3..4c66ba51e 100644
--- a/source/slang/diagnostics.h
+++ b/source/slang/diagnostics.h
@@ -201,6 +201,9 @@ namespace Slang
void diagnoseRaw(
Severity severity,
char const* message);
+ void diagnoseRaw(
+ Severity severity,
+ const UnownedStringSlice& message);
};
namespace Diagnostics
diff --git a/source/slang/dxc-support.cpp b/source/slang/dxc-support.cpp
index b00583f10..7fe22191b 100644
--- a/source/slang/dxc-support.cpp
+++ b/source/slang/dxc-support.cpp
@@ -33,7 +33,19 @@ namespace Slang
EntryPointRequest* entryPoint,
TargetRequest* targetReq);
- int emitDXILForEntryPointUsingDXC(
+ 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();
+ }
+
+ SlangResult emitDXILForEntryPointUsingDXC(
EntryPointRequest* entryPoint,
TargetRequest* targetReq,
List<uint8_t>& outCode)
@@ -49,26 +61,20 @@ namespace Slang
auto dxcCreateInstance = (DxcCreateInstanceProc)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Dxc_DxcCreateInstance, &compileRequest->mSink);
if (!dxcCreateInstance)
{
- return 1;
+ return SLANG_FAIL;
}
- IDxcCompiler* dxcCompiler = nullptr;
- if (FAILED(dxcCreateInstance(
+ ComPtr<IDxcCompiler> dxcCompiler;
+ SLANG_RETURN_ON_FAIL(dxcCreateInstance(
CLSID_DxcCompiler,
__uuidof(dxcCompiler),
- (LPVOID*) &dxcCompiler)))
- {
- return 1;
- }
+ (LPVOID*)dxcCompiler.writeRef()));
- IDxcLibrary* dxcLibrary = nullptr;
- if (FAILED(dxcCreateInstance(
+ ComPtr<IDxcLibrary> dxcLibrary;
+ SLANG_RETURN_ON_FAIL(dxcCreateInstance(
CLSID_DxcLibrary,
__uuidof(dxcLibrary),
- (LPVOID*) &dxcLibrary)))
- {
- return 1;
- }
+ (LPVOID*)dxcLibrary.writeRef()));
// Now let's go ahead and generate HLSL for the entry
// point, since we'll need that to feed into dxc.
@@ -78,15 +84,12 @@ namespace Slang
// Wrap the
// Create blob from the string
- IDxcBlobEncoding* dxcSourceBlob = nullptr;
- if (FAILED(dxcLibrary->CreateBlobWithEncodingFromPinned(
+ ComPtr<IDxcBlobEncoding> dxcSourceBlob;
+ SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned(
(LPBYTE)hlslCode.Buffer(),
(UINT32)hlslCode.Length(),
0,
- &dxcSourceBlob)))
- {
- return 1;
- }
+ dxcSourceBlob.writeRef()));
WCHAR const* args[16];
UINT32 argCount = 0;
@@ -158,9 +161,11 @@ namespace Slang
args[argCount++] = L"-enable-16bit-types";
}
- IDxcOperationResult* dxcResult = nullptr;
- if (FAILED(dxcCompiler->Compile(dxcSourceBlob,
- L"slang",
+ const String sourcePath = calcTranslationUnitSourcePath(entryPoint->getTranslationUnit());
+
+ ComPtr<IDxcOperationResult> dxcResult;
+ SLANG_RETURN_ON_FAIL(dxcCompiler->Compile(dxcSourceBlob,
+ sourcePath.ToWString().begin(),
profile.GetStage() == Stage::Unknown ? L"" : wideEntryPointName.begin(),
wideProfileName.begin(),
args,
@@ -168,74 +173,44 @@ namespace Slang
nullptr, // `#define`s
0, // `#define` count
nullptr, // `#include` handler
- &dxcResult)))
- {
- return 1;
- }
+ dxcResult.writeRef()));
// Retrieve result.
HRESULT resultCode = S_OK;
- if (FAILED(dxcResult->GetStatus(&resultCode)))
- {
- // This indicates that we failed to retrieve the reuslt...
- return 1;
- }
-
+ 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 (FAILED(resultCode))
+ 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.
+ //
- // Try to read any diagnostic output.
- IDxcBlobEncoding* dxcErrorBlob = nullptr;
- if (!FAILED(dxcResult->GetErrorBuffer(&dxcErrorBlob)))
- {
- // 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.
- //
- // TODO: Alternatively, `diagnoseRaw()` should accept an
- // `UnownedStringSlice` instead of a `const char*`.
- //
- auto errorBegin = (char const*) dxcErrorBlob->GetBufferPointer();
- auto errorEnd = errorBegin + dxcErrorBlob->GetBufferSize();
- String errorString = UnownedStringSlice(errorBegin, errorEnd);
-
- compileRequest->mSink.diagnoseRaw(
- FAILED(resultCode) ? Severity::Error : Severity::Warning,
- errorString.Buffer());
- dxcErrorBlob->Release();
- }
-
- return 1;
+ reportExternalCompileError("dxc", resultCode, _getSlice(dxcErrorBlob), &entryPoint->compileRequest->mSink);
+ return resultCode;
}
// Okay, the compile supposedly succeeded, so we
// just need to grab the buffer with the output DXIL.
- IDxcBlob* dxcResultBlob = nullptr;
- if (FAILED(dxcResult->GetResult(&dxcResultBlob)))
- {
- return 1;
- }
-
+ ComPtr<IDxcBlob> dxcResultBlob;
+ SLANG_RETURN_ON_FAIL(dxcResult->GetResult(dxcResultBlob.writeRef()));
+
outCode.AddRange(
(uint8_t const*)dxcResultBlob->GetBufferPointer(),
(int) dxcResultBlob->GetBufferSize());
- // Clean up after ourselves.
-
- if(dxcResultBlob) dxcResultBlob ->Release();
- if(dxcResult) dxcResult ->Release();
- if(dxcLibrary) dxcLibrary ->Release();
- if(dxcCompiler) dxcCompiler ->Release();
-
- return 0;
+ return SLANG_OK;
}
SlangResult dissassembleDXILUsingDXC(
@@ -270,10 +245,8 @@ namespace Slang
ComPtr<IDxcBlobEncoding> dxcResultBlob;
SLANG_RETURN_ON_FAIL(dxcCompiler->Disassemble(dxcSourceBlob, dxcResultBlob.writeRef()));
- char const* codeBegin = (char const*)dxcResultBlob->GetBufferPointer();
- char const* codeEnd = codeBegin + dxcResultBlob->GetBufferSize() - 1;
- stringOut = String(codeBegin, codeEnd);
-
+ stringOut = _getSlice(dxcResultBlob);
+
return SLANG_OK;
}
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 22f6feac3..d516d0cb2 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -1209,6 +1209,14 @@ SLANG_API SlangResult spSessionCheckCompileTargetSupport(
return Slang::checkCompileTargetSupport(s, Slang::CodeGenTarget(target));
}
+SLANG_API SlangResult spSessionCheckPassThroughSupport(
+ SlangSession* session,
+ SlangPassThrough passThrough)
+{
+ auto s = SESSION(session);
+ return Slang::checkExternalCompilerSupport(s, Slang::PassThroughMode(passThrough));
+}
+
SLANG_API SlangCompileRequest* spCreateCompileRequest(
SlangSession* session)
{