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:
commit
2677fd9a8e
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 = {};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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(¶ms[param_count], &ranges[param_count], D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 3,
|
SetRootParamTable(¶ms[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(¶ms[param_count], 3, 1, D3D12_SHADER_VISIBILITY_VERTEX);
|
SetRootParamConstant(¶ms[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(¶ms[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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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],
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue