Vulkan: Fix case where uniforms could be overwritten
If a draw caused a command buffer submission, the current uniform storage should not be used for the new command buffer.
This commit is contained in:
parent
4c11735bd5
commit
3adeacb78d
|
@ -467,26 +467,21 @@ void StateTracker::UpdatePixelShaderConstants()
|
||||||
void StateTracker::UploadAllConstants()
|
void StateTracker::UploadAllConstants()
|
||||||
{
|
{
|
||||||
// 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.
|
||||||
|
size_t ub_alignment = g_vulkan_context->GetUniformBufferAlignment();
|
||||||
size_t pixel_constants_offset = 0;
|
size_t pixel_constants_offset = 0;
|
||||||
size_t vertex_constants_offset =
|
size_t vertex_constants_offset =
|
||||||
Util::AlignValue(pixel_constants_offset + sizeof(PixelShaderConstants),
|
Util::AlignValue(pixel_constants_offset + sizeof(PixelShaderConstants), ub_alignment);
|
||||||
g_vulkan_context->GetUniformBufferAlignment());
|
|
||||||
size_t geometry_constants_offset =
|
size_t geometry_constants_offset =
|
||||||
Util::AlignValue(vertex_constants_offset + sizeof(VertexShaderConstants),
|
Util::AlignValue(vertex_constants_offset + sizeof(VertexShaderConstants), ub_alignment);
|
||||||
g_vulkan_context->GetUniformBufferAlignment());
|
size_t allocation_size = geometry_constants_offset + sizeof(GeometryShaderConstants);
|
||||||
size_t total_allocation_size = geometry_constants_offset + sizeof(GeometryShaderConstants);
|
|
||||||
|
|
||||||
// Allocate everything at once.
|
// Allocate everything at once.
|
||||||
if (!m_uniform_stream_buffer->ReserveMemory(
|
if (!m_uniform_stream_buffer->ReserveMemory(allocation_size, ub_alignment, true, true, false))
|
||||||
total_allocation_size, g_vulkan_context->GetUniformBufferAlignment(), true, true, false))
|
|
||||||
{
|
{
|
||||||
// If this fails, wait until the GPU has caught up.
|
|
||||||
// The only places that call constant updates are safe to have state restored.
|
// The only places that call constant updates are safe to have state restored.
|
||||||
WARN_LOG(VIDEO, "Executing command list while waiting for space in uniform buffer");
|
WARN_LOG(VIDEO, "Executing command buffer while waiting for space in uniform buffer");
|
||||||
Util::ExecuteCurrentCommandsAndRestoreState(false);
|
Util::ExecuteCurrentCommandsAndRestoreState(false);
|
||||||
if (!m_uniform_stream_buffer->ReserveMemory(total_allocation_size,
|
if (!m_uniform_stream_buffer->ReserveMemory(allocation_size, ub_alignment, true, true, false))
|
||||||
g_vulkan_context->GetUniformBufferAlignment(), true,
|
|
||||||
true, false))
|
|
||||||
{
|
{
|
||||||
PanicAlert("Failed to allocate space for constants in streaming buffer");
|
PanicAlert("Failed to allocate space for constants in streaming buffer");
|
||||||
return;
|
return;
|
||||||
|
@ -528,7 +523,7 @@ void StateTracker::UploadAllConstants()
|
||||||
&GeometryShaderManager::constants, sizeof(GeometryShaderConstants));
|
&GeometryShaderManager::constants, sizeof(GeometryShaderConstants));
|
||||||
|
|
||||||
// Finally, flush buffer memory after copying
|
// Finally, flush buffer memory after copying
|
||||||
m_uniform_stream_buffer->CommitMemory(total_allocation_size);
|
m_uniform_stream_buffer->CommitMemory(allocation_size);
|
||||||
|
|
||||||
// Clear dirty flags
|
// Clear dirty flags
|
||||||
VertexShaderManager::dirty = false;
|
VertexShaderManager::dirty = false;
|
||||||
|
@ -616,6 +611,13 @@ void StateTracker::InvalidateDescriptorSets()
|
||||||
m_dirty_flags &= ~DIRTY_FLAG_PS_SSBO;
|
m_dirty_flags &= ~DIRTY_FLAG_PS_SSBO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StateTracker::InvalidateConstants()
|
||||||
|
{
|
||||||
|
VertexShaderManager::dirty = true;
|
||||||
|
GeometryShaderManager::dirty = true;
|
||||||
|
PixelShaderManager::dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
void StateTracker::SetPendingRebind()
|
void StateTracker::SetPendingRebind()
|
||||||
{
|
{
|
||||||
m_dirty_flags |= DIRTY_FLAG_DYNAMIC_OFFSETS | DIRTY_FLAG_DESCRIPTOR_SET_BINDING |
|
m_dirty_flags |= DIRTY_FLAG_DYNAMIC_OFFSETS | DIRTY_FLAG_DESCRIPTOR_SET_BINDING |
|
||||||
|
|
|
@ -76,6 +76,9 @@ public:
|
||||||
// now be in a different pool for the new command buffer.
|
// now be in a different pool for the new command buffer.
|
||||||
void InvalidateDescriptorSets();
|
void InvalidateDescriptorSets();
|
||||||
|
|
||||||
|
// Same with the uniforms, as the current storage will belong to the previous command buffer.
|
||||||
|
void InvalidateConstants();
|
||||||
|
|
||||||
// Set dirty flags on everything to force re-bind at next draw time.
|
// Set dirty flags on everything to force re-bind at next draw time.
|
||||||
void SetPendingRebind();
|
void SetPendingRebind();
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,7 @@ void ExecuteCurrentCommandsAndRestoreState(bool execute_off_thread, bool wait_fo
|
||||||
StateTracker::GetInstance()->EndRenderPass();
|
StateTracker::GetInstance()->EndRenderPass();
|
||||||
g_command_buffer_mgr->ExecuteCommandBuffer(execute_off_thread, wait_for_completion);
|
g_command_buffer_mgr->ExecuteCommandBuffer(execute_off_thread, wait_for_completion);
|
||||||
StateTracker::GetInstance()->InvalidateDescriptorSets();
|
StateTracker::GetInstance()->InvalidateDescriptorSets();
|
||||||
|
StateTracker::GetInstance()->InvalidateConstants();
|
||||||
StateTracker::GetInstance()->SetPendingRebind();
|
StateTracker::GetInstance()->SetPendingRebind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue