Skip to content

Commit 316aa44

Browse files
committed
vk: Fix crash when shuffling between cyclic and non-cyclic Z-buffer in one logical pass
1 parent e586986 commit 316aa44

File tree

1 file changed

+39
-25
lines changed

1 file changed

+39
-25
lines changed

rpcs3/Emu/RSX/VK/VKDraw.cpp

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -65,38 +65,51 @@ namespace vk
6565
case VK_IMAGE_LAYOUT_GENERAL:
6666
case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT:
6767
ensure(sampler_state->upload_context == rsx::texture_upload_context::framebuffer_storage);
68-
if (!sampler_state->is_cyclic_reference)
68+
if (sampler_state->is_cyclic_reference) [[ unlikely ]]
6969
{
70-
// This was used in a cyclic ref before, but is missing a barrier
71-
// No need for a full stall, use a custom barrier instead
72-
VkPipelineStageFlags src_stage;
73-
VkAccessFlags src_access;
74-
if (raw->aspect() == VK_IMAGE_ASPECT_COLOR_BIT)
75-
{
76-
src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
77-
src_access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
78-
}
79-
else
80-
{
81-
src_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
82-
src_access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
83-
}
84-
85-
vk::insert_image_memory_barrier(
86-
cmd,
87-
raw->value,
88-
raw->current_layout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
89-
src_stage, dst_stage,
90-
src_access, VK_ACCESS_SHADER_READ_BIT,
91-
{ raw->aspect(), 0, 1, 0, 1 });
70+
// Nothing to do
71+
break;
72+
}
9273

93-
raw->current_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
74+
// This was used in a cyclic ref before, but is missing a barrier
75+
// No need for a full stall, use a custom barrier instead
76+
VkPipelineStageFlags src_stage;
77+
VkAccessFlags src_access;
78+
if (raw->aspect() == VK_IMAGE_ASPECT_COLOR_BIT)
79+
{
80+
src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
81+
src_access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
9482
}
83+
else
84+
{
85+
src_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
86+
src_access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
87+
}
88+
89+
vk::insert_image_memory_barrier(
90+
cmd,
91+
raw->value,
92+
raw->current_layout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
93+
src_stage, dst_stage,
94+
src_access, VK_ACCESS_SHADER_READ_BIT,
95+
{ raw->aspect(), 0, 1, 0, 1 });
96+
97+
raw->current_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
9598
break;
9699
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
97100
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
98101
ensure(sampler_state->upload_context == rsx::texture_upload_context::framebuffer_storage);
99-
raw->change_layout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
102+
if (!sampler_state->is_cyclic_reference) [[ likely ]]
103+
{
104+
// Standard pre-read barrier.
105+
raw->change_layout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
106+
break;
107+
}
108+
109+
// Normally this shouldn't happen. But that is only guaranteed if the attachment state never changes outside of RTT rebind interrupts.
110+
// If the shader changes between binds to "disable" the cyclic nature, we could end up here.
111+
// Draw 1 (cyllic) -> texture_barrier -> Draw 2 (no textures) -> attachment_optimal -> Draw 3 (cylic again, no new data) -> incorrect layout.
112+
vk::as_rtt(raw)->texture_barrier(cmd);
100113
break;
101114
}
102115
}
@@ -1051,6 +1064,7 @@ void VKGSRender::end()
10511064
// We actually need to end the subpass as a minimum. Without this, early-Z optimiazations in following draws will clobber reads from previous draws and cause flickering.
10521065
// Since we're ending the subpass, might as well restore DCC/HiZ for extra performance
10531066
ds->change_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
1067+
ds->reset_surface_counters();
10541068
}
10551069
}
10561070

0 commit comments

Comments
 (0)