Skip to content

Commit

Permalink
GS/Vulkan: Handle case where DS == Texture
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
stenzek authored and lightningterror committed Feb 1, 2022
1 parent b55e59e commit 8ce8ac4
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
30 changes: 28 additions & 2 deletions pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h
Expand Up @@ -231,6 +231,7 @@ class GSDeviceVK final : public GSDevice
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;
Expand Down

0 comments on commit 8ce8ac4

Please sign in to comment.