Skip to content

Commit 7089a21

Browse files
GS:VK: Use vkCmdPipelineBarrier2KHR
Requires VK_KHR_synchronization2 Co-Authored-By: TJnotJT <tjnotjt.github@gmail.com>
1 parent 236f67a commit 7089a21

5 files changed

Lines changed: 216 additions & 276 deletions

File tree

pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp

Lines changed: 71 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ static std::mutex s_instance_mutex;
8181
// Device extensions that are required for PCSX2.
8282
static constexpr const char* s_required_device_extensions[] = {
8383
VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,
84+
VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME,
8485
};
8586

8687
GSDeviceVK::GSDeviceVK()
@@ -1975,21 +1976,32 @@ void GSDeviceVK::SubmitSpinCommand(u32 index, u32 cycles)
19751976
{
19761977
m_spin_buffer_initialized = true;
19771978
vkCmdFillBuffer(resources.command_buffer, m_spin_buffer, 0, VK_WHOLE_SIZE, 0);
1978-
VkBufferMemoryBarrier barrier = {VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER};
1979+
VkBufferMemoryBarrier2 barrier = {VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2};
1980+
barrier.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
1981+
barrier.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
19791982
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
19801983
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
19811984
barrier.srcQueueFamilyIndex = m_spin_queue_family_index;
19821985
barrier.dstQueueFamilyIndex = m_spin_queue_family_index;
19831986
barrier.buffer = m_spin_buffer;
19841987
barrier.offset = 0;
19851988
barrier.size = VK_WHOLE_SIZE;
1986-
vkCmdPipelineBarrier(resources.command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1987-
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
1989+
VkDependencyInfo dependency = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
1990+
dependency.bufferMemoryBarrierCount = 1;
1991+
dependency.pBufferMemoryBarriers = &barrier;
1992+
vkCmdPipelineBarrier2KHR(resources.command_buffer, &dependency);
19881993
}
19891994

19901995
if (m_spin_queue_is_graphics_queue)
1991-
vkCmdPipelineBarrier(resources.command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
1992-
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 0, nullptr);
1996+
{
1997+
VkMemoryBarrier2 barrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER_2};
1998+
barrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
1999+
barrier.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
2000+
VkDependencyInfo dependency = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
2001+
dependency.memoryBarrierCount = 1;
2002+
dependency.pMemoryBarriers = &barrier;
2003+
vkCmdPipelineBarrier2KHR(resources.command_buffer, &dependency);
2004+
}
19932005

19942006
const u32 timestamp_base = (index + NUM_COMMAND_BUFFERS) * 2;
19952007
vkCmdResetQueryPool(resources.command_buffer, m_timestamp_query_pool, timestamp_base, 2);
@@ -3028,9 +3040,9 @@ void GSDeviceVK::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
30283040
sTexVK->SetUseFenceCounter(GetCurrentFenceCounter());
30293041
dTexVK->SetUseFenceCounter(GetCurrentFenceCounter());
30303042
sTexVK->TransitionToLayout(
3031-
(dTexVK == sTexVK) ? GSTextureVK::Layout::TransferSelf : GSTextureVK::Layout::TransferSrc);
3043+
(dTexVK == sTexVK) ? GSTextureVK::Layout::CopySelf : GSTextureVK::Layout::CopySrc);
30323044
dTexVK->TransitionToLayout(
3033-
(dTexVK == sTexVK) ? GSTextureVK::Layout::TransferSelf : GSTextureVK::Layout::TransferDst);
3045+
(dTexVK == sTexVK) ? GSTextureVK::Layout::CopySelf : GSTextureVK::Layout::CopyDst);
30343046

30353047
vkCmdCopyImage(GetCurrentCommandBuffer(), sTexVK->GetImage(), sTexVK->GetVkLayout(), dTexVK->GetImage(),
30363048
dTexVK->GetVkLayout(), 1, &ic);
@@ -3298,8 +3310,8 @@ void GSDeviceVK::BlitRect(GSTexture* sTex, const GSVector4i& sRect, u32 sLevel,
32983310

32993311
EndRenderPass();
33003312

3301-
sTexVK->TransitionToLayout(GSTextureVK::Layout::TransferSrc);
3302-
dTexVK->TransitionToLayout(GSTextureVK::Layout::TransferDst);
3313+
sTexVK->TransitionToLayout(GSTextureVK::Layout::BlitSrc);
3314+
dTexVK->TransitionToLayout(GSTextureVK::Layout::BlitDst);
33033315

33043316
// ensure we don't leave this bound later on
33053317
if (m_tfx_textures[0] == sTexVK)
@@ -4734,7 +4746,7 @@ void GSDeviceVK::RenderBlankFrame()
47344746

47354747
VkCommandBuffer cmdbuffer = GetCurrentCommandBuffer();
47364748
GSTextureVK* sctex = m_swap_chain->GetCurrentTexture();
4737-
sctex->TransitionToLayout(cmdbuffer, GSTextureVK::Layout::TransferDst);
4749+
sctex->TransitionToLayout(cmdbuffer, GSTextureVK::Layout::ClearDst);
47384750

47394751
constexpr VkImageSubresourceRange srr = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
47404752
vkCmdClearColorImage(
@@ -6523,27 +6535,9 @@ void GSDeviceVK::UploadHWDrawVerticesAndIndices(GSHWDrawConfig& config)
65236535
}
65246536
}
65256537

6526-
VkImageMemoryBarrier GSDeviceVK::GetColorBufferFeedbackBarrier(GSTextureVK* rt) const
6527-
{
6528-
const VkImageLayout layout =
6529-
UseFeedbackLoopLayout() ? VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT : VK_IMAGE_LAYOUT_GENERAL;
6530-
const VkAccessFlags dst_access =
6531-
UseFeedbackLoopLayout() ? VK_ACCESS_SHADER_READ_BIT : VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
6532-
return {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, nullptr,
6533-
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, dst_access, layout, layout,
6534-
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, rt->GetImage(), {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}};
6535-
}
6536-
6537-
VkImageMemoryBarrier GSDeviceVK::GetDepthStencilBufferFeedbackBarrier(GSTextureVK* ds) const
6538+
VkImageLayout GSDeviceVK::GetFeedbackLoopLayout() const
65386539
{
6539-
const VkImageLayout layout =
6540-
UseFeedbackLoopLayout() ? VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT : VK_IMAGE_LAYOUT_GENERAL;
6541-
const VkAccessFlags dst_access =
6542-
UseFeedbackLoopLayout() ? VK_ACCESS_SHADER_READ_BIT : VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
6543-
return {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, nullptr,
6544-
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, dst_access, layout, layout,
6545-
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, ds->GetImage(),
6546-
{VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u}};
6540+
return UseFeedbackLoopLayout() ? VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT : VK_IMAGE_LAYOUT_GENERAL;
65476541
}
65486542

65496543
VkDependencyFlags GSDeviceVK::GetFeedbackBarrierDependencyFlags() const
@@ -6552,6 +6546,50 @@ VkDependencyFlags GSDeviceVK::GetFeedbackBarrierDependencyFlags() const
65526546
VK_DEPENDENCY_BY_REGION_BIT;
65536547
}
65546548

6549+
VkAccessFlagBits2 GSDeviceVK::GetFeedbackLoopInputAccessBits() const
6550+
{
6551+
return UseFeedbackLoopLayout() ? VK_ACCESS_2_SHADER_READ_BIT : VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT;
6552+
}
6553+
6554+
void GSDeviceVK::FeedbackBarrier(GSTextureVK* rt, GSTextureVK* ds)
6555+
{
6556+
VkImageMemoryBarrier2 barrier_template = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2};
6557+
barrier_template.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
6558+
barrier_template.dstAccessMask = GetFeedbackLoopInputAccessBits();
6559+
barrier_template.oldLayout = GetFeedbackLoopLayout();
6560+
barrier_template.newLayout = GetFeedbackLoopLayout();
6561+
barrier_template.subresourceRange.levelCount = 1;
6562+
barrier_template.subresourceRange.layerCount = 1;
6563+
6564+
std::array<VkImageMemoryBarrier2, 2> barriers;
6565+
u32 num_barriers = 0;
6566+
6567+
if (rt)
6568+
{
6569+
VkImageMemoryBarrier2& barrier = barriers[num_barriers++] = barrier_template;
6570+
barrier.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
6571+
barrier.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
6572+
barrier.image = rt->GetImage();
6573+
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
6574+
}
6575+
6576+
if (ds)
6577+
{
6578+
VkImageMemoryBarrier2& barrier = barriers[num_barriers++] = barrier_template;
6579+
barrier.srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
6580+
barrier.srcAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
6581+
barrier.image = ds->GetImage();
6582+
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; // We don't do stencil feedback, so depth only
6583+
}
6584+
6585+
VkDependencyInfo dependency = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
6586+
dependency.dependencyFlags = GetFeedbackBarrierDependencyFlags();
6587+
dependency.imageMemoryBarrierCount = num_barriers;
6588+
dependency.pImageMemoryBarriers = barriers.data();
6589+
6590+
vkCmdPipelineBarrier2KHR(GetCurrentCommandBuffer(), &dependency);
6591+
}
6592+
65556593
void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt, GSTextureVK* draw_ds,
65566594
bool one_barrier, bool full_barrier)
65576595
{
@@ -6565,38 +6603,7 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
65656603
if ((one_barrier || full_barrier) && !(config.IsFeedbackLoopRT(m_pipeline_selector.ps) || config.IsFeedbackLoopDepth(m_pipeline_selector.ps))) [[unlikely]]
65666604
Console.Warning("VK: Possible unnecessary barrier detected.");
65676605
#endif
6568-
VkDependencyFlags barrier_flags = GetFeedbackBarrierDependencyFlags();
6569-
6570-
std::array<VkImageMemoryBarrier, 2> barriers;
6571-
u32 n_barriers = 0;
6572-
if (full_barrier || one_barrier)
6573-
{
6574-
if (draw_rt)
6575-
{
6576-
barriers[0] = GetColorBufferFeedbackBarrier(draw_rt);
6577-
n_barriers++;
6578-
}
6579-
if (draw_ds)
6580-
{
6581-
barriers[1] = GetDepthStencilBufferFeedbackBarrier(draw_ds);
6582-
n_barriers++;
6583-
}
6584-
}
6585-
6586-
const auto IssueBarriers = [&]() {
6587-
if (draw_rt)
6588-
{
6589-
vkCmdPipelineBarrier(GetCurrentCommandBuffer(),
6590-
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
6591-
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier_flags, 0, nullptr, 0, nullptr, 1, &barriers[0]);
6592-
}
6593-
if (draw_ds)
6594-
{
6595-
vkCmdPipelineBarrier(GetCurrentCommandBuffer(),
6596-
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
6597-
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier_flags, 0, nullptr, 0, nullptr, 1, &barriers[1]);
6598-
}
6599-
};
6606+
const int n_barriers = (draw_rt ? 1 : 0) + (draw_ds ? 1 : 0);
66006607

66016608
if (full_barrier)
66026609
{
@@ -6610,7 +6617,7 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
66106617

66116618
for (u32 n = 0, p = 0; n < draw_list_size; n++)
66126619
{
6613-
IssueBarriers();
6620+
FeedbackBarrier(draw_rt, draw_ds);
66146621

66156622
const u32 count = config.drawlist->at(n) * indices_per_prim;
66166623
Draw(config, p, count);
@@ -6623,7 +6630,7 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
66236630
if (one_barrier)
66246631
{
66256632
g_perfmon.Put(GSPerfMon::Barriers, n_barriers);
6626-
IssueBarriers();
6633+
FeedbackBarrier(draw_rt, draw_ds);
66276634
}
66286635

66296636
Draw(config);

pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -641,9 +641,10 @@ class GSDeviceVK final : public GSDevice
641641
void RenderHW(GSHWDrawConfig& config) override;
642642
void UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelector& pipe);
643643
void UploadHWDrawVerticesAndIndices(GSHWDrawConfig& config);
644-
VkImageMemoryBarrier GetColorBufferFeedbackBarrier(GSTextureVK* rt) const;
645-
VkImageMemoryBarrier GetDepthStencilBufferFeedbackBarrier(GSTextureVK* ds) const;
644+
VkImageLayout GetFeedbackLoopLayout() const;
646645
VkDependencyFlags GetFeedbackBarrierDependencyFlags() const;
646+
VkAccessFlagBits2 GetFeedbackLoopInputAccessBits() const;
647+
void FeedbackBarrier(GSTextureVK* rt, GSTextureVK* ds);
647648
void SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt, GSTextureVK* draw_ds,
648649
bool one_barrier, bool full_barrier);
649650

0 commit comments

Comments
 (0)