GS/Vulkan: Handle case where DS == Texture

Technically we can handle this as another feedback loop, but in my
opinion it's not worth it, since there's only two games I've seen which
do this - Ico and Mercenaries.
This commit is contained in:
Connor McLaughlin 2022-02-01 19:32:18 +10:00 committed by lightningterror
parent b55e59e665
commit 8ce8ac4404
2 changed files with 29 additions and 2 deletions

View File

@ -444,12 +444,17 @@ void GSDeviceVK::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r)
return;
}
const GSVector4i dst_rc(r - r.xyxy());
DoCopyRect(sTex, dTex, r, dst_rc);
}
void GSDeviceVK::DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, const GSVector4i& dst_rc)
{
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
GSTextureVK* const sTexVK = static_cast<GSTextureVK*>(sTex);
GSTextureVK* const dTexVK = static_cast<GSTextureVK*>(dTex);
const GSVector4i dtex_rc(0, 0, dTexVK->GetWidth(), dTexVK->GetHeight());
const GSVector4i dst_rc(r - r.xyxy());
if (sTexVK->GetState() == GSTexture::State::Cleared)
{
@ -499,7 +504,7 @@ void GSDeviceVK::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r)
// *now* we can do a normal image copy.
const VkImageAspectFlags src_aspect = (sTexVK->IsDepthStencil()) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
const VkImageAspectFlags dst_aspect = (dTexVK->IsDepthStencil()) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
const VkImageCopy ic = {{src_aspect, 0u, 0u, 1u}, {r.left, r.top, 0u}, {dst_aspect, 0u, 0u, 1u}, {0u, 0u, 0u},
const VkImageCopy ic = {{src_aspect, 0u, 0u, 1u}, {r.left, r.top, 0u}, {dst_aspect, 0u, 0u, 1u}, {dst_rc.left, dst_rc.top, 0u},
{static_cast<u32>(r.width()), static_cast<u32>(r.height()), 1u}};
EndRenderPass();
@ -2708,6 +2713,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
GSTextureVK* draw_rt = static_cast<GSTextureVK*>(config.rt);
GSTextureVK* draw_ds = static_cast<GSTextureVK*>(config.ds);
GSTextureVK* hdr_rt = nullptr;
GSTextureVK* copy_ds = nullptr;
// Switch to hdr target for colclip rendering
if (pipe.ps.hdr)
@ -2738,6 +2744,23 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
draw_rt = hdr_rt;
}
if (config.tex && config.tex == config.ds)
{
// requires a copy of the depth buffer. this is mainly for ico.
copy_ds = static_cast<GSTextureVK*>(CreateDepthStencil(rtsize.x, rtsize.y, GSTexture::Format::DepthStencil, false));
if (copy_ds)
{
EndRenderPass();
GL_PUSH("Copy depth to temp texture for shuffle {%d,%d %dx%d}",
config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
DoCopyRect(config.ds, copy_ds, config.drawarea, config.drawarea);
PSSetShaderResource(0, copy_ds, true);
}
}
const bool render_area_okay =
(!hdr_rt && DATE_rp != DATE_RENDER_PASS_STENCIL_ONE && CheckRenderPassArea(render_area));
const bool same_framebuffer =
@ -2820,6 +2843,9 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
SendHWDraw(config, draw_rt);
}
if (copy_ds)
Recycle(copy_ds);
if (date_image)
Recycle(date_image);

View File

@ -231,6 +231,7 @@ public:
bool ReadbackTexture(GSTexture* src, const GSVector4i& rect, u32 level, GSTexture::GSMap* dst);
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r) override;
void DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, const GSVector4i& dst_rc);
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
ShaderConvert shader = ShaderConvert::COPY, bool linear = true) override;