summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/Vulkan/VKTexture.cpp
diff options
context:
space:
mode:
authorTellowKrinkle <tellowkrinkle@gmail.com>2025-10-18 05:15:04 -0500
committerTellowKrinkle <tellowkrinkle@gmail.com>2025-10-18 05:24:37 -0500
commite599ae37c31b0beb1594b3e664faa0a50db91690 (patch)
treebd47db449706e2e23864f6af06070fac50351445 /Source/Core/VideoBackends/Vulkan/VKTexture.cpp
parent7b994d965432687e194c87b347e584ddda08bfae (diff)
VideoBackends:Vulkan: Prevent hazards when restarting render passes
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan/VKTexture.cpp')
-rw-r--r--Source/Core/VideoBackends/Vulkan/VKTexture.cpp68
1 files changed, 62 insertions, 6 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp
index edccc9da14..ee6a1b77b3 100644
--- a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp
@@ -466,6 +466,8 @@ void VKTexture::TransitionToLayout(VkCommandBuffer command_buffer, VkImageLayout
if (m_layout == new_layout)
return;
+ m_written_since_last_layout_change = false;
+
VkImageMemoryBarrier barrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
nullptr, // const void* pNext
@@ -613,6 +615,8 @@ void VKTexture::TransitionToLayout(VkCommandBuffer command_buffer,
if (m_compute_layout == new_layout)
return;
+ m_written_since_last_layout_change = false;
+
VkImageMemoryBarrier barrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
nullptr, // const void* pNext
@@ -709,6 +713,49 @@ void VKTexture::TransitionToLayout(VkCommandBuffer command_buffer,
&barrier);
}
+void VKTexture::PrepareForRenderPass(VkCommandBuffer command_buffer) const
+{
+ // Should only be used on images that are already in the layout for being rendered to
+ ASSERT(m_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ||
+ m_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ if (m_written_since_last_layout_change)
+ {
+ // If the image has already been written, we need a barrier to prevent WaW or RaW hazards.
+ VkPipelineStageFlags srcStage = 0;
+ VkPipelineStageFlags dstStage = 0;
+ VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
+ barrier.image = m_image;
+ barrier.oldLayout = m_layout;
+ barrier.newLayout = m_layout;
+ barrier.subresourceRange.aspectMask = GetImageAspectForFormat(GetFormat());
+ barrier.subresourceRange.layerCount = GetLayers();
+ barrier.subresourceRange.levelCount = GetLevels();
+ if (barrier.subresourceRange.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
+ {
+ barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | //
+ VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
+ srcStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ }
+ else
+ {
+ barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
+ srcStage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ dstStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
+ }
+ vkCmdPipelineBarrier(command_buffer, srcStage, dstStage, 0, //
+ 0, nullptr, 0, nullptr, 1, &barrier);
+ }
+ else
+ {
+ // Otherwise, it's about to be written right now.
+ m_written_since_last_layout_change = true;
+ }
+}
+
VKStagingTexture::VKStagingTexture(PrivateTag, StagingTextureType type, const TextureConfig& config,
std::unique_ptr<StagingBuffer> buffer, VkImage linear_image,
VmaAllocation linear_image_alloc)
@@ -1117,27 +1164,36 @@ void VKFramebuffer::Unbind()
void VKFramebuffer::TransitionForRender()
{
+ VkCommandBuffer cb = g_command_buffer_mgr->GetCurrentCommandBuffer();
if (m_color_attachment)
{
static_cast<VKTexture*>(m_color_attachment)
- ->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ ->TransitionToLayout(cb, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
}
for (auto* attachment : m_additional_color_attachments)
{
static_cast<VKTexture*>(attachment)
- ->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ ->TransitionToLayout(cb, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
}
if (m_depth_attachment)
{
static_cast<VKTexture*>(m_depth_attachment)
- ->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
- VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ ->TransitionToLayout(cb, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
}
+void VKFramebuffer::PrepareForRenderPass()
+{
+ VkCommandBuffer cb = g_command_buffer_mgr->GetCurrentCommandBuffer();
+ if (m_color_attachment)
+ static_cast<VKTexture*>(m_color_attachment)->PrepareForRenderPass(cb);
+ if (m_depth_attachment)
+ static_cast<VKTexture*>(m_depth_attachment)->PrepareForRenderPass(cb);
+ for (auto* attachment : m_additional_color_attachments)
+ static_cast<VKTexture*>(attachment)->PrepareForRenderPass(cb);
+}
+
void VKFramebuffer::SetAndClear(const VkRect2D& rect, const VkClearValue& color_value,
const VkClearValue& depth_value)
{