From 647d74af0d8a534ddf41352172b8e9c2854e5533 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 11 Jan 2025 22:44:38 +0100 Subject: [PATCH] Fixes for vertex layouts binding into graphics backend --- .../Graphics/Shaders/GPUVertexLayout.cpp | 4 +++- .../DirectX/DX11/GPUShaderDX11.cpp | 6 ++++- .../DirectX/DX12/GPUContextDX12.cpp | 11 ++++++--- .../DirectX/DX12/GPUPipelineStateDX12.cpp | 23 +++++++++++++++---- .../DirectX/DX12/GPUPipelineStateDX12.h | 3 ++- .../DirectX/ShaderCompilerD3D.cpp | 2 +- .../DirectX/ShaderCompilerDX.cpp | 2 +- 7 files changed, 39 insertions(+), 12 deletions(-) diff --git a/Source/Engine/Graphics/Shaders/GPUVertexLayout.cpp b/Source/Engine/Graphics/Shaders/GPUVertexLayout.cpp index 822766e67..354a6dfa6 100644 --- a/Source/Engine/Graphics/Shaders/GPUVertexLayout.cpp +++ b/Source/Engine/Graphics/Shaders/GPUVertexLayout.cpp @@ -262,7 +262,9 @@ GPUVertexLayout* GPUVertexLayout::Merge(GPUVertexLayout* base, GPUVertexLayout* { // Insert any missing elements VertexElement ne = { e.Type, missingSlotOverride != -1 ? (byte)missingSlotOverride : e.Slot, 0, e.PerInstance, e.Format }; - if (e.Type == VertexElement::Types::TexCoord1 || e.Type == VertexElement::Types::TexCoord2 || e.Type == VertexElement::Types::TexCoord3) + if (e.Type == VertexElement::Types::TexCoord1 || + e.Type == VertexElement::Types::TexCoord2 || + e.Type == VertexElement::Types::TexCoord3) { // Alias missing texcoords with existing texcoords for (const VertexElement& ee : newElements) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp index 4251b3a55..3b78882ae 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp @@ -26,7 +26,11 @@ ID3D11InputLayout* GPUShaderProgramVSDX11::GetInputLayout(GPUVertexLayoutDX11* v { if (vertexLayout && vertexLayout->InputElementsCount) { - auto mergedVertexLayout = (GPUVertexLayoutDX11*)GPUVertexLayout::Merge(vertexLayout, Layout ? Layout : InputLayout); + GPUVertexLayoutDX11* mergedVertexLayout = vertexLayout; + if (!mergedVertexLayout) + mergedVertexLayout = (GPUVertexLayoutDX11*)Layout; // Fallback to shader-specified layout (if using old APIs) + if (InputLayout) + mergedVertexLayout = (GPUVertexLayoutDX11*)GPUVertexLayout::Merge(mergedVertexLayout, InputLayout); LOG_DIRECTX_RESULT(vertexLayout->GetDevice()->GetDevice()->CreateInputLayout(mergedVertexLayout->InputElements, mergedVertexLayout->InputElementsCount, Bytecode.Get(), Bytecode.Length(), &inputLayout)); } _cache.Add(vertexLayout, inputLayout); diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp index 6f9be059f..6a1f4ec01 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp @@ -563,7 +563,7 @@ void GPUContextDX12::flushPS() // Change state ASSERT(_currentState->IsValid()); #if GPU_ENABLE_ASSERTION_LOW_LAYERS - if (!_vertexLayout && _vbHandles[0] && !_currentState->VertexLayout) + if (!_vertexLayout && _vbHandles[0] && !_currentState->VertexBufferLayout) { LOG(Error, "Missing Vertex Layout (not assigned to GPUBuffer). Vertex Shader won't read valid data resulting incorrect visuals."); } @@ -957,7 +957,6 @@ void GPUContextDX12::BindUA(int32 slot, GPUResourceView* view) void GPUContextDX12::BindVB(const Span& vertexBuffers, const uint32* vertexBuffersOffsets, GPUVertexLayout* vertexLayout) { ASSERT(vertexBuffers.Length() >= 0 && vertexBuffers.Length() <= GPU_MAX_VB_BINDED); - bool vbEdited = _vbCount != vertexBuffers.Length(); D3D12_VERTEX_BUFFER_VIEW views[GPU_MAX_VB_BINDED]; for (int32 i = 0; i < vertexBuffers.Length(); i++) @@ -990,7 +989,13 @@ void GPUContextDX12::BindVB(const Span& vertexBuffers, const uint32* #endif _commandList->IASetVertexBuffers(0, vertexBuffers.Length(), views); } - _vertexLayout = (GPUVertexLayoutDX12*)(vertexLayout ? vertexLayout : GPUVertexLayout::Get(vertexBuffers)); + if (!vertexLayout) + vertexLayout = GPUVertexLayout::Get(vertexBuffers); + if (_vertexLayout != vertexLayout) + { + _vertexLayout = (GPUVertexLayoutDX12*)vertexLayout; + _psDirtyFlag = true; + } } void GPUContextDX12::BindIB(GPUBuffer* indexBuffer) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUPipelineStateDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUPipelineStateDX12.cpp index c68fda240..ae8e29918 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUPipelineStateDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUPipelineStateDX12.cpp @@ -83,9 +83,20 @@ ID3D12PipelineState* GPUPipelineStateDX12::GetState(GPUTextureViewDX12* depth, i _desc.SampleDesc.Quality = key.MSAA == MSAALevel::None ? 0 : GPUDeviceDX12::GetMaxMSAAQuality((int32)key.MSAA); _desc.SampleMask = D3D12_DEFAULT_SAMPLE_MASK; _desc.DSVFormat = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindDepthStencilFormat(key.DepthFormat)); - vertexLayout = (GPUVertexLayoutDX12*)GPUVertexLayout::Merge(vertexLayout, VertexLayout); - _desc.InputLayout.pInputElementDescs = vertexLayout ? vertexLayout->InputElements : nullptr; - _desc.InputLayout.NumElements = vertexLayout ? vertexLayout->InputElementsCount : 0; + if (!vertexLayout) + vertexLayout = VertexBufferLayout; // Fallback to shader-specified layout (if using old APIs) + if (vertexLayout) + { + if (VertexInputLayout) + vertexLayout = (GPUVertexLayoutDX12*)GPUVertexLayout::Merge(vertexLayout, VertexInputLayout); + _desc.InputLayout.pInputElementDescs = vertexLayout->InputElements; + _desc.InputLayout.NumElements = vertexLayout->InputElementsCount; + } + else + { + _desc.InputLayout.pInputElementDescs = nullptr; + _desc.InputLayout.NumElements = 0; + } // Create object const HRESULT result = _device->GetDevice()->CreateGraphicsPipelineState(&_desc, IID_PPV_ARGS(&state)); @@ -180,7 +191,11 @@ bool GPUPipelineStateDX12::Init(const Description& desc) INIT_SHADER_STAGE(PS, GPUShaderProgramPSDX12); // Input Assembly - VertexLayout = desc.VS ? (GPUVertexLayoutDX12*)(desc.VS->Layout ? desc.VS->Layout : desc.VS->InputLayout) : nullptr; + if (desc.VS) + { + VertexBufferLayout = (GPUVertexLayoutDX12*)desc.VS->Layout; + VertexInputLayout = (GPUVertexLayoutDX12*)desc.VS->InputLayout; + } const D3D12_PRIMITIVE_TOPOLOGY_TYPE primTypes1[] = { D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED, diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUPipelineStateDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUPipelineStateDX12.h index aaaae48d2..7645e9914 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUPipelineStateDX12.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUPipelineStateDX12.h @@ -58,7 +58,8 @@ public: public: D3D_PRIMITIVE_TOPOLOGY PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; DxShaderHeader Header; - GPUVertexLayoutDX12* VertexLayout; + GPUVertexLayoutDX12* VertexBufferLayout = nullptr; + GPUVertexLayoutDX12* VertexInputLayout = nullptr; /// /// Gets DirectX 12 graphics pipeline state object for the given rendering state. Uses depth buffer and render targets formats and multi-sample levels to setup a proper PSO. Uses caching. diff --git a/Source/Engine/ShadersCompilation/DirectX/ShaderCompilerD3D.cpp b/Source/Engine/ShadersCompilation/DirectX/ShaderCompilerD3D.cpp index 131d77033..bb2c408cc 100644 --- a/Source/Engine/ShadersCompilation/DirectX/ShaderCompilerD3D.cpp +++ b/Source/Engine/ShadersCompilation/DirectX/ShaderCompilerD3D.cpp @@ -277,7 +277,7 @@ bool ShaderCompilerD3D::CompileShader(ShaderFunctionMeta& meta, WritePermutation { D3D11_SIGNATURE_PARAMETER_DESC inputDesc; reflector->GetInputParameterDesc(inputIdx, &inputDesc); - if (inputDesc.ReadWriteMask == 0 || inputDesc.SystemValueType != D3D10_NAME_UNDEFINED) + if (inputDesc.SystemValueType != D3D10_NAME_UNDEFINED) continue; auto format = PixelFormat::Unknown; switch (inputDesc.ComponentType) diff --git a/Source/Engine/ShadersCompilation/DirectX/ShaderCompilerDX.cpp b/Source/Engine/ShadersCompilation/DirectX/ShaderCompilerDX.cpp index c2431c485..d224503e2 100644 --- a/Source/Engine/ShadersCompilation/DirectX/ShaderCompilerDX.cpp +++ b/Source/Engine/ShadersCompilation/DirectX/ShaderCompilerDX.cpp @@ -327,7 +327,7 @@ bool ShaderCompilerDX::CompileShader(ShaderFunctionMeta& meta, WritePermutationD { D3D12_SIGNATURE_PARAMETER_DESC inputDesc; shaderReflection->GetInputParameterDesc(inputIdx, &inputDesc); - if (inputDesc.ReadWriteMask == 0 || inputDesc.SystemValueType != D3D10_NAME_UNDEFINED) + if (inputDesc.SystemValueType != D3D10_NAME_UNDEFINED) continue; auto format = PixelFormat::Unknown; switch (inputDesc.ComponentType)