From 0717c9e7eb0d3fb5595b018c8bd97d66e81f2128 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Fri, 26 Oct 2018 08:03:40 -0700 Subject: Enabled Vulkan backend to take compiled SPIRV byte code --- Graphics/GraphicsEngine/interface/Shader.h | 6 ++-- .../GraphicsEngineD3DBase/src/ShaderD3DBase.cpp | 12 ++++---- Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp | 33 ++++++++++++++++------ 3 files changed, 35 insertions(+), 16 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h index dc0b29be..fe0fcf5c 100644 --- a/Graphics/GraphicsEngine/interface/Shader.h +++ b/Graphics/GraphicsEngine/interface/Shader.h @@ -252,7 +252,9 @@ struct ShaderCreationAttribs /// Compiled shader bytecode. /// If shader byte code is provided, FilePath and Source members must be null - /// \note. This option is currently only supported for D3D11 and D3D12. + /// \note. This option is supported for D3D11, D3D12 and Vulkan backends. + /// For D3D11 and D3D12 backends, HLSL bytecode should be provided. Vulkan + /// backend expects SPIRV bytecode. /// The bytecode must contain reflection information. If shaders were compiled /// using fxc, make sure that /Qstrip_reflect option is *not* specified. /// Also, shaders need to be compiled against 4.0 profile or higher. @@ -260,7 +262,7 @@ struct ShaderCreationAttribs /// Size of the compiled shader bytecode - /// Byte code size must be provided if ByteCode is not null + /// Byte code size (in bytes) must be provided if ByteCode is not null size_t ByteCodeSize = 0; /// Shader entry point diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp index 177d1f3f..2c18d66a 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp @@ -137,8 +137,8 @@ ShaderD3DBase::ShaderD3DBase(const ShaderCreationAttribs &CreationAttribs) { if (CreationAttribs.Source || CreationAttribs.FilePath) { - VERIFY(CreationAttribs.ByteCode == nullptr, "'ByteCode' must be null when shader is created from the source code or a file"); - VERIFY(CreationAttribs.ByteCodeSize == 0, "'ByteCodeSize' must be 0 when shader is created from the source code or a file"); + DEV_CHECK_ERR(CreationAttribs.ByteCode == nullptr, "'ByteCode' must be null when shader is created from the source code or a file"); + DEV_CHECK_ERR(CreationAttribs.ByteCodeSize == 0, "'ByteCodeSize' must be 0 when shader is created from the source code or a file"); std::string strShaderProfile; switch(CreationAttribs.Desc.ShaderType) @@ -159,12 +159,12 @@ ShaderD3DBase::ShaderD3DBase(const ShaderCreationAttribs &CreationAttribs) String ShaderSource(g_HLSLDefinitions); if (CreationAttribs.Source) { - VERIFY(CreationAttribs.FilePath == nullptr, "'FilePath' is expected to be null when shader source code is provided"); + DEV_CHECK_ERR(CreationAttribs.FilePath == nullptr, "'FilePath' is expected to be null when shader source code is provided"); ShaderSource.append(CreationAttribs.Source); } else { - VERIFY(CreationAttribs.pShaderSourceStreamFactory, "Input stream factory is null"); + DEV_CHECK_ERR(CreationAttribs.pShaderSourceStreamFactory, "Input stream factory is null"); RefCntAutoPtr pSourceStream; CreationAttribs.pShaderSourceStreamFactory->CreateInputStream(CreationAttribs.FilePath, &pSourceStream); RefCntAutoPtr pFileData(MakeNewRCObj()(0)); @@ -189,7 +189,7 @@ ShaderD3DBase::ShaderD3DBase(const ShaderCreationAttribs &CreationAttribs) pDefines = D3DMacros.data(); } - VERIFY(CreationAttribs.EntryPoint != nullptr, "Entry point must not be null"); + DEV_CHECK_ERR(CreationAttribs.EntryPoint != nullptr, "Entry point must not be null"); CComPtr errors; auto hr = CompileShader(ShaderSource.c_str(), CreationAttribs.EntryPoint, pDefines, CreationAttribs.pShaderSourceStreamFactory, strShaderProfile.c_str(), &m_pShaderByteCode, &errors); @@ -219,7 +219,7 @@ ShaderD3DBase::ShaderD3DBase(const ShaderCreationAttribs &CreationAttribs) } else if (CreationAttribs.ByteCode) { - VERIFY(CreationAttribs.ByteCodeSize != 0, "ByteCode size must be greater than 0"); + DEV_CHECK_ERR(CreationAttribs.ByteCodeSize != 0, "ByteCode size must be greater than 0"); CHECK_D3D_RESULT_THROW(D3DCreateBlob(CreationAttribs.ByteCodeSize, &m_pShaderByteCode), "Failed to create D3D blob"); memcpy(m_pShaderByteCode->GetBufferPointer(), CreationAttribs.ByteCode, CreationAttribs.ByteCodeSize); } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp index e27445f9..137727ff 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp @@ -39,19 +39,36 @@ ShaderVkImpl::ShaderVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* m_StaticResCache (ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources), m_StaticVarsMgr (*this) { - if (CreationAttribs.SourceLanguage == SHADER_SOURCE_LANGUAGE_HLSL) + if (CreationAttribs.Source != nullptr || CreationAttribs.FilePath != nullptr) { - m_SPIRV = HLSLtoSPIRV(CreationAttribs, CreationAttribs.ppCompilerOutput); + DEV_CHECK_ERR(CreationAttribs.ByteCode == nullptr, "'ByteCode' must be null when shader is created from source code or a file"); + DEV_CHECK_ERR(CreationAttribs.ByteCodeSize == 0, "'ByteCodeSize' must be 0 when shader is created from source code or a file"); + + if (CreationAttribs.SourceLanguage == SHADER_SOURCE_LANGUAGE_HLSL) + { + m_SPIRV = HLSLtoSPIRV(CreationAttribs, CreationAttribs.ppCompilerOutput); + } + else + { + auto GLSLSource = BuildGLSLSourceString(CreationAttribs, TargetGLSLCompiler::glslang, "#define TARGET_API_VULKAN 1\n"); + m_SPIRV = GLSLtoSPIRV(m_Desc.ShaderType, GLSLSource.c_str(), static_cast(GLSLSource.length()), CreationAttribs.ppCompilerOutput); + } + + if (m_SPIRV.empty()) + { + LOG_ERROR_AND_THROW("Failed to compile shader"); + } } - else + else if (CreationAttribs.ByteCode != nullptr) { - auto GLSLSource = BuildGLSLSourceString(CreationAttribs, TargetGLSLCompiler::glslang, "#define TARGET_API_VULKAN 1\n"); - m_SPIRV = GLSLtoSPIRV(m_Desc.ShaderType, GLSLSource.c_str(), static_cast(GLSLSource.length()), CreationAttribs.ppCompilerOutput); + DEV_CHECK_ERR(CreationAttribs.ByteCodeSize != 0, "ByteCodeSize must not be 0"); + DEV_CHECK_ERR(CreationAttribs.ByteCodeSize % 4 == 0, "Byte code size (", CreationAttribs.ByteCodeSize, ") is not multiple of 4"); + m_SPIRV.resize(CreationAttribs.ByteCodeSize/4); + memcpy(m_SPIRV.data(), CreationAttribs.ByteCode, CreationAttribs.ByteCodeSize); } - - if (m_SPIRV.empty()) + else { - LOG_ERROR_AND_THROW("Failed to compile shader"); + LOG_ERROR_AND_THROW("Shader source must be provided through one of the 'Source', 'FilePath' or 'ByteCode' members"); } // We cannot create shader module here because resource bindings are assigned when -- cgit v1.2.3