Merge pull request #12185 from iwubcode/custom_shader_uniform_backend_support

VideoBackends / VideoCommon: add support for custom shader uniforms to D3D, Vulkan, OGL
This commit is contained in:
Admiral H. Curtiss 2023-10-15 00:21:56 +02:00 committed by GitHub
commit 2677fd9a8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 237 additions and 86 deletions

View File

@ -69,12 +69,18 @@ void StateManager::Apply()
if (dirtyConstants) if (dirtyConstants)
{ {
if (m_current.pixelConstants[0] != m_pending.pixelConstants[0] || 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, u32 count = 1;
m_pending.pixelConstants.data()); 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[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];
} }
if (m_current.vertexConstants != m_pending.vertexConstants) if (m_current.vertexConstants != m_pending.vertexConstants)

View File

@ -91,13 +91,16 @@ public:
m_pending.samplers[index] = sampler; 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_dirtyFlags.set(DirtyFlag_PixelConstants);
m_pending.pixelConstants[0] = buffer0; m_pending.pixelConstants[0] = buffer0;
m_pending.pixelConstants[1] = buffer1; m_pending.pixelConstants[1] = buffer1;
m_pending.pixelConstants[2] = buffer2;
} }
void SetVertexConstants(ID3D11Buffer* buffer) void SetVertexConstants(ID3D11Buffer* buffer)
@ -252,7 +255,7 @@ private:
{ {
std::array<ID3D11ShaderResourceView*, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> textures; std::array<ID3D11ShaderResourceView*, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> textures;
std::array<ID3D11SamplerState*, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> samplers; std::array<ID3D11SamplerState*, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> samplers;
std::array<ID3D11Buffer*, 2> pixelConstants; std::array<ID3D11Buffer*, 3> pixelConstants;
ID3D11Buffer* vertexConstants; ID3D11Buffer* vertexConstants;
ID3D11Buffer* geometryConstants; ID3D11Buffer* geometryConstants;
ID3D11Buffer* vertexBuffer; ID3D11Buffer* vertexBuffer;

View File

@ -288,9 +288,25 @@ void VertexManager::UploadUniforms()
pixel_shader_manager.dirty = false; 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( D3D::stateman->SetPixelConstants(
m_pixel_constant_buffer.Get(), 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->SetVertexConstants(m_vertex_constant_buffer.Get());
D3D::stateman->SetGeometryConstants(m_geometry_constant_buffer.Get()); D3D::stateman->SetGeometryConstants(m_geometry_constant_buffer.Get());
} }

View File

@ -68,6 +68,9 @@ private:
ComPtr<ID3D11Buffer> m_geometry_constant_buffer = nullptr; ComPtr<ID3D11Buffer> m_geometry_constant_buffer = nullptr;
ComPtr<ID3D11Buffer> m_pixel_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; ComPtr<ID3D11Buffer> m_texel_buffer = nullptr;
std::array<ComPtr<ID3D11ShaderResourceView>, NUM_TEXEL_BUFFER_FORMATS> m_texel_buffer_views; std::array<ComPtr<ID3D11ShaderResourceView>, NUM_TEXEL_BUFFER_FORMATS> m_texel_buffer_views;
u32 m_texel_buffer_offset = 0; u32 m_texel_buffer_offset = 0;

View File

@ -161,7 +161,7 @@ void Gfx::SetPipeline(const AbstractPipeline* pipeline)
m_dirty_bits |= DirtyState_RootSignature | DirtyState_PS_CBV | DirtyState_VS_CBV | m_dirty_bits |= DirtyState_RootSignature | DirtyState_PS_CBV | DirtyState_VS_CBV |
DirtyState_GS_CBV | DirtyState_SRV_Descriptor | DirtyState_GS_CBV | DirtyState_SRV_Descriptor |
DirtyState_Sampler_Descriptor | DirtyState_UAV_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) 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_ScissorRect | DirtyState_PS_UAV | DirtyState_PS_CBV | DirtyState_VS_CBV |
DirtyState_GS_CBV | DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor | DirtyState_GS_CBV | DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor |
DirtyState_UAV_Descriptor | DirtyState_VertexBuffer | DirtyState_IndexBuffer | 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 cmdlist = g_dx_context->GetCommandList();
auto* const pipeline = static_cast<const DXPipeline*>(m_current_pipeline); 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)) if (dirty_bits & DirtyState_VS_SRV_Descriptor && UsesDynamicVertexLoader(pipeline))
{ {
cmdlist->SetGraphicsRootDescriptorTable(ROOT_PARAMETER_VS_SRV, cmdlist->SetGraphicsRootDescriptorTable(ROOT_PARAMETER_VS_SRV,
@ -584,7 +591,7 @@ bool Gfx::ApplyState()
if (dirty_bits & DirtyState_GS_CBV) if (dirty_bits & DirtyState_GS_CBV)
{ {
cmdlist->SetGraphicsRootConstantBufferView(ROOT_PARAMETER_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) if (dirty_bits & DirtyState_UAV_Descriptor && g_ActiveConfig.bBBoxEnable)

View File

@ -98,8 +98,6 @@ protected:
void OnConfigChanged(u32 bits) override; void OnConfigChanged(u32 bits) override;
private: private:
static const u32 NUM_CONSTANT_BUFFERS = 3;
// Dirty bits // Dirty bits
enum DirtyStates enum DirtyStates
{ {
@ -113,27 +111,28 @@ private:
DirtyState_PS_UAV = (1 << 7), DirtyState_PS_UAV = (1 << 7),
DirtyState_PS_CBV = (1 << 8), DirtyState_PS_CBV = (1 << 8),
DirtyState_VS_CBV = (1 << 9), DirtyState_VS_CBV = (1 << 9),
DirtyState_GS_CBV = (1 << 10), DirtyState_PS_CUS_CBV = (1 << 10),
DirtyState_SRV_Descriptor = (1 << 11), DirtyState_GS_CBV = (1 << 11),
DirtyState_Sampler_Descriptor = (1 << 12), DirtyState_SRV_Descriptor = (1 << 12),
DirtyState_UAV_Descriptor = (1 << 13), DirtyState_Sampler_Descriptor = (1 << 13),
DirtyState_VertexBuffer = (1 << 14), DirtyState_UAV_Descriptor = (1 << 14),
DirtyState_IndexBuffer = (1 << 15), DirtyState_VertexBuffer = (1 << 15),
DirtyState_PrimitiveTopology = (1 << 16), DirtyState_IndexBuffer = (1 << 16),
DirtyState_RootSignature = (1 << 17), DirtyState_PrimitiveTopology = (1 << 17),
DirtyState_ComputeRootSignature = (1 << 18), DirtyState_RootSignature = (1 << 18),
DirtyState_DescriptorHeaps = (1 << 19), DirtyState_ComputeRootSignature = (1 << 19),
DirtyState_VS_SRV = (1 << 20), DirtyState_DescriptorHeaps = (1 << 20),
DirtyState_VS_SRV_Descriptor = (1 << 21), DirtyState_VS_SRV = (1 << 21),
DirtyState_VS_SRV_Descriptor = (1 << 22),
DirtyState_All = DirtyState_All =
DirtyState_Framebuffer | DirtyState_Pipeline | DirtyState_Textures | DirtyState_Samplers | DirtyState_Framebuffer | DirtyState_Pipeline | DirtyState_Textures | DirtyState_Samplers |
DirtyState_Viewport | DirtyState_ScissorRect | DirtyState_ComputeImageTexture | DirtyState_Viewport | DirtyState_ScissorRect | DirtyState_ComputeImageTexture |
DirtyState_PS_UAV | DirtyState_PS_CBV | DirtyState_VS_CBV | DirtyState_GS_CBV | DirtyState_PS_UAV | DirtyState_PS_CBV | DirtyState_VS_CBV | DirtyState_PS_CUS_CBV |
DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor | DirtyState_UAV_Descriptor | DirtyState_GS_CBV | DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor |
DirtyState_VertexBuffer | DirtyState_IndexBuffer | DirtyState_PrimitiveTopology | DirtyState_UAV_Descriptor | DirtyState_VertexBuffer | DirtyState_IndexBuffer |
DirtyState_RootSignature | DirtyState_ComputeRootSignature | DirtyState_DescriptorHeaps | DirtyState_PrimitiveTopology | DirtyState_RootSignature | DirtyState_ComputeRootSignature |
DirtyState_VS_SRV | DirtyState_VS_SRV_Descriptor DirtyState_DescriptorHeaps | DirtyState_VS_SRV | DirtyState_VS_SRV_Descriptor
}; };
void CheckForSwapChainChanges(); void CheckForSwapChainChanges();
@ -158,7 +157,7 @@ private:
{ {
ID3D12RootSignature* root_signature = nullptr; ID3D12RootSignature* root_signature = nullptr;
DXShader* compute_shader = 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 = {}; std::array<D3D12_CPU_DESCRIPTOR_HANDLE, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> textures = {};
D3D12_CPU_DESCRIPTOR_HANDLE vs_srv = {}; D3D12_CPU_DESCRIPTOR_HANDLE vs_srv = {};
D3D12_CPU_DESCRIPTOR_HANDLE ps_uav = {}; D3D12_CPU_DESCRIPTOR_HANDLE ps_uav = {};

View File

@ -167,7 +167,7 @@ void VertexManager::UpdateGeometryShaderConstants()
if (!geometry_shader_manager.dirty || !ReserveConstantStorage()) if (!geometry_shader_manager.dirty || !ReserveConstantStorage())
return; 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, std::memcpy(m_uniform_stream_buffer.GetCurrentHostPointer(), &geometry_shader_manager.constants,
sizeof(GeometryShaderConstants)); sizeof(GeometryShaderConstants));
m_uniform_stream_buffer.CommitMemory(sizeof(GeometryShaderConstants)); m_uniform_stream_buffer.CommitMemory(sizeof(GeometryShaderConstants));
@ -180,23 +180,41 @@ void VertexManager::UpdatePixelShaderConstants()
auto& system = Core::System::GetInstance(); auto& system = Core::System::GetInstance();
auto& pixel_shader_manager = system.GetPixelShaderManager(); auto& pixel_shader_manager = system.GetPixelShaderManager();
if (!pixel_shader_manager.dirty || !ReserveConstantStorage()) if (!ReserveConstantStorage())
return; return;
Gfx::GetInstance()->SetConstantBuffer(0, m_uniform_stream_buffer.GetCurrentGPUPointer()); if (pixel_shader_manager.dirty)
std::memcpy(m_uniform_stream_buffer.GetCurrentHostPointer(), &pixel_shader_manager.constants, {
sizeof(PixelShaderConstants)); Gfx::GetInstance()->SetConstantBuffer(0, m_uniform_stream_buffer.GetCurrentGPUPointer());
m_uniform_stream_buffer.CommitMemory(sizeof(PixelShaderConstants)); std::memcpy(m_uniform_stream_buffer.GetCurrentHostPointer(), &pixel_shader_manager.constants,
ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, sizeof(PixelShaderConstants)); sizeof(PixelShaderConstants));
pixel_shader_manager.dirty = false; 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() bool VertexManager::ReserveConstantStorage()
{ {
auto& system = Core::System::GetInstance();
auto& pixel_shader_manager = system.GetPixelShaderManager();
static constexpr u32 reserve_size = static constexpr u32 reserve_size =
static_cast<u32>(std::max({sizeof(PixelShaderConstants), sizeof(VertexShaderConstants), static_cast<u32>(std::max({sizeof(PixelShaderConstants), sizeof(VertexShaderConstants),
sizeof(GeometryShaderConstants)})); 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)) D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT))
{ {
return true; return true;
@ -214,6 +232,9 @@ bool VertexManager::ReserveConstantStorage()
void VertexManager::UploadAllConstants() 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. // We are free to re-use parts of the buffer now since we're uploading all constants.
const u32 pixel_constants_offset = 0; const u32 pixel_constants_offset = 0;
constexpr u32 vertex_constants_offset = constexpr u32 vertex_constants_offset =
@ -222,7 +243,11 @@ void VertexManager::UploadAllConstants()
constexpr u32 geometry_constants_offset = constexpr u32 geometry_constants_offset =
Common::AlignUp(vertex_constants_offset + sizeof(VertexShaderConstants), Common::AlignUp(vertex_constants_offset + sizeof(VertexShaderConstants),
D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT); 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. // Allocate everything at once.
// We should only be here if the buffer was full and a command buffer was submitted anyway. // 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() + Gfx::GetInstance()->SetConstantBuffer(1, m_uniform_stream_buffer.GetCurrentGPUPointer() +
vertex_constants_offset); vertex_constants_offset);
Gfx::GetInstance()->SetConstantBuffer(2, m_uniform_stream_buffer.GetCurrentGPUPointer() + 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); geometry_constants_offset);
auto& system = Core::System::GetInstance();
auto& pixel_shader_manager = system.GetPixelShaderManager();
auto& vertex_shader_manager = system.GetVertexShaderManager(); auto& vertex_shader_manager = system.GetVertexShaderManager();
auto& geometry_shader_manager = system.GetGeometryShaderManager(); auto& geometry_shader_manager = system.GetGeometryShaderManager();
@ -253,6 +278,12 @@ void VertexManager::UploadAllConstants()
&vertex_shader_manager.constants, sizeof(VertexShaderConstants)); &vertex_shader_manager.constants, sizeof(VertexShaderConstants));
std::memcpy(m_uniform_stream_buffer.GetCurrentHostPointer() + geometry_constants_offset, std::memcpy(m_uniform_stream_buffer.GetCurrentHostPointer() + geometry_constants_offset,
&geometry_shader_manager.constants, sizeof(GeometryShaderConstants)); &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 // Finally, flush buffer memory after copying
m_uniform_stream_buffer.CommitMemory(allocation_size); m_uniform_stream_buffer.CommitMemory(allocation_size);

View File

@ -339,7 +339,7 @@ bool DXContext::CreateRootSignatures()
bool DXContext::CreateGXRootSignature() bool DXContext::CreateGXRootSignature()
{ {
// GX: // 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 textures (visible in PS).
// - VideoCommon::MAX_PIXEL_SHADER_SAMPLERS samplers (visible in PS). // - VideoCommon::MAX_PIXEL_SHADER_SAMPLERS samplers (visible in PS).
// - 1 UAV (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, SetRootParamTable(&params[param_count], &ranges[param_count], D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 3,
1, D3D12_SHADER_VISIBILITY_VERTEX); 1, D3D12_SHADER_VISIBILITY_VERTEX);
param_count++; param_count++;
SetRootParamConstant(&params[param_count], 3, 1, D3D12_SHADER_VISIBILITY_VERTEX); SetRootParamConstant(&params[param_count], 4, 1, D3D12_SHADER_VISIBILITY_VERTEX);
param_count++; param_count++;
// Since these must be contiguous, pixel lighting goes to bbox if not enabled. // Since these must be contiguous, pixel lighting goes to bbox if not enabled.
@ -383,6 +383,9 @@ bool DXContext::CreateGXRootSignature()
param_count++; 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); return BuildRootSignature(m_device.Get(), &m_gx_root_signature, params.data(), param_count);
} }

View File

@ -30,7 +30,8 @@ enum ROOT_PARAMETER
ROOT_PARAMETER_VS_SRV, ROOT_PARAMETER_VS_SRV,
ROOT_PARAMETER_BASE_VERTEX_CONSTANT, ROOT_PARAMETER_BASE_VERTEX_CONSTANT,
ROOT_PARAMETER_PS_UAV_OR_CBV2, 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 NUM_ROOT_PARAMETERS
}; };
// Compute shader root parameters // Compute shader root parameters

View File

@ -458,7 +458,7 @@ std::optional<std::string> Metal::Util::TranslateShaderToMSL(ShaderStage stage,
static const spirv_cross::MSLResourceBinding resource_bindings[] = { static const spirv_cross::MSLResourceBinding resource_bindings[] = {
MakeResourceBinding(spv::ExecutionModelVertex, 0, 0, 1, 0, 0), // vs/ubo MakeResourceBinding(spv::ExecutionModelVertex, 0, 0, 1, 0, 0), // vs/ubo
MakeResourceBinding(spv::ExecutionModelVertex, 0, 1, 1, 0, 0), // vs/ubo MakeResourceBinding(spv::ExecutionModelVertex, 0, 1, 1, 0, 0), // vs/ubo
MakeResourceBinding(spv::ExecutionModelVertex, 0, 2, 2, 0, 0), // vs/ubo MakeResourceBinding(spv::ExecutionModelVertex, 0, 3, 2, 0, 0), // vs/ubo
MakeResourceBinding(spv::ExecutionModelVertex, 2, 1, 0, 0, 0), // vs/ssbo MakeResourceBinding(spv::ExecutionModelVertex, 2, 1, 0, 0, 0), // vs/ssbo
MakeResourceBinding(spv::ExecutionModelFragment, 0, 0, 0, 0, 0), // vs/ubo MakeResourceBinding(spv::ExecutionModelFragment, 0, 0, 0, 0, 0), // vs/ubo
MakeResourceBinding(spv::ExecutionModelFragment, 0, 1, 1, 0, 0), // vs/ubo MakeResourceBinding(spv::ExecutionModelFragment, 0, 1, 1, 0, 0), // vs/ubo

View File

@ -105,9 +105,9 @@ void SHADER::SetProgramVariables()
if (VSBlock_id != -1) if (VSBlock_id != -1)
glUniformBlockBinding(glprogid, VSBlock_id, 2); glUniformBlockBinding(glprogid, VSBlock_id, 2);
if (GSBlock_id != -1) if (GSBlock_id != -1)
glUniformBlockBinding(glprogid, GSBlock_id, 3); glUniformBlockBinding(glprogid, GSBlock_id, 4);
if (UBERBlock_id != -1) if (UBERBlock_id != -1)
glUniformBlockBinding(glprogid, UBERBlock_id, 4); glUniformBlockBinding(glprogid, UBERBlock_id, 5);
// Bind Texture Samplers // Bind Texture Samplers
for (int a = 0; a < 8; ++a) for (int a = 0; a < 8; ++a)
@ -232,35 +232,54 @@ void ProgramShaderCache::UploadConstants()
auto& pixel_shader_manager = system.GetPixelShaderManager(); auto& pixel_shader_manager = system.GetPixelShaderManager();
auto& vertex_shader_manager = system.GetVertexShaderManager(); auto& vertex_shader_manager = system.GetVertexShaderManager();
auto& geometry_shader_manager = system.GetGeometryShaderManager(); 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, &pixel_shader_manager.constants, sizeof(PixelShaderConstants));
memcpy(buffer.first + Common::AlignUp(sizeof(PixelShaderConstants), s_ubo_align), u64 size = Common::AlignUp(sizeof(PixelShaderConstants), s_ubo_align);
&vertex_shader_manager.constants, sizeof(VertexShaderConstants));
memcpy(buffer.first + Common::AlignUp(sizeof(PixelShaderConstants), s_ubo_align) + memcpy(buffer.first + size, &vertex_shader_manager.constants, sizeof(VertexShaderConstants));
Common::AlignUp(sizeof(VertexShaderConstants), s_ubo_align), size += Common::AlignUp(sizeof(VertexShaderConstants), s_ubo_align);
&geometry_shader_manager.constants, sizeof(GeometryShaderConstants));
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, glBindBufferRange(GL_UNIFORM_BUFFER, 1, s_buffer->m_buffer, buffer.second,
sizeof(PixelShaderConstants)); sizeof(PixelShaderConstants));
glBindBufferRange(GL_UNIFORM_BUFFER, 2, s_buffer->m_buffer, size = Common::AlignUp(sizeof(PixelShaderConstants), s_ubo_align);
buffer.second + Common::AlignUp(sizeof(PixelShaderConstants), s_ubo_align), glBindBufferRange(GL_UNIFORM_BUFFER, 2, s_buffer->m_buffer, buffer.second + size,
sizeof(VertexShaderConstants)); sizeof(VertexShaderConstants));
glBindBufferRange(GL_UNIFORM_BUFFER, 3, s_buffer->m_buffer, size += Common::AlignUp(sizeof(VertexShaderConstants), s_ubo_align);
buffer.second + Common::AlignUp(sizeof(PixelShaderConstants), s_ubo_align) +
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)); sizeof(GeometryShaderConstants));
pixel_shader_manager.dirty = false; pixel_shader_manager.dirty = false;
vertex_shader_manager.dirty = false; vertex_shader_manager.dirty = false;
geometry_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); s_buffer->Unmap(alloc_size);
// bind the same sub-buffer to all stages // 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); glBindBufferRange(GL_UNIFORM_BUFFER, index, s_buffer->m_buffer, buffer.second, data_size);
ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, data_size); ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, data_size);

