From 0e73a012796cf87fb1ea86488c630e57d53d273d Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sat, 16 Aug 2025 15:07:24 -0500 Subject: [PATCH] VideoBackends: allow custom pixel uniforms to be passed to the vertex shader as well --- Source/Core/VideoBackends/D3D/D3DState.cpp | 20 ++++++++++--------- Source/Core/VideoBackends/D3D/D3DState.h | 19 ++++++++++++------ .../VideoBackends/D3D/D3DVertexManager.cpp | 13 ++++++------ .../Core/VideoBackends/D3D/D3DVertexManager.h | 4 ++-- Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp | 8 +++++--- Source/Core/VideoBackends/D3D12/D3D12Gfx.h | 4 ++-- .../D3D12/D3D12VertexManager.cpp | 10 ++++++++++ .../VideoBackends/D3D12/D3D12VertexManager.h | 1 + .../Core/VideoBackends/D3D12/DX12Context.cpp | 6 ++++-- Source/Core/VideoBackends/D3D12/DX12Context.h | 1 + Source/Core/VideoBackends/Vulkan/Constants.h | 2 +- .../Core/VideoBackends/Vulkan/ObjectCache.cpp | 4 ++-- .../VideoBackends/Vulkan/StateTracker.cpp | 4 ++-- .../VideoBackends/Vulkan/VKVertexManager.cpp | 4 ++-- 14 files changed, 62 insertions(+), 38 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DState.cpp b/Source/Core/VideoBackends/D3D/D3DState.cpp index f4e02d6ea5..a5c432da0d 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.cpp +++ b/Source/Core/VideoBackends/D3D/D3DState.cpp @@ -59,6 +59,7 @@ void StateManager::Apply() const bool dirtyConstants = m_dirtyFlags.test(DirtyFlag_PixelConstants) || m_dirtyFlags.test(DirtyFlag_VertexConstants) || + m_dirtyFlags.test(DirtyFlag_CustomConstants) || m_dirtyFlags.test(DirtyFlag_GeometryConstants); const bool dirtyShaders = m_dirtyFlags.test(DirtyFlag_PixelShader) || m_dirtyFlags.test(DirtyFlag_VertexShader) || @@ -69,18 +70,12 @@ void StateManager::Apply() if (dirtyConstants) { if (m_current.pixelConstants[0] != m_pending.pixelConstants[0] || - m_current.pixelConstants[1] != m_pending.pixelConstants[1] || - m_current.pixelConstants[2] != m_pending.pixelConstants[2]) + m_current.pixelConstants[1] != m_pending.pixelConstants[1]) { - u32 count = 1; - if (m_pending.pixelConstants[1]) - count++; - if (m_pending.pixelConstants[2]) - count++; - D3D::context->PSSetConstantBuffers(0, count, m_pending.pixelConstants.data()); + D3D::context->PSSetConstantBuffers(0, 1, &m_pending.pixelConstants[0]); + D3D::context->PSSetConstantBuffers(1, 1, &m_pending.pixelConstants[1]); m_current.pixelConstants[0] = m_pending.pixelConstants[0]; m_current.pixelConstants[1] = m_pending.pixelConstants[1]; - m_current.pixelConstants[2] = m_pending.pixelConstants[2]; } if (m_current.vertexConstants != m_pending.vertexConstants) @@ -90,6 +85,13 @@ void StateManager::Apply() m_current.vertexConstants = m_pending.vertexConstants; } + if (m_current.customConstants != m_pending.customConstants) + { + D3D::context->PSSetConstantBuffers(2, 1, &m_pending.customConstants); + D3D::context->VSSetConstantBuffers(2, 1, &m_pending.customConstants); + m_current.customConstants = m_pending.customConstants; + } + if (m_current.geometryConstants != m_pending.geometryConstants) { D3D::context->GSSetConstantBuffers(0, 1, &m_pending.geometryConstants); diff --git a/Source/Core/VideoBackends/D3D/D3DState.h b/Source/Core/VideoBackends/D3D/D3DState.h index 9b14b00350..05a1f089ea 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.h +++ b/Source/Core/VideoBackends/D3D/D3DState.h @@ -91,16 +91,13 @@ public: m_pending.samplers[index] = sampler; } - void SetPixelConstants(ID3D11Buffer* buffer0, ID3D11Buffer* buffer1 = nullptr, - ID3D11Buffer* buffer2 = nullptr) + void SetPixelConstants(ID3D11Buffer* buffer0, ID3D11Buffer* buffer1 = nullptr) { - if (m_current.pixelConstants[0] != buffer0 || m_current.pixelConstants[1] != buffer1 || - m_current.pixelConstants[2] != buffer2) + if (m_current.pixelConstants[0] != buffer0 || m_current.pixelConstants[1] != buffer1) m_dirtyFlags.set(DirtyFlag_PixelConstants); m_pending.pixelConstants[0] = buffer0; m_pending.pixelConstants[1] = buffer1; - m_pending.pixelConstants[2] = buffer2; } void SetVertexConstants(ID3D11Buffer* buffer) @@ -111,6 +108,14 @@ public: m_pending.vertexConstants = buffer; } + void SetCustomConstants(ID3D11Buffer* buffer) + { + if (m_current.customConstants != buffer) + m_dirtyFlags.set(DirtyFlag_CustomConstants); + + m_pending.customConstants = buffer; + } + void SetGeometryConstants(ID3D11Buffer* buffer) { if (m_current.geometryConstants != buffer) @@ -232,6 +237,7 @@ private: DirtyFlag_Sampler0 = DirtyFlag_Texture0 + VideoCommon::MAX_PIXEL_SHADER_SAMPLERS, DirtyFlag_PixelConstants = DirtyFlag_Sampler0 + VideoCommon::MAX_PIXEL_SHADER_SAMPLERS, DirtyFlag_VertexConstants, + DirtyFlag_CustomConstants, // Custom shader constants used by both vertex/pixel stages DirtyFlag_GeometryConstants, DirtyFlag_VertexBuffer, @@ -255,8 +261,9 @@ private: { std::array textures; std::array samplers; - std::array pixelConstants; + std::array pixelConstants; ID3D11Buffer* vertexConstants; + ID3D11Buffer* customConstants; ID3D11Buffer* geometryConstants; ID3D11Buffer* vertexBuffer; ID3D11Buffer* indexBuffer; diff --git a/Source/Core/VideoBackends/D3D/D3DVertexManager.cpp b/Source/Core/VideoBackends/D3D/D3DVertexManager.cpp index 89a816b925..c88fee33ee 100644 --- a/Source/Core/VideoBackends/D3D/D3DVertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/D3DVertexManager.cpp @@ -290,24 +290,23 @@ void VertexManager::UploadUniforms() if (pixel_shader_manager.custom_constants_dirty) { - if (m_last_custom_pixel_buffer_size < pixel_shader_manager.custom_constants.size()) + if (m_last_custom_buffer_size < pixel_shader_manager.custom_constants.size()) { - m_custom_pixel_constant_buffer = + m_custom_constant_buffer = AllocateConstantBuffer(static_cast(pixel_shader_manager.custom_constants.size())); } - UpdateConstantBuffer(m_custom_pixel_constant_buffer.Get(), + UpdateConstantBuffer(m_custom_constant_buffer.Get(), pixel_shader_manager.custom_constants.data(), static_cast(pixel_shader_manager.custom_constants.size())); - m_last_custom_pixel_buffer_size = pixel_shader_manager.custom_constants.size(); + m_last_custom_buffer_size = pixel_shader_manager.custom_constants.size(); pixel_shader_manager.custom_constants_dirty = false; } D3D::stateman->SetPixelConstants( m_pixel_constant_buffer.Get(), - g_ActiveConfig.bEnablePixelLighting ? m_vertex_constant_buffer.Get() : nullptr, - pixel_shader_manager.custom_constants.empty() ? nullptr : - m_custom_pixel_constant_buffer.Get()); + g_ActiveConfig.bEnablePixelLighting ? m_vertex_constant_buffer.Get() : nullptr); D3D::stateman->SetVertexConstants(m_vertex_constant_buffer.Get()); D3D::stateman->SetGeometryConstants(m_geometry_constant_buffer.Get()); + D3D::stateman->SetCustomConstants(m_custom_constant_buffer.Get()); } } // namespace DX11 diff --git a/Source/Core/VideoBackends/D3D/D3DVertexManager.h b/Source/Core/VideoBackends/D3D/D3DVertexManager.h index c406eea12e..ef7c4a9191 100644 --- a/Source/Core/VideoBackends/D3D/D3DVertexManager.h +++ b/Source/Core/VideoBackends/D3D/D3DVertexManager.h @@ -68,8 +68,8 @@ private: ComPtr m_geometry_constant_buffer = nullptr; ComPtr m_pixel_constant_buffer = nullptr; - ComPtr m_custom_pixel_constant_buffer = nullptr; - std::size_t m_last_custom_pixel_buffer_size = 0; + ComPtr m_custom_constant_buffer = nullptr; + std::size_t m_last_custom_buffer_size = 0; ComPtr m_texel_buffer = nullptr; std::array, NUM_TEXEL_BUFFER_FORMATS> m_texel_buffer_views; diff --git a/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp b/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp index b579262f09..265ec06e6c 100644 --- a/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp +++ b/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp @@ -160,7 +160,7 @@ void Gfx::SetPipeline(const AbstractPipeline* pipeline) m_dirty_bits |= DirtyState_RootSignature | DirtyState_PS_CBV | DirtyState_VS_CBV | DirtyState_GS_CBV | DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor | DirtyState_UAV_Descriptor | - DirtyState_VS_SRV_Descriptor | DirtyState_PS_CUS_CBV; + DirtyState_VS_SRV_Descriptor | DirtyState_CUS_CBV; } if (dx_pipeline->UseIntegerRTV() != m_state.using_integer_rtv) { @@ -524,7 +524,7 @@ bool Gfx::ApplyState() DirtyState_ScissorRect | DirtyState_PS_UAV | DirtyState_PS_CBV | DirtyState_VS_CBV | DirtyState_GS_CBV | DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor | DirtyState_UAV_Descriptor | DirtyState_VertexBuffer | DirtyState_IndexBuffer | - DirtyState_PrimitiveTopology | DirtyState_VS_SRV_Descriptor | DirtyState_PS_CUS_CBV); + DirtyState_PrimitiveTopology | DirtyState_VS_SRV_Descriptor | DirtyState_CUS_CBV); auto* const cmdlist = g_dx_context->GetCommandList(); auto* const pipeline = static_cast(m_current_pipeline); @@ -575,8 +575,10 @@ bool Gfx::ApplyState() } } - if (dirty_bits & DirtyState_PS_CUS_CBV) + if (dirty_bits & DirtyState_CUS_CBV) { + cmdlist->SetGraphicsRootConstantBufferView(ROOT_PARAMETER_VS_CUS_CBV, + m_state.constant_buffers[2]); cmdlist->SetGraphicsRootConstantBufferView(ROOT_PARAMETER_PS_CUS_CBV, m_state.constant_buffers[2]); } diff --git a/Source/Core/VideoBackends/D3D12/D3D12Gfx.h b/Source/Core/VideoBackends/D3D12/D3D12Gfx.h index a852a46a0f..ce574a3690 100644 --- a/Source/Core/VideoBackends/D3D12/D3D12Gfx.h +++ b/Source/Core/VideoBackends/D3D12/D3D12Gfx.h @@ -112,7 +112,7 @@ private: DirtyState_PS_UAV = (1 << 7), DirtyState_PS_CBV = (1 << 8), DirtyState_VS_CBV = (1 << 9), - DirtyState_PS_CUS_CBV = (1 << 10), + DirtyState_CUS_CBV = (1 << 10), DirtyState_GS_CBV = (1 << 11), DirtyState_SRV_Descriptor = (1 << 12), DirtyState_Sampler_Descriptor = (1 << 13), @@ -129,7 +129,7 @@ private: DirtyState_All = DirtyState_Framebuffer | DirtyState_Pipeline | DirtyState_Textures | DirtyState_Samplers | DirtyState_Viewport | DirtyState_ScissorRect | DirtyState_ComputeImageTexture | - DirtyState_PS_UAV | DirtyState_PS_CBV | DirtyState_VS_CBV | DirtyState_PS_CUS_CBV | + DirtyState_PS_UAV | DirtyState_PS_CBV | DirtyState_VS_CBV | DirtyState_CUS_CBV | DirtyState_GS_CBV | DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor | DirtyState_UAV_Descriptor | DirtyState_VertexBuffer | DirtyState_IndexBuffer | DirtyState_PrimitiveTopology | DirtyState_RootSignature | DirtyState_ComputeRootSignature | diff --git a/Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp b/Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp index c0fe195e75..4565db29bd 100644 --- a/Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp @@ -141,6 +141,7 @@ void VertexManager::UploadUniforms() UpdateVertexShaderConstants(); UpdateGeometryShaderConstants(); UpdatePixelShaderConstants(); + UpdateCustomShaderConstants(); } void VertexManager::UpdateVertexShaderConstants() @@ -192,6 +193,15 @@ void VertexManager::UpdatePixelShaderConstants() ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, sizeof(PixelShaderConstants)); pixel_shader_manager.dirty = false; } +} + +void VertexManager::UpdateCustomShaderConstants() +{ + auto& system = Core::System::GetInstance(); + auto& pixel_shader_manager = system.GetPixelShaderManager(); + + if (!ReserveConstantStorage()) + return; if (pixel_shader_manager.custom_constants_dirty) { diff --git a/Source/Core/VideoBackends/D3D12/D3D12VertexManager.h b/Source/Core/VideoBackends/D3D12/D3D12VertexManager.h index df637f1f53..76c0c6d7cb 100644 --- a/Source/Core/VideoBackends/D3D12/D3D12VertexManager.h +++ b/Source/Core/VideoBackends/D3D12/D3D12VertexManager.h @@ -35,6 +35,7 @@ protected: void UpdateVertexShaderConstants(); void UpdateGeometryShaderConstants(); void UpdatePixelShaderConstants(); + void UpdateCustomShaderConstants(); // Allocates storage in the uniform buffer of the specified size. If this storage cannot be // allocated immediately, the current command buffer will be submitted and all stage's diff --git a/Source/Core/VideoBackends/D3D12/DX12Context.cpp b/Source/Core/VideoBackends/D3D12/DX12Context.cpp index f3b481e8fc..2fa9fa8aa8 100644 --- a/Source/Core/VideoBackends/D3D12/DX12Context.cpp +++ b/Source/Core/VideoBackends/D3D12/DX12Context.cpp @@ -339,7 +339,7 @@ bool DXContext::CreateRootSignatures() bool DXContext::CreateGXRootSignature() { // GX: - // - 4 constant buffers (bindings 0-3), 0/1/2 visible in PS, 2 visible in VS, 1 visible in GS. + // - 4 constant buffers (bindings 0-3), 0/1/2 visible in PS, 3 visible in VS, 1 visible in GS. // - VideoCommon::MAX_PIXEL_SHADER_SAMPLERS textures (visible in PS). // - VideoCommon::MAX_PIXEL_SHADER_SAMPLERS samplers (visible in PS). // - 1 UAV (visible in PS). @@ -359,8 +359,10 @@ bool DXContext::CreateGXRootSignature() param_count++; SetRootParamCBV(¶ms[param_count], 1, D3D12_SHADER_VISIBILITY_VERTEX); param_count++; + SetRootParamCBV(¶ms[param_count], 2, D3D12_SHADER_VISIBILITY_VERTEX); + param_count++; if (g_ActiveConfig.UseVSForLinePointExpand()) - SetRootParamCBV(¶ms[param_count], 2, D3D12_SHADER_VISIBILITY_VERTEX); + SetRootParamCBV(¶ms[param_count], 3, D3D12_SHADER_VISIBILITY_VERTEX); else SetRootParamCBV(¶ms[param_count], 0, D3D12_SHADER_VISIBILITY_GEOMETRY); param_count++; diff --git a/Source/Core/VideoBackends/D3D12/DX12Context.h b/Source/Core/VideoBackends/D3D12/DX12Context.h index b43ece742a..0e1c4e7bc9 100644 --- a/Source/Core/VideoBackends/D3D12/DX12Context.h +++ b/Source/Core/VideoBackends/D3D12/DX12Context.h @@ -26,6 +26,7 @@ enum ROOT_PARAMETER ROOT_PARAMETER_PS_SAMPLERS, ROOT_PARAMETER_VS_CBV, ROOT_PARAMETER_VS_CBV2, + ROOT_PARAMETER_VS_CUS_CBV, ROOT_PARAMETER_GS_CBV, ROOT_PARAMETER_VS_SRV, ROOT_PARAMETER_BASE_VERTEX_CONSTANT, diff --git a/Source/Core/VideoBackends/Vulkan/Constants.h b/Source/Core/VideoBackends/Vulkan/Constants.h index 90271c60bd..afb70e0875 100644 --- a/Source/Core/VideoBackends/Vulkan/Constants.h +++ b/Source/Core/VideoBackends/Vulkan/Constants.h @@ -70,7 +70,7 @@ enum UNIFORM_BUFFER_DESCRIPTOR_SET_BINDING { UBO_DESCRIPTOR_SET_BINDING_PS, UBO_DESCRIPTOR_SET_BINDING_VS, - UBO_DESCRIPTOR_SET_BINDING_PS_CUST, + UBO_DESCRIPTOR_SET_BINDING_CUST, UBO_DESCRIPTOR_SET_BINDING_GS, NUM_UBO_DESCRIPTOR_SET_BINDINGS }; diff --git a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp index 2da221c636..128c24cd1a 100644 --- a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp @@ -115,8 +115,8 @@ bool ObjectCache::CreateDescriptorSetLayouts() VK_SHADER_STAGE_FRAGMENT_BIT}, {UBO_DESCRIPTOR_SET_BINDING_VS, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT}, - {UBO_DESCRIPTOR_SET_BINDING_PS_CUST, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, - VK_SHADER_STAGE_FRAGMENT_BIT}, + {UBO_DESCRIPTOR_SET_BINDING_CUST, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, + VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT}, {UBO_DESCRIPTOR_SET_BINDING_GS, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_GEOMETRY_BIT}, }}; diff --git a/Source/Core/VideoBackends/Vulkan/StateTracker.cpp b/Source/Core/VideoBackends/Vulkan/StateTracker.cpp index e55071533a..575ba9a352 100644 --- a/Source/Core/VideoBackends/Vulkan/StateTracker.cpp +++ b/Source/Core/VideoBackends/Vulkan/StateTracker.cpp @@ -496,8 +496,8 @@ void StateTracker::UpdateGXDescriptorSet() continue; } - // If custom pixel shaders haven't been used, their buffer range is 0 - if (i == UBO_DESCRIPTOR_SET_BINDING_PS_CUST && m_bindings.gx_ubo_bindings[i].range == 0) + // If custom shaders haven't been used, their buffer range is 0 + if (i == UBO_DESCRIPTOR_SET_BINDING_CUST && m_bindings.gx_ubo_bindings[i].range == 0) { continue; } diff --git a/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp b/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp index e18a5ffd81..dea5df2ea9 100644 --- a/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp @@ -261,7 +261,7 @@ void VertexManager::UpdatePixelShaderConstants() if (pixel_shader_manager.custom_constants_dirty) { StateTracker::GetInstance()->SetGXUniformBuffer( - UBO_DESCRIPTOR_SET_BINDING_PS_CUST, m_uniform_stream_buffer->GetBuffer(), + UBO_DESCRIPTOR_SET_BINDING_CUST, m_uniform_stream_buffer->GetBuffer(), m_uniform_stream_buffer->GetCurrentOffset(), static_cast(pixel_shader_manager.custom_constants.size())); std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer(), @@ -337,7 +337,7 @@ void VertexManager::UploadAllConstants() if (!pixel_shader_manager.custom_constants.empty()) { StateTracker::GetInstance()->SetGXUniformBuffer( - UBO_DESCRIPTOR_SET_BINDING_PS_CUST, m_uniform_stream_buffer->GetBuffer(), + UBO_DESCRIPTOR_SET_BINDING_CUST, m_uniform_stream_buffer->GetBuffer(), m_uniform_stream_buffer->GetCurrentOffset() + custom_pixel_constants_offset, custom_constants_size); }