diff options
| -rw-r--r-- | premake5.lua | 6 | ||||
| -rw-r--r-- | source/slang/compiler.cpp | 44 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang | 21 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang.h | 21 | ||||
| -rw-r--r-- | source/slang/profile-defs.h | 13 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj.filters | 22 | ||||
| -rw-r--r-- | tools/copy-hlsl-libs.bat | 11 | ||||
| -rw-r--r-- | tools/render-test/d3d-util.cpp | 4 | ||||
| -rw-r--r-- | tools/render-test/d3d-util.h | 4 | ||||
| -rw-r--r-- | tools/render-test/main.cpp | 38 | ||||
| -rw-r--r-- | tools/render-test/options.cpp | 4 | ||||
| -rw-r--r-- | tools/render-test/options.h | 3 | ||||
| -rw-r--r-- | tools/render-test/render-d3d11.cpp | 30 | ||||
| -rw-r--r-- | tools/render-test/render-d3d12.cpp | 42 | ||||
| -rw-r--r-- | tools/render-test/render-gl.cpp | 28 | ||||
| -rw-r--r-- | tools/render-test/render-test.vcxproj | 12 | ||||
| -rw-r--r-- | tools/render-test/render-vk.cpp | 45 | ||||
| -rw-r--r-- | tools/render-test/render.h | 50 | ||||
| -rw-r--r-- | tools/render-test/slang-support.cpp | 312 | ||||
| -rw-r--r-- | tools/render-test/slang-support.h | 16 |
20 files changed, 436 insertions, 290 deletions
diff --git a/premake5.lua b/premake5.lua index 390d67a92..9bb41e71b 100644 --- a/premake5.lua +++ b/premake5.lua @@ -366,8 +366,14 @@ tool "render-test" includedirs { ".", "external", "source" } links { "core", "slang" } filter { "system:windows" } + systemversion "10.0.14393.0" + -- For Windows targets, we want to copy d3dcompiler_47.dll, + -- dxcompiler.dll, and dxil.dll from the Windows SDK redistributable + -- directory into the output directory. + postbuildcommands { '"$(SolutionDir)tools\\copy-hlsl-libs.bat" "$(WindowsSdkDir)Redist/D3D/%{cfg.platform:lower()}/" "%{cfg.targetdir}/"'} + -- -- The `slangc` command-line application is just a very thin wrapper -- around the Slang dynamic library, so its build is extermely simple. diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp index b7cbc2327..66df01db0 100644 --- a/source/slang/compiler.cpp +++ b/source/slang/compiler.cpp @@ -279,13 +279,43 @@ namespace Slang auto profile = getEffectiveProfile(entryPoint, targetReq); + // 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; + if( entryPoint->compileRequest->passThrough != PassThroughMode::None ) + { + for( auto& define : entryPoint->compileRequest->preprocessorDefinitions ) + { + D3D_SHADER_MACRO dxMacro; + dxMacro.Name = define.Key.Buffer(); + dxMacro.Definition = define.Value.Buffer(); + dxMacrosStorage.Add(dxMacro); + } + for( auto& define : entryPoint->getTranslationUnit()->preprocessorDefinitions ) + { + D3D_SHADER_MACRO dxMacro; + dxMacro.Name = define.Key.Buffer(); + dxMacro.Definition = define.Value.Buffer(); + dxMacrosStorage.Add(dxMacro); + } + D3D_SHADER_MACRO nullTerminator = { 0, 0 }; + dxMacrosStorage.Add(nullTerminator); + + dxMacros = dxMacrosStorage.Buffer(); + } + ID3DBlob* codeBlob; ID3DBlob* diagnosticsBlob; HRESULT hr = D3DCompile_( hlslCode.begin(), hlslCode.Length(), "slang", - nullptr, + dxMacros, nullptr, getText(entryPoint->name).begin(), GetHLSLProfileName(profile), @@ -300,7 +330,17 @@ namespace Slang data.AddRange((uint8_t const*)codeBlob->GetBufferPointer(), (int)codeBlob->GetBufferSize()); codeBlob->Release(); } - if (diagnosticsBlob) + + // 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 diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 86f9eb946..10665915d 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -750,6 +750,27 @@ __generic<T : __BuiltinArithmeticType, let R : int, let N : int, let C : int> __ float noise(float x); __generic<let N : int> float noise(vector<float, N> x); +/// Indicate that an index may be non-uniform at execution time. +/// +/// Shader Model 5.1 and 6.x introduce support for dynamic indexing +/// of arrays of resources, but place the restriction that *by default* +/// the implementation can assume that any value used as an index into +/// such arrays will be dynamically uniform across an entire `Draw` or `Dispatch` +/// (when using instancing, the value must be uniform across all instances; +/// it does not seem that the restriction extends to draws within a multi-draw). +/// +/// In order to indicate to the implementation that it cannot make the +/// uniformity assumption, a shader programmer is required to pass the index +/// to the `NonUniformResourceIndex` function before using it as an index. +/// The function superficially acts like an identity function. +/// +/// Note: a future version of Slang may take responsibility for inserting calls +/// to this function as necessary in output code, rather than make this +/// the user's responsibility, so that the default behavior of the language +/// is more semantically "correct." +uint NonUniformResourceIndex(uint index); +int NonUniformResourceIndex(int index); + // Normalize a vector __generic<T : __BuiltinFloatingPointType, let N : int> vector<T,N> normalize(vector<T,N> x); diff --git a/source/slang/hlsl.meta.slang.h b/source/slang/hlsl.meta.slang.h index c05e81cd1..d63f38e47 100644 --- a/source/slang/hlsl.meta.slang.h +++ b/source/slang/hlsl.meta.slang.h @@ -783,6 +783,27 @@ SLANG_RAW("// noise (deprecated)\n") SLANG_RAW("float noise(float x);\n") SLANG_RAW("__generic<let N : int> float noise(vector<float, N> x);\n") SLANG_RAW("\n") +SLANG_RAW("/// Indicate that an index may be non-uniform at execution time.\n") +SLANG_RAW("///\n") +SLANG_RAW("/// Shader Model 5.1 and 6.x introduce support for dynamic indexing\n") +SLANG_RAW("/// of arrays of resources, but place the restriction that *by default*\n") +SLANG_RAW("/// the implementation can assume that any value used as an index into\n") +SLANG_RAW("/// such arrays will be dynamically uniform across an entire `Draw` or `Dispatch`\n") +SLANG_RAW("/// (when using instancing, the value must be uniform across all instances;\n") +SLANG_RAW("/// it does not seem that the restriction extends to draws within a multi-draw).\n") +SLANG_RAW("///\n") +SLANG_RAW("/// In order to indicate to the implementation that it cannot make the\n") +SLANG_RAW("/// uniformity assumption, a shader programmer is required to pass the index\n") +SLANG_RAW("/// to the `NonUniformResourceIndex` function before using it as an index.\n") +SLANG_RAW("/// The function superficially acts like an identity function.\n") +SLANG_RAW("///\n") +SLANG_RAW("/// Note: a future version of Slang may take responsibility for inserting calls\n") +SLANG_RAW("/// to this function as necessary in output code, rather than make this\n") +SLANG_RAW("/// the user's responsibility, so that the default behavior of the language\n") +SLANG_RAW("/// is more semantically \"correct.\"\n") +SLANG_RAW("uint NonUniformResourceIndex(uint index);\n") +SLANG_RAW("int NonUniformResourceIndex(int index);\n") +SLANG_RAW("\n") SLANG_RAW("// Normalize a vector\n") SLANG_RAW("__generic<T : __BuiltinFloatingPointType, let N : int> vector<T,N> normalize(vector<T,N> x);\n") SLANG_RAW("\n") diff --git a/source/slang/profile-defs.h b/source/slang/profile-defs.h index 2f029aff0..93703f3b9 100644 --- a/source/slang/profile-defs.h +++ b/source/slang/profile-defs.h @@ -205,6 +205,19 @@ PROFILE_ALIAS(DX_None_6_3, DX_Lib_6_3, sm_6_3) // Define all the GLSL profiles +PROFILE(GLSL_None_110, glsl_110, Unknown, GLSL_110) +PROFILE(GLSL_None_120, glsl_120, Unknown, GLSL_120) +PROFILE(GLSL_None_130, glsl_130, Unknown, GLSL_130) +PROFILE(GLSL_None_140, glsl_140, Unknown, GLSL_140) +PROFILE(GLSL_None_150, glsl_150, Unknown, GLSL_150) +PROFILE(GLSL_None_330, glsl_330, Unknown, GLSL_330) +PROFILE(GLSL_None_400, glsl_400, Unknown, GLSL_400) +PROFILE(GLSL_None_410, glsl_410, Unknown, GLSL_410) +PROFILE(GLSL_None_420, glsl_420, Unknown, GLSL_420) +PROFILE(GLSL_None_430, glsl_430, Unknown, GLSL_430) +PROFILE(GLSL_None_440, glsl_440, Unknown, GLSL_440) +PROFILE(GLSL_None_450, glsl_450, Unknown, GLSL_450) + #define P(UPPER, LOWER, VERSION) \ PROFILE(GLSL_##UPPER##_##VERSION, glsl_##LOWER##_##VERSION, UPPER, GLSL_##VERSION) diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters index cb0235e61..f12163f27 100644 --- a/source/slang/slang.vcxproj.filters +++ b/source/slang/slang.vcxproj.filters @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <Filter Include="Header Files"> @@ -54,6 +54,12 @@ <ClInclude Include="ir-insts.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="ir-restructure-scoping.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="ir-restructure.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="ir-ssa.h"> <Filter>Header Files</Filter> </ClInclude> @@ -153,10 +159,6 @@ <ClInclude Include="vm.h"> <Filter>Header Files</Filter> </ClInclude> - <ClInclude Include="ir-restructure.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="ir-restructure-scoping.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="bytecode.cpp"> @@ -186,6 +188,12 @@ <ClCompile Include="ir-legalize-types.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="ir-restructure-scoping.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="ir-restructure.cpp"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="ir-ssa.cpp"> <Filter>Source Files</Filter> </ClCompile> @@ -258,10 +266,6 @@ <ClCompile Include="vm.cpp"> <Filter>Source Files</Filter> </ClCompile> - <ClCompile Include="ir-restructure.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="ir-restructure-scoping.cpp" /> </ItemGroup> <ItemGroup> <None Include="slang.natvis"> diff --git a/tools/copy-hlsl-libs.bat b/tools/copy-hlsl-libs.bat new file mode 100644 index 000000000..91d5be852 --- /dev/null +++ b/tools/copy-hlsl-libs.bat @@ -0,0 +1,11 @@ +@echo off +setlocal + +set SOURCE_DIR=%~1 +set TARGET_DIR=%~2 + +robocopy "%SOURCE_DIR%" "%TARGET_DIR%" d3dcompiler_47.dll /r:0 >nul +robocopy "%SOURCE_DIR%" "%TARGET_DIR%" dxcompiler.dll /r:0 >nul +robocopy "%SOURCE_DIR%" "%TARGET_DIR%" dxil.dll /r:0 >nul + +exit /b 0 diff --git a/tools/render-test/d3d-util.cpp b/tools/render-test/d3d-util.cpp index bef0e6baa..08aa563ca 100644 --- a/tools/render-test/d3d-util.cpp +++ b/tools/render-test/d3d-util.cpp @@ -214,6 +214,10 @@ bool D3DUtil::isTypeless(DXGI_FORMAT format) } } +// Note: this subroutine is now only used by D3D11 for generating bytecode to go into input layouts. +// +// TODO: we can probably remove that code completely by switching to a PSO-like model across all APIs. +// /* static */Result D3DUtil::compileHLSLShader(char const* sourcePath, char const* source, char const* entryPointName, char const* dxProfileName, ComPtr<ID3DBlob>& shaderBlobOut) { // Rather than statically link against the `d3dcompile` library, we diff --git a/tools/render-test/d3d-util.h b/tools/render-test/d3d-util.h index 6ac39aefb..51eefd151 100644 --- a/tools/render-test/d3d-util.h +++ b/tools/render-test/d3d-util.h @@ -36,9 +36,7 @@ class D3DUtil /// Calculate size taking into account alignment. Alignment must be a power of 2 static UInt calcAligned(UInt size, UInt alignment) { return (size + alignment - 1) & ~(alignment - 1); } - /// The Slang compiler currently generates HLSL source, so we'll need a utility - /// routine (defined later) to translate that into D3D11 shader bytecode. - /// Definition of the HLSL-to-bytecode compilation logic. + /// Compile HLSL code to DXBC static Slang::Result compileHLSLShader(char const* sourcePath, char const* source, char const* entryPointName, char const* dxProfileName, Slang::ComPtr<ID3DBlob>& shaderBlobOut); /// Given a slang pixel format returns the equivalent DXGI_ pixel format. If the format is not known, will return DXGI_FORMAT_UNKNOWN diff --git a/tools/render-test/main.cpp b/tools/render-test/main.cpp index 767c33e14..935b9bc98 100644 --- a/tools/render-test/main.cpp +++ b/tools/render-test/main.cpp @@ -96,12 +96,6 @@ static const char vertexEntryPointName[] = "vertexMain"; static const char fragmentEntryPointName[] = "fragmentMain"; static const char computeEntryPointName[] = "computeMain"; -// "Profile" to use when compiling for HLSL targets -// TODO: does this belong here? -static const char vertexProfileName[] = "vs_5_0"; -static const char fragmentProfileName[] = "ps_5_0"; -static const char computeProfileName[] = "cs_5_0"; - SlangResult RenderTestApp::initialize(Renderer* renderer, ShaderCompiler* shaderCompiler) { SLANG_RETURN_ON_FAIL(initializeShaders(shaderCompiler)); @@ -201,16 +195,13 @@ Result RenderTestApp::initializeShaders(ShaderCompiler* shaderCompiler) { compileRequest.vertexShader.source = sourceInfo; compileRequest.vertexShader.name = vertexEntryPointName; - compileRequest.vertexShader.profile = vertexProfileName; compileRequest.fragmentShader.source = sourceInfo; compileRequest.fragmentShader.name = fragmentEntryPointName; - compileRequest.fragmentShader.profile = fragmentProfileName; } else { compileRequest.computeShader.source = sourceInfo; compileRequest.computeShader.name = computeEntryPointName; - compileRequest.computeShader.profile = computeProfileName; } compileRequest.entryPointTypeArguments = m_shaderInputLayout.globalTypeArguments; m_shaderProgram = shaderCompiler->compileProgram(compileRequest); @@ -412,30 +403,40 @@ SlangResult innerMain(int argc, char** argv) SlangSourceLanguage nativeLanguage = SLANG_SOURCE_LANGUAGE_UNKNOWN; SlangCompileTarget slangTarget = SLANG_TARGET_NONE; + SlangPassThrough slangPassThrough = SLANG_PASS_THROUGH_NONE; + char const* profileName = ""; switch (gOptions.rendererType) { case RendererType::DirectX11: renderer = createD3D11Renderer(); - slangTarget = SLANG_HLSL; + slangTarget = SLANG_DXBC; nativeLanguage = SLANG_SOURCE_LANGUAGE_HLSL; + slangPassThrough = SLANG_PASS_THROUGH_FXC; + profileName = "sm_5_0"; break; case RendererType::DirectX12: renderer = createD3D12Renderer(); - slangTarget = SLANG_HLSL; + slangTarget = SLANG_DXBC; nativeLanguage = SLANG_SOURCE_LANGUAGE_HLSL; + slangPassThrough = SLANG_PASS_THROUGH_FXC; + profileName = "sm_5_0"; break; case RendererType::OpenGl: renderer = createGLRenderer(); slangTarget = SLANG_GLSL; nativeLanguage = SLANG_SOURCE_LANGUAGE_GLSL; + slangPassThrough = SLANG_PASS_THROUGH_GLSLANG; + profileName = "glsl_430"; break; case RendererType::Vulkan: renderer = createVKRenderer(); slangTarget = SLANG_SPIRV; nativeLanguage = SLANG_SOURCE_LANGUAGE_GLSL; + slangPassThrough = SLANG_PASS_THROUGH_GLSLANG; + profileName = "glsl_430"; break; default: @@ -449,15 +450,20 @@ SlangResult innerMain(int argc, char** argv) SLANG_RETURN_ON_FAIL(renderer->initialize(desc, windowHandle)); - auto shaderCompiler = renderer->getShaderCompiler(); + ShaderCompiler shaderCompiler; + shaderCompiler.renderer = renderer; + shaderCompiler.target = slangTarget; + shaderCompiler.profile = profileName; switch (gOptions.inputLanguageID) { case Options::InputLanguageID::Slang: - shaderCompiler = createSlangShaderCompiler(shaderCompiler, SLANG_SOURCE_LANGUAGE_SLANG, slangTarget); + shaderCompiler.sourceLanguage = SLANG_SOURCE_LANGUAGE_SLANG; + shaderCompiler.passThrough = SLANG_PASS_THROUGH_NONE; break; - case Options::InputLanguageID::NativeRewrite: - shaderCompiler = createSlangShaderCompiler(shaderCompiler, nativeLanguage, slangTarget); + case Options::InputLanguageID::Native: + shaderCompiler.sourceLanguage = nativeLanguage; + shaderCompiler.passThrough = slangPassThrough; break; default: @@ -467,7 +473,7 @@ SlangResult innerMain(int argc, char** argv) { RenderTestApp app; - SLANG_RETURN_ON_FAIL(app.initialize(renderer, shaderCompiler)); + SLANG_RETURN_ON_FAIL(app.initialize(renderer, &shaderCompiler)); // Once initialization is all complete, we show the window... ShowWindow(windowHandle, showCommand); diff --git a/tools/render-test/options.cpp b/tools/render-test/options.cpp index 1aa72c033..54aa3c429 100644 --- a/tools/render-test/options.cpp +++ b/tools/render-test/options.cpp @@ -75,12 +75,12 @@ SlangResult parseOptions(int* argc, char** argv) else if( strcmp(arg, "-hlsl-rewrite") == 0 ) { setDefaultRendererType( RendererType::DirectX11); - gOptions.inputLanguageID = InputLanguageID::NativeRewrite; + gOptions.inputLanguageID = InputLanguageID::Slang; } else if( strcmp(arg, "-glsl-rewrite") == 0 ) { setDefaultRendererType(RendererType::OpenGl); - gOptions.inputLanguageID = InputLanguageID::NativeRewrite; + gOptions.inputLanguageID = InputLanguageID::Slang; } else if( strcmp(arg, "-slang") == 0 ) { diff --git a/tools/render-test/options.h b/tools/render-test/options.h index 630c30d8a..4c0f1098f 100644 --- a/tools/render-test/options.h +++ b/tools/render-test/options.h @@ -24,9 +24,6 @@ struct Options // Raw HLSL or GLSL input, bypassing Slang Native, - - // Raw HLSL or GLSL input, passed through the Slang rewriter - NativeRewrite }; diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp index 0ba2c8dc3..1ca293fad 100644 --- a/tools/render-test/render-d3d11.cpp +++ b/tools/render-test/render-d3d11.cpp @@ -42,7 +42,7 @@ using namespace Slang; namespace renderer_test { -class D3D11Renderer : public Renderer, public ShaderCompiler +class D3D11Renderer : public Renderer { public: // Renderer implementation @@ -55,7 +55,7 @@ public: virtual SlangResult captureScreenSurface(Surface& surfaceOut) override; virtual InputLayout* createInputLayout( const InputElementDesc* inputElements, UInt inputElementCount) override; virtual BindingState* createBindingState(const BindingState::Desc& desc) override; - virtual ShaderCompiler* getShaderCompiler() override; + virtual ShaderProgram* createProgram(const ShaderProgram::Desc& desc) override; virtual void* map(BufferResource* buffer, MapFlavor flavor) override; virtual void unmap(BufferResource* buffer) override; virtual void setInputLayout(InputLayout* inputLayout) override; @@ -69,9 +69,6 @@ public: virtual void waitForGpu() override {} virtual RendererType getRendererType() const override { return RendererType::DirectX11; } - // ShaderCompiler implementation - virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override; - protected: struct BindingDetail @@ -380,11 +377,6 @@ SlangResult D3D11Renderer::captureScreenSurface(Surface& surfaceOut) return captureTextureToSurface(m_device, m_immediateContext, m_renderTargetTextures[0], surfaceOut); } -ShaderCompiler* D3D11Renderer::getShaderCompiler() -{ - return this; -} - static D3D11_BIND_FLAG _calcResourceFlag(Resource::BindFlag::Enum bindFlag) { typedef Resource::BindFlag BindFlag; @@ -784,15 +776,14 @@ void D3D11Renderer::draw(UInt vertexCount, UInt startVertex) m_immediateContext->Draw((UINT)vertexCount, (UINT)startVertex); } -ShaderProgram* D3D11Renderer::compileProgram(const ShaderCompileRequest& request) +ShaderProgram* D3D11Renderer::createProgram(const ShaderProgram::Desc& desc) { - if (request.computeShader.name) + if (desc.pipelineType == PipelineType::Compute) { - ComPtr<ID3DBlob> computeShaderBlob; - SLANG_RETURN_NULL_ON_FAIL(D3DUtil::compileHLSLShader(request.computeShader.source.path, request.computeShader.source.dataBegin, request.computeShader.name, request.computeShader.profile, computeShaderBlob)); + auto computeKernel = desc.findKernel(StageType::Compute); ComPtr<ID3D11ComputeShader> computeShader; - SLANG_RETURN_NULL_ON_FAIL(m_device->CreateComputeShader(computeShaderBlob->GetBufferPointer(), computeShaderBlob->GetBufferSize(), nullptr, computeShader.writeRef())); + SLANG_RETURN_NULL_ON_FAIL(m_device->CreateComputeShader(computeKernel->codeBegin, computeKernel->getCodeSize(), nullptr, computeShader.writeRef())); ShaderProgramImpl* shaderProgram = new ShaderProgramImpl(); shaderProgram->m_computeShader.swap(computeShader); @@ -800,15 +791,14 @@ ShaderProgram* D3D11Renderer::compileProgram(const ShaderCompileRequest& request } else { - ComPtr<ID3DBlob> vertexShaderBlob, fragmentShaderBlob; - SLANG_RETURN_NULL_ON_FAIL(D3DUtil::compileHLSLShader(request.vertexShader.source.path, request.vertexShader.source.dataBegin, request.vertexShader.name, request.vertexShader.profile, vertexShaderBlob)); - SLANG_RETURN_NULL_ON_FAIL(D3DUtil::compileHLSLShader(request.fragmentShader.source.path, request.fragmentShader.source.dataBegin, request.fragmentShader.name, request.fragmentShader.profile, fragmentShaderBlob)); + auto vertexKernel = desc.findKernel(StageType::Vertex); + auto fragmentKernel = desc.findKernel(StageType::Fragment); ComPtr<ID3D11VertexShader> vertexShader; ComPtr<ID3D11PixelShader> pixelShader; - SLANG_RETURN_NULL_ON_FAIL(m_device->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, vertexShader.writeRef())); - SLANG_RETURN_NULL_ON_FAIL(m_device->CreatePixelShader(fragmentShaderBlob->GetBufferPointer(), fragmentShaderBlob->GetBufferSize(), nullptr, pixelShader.writeRef())); + SLANG_RETURN_NULL_ON_FAIL(m_device->CreateVertexShader(vertexKernel->codeBegin, vertexKernel->getCodeSize(), nullptr, vertexShader.writeRef())); + SLANG_RETURN_NULL_ON_FAIL(m_device->CreatePixelShader(fragmentKernel->codeBegin, fragmentKernel->getCodeSize(), nullptr, pixelShader.writeRef())); ShaderProgramImpl* shaderProgram = new ShaderProgramImpl(); shaderProgram->m_vertexShader.swap(vertexShader); diff --git a/tools/render-test/render-d3d12.cpp b/tools/render-test/render-d3d12.cpp index 430a273ef..593991205 100644 --- a/tools/render-test/render-d3d12.cpp +++ b/tools/render-test/render-d3d12.cpp @@ -49,7 +49,7 @@ namespace renderer_test { using namespace Slang; -class D3D12Renderer : public Renderer, public ShaderCompiler +class D3D12Renderer : public Renderer { public: // Renderer implementation @@ -62,7 +62,7 @@ public: virtual SlangResult captureScreenSurface(Surface& surfaceOut) override; virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) override; virtual BindingState* createBindingState(const BindingState::Desc& bindingStateDesc) override; - virtual ShaderCompiler* getShaderCompiler() override; + virtual ShaderProgram* createProgram(const ShaderProgram::Desc& desc) override; virtual void* map(BufferResource* buffer, MapFlavor flavor) override; virtual void unmap(BufferResource* buffer) override; virtual void setInputLayout(InputLayout* inputLayout) override; @@ -76,9 +76,6 @@ public: virtual void waitForGpu() override; virtual RendererType getRendererType() const override { return RendererType::DirectX12; } - // ShaderCompiler implementation - virtual ShaderProgram* compileProgram(const ShaderCompileRequest& request) override; - ~D3D12Renderer(); protected: @@ -1685,11 +1682,6 @@ SlangResult D3D12Renderer::captureScreenSurface(Surface& surfaceOut) return captureTextureToSurface(*m_renderTargets[m_renderTargetIndex], surfaceOut); } -ShaderCompiler* D3D12Renderer::getShaderCompiler() -{ - return this; -} - static D3D12_RESOURCE_STATES _calcResourceState(Resource::Usage usage) { typedef Resource::Usage Usage; @@ -2343,6 +2335,10 @@ BindingState* D3D12Renderer::createBindingState(const BindingState::Desc& bindin uavDesc.Buffer.StructureByteStride = 0; } + else if( bufferDesc.format != Format::Unknown ) + { + uavDesc.Buffer.StructureByteStride = 0; + } m_device->CreateUnorderedAccessView(bufferResource->m_resource, nullptr, &uavDesc, bindingState->m_viewHeap.getCpuHandle(dstDetail.m_uavIndex)); } @@ -2445,29 +2441,23 @@ void D3D12Renderer::setBindingState(BindingState* state) m_boundBindingState = static_cast<BindingStateImpl*>(state); } -// ShaderCompiler interface - -ShaderProgram* D3D12Renderer::compileProgram(const ShaderCompileRequest& request) +ShaderProgram* D3D12Renderer::createProgram(const ShaderProgram::Desc& desc) { - RefPtr<ShaderProgramImpl> program(new ShaderProgramImpl); + RefPtr<ShaderProgramImpl> program(new ShaderProgramImpl()); + program->m_pipelineType = desc.pipelineType; - if (request.computeShader.name) + if (desc.pipelineType == PipelineType::Compute) { - program->m_pipelineType = PipelineType::Compute; - ComPtr<ID3DBlob> computeShaderBlob; - SLANG_RETURN_NULL_ON_FAIL(D3DUtil::compileHLSLShader(request.computeShader.source.path, request.computeShader.source.dataBegin, request.computeShader.name, request.computeShader.profile, computeShaderBlob)); - - program->m_computeShader.InsertRange(0, (const uint8_t*)computeShaderBlob->GetBufferPointer(), UInt(computeShaderBlob->GetBufferSize())); + auto computeKernel = desc.findKernel(StageType::Compute); + program->m_computeShader.InsertRange(0, (const uint8_t*) computeKernel->codeBegin, computeKernel->getCodeSize()); } else { - program->m_pipelineType = PipelineType::Graphics; - ComPtr<ID3DBlob> vertexShaderBlob, fragmentShaderBlob; - SLANG_RETURN_NULL_ON_FAIL(D3DUtil::compileHLSLShader(request.vertexShader.source.path, request.vertexShader.source.dataBegin, request.vertexShader.name, request.vertexShader.profile, vertexShaderBlob)); - SLANG_RETURN_NULL_ON_FAIL(D3DUtil::compileHLSLShader(request.fragmentShader.source.path, request.fragmentShader.source.dataBegin, request.fragmentShader.name, request.fragmentShader.profile, fragmentShaderBlob)); + auto vertexKernel = desc.findKernel(StageType::Vertex); + auto fragmentKernel = desc.findKernel(StageType::Fragment); - program->m_vertexShader.InsertRange(0, (const uint8_t*)vertexShaderBlob->GetBufferPointer(), UInt(vertexShaderBlob->GetBufferSize())); - program->m_pixelShader.InsertRange(0, (const uint8_t*)fragmentShaderBlob->GetBufferPointer(), UInt(fragmentShaderBlob->GetBufferSize())); + program->m_vertexShader.InsertRange(0, (const uint8_t*) vertexKernel->codeBegin, vertexKernel->getCodeSize()); + program->m_pixelShader.InsertRange(0, (const uint8_t*) fragmentKernel->codeBegin, fragmentKernel->getCodeSize()); } return program.detach(); diff --git a/tools/render-test/render-gl.cpp b/tools/render-test/render-gl.cpp index 00e4427b8..dc9f0c43a 100644 --- a/tools/render-test/render-gl.cpp +++ b/tools/render-test/render-gl.cpp @@ -75,7 +75,7 @@ using namespace Slang; namespace renderer_test { -class GLRenderer : public Renderer, public ShaderCompiler +class GLRenderer : public Renderer { public: @@ -89,7 +89,7 @@ public: virtual SlangResult captureScreenSurface(Surface& surfaceOut) override; virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) override; virtual BindingState* createBindingState(const BindingState::Desc& bindingStateDesc) override; - virtual ShaderCompiler* getShaderCompiler() override; + virtual ShaderProgram* createProgram(const ShaderProgram::Desc& desc) override; virtual void* map(BufferResource* buffer, MapFlavor flavor) override; virtual void unmap(BufferResource* buffer) override; virtual void setInputLayout(InputLayout* inputLayout) override; @@ -103,9 +103,6 @@ public: virtual void waitForGpu() override {} virtual RendererType getRendererType() const override { return RendererType::OpenGl; } - // ShaderCompiler implementation - virtual ShaderProgram* compileProgram(const ShaderCompileRequest& request) override; - protected: enum { @@ -592,11 +589,6 @@ SlangResult GLRenderer::captureScreenSurface(Surface& surfaceOut) return SLANG_OK; } -ShaderCompiler* GLRenderer::getShaderCompiler() -{ - return this; -} - TextureResource* GLRenderer::createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& descIn, const TextureResource::Data* initData) { TextureResource::Desc srcDesc(descIn); @@ -999,22 +991,24 @@ void GLRenderer::setBindingState(BindingState* stateIn) } } -// ShaderCompiler interface - -ShaderProgram* GLRenderer::compileProgram(const ShaderCompileRequest& request) +ShaderProgram* GLRenderer::createProgram(const ShaderProgram::Desc& desc) { auto programID = glCreateProgram(); - if (request.computeShader.name) + if(desc.pipelineType == PipelineType::Compute ) { - auto computeShaderID = loadShader(GL_COMPUTE_SHADER, request.computeShader.source.dataBegin); + auto computeKernel = desc.findKernel(StageType::Compute); + auto computeShaderID = loadShader(GL_COMPUTE_SHADER, (char const*) computeKernel->codeBegin); glAttachShader(programID, computeShaderID); glLinkProgram(programID); glDeleteShader(computeShaderID); } else { - auto vertexShaderID = loadShader(GL_VERTEX_SHADER, request.vertexShader.source.dataBegin); - auto fragmentShaderID = loadShader(GL_FRAGMENT_SHADER, request.fragmentShader.source.dataBegin); + auto vertexKernel = desc.findKernel(StageType::Vertex); + auto fragmentKernel = desc.findKernel(StageType::Fragment); + + auto vertexShaderID = loadShader(GL_VERTEX_SHADER, (char const*) vertexKernel->codeBegin); + auto fragmentShaderID = loadShader(GL_FRAGMENT_SHADER, (char const*) fragmentKernel->codeBegin); glAttachShader(programID, vertexShaderID); glAttachShader(programID, fragmentShaderID); diff --git a/tools/render-test/render-test.vcxproj b/tools/render-test/render-test.vcxproj index eabb11615..915d0d753 100644 --- a/tools/render-test/render-test.vcxproj +++ b/tools/render-test/render-test.vcxproj @@ -108,6 +108,9 @@ <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> </Link> + <PostBuildEvent> + <Command>"$(SolutionDir)tools\copy-hlsl-libs.bat" "$(WindowsSdkDir)Redist/D3D/x86/" "../../bin/windows-x86/debug/"</Command> + </PostBuildEvent> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ClCompile> @@ -123,6 +126,9 @@ <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> </Link> + <PostBuildEvent> + <Command>"$(SolutionDir)tools\copy-hlsl-libs.bat" "$(WindowsSdkDir)Redist/D3D/x64/" "../../bin/windows-x64/debug/"</Command> + </PostBuildEvent> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> @@ -142,6 +148,9 @@ <EnableCOMDATFolding>true</EnableCOMDATFolding> <OptimizeReferences>true</OptimizeReferences> </Link> + <PostBuildEvent> + <Command>"$(SolutionDir)tools\copy-hlsl-libs.bat" "$(WindowsSdkDir)Redist/D3D/x86/" "../../bin/windows-x86/release/"</Command> + </PostBuildEvent> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ClCompile> @@ -161,6 +170,9 @@ <EnableCOMDATFolding>true</EnableCOMDATFolding> <OptimizeReferences>true</OptimizeReferences> </Link> + <PostBuildEvent> + <Command>"$(SolutionDir)tools\copy-hlsl-libs.bat" "$(WindowsSdkDir)Redist/D3D/x64/" "../../bin/windows-x64/release/"</Command> + </PostBuildEvent> </ItemDefinitionGroup> <ItemGroup> <ClInclude Include="circular-resource-heap-d3d12.h" /> diff --git a/tools/render-test/render-vk.cpp b/tools/render-test/render-vk.cpp index 5be1f5684..bbdc2f08c 100644 --- a/tools/render-test/render-vk.cpp +++ b/tools/render-test/render-vk.cpp @@ -29,7 +29,7 @@ namespace renderer_test { using namespace Slang; -class VKRenderer : public Renderer, public ShaderCompiler +class VKRenderer : public Renderer { public: enum { kMaxRenderTargets = 8, kMaxAttachments = kMaxRenderTargets + 1 }; @@ -44,7 +44,7 @@ public: virtual SlangResult captureScreenSurface(Surface& surface) override; virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) override; virtual BindingState* createBindingState(const BindingState::Desc& bindingStateDesc) override; - virtual ShaderCompiler* getShaderCompiler() override; + virtual ShaderProgram* createProgram(const ShaderProgram::Desc& desc) override; virtual void* map(BufferResource* buffer, MapFlavor flavor) override; virtual void unmap(BufferResource* buffer) override; virtual void setInputLayout(InputLayout* inputLayout) override; @@ -58,9 +58,6 @@ public: virtual void waitForGpu() override; virtual RendererType getRendererType() const override { return RendererType::Vulkan; } - // ShaderCompiler implementation - virtual ShaderProgram* compileProgram(const ShaderCompileRequest& request) override; - /// Dtor ~VKRenderer(); @@ -267,7 +264,10 @@ public: VkBool32 handleDebugMessage(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg); - VkPipelineShaderStageCreateInfo compileEntryPoint(const ShaderCompileRequest::EntryPoint& entryPointRequest, VkShaderStageFlagBits stage, List<char>& bufferOut); + VkPipelineShaderStageCreateInfo compileEntryPoint( + ShaderProgram::KernelDesc const& kernelDesc, + VkShaderStageFlagBits stage, + List<char>& bufferOut); static VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void* pUserData); @@ -922,10 +922,13 @@ VkBool32 VKRenderer::handleDebugMessage(VkDebugReportFlagsEXT flags, VkDebugRepo return ((VKRenderer*)pUserData)->handleDebugMessage(flags, objType, srcObject, location, msgCode, pLayerPrefix, pMsg); } -VkPipelineShaderStageCreateInfo VKRenderer::compileEntryPoint(const ShaderCompileRequest::EntryPoint& entryPointRequest, VkShaderStageFlagBits stage, List<char>& bufferOut) +VkPipelineShaderStageCreateInfo VKRenderer::compileEntryPoint( + ShaderProgram::KernelDesc const& kernelDesc, + VkShaderStageFlagBits stage, + List<char>& bufferOut) { - char const* dataBegin = entryPointRequest.source.dataBegin; - char const* dataEnd = entryPointRequest.source.dataEnd; + char const* dataBegin = (char const*) kernelDesc.codeBegin; + char const* dataEnd = (char const*) kernelDesc.codeEnd; // We need to make a copy of the code, since the Slang compiler // will free the memory after a compile request is closed. @@ -1192,11 +1195,6 @@ SlangResult VKRenderer::captureScreenSurface(Surface& surfaceOut) return SLANG_FAIL; } -ShaderCompiler* VKRenderer::getShaderCompiler() -{ - return this; -} - static VkBufferUsageFlagBits _calcBufferUsageFlags(Resource::BindFlag::Enum bind) { typedef Resource::BindFlag BindFlag; @@ -1999,20 +1997,21 @@ void VKRenderer::setBindingState(BindingState* state) m_currentBindingState = static_cast<BindingStateImpl*>(state); } -// ShaderCompiler interface -ShaderProgram* VKRenderer::compileProgram(const ShaderCompileRequest& request) +ShaderProgram* VKRenderer::createProgram(const ShaderProgram::Desc& desc) { - const PipelineType pipelineType = request.computeShader.name ? PipelineType::Compute : PipelineType::Graphics; - - ShaderProgramImpl* impl = new ShaderProgramImpl(pipelineType); - if (request.computeShader.name) + ShaderProgramImpl* impl = new ShaderProgramImpl(desc.pipelineType); + if( desc.pipelineType == PipelineType::Compute) { - impl->m_compute = compileEntryPoint(request.computeShader, VK_SHADER_STAGE_COMPUTE_BIT, impl->m_buffers[0]); + auto computeKernel = desc.findKernel(StageType::Compute); + impl->m_compute = compileEntryPoint(*computeKernel, VK_SHADER_STAGE_COMPUTE_BIT, impl->m_buffers[0]); } else { - impl->m_vertex = compileEntryPoint(request.vertexShader, VK_SHADER_STAGE_VERTEX_BIT, impl->m_buffers[0]); - impl->m_fragment = compileEntryPoint(request.fragmentShader, VK_SHADER_STAGE_FRAGMENT_BIT, impl->m_buffers[1]); + auto vertexKernel = desc.findKernel(StageType::Vertex); + auto fragmentKernel = desc.findKernel(StageType::Fragment); + + impl->m_vertex = compileEntryPoint(*vertexKernel, VK_SHADER_STAGE_VERTEX_BIT, impl->m_buffers[0]); + impl->m_fragment = compileEntryPoint(*fragmentKernel, VK_SHADER_STAGE_FRAGMENT_BIT, impl->m_buffers[1]); } return impl; } diff --git a/tools/render-test/render.h b/tools/render-test/render.h index 807fabf23..2ad736c27 100644 --- a/tools/render-test/render.h +++ b/tools/render-test/render.h @@ -32,6 +32,18 @@ enum class PipelineType CountOf, }; +enum class StageType +{ + Unknown, + Vertex, + Hull, + Domain, + Geometry, + Fragment, + Compute, + CountOf, +}; + enum class RendererType { Unknown, @@ -63,7 +75,32 @@ enum class BindingStyle class ShaderProgram: public Slang::RefObject { - public: +public: + + struct KernelDesc + { + StageType stage; + void const* codeBegin; + void const* codeEnd; + + UInt getCodeSize() const { return (char const*)codeEnd - (char const*)codeBegin; } + }; + + struct Desc + { + PipelineType pipelineType; + KernelDesc const* kernels; + Int kernelCount; + + /// Find and return the kernel for `stage`, if present. + KernelDesc const* findKernel(StageType stage) const + { + for(Int ii = 0; ii < kernelCount; ++ii) + if(kernels[ii].stage == stage) + return &kernels[ii]; + return nullptr; + } + }; }; struct ShaderCompileRequest @@ -84,8 +121,6 @@ struct ShaderCompileRequest struct EntryPoint { char const* name = nullptr; - char const* profile = nullptr; - SourceInfo source; }; @@ -96,12 +131,6 @@ struct ShaderCompileRequest Slang::List<Slang::String> entryPointTypeArguments; }; -class ShaderCompiler -{ -public: - virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) = 0; -}; - /// Different formats of things like pixels or elements of vertices /// NOTE! Any change to this type (adding, removing, changing order) - must also be reflected in changes to RendererUtil enum class Format @@ -496,7 +525,8 @@ public: virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) = 0; virtual BindingState* createBindingState(const BindingState::Desc& desc) { return nullptr; } - virtual ShaderCompiler* getShaderCompiler() = 0; + + virtual ShaderProgram* createProgram(const ShaderProgram::Desc& desc) = 0; virtual void* map(BufferResource* buffer, MapFlavor flavor) = 0; virtual void unmap(BufferResource* buffer) = 0; diff --git a/tools/render-test/slang-support.cpp b/tools/render-test/slang-support.cpp index 342af571c..d69060449 100644 --- a/tools/render-test/slang-support.cpp +++ b/tools/render-test/slang-support.cpp @@ -11,167 +11,169 @@ namespace renderer_test { -struct SlangShaderCompilerWrapper : public ShaderCompiler +ShaderProgram* ShaderCompiler::compileProgram( + ShaderCompileRequest const& request) { - ShaderCompiler* innerCompiler; - SlangCompileTarget target; - SlangSourceLanguage sourceLanguage; - - virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override - { - SlangSession* slangSession = spCreateSession(NULL); - SlangCompileRequest* slangRequest = spCreateCompileRequest(slangSession); - - spSetCodeGenTarget(slangRequest, target); - - // Define a macro so that shader code in a test can detect what language we - // are nominally working with. - char const* langDefine = nullptr; - switch (sourceLanguage) - { - case SLANG_SOURCE_LANGUAGE_GLSL: langDefine = "__GLSL__"; break; - case SLANG_SOURCE_LANGUAGE_HLSL: langDefine = "__HLSL__"; break; - case SLANG_SOURCE_LANGUAGE_SLANG: langDefine = "__SLANG__"; break; - default: - assert(!"unexpected"); - break; - } - spAddPreprocessorDefine(slangRequest, langDefine, "1"); - - // If we are dealing with GLSL input, then we need to set up - // Slang to pass through to glslang instead of actually running - // the compiler (this is a workaround to make direct comparisons - // possible) - if (sourceLanguage == SLANG_SOURCE_LANGUAGE_GLSL) + SlangSession* slangSession = spCreateSession(NULL); + SlangCompileRequest* slangRequest = spCreateCompileRequest(slangSession); + + spSetCodeGenTarget(slangRequest, target); + spSetTargetProfile(slangRequest, 0, + spFindProfile(slangSession, profile)); + + // Define a macro so that shader code in a test can detect what language we + // are nominally working with. + char const* langDefine = nullptr; + switch (sourceLanguage) + { + case SLANG_SOURCE_LANGUAGE_GLSL: + spAddPreprocessorDefine(slangRequest, "__GLSL__", "1"); + break; + + case SLANG_SOURCE_LANGUAGE_SLANG: + spAddPreprocessorDefine(slangRequest, "__SLANG__", "1"); + // fall through + case SLANG_SOURCE_LANGUAGE_HLSL: + spAddPreprocessorDefine(slangRequest, "__HLSL__", "1"); + break; + + default: + assert(!"unexpected"); + break; + } + + if (passThrough != SLANG_PASS_THROUGH_NONE) + { + spSetPassThrough(slangRequest, passThrough); + } + + // Preocess any additional command-line options specified for Slang using + // the `-xslang <arg>` option to `render-test`. + spProcessCommandLineArguments(slangRequest, &gOptions.slangArgs[0], gOptions.slangArgCount); + + int computeTranslationUnit = 0; + int vertexTranslationUnit = 0; + int fragmentTranslationUnit = 0; + char const* vertexEntryPointName = request.vertexShader.name; + char const* fragmentEntryPointName = request.fragmentShader.name; + char const* computeEntryPointName = request.computeShader.name; + + if (sourceLanguage == SLANG_SOURCE_LANGUAGE_GLSL) + { + // GLSL presents unique challenges because, frankly, it got the whole + // compilation model wrong. One aspect of working around this is that + // we will compile the same source file multiple times: once per + // entry point, and we will have different preprocessor definitions + // active in each case. + + vertexTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr); + spAddTranslationUnitSourceString(slangRequest, vertexTranslationUnit, request.source.path, request.source.dataBegin); + spTranslationUnit_addPreprocessorDefine(slangRequest, vertexTranslationUnit, "__GLSL_VERTEX__", "1"); + vertexEntryPointName = "main"; + + fragmentTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr); + spAddTranslationUnitSourceString(slangRequest, fragmentTranslationUnit, request.source.path, request.source.dataBegin); + spTranslationUnit_addPreprocessorDefine(slangRequest, fragmentTranslationUnit, "__GLSL_FRAGMENT__", "1"); + fragmentEntryPointName = "main"; + + computeTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr); + spAddTranslationUnitSourceString(slangRequest, computeTranslationUnit, request.source.path, request.source.dataBegin); + spTranslationUnit_addPreprocessorDefine(slangRequest, computeTranslationUnit, "__GLSL_COMPUTE__", "1"); + computeEntryPointName = "main"; + } + else + { + int translationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr); + spAddTranslationUnitSourceString(slangRequest, translationUnit, request.source.path, request.source.dataBegin); + + vertexTranslationUnit = translationUnit; + fragmentTranslationUnit = translationUnit; + computeTranslationUnit = translationUnit; + } + + + ShaderProgram * result = nullptr; + Slang::List<const char*> rawTypeNames; + for (auto typeName : request.entryPointTypeArguments) + rawTypeNames.Add(typeName.Buffer()); + if (request.computeShader.name) + { + int computeEntryPoint = spAddEntryPointEx(slangRequest, computeTranslationUnit, + computeEntryPointName, + SLANG_STAGE_COMPUTE, + (int)rawTypeNames.Count(), + rawTypeNames.Buffer()); + + spSetLineDirectiveMode(slangRequest, SLANG_LINE_DIRECTIVE_MODE_NONE); + int compileErr = spCompile(slangRequest); + if (auto diagnostics = spGetDiagnosticOutput(slangRequest)) { - spSetPassThrough(slangRequest, SLANG_PASS_THROUGH_GLSLANG); + fprintf(stderr, "%s", diagnostics); } + if (!compileErr) + { + size_t codeSize = 0; + char const* code = (char const*) spGetEntryPointCode(slangRequest, computeEntryPoint, &codeSize); + + ShaderProgram::KernelDesc kernelDesc; + kernelDesc.stage = StageType::Compute; + kernelDesc.codeBegin = code; + kernelDesc.codeEnd = code + codeSize; - // Preocess any additional command-line options specified for Slang using - // the `-xslang <arg>` option to `render-test`. - spProcessCommandLineArguments(slangRequest, &gOptions.slangArgs[0], gOptions.slangArgCount); - - int computeTranslationUnit = 0; - int vertexTranslationUnit = 0; - int fragmentTranslationUnit = 0; - char const* vertexEntryPointName = request.vertexShader.name; - char const* fragmentEntryPointName = request.fragmentShader.name; - char const* computeEntryPointName = request.computeShader.name; - - if (sourceLanguage == SLANG_SOURCE_LANGUAGE_GLSL) - { - // GLSL presents unique challenges because, frankly, it got the whole - // compilation model wrong. One aspect of working around this is that - // we will compile the same source file multiple times: once per - // entry point, and we will have different preprocessor definitions - // active in each case. - - vertexTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr); - spAddTranslationUnitSourceString(slangRequest, vertexTranslationUnit, request.source.path, request.source.dataBegin); - spTranslationUnit_addPreprocessorDefine(slangRequest, vertexTranslationUnit, "__GLSL_VERTEX__", "1"); - vertexEntryPointName = "main"; - - fragmentTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr); - spAddTranslationUnitSourceString(slangRequest, fragmentTranslationUnit, request.source.path, request.source.dataBegin); - spTranslationUnit_addPreprocessorDefine(slangRequest, fragmentTranslationUnit, "__GLSL_FRAGMENT__", "1"); - fragmentEntryPointName = "main"; - - computeTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr); - spAddTranslationUnitSourceString(slangRequest, computeTranslationUnit, request.source.path, request.source.dataBegin); - spTranslationUnit_addPreprocessorDefine(slangRequest, computeTranslationUnit, "__GLSL_COMPUTE__", "1"); - computeEntryPointName = "main"; - } - else - { - int translationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr); - spAddTranslationUnitSourceString(slangRequest, translationUnit, request.source.path, request.source.dataBegin); - - vertexTranslationUnit = translationUnit; - fragmentTranslationUnit = translationUnit; - computeTranslationUnit = translationUnit; - } - - - ShaderProgram * result = nullptr; - Slang::List<const char*> rawTypeNames; - for (auto typeName : request.entryPointTypeArguments) - rawTypeNames.Add(typeName.Buffer()); - if (request.computeShader.name) - { - int computeEntryPoint = spAddEntryPointEx(slangRequest, computeTranslationUnit, - computeEntryPointName, - spFindProfile(slangSession, request.computeShader.profile), - (int)rawTypeNames.Count(), - rawTypeNames.Buffer()); - - spSetLineDirectiveMode(slangRequest, SLANG_LINE_DIRECTIVE_MODE_NONE); - int compileErr = spCompile(slangRequest); - if (auto diagnostics = spGetDiagnosticOutput(slangRequest)) - { - fprintf(stderr, "%s", diagnostics); - } - if (!compileErr) - { - ShaderCompileRequest innerRequest = request; - - size_t codeSize = 0; - char const* code = (char const*) spGetEntryPointCode(slangRequest, computeEntryPoint, &codeSize); - innerRequest.computeShader.source.dataBegin = code; - innerRequest.computeShader.source.dataEnd = code + codeSize; - result = innerCompiler->compileProgram(innerRequest); - } - } - else - { - int vertexEntryPoint = spAddEntryPointEx(slangRequest, vertexTranslationUnit, vertexEntryPointName, spFindProfile(slangSession, request.vertexShader.profile), (int)rawTypeNames.Count(), rawTypeNames.Buffer()); - int fragmentEntryPoint = spAddEntryPointEx(slangRequest, fragmentTranslationUnit, fragmentEntryPointName, spFindProfile(slangSession, request.fragmentShader.profile), (int)rawTypeNames.Count(), rawTypeNames.Buffer()); - - int compileErr = spCompile(slangRequest); - if (auto diagnostics = spGetDiagnosticOutput(slangRequest)) - { - // TODO(tfoley): re-enable when I get a logging solution in place - // OutputDebugStringA(diagnostics); - fprintf(stderr, "%s", diagnostics); - } - if (!compileErr) - { - ShaderCompileRequest innerRequest = request; - - size_t vertexCodeSize = 0; - char const* vertexCode = (char const*) spGetEntryPointCode(slangRequest, vertexEntryPoint, &vertexCodeSize); - - size_t fragmentCodeSize = 0; - char const* fragmentCode = (char const*) spGetEntryPointCode(slangRequest, fragmentEntryPoint, &fragmentCodeSize); - - innerRequest.vertexShader.source.dataBegin = vertexCode; - innerRequest.vertexShader.source.dataEnd = vertexCode + vertexCodeSize; - - innerRequest.fragmentShader.source.dataBegin = fragmentCode; - innerRequest.fragmentShader.source.dataEnd = fragmentCode + fragmentCodeSize; - - result = innerCompiler->compileProgram(innerRequest); - } - } - // We clean up the Slang compilation context and result *after* - // we have run the downstream compiler, because Slang - // owns the memory allocation for the generated text, and will - // free it when we destroy the compilation result. - spDestroyCompileRequest(slangRequest); - spDestroySession(slangSession); - - return result; + ShaderProgram::Desc desc; + desc.pipelineType = PipelineType::Compute; + desc.kernels = &kernelDesc; + desc.kernelCount = 1; + + result = renderer->createProgram(desc); + } } -}; + else + { + int vertexEntryPoint = spAddEntryPointEx(slangRequest, vertexTranslationUnit, vertexEntryPointName, SLANG_STAGE_VERTEX, (int)rawTypeNames.Count(), rawTypeNames.Buffer()); + int fragmentEntryPoint = spAddEntryPointEx(slangRequest, fragmentTranslationUnit, fragmentEntryPointName, SLANG_STAGE_FRAGMENT, (int)rawTypeNames.Count(), rawTypeNames.Buffer()); -ShaderCompiler* createSlangShaderCompiler( - ShaderCompiler* innerCompiler, - SlangSourceLanguage sourceLanguage, - SlangCompileTarget target) -{ - auto result = new SlangShaderCompilerWrapper(); - result->innerCompiler = innerCompiler; - result->sourceLanguage = sourceLanguage; - result->target = target; + int compileErr = spCompile(slangRequest); + if (auto diagnostics = spGetDiagnosticOutput(slangRequest)) + { + // TODO(tfoley): re-enable when I get a logging solution in place +// OutputDebugStringA(diagnostics); + fprintf(stderr, "%s", diagnostics); + } + if (!compileErr) + { + size_t vertexCodeSize = 0; + char const* vertexCode = (char const*) spGetEntryPointCode(slangRequest, vertexEntryPoint, &vertexCodeSize); + + size_t fragmentCodeSize = 0; + char const* fragmentCode = (char const*) spGetEntryPointCode(slangRequest, fragmentEntryPoint, &fragmentCodeSize); + + static const int kDescCount = 2; + + ShaderProgram::KernelDesc kernelDescs[kDescCount]; + + kernelDescs[0].stage = StageType::Vertex; + kernelDescs[0].codeBegin = vertexCode; + kernelDescs[0].codeEnd = vertexCode + vertexCodeSize; + + kernelDescs[1].stage = StageType::Fragment; + kernelDescs[1].codeBegin = fragmentCode; + kernelDescs[1].codeEnd = fragmentCode + fragmentCodeSize; + + ShaderProgram::Desc desc; + desc.pipelineType = PipelineType::Graphics; + desc.kernels = &kernelDescs[0]; + desc.kernelCount = kDescCount; + + result = renderer->createProgram(desc); + } + } + // We clean up the Slang compilation context and result *after* + // we have run the downstream compiler, because Slang + // owns the memory allocation for the generated text, and will + // free it when we destroy the compilation result. + spDestroyCompileRequest(slangRequest); + spDestroySession(slangSession); return result; } diff --git a/tools/render-test/slang-support.h b/tools/render-test/slang-support.h index c24b0e2e6..8697abcb8 100644 --- a/tools/render-test/slang-support.h +++ b/tools/render-test/slang-support.h @@ -9,9 +9,17 @@ namespace renderer_test { -ShaderCompiler* createSlangShaderCompiler( - ShaderCompiler* innerCompiler, - SlangSourceLanguage sourceLanguage, - SlangCompileTarget target); +struct ShaderCompiler +{ + Renderer* renderer; + SlangCompileTarget target; + SlangSourceLanguage sourceLanguage; + SlangPassThrough passThrough; + char const* profile; + + ShaderProgram* compileProgram( + ShaderCompileRequest const& request); +}; + } // renderer_test |