View File

@ -38,7 +38,7 @@ enum DESCRIPTOR_SET_LAYOUT
// We use four pipeline layouts: // We use four pipeline layouts:
// - Standard // - 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] // - 8 combined image samplers (accessible from PS) [set=1, binding=0-7]
// - 1 SSBO accessible from PS if supported [set=2, binding=0] // - 1 SSBO accessible from PS if supported [set=2, binding=0]
// - Uber // - Uber
@ -70,6 +70,7 @@ enum UNIFORM_BUFFER_DESCRIPTOR_SET_BINDING
{ {
UBO_DESCRIPTOR_SET_BINDING_PS, UBO_DESCRIPTOR_SET_BINDING_PS,
UBO_DESCRIPTOR_SET_BINDING_VS, UBO_DESCRIPTOR_SET_BINDING_VS,
UBO_DESCRIPTOR_SET_BINDING_PS_CUST,
UBO_DESCRIPTOR_SET_BINDING_GS, UBO_DESCRIPTOR_SET_BINDING_GS,
NUM_UBO_DESCRIPTOR_SET_BINDINGS NUM_UBO_DESCRIPTOR_SET_BINDINGS
}; };

View File

@ -110,11 +110,13 @@ bool ObjectCache::CreateDescriptorSetLayouts()
{ {
// The geometry shader buffer must be last in this binding set, as we don't include it // 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. // 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, {UBO_DESCRIPTOR_SET_BINDING_PS, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1,
VK_SHADER_STAGE_FRAGMENT_BIT}, VK_SHADER_STAGE_FRAGMENT_BIT},
{UBO_DESCRIPTOR_SET_BINDING_VS, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, {UBO_DESCRIPTOR_SET_BINDING_VS, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1,
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT}, 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, {UBO_DESCRIPTOR_SET_BINDING_GS, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1,
VK_SHADER_STAGE_GEOMETRY_BIT}, VK_SHADER_STAGE_GEOMETRY_BIT},
}}; }};
@ -170,7 +172,7 @@ bool ObjectCache::CreateDescriptorSetLayouts()
{18, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT}, {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{{ std::array<VkDescriptorSetLayoutCreateInfo, NUM_DESCRIPTOR_SET_LAYOUTS> create_infos{{
{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, nullptr, 0, {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, nullptr, 0,

View File

@ -494,6 +494,12 @@ void StateTracker::UpdateGXDescriptorSet()
continue; 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)
{
continue;
}
writes[num_writes++] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, writes[num_writes++] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
nullptr, nullptr,
m_gx_descriptor_sets[0], m_gx_descriptor_sets[0],

View File

@ -243,22 +243,43 @@ void VertexManager::UpdatePixelShaderConstants()
auto& system = Core::System::GetInstance(); auto& system = Core::System::GetInstance();
auto& pixel_shader_manager = system.GetPixelShaderManager(); auto& pixel_shader_manager = system.GetPixelShaderManager();
if (!pixel_shader_manager.dirty || !ReserveConstantStorage()) if (!ReserveConstantStorage())
return; return;
StateTracker::GetInstance()->SetGXUniformBuffer( if (pixel_shader_manager.dirty)
UBO_DESCRIPTOR_SET_BINDING_PS, m_uniform_stream_buffer->GetBuffer(), {
m_uniform_stream_buffer->GetCurrentOffset(), sizeof(PixelShaderConstants)); StateTracker::GetInstance()->SetGXUniformBuffer(
std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer(), &pixel_shader_manager.constants, UBO_DESCRIPTOR_SET_BINDING_PS, m_uniform_stream_buffer->GetBuffer(),
sizeof(PixelShaderConstants)); m_uniform_stream_buffer->GetCurrentOffset(), sizeof(PixelShaderConstants));
m_uniform_stream_buffer->CommitMemory(sizeof(PixelShaderConstants)); std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer(), &pixel_shader_manager.constants,
ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, sizeof(PixelShaderConstants)); sizeof(PixelShaderConstants));
pixel_shader_manager.dirty = false; 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() 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())) g_vulkan_context->GetUniformBufferAlignment()))
{ {
return true; return true;
@ -276,6 +297,11 @@ bool VertexManager::ReserveConstantStorage()
void VertexManager::UploadAllConstants() 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. // 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 ub_alignment = static_cast<u32>(g_vulkan_context->GetUniformBufferAlignment());
const u32 pixel_constants_offset = 0; const u32 pixel_constants_offset = 0;
@ -283,7 +309,9 @@ void VertexManager::UploadAllConstants()
Common::AlignUp(pixel_constants_offset + sizeof(PixelShaderConstants), ub_alignment); Common::AlignUp(pixel_constants_offset + sizeof(PixelShaderConstants), ub_alignment);
const u32 geometry_constants_offset = const u32 geometry_constants_offset =
Common::AlignUp(vertex_constants_offset + sizeof(VertexShaderConstants), ub_alignment); 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. // Allocate everything at once.
// We should only be here if the buffer was full and a command buffer was submitted anyway. // 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; return;
} }
auto& system = Core::System::GetInstance();
auto& pixel_shader_manager = system.GetPixelShaderManager();
auto& vertex_shader_manager = system.GetVertexShaderManager(); auto& vertex_shader_manager = system.GetVertexShaderManager();
auto& geometry_shader_manager = system.GetGeometryShaderManager(); auto& geometry_shader_manager = system.GetGeometryShaderManager();
@ -307,6 +333,14 @@ void VertexManager::UploadAllConstants()
UBO_DESCRIPTOR_SET_BINDING_VS, m_uniform_stream_buffer->GetBuffer(), UBO_DESCRIPTOR_SET_BINDING_VS, m_uniform_stream_buffer->GetBuffer(),
m_uniform_stream_buffer->GetCurrentOffset() + vertex_constants_offset, m_uniform_stream_buffer->GetCurrentOffset() + vertex_constants_offset,
sizeof(VertexShaderConstants)); 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( StateTracker::GetInstance()->SetGXUniformBuffer(
UBO_DESCRIPTOR_SET_BINDING_GS, m_uniform_stream_buffer->GetBuffer(), UBO_DESCRIPTOR_SET_BINDING_GS, m_uniform_stream_buffer->GetBuffer(),
m_uniform_stream_buffer->GetCurrentOffset() + geometry_constants_offset, m_uniform_stream_buffer->GetCurrentOffset() + geometry_constants_offset,
@ -319,6 +353,12 @@ void VertexManager::UploadAllConstants()
&vertex_shader_manager.constants, sizeof(VertexShaderConstants)); &vertex_shader_manager.constants, sizeof(VertexShaderConstants));
std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer() + geometry_constants_offset, std::memcpy(m_uniform_stream_buffer->GetCurrentHostPointer() + geometry_constants_offset,
&geometry_shader_manager.constants, sizeof(GeometryShaderConstants)); &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 // Finally, flush buffer memory after copying
m_uniform_stream_buffer->CommitMemory(allocation_size); m_uniform_stream_buffer->CommitMemory(allocation_size);

