diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-01-16 13:31:42 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-01-16 13:31:42 -0500 |
| commit | 86e11e0e111fab60b9517056ac049bfac6e3bd25 (patch) | |
| tree | f34a8343fb6a949235f1973dc873814f408987ef /source | |
| parent | c260e6aa3a7dc3e6794442daacde3ae23f029e0b (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.cpp | 38 | ||||
| -rw-r--r-- | source/core/platform.h | 9 | ||||
| -rw-r--r-- | source/slang/compiler.cpp | 336 | ||||
| -rw-r--r-- | source/slang/compiler.h | 18 | ||||
| -rw-r--r-- | source/slang/diagnostics.cpp | 9 | ||||
| -rw-r--r-- | source/slang/diagnostics.h | 3 | ||||
| -rw-r--r-- | source/slang/dxc-support.cpp | 121 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 8 |
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) { |
