diff options
Diffstat (limited to 'source/slang/dxc-support.cpp')
| -rw-r--r-- | source/slang/dxc-support.cpp | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/source/slang/dxc-support.cpp b/source/slang/dxc-support.cpp new file mode 100644 index 000000000..8de63f494 --- /dev/null +++ b/source/slang/dxc-support.cpp @@ -0,0 +1,280 @@ +// dxc-support.cpp +#include "compiler.h" + +// This file implements support for invoking the `dxcompiler` +// library to translate HLSL to DXIL. + +#if defined(_WIN32) +# if !defined(SLANG_ENABLE_DXIL_SUPPORT) +# define SLANG_ENABLE_DXIL_SUPPORT 1 +# endif +#endif + +#if !defined(SLANG_ENABLE_DXIL_SUPPORT) +# define SLANG_ENABLE_DXIL_SUPPORT 0 +#endif + +#if SLANG_ENABLE_DXIL_SUPPORT + +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include <Windows.h> +#include <Unknwn.h> +#include "../../external/dxc/dxcapi.h" +#undef WIN32_LEAN_AND_MEAN +#undef NOMINMAX + +#include "../core/platform.h" + +namespace Slang +{ + char const* GetHLSLProfileName(Profile profile); + String emitHLSLForEntryPoint( + EntryPointRequest* entryPoint, + TargetRequest* targetReq); + + SharedLibrary loadDXCSharedLibrary(CompileRequest* request) + { + // TODO(tfoley): Let user specify name/path of library to use. + char const* libraryName = "dxcompiler"; + + SharedLibrary library = SharedLibrary::load(libraryName); + if (!library) + { + request->mSink.diagnose(SourceLoc(), Diagnostics::failedToLoadDynamicLibrary, libraryName); + } + return library; + } + + SharedLibrary getDXCSharedLibrary(CompileRequest* request) + { + static SharedLibrary library = loadDXCSharedLibrary(request); + return library; + } + + int emitDXILForEntryPointUsingDXC( + EntryPointRequest* entryPoint, + TargetRequest* targetReq, + List<uint8_t>& outCode) + { + auto compileRequest = entryPoint->compileRequest; + + // First deal with all the rigamarole of loading + // the `dxcompiler` library, and creating the + // top-level COM objects that will be used to + // compile things. + + static DxcCreateInstanceProc dxcCreateInstance = nullptr; + if (!dxcCreateInstance) + { + auto dxcSharedLibrary = getDXCSharedLibrary(compileRequest); + if (!dxcSharedLibrary) + return 1; + + dxcCreateInstance = (DxcCreateInstanceProc) dxcSharedLibrary.findFuncByName("DxcCreateInstance"); + if (!dxcCreateInstance) + return 1; + } + + IDxcCompiler* dxcCompiler = nullptr; + if (FAILED(dxcCreateInstance( + CLSID_DxcCompiler, + __uuidof(dxcCompiler), + (LPVOID*) &dxcCompiler))) + { + return 1; + } + + IDxcLibrary* dxcLibrary = nullptr; + if (FAILED(dxcCreateInstance( + CLSID_DxcLibrary, + __uuidof(dxcLibrary), + (LPVOID*) &dxcLibrary))) + { + return 1; + } + + // Now let's go ahead and generate HLSL for the entry + // point, since we'll need that to feed into dxc. + auto hlslCode = emitHLSLForEntryPoint(entryPoint, targetReq); + maybeDumpIntermediate(entryPoint->compileRequest, hlslCode.Buffer(), CodeGenTarget::HLSL); + + // Wrap the + + // Create blob from the string + IDxcBlobEncoding* dxcSourceBlob = nullptr; + if (FAILED(dxcLibrary->CreateBlobWithEncodingFromPinned( + (LPBYTE)hlslCode.Buffer(), + (UINT32)hlslCode.Length(), + 0, + &dxcSourceBlob))) + { + return 1; + } + + WCHAR const* args[16]; + UINT32 argCount = 0; + + // TODO: deal with + bool treatWarningsAsErrors = false; + if (treatWarningsAsErrors) + { + args[argCount++] = L"-WX"; + } + + String entryPointName = getText(entryPoint->name); + OSString wideEntryPointName = entryPointName.ToWString(); + + String profileName = GetHLSLProfileName(entryPoint->profile); + OSString wideProfileName = profileName.ToWString(); + + + IDxcOperationResult* dxcResult = nullptr; + if (FAILED(dxcCompiler->Compile(dxcSourceBlob, + L"slang", + wideEntryPointName.begin(), + wideProfileName.begin(), + args, + argCount, + nullptr, // `#define`s + 0, // `#define` count + nullptr, // `#include` handler + &dxcResult))) + { + return 1; + } + + // Retrieve result. + HRESULT resultCode = S_OK; + if (FAILED(dxcResult->GetStatus(&resultCode))) + { + // This indicates that we failed to retrieve the reuslt... + return 1; + } + + // 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)) + { + // Compilation failed. + + + // Try to read any diagnostic output. + IDxcBlobEncoding* dxcErrorBlob = nullptr; + if (!FAILED(dxcResult->GetErrorBuffer(&dxcErrorBlob))) + { + void* data = dxcErrorBlob->GetBufferPointer(); + compileRequest->mSink.diagnoseRaw( + FAILED(resultCode) ? Severity::Error : Severity::Warning, + (char const*)dxcErrorBlob->GetBufferPointer()); + dxcErrorBlob->Release(); + } + + + return 1; + } + + // 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; + } + + 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; + } + + String dissassembleDXILUsingDXC( + CompileRequest* compileRequest, + void const* data, + size_t size) + { + // First deal with all the rigamarole of loading + // the `dxcompiler` library, and creating the + // top-level COM objects that will be used to + // compile things. + + static DxcCreateInstanceProc dxcCreateInstance = nullptr; + if (!dxcCreateInstance) + { + auto dxcSharedLibrary = getDXCSharedLibrary(compileRequest); + if (!dxcSharedLibrary) + return 1; + + dxcCreateInstance = (DxcCreateInstanceProc) dxcSharedLibrary.findFuncByName("DxcCreateInstance"); + if (!dxcCreateInstance) + return 1; + } + + IDxcCompiler* dxcCompiler = nullptr; + if (FAILED(dxcCreateInstance( + CLSID_DxcCompiler, + __uuidof(dxcCompiler), + (LPVOID*) &dxcCompiler))) + { + return 1; + } + + IDxcLibrary* dxcLibrary = nullptr; + if (FAILED(dxcCreateInstance( + CLSID_DxcLibrary, + __uuidof(dxcLibrary), + (LPVOID*) &dxcLibrary))) + { + return 1; + } + + // Create blob from the input data + IDxcBlobEncoding* dxcSourceBlob = nullptr; + if (FAILED(dxcLibrary->CreateBlobWithEncodingFromPinned( + (LPBYTE) data, + (UINT32) size, + 0, + &dxcSourceBlob))) + { + return 1; + } + + IDxcBlobEncoding* dxcResultBlob = nullptr; + if(FAILED(dxcCompiler->Disassemble( + dxcSourceBlob, + &dxcResultBlob))) + { + return 1; + } + + String result; + char const* codeBegin = (char const*)dxcResultBlob->GetBufferPointer(); + char const* codeEnd = codeBegin + dxcResultBlob->GetBufferSize() - 1; + result.append(codeBegin, codeEnd); + + if(dxcResultBlob) dxcResultBlob ->Release(); + if(dxcLibrary) dxcLibrary ->Release(); + if(dxcCompiler) dxcCompiler ->Release(); + + return result; + } + + +} // namespace Slang + +#endif + + + |