View File

@ -19,7 +19,7 @@ namespace VideoCommon
// As pipelines encompass both shader UIDs and render states, changes to either of these should // As pipelines encompass both shader UIDs and render states, changes to either of these should
// also increment the pipeline UID version. Incrementing the UID version will cause all UID // also increment the pipeline UID version. Incrementing the UID version will cause all UID
// caches to be invalidated. // caches to be invalidated.
constexpr u32 GX_PIPELINE_UID_VERSION = 7; // Last changed in PR 11859 constexpr u32 GX_PIPELINE_UID_VERSION = 8; // Last changed in PR 12185
struct GXPipelineUid struct GXPipelineUid
{ {

View File

@ -93,7 +93,7 @@ ShaderCode GenerateGeometryShaderCode(APIType api_type, const ShaderHostConfig&
// uniforms // uniforms
if (api_type == APIType::OpenGL || api_type == APIType::Vulkan) 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 else
out.Write("cbuffer GSBlock {{\n"); out.Write("cbuffer GSBlock {{\n");

View File

@ -3,6 +3,8 @@
#pragma once #pragma once
#include <span>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "VideoCommon/ConstantManager.h" #include "VideoCommon/ConstantManager.h"
@ -52,6 +54,10 @@ public:
PixelShaderConstants constants{}; PixelShaderConstants constants{};
bool dirty = false; bool dirty = false;
// Constants for custom shaders
std::span<u8> custom_constants;
bool custom_constants_dirty = false;
private: private:
bool m_fog_range_adjusted_changed = false; bool m_fog_range_adjusted_changed = false;
bool m_viewport_changed = false; bool m_viewport_changed = false;

View File

@ -52,7 +52,7 @@ ShaderCode GenVertexShader(APIType api_type, const ShaderHostConfig& host_config
if (vertex_loader) 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("{}", s_geometry_shader_uniforms);
out.Write("}};\n"); 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. // 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 // 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 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" " uint base_vertex;\n"
"}};\n\n" "}};\n\n"
"uint GetVertexBaseOffset(uint vertex_id) {{\n" "uint GetVertexBaseOffset(uint vertex_id) {{\n"

View File

@ -595,6 +595,7 @@ void VertexManagerBase::Flush()
CustomPixelShaderContents custom_pixel_shader_contents; CustomPixelShaderContents custom_pixel_shader_contents;
std::optional<CustomPixelShader> custom_pixel_shader; std::optional<CustomPixelShader> custom_pixel_shader;
std::vector<std::string> custom_pixel_texture_names; std::vector<std::string> custom_pixel_texture_names;
std::span<u8> custom_pixel_shader_uniforms;
for (int i = 0; i < texture_names.size(); i++) for (int i = 0; i < texture_names.size(); i++)
{ {
const std::string& texture_name = texture_names[i]; const std::string& texture_name = texture_names[i];
@ -644,6 +645,12 @@ void VertexManagerBase::Flush()
// Now we can upload uniforms, as nothing else will override them. // Now we can upload uniforms, as nothing else will override them.
geometry_shader_manager.SetConstants(m_current_primitive_type); geometry_shader_manager.SetConstants(m_current_primitive_type);
pixel_shader_manager.SetConstants(); pixel_shader_manager.SetConstants();
if (!custom_pixel_shader_uniforms.empty() &&
pixel_shader_manager.custom_constants.data() != custom_pixel_shader_uniforms.data())
{
pixel_shader_manager.custom_constants_dirty = true;
}
pixel_shader_manager.custom_constants = custom_pixel_shader_uniforms;
UploadUniforms(); UploadUniforms();
// Update the pipeline, or compile one if needed. // Update the pipeline, or compile one if needed.
@ -1052,7 +1059,8 @@ void VertexManagerBase::OnEndFrame()
return; return;
// In order to reduce CPU readback latency, we want to kick a command buffer roughly halfway // In order to reduce CPU readback latency, we want to kick a command buffer roughly halfway
// between the draw counters that invoked the readback, or every 250 draws, whichever is smaller. // between the draw counters that invoked the readback, or every 250 draws, whichever is
// smaller.
if (g_ActiveConfig.iCommandBufferExecuteInterval > 0) if (g_ActiveConfig.iCommandBufferExecuteInterval > 0)
{ {
u32 last_draw_counter = 0; u32 last_draw_counter = 0;

View File

@ -96,14 +96,14 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
if (uid_data->vs_expand != VSExpand::None) 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("{}", s_geometry_shader_uniforms);
out.Write("}};\n"); out.Write("}};\n");
if (api_type == APIType::D3D) if (api_type == APIType::D3D)
{ {
// D3D doesn't include the base vertex in SV_VertexID // 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" " uint base_vertex;\n"
"}};\n\n"); "}};\n\n");
} }