mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-12-16 04:09:39 +00:00
Merge pull request #14025 from TellowKrinkle/RenderPassHazards
VideoBackends:Vulkan: Prevent hazards when restarting render passes
This commit is contained in:
commit
5f5cfda5ad
@ -288,6 +288,7 @@ void StateTracker::BeginRenderPass()
|
|||||||
|
|
||||||
m_current_render_pass = m_framebuffer->GetLoadRenderPass();
|
m_current_render_pass = m_framebuffer->GetLoadRenderPass();
|
||||||
m_framebuffer_render_area = m_framebuffer->GetRect();
|
m_framebuffer_render_area = m_framebuffer->GetRect();
|
||||||
|
m_framebuffer->PrepareForRenderPass();
|
||||||
|
|
||||||
VkRenderPassBeginInfo begin_info = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
VkRenderPassBeginInfo begin_info = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
nullptr,
|
nullptr,
|
||||||
@ -337,6 +338,7 @@ void StateTracker::BeginClearRenderPass(const VkRect2D& area, const VkClearValue
|
|||||||
|
|
||||||
m_current_render_pass = m_framebuffer->GetClearRenderPass();
|
m_current_render_pass = m_framebuffer->GetClearRenderPass();
|
||||||
m_framebuffer_render_area = area;
|
m_framebuffer_render_area = area;
|
||||||
|
m_framebuffer->PrepareForRenderPass();
|
||||||
|
|
||||||
VkRenderPassBeginInfo begin_info = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
VkRenderPassBeginInfo begin_info = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
nullptr,
|
nullptr,
|
||||||
|
|||||||
@ -466,6 +466,8 @@ void VKTexture::TransitionToLayout(VkCommandBuffer command_buffer, VkImageLayout
|
|||||||
if (m_layout == new_layout)
|
if (m_layout == new_layout)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_written_since_last_layout_change = false;
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier = {
|
VkImageMemoryBarrier barrier = {
|
||||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
|
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
|
||||||
nullptr, // const void* pNext
|
nullptr, // const void* pNext
|
||||||
@ -613,6 +615,8 @@ void VKTexture::TransitionToLayout(VkCommandBuffer command_buffer,
|
|||||||
if (m_compute_layout == new_layout)
|
if (m_compute_layout == new_layout)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_written_since_last_layout_change = false;
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier = {
|
VkImageMemoryBarrier barrier = {
|
||||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
|
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
|
||||||
nullptr, // const void* pNext
|
nullptr, // const void* pNext
|
||||||
@ -709,6 +713,49 @@ void VKTexture::TransitionToLayout(VkCommandBuffer command_buffer,
|
|||||||
&barrier);
|
&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,
|
VKStagingTexture::VKStagingTexture(PrivateTag, StagingTextureType type, const TextureConfig& config,
|
||||||
std::unique_ptr<StagingBuffer> buffer, VkImage linear_image,
|
std::unique_ptr<StagingBuffer> buffer, VkImage linear_image,
|
||||||
VmaAllocation linear_image_alloc)
|
VmaAllocation linear_image_alloc)
|
||||||
@ -1117,27 +1164,36 @@ void VKFramebuffer::Unbind()
|
|||||||
|
|
||||||
void VKFramebuffer::TransitionForRender()
|
void VKFramebuffer::TransitionForRender()
|
||||||
{
|
{
|
||||||
|
VkCommandBuffer cb = g_command_buffer_mgr->GetCurrentCommandBuffer();
|
||||||
if (m_color_attachment)
|
if (m_color_attachment)
|
||||||
{
|
{
|
||||||
static_cast<VKTexture*>(m_color_attachment)
|
static_cast<VKTexture*>(m_color_attachment)
|
||||||
->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
->TransitionToLayout(cb, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
|
||||||
}
|
}
|
||||||
for (auto* attachment : m_additional_color_attachments)
|
for (auto* attachment : m_additional_color_attachments)
|
||||||
{
|
{
|
||||||
static_cast<VKTexture*>(attachment)
|
static_cast<VKTexture*>(attachment)
|
||||||
->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
->TransitionToLayout(cb, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_depth_attachment)
|
if (m_depth_attachment)
|
||||||
{
|
{
|
||||||
static_cast<VKTexture*>(m_depth_attachment)
|
static_cast<VKTexture*>(m_depth_attachment)
|
||||||
->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
->TransitionToLayout(cb, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||||
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,
|
void VKFramebuffer::SetAndClear(const VkRect2D& rect, const VkClearValue& color_value,
|
||||||
const VkClearValue& depth_value)
|
const VkClearValue& depth_value)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -69,6 +69,7 @@ public:
|
|||||||
|
|
||||||
void TransitionToLayout(VkCommandBuffer command_buffer, VkImageLayout new_layout) const;
|
void TransitionToLayout(VkCommandBuffer command_buffer, VkImageLayout new_layout) const;
|
||||||
void TransitionToLayout(VkCommandBuffer command_buffer, ComputeImageLayout new_layout) const;
|
void TransitionToLayout(VkCommandBuffer command_buffer, ComputeImageLayout new_layout) const;
|
||||||
|
void PrepareForRenderPass(VkCommandBuffer command_buffer) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CreateView(VkImageViewType type);
|
bool CreateView(VkImageViewType type);
|
||||||
@ -78,6 +79,7 @@ private:
|
|||||||
VkImageView m_view = VK_NULL_HANDLE;
|
VkImageView m_view = VK_NULL_HANDLE;
|
||||||
mutable VkImageLayout m_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
mutable VkImageLayout m_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
mutable ComputeImageLayout m_compute_layout = ComputeImageLayout::Undefined;
|
mutable ComputeImageLayout m_compute_layout = ComputeImageLayout::Undefined;
|
||||||
|
mutable bool m_written_since_last_layout_change = false;
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -141,6 +143,7 @@ public:
|
|||||||
|
|
||||||
void Unbind();
|
void Unbind();
|
||||||
void TransitionForRender();
|
void TransitionForRender();
|
||||||
|
void PrepareForRenderPass();
|
||||||
|
|
||||||
void SetAndClear(const VkRect2D& rect, const VkClearValue& color_value,
|
void SetAndClear(const VkRect2D& rect, const VkClearValue& color_value,
|
||||||
const VkClearValue& depth_value);
|
const VkClearValue& depth_value);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user