diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/compiler.cpp | 83 | ||||
| -rw-r--r-- | source/slang/compiler.h | 7 | ||||
| -rw-r--r-- | source/slang/dxc-support.cpp | 280 | ||||
| -rw-r--r-- | source/slang/options.cpp | 3 | ||||
| -rw-r--r-- | source/slang/profile-defs.h | 29 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj | 1 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj.filters | 1 | ||||
| -rw-r--r-- | source/slang/type-layout.cpp | 2 |
8 files changed, 402 insertions, 4 deletions
diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp index 8cf801a79..f045253b0 100644 --- a/source/slang/compiler.cpp +++ b/source/slang/compiler.cpp @@ -15,7 +15,7 @@ #include "reflection.h" #include "emit.h" -// Enable calling through to `fxc` to +// Enable calling through to `fxc` or `dxc` to // generate code on Windows. #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -27,12 +27,18 @@ #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 by default: +// Otherwise, don't enable DXBC/DXIL by default: #ifndef SLANG_ENABLE_DXBC_SUPPORT #define SLANG_ENABLE_DXBC_SUPPORT 0 #endif +#ifndef SLANG_ENABLE_DXIL_SUPPORT + #define SLANG_ENABLE_DXIL_SUPPORT 0 +#endif // Enable calling through to `glslang` on // all platforms. @@ -356,6 +362,22 @@ namespace Slang } #endif +#if SLANG_ENABLE_DXIL_SUPPORT + +// Implementations in `dxc-support.cpp` + +int emitDXILForEntryPointUsingDXC( + EntryPointRequest* entryPoint, + TargetRequest* targetReq, + List<uint8_t>& outCode); + +String dissassembleDXILUsingDXC( + CompileRequest* compileRequest, + void const* data, + size_t size); + +#endif + #if SLANG_ENABLE_GLSLANG_SUPPORT SharedLibrary loadGLSLCompilerDLL(CompileRequest* request) @@ -540,6 +562,38 @@ namespace Slang break; #endif +#if SLANG_ENABLE_DXIL_SUPPORT + case CodeGenTarget::DXIL: + { + List<uint8_t> code; + int err = emitDXILForEntryPointUsingDXC(entryPoint, targetReq, code); + if (!err) + { + maybeDumpIntermediate(compileRequest, code.Buffer(), code.Count(), target); + result = CompileResult(code); + } + } + break; + + case CodeGenTarget::DXILAssembly: + { + List<uint8_t> code; + int err = emitDXILForEntryPointUsingDXC(entryPoint, targetReq, code); + if (!err) + { + String assembly = dissassembleDXILUsingDXC( + compileRequest, + code.Buffer(), + code.Count()); + + maybeDumpIntermediate(compileRequest, assembly.Buffer(), target); + + result = CompileResult(assembly); + } + } + break; +#endif + case CodeGenTarget::SPIRV: { List<uint8_t> code = emitSPIRVForEntryPoint(entryPoint, targetReq); @@ -703,6 +757,17 @@ namespace Slang break; #endif + #if SLANG_ENABLE_DXIL_SUPPORT + case CodeGenTarget::DXIL: + { + String assembly = dissassembleDXILUsingDXC(compileRequest, + data.begin(), + data.end() - data.begin()); + writeOutputToConsole(compileRequest, assembly); + } + break; + #endif + case CodeGenTarget::SPIRV: { String assembly = dissassembleSPIRV(compileRequest, @@ -943,6 +1008,20 @@ namespace Slang } break; #endif + + #if SLANG_ENABLE_DXIL_SUPPORT + case CodeGenTarget::DXILAssembly: + dumpIntermediateText(compileRequest, data, size, ".dxil.asm"); + break; + + case CodeGenTarget::DXIL: + dumpIntermediateBinary(compileRequest, data, size, ".dxil"); + { + String dxilAssembly = dissassembleDXILUsingDXC(compileRequest, data, size); + dumpIntermediateText(compileRequest, dxilAssembly.begin(), dxilAssembly.Length(), ".dxil.asm"); + } + break; + #endif } } diff --git a/source/slang/compiler.h b/source/slang/compiler.h index b7ab980fc..7b539ce69 100644 --- a/source/slang/compiler.h +++ b/source/slang/compiler.h @@ -47,6 +47,8 @@ namespace Slang SPIRVAssembly = SLANG_SPIRV_ASM, DXBytecode = SLANG_DXBC, DXBytecodeAssembly = SLANG_DXBC_ASM, + DXIL = SLANG_DXIL, + DXILAssembly = SLANG_DXIL_ASM, }; enum class ContainerFormat @@ -126,8 +128,9 @@ namespace Slang enum class PassThroughMode : SlangPassThrough { None = SLANG_PASS_THROUGH_NONE, // don't pass through: use Slang compiler - HLSL = SLANG_PASS_THROUGH_FXC, // pass through HLSL to `D3DCompile` API -// GLSL, // pass through GLSL to `glslang` library + fxc = SLANG_PASS_THROUGH_FXC, // pass through HLSL to `D3DCompile` API + dxc = SLANG_PASS_THROUGH_DXC, // pass through HLSL to `IDxcCompiler` API + glslang = SLANG_PASS_THROUGH_GLSLANG, // pass through GLSL to `glslang` library }; class SourceFile; 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 + + + diff --git a/source/slang/options.cpp b/source/slang/options.cpp index 971d17b51..7eea3fecc 100644 --- a/source/slang/options.cpp +++ b/source/slang/options.cpp @@ -317,6 +317,8 @@ struct OptionsParser CASE(spirv, SPIRV); CASE(spirv-assembly, SPIRV_ASM); + CASE(dxil, DXIL); + CASE(dxil-assembly, DXIL_ASM); CASE(none, TARGET_NONE); #undef CASE @@ -390,6 +392,7 @@ struct OptionsParser String name = tryReadCommandLineArgument(arg, &argCursor, argEnd); SlangPassThrough passThrough = SLANG_PASS_THROUGH_NONE; if (name == "fxc") { passThrough = SLANG_PASS_THROUGH_FXC; } + else if (name == "dxc") { passThrough = SLANG_PASS_THROUGH_DXC; } else if (name == "glslang") { passThrough = SLANG_PASS_THROUGH_GLSLANG; } else { diff --git a/source/slang/profile-defs.h b/source/slang/profile-defs.h index 84153ee46..ea23398e1 100644 --- a/source/slang/profile-defs.h +++ b/source/slang/profile-defs.h @@ -77,6 +77,9 @@ PROFILE_VERSION(DX_4_0_Level_9_1, DX) PROFILE_VERSION(DX_4_0_Level_9_3, DX) PROFILE_VERSION(DX_4_1, DX) PROFILE_VERSION(DX_5_0, DX) +PROFILE_VERSION(DX_6_0, DX) +PROFILE_VERSION(DX_6_1, DX) +PROFILE_VERSION(DX_6_2, DX) PROFILE_VERSION(GLSL_110, GLSL) PROFILE_VERSION(GLSL_120, GLSL) @@ -97,23 +100,49 @@ PROFILE_VERSION(GLSL_450, GLSL) PROFILE(DX_Compute_4_0, cs_4_0, Compute, DX_4_0) PROFILE(DX_Compute_4_1, cs_4_1, Compute, DX_4_1) PROFILE(DX_Compute_5_0, cs_5_0, Compute, DX_5_0) +PROFILE(DX_Compute_6_0, cs_6_0, Compute, DX_6_0) +PROFILE(DX_Compute_6_1, cs_6_1, Compute, DX_6_1) +PROFILE(DX_Compute_6_2, cs_6_2, Compute, DX_6_2) + PROFILE(DX_Domain_5_0, ds_5_0, Domain, DX_5_0) +PROFILE(DX_Domain_6_0, ds_6_0, Domain, DX_6_0) +PROFILE(DX_Domain_6_1, ds_6_1, Domain, DX_6_1) +PROFILE(DX_Domain_6_2, ds_6_2, Domain, DX_6_2) + PROFILE(DX_Geometry_4_0, gs_4_0, Geometry, DX_4_0) PROFILE(DX_Geometry_4_1, gs_4_1, Geometry, DX_4_1) PROFILE(DX_Geometry_5_0, gs_5_0, Geometry, DX_5_0) +PROFILE(DX_Geometry_6_0, gs_6_0, Geometry, DX_6_0) +PROFILE(DX_Geometry_6_1, gs_6_1, Geometry, DX_6_1) +PROFILE(DX_Geometry_6_2, gs_6_2, Geometry, DX_6_2) + + PROFILE(DX_Hull_5_0, hs_5_0, Hull, DX_5_0) +PROFILE(DX_Hull_6_0, hs_6_0, Hull, DX_6_0) +PROFILE(DX_Hull_6_1, hs_6_1, Hull, DX_6_1) +PROFILE(DX_Hull_6_2, hs_6_2, Hull, DX_6_2) + + PROFILE(DX_Fragment_4_0, ps_4_0, Fragment, DX_4_0) PROFILE(DX_Fragment_4_0_Level_9_0, ps_4_0_level_9_0, Fragment, DX_4_0_Level_9_0) PROFILE(DX_Fragment_4_0_Level_9_1, ps_4_0_level_9_1, Fragment, DX_4_0_Level_9_1) PROFILE(DX_Fragment_4_0_Level_9_3, ps_4_0_level_9_3, Fragment, DX_4_0_Level_9_3) PROFILE(DX_Fragment_4_1, ps_4_1, Fragment, DX_4_1) PROFILE(DX_Fragment_5_0, ps_5_0, Fragment, DX_5_0) +PROFILE(DX_Fragment_6_0, ps_6_0, Fragment, DX_6_0) +PROFILE(DX_Fragment_6_1, ps_6_1, Fragment, DX_6_1) +PROFILE(DX_Fragment_6_2, ps_6_2, Fragment, DX_6_2) + + PROFILE(DX_Vertex_4_0, vs_4_0, Vertex, DX_4_0) PROFILE(DX_Vertex_4_0_Level_9_0, vs_4_0_level_9_0, Vertex, DX_4_0_Level_9_0) PROFILE(DX_Vertex_4_0_Level_9_1, vs_4_0_level_9_1, Vertex, DX_4_0_Level_9_1) PROFILE(DX_Vertex_4_0_Level_9_3, vs_4_0_level_9_3, Vertex, DX_4_0_Level_9_3) PROFILE(DX_Vertex_4_1, vs_4_1, Vertex, DX_4_1) PROFILE(DX_Vertex_5_0, vs_5_0, Vertex, DX_5_0) +PROFILE(DX_Vertex_6_0, vs_6_0, Vertex, DX_6_0) +PROFILE(DX_Vertex_6_1, vs_6_1, Vertex, DX_6_1) +PROFILE(DX_Vertex_6_2, vs_6_2, Vertex, DX_6_2) // Define all the GLSL profiles diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj index 072556cb9..b09eae3ab 100644 --- a/source/slang/slang.vcxproj +++ b/source/slang/slang.vcxproj @@ -209,6 +209,7 @@ <ClCompile Include="check.cpp" /> <ClCompile Include="compiler.cpp" /> <ClCompile Include="diagnostics.cpp" /> + <ClCompile Include="dxc-support.cpp" /> <ClCompile Include="emit.cpp" /> <ClCompile Include="ir.cpp" /> <ClCompile Include="lexer.cpp" /> diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters index ba16ac8d8..ef9b3c8e5 100644 --- a/source/slang/slang.vcxproj.filters +++ b/source/slang/slang.vcxproj.filters @@ -70,6 +70,7 @@ <ClCompile Include="bytecode.cpp" /> <ClCompile Include="vm.cpp" /> <ClCompile Include="mangle.cpp" /> + <ClCompile Include="dxc-support.cpp" /> </ItemGroup> <ItemGroup> <CustomBuild Include="core.meta.slang" /> diff --git a/source/slang/type-layout.cpp b/source/slang/type-layout.cpp index 19b9a435e..0825da6b4 100644 --- a/source/slang/type-layout.cpp +++ b/source/slang/type-layout.cpp @@ -621,6 +621,8 @@ LayoutRulesFamilyImpl* GetLayoutRulesFamilyImpl(CodeGenTarget target) case CodeGenTarget::HLSL: case CodeGenTarget::DXBytecode: case CodeGenTarget::DXBytecodeAssembly: + case CodeGenTarget::DXIL: + case CodeGenTarget::DXILAssembly: return &kHLSLLayoutRulesFamilyImpl; case CodeGenTarget::GLSL: |
