GS: Make CopyRect() take a destination offset

This commit is contained in:
Connor McLaughlin 2022-04-21 23:43:00 +10:00 committed by refractionpcsx2
parent b042aeacf5
commit b344ee094f
13 changed files with 35 additions and 72 deletions

View File

@ -717,7 +717,7 @@ public:
/// Must be called to free resources after calling `DownloadTexture` or `DownloadTextureConvert`
virtual void DownloadTextureComplete() {}
virtual void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r) {}
virtual void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) {}
virtual void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) {}
virtual void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha) {}

View File

@ -515,7 +515,7 @@ bool GSDevice11::DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTextu
m_download_tex.reset(static_cast<GSTexture11*>(CreateOffscreen(rect.width(), rect.height(), src->GetFormat())));
if (!m_download_tex)
return false;
CopyRect(src, m_download_tex.get(), rect);
CopyRect(src, m_download_tex.get(), rect, 0, 0);
return m_download_tex->Map(out_map);
}
@ -528,22 +528,11 @@ void GSDevice11::DownloadTextureComplete()
}
}
void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r)
{
if (!sTex || !dTex)
{
ASSERT(0);
return;
}
CopyRect(sTex, r, dTex, 0, 0);
}
void GSDevice11::CopyRect(GSTexture* sTex, const GSVector4i& sRect, GSTexture* dTex, u32 destX, u32 destY)
void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY)
{
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
D3D11_BOX box = {(UINT)sRect.left, (UINT)sRect.top, 0U, (UINT)sRect.right, (UINT)sRect.bottom, 1U};
D3D11_BOX box = {(UINT)r.left, (UINT)r.top, 0U, (UINT)r.right, (UINT)r.bottom, 1U};
// DX api isn't happy if we pass a box for depth copy
// It complains that depth/multisample must be a full copy
@ -565,12 +554,12 @@ void GSDevice11::CloneTexture(GSTexture* src, GSTexture** dest, const GSVector4i
{
// DX11 requires that you copy the entire depth buffer.
*dest = CreateDepthStencil(w, h, src->GetFormat(), false);
CopyRect(src, GSVector4i(0, 0, w, h), *dest, 0, 0);
CopyRect(src, *dest, GSVector4i(0, 0, w, h), 0, 0);
}
else
{
*dest = CreateRenderTarget(w, h, src->GetFormat(), false);
CopyRect(src, rect, *dest, rect.left, rect.top);
CopyRect(src, *dest, rect, rect.left, rect.top);
}
}

View File

@ -251,8 +251,7 @@ public:
void CloneTexture(GSTexture* src, GSTexture** dest, const GSVector4i& rect);
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r);
void CopyRect(GSTexture* sTex, const GSVector4i& sRect, GSTexture* dTex, u32 destX, u32 destY);
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) final;
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear = true);

View File

@ -401,19 +401,7 @@ void GSDevice12::DownloadTextureComplete()
UnmapStagingBuffer();
}
void GSDevice12::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r)
{
if (!sTex || !dTex)
{
ASSERT(0);
return;
}
const GSVector4i dst_rc(r - r.xyxy());
DoCopyRect(sTex, dTex, r, dst_rc);
}
void GSDevice12::DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, const GSVector4i& dst_rc)
void GSDevice12::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY)
{
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
@ -426,7 +414,7 @@ void GSDevice12::DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i&
// source is cleared. if destination is a render target, we can carry the clear forward
if (dTexVK->IsRenderTargetOrDepthStencil())
{
if (dtex_rc.eq(dst_rc))
if (dtex_rc.eq(r))
{
// pass it forward if we're clearing the whole thing
if (sTexVK->IsDepthStencil())
@ -464,7 +452,7 @@ void GSDevice12::DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i&
// if the destination has been cleared, and we're not overwriting the whole thing, commit the clear first
// (the area outside of where we're copying to)
if (dTexVK->GetState() == GSTexture::State::Cleared && !dtex_rc.eq(dst_rc))
if (dTexVK->GetState() == GSTexture::State::Cleared && !dtex_rc.eq(r))
dTexVK->CommitClear();
EndRenderPass();
@ -485,7 +473,7 @@ void GSDevice12::DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i&
const D3D12_BOX srcbox{static_cast<UINT>(r.left), static_cast<UINT>(r.top), 0u,
static_cast<UINT>(r.right), static_cast<UINT>(r.bottom), 1u};
g_d3d12_context->GetCommandList()->CopyTextureRegion(
&dstloc, dst_rc.left, dst_rc.top, 0,
&dstloc, destX, destY, 0,
&srcloc, &srcbox);
dTexVK->SetState(GSTexture::State::Dirty);
@ -2514,7 +2502,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
config.drawarea.width(), config.drawarea.height());
draw_rt_clone->SetState(GSTexture::State::Invalidated);
DoCopyRect(draw_rt, draw_rt_clone, config.drawarea, config.drawarea);
CopyRect(draw_rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
PSSetShaderResource(2, draw_rt_clone, true);
}
}
@ -2532,7 +2520,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
config.drawarea.width(), config.drawarea.height());
copy_ds->SetState(GSTexture::State::Invalidated);
DoCopyRect(config.ds, copy_ds, config.drawarea, config.drawarea);
CopyRect(config.ds, copy_ds, config.drawarea, config.drawarea.left, config.drawarea.top);
PSSetShaderResource(0, copy_ds, true);
}
}

View File

@ -248,8 +248,7 @@ public:
GSTexture* DrawForReadback(GSTexture* src, const GSVector4& sRect, int w, int h, int format = 0, int ps_shader = 0);
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 CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
ShaderConvert shader = ShaderConvert::COPY, bool linear = true) override;

View File

@ -1571,7 +1571,7 @@ void GSRendererHW::Draw()
g_gs_device->CreateSparseRenderTarget(new_w, new_h, tex->GetFormat()) :
g_gs_device->CreateSparseDepthStencil(new_w, new_h, tex->GetFormat());
const GSVector4i r{ 0, 0, w, h };
g_gs_device->CopyRect(tex, t->m_texture, r);
g_gs_device->CopyRect(tex, t->m_texture, r, 0, 0);
g_gs_device->Recycle(tex);
t->m_texture->SetScale(up_s);
(is_rt ? rt_tex : ds_tex) = t->m_texture;
@ -2017,11 +2017,11 @@ bool GSRendererHW::OI_BlitFMV(GSTextureCache::Target* _rt, GSTextureCache::Sourc
const GSVector4i r_full(0, 0, tw, th);
if (GSTexture* rt = g_gs_device->CreateRenderTarget(tw, th, GSTexture::Format::Color))
{
g_gs_device->CopyRect(tex->m_texture, rt, r_full);
g_gs_device->CopyRect(tex->m_texture, rt, r_full, 0, 0);
g_gs_device->StretchRect(tex->m_texture, sRect, rt, dRect);
g_gs_device->CopyRect(rt, tex->m_texture, r_full);
g_gs_device->CopyRect(rt, tex->m_texture, r_full, 0, 0);
g_gs_device->Recycle(rt);
}

View File

@ -1188,7 +1188,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
GSTexture* dTex = g_gs_device->CreateTexture(w, h, false, GSTexture::Format::Color, true);
GSVector4i area(x, y, x + w, y + h);
g_gs_device->CopyRect(sTex, dTex, area);
g_gs_device->CopyRect(sTex, dTex, area, 0, 0);
// Keep a trace of origin of the texture
src->m_texture = dTex;
@ -1380,7 +1380,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
if (use_texture)
{
g_gs_device->CopyRect(sTex, dTex, sRect);
g_gs_device->CopyRect(sTex, dTex, sRect, 0, 0);
}
else
{

View File

@ -349,7 +349,7 @@ public:
bool DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map) override;
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r) override;
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;
void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, id<MTLRenderPipelineState> pipeline, bool linear, LoadAction load_action, void* frag_uniform, size_t frag_uniform_len);
void DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2i& ds);
/// Copy from a position in sTex to the same position in the currently active render encoder using the given fs pipeline and rect

View File

@ -941,7 +941,7 @@ bool GSDeviceMTL::DownloadTexture(GSTexture* src, const GSVector4i& rect, GSText
return true;
}}
void GSDeviceMTL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r)
void GSDeviceMTL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY)
{ @autoreleasepool {
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
@ -971,7 +971,7 @@ void GSDeviceMTL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r
toTexture:dT->GetTexture()
destinationSlice:0
destinationLevel:0
destinationOrigin:MTLOriginMake(0, 0, 0)];
destinationOrigin:MTLOriginMake((int)destX, (int)destY, 0)];
[encoder endEncoding];
}}

View File

@ -1145,7 +1145,7 @@ void GSDeviceOGL::BlitRect(GSTexture* sTex, const GSVector4i& r, const GSVector2
}
// Copy a sub part of a texture into another
void GSDeviceOGL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r)
void GSDeviceOGL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY)
{
ASSERT(sTex && dTex);
if (!(sTex && dTex))
@ -1167,7 +1167,7 @@ void GSDeviceOGL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r
glCopyImageSubData(sid, GL_TEXTURE_2D,
0, r.x, r.y, 0,
did, GL_TEXTURE_2D,
0, 0, 0, 0,
0, destX, destY, 0,
r.width(), r.height(), 1);
}

View File

@ -341,7 +341,7 @@ public:
bool DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map) final;
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r) final;
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) final;
void PushDebugGroup(const char* fmt, ...) final;
void PopDebugGroup() final;

View File

@ -489,19 +489,7 @@ bool GSDeviceVK::DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTextu
void GSDeviceVK::DownloadTextureComplete() {}
void GSDeviceVK::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r)
{
if (!sTex || !dTex)
{
ASSERT(0);
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)
void GSDeviceVK::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY)
{
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
@ -514,7 +502,7 @@ void GSDeviceVK::DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i&
// source is cleared. if destination is a render target, we can carry the clear forward
if (dTexVK->IsRenderTargetOrDepthStencil())
{
if (dtex_rc.eq(dst_rc))
if (dtex_rc.eq(r))
{
// pass it forward if we're clearing the whole thing
if (sTexVK->IsDepthStencil())
@ -529,7 +517,7 @@ void GSDeviceVK::DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i&
// otherwise we need to do an attachment clear
const bool depth = (dTexVK->GetType() == GSTexture::Type::DepthStencil);
OMSetRenderTargets(depth ? nullptr : dTexVK, depth ? dTexVK : nullptr, dtex_rc, false);
BeginRenderPassForStretchRect(dTexVK, dtex_rc, dst_rc);
BeginRenderPassForStretchRect(dTexVK, dtex_rc, GSVector4i(destX, destY, destX + r.width(), destY + r.height()));
// so use an attachment clear
VkClearAttachment ca;
@ -539,7 +527,7 @@ void GSDeviceVK::DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i&
ca.clearValue.depthStencil.stencil = 0;
ca.colorAttachment = 0;
const VkClearRect cr = { {{0, 0}, {static_cast<u32>(dst_rc.width()), static_cast<u32>(dst_rc.height())}}, 0u, 1u };
const VkClearRect cr = { {{0, 0}, {static_cast<u32>(r.width()), static_cast<u32>(r.height())}}, 0u, 1u };
vkCmdClearAttachments(g_vulkan_context->GetCurrentCommandBuffer(), 1, &ca, 1, &cr);
return;
}
@ -551,13 +539,14 @@ void GSDeviceVK::DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i&
// if the destination has been cleared, and we're not overwriting the whole thing, commit the clear first
// (the area outside of where we're copying to)
if (dTexVK->GetState() == GSTexture::State::Cleared && !dtex_rc.eq(dst_rc))
if (dTexVK->GetState() == GSTexture::State::Cleared && !dtex_rc.eq(r))
dTexVK->CommitClear();
// *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}, {dst_rc.left, dst_rc.top, 0u},
const VkImageCopy ic = {{src_aspect, 0u, 0u, 1u}, {r.left, r.top, 0u}, {dst_aspect, 0u, 0u, 1u},
{static_cast<s32>(destX), static_cast<s32>(destY), 0u},
{static_cast<u32>(r.width()), static_cast<u32>(r.height()), 1u}};
EndRenderPass();
@ -2925,7 +2914,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
DoCopyRect(draw_rt, draw_rt_clone, config.drawarea, config.drawarea);
CopyRect(draw_rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
PSSetShaderResource(2, draw_rt_clone, true);
}
}
@ -2942,7 +2931,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
DoCopyRect(config.ds, copy_ds, config.drawarea, config.drawarea);
CopyRect(config.ds, copy_ds, config.drawarea, config.drawarea.left, config.drawarea.top);
PSSetShaderResource(0, copy_ds, true);
}
}

View File

@ -223,8 +223,7 @@ public:
bool DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map) override;
void DownloadTextureComplete() override;
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r) override;
void DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, const GSVector4i& dst_rc);
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
ShaderConvert shader = ShaderConvert::COPY, bool linear = true) override;