VideoBackends / VideoCommon: add new uniform buffer object for custom shader materials (slot 3, geometry shader buffer moves to slot 4 if available)
This commit is contained in:
parent
92accc3ef7
commit
b6d321bfb1
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 = {};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(¶ms[param_count], &ranges[param_count], D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 3,
|
||||
1, D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
param_count++;
|
||||
SetRootParamConstant(¶ms[param_count], 3, 1, D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
SetRootParamConstant(¶ms[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(¶ms[param_count], 2, D3D12_SHADER_VISIBILITY_PIXEL);
|
||||
param_count++;
|
||||
|
||||
return BuildRootSignature(m_device.Get(), &m_gx_root_signature, params.data(), param_count);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue