GS:Vk: Use vkCmdPipelineBarrier2KHR

Co-Authored-By: TJnotJT <[email protected]>
This commit is contained in:
TellowKrinkle
2026-10-06 23:35:15 +02:00
committed by lightningterror
co-authored by TJnotJT
parent 4463fe4e7b
commit cf8633fe50
5 changed files with 304 additions and 279 deletions
+156 -74
View File
@@ -52,6 +52,67 @@ enum : u32
static u32 s_debug_scope_depth = 0;
#endif
namespace ReplaceVK
{
static VkPipelineStageFlags TranslateStageFlags(VkPipelineStageFlags2 flags2)
{
VkPipelineStageFlags flags = static_cast<VkPipelineStageFlags>(flags2);
static constexpr VkPipelineStageFlags2 transfer = VK_PIPELINE_STAGE_2_COPY_BIT | VK_PIPELINE_STAGE_2_RESOLVE_BIT | VK_PIPELINE_STAGE_2_BLIT_BIT | VK_PIPELINE_STAGE_2_CLEAR_BIT;
if (flags2 & transfer)
flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
assert(!(flags2 & ~transfer & ~static_cast<VkPipelineStageFlags2>(VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM)));
return flags;
}
static VkAccessFlags TranslateAccessFlags(VkAccessFlags2 flags2)
{
VkAccessFlags flags = static_cast<VkAccessFlags>(flags2);
assert(!(flags2 & ~static_cast<VkAccessFlags2>(VK_ACCESS_FLAG_BITS_MAX_ENUM)));
return flags;
}
static void VKAPI_CALL CmdPipelineBarrier2(VkCommandBuffer commandBuffer, const VkDependencyInfo* RESTRICT pDependencyInfo)
{
assert(!pDependencyInfo->pNext);
VkDependencyFlags dependencyFlags = pDependencyInfo->dependencyFlags;
for (const VkMemoryBarrier2& barrier2 : std::span(pDependencyInfo->pMemoryBarriers, pDependencyInfo->memoryBarrierCount))
{
VkMemoryBarrier barrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER};
barrier.srcAccessMask = TranslateAccessFlags(barrier2.srcAccessMask);
barrier.dstAccessMask = TranslateAccessFlags(barrier2.dstAccessMask);
vkCmdPipelineBarrier(commandBuffer, TranslateStageFlags(barrier2.srcStageMask), TranslateStageFlags(barrier2.dstStageMask),
dependencyFlags, 1, &barrier, 0, nullptr, 0, nullptr);
}
for (const VkBufferMemoryBarrier2& barrier2 : std::span(pDependencyInfo->pBufferMemoryBarriers, pDependencyInfo->bufferMemoryBarrierCount))
{
VkBufferMemoryBarrier barrier = {VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER};
barrier.srcAccessMask = TranslateAccessFlags(barrier2.srcAccessMask);
barrier.dstAccessMask = TranslateAccessFlags(barrier2.dstAccessMask);
barrier.srcQueueFamilyIndex = barrier2.srcQueueFamilyIndex;
barrier.dstQueueFamilyIndex = barrier2.dstQueueFamilyIndex;
barrier.buffer = barrier2.buffer;
barrier.offset = barrier2.offset;
barrier.size = barrier2.size;
vkCmdPipelineBarrier(commandBuffer, TranslateStageFlags(barrier2.srcStageMask), TranslateStageFlags(barrier2.dstStageMask),
dependencyFlags, 0, nullptr, 1, &barrier, 0, nullptr);
}
for (const VkImageMemoryBarrier2& barrier2 : std::span(pDependencyInfo->pImageMemoryBarriers, pDependencyInfo->imageMemoryBarrierCount))
{
VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
barrier.srcAccessMask = TranslateAccessFlags(barrier2.srcAccessMask);
barrier.dstAccessMask = TranslateAccessFlags(barrier2.dstAccessMask);
barrier.oldLayout = barrier2.oldLayout;
barrier.newLayout = barrier2.newLayout;
barrier.srcQueueFamilyIndex = barrier2.srcQueueFamilyIndex;
barrier.dstQueueFamilyIndex = barrier2.dstQueueFamilyIndex;
barrier.image = barrier2.image;
barrier.subresourceRange = barrier2.subresourceRange;
vkCmdPipelineBarrier(commandBuffer, TranslateStageFlags(barrier2.srcStageMask), TranslateStageFlags(barrier2.dstStageMask),
dependencyFlags, 0, nullptr, 0, nullptr, 1, &barrier);
}
}
} // namespace ReplaceVK
static bool IsDATEModePrimIDInit(u32 flag)
{
return flag == 1 || flag == 2;
@@ -423,6 +484,7 @@ bool GSDeviceVK::SelectDeviceExtensions(ExtensionList* extension_list, bool enab
m_optional_extensions.vk_khr_driver_properties = SupportsExtension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, false);
m_optional_extensions.vk_ext_calibrated_timestamps =
SupportsExtension(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, false);
m_optional_extensions.vk_khr_synchronization2 = SupportsExtension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, false);
if (m_optional_extensions.vk_swapchain_maintenance1)
{
@@ -619,6 +681,8 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
device_info.ppEnabledLayerNames = layer_names;
}
VkPhysicalDeviceSynchronization2Features sync2_features = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES};
// provoking vertex
VkPhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT};
@@ -634,6 +698,11 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT fragment_shader_interlock_ext_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT};
if (m_optional_extensions.vk_khr_synchronization2)
{
sync2_features.synchronization2 = VK_TRUE;
Vulkan::AddPointerToChain(&device_info, &sync2_features);
}
if (m_optional_extensions.vk_ext_provoking_vertex)
{
provoking_vertex_feature.provokingVertexLast = VK_TRUE;
@@ -703,6 +772,12 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
if (!ProcessDeviceExtensions())
return false;
// Add replacements for unsupported functions
if (!m_optional_extensions.vk_khr_synchronization2)
{
vkCmdPipelineBarrier2KHR = ReplaceVK::CmdPipelineBarrier2;
}
if (m_spinning_supported)
{
vkGetDeviceQueue(m_device, m_spin_queue_family_index, spin_queue_index, &m_spin_queue);
@@ -726,6 +801,8 @@ bool GSDeviceVK::ProcessDeviceExtensions()
{
// advanced feature checks
VkPhysicalDeviceFeatures2 features2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
VkPhysicalDeviceSynchronization2Features sync2_features = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES};
VkPhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex_features = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT};
VkPhysicalDeviceLineRasterizationFeaturesEXT line_rasterization_feature = {
@@ -741,6 +818,8 @@ bool GSDeviceVK::ProcessDeviceExtensions()
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT };
// add in optional feature structs
if (m_optional_extensions.vk_khr_synchronization2)
Vulkan::AddPointerToChain(&features2, &sync2_features);
if (m_optional_extensions.vk_ext_provoking_vertex)
Vulkan::AddPointerToChain(&features2, &provoking_vertex_features);
if (m_optional_extensions.vk_ext_line_rasterization)
@@ -758,6 +837,7 @@ bool GSDeviceVK::ProcessDeviceExtensions()
vkGetPhysicalDeviceFeatures2(m_physical_device, &features2);
// confirm we actually support it
m_optional_extensions.vk_khr_synchronization2 &= (sync2_features.synchronization2 == VK_TRUE);
m_optional_extensions.vk_ext_provoking_vertex &= (provoking_vertex_features.provokingVertexLast == VK_TRUE);
m_optional_extensions.vk_ext_rasterization_order_attachment_access &=
(rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess == VK_TRUE);
@@ -838,6 +918,8 @@ bool GSDeviceVK::ProcessDeviceExtensions()
m_optional_extensions.vk_swapchain_maintenance1 ? "supported" : "NOT supported");
Console.WriteLn("VK_EXT_full_screen_exclusive is %s",
m_optional_extensions.vk_ext_full_screen_exclusive ? "supported" : "NOT supported");
Console.WriteLn("VK_KHR_synchronization2 is %s",
m_optional_extensions.vk_khr_synchronization2 ? "supported" : "NOT supported");
Console.WriteLn(
"VK_EXT_provoking_vertex is %s", m_optional_extensions.vk_ext_provoking_vertex ? "supported" : "NOT supported");
Console.WriteLn("VK_EXT_line_rasterization is %s",
@@ -1667,11 +1749,8 @@ VkRenderPass GSDeviceVK::CreateCachedRenderPass(RenderPassCacheKey key)
subpass_dependency[num_subpass_dependencies].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
subpass_dependency[num_subpass_dependencies].srcAccessMask =
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
subpass_dependency[num_subpass_dependencies].dstAccessMask =
UseFeedbackLoopLayout() ? VK_ACCESS_SHADER_READ_BIT : VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
subpass_dependency[num_subpass_dependencies].dependencyFlags =
UseFeedbackLoopLayout() ? (VK_DEPENDENCY_BY_REGION_BIT | VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT) :
VK_DEPENDENCY_BY_REGION_BIT;
subpass_dependency[num_subpass_dependencies].dstAccessMask = static_cast<VkAccessFlags>(GetFeedbackLoopInputAccessFlags());
subpass_dependency[num_subpass_dependencies].dependencyFlags = GetFeedbackBarrierDependencyFlags();
num_subpass_dependencies++;
}
}
@@ -1713,11 +1792,8 @@ VkRenderPass GSDeviceVK::CreateCachedRenderPass(RenderPassCacheKey key)
subpass_dependency[num_subpass_dependencies].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
subpass_dependency[num_subpass_dependencies].srcAccessMask =
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
subpass_dependency[num_subpass_dependencies].dstAccessMask =
UseFeedbackLoopLayout() ? VK_ACCESS_SHADER_READ_BIT : VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
subpass_dependency[num_subpass_dependencies].dependencyFlags =
UseFeedbackLoopLayout() ? (VK_DEPENDENCY_BY_REGION_BIT | VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT) :
VK_DEPENDENCY_BY_REGION_BIT;
subpass_dependency[num_subpass_dependencies].dstAccessMask = static_cast<VkAccessFlags>(GetFeedbackLoopInputAccessFlags());
subpass_dependency[num_subpass_dependencies].dependencyFlags = GetFeedbackBarrierDependencyFlags();
num_subpass_dependencies++;
}
}
@@ -1999,7 +2075,9 @@ void GSDeviceVK::SubmitSpinCommand(u32 index, u32 cycles)
{
m_spin_buffer_initialized = true;
vkCmdFillBuffer(resources.command_buffer, m_spin_buffer, 0, VK_WHOLE_SIZE, 0);
VkBufferMemoryBarrier barrier = {VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER};
VkBufferMemoryBarrier2 barrier = {VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2};
barrier.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
barrier.srcQueueFamilyIndex = m_spin_queue_family_index;
@@ -2007,13 +2085,22 @@ void GSDeviceVK::SubmitSpinCommand(u32 index, u32 cycles)
barrier.buffer = m_spin_buffer;
barrier.offset = 0;
barrier.size = VK_WHOLE_SIZE;
vkCmdPipelineBarrier(resources.command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
VkDependencyInfo dependency = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
dependency.bufferMemoryBarrierCount = 1;
dependency.pBufferMemoryBarriers = &barrier;
vkCmdPipelineBarrier2KHR(resources.command_buffer, &dependency);
}
if (m_spin_queue_is_graphics_queue)
vkCmdPipelineBarrier(resources.command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 0, nullptr);
{
VkMemoryBarrier2 barrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER_2};
barrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
VkDependencyInfo dependency = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
dependency.memoryBarrierCount = 1;
dependency.pMemoryBarriers = &barrier;
vkCmdPipelineBarrier2KHR(resources.command_buffer, &dependency);
}
const u32 timestamp_base = (index + NUM_COMMAND_BUFFERS) * 2;
vkCmdResetQueryPool(resources.command_buffer, m_timestamp_query_pool, timestamp_base, 2);
@@ -3052,9 +3139,9 @@ void GSDeviceVK::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
sTexVK->SetUseFenceCounter(GetCurrentFenceCounter());
dTexVK->SetUseFenceCounter(GetCurrentFenceCounter());
sTexVK->TransitionToLayout(
(dTexVK == sTexVK) ? GSTextureVK::Layout::TransferSelf : GSTextureVK::Layout::TransferSrc);
(dTexVK == sTexVK) ? GSTextureVK::Layout::CopySelf : GSTextureVK::Layout::CopySrc);
dTexVK->TransitionToLayout(
(dTexVK == sTexVK) ? GSTextureVK::Layout::TransferSelf : GSTextureVK::Layout::TransferDst);
(dTexVK == sTexVK) ? GSTextureVK::Layout::CopySelf : GSTextureVK::Layout::CopyDst);
vkCmdCopyImage(GetCurrentCommandBuffer(), sTexVK->GetImage(), sTexVK->GetVkLayout(), dTexVK->GetImage(),
dTexVK->GetVkLayout(), 1, &ic);
@@ -3322,8 +3409,8 @@ void GSDeviceVK::BlitRect(GSTexture* sTex, const GSVector4i& sRect, u32 sLevel,
EndRenderPass();
sTexVK->TransitionToLayout(GSTextureVK::Layout::TransferSrc);
dTexVK->TransitionToLayout(GSTextureVK::Layout::TransferDst);
sTexVK->TransitionToLayout(GSTextureVK::Layout::BlitSrc);
dTexVK->TransitionToLayout(GSTextureVK::Layout::BlitDst);
// ensure we don't leave this bound later on
if (m_tfx_textures[0] == sTexVK)
@@ -4768,7 +4855,7 @@ void GSDeviceVK::RenderBlankFrame()
VkCommandBuffer cmdbuffer = GetCurrentCommandBuffer();
GSTextureVK* sctex = m_swap_chain->GetCurrentTexture();
sctex->TransitionToLayout(cmdbuffer, GSTextureVK::Layout::TransferDst);
sctex->TransitionToLayout(cmdbuffer, GSTextureVK::Layout::ClearDst);
constexpr VkImageSubresourceRange srr = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
vkCmdClearColorImage(
@@ -6543,27 +6630,9 @@ void GSDeviceVK::UploadHWDrawVerticesAndIndices(GSHWDrawConfig& config)
}
}
VkImageMemoryBarrier GSDeviceVK::GetColorBufferFeedbackBarrier(GSTextureVK* rt) const
VkImageLayout GSDeviceVK::GetFeedbackLoopLayout() const
{
const VkImageLayout layout =
UseFeedbackLoopLayout() ? VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT : VK_IMAGE_LAYOUT_GENERAL;
const VkAccessFlags dst_access =
UseFeedbackLoopLayout() ? VK_ACCESS_SHADER_READ_BIT : VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
return {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, nullptr,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, dst_access, layout, layout,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, rt->GetImage(), {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}};
}
VkImageMemoryBarrier GSDeviceVK::GetDepthStencilBufferFeedbackBarrier(GSTextureVK* ds) const
{
const VkImageLayout layout =
UseFeedbackLoopLayout() ? VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT : VK_IMAGE_LAYOUT_GENERAL;
const VkAccessFlags dst_access =
UseFeedbackLoopLayout() ? VK_ACCESS_SHADER_READ_BIT : VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
return {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, nullptr,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, dst_access, layout, layout,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, ds->GetImage(),
{VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u}};
return UseFeedbackLoopLayout() ? VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT : VK_IMAGE_LAYOUT_GENERAL;
}
VkDependencyFlags GSDeviceVK::GetFeedbackBarrierDependencyFlags() const
@@ -6572,6 +6641,50 @@ VkDependencyFlags GSDeviceVK::GetFeedbackBarrierDependencyFlags() const
VK_DEPENDENCY_BY_REGION_BIT;
}
VkAccessFlags2 GSDeviceVK::GetFeedbackLoopInputAccessFlags() const
{
return UseFeedbackLoopLayout() ? VK_ACCESS_2_SHADER_READ_BIT : VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT;
}
void GSDeviceVK::FeedbackBarrier(GSTextureVK* rt, GSTextureVK* ds)
{
VkImageMemoryBarrier2 barrier_template = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2};
barrier_template.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
barrier_template.dstAccessMask = GetFeedbackLoopInputAccessFlags();
barrier_template.oldLayout = GetFeedbackLoopLayout();
barrier_template.newLayout = GetFeedbackLoopLayout();
barrier_template.subresourceRange.levelCount = 1;
barrier_template.subresourceRange.layerCount = 1;
std::array<VkImageMemoryBarrier2, 2> barriers;
u32 num_barriers = 0;
if (rt)
{
VkImageMemoryBarrier2& barrier = barriers[num_barriers++] = barrier_template;
barrier.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
barrier.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
barrier.image = rt->GetImage();
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
if (ds)
{
VkImageMemoryBarrier2& barrier = barriers[num_barriers++] = barrier_template;
barrier.srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
barrier.srcAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
barrier.image = ds->GetImage();
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
}
VkDependencyInfo dependency = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
dependency.dependencyFlags = GetFeedbackBarrierDependencyFlags();
dependency.imageMemoryBarrierCount = num_barriers;
dependency.pImageMemoryBarriers = barriers.data();
vkCmdPipelineBarrier2KHR(GetCurrentCommandBuffer(), &dependency);
}
void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt, GSTextureVK* draw_ds,
bool one_barrier, bool full_barrier)
{
@@ -6585,38 +6698,7 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
if ((one_barrier || full_barrier) && !(config.IsFeedbackLoopRT(m_pipeline_selector.ps) || config.IsFeedbackLoopDepth(m_pipeline_selector.ps))) [[unlikely]]
Console.Warning("VK: Possible unnecessary barrier detected.");
#endif
VkDependencyFlags barrier_flags = GetFeedbackBarrierDependencyFlags();
std::array<VkImageMemoryBarrier, 2> barriers;
u32 n_barriers = 0;
if (full_barrier || one_barrier)
{
if (draw_rt)
{
barriers[0] = GetColorBufferFeedbackBarrier(draw_rt);
n_barriers++;
}
if (draw_ds)
{
barriers[1] = GetDepthStencilBufferFeedbackBarrier(draw_ds);
n_barriers++;
}
}
const auto IssueBarriers = [&]() {
if (draw_rt)
{
vkCmdPipelineBarrier(GetCurrentCommandBuffer(),
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier_flags, 0, nullptr, 0, nullptr, 1, &barriers[0]);
}
if (draw_ds)
{
vkCmdPipelineBarrier(GetCurrentCommandBuffer(),
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier_flags, 0, nullptr, 0, nullptr, 1, &barriers[1]);
}
};
const int n_barriers = (draw_rt ? 1 : 0) + (draw_ds ? 1 : 0);
if (full_barrier)
{
@@ -6630,7 +6712,7 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
for (u32 n = 0, p = 0; n < draw_list_size; n++)
{
IssueBarriers();
FeedbackBarrier(draw_rt, draw_ds);
const u32 count = config.drawlist->at(n) * indices_per_prim;
Draw(config, p, count);
@@ -6643,7 +6725,7 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
if (one_barrier)
{
g_perfmon.Put(GSPerfMon::Barriers, n_barriers);
IssueBarriers();
FeedbackBarrier(draw_rt, draw_ds);
}
Draw(config);
+4 -2
View File
@@ -45,6 +45,7 @@ public:
bool vk_swapchain_maintenance1_is_khr : 1;
bool vk_khr_driver_properties : 1;
bool vk_khr_shader_non_semantic_info : 1;
bool vk_khr_synchronization2 : 1;
bool vk_ext_attachment_feedback_loop_layout : 1;
bool vk_ext_fragment_shader_interlock : 1;
};
@@ -640,9 +641,10 @@ public:
void RenderHW(GSHWDrawConfig& config) override;
void UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelector& pipe);
void UploadHWDrawVerticesAndIndices(GSHWDrawConfig& config);
VkImageMemoryBarrier GetColorBufferFeedbackBarrier(GSTextureVK* rt) const;
VkImageMemoryBarrier GetDepthStencilBufferFeedbackBarrier(GSTextureVK* ds) const;
VkImageLayout GetFeedbackLoopLayout() const;
VkDependencyFlags GetFeedbackBarrierDependencyFlags() const;
VkAccessFlags2 GetFeedbackLoopInputAccessFlags() const;
void FeedbackBarrier(GSTextureVK* rt, GSTextureVK* ds);
void SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt, GSTextureVK* draw_ds,
bool one_barrier, bool full_barrier);
+137 -200
View File
@@ -34,31 +34,105 @@ static constexpr const VkComponentMapping s_identity_swizzle{VK_COMPONENT_SWIZZL
static VkImageLayout GetVkImageLayout(GSTextureVK::Layout layout)
{
static constexpr std::array<VkImageLayout, static_cast<u32>(GSTextureVK::Layout::Count)> s_vk_layout_mapping = {{
static constexpr VkImageLayout s_vk_layout_mapping[] = {
VK_IMAGE_LAYOUT_UNDEFINED, // Undefined
VK_IMAGE_LAYOUT_PREINITIALIZED, // Preinitialized
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // ColorAttachment
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // DepthStencilAttachment
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // ShaderReadOnly
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // ClearDst
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // TransferSrc
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // TransferDst
VK_IMAGE_LAYOUT_GENERAL, // TransferSelf
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // CopySrc
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // CopyDst
VK_IMAGE_LAYOUT_GENERAL, // CopySelf
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // BlitSrc
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // BlitDst
VK_IMAGE_LAYOUT_GENERAL, // BlitSelf
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // PresentSrc
VK_IMAGE_LAYOUT_GENERAL, // FeedbackLoop
VK_IMAGE_LAYOUT_GENERAL, // ReadWriteImage
VK_IMAGE_LAYOUT_GENERAL, // ComputeReadWriteImage
VK_IMAGE_LAYOUT_GENERAL, // General
}};
return (layout == GSTextureVK::Layout::FeedbackLoop && GSDeviceVK::GetInstance()->UseFeedbackLoopLayout()) ?
VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT :
s_vk_layout_mapping[static_cast<u32>(layout)];
};
static_assert(std::size(s_vk_layout_mapping) == static_cast<u32>(GSTextureVK::Layout::Count));
if (layout == GSTextureVK::Layout::FeedbackLoop)
return GSDeviceVK::GetInstance()->GetFeedbackLoopLayout();
else
return s_vk_layout_mapping[static_cast<u32>(layout)];
}
static VkAccessFlagBits GetFeedbackLoopInputAccessBits()
static VkPipelineStageFlags2 GetPipelineStageFlags(GSTextureVK::Layout layout, bool color)
{
return GSDeviceVK::GetInstance()->UseFeedbackLoopLayout() ? VK_ACCESS_SHADER_READ_BIT :
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
static constexpr VkPipelineStageFlags2 s_vk_stage_mapping[] = {
VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, // Undefined
VK_PIPELINE_STAGE_2_HOST_BIT, // Preinitialized
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, // ColorAttachment
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, // DepthStencilAttachment
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, // ShaderReadOnly
VK_PIPELINE_STAGE_2_CLEAR_BIT, // ClearDst
VK_PIPELINE_STAGE_2_COPY_BIT, // CopySrc
VK_PIPELINE_STAGE_2_COPY_BIT, // CopyDst
VK_PIPELINE_STAGE_2_COPY_BIT, // CopySelf
VK_PIPELINE_STAGE_2_BLIT_BIT, // BlitSrc
VK_PIPELINE_STAGE_2_BLIT_BIT, // BlitDst
VK_PIPELINE_STAGE_2_BLIT_BIT, // BlitSelf
VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, // PresentSrc
VK_PIPELINE_STAGE_2_NONE, // FeedbackLoop (overridden)
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, // ReadWriteImage
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, // ComputeReadWriteImage
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, // General
};
static_assert(std::size(s_vk_stage_mapping) == static_cast<u32>(GSTextureVK::Layout::Count));
if (layout == GSTextureVK::Layout::FeedbackLoop)
{
VkPipelineStageFlags2 flags = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
if (color)
flags |= VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
else
flags |= VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
return flags;
}
else
{
return s_vk_stage_mapping[static_cast<u32>(layout)];
}
}
static VkAccessFlags2 GetAccessFlags(GSTextureVK::Layout layout, bool color)
{
static constexpr VkPipelineStageFlags2 s_vk_access_mapping[] = {
VK_ACCESS_2_NONE, // Undefined
VK_ACCESS_2_HOST_WRITE_BIT, // Preinitialized
VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, // ColorAttachment
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // DepthStencilAttachment
VK_ACCESS_2_SHADER_READ_BIT, // ShaderReadOnly
VK_ACCESS_2_TRANSFER_WRITE_BIT, // ClearDst
VK_ACCESS_2_TRANSFER_READ_BIT, // CopySrc
VK_ACCESS_2_TRANSFER_WRITE_BIT, // CopyDst
VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT, // CopySelf
VK_ACCESS_2_TRANSFER_READ_BIT, // BlitSrc
VK_ACCESS_2_TRANSFER_WRITE_BIT, // BlitDst
VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT, // BlitSelf
VK_ACCESS_2_NONE, // PresentSrc
VK_ACCESS_2_NONE, // FeedbackLoop (overridden)
VK_ACCESS_2_SHADER_STORAGE_READ_BIT | VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, // ReadWriteImage
VK_ACCESS_2_SHADER_STORAGE_READ_BIT | VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, // ComputeReadWriteImage
VK_ACCESS_2_NONE, // General
};
static_assert(std::size(s_vk_access_mapping) == static_cast<u32>(GSTextureVK::Layout::Count));
if (layout == GSTextureVK::Layout::FeedbackLoop)
{
VkAccessFlags2 flags;
if (color)
flags = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
else
flags = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
return flags | GSDeviceVK::GetInstance()->GetFeedbackLoopInputAccessFlags();
}
else
{
return s_vk_access_mapping[static_cast<u32>(layout)];
}
}
GSTextureVK::GSTextureVK(Usage usage, Format format, int width, int height, int levels, VkImage image,
@@ -315,9 +389,9 @@ void GSTextureVK::UpdateFromBuffer(VkCommandBuffer cmdbuf, int level, u32 x, u32
{
const Layout old_layout = m_layout;
if (old_layout == Layout::Undefined)
TransitionToLayout(cmdbuf, Layout::TransferDst);
else if (old_layout != Layout::TransferDst)
TransitionSubresourcesToLayout(cmdbuf, level, 1, old_layout, Layout::TransferDst);
TransitionToLayout(cmdbuf, Layout::CopyDst);
else if (old_layout != Layout::CopyDst)
TransitionSubresourcesToLayout(cmdbuf, level, 1, old_layout, Layout::CopyDst);
const VkBufferImageCopy bic = {static_cast<VkDeviceSize>(buffer_offset), row_length, buffer_height,
{VK_IMAGE_ASPECT_COLOR_BIT, static_cast<u32>(level), 0u, 1u}, {static_cast<s32>(x), static_cast<s32>(y), 0},
@@ -325,8 +399,8 @@ void GSTextureVK::UpdateFromBuffer(VkCommandBuffer cmdbuf, int level, u32 x, u32
vkCmdCopyBufferToImage(cmdbuf, buffer, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bic);
if (old_layout != Layout::TransferDst && old_layout != Layout::Undefined)
TransitionSubresourcesToLayout(cmdbuf, level, 1, Layout::TransferDst, old_layout);
if (old_layout != Layout::CopyDst && old_layout != Layout::Undefined)
TransitionSubresourcesToLayout(cmdbuf, level, 1, Layout::CopyDst, old_layout);
}
bool GSTextureVK::Update(const GSVector4i& r, const void* data, int pitch, int layer)
@@ -387,7 +461,7 @@ bool GSTextureVK::Update(const GSVector4i& r, const void* data, int pitch, int l
// first time the texture is used? don't leave it undefined
if (m_layout == Layout::Undefined)
TransitionToLayout(cmdbuf, Layout::TransferDst);
TransitionToLayout(cmdbuf, Layout::CopyDst);
// if we're an rt and have been cleared, and the full rect isn't being uploaded, do the clear
if (IsRenderTarget())
@@ -469,7 +543,7 @@ void GSTextureVK::Unmap()
// first time the texture is used? don't leave it undefined
if (m_layout == Layout::Undefined)
TransitionToLayout(cmdbuf, Layout::TransferDst);
TransitionToLayout(cmdbuf, Layout::CopyDst);
// if we're an rt and have been cleared, and the full rect isn't being uploaded, do the clear
if (IsRenderTarget())
@@ -494,7 +568,7 @@ void GSTextureVK::GenerateMipmap()
const VkCommandBuffer cmdbuf = GetCommandBufferForUpdate();
if (m_layout == Layout::Undefined)
TransitionToLayout(cmdbuf, Layout::TransferSrc);
TransitionToLayout(cmdbuf, Layout::BlitSrc);
for (int dst_level = 1; dst_level < m_mipmap_levels; dst_level++)
{
@@ -504,8 +578,8 @@ void GSTextureVK::GenerateMipmap()
const int dst_width = std::max<int>(m_size.x >> dst_level, 1);
const int dst_height = std::max<int>(m_size.y >> dst_level, 1);
TransitionSubresourcesToLayout(cmdbuf, src_level, 1, m_layout, Layout::TransferSrc);
TransitionSubresourcesToLayout(cmdbuf, dst_level, 1, m_layout, Layout::TransferDst);
TransitionSubresourcesToLayout(cmdbuf, src_level, 1, m_layout, Layout::BlitSrc);
TransitionSubresourcesToLayout(cmdbuf, dst_level, 1, m_layout, Layout::BlitDst);
const VkImageBlit blit = {
{VK_IMAGE_ASPECT_COLOR_BIT, static_cast<u32>(src_level), 0u, 1u}, // srcSubresource
@@ -517,8 +591,8 @@ void GSTextureVK::GenerateMipmap()
vkCmdBlitImage(cmdbuf, m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR);
TransitionSubresourcesToLayout(cmdbuf, src_level, 1, Layout::TransferSrc, m_layout);
TransitionSubresourcesToLayout(cmdbuf, dst_level, 1, Layout::TransferDst, m_layout);
TransitionSubresourcesToLayout(cmdbuf, src_level, 1, Layout::BlitSrc, m_layout);
TransitionSubresourcesToLayout(cmdbuf, dst_level, 1, Layout::BlitDst, m_layout);
}
}
@@ -620,168 +694,29 @@ void GSTextureVK::TransitionSubresourcesToLayout(
aspect = VK_IMAGE_ASPECT_COLOR_BIT;
}
VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, nullptr, 0, 0, GetVkImageLayout(old_layout),
GetVkImageLayout(new_layout), VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, m_image,
{aspect, static_cast<u32>(start_level), static_cast<u32>(num_levels), 0u, 1u}};
// These layouts should only be used on one side of the barrier
pxAssert(old_layout != Layout::PresentSrc);
pxAssert(new_layout != Layout::Undefined);
pxAssert(new_layout != Layout::Preinitialized);
// srcStageMask -> Stages that must complete before the barrier
// dstStageMask -> Stages that must wait for after the barrier before beginning
VkPipelineStageFlags srcStageMask, dstStageMask;
switch (old_layout)
{
case Layout::Undefined:
// Layout undefined therefore contents undefined, and we don't care what happens to it.
barrier.srcAccessMask = 0;
srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
break;
VkImageMemoryBarrier2 barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2};
barrier.srcStageMask = GetPipelineStageFlags(old_layout, !IsDepthStencil());
barrier.dstStageMask = GetPipelineStageFlags(new_layout, !IsDepthStencil());
barrier.srcAccessMask = GetAccessFlags(old_layout, !IsDepthStencil());
barrier.dstAccessMask = GetAccessFlags(new_layout, !IsDepthStencil());
barrier.oldLayout = GetVkImageLayout(old_layout);
barrier.newLayout = GetVkImageLayout(new_layout);
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = m_image;
barrier.subresourceRange = {aspect, static_cast<u32>(start_level), static_cast<u32>(num_levels), 0u, 1u};
case Layout::Preinitialized:
// Image has been pre-initialized by the host, so ensure all writes have completed.
barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_HOST_BIT;
break;
VkDependencyInfo dependency = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
dependency.dependencyFlags = GSDeviceVK::GetInstance()->GetFeedbackBarrierDependencyFlags();
dependency.imageMemoryBarrierCount = 1;
dependency.pImageMemoryBarriers = &barrier;
case Layout::ColorAttachment:
// Image was being used as a color attachment, so ensure all writes have completed.
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
break;
case Layout::DepthStencilAttachment:
// Image was being used as a depthstencil attachment, so ensure all writes have completed.
barrier.srcAccessMask =
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
break;
case Layout::ShaderReadOnly:
// Image was being used as a shader resource, make sure all reads have finished.
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case Layout::ClearDst:
// Image was being used as a clear destination, ensure all writes have finished.
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case Layout::TransferSrc:
// Image was being used as a copy source, ensure all reads have finished.
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case Layout::TransferDst:
// Image was being used as a copy destination, ensure all writes have finished.
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case Layout::TransferSelf:
// Image was being used as a copy source and destination, ensure all reads and writes have finished.
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case Layout::FeedbackLoop:
barrier.srcAccessMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT)
? (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | GetFeedbackLoopInputAccessBits())
: (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | GetFeedbackLoopInputAccessBits());
srcStageMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT)
? (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
: (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
break;
case Layout::ReadWriteImage:
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case Layout::ComputeReadWriteImage:
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
break;
case Layout::General:
default:
srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
break;
}
switch (new_layout)
{
case Layout::Undefined:
barrier.dstAccessMask = 0;
dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
break;
case Layout::ColorAttachment:
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
break;
case Layout::DepthStencilAttachment:
barrier.dstAccessMask =
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
break;
case Layout::ShaderReadOnly:
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case Layout::ClearDst:
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case Layout::TransferSrc:
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case Layout::TransferDst:
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case Layout::TransferSelf:
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case Layout::PresentSrc:
srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
break;
case Layout::FeedbackLoop:
barrier.dstAccessMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT)
? (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | GetFeedbackLoopInputAccessBits())
: (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | GetFeedbackLoopInputAccessBits());
dstStageMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT)
? (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
: (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
break;
case Layout::ReadWriteImage:
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case Layout::ComputeReadWriteImage:
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
break;
case Layout::General:
default:
dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
break;
}
vkCmdPipelineBarrier(command_buffer, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1, &barrier);
vkCmdPipelineBarrier2KHR(command_buffer, &dependency);
// Count as a UAV barrier if we transition to/from UAV.
if (IsRenderTargetOrDepthStencil() &&
@@ -902,9 +837,9 @@ void GSDownloadTextureVK::CopyFromTexture(
GSTextureVK::Layout old_layout = vkTex->GetLayout();
if (old_layout == GSTextureVK::Layout::Undefined)
vkTex->TransitionToLayout(cmdbuf, GSTextureVK::Layout::TransferSrc);
else if (old_layout != GSTextureVK::Layout::TransferSrc)
vkTex->TransitionSubresourcesToLayout(cmdbuf, src_level, 1, old_layout, GSTextureVK::Layout::TransferSrc);
vkTex->TransitionToLayout(cmdbuf, GSTextureVK::Layout::CopySrc);
else if (old_layout != GSTextureVK::Layout::CopySrc)
vkTex->TransitionSubresourcesToLayout(cmdbuf, src_level, 1, old_layout, GSTextureVK::Layout::CopySrc);
VkBufferImageCopy image_copy = {};
const VkImageAspectFlags aspect = vkTex->IsDepthStencil() ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
@@ -919,22 +854,24 @@ void GSDownloadTextureVK::CopyFromTexture(
vkCmdCopyImageToBuffer(cmdbuf, vkTex->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_buffer, 1, &image_copy);
// flush gpu cache
const VkBufferMemoryBarrier buffer_info = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType
nullptr, // const void* pNext
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask
VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
m_buffer, // VkBuffer buffer
0, // VkDeviceSize offset
copy_size // VkDeviceSize size
};
vkCmdPipelineBarrier(
cmdbuf, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 1, &buffer_info, 0, nullptr);
VkBufferMemoryBarrier2 buffer_info = {VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2};
buffer_info.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT;
buffer_info.dstStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
buffer_info.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
buffer_info.dstAccessMask = VK_ACCESS_2_HOST_READ_BIT;
buffer_info.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
buffer_info.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
buffer_info.buffer = m_buffer;
buffer_info.size = copy_size;
if (old_layout != GSTextureVK::Layout::TransferSrc && old_layout != GSTextureVK::Layout::Undefined)
vkTex->TransitionSubresourcesToLayout(cmdbuf, src_level, 1, GSTextureVK::Layout::TransferSrc, old_layout);
VkDependencyInfo barrier_info = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
barrier_info.bufferMemoryBarrierCount = 1;
barrier_info.pBufferMemoryBarriers = &buffer_info;
vkCmdPipelineBarrier2KHR(cmdbuf, &barrier_info);
if (old_layout != GSTextureVK::Layout::CopySrc && old_layout != GSTextureVK::Layout::Undefined)
vkTex->TransitionSubresourcesToLayout(cmdbuf, src_level, 1, GSTextureVK::Layout::CopySrc, old_layout);
m_copy_fence_counter = GSDeviceVK::GetInstance()->GetCurrentFenceCounter();
m_needs_cache_invalidate = true;
+6 -3
View File
@@ -20,9 +20,12 @@ public:
DepthStencilAttachment,
ShaderReadOnly,
ClearDst,
TransferSrc,
TransferDst,
TransferSelf,
CopySrc,
CopyDst,
CopySelf,
BlitSrc,
BlitDst,
BlitSelf,
PresentSrc,
FeedbackLoop,
ReadWriteImage,
@@ -201,6 +201,7 @@ VULKAN_DEVICE_ENTRY_POINT(vkCmdSetEvent, true)
VULKAN_DEVICE_ENTRY_POINT(vkCmdResetEvent, true)
VULKAN_DEVICE_ENTRY_POINT(vkCmdWaitEvents, true)
VULKAN_DEVICE_ENTRY_POINT(vkCmdPipelineBarrier, true)
VULKAN_DEVICE_ENTRY_POINT(vkCmdPipelineBarrier2KHR, false)
VULKAN_DEVICE_ENTRY_POINT(vkCmdBeginQuery, true)
VULKAN_DEVICE_ENTRY_POINT(vkCmdEndQuery, true)
VULKAN_DEVICE_ENTRY_POINT(vkCmdResetQueryPool, true)