VulkanDevice: Use vkCmdClearAttachments() to avoid render pass restart
This commit is contained in:
parent
5ec1331831
commit
41cc60e87e
|
@ -2678,22 +2678,45 @@ void VulkanDevice::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u
|
||||||
void VulkanDevice::ClearRenderTarget(GPUTexture* t, u32 c)
|
void VulkanDevice::ClearRenderTarget(GPUTexture* t, u32 c)
|
||||||
{
|
{
|
||||||
GPUDevice::ClearRenderTarget(t, c);
|
GPUDevice::ClearRenderTarget(t, c);
|
||||||
if (InRenderPass() && IsRenderTargetBound(t))
|
if (InRenderPass())
|
||||||
EndRenderPass();
|
{
|
||||||
|
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<u32>(idx),
|
||||||
|
{.color = static_cast<VulkanTexture*>(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)
|
void VulkanDevice::ClearDepth(GPUTexture* t, float d)
|
||||||
{
|
{
|
||||||
GPUDevice::ClearDepth(t, d);
|
GPUDevice::ClearDepth(t, d);
|
||||||
if (InRenderPass() && m_current_depth_target == t)
|
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<VulkanTexture*>(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)
|
void VulkanDevice::InvalidateRenderTarget(GPUTexture* t)
|
||||||
{
|
{
|
||||||
GPUDevice::InvalidateRenderTarget(t);
|
GPUDevice::InvalidateRenderTarget(t);
|
||||||
if (InRenderPass() && (t->IsRenderTarget() ? IsRenderTargetBound(t) : (m_current_depth_target == t)))
|
if (InRenderPass() && (t->IsRenderTarget() ? (IsRenderTargetBoundIndex(t) >= 0) : (m_current_depth_target == t)))
|
||||||
EndRenderPass();
|
{
|
||||||
|
// 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()
|
bool VulkanDevice::CreateBuffers()
|
||||||
|
@ -3462,15 +3485,15 @@ void VulkanDevice::InvalidateCachedState()
|
||||||
m_current_pipeline = nullptr;
|
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++)
|
for (u32 i = 0; i < m_num_current_render_targets; i++)
|
||||||
{
|
{
|
||||||
if (m_current_render_targets[i] == tex)
|
if (m_current_render_targets[i] == tex)
|
||||||
return true;
|
return static_cast<s32>(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPipelineLayout VulkanDevice::GetCurrentVkPipelineLayout() const
|
VkPipelineLayout VulkanDevice::GetCurrentVkPipelineLayout() const
|
||||||
|
|
|
@ -348,7 +348,7 @@ private:
|
||||||
/// Set dirty flags on everything to force re-bind at next draw time.
|
/// Set dirty flags on everything to force re-bind at next draw time.
|
||||||
void InvalidateCachedState();
|
void InvalidateCachedState();
|
||||||
|
|
||||||
bool IsRenderTargetBound(const GPUTexture* tex) const;
|
s32 IsRenderTargetBoundIndex(const GPUTexture* tex) const;
|
||||||
|
|
||||||
/// Applies any changed state.
|
/// Applies any changed state.
|
||||||
VkPipelineLayout GetCurrentVkPipelineLayout() const;
|
VkPipelineLayout GetCurrentVkPipelineLayout() const;
|
||||||
|
|
|
@ -212,6 +212,18 @@ VkImageLayout VulkanTexture::GetVkLayout() const
|
||||||
return GetVkImageLayout(m_layout);
|
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()
|
VkCommandBuffer VulkanTexture::GetCommandBufferForUpdate()
|
||||||
{
|
{
|
||||||
VulkanDevice& dev = VulkanDevice::GetInstance();
|
VulkanDevice& dev = VulkanDevice::GetInstance();
|
||||||
|
|
|
@ -47,6 +47,8 @@ public:
|
||||||
ALWAYS_INLINE VkFormat GetVkFormat() const { return m_vk_format; }
|
ALWAYS_INLINE VkFormat GetVkFormat() const { return m_vk_format; }
|
||||||
|
|
||||||
VkImageLayout GetVkLayout() const;
|
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 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;
|
bool Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer = 0, u32 level = 0) override;
|
||||||
|
|
Loading…
Reference in New Issue