diff --git a/src/util/vulkan_device.cpp b/src/util/vulkan_device.cpp index 68c345ecd..739fe80da 100644 --- a/src/util/vulkan_device.cpp +++ b/src/util/vulkan_device.cpp @@ -2678,22 +2678,45 @@ void VulkanDevice::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u void VulkanDevice::ClearRenderTarget(GPUTexture* t, u32 c) { GPUDevice::ClearRenderTarget(t, c); - if (InRenderPass() && IsRenderTargetBound(t)) - EndRenderPass(); + if (InRenderPass()) + { + const s32 idx = IsRenderTargetBoundIndex(t); + if (idx >= 0) + { + // Use an attachment clear so the render pass isn't restarted. + const VkClearAttachment ca = {VK_IMAGE_ASPECT_COLOR_BIT, + static_cast(idx), + {.color = static_cast(t)->GetClearColorValue()}}; + const VkClearRect rc = {{{0, 0}, {t->GetWidth(), t->GetHeight()}}, 0u, 1u}; + vkCmdClearAttachments(m_current_command_buffer, 1, &ca, 1, &rc); + t->SetState(GPUTexture::State::Dirty); + } + } } void VulkanDevice::ClearDepth(GPUTexture* t, float d) { GPUDevice::ClearDepth(t, d); if (InRenderPass() && m_current_depth_target == t) - EndRenderPass(); + { + // Use an attachment clear so the render pass isn't restarted. + const VkClearAttachment ca = { + VK_IMAGE_ASPECT_DEPTH_BIT, 0, {.depthStencil = static_cast(t)->GetClearDepthValue()}}; + const VkClearRect rc = {{{0, 0}, {t->GetWidth(), t->GetHeight()}}, 0u, 1u}; + vkCmdClearAttachments(m_current_command_buffer, 1, &ca, 1, &rc); + t->SetState(GPUTexture::State::Dirty); + } } void VulkanDevice::InvalidateRenderTarget(GPUTexture* t) { GPUDevice::InvalidateRenderTarget(t); - if (InRenderPass() && (t->IsRenderTarget() ? IsRenderTargetBound(t) : (m_current_depth_target == t))) - EndRenderPass(); + if (InRenderPass() && (t->IsRenderTarget() ? (IsRenderTargetBoundIndex(t) >= 0) : (m_current_depth_target == t))) + { + // Invalidate includes leaving whatever's in the current buffer. + GL_INS_FMT("Invalidating current {}", t->IsRenderTarget() ? "RT" : "DS"); + t->SetState(GPUTexture::State::Dirty); + } } bool VulkanDevice::CreateBuffers() @@ -3462,15 +3485,15 @@ void VulkanDevice::InvalidateCachedState() m_current_pipeline = nullptr; } -bool VulkanDevice::IsRenderTargetBound(const GPUTexture* tex) const +s32 VulkanDevice::IsRenderTargetBoundIndex(const GPUTexture* tex) const { for (u32 i = 0; i < m_num_current_render_targets; i++) { if (m_current_render_targets[i] == tex) - return true; + return static_cast(i); } - return false; + return -1; } VkPipelineLayout VulkanDevice::GetCurrentVkPipelineLayout() const diff --git a/src/util/vulkan_device.h b/src/util/vulkan_device.h index 308b6497b..94f7f732e 100644 --- a/src/util/vulkan_device.h +++ b/src/util/vulkan_device.h @@ -348,7 +348,7 @@ private: /// Set dirty flags on everything to force re-bind at next draw time. void InvalidateCachedState(); - bool IsRenderTargetBound(const GPUTexture* tex) const; + s32 IsRenderTargetBoundIndex(const GPUTexture* tex) const; /// Applies any changed state. VkPipelineLayout GetCurrentVkPipelineLayout() const; diff --git a/src/util/vulkan_texture.cpp b/src/util/vulkan_texture.cpp index 621774514..d9aa6f6f1 100644 --- a/src/util/vulkan_texture.cpp +++ b/src/util/vulkan_texture.cpp @@ -212,6 +212,18 @@ VkImageLayout VulkanTexture::GetVkLayout() const return GetVkImageLayout(m_layout); } +VkClearColorValue VulkanTexture::GetClearColorValue() const +{ + VkClearColorValue ccv; + std::memcpy(ccv.float32, GetUNormClearColor().data(), sizeof(ccv.float32)); + return ccv; +} + +VkClearDepthStencilValue VulkanTexture::GetClearDepthValue() const +{ + return VkClearDepthStencilValue{m_clear_value.depth, 0u}; +} + VkCommandBuffer VulkanTexture::GetCommandBufferForUpdate() { VulkanDevice& dev = VulkanDevice::GetInstance(); diff --git a/src/util/vulkan_texture.h b/src/util/vulkan_texture.h index 7e8a0b684..479b0a1c8 100644 --- a/src/util/vulkan_texture.h +++ b/src/util/vulkan_texture.h @@ -47,6 +47,8 @@ public: ALWAYS_INLINE VkFormat GetVkFormat() const { return m_vk_format; } VkImageLayout GetVkLayout() const; + VkClearColorValue GetClearColorValue() const; + VkClearDepthStencilValue GetClearDepthValue() const; bool Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch, u32 layer = 0, u32 level = 0) override; bool Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer = 0, u32 level = 0) override;