summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authoriwubcode <iwubcode@users.noreply.github.com>2023-09-19 19:29:38 -0500
committeriwubcode <iwubcode@users.noreply.github.com>2023-10-06 02:17:42 -0500
commitb6d321bfb176b8296d9b128d3bb23da5b1a9124c (patch)
treec700dda47a8d7f9929abe0e50e6fee9bdce15df4 /Source
parent92accc3ef7bd599e112a67ee0095b22dd48c3055 (diff)
VideoBackends / VideoCommon: add new uniform buffer object for custom shader materials (slot 3, geometry shader buffer moves to slot 4 if available)
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/VideoBackends/D3D/D3DState.cpp12
-rw-r--r--Source/Core/VideoBackends/D3D/D3DState.h9
-rw-r--r--Source/Core/VideoBackends/D3D/D3DVertexManager.cpp18
-rw-r--r--Source/Core/VideoBackends/D3D/D3DVertexManager.h3
-rw-r--r--Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp13
-rw-r--r--Source/Core/VideoBackends/D3D12/D3D12Gfx.h39
-rw-r--r--Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp55
-rw-r--r--Source/Core/VideoBackends/D3D12/DX12Context.cpp7
-rw-r--r--Source/Core/VideoBackends/D3D12/DX12Context.h3
-rw-r--r--Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp53
-rw-r--r--Source/Core/VideoBackends/Vulkan/Constants.h3
-rw-r--r--Source/Core/VideoBackends/Vulkan/ObjectCache.cpp6
-rw-r--r--Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp66
-rw-r--r--Source/Core/VideoCommon/GeometryShaderGen.cpp2
-rw-r--r--Source/Core/VideoCommon/UberShaderVertex.cpp4
-rw-r--r--Source/Core/VideoCommon/VertexShaderGen.cpp4
16 files changed, 214 insertions, 83 deletions
diff --git a/Source/Core/VideoBackends/D3D/D3DState.cpp b/Source/Core/VideoBackends/D3D/D3DState.cpp
index 0372252b9a..f3aed1c1f2 100644
--- a/Source/Core/VideoBackends/D3D/D3DState.cpp
+++ b/Source/Core/VideoBackends/D3D/D3DState.cpp
@@ -69,12 +69,18 @@ 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[1] != m_pending.pixelConstants[1] ||
+ m_current.pixelConstants[2] != m_pending.pixelConstants[2])
{
- D3D::context->PSSetConstantBuffers(0, m_pending.pixelConstants[1] ? 2 : 1,
- m_pending.pixelConstants.data());
+ u32 count = 1;
+ if (m_pending.pixelConstants[1])
+ count++;
+ if (m_pending.pixelConstants[2])
+ count++;
+ D3D::context->PSSetConstantBuffers(0, count, m_pending.pixelConstants.data());
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)
diff --git a/Source/Core/VideoBackends/D3D/D3DState.h b/Source/Core/VideoBackends/D3D/D3DState.h
index 0893220e71..9b14b00350 100644
--- a/Source/Core/VideoBackends/D3D/D3DState.h
+++ b/Source/Core/VideoBackends/D3D/D3DState.h
@@ -91,13 +91,16 @@ public:
m_pending.samplers[index] = sampler;
}
- void SetPixelConstants(ID3D11Buffer* buffer0, ID3D11Buffer* buffer1 = nullptr)
+ void SetPixelConstants(ID3D11Buffer* buffer0, ID3D11Buffer* buffer1 = nullptr,
+ ID3D11Buffer* buffer2 = nullptr)
{
- if (m_current.pixelConstants[0] != buffer0 || m_current.pixelConstants[1] != buffer1)
+ if (m_current.pixelConstants[0] != buffer0 || m_current.pixelConstants[1] != buffer1 ||
+ m_current.pixelConstants[2] != buffer2)
m_dirtyFlags.set(DirtyFlag_PixelConstants);
m_pending.pixelConstants[0] = buffer0;
m_pending.pixelConstants[1] = buffer1;
+ m_pending.pixelConstants[2] = buffer2;
}
void SetVertexConstants(ID3D11Buffer* buffer)
@@ -252,7 +255,7 @@ private:
{
std::array<ID3D11ShaderResourceView*, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> textures;
std::array<ID3D11SamplerState*, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> samplers;
- std::array<ID3D11Buffer*, 2> pixelConstants;
+ std::array<ID3D11Buffer*, 3> pixelConstants;
ID3D11Buffer* vertexConstants;
ID3D11Buffer* geometryConstants;
ID3D11Buffer* vertexBuffer;
diff --git a/Source/Core/VideoBackends/D3D/D3DVertexManager.cpp b/Source/Core/VideoBackends/D3D/D3DVertexManager.cpp
index 4aa1c40266..5929788b03 100644
--- a/Source/Core/VideoBackends/D3D/D3DVertexManager.cpp
+++ b/Source/Core/VideoBackends/D3D/D3DVertexManager.cpp
@@ -288,9 +288,25 @@ void VertexManager::UploadUniforms()
pixel_shader_manager.dirty = false;
}
+ if (pixel_shader_manager.custom_constants_dirty)
+ {
+ if (m_last_custom_pixel_buffer_size < pixel_shader_manager.custom_constants.size())
+ {
+ m_custom_pixel_constant_buffer =
+ AllocateConstantBuffer(static_cast<u32>(pixel_shader_manager.custom_constants.size()));
+ }
+ UpdateConstantBuffer(m_custom_pixel_constant_buffer.Get(),
+ pixel_shader_manager.custom_constants.data(),
+ static_cast<u32>(pixel_shader_manager.custom_constants.size()));
+ m_last_custom_pixel_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);
+ g_ActiveConfig.bEnablePixelLighting ? m_vertex_constant_buffer.Get() : nullptr,
+ pixel_shader_manager.custom_constants.empty() ? nullptr :
+ m_custom_pixel_constant_buffer.Get());
D3D::stateman->SetVertexConstants(m_vertex_constant_buffer.Get());
D3D::stateman->SetGeometryConstants(m_geometry_constant_buffer.Get());
}
diff --git a/Source/Core/VideoBackends/D3D/D3DVertexManager.h b/Source/Core/VideoBackends/D3D/D3DVertexManager.h
index 669d670fed..4bdbf34bb0 100644
--- a/Source/Core/VideoBackends/D3D/D3DVertexManager.h
+++ b/Source/Core/VideoBackends/D3D/D3DVertexManager.h
@@ -68,6 +68,9 @@ private:
ComPtr<ID3D11Buffer> m_geometry_constant_buffer = nullptr;
ComPtr<ID3D11Buffer> m_pixel_constant_buffer = nullptr;
+ ComPtr<ID3D11Buffer> m_custom_pixel_constant_buffer = nullptr;
+ std::size_t m_last_custom_pixel_buffer_size = 0;
+
ComPtr<ID3D11Buffer> m_texel_buffer = nullptr;
std::array<ComPtr<ID3D11ShaderResourceView>, NUM_TEXEL_BUFFER_FORMATS> m_texel_buffer_views;
u32 m_texel_buffer_offset = 0;
diff --git a/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp b/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp
index 84bac629ac..08d273859f 100644
--- a/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp
+++ b/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp
@@ -161,7 +161,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_VS_SRV_Descriptor | DirtyState_PS_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_PrimitiveTopology | DirtyState_VS_SRV_Descriptor | DirtyState_PS_CUS_CBV);
auto* const cmdlist = g_dx_context->GetCommandList();
auto* const pipeline = static_cast<const DXPipeline*>(m_current_pipeline);
@@ -575,6 +575,13 @@ bool Gfx::ApplyState()
}
}
+ if (dirty_bits & DirtyState_PS_CUS_CBV)
+ {
+ cmdlist->SetGraphicsRootConstantBufferView(
+ g_ActiveConfig.bBBoxEnable ? ROOT_PARAMETER_PS_CUS_CBV : ROOT_PARAMETER_PS_CBV2,
+ m_state.constant_buffers[2]);
+ }
+
if (dirty_bits & DirtyState_VS_SRV_Descriptor && UsesDynamicVertexLoader(pipeline))
{
cmdlist->SetGraphicsRootDescriptorTable(ROOT_PARAMETER_VS_SRV,
@@ -584,7 +591,7 @@ bool Gfx::ApplyState()
if (dirty_bits & DirtyState_GS_CBV)
{
cmdlist->SetGraphicsRootConstantBufferView(ROOT_PARAMETER_GS_CBV,
- m_state.constant_buffers[2]);
+ m_state.constant_buffers[3]);
}
if (dirty_bits & DirtyState_UAV_Descriptor && g_ActiveConfig.bBBoxEnable)
diff --git a/Source/Core/VideoBackends/D3D12/D3D12Gfx.h b/Source/Core/VideoBackends/D3D12/D3D12Gfx.h
index b3426cb95e..9f537e5e09 100644
--- a/Source/Core/VideoBackends/D3D12/D3D12Gfx.h
+++ b/Source/Core/VideoBackends/D3D12/D3D12Gfx.h
@@ -98,8 +98,6 @@ protected:
void OnConfigChanged(u32 bits) override;
private:
- static const u32 NUM_CONSTANT_BUFFERS = 3;
-
// Dirty bits
enum DirtyStates
{
@@ -113,27 +111,28 @@ private:
DirtyState_PS_UAV = (1 << 7),
DirtyState_PS_CBV = (1 << 8),
DirtyState_VS_CBV = (1 << 9),
- DirtyState_GS_CBV = (1 << 10),
- DirtyState_SRV_Descriptor = (1 << 11),
- DirtyState_Sampler_Descriptor = (1 << 12),
- DirtyState_UAV_Descriptor = (1 << 13),
- DirtyState_VertexBuffer = (1 << 14),
- DirtyState_IndexBuffer = (1 << 15),
- DirtyState_PrimitiveTopology = (1 << 16),
- DirtyState_RootSignature = (1 << 17),
- DirtyState_ComputeRootSignature = (1 << 18),
- DirtyState_DescriptorHeaps = (1 << 19),
- DirtyState_VS_SRV = (1 << 20),
- DirtyState_VS_SRV_Descriptor = (1 << 21),
+ DirtyState_PS_CUS_CBV = (1 << 10),
+ DirtyState_GS_CBV = (1 << 11),
+ DirtyState_SRV_Descriptor = (1 << 12),
+ DirtyState_Sampler_Descriptor = (1 << 13),
+ DirtyState_UAV_Descriptor = (1 << 14),
+ DirtyState_VertexBuffer = (1 << 15),
+ DirtyState_IndexBuffer = (1 << 16),
+ DirtyState_PrimitiveTopology = (1 << 17),
+ DirtyState_RootSignature = (1 << 18),
+ DirtyState_ComputeRootSignature = (1 << 19),
+ DirtyState_DescriptorHeaps = (1 << 20),
+ DirtyState_VS_SRV = (1 << 21),
+ DirtyState_VS_SRV_Descriptor = (1 << 22),
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_GS_CBV |
- DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor | DirtyState_UAV_Descriptor |
- DirtyState_VertexBuffer | DirtyState_IndexBuffer | DirtyState_PrimitiveTopology |
- DirtyState_RootSignature | DirtyState_ComputeRootSignature | DirtyState_DescriptorHeaps |
- DirtyState_VS_SRV | DirtyState_VS_SRV_Descriptor
+ DirtyState_PS_UAV | DirtyState_PS_CBV | DirtyState_VS_CBV | DirtyState_PS_CUS_CBV |
+ DirtyState_GS_CBV | DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor |
+ DirtyState_UAV_Descriptor | DirtyState_VertexBuffer | DirtyState_IndexBuffer |
+ DirtyState_PrimitiveTopology | DirtyState_RootSignature | DirtyState_ComputeRootSignature |
+ DirtyState_DescriptorHeaps | DirtyState_VS_SRV | DirtyState_VS_SRV_Descriptor
};
void CheckForSwapChainChanges();
@@ -158,7 +157,7 @@ private:
{
ID3D12RootSignature* root_signature = nullptr;
DXShader* compute_shader = nullptr;
- std::array<D3D12_GPU_VIRTUAL_ADDRESS, 3> constant_buffers = {};
+ std::array<D3D12_GPU_VIRTUAL_ADDRESS, 4> constant_buffers = {};
std::array<D3D12_CPU_DESCRIPTOR_HANDLE, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> textures = {};
D3D12_CPU_DESCRIPTOR_HANDLE vs_srv = {};
D3D12_CPU_DESCRIPTOR_HANDLE ps_uav = {};
diff --git a/Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp b/Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp
index 03e88e3867..c0fe195e75 100644
--- a/Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp
+++ b/Source/Core/VideoBackends/D3D12/D3D12VertexManager.cpp
@@ -167,7 +167,7 @@ void VertexManager::UpdateGeometryShaderConstants()
if (!geometry_shader_manager.dirty || !ReserveConstantStorage())
return;
- Gfx::GetInstance()->SetConstantBuffer(2, m_uniform_stream_buffer.GetCurrentGPUPointer());
+ Gfx::GetInstance()->SetConstantBuffer(3, m_uniform_stream_buffer.GetCurrentGPUPointer());
std::memcpy(m_uniform_stream_buffer.GetCurrentHostPointer(), &geometry_shader_manager.constants,
sizeof(GeometryShaderConstants));
m_uniform_stream_buffer.CommitMemory(sizeof(GeometryShaderConstants));
@@ -180,23 +180,41 @@ void VertexManager::UpdatePixelShaderConstants()
auto& system = Core::System::GetInstance();
auto& pixel_shader_manager = system.GetPixelShaderManager();
- if (!pixel_shader_manager.dirty || !ReserveConstantStorage())
+ if (!ReserveConstantStorage())
return;
- Gfx::GetInstance()->SetConstantBuffer(0, m_uniform_stream_buffer.GetCurrentGPUPointer());
- std::memcpy(m_uniform_stream_buffer.GetCurrentHostPointer(), &pixel_shader_manager.constants,
- sizeof(PixelShaderConstants));
- m_uniform_stream_buffer.CommitMemory(sizeof(PixelShaderConstants));
- ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, sizeof(PixelShaderConstants));
- pixel_shader_manager.dirty = false;
+ if (pixel_shader_manager.dirty)
+ {
+ Gfx::GetInstance()->SetConstantBuffer(0, m_uniform_stream_buffer.GetCurrentGPUPointer());
+ std::memcpy(m_uniform_stream_buffer.GetCurrentHostPointer(), &pixel_shader_manager.constants,
+ sizeof(PixelShaderConstants));
+ m_uniform_stream_buffer.CommitMemory(sizeof(PixelShaderConstants));
+ ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, sizeof(PixelShaderConstants));
+ pixel_shader_manager.dirty = false;
+ }
+
+ if (pixel_shader_manager.custom_constants_dirty)
+ {
+ Gfx::GetInstance()->SetConstantBuffer(2, m_uniform_stream_buffer.GetCurrentGPUPointer());
+ std::memcpy(m_uniform_stream_buffer.GetCurrentHostPointer(),
+ pixel_shader_manager.custom_constants.data(),
+ pixel_shader_manager.custom_constants.size());
+ m_uniform_stream_buffer.CommitMemory(
+ static_cast<u32>(pixel_shader_manager.custom_constants.size()));
+ pixel_shader_manager.custom_constants_dirty = false;
+ }
}
bool VertexManager::ReserveConstantStorage()
{
+ auto& system = Core::System::GetInstance();
+ auto& pixel_shader_manager = system.GetPixelShaderManager();
+
static constexpr u32 reserve_size =
static_cast<u32>(std::max({sizeof(PixelShaderConstants), sizeof(VertexShaderConstants),
sizeof(GeometryShaderConstants)}));
- if (m_uniform_stream_buffer.ReserveMemory(reserve_size,
+ const u32 custom_constants_size = static_cast<u32>(pixel_shader_manager.custom_constants.size());
+ if (m_uniform_stream_buffer.ReserveMemory(reserve_size + custom_constants_size,
D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT))
{
return true;
@@ -214,6 +232,9 @@ bool VertexManager::ReserveConstantStorage()
void VertexManager::UploadAllConstants()
{
+ auto& system = Core::System::GetInstance();
+ auto& pixel_shader_manager = system.GetPixelShaderManager();
+
// We are free to re-use parts of the buffer now since we're uploading all constants.
const u32 pixel_constants_offset = 0;
constexpr u32 vertex_constants_offset =
@@ -222,7 +243,11 @@ void VertexManager::UploadAllConstants()
constexpr u32 geometry_constants_offset =
Common::AlignUp(vertex_constants_offset + sizeof(VertexShaderConstants),
D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
- const u32 allocation_size = geometry_constants_offset + sizeof(GeometryShaderConstants);
+ constexpr u32 custom_pixel_constants_offset =
+ Common::AlignUp(geometry_constants_offset + sizeof(GeometryShaderConstants),
+ D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
+ const u32 allocation_size = custom_pixel_constants_offset +
+ static_cast<u32>(pixel_shader_manager.custom_constants.size());
// Allocate everything at once.
// We should only be here if the buffer was full and a command buffer was submitted anyway.
@@ -239,10 +264,10 @@ void VertexManager::UploadAllConstants()
Gfx::GetInstance()->SetConstantBuffer(1, m_uniform_stream_buffer.GetCurrentGPUPointer() +
vertex_constants_offset);
Gfx::GetInstance()->SetConstantBuffer(2, m_uniform_stream_buffer.GetCurrentGPUPointer() +
+ custom_pixel_constants_offset);
+ Gfx::GetInstance()->SetConstantBuffer(3, m_uniform_stream_buffer.GetCurrentGPUPointer() +
geometry_constants_offset);
- auto& system = Core::System::GetInstance();
- auto& pixel_shader_manager = system.GetPixelShaderManager();
auto& vertex_shader_manager = system.GetVertexShaderManager();
auto& geometry_shader_manager = system.GetGeometryShaderManager();
@@ -253,6 +278,12 @@ void VertexManager::UploadAllConstants()
&vertex_shader_manager.constants, sizeof(VertexShaderConstants));
std::memcpy(m_uniform_stream_buffer.GetCurrentHostPointer() + geometry_constants_offset,
&geometry_shader_manager.constants, sizeof(GeometryShaderConstants));
+ if (!pixel_shader_manager.custom_constants.empty())
+ {
+ std::memcpy(m_uniform_stream_buffer.GetCurrentHostPointer() + custom_pixel_constants_offset,
+ pixel_shader_manager.custom_constants.data(),
+ pixel_shader_manager.custom_constants.size());
+ }
// Finally, flush buffer memory after copying
m_uniform_stream_buffer.CommitMemory(allocation_size);
diff --git a/Source/Core/VideoBackends/D3D12/DX12Context.cpp b/Source/Core/VideoBackends/D3D12/DX12Context.cpp
index dd8630ac3b..843efc79d4 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:
- // - 3 constant buffers (bindings 0-2), 0/1 visible in PS, 2 visible in VS, 1 visible in GS.
+ // - 4 constant buffers (bindings 0-3), 0/1/2 visible in PS, 2 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).
@@ -367,7 +367,7 @@ bool DXContext::CreateGXRootSignature()
SetRootParamTable(&params[param_count], &ranges[param_count], D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 3,
1, D3D12_SHADER_VISIBILITY_VERTEX);
param_count++;
- SetRootParamConstant(&params[param_count], 3, 1, D3D12_SHADER_VISIBILITY_VERTEX);
+ SetRootParamConstant(&params[param_count], 4, 1, D3D12_SHADER_VISIBILITY_VERTEX);
param_count++;
// Since these must be contiguous, pixel lighting goes to bbox if not enabled.
@@ -383,6 +383,9 @@ bool DXContext::CreateGXRootSignature()
param_count++;
}
+ SetRootParamCBV(&params[param_count], 2, D3D12_SHADER_VISIBILITY_PIXEL);
+ param_count++;
+
return BuildRootSignature(m_device.Get(), &m_gx_root_signature, params.data(), param_count);
}
diff --git a/Source/Core/VideoBackends/D3D12/DX12Context.h b/Source/Core/VideoBackends/D3D12/DX12Context.h
index ad9ef9fe74..d492e7face 100644
--- a/Source/Core/VideoBackends/D3D12/DX12Context.h
+++ b/Source/Core/VideoBackends/D3D12/DX12Context.h
@@ -30,7 +30,8 @@ enum ROOT_PARAMETER
ROOT_PARAMETER_VS_SRV,
ROOT_PARAMETER_BASE_VERTEX_CONSTANT,
ROOT_PARAMETER_PS_UAV_OR_CBV2,
- ROOT_PARAMETER_PS_CBV2, // ROOT_PARAMETER_PS_UAV_OR_CBV2 if bbox is not enabled
+ ROOT_PARAMETER_PS_CBV2, // ROOT_PARAMETER_PS_UAV_OR_CBV2 if bbox is not enabled
+ ROOT_PARAMETER_PS_CUS_CBV, // ROOT_PARAMETER_PS_CBV2 if bbox is not enabled
NUM_ROOT_PARAMETERS
};
// Compute shader root parameters
diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp
index 8c56a40e8c..91794696b9 100644
--- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp
+++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp
@@ -105,9 +105,9 @@ void SHADER::SetProgramVariables()
if (VSBlock_id != -1)
glUniformBlockBinding(glprogid, VSBlock_id, 2);
if (GSBlock_id != -1)
- glUniformBlockBinding(glprogid, GSBlock_id, 3);
+ glUniformBlockBinding(glprogid, GSBlock_id, 4);
if (UBERBlock_id != -1)
- glUniformBlockBinding(glprogid, UBERBlock_id, 4);
+ glUniformBlockBinding(glprogid, UBERBlock_id, 5);
// Bind Texture Samplers
for (int a = 0; a < 8; ++a)
@@ -232,35 +232,54 @@ void ProgramShaderCache::UploadConstants()
auto& pixel_shader_manager = system.GetPixelShaderManager();
auto& vertex_shader_manager = system.GetVertexShaderManager();
auto& geometry_shader_manager = system.GetGeometryShaderManager();
- if (pixel_shader_manager.dirty || vertex_shader_manager.dirty || geometry_shader_manager.dirty)
+ if (pixel_shader_manager.dirty || vertex_shader_manager.dirty || geometry_shader_manager.dirty ||
+ pixel_shader_manager.custom_constants_dirty)
{
- auto buffer = s_buffer->Map(s_ubo_buffer_size, s_ubo_align);
+ const u32 custom_constants_size = static_cast<u32>(
+ Common::AlignUp(pixel_shader_manager.custom_constants.size(), s_ubo_align));
+ auto buffer = s_buffer->Map(s_ubo_buffer_size + custom_constants_size, s_ubo_align);
memcpy(buffer.first, &pixel_shader_manager.constants, sizeof(PixelShaderConstants));
- memcpy(buffer.first + Common::AlignUp(sizeof(PixelShaderConstants), s_ubo_align),
- &vertex_shader_manager.constants, sizeof(VertexShaderConstants));
+ u64 size = Common::AlignUp(sizeof(PixelShaderConstants), s_ubo_align);
- memcpy(buffer.first + Common::AlignUp(sizeof(PixelShaderConstants), s_ubo_align) +
- Common::AlignUp(sizeof(VertexShaderConstants), s_ubo_align),
- &geometry_shader_manager.constants, sizeof(GeometryShaderConstants));
+ memcpy(buffer.first + size, &vertex_shader_manager.constants, sizeof(VertexShaderConstants));
+ size += Common::AlignUp(sizeof(VertexShaderConstants), s_ubo_align);
+
+ if (!pixel_shader_manager.custom_constants.empty())
+ {
+ memcpy(buffer.first + size, pixel_shader_manager.custom_constants.data(),
+ pixel_shader_manager.custom_constants.size());
+ size += custom_constants_size;
+ }
+
+ memcpy(buffer.first + size, &geometry_shader_manager.constants,
+ sizeof(GeometryShaderConstants));
+
+ s_buffer->Unmap(s_ubo_buffer_size + custom_constants_size);
- s_buffer->Unmap(s_ubo_buffer_size);
glBindBufferRange(GL_UNIFORM_BUFFER, 1, s_buffer->m_buffer, buffer.second,
sizeof(PixelShaderConstants));
- glBindBufferRange(GL_UNIFORM_BUFFER, 2, s_buffer->m_buffer,
- buffer.second + Common::AlignUp(sizeof(PixelShaderConstants), s_ubo_align),
+ size = Common::AlignUp(sizeof(PixelShaderConstants), s_ubo_align);
+ glBindBufferRange(GL_UNIFORM_BUFFER, 2, s_buffer->m_buffer, buffer.second + size,
sizeof(VertexShaderConstants));
- glBindBufferRange(GL_UNIFORM_BUFFER, 3, s_buffer->m_buffer,
- buffer.second + Common::AlignUp(sizeof(PixelShaderConstants), s_ubo_align) +
- Common::AlignUp(sizeof(VertexShaderConstants), s_ubo_align),
+ size += Common::AlignUp(sizeof(VertexShaderConstants), s_ubo_align);
+
+ if (!pixel_shader_manager.custom_constants.empty())
+ {
+ glBindBufferRange(GL_UNIFORM_BUFFER, 3, s_buffer->m_buffer, buffer.second + size,
+ pixel_shader_manager.custom_constants.size());
+ size += Common::AlignUp(pixel_shader_manager.custom_constants.size(), s_ubo_align);
+ }
+ glBindBufferRange(GL_UNIFORM_BUFFER, 4, s_buffer->m_buffer, buffer.second + size,
sizeof(GeometryShaderConstants));
pixel_shader_manager.dirty = false;
vertex_shader_manager.dirty = false;
geometry_shader_manager.dirty = false;
+ pixel_shader_manager.custom_constants_dirty = false;
- ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, s_ubo_buffer_size);
+ ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, s_ubo_buffer_size + custom_constants_size);
}
}
@@ -273,7 +292,7 @@ void ProgramShaderCache::UploadConstants(const void* data, u32 data_size)
s_buffer->Unmap(alloc_size);
// bind the same sub-buffer to all stages
- for (u32 index = 1; index <= 3; index++)
+ for (u32 index = 1; index <= 4; index++)
glBindBufferRange(GL_UNIFORM_BUFFER, index, s_buffer->m_buffer, buffer.second, data_size);
ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, data_size);
diff --git a/Source/Core/VideoBackends/Vulkan/Constants.h b/Source/Core/VideoBackends/Vulkan/Constants.h
index 2bdceefe3b..90271c60bd 100644
--- a/Source/Core/VideoBackends/Vulkan/Constants.h
+++ b/Source/Core/VideoBackends/Vulkan/Constants.h
@@ -38,7 +38,7 @@ enum DESCRIPTOR_SET_LAYOUT
// We use four pipeline layouts:
// - Standard
-// - Per-stage UBO (VS/GS/PS, VS constants accessible from PS) [set=0, binding=0-2]
+// - Per-stage UBO (VS/GS/PS, VS constants accessible from PS) [set=0, binding=0-3]
// - 8 combined image samplers (accessible from PS) [set=1, binding=0-7]
// - 1 SSBO accessible from PS if supported [set=2, binding=0]
// - Uber
@@ -70,6 +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_GS,
NUM_UBO_DESCRIPTOR_SET_BINDINGS
};
diff --git a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp
index d899191614..3a226b7177 100644
--- a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp
+++ b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp
@@ -110,11 +110,13 @@ bool ObjectCache::CreateDescriptorSetLayouts()
{
// The geometry shader buffer must be last in this binding set, as we don't include it
// if geometry shaders are not supported by the device. See the decrement below.
- static const std::array<VkDescriptorSetLayoutBinding, 3> standard_ubo_bindings{{
+ static const std::array<VkDescriptorSetLayoutBinding, 4> standard_ubo_bindings{{
{UBO_DESCRIPTOR_SET_BINDING_PS, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1,
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_GS, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1,
VK_SHADER_STAGE_GEOMETRY_BIT},
}};
@@ -170,7 +172,7 @@ bool ObjectCache::CreateDescriptorSetLayouts()
{18, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT},
}};
- std::array<VkDescriptorSetLayoutBinding, 3> ubo_bindings = standard_ubo_bindings;
+ std::array<VkDescriptorSetLayoutBinding, 4> ubo_bindings = standard_ubo_bindings;
std::array<VkDescriptorSetLayoutCreateInfo, NUM_DESCRIPTOR_SET_LAYOUTS> create_infos{{
{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, nullptr, 0,
diff --git a/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp b/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp
index 5069d3e6d0..73c9dfde59 100644
--- a/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp
@@ -243,22 +243,43 @@ void VertexManager::UpdatePixelShaderConstants()
auto& system = Core::System::GetInstance();
auto& pixel_shader_manager = system.GetPixelShaderManager();
- if (!pixel_shader_manager.dirty || !ReserveConstantStorage())
+ if (!ReserveConstantStorage())
return;
- StateTracker::GetInstance()->SetGXUniformBuffer(
- UBO_DESCRIPTOR_SET_BINDING_PS, m_uniform_stream_buffer->GetBuffer(),
- m_uniform_stream_buffer->GetCurrentOffset(), sizeof(PixelShaderConstants));
- std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer(), &pixel_shader_manager.constants,
- sizeof(PixelShaderConstants));
- m_uniform_stream_buffer->CommitMemory(sizeof(PixelShaderConstants));
- ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, sizeof(PixelShaderConstants));
- pixel_shader_manager.dirty = false;
+ if (pixel_shader_manager.dirty)
+ {
+ StateTracker::GetInstance()->SetGXUniformBuffer(
+ UBO_DESCRIPTOR_SET_BINDING_PS, m_uniform_stream_buffer->GetBuffer(),
+ m_uniform_stream_buffer->GetCurrentOffset(), sizeof(PixelShaderConstants));
+ std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer(), &pixel_shader_manager.constants,
+ sizeof(PixelShaderConstants));
+ m_uniform_stream_buffer->CommitMemory(sizeof(PixelShaderConstants));
+ ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, sizeof(PixelShaderConstants));
+ pixel_shader_manager.dirty = false;
+ }
+
+ if (pixel_shader_manager.custom_constants_dirty)
+ {
+ StateTracker::GetInstance()->SetGXUniformBuffer(
+ UBO_DESCRIPTOR_SET_BINDING_PS_CUST, m_uniform_stream_buffer->GetBuffer(),
+ m_uniform_stream_buffer->GetCurrentOffset(),
+ static_cast<u32>(pixel_shader_manager.custom_constants.size()));
+ std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer(),
+ pixel_shader_manager.custom_constants.data(),
+ pixel_shader_manager.custom_constants.size());
+ m_uniform_stream_buffer->CommitMemory(
+ static_cast<u32>(pixel_shader_manager.custom_constants.size()));
+ pixel_shader_manager.custom_constants_dirty = false;
+ }
}
bool VertexManager::ReserveConstantStorage()
{
- if (m_uniform_stream_buffer->ReserveMemory(m_uniform_buffer_reserve_size,
+ auto& system = Core::System::GetInstance();
+ auto& pixel_shader_manager = system.GetPixelShaderManager();
+ const u32 custom_constants_size = static_cast<u32>(pixel_shader_manager.custom_constants.size());
+
+ if (m_uniform_stream_buffer->ReserveMemory(m_uniform_buffer_reserve_size + custom_constants_size,
g_vulkan_context->GetUniformBufferAlignment()))
{
return true;
@@ -276,6 +297,11 @@ bool VertexManager::ReserveConstantStorage()
void VertexManager::UploadAllConstants()
{
+ auto& system = Core::System::GetInstance();
+ auto& pixel_shader_manager = system.GetPixelShaderManager();
+
+ const u32 custom_constants_size = static_cast<u32>(pixel_shader_manager.custom_constants.size());
+
// We are free to re-use parts of the buffer now since we're uploading all constants.
const u32 ub_alignment = static_cast<u32>(g_vulkan_context->GetUniformBufferAlignment());
const u32 pixel_constants_offset = 0;
@@ -283,7 +309,9 @@ void VertexManager::UploadAllConstants()
Common::AlignUp(pixel_constants_offset + sizeof(PixelShaderConstants), ub_alignment);
const u32 geometry_constants_offset =
Common::AlignUp(vertex_constants_offset + sizeof(VertexShaderConstants), ub_alignment);
- const u32 allocation_size = geometry_constants_offset + sizeof(GeometryShaderConstants);
+ const u32 custom_pixel_constants_offset =
+ Common::AlignUp(geometry_constants_offset + sizeof(GeometryShaderConstants), ub_alignment);
+ const u32 allocation_size = custom_pixel_constants_offset + custom_constants_size;
// Allocate everything at once.
// We should only be here if the buffer was full and a command buffer was submitted anyway.
@@ -293,8 +321,6 @@ void VertexManager::UploadAllConstants()
return;
}
- auto& system = Core::System::GetInstance();
- auto& pixel_shader_manager = system.GetPixelShaderManager();
auto& vertex_shader_manager = system.GetVertexShaderManager();
auto& geometry_shader_manager = system.GetGeometryShaderManager();
@@ -307,6 +333,14 @@ void VertexManager::UploadAllConstants()
UBO_DESCRIPTOR_SET_BINDING_VS, m_uniform_stream_buffer->GetBuffer(),
m_uniform_stream_buffer->GetCurrentOffset() + vertex_constants_offset,
sizeof(VertexShaderConstants));
+
+ if (!pixel_shader_manager.custom_constants.empty())
+ {
+ StateTracker::GetInstance()->SetGXUniformBuffer(
+ UBO_DESCRIPTOR_SET_BINDING_PS_CUST, m_uniform_stream_buffer->GetBuffer(),
+ m_uniform_stream_buffer->GetCurrentOffset() + custom_pixel_constants_offset,
+ custom_constants_size);
+ }
StateTracker::GetInstance()->SetGXUniformBuffer(
UBO_DESCRIPTOR_SET_BINDING_GS, m_uniform_stream_buffer->GetBuffer(),
m_uniform_stream_buffer->GetCurrentOffset() + geometry_constants_offset,
@@ -319,6 +353,12 @@ void VertexManager::UploadAllConstants()
&vertex_shader_manager.constants, sizeof(VertexShaderConstants));
std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer() + geometry_constants_offset,
&geometry_shader_manager.constants, sizeof(GeometryShaderConstants));
+ if (!pixel_shader_manager.custom_constants.empty())
+ {
+ std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer() + custom_pixel_constants_offset,
+ pixel_shader_manager.custom_constants.data(),
+ pixel_shader_manager.custom_constants.size());
+ }
// Finally, flush buffer memory after copying
m_uniform_stream_buffer->CommitMemory(allocation_size);
diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp
index 5b552f9298..c4b6649331 100644
--- a/Source/Core/VideoCommon/GeometryShaderGen.cpp
+++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp
@@ -93,7 +93,7 @@ ShaderCode GenerateGeometryShaderCode(APIType api_type, const ShaderHostConfig&
// uniforms
if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)
- out.Write("UBO_BINDING(std140, 3) uniform GSBlock {{\n");
+ out.Write("UBO_BINDING(std140, 4) uniform GSBlock {{\n");
else
out.Write("cbuffer GSBlock {{\n");
diff --git a/Source/Core/VideoCommon/UberShaderVertex.cpp b/Source/Core/VideoCommon/UberShaderVertex.cpp
index 6e663a1d02..71fc974ced 100644
--- a/Source/Core/VideoCommon/UberShaderVertex.cpp
+++ b/Source/Core/VideoCommon/UberShaderVertex.cpp
@@ -52,7 +52,7 @@ ShaderCode GenVertexShader(APIType api_type, const ShaderHostConfig& host_config
if (vertex_loader)
{
- out.Write("UBO_BINDING(std140, 3) uniform GSBlock {{\n");
+ out.Write("UBO_BINDING(std140, 4) uniform GSBlock {{\n");
out.Write("{}", s_geometry_shader_uniforms);
out.Write("}};\n");
}
@@ -84,7 +84,7 @@ SSBO_BINDING(1) readonly restrict buffer Vertices {{
// D3D12 uses a root constant for this uniform, since it changes with every draw.
// D3D11 doesn't currently support dynamic vertex loader, and we'll have to figure something
// out for it if we want to support it in the future.
- out.Write("UBO_BINDING(std140, 4) uniform DX_Constants {{\n"
+ out.Write("UBO_BINDING(std140, 5) uniform DX_Constants {{\n"
" uint base_vertex;\n"
"}};\n\n"
"uint GetVertexBaseOffset(uint vertex_id) {{\n"
diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp
index ff555b74fe..d2898cb412 100644
--- a/Source/Core/VideoCommon/VertexShaderGen.cpp
+++ b/Source/Core/VideoCommon/VertexShaderGen.cpp
@@ -96,14 +96,14 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
if (uid_data->vs_expand != VSExpand::None)
{
- out.Write("UBO_BINDING(std140, 3) uniform GSBlock {{\n");
+ out.Write("UBO_BINDING(std140, 4) uniform GSBlock {{\n");
out.Write("{}", s_geometry_shader_uniforms);
out.Write("}};\n");
if (api_type == APIType::D3D)
{
// D3D doesn't include the base vertex in SV_VertexID
- out.Write("UBO_BINDING(std140, 4) uniform DX_Constants {{\n"
+ out.Write("UBO_BINDING(std140, 5) uniform DX_Constants {{\n"
" uint base_vertex;\n"
"}};\n\n");
}