Compare commits

...

3 Commits

Author SHA1 Message Date
TJnotJT
35624a12d9 GS/HW: Refactor StretchRect() to have single entry to renderer/reduce duplication. 2025-11-25 18:38:52 +01:00
JordanTheToaster
9b147cc57c GameDB: FFX-2 FMV FIxes 2025-11-25 17:50:06 +01:00
JordanTheToaster
10e13cfece GS/HW: Test double buffer offset from target base address on lookup 2025-11-25 17:50:06 +01:00
14 changed files with 170 additions and 174 deletions

View File

@@ -2588,12 +2588,11 @@ SCAJ-25012:
region: "NTSC-Unk"
clampModes:
eeClampMode: 3 # Fixes animations.
gameFixes:
- SoftwareRendererFMVHack # Fixes brightness and overlapping subtitles.
gsHWFixes:
roundSprite: 1 # Fixes font artifacts.
halfPixelOffset: 5 # Helps align post effects.
autoFlush: 1 # Fixes missing blur.
textureInsideRT: 1 # Fixes broken FMVs.
SCAJ-25026:
name: "Kunoichi Shinobi"
region: "NTSC-Unk"
@@ -13155,12 +13154,11 @@ SLAJ-25012:
region: "NTSC-Unk"
clampModes:
eeClampMode: 3 # Fixes animations.
gameFixes:
- SoftwareRendererFMVHack # Fixes brightness and overlapping subtitles.
gsHWFixes:
roundSprite: 1 # Fixes font artifacts.
halfPixelOffset: 5 # Helps align post effects.
autoFlush: 1 # Fixes missing blur.
textureInsideRT: 1 # Fixes broken FMVs.
SLAJ-25014:
name: "Cyber Troopers - Virtual-On Marz"
region: "NTSC-Unk"
@@ -13749,12 +13747,11 @@ SLED-51921:
region: "PAL-Unk"
clampModes:
eeClampMode: 3 # Fixes animations.
gameFixes:
- SoftwareRendererFMVHack # Fixes brightness and overlapping subtitles.
gsHWFixes:
roundSprite: 1 # Fixes font artifacts.
halfPixelOffset: 5 # Helps align post effects.
autoFlush: 1 # Fixes missing blur.
textureInsideRT: 1 # Fixes broken FMVs.
SLED-51961:
name: "Prince of Persia - The Sands of Time [Demo]"
region: "PAL-E"
@@ -18650,58 +18647,53 @@ SLES-51815:
compat: 5
clampModes:
eeClampMode: 3 # Fixes animations.
gameFixes:
- SoftwareRendererFMVHack # Fixes brightness and overlapping subtitles.
gsHWFixes:
roundSprite: 1 # Fixes font artifacts.
halfPixelOffset: 5 # Helps align post effects.
autoFlush: 1 # Fixes missing blur.
textureInsideRT: 1 # Fixes broken FMVs.
SLES-51816:
name: "Final Fantasy X-2"
region: "PAL-F"
clampModes:
eeClampMode: 3 # Fixes animations.
gameFixes:
- SoftwareRendererFMVHack # Fixes brightness and overlapping subtitles.
gsHWFixes:
roundSprite: 1 # Fixes font artifacts.
halfPixelOffset: 5 # Helps align post effects.
autoFlush: 1 # Fixes missing blur.
textureInsideRT: 1 # Fixes broken FMVs.
SLES-51817:
name: "Final Fantasy X-2"
region: "PAL-G"
compat: 5
clampModes:
eeClampMode: 3 # Fixes animations.
gameFixes:
- SoftwareRendererFMVHack # Fixes brightness and overlapping subtitles.
gsHWFixes:
roundSprite: 1 # Fixes font artifacts.
halfPixelOffset: 5 # Helps align post effects.
autoFlush: 1 # Fixes missing blur.
textureInsideRT: 1 # Fixes broken FMVs.
SLES-51818:
name: "Final Fantasy X-2"
region: "PAL-I"
clampModes:
eeClampMode: 3 # Fixes animations.
gameFixes:
- SoftwareRendererFMVHack # Fixes brightness and overlapping subtitles.
gsHWFixes:
roundSprite: 1 # Fixes font artifacts.
halfPixelOffset: 5 # Helps align post effects.
autoFlush: 1 # Fixes missing blur.
textureInsideRT: 1 # Fixes broken FMVs.
SLES-51819:
name: "Final Fantasy X-2"
region: "PAL-S"
compat: 5
clampModes:
eeClampMode: 3 # Fixes animations.
gameFixes:
- SoftwareRendererFMVHack # Fixes brightness and overlapping subtitles.
gsHWFixes:
roundSprite: 1 # Fixes font artifacts.
halfPixelOffset: 5 # Helps align post effects.
autoFlush: 1 # Fixes missing blur.
textureInsideRT: 1 # Fixes broken FMVs.
SLES-51820:
name: "Sniper Elite"
region: "PAL-M5"
@@ -31722,12 +31714,11 @@ SLKA-25144:
compat: 5
clampModes:
eeClampMode: 3 # Fixes animations.
gameFixes:
- SoftwareRendererFMVHack # Fixes brightness and overlapping subtitles.
gsHWFixes:
roundSprite: 1 # Fixes font artifacts.
halfPixelOffset: 5 # Helps align post effects.
autoFlush: 1 # Fixes missing blur.
textureInsideRT: 1 # Fixes broken FMVs.
SLKA-25145:
name: ".hack//침식오염 Vol.3"
name-sort: ".hack Outbreak Vol. 3"
@@ -47673,12 +47664,11 @@ SLPM-66125:
region: "NTSC-J"
clampModes:
eeClampMode: 3 # Fixes animations.
gameFixes:
- SoftwareRendererFMVHack # Fixes brightness and overlapping subtitles.
gsHWFixes:
roundSprite: 1 # Fixes font artifacts.
halfPixelOffset: 5 # Helps align post effects.
autoFlush: 1 # Fixes missing blur.
textureInsideRT: 1 # Fixes broken FMVs.
SLPM-66127:
name: "Harukanaru Toki no Naka de 3 - Izayoiki"
region: "NTSC-J"
@@ -58539,12 +58529,11 @@ SLPS-25250:
region: "NTSC-J"
clampModes:
eeClampMode: 3 # Fixes animations.
gameFixes:
- SoftwareRendererFMVHack # Fixes brightness and overlapping subtitles.
gsHWFixes:
roundSprite: 1 # Fixes font artifacts.
halfPixelOffset: 5 # Helps align post effects.
autoFlush: 1 # Fixes missing blur.
textureInsideRT: 1 # Fixes broken FMVs.
SLPS-25251:
name: "MVPベースボール2003"
name-sort: "MVPべーすぼーる2003"
@@ -67244,12 +67233,11 @@ SLUS-20672:
compat: 5
clampModes:
eeClampMode: 3 # Fixes animations.
gameFixes:
- SoftwareRendererFMVHack # Fixes brightness and overlapping subtitles.
gsHWFixes:
roundSprite: 1 # Fixes font artifacts.
halfPixelOffset: 5 # Helps align post effects.
autoFlush: 1 # Fixes missing blur.
textureInsideRT: 1 # Fixes broken FMVs.
SLUS-20673:
name: "Alias"
region: "NTSC-U"

View File

@@ -723,6 +723,39 @@ GSTexture* GSDevice::CreateTexture(int w, int h, int mipmap_levels, GSTexture::F
return FetchSurface(GSTexture::Type::Texture, w, h, levels, format, false, m_features.prefer_new_textures && !prefer_reuse);
}
void GSDevice::DoStretchRectWithAssertions(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear)
{
pxAssert((dTex && dTex->IsDepthStencil()) == HasDepthOutput(shader));
pxAssert(linear ? SupportsBilinear(shader) : SupportsNearest(shader));
GL_INS("StretchRect(%d) {%d,%d} %dx%d -> {%d,%d) %dx%d", shader, int(sRect.left), int(sRect.top),
int(sRect.right - sRect.left), int(sRect.bottom - sRect.top), int(dRect.left), int(dRect.top),
int(dRect.right - dRect.left), int(dRect.bottom - dRect.top));
DoStretchRect(sTex, sRect, dTex, dRect, cms, shader, linear);
}
void GSDevice::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
bool red, bool green, bool blue, bool alpha, ShaderConvert shader)
{
GSHWDrawConfig::ColorMaskSelector cms;
cms.wr = red;
cms.wg = green;
cms.wb = blue;
cms.wa = alpha;
pxAssert(HasVariableWriteMask(shader));
GL_INS("ColorCopy Red:%d Green:%d Blue:%d Alpha:%d", cms.wr, cms.wg, cms.wb, cms.wa);
DoStretchRectWithAssertions(sTex, sRect, dTex, dRect, cms, shader, false);
}
void GSDevice::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
ShaderConvert shader, bool linear)
{
DoStretchRectWithAssertions(sTex, sRect, dTex, dRect, GSHWDrawConfig::ColorMaskSelector(ShaderConvertWriteMask(shader)), shader, linear);
}
void GSDevice::StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
{
StretchRect(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, shader, linear);
@@ -734,11 +767,11 @@ void GSDevice::DrawMultiStretchRects(
for (u32 i = 0; i < num_rects; i++)
{
const MultiStretchRect& sr = rects[i];
pxAssert(shader == ShaderConvert::COPY || shader == ShaderConvert::RTA_CORRECTION || rects[0].wmask.wrgba == 0xf);
pxAssert(HasVariableWriteMask(shader) || rects[0].wmask.wrgba == 0xf);
if (rects[0].wmask.wrgba != 0xf)
{
g_gs_device->StretchRect(sr.src, sr.src_rect, dTex, sr.dst_rect, rects[0].wmask.wr,
rects[0].wmask.wg, rects[0].wmask.wb, rects[0].wmask.wa);
rects[0].wmask.wg, rects[0].wmask.wb, rects[0].wmask.wa, shader);
}
else
{

View File

@@ -69,6 +69,27 @@ enum class ShaderInterlace
Count
};
static inline bool HasVariableWriteMask(ShaderConvert shader)
{
switch (shader)
{
case ShaderConvert::COPY:
case ShaderConvert::RTA_CORRECTION:
return true;
default:
return false;
}
}
static inline int GetShaderIndexForMask(ShaderConvert shader, int mask)
{
pxAssert(HasVariableWriteMask(shader));
int index = mask;
if (shader == ShaderConvert::RTA_CORRECTION)
index |= 1 << 4;
return index;
}
static inline bool HasDepthOutput(ShaderConvert shader)
{
switch (shader)
@@ -549,6 +570,7 @@ struct alignas(16) GSHWDrawConfig
constexpr ColorMaskSelector(): key(0xF) {}
constexpr ColorMaskSelector(u8 c): key(0) { wrgba = c; }
};
#pragma pack(pop)
struct alignas(16) VSConstantBuffer
{
@@ -922,6 +944,12 @@ protected:
/// Perform texture operations for ImGui
void UpdateImGuiTextures();
protected:
// Entry point to the renderer-specific StretchRect code.
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear) = 0;
void DoStretchRectWithAssertions(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear);
public:
GSDevice();
virtual ~GSDevice();
@@ -1037,9 +1065,9 @@ public:
virtual std::unique_ptr<GSDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GSTexture::Format format) = 0;
virtual void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) = 0;
virtual void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) = 0;
virtual void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY) = 0;
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY);
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true);
void StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true);
/// Performs a screen blit for display. If dTex is null, it assumes you are writing to the system framebuffer/swap chain.

View File

@@ -1274,28 +1274,18 @@ void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
dTex->SetState(GSTexture::State::Dirty);
}
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
void GSDevice11::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear)
{
pxAssert(dTex->IsDepthStencil() == HasDepthOutput(shader));
pxAssert(linear ? SupportsBilinear(shader) : SupportsNearest(shader));
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), nullptr,
m_convert.bs[ShaderConvertWriteMask(shader)].get(), linear);
DoStretchRect(sTex, sRect, dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), nullptr, m_convert.bs[cms.wrgba].get(), linear);
}
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear)
void GSDevice11::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear)
{
StretchRect(sTex, sRect, dTex, dRect, ps, ps_cb, m_convert.bs[D3D11_COLOR_WRITE_ENABLE_ALL].get(), linear);
DoStretchRect(sTex, sRect, dTex, dRect, ps, ps_cb, m_convert.bs[D3D11_COLOR_WRITE_ENABLE_ALL].get(), linear);
}
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader)
{
const u8 index = static_cast<u8>(red) | (static_cast<u8>(green) << 1) | (static_cast<u8>(blue) << 2) |
(static_cast<u8>(alpha) << 3);
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), nullptr,
m_convert.bs[index].get(), false);
}
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear)
void GSDevice11::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear)
{
CommitClear(sTex);
@@ -1439,7 +1429,7 @@ void GSDevice11::UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX, u
const GSVector4 dRect(0, 0, dSize, 1);
const ShaderConvert shader = (dSize == 16) ? ShaderConvert::CLUT_4 : ShaderConvert::CLUT_8;
StretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
}
void GSDevice11::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM)
@@ -1457,7 +1447,7 @@ void GSDevice11::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offs
const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
StretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
}
void GSDevice11::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 downsample_factor, const GSVector2i& clamp_min, const GSVector4& dRect)
@@ -1477,7 +1467,7 @@ void GSDevice11::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
const ShaderConvert shader = ShaderConvert::DOWNSAMPLE_COPY;
StretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
}
void GSDevice11::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvert shader)
@@ -1596,7 +1586,7 @@ void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
// Save 2nd output
if (feedback_write_2)
{
StretchRect(dTex, full_r, sTex[2], dRect[2], m_convert.ps[static_cast<int>(ShaderConvert::YUV)].get(),
DoStretchRect(dTex, full_r, sTex[2], dRect[2], m_convert.ps[static_cast<int>(ShaderConvert::YUV)].get(),
m_merge.cb.get(), nullptr, linear);
}
@@ -1607,12 +1597,12 @@ void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
if (sTex[0])
{
// 1st output is enabled. It must be blended
StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge.ps[PMODE.MMOD].get(), m_merge.cb.get(), m_merge.bs.get(), linear);
DoStretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge.ps[PMODE.MMOD].get(), m_merge.cb.get(), m_merge.bs.get(), linear);
}
if (feedback_write_1)
{
StretchRect(dTex, full_r, sTex[2], dRect[2], m_convert.ps[static_cast<int>(ShaderConvert::YUV)].get(),
DoStretchRect(dTex, full_r, sTex[2], dRect[2], m_convert.ps[static_cast<int>(ShaderConvert::YUV)].get(),
m_merge.cb.get(), nullptr, linear);
}
}
@@ -1621,7 +1611,7 @@ void GSDevice11::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture*
{
m_ctx->UpdateSubresource(m_interlace.cb.get(), 0, nullptr, &cb, 0, 0);
StretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)].get(), m_interlace.cb.get(), linear);
DoStretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)].get(), m_interlace.cb.get(), linear);
}
void GSDevice11::DoFXAA(GSTexture* sTex, GSTexture* dTex)
@@ -1647,7 +1637,7 @@ void GSDevice11::DoFXAA(GSTexture* sTex, GSTexture* dTex)
return;
}
StretchRect(sTex, sRect, dTex, dRect, m_fxaa_ps.get(), nullptr, true);
DoStretchRect(sTex, sRect, dTex, dRect, m_fxaa_ps.get(), nullptr, true);
}
void GSDevice11::DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4])
@@ -1659,7 +1649,7 @@ void GSDevice11::DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float para
m_ctx->UpdateSubresource(m_shadeboost.cb.get(), 0, nullptr, params, 0, 0);
StretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps.get(), m_shadeboost.cb.get(), false);
DoStretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps.get(), m_shadeboost.cb.get(), false);
}
void GSDevice11::SetupVS(VSSelector sel, const GSHWDrawConfig::VSConstantBuffer* cb)
@@ -2647,7 +2637,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
return;
}
StretchRect(colclip_rt ? colclip_rt : config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
DoStretchRect(colclip_rt ? colclip_rt : config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
primid_texture, GSVector4(config.drawarea), m_date.primid_init_ps[static_cast<u8>(config.datm)].get(), nullptr, false);
}
else if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil ||

View File

@@ -253,6 +253,10 @@ private:
D3D11ShaderCache m_shader_cache;
std::string m_tfx_source;
protected:
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear) override;
public:
GSDevice11();
~GSDevice11() override;
@@ -298,10 +302,8 @@ public:
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;
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear = true);
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY) override;
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear = true);
void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear);
void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear);
void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, bool linear) override;
void UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, GSTexture* dTex, u32 dOffset, u32 dSize) override;
void ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM) override;

View File

@@ -1425,30 +1425,17 @@ void GSDevice12::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
dTex12->SetState(GSTexture::State::Dirty);
}
void GSDevice12::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
ShaderConvert shader /* = ShaderConvert::COPY */, bool linear /* = true */)
void GSDevice12::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear)
{
pxAssert(HasDepthOutput(shader) == (dTex && dTex->GetType() == GSTexture::Type::DepthStencil));
GL_INS("StretchRect(%d) {%d,%d} %dx%d -> {%d,%d) %dx%d", shader, int(sRect.left), int(sRect.top),
int(sRect.right - sRect.left), int(sRect.bottom - sRect.top), int(dRect.left), int(dRect.top),
int(dRect.right - dRect.left), int(dRect.bottom - dRect.top));
const bool allow_discard = (cms.wrgba == 0xf);
const ID3D12PipelineState* state;
if (HasVariableWriteMask(shader))
state = m_color_copy[GetShaderIndexForMask(shader, cms.wrgba)].get();
else
state = dTex ? m_convert[static_cast<int>(shader)].get() : m_present[static_cast<int>(shader)].get();
DoStretchRect(static_cast<GSTexture12*>(sTex), sRect, static_cast<GSTexture12*>(dTex), dRect,
dTex ? m_convert[static_cast<int>(shader)].get() : m_present[static_cast<int>(shader)].get(), linear,
ShaderConvertWriteMask(shader) == 0xf);
}
void GSDevice12::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red,
bool green, bool blue, bool alpha, ShaderConvert shader)
{
GL_PUSH("ColorCopy Red:%d Green:%d Blue:%d Alpha:%d", red, green, blue, alpha);
const u32 index = (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
int rta_offset = (shader == ShaderConvert::RTA_CORRECTION) ? 16 : 0;
const bool allow_discard = (index == 0xf);
DoStretchRect(static_cast<GSTexture12*>(sTex), sRect, static_cast<GSTexture12*>(dTex), dRect,
m_color_copy[index + rta_offset].get(), false, allow_discard);
state, linear, allow_discard);
}
void GSDevice12::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
@@ -1639,10 +1626,10 @@ void GSDevice12::DoMultiStretchRects(
SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
SetUtilityTexture(rects[0].src, rects[0].linear ? m_linear_sampler_cpu : m_point_sampler_cpu);
pxAssert(shader == ShaderConvert::COPY || shader == ShaderConvert::RTA_CORRECTION || rects[0].wmask.wrgba == 0xf);
int rta_bit = (shader == ShaderConvert::RTA_CORRECTION) ? 16 : 0;
SetPipeline((rects[0].wmask.wrgba != 0xf) ? m_color_copy[rects[0].wmask.wrgba | rta_bit].get() :
m_convert[static_cast<int>(shader)].get());
pxAssert(HasVariableWriteMask(shader) || rects[0].wmask.wrgba == 0xf);
SetPipeline((rects[0].wmask.wrgba != 0xf) ?
m_color_copy[GetShaderIndexForMask(shader, rects[0].wmask.wrgba)].get() :
m_convert[static_cast<int>(shader)].get());
if (ApplyUtilityState())
DrawIndexedPrimitive();

View File

@@ -390,6 +390,10 @@ private:
void DestroyResources();
protected:
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear) override;
public:
GSDevice12();
~GSDevice12() override;
@@ -428,10 +432,6 @@ public:
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;
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red,
bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY) override;
void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
PresentShader shader, float shaderTime, bool linear) override;
void UpdateCLUTTexture(

View File

@@ -2663,8 +2663,10 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
for (auto i = list.begin(); i != list.end(); ++i)
{
Target* t = *i;
const bool half_buffer_match = GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets && TEX0.TBW == t->m_TEX0.TBW && TEX0.PSM == t->m_TEX0.PSM &&
bp == GSLocalMemory::GetStartBlockAddress(t->m_TEX0.TBP0, t->m_TEX0.TBW, t->m_TEX0.PSM, GSVector4i(0, size.y, size.x, size.y + 1));
// Make sure the target is inside the texture
if (t->m_TEX0.TBP0 <= bp && bp <= t->m_end_block && t->Inside(bp, TEX0.TBW, TEX0.PSM, GSVector4i::loadh(size)))
if (t->m_TEX0.TBP0 <= bp && bp <= t->m_end_block && (half_buffer_match || t->Inside(bp, TEX0.TBW, TEX0.PSM, GSVector4i::loadh(size))))
{
if (dst && (GSState::s_n - dst->m_last_draw) < (GSState::s_n - t->m_last_draw))
continue;

View File

@@ -407,8 +407,6 @@ public:
void DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2& ds);
/// Copy from a position in sTex to the same position in the currently active render encoder using the given fs pipeline and rect
void RenderCopy(GSTexture* sTex, id<MTLRenderPipelineState> pipeline, const GSVector4i& rect);
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) override;
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY) override;
void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, bool linear) override;
void DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvert shader) override;
void UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, GSTexture* dTex, u32 dOffset, u32 dSize) override;
@@ -452,6 +450,10 @@ public:
void RenderImGui(ImDrawData* data);
u32 FrameNo() const { return m_frame; }
protected:
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear) override;
};
static constexpr bool IsCommandBufferCompleted(MTLCommandBufferStatus status)

View File

@@ -1600,33 +1600,21 @@ void GSDeviceMTL::RenderCopy(GSTexture* sTex, id<MTLRenderPipelineState> pipelin
g_perfmon.Put(GSPerfMon::DrawCalls, 1);
}
void GSDeviceMTL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
void GSDeviceMTL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear)
{ @autoreleasepool {
pxAssert(linear ? SupportsBilinear(shader) : SupportsNearest(shader));
id<MTLRenderPipelineState> pipeline = m_convert_pipeline[static_cast<int>(shader)];
const LoadAction load_action = (cms.wrgba == 0xf) ? LoadAction::DontCareIfFull : LoadAction::Load;
id<MTLRenderPipelineState> pipeline;
if (HasVariableWriteMask(shader))
pipeline = m_convert_pipeline_copy_mask[GetShaderIndexForMask(shader, cms.wrgba)];
else
pipeline = m_convert_pipeline[static_cast<int>(shader)];
pxAssertRel(pipeline, fmt::format("No pipeline for {}", shaderName(shader)).c_str());
const LoadAction load_action = (ShaderConvertWriteMask(shader) == 0xf) ? LoadAction::DontCareIfFull : LoadAction::Load;
DoStretchRect(sTex, sRect, dTex, dRect, pipeline, linear, load_action, nullptr, 0);
}}
void GSDeviceMTL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader)
{ @autoreleasepool {
int sel = 0;
if (red) sel |= 1;
if (green) sel |= 2;
if (blue) sel |= 4;
if (alpha) sel |= 8;
if (shader == ShaderConvert::RTA_CORRECTION) sel |= 16;
const int color_sel = sel & 15;
id<MTLRenderPipelineState> pipeline = m_convert_pipeline_copy_mask[sel];
DoStretchRect(sTex, sRect, dTex, dRect, pipeline, false, color_sel == 15 ? LoadAction::DontCareIfFull : LoadAction::Load, nullptr, 0);
}}
static_assert(sizeof(DisplayConstantBuffer) == sizeof(GSMTLPresentPSUniform));
static_assert(offsetof(DisplayConstantBuffer, SourceRect) == offsetof(GSMTLPresentPSUniform, source_rect));
static_assert(offsetof(DisplayConstantBuffer, TargetRect) == offsetof(GSMTLPresentPSUniform, target_rect));
@@ -1683,9 +1671,9 @@ void GSDeviceMTL::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_r
const u32 end = i * 4;
const u32 vertex_count = end - start;
const u32 index_count = vertex_count + (vertex_count >> 1); // 6 indices per 4 vertices
const int rta_bit = shader == ShaderConvert::RTA_CORRECTION ? 16 : 0;
pxAssert(HasVariableWriteMask(shader) || wmask == 0xf);
id<MTLRenderPipelineState> new_pipeline = wmask == 0xf ? m_convert_pipeline[static_cast<int>(shader)]
: m_convert_pipeline_copy_mask[wmask | rta_bit];
: m_convert_pipeline_copy_mask[GetShaderIndexForMask(shader, wmask)];
if (new_pipeline != pipeline)
{
pipeline = new_pipeline;

View File

@@ -1253,7 +1253,7 @@ GSTexture* GSDeviceOGL::InitPrimDateTexture(GSTexture* rt, const GSVector4i& are
return nullptr;
GL_PUSH("PrimID Destination Alpha Clear");
StretchRect(rt, GSVector4(area) / GSVector4(rtsize).xyxy(), tex, GSVector4(area), m_date.primid_ps[static_cast<u8>(datm)], false);
DoStretchRect(rt, GSVector4(area) / GSVector4(rtsize).xyxy(), tex, GSVector4(area), m_date.primid_ps[static_cast<u8>(datm)], false);
return tex;
}
@@ -1472,31 +1472,20 @@ void GSDeviceOGL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r
dTex->SetState(GSTexture::State::Dirty);
}
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
void GSDeviceOGL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
OMColorMaskSelector cms, ShaderConvert shader, bool linear)
{
pxAssert(dTex->IsDepthStencil() == HasDepthOutput(shader));
pxAssert(linear ? SupportsBilinear(shader) : SupportsNearest(shader));
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[(int)shader], false, OMColorMaskSelector(ShaderConvertWriteMask(shader)), linear);
DoStretchRect(sTex, sRect, dTex, dRect, m_convert.ps[static_cast<int>(shader)], false, cms, linear);
}
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool linear)
void GSDeviceOGL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
const GLProgram& ps, bool linear)
{
StretchRect(sTex, sRect, dTex, dRect, ps, false, OMColorMaskSelector(), linear);
DoStretchRect(sTex, sRect, dTex, dRect, ps, false, OMColorMaskSelector(), linear);
}
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader)
{
OMColorMaskSelector cms;
cms.wr = red;
cms.wg = green;
cms.wb = blue;
cms.wa = alpha;
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[(int)shader], false, cms, false);
}
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear)
void GSDeviceOGL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
const GLProgram& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear)
{
CommitClear(sTex, true);
@@ -1816,12 +1805,12 @@ void GSDeviceOGL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
// Blend with a constant alpha
m_merge_obj.ps[1].Bind();
m_merge_obj.ps[1].Uniform4fv(0, GSVector4::unorm8(c).v);
StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[1], true, OMColorMaskSelector(), linear);
DoStretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[1], true, OMColorMaskSelector(), linear);
}
else
{
// Blend with 2 * input alpha
StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[0], true, OMColorMaskSelector(), linear);
DoStretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[0], true, OMColorMaskSelector(), linear);
}
}
@@ -1836,7 +1825,7 @@ void GSDeviceOGL::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture
m_interlace.ps[static_cast<int>(shader)].Bind();
m_interlace.ps[static_cast<int>(shader)].Uniform4fv(0, cb.ZrH.F32);
StretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)], linear);
DoStretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)], linear);
}
bool GSDeviceOGL::CompileFXAAProgram()
@@ -1875,7 +1864,7 @@ void GSDeviceOGL::DoFXAA(GSTexture* sTex, GSTexture* dTex)
const GSVector4 sRect(0, 0, 1, 1);
const GSVector4 dRect(0, 0, s.x, s.y);
StretchRect(sTex, sRect, dTex, dRect, m_fxaa.ps, true);
DoStretchRect(sTex, sRect, dTex, dRect, m_fxaa.ps, true);
}
bool GSDeviceOGL::CompileShadeBoostProgram()
@@ -1909,7 +1898,7 @@ void GSDeviceOGL::DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float par
const GSVector4 sRect(0, 0, 1, 1);
const GSVector4 dRect(0, 0, s.x, s.y);
StretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps, false);
DoStretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps, false);
}
void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, SetDATM datm, const GSVector4i& bbox)

View File

@@ -265,6 +265,10 @@ private:
void DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2i& ds);
protected:
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear) override;
public:
GSDeviceOGL();
virtual ~GSDeviceOGL();
@@ -317,10 +321,8 @@ public:
// BlitRect *does* mess with GL state, be sure to re-bind.
void BlitRect(GSTexture* sTex, const GSVector4i& r, const GSVector2i& dsize, bool at_origin, bool linear);
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) override;
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool linear = true);
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY) override;
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear = true);
void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool linear);
void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear);
void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, bool linear) override;
void UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, GSTexture* dTex, u32 dOffset, u32 dSize) override;
void ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM) override;

View File

@@ -2821,31 +2821,16 @@ void GSDeviceVK::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
dTexVK->SetState(GSTexture::State::Dirty);
}
void GSDeviceVK::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
ShaderConvert shader /* = ShaderConvert::COPY */, bool linear /* = true */)
void GSDeviceVK::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear)
{
pxAssert(HasDepthOutput(shader) == (dTex && dTex->GetType() == GSTexture::Type::DepthStencil));
pxAssert(linear ? SupportsBilinear(shader) : SupportsNearest(shader));
GL_INS("StretchRect(%d) {%d,%d} %dx%d -> {%d,%d) %dx%d", shader, int(sRect.left), int(sRect.top),
int(sRect.right - sRect.left), int(sRect.bottom - sRect.top), int(dRect.left), int(dRect.top),
int(dRect.right - dRect.left), int(dRect.bottom - dRect.top));
DoStretchRect(static_cast<GSTextureVK*>(sTex), sRect, static_cast<GSTextureVK*>(dTex), dRect,
dTex ? m_convert[static_cast<int>(shader)] : m_present[static_cast<int>(shader)], linear,
ShaderConvertWriteMask(shader) == 0xf);
}
void GSDeviceVK::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red,
bool green, bool blue, bool alpha, ShaderConvert shader)
{
GL_PUSH("ColorCopy Red:%d Green:%d Blue:%d Alpha:%d", red, green, blue, alpha);
const u32 index = (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
const bool allow_discard = (index == 0xf);
int rta_offset = (shader == ShaderConvert::RTA_CORRECTION) ? 16 : 0;
DoStretchRect(static_cast<GSTextureVK*>(sTex), sRect, static_cast<GSTextureVK*>(dTex), dRect, m_color_copy[index + rta_offset],
false, allow_discard);
const bool allow_discard = (cms.wrgba == 0xf);
VkPipeline state;
if (HasVariableWriteMask(shader))
state = m_color_copy[GetShaderIndexForMask(shader, cms.wrgba)];
else
state = dTex ? m_convert[static_cast<int>(shader)] : m_present[static_cast<int>(shader)];
DoStretchRect(static_cast<GSTextureVK*>(sTex), sRect, static_cast<GSTextureVK*>(dTex), dRect, state, linear, allow_discard);
}
void GSDeviceVK::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
@@ -2967,10 +2952,10 @@ void GSDeviceVK::DoMultiStretchRects(
BeginRenderPassForStretchRect(dTex, rc, rc, false);
SetUtilityTexture(rects[0].src, rects[0].linear ? m_linear_sampler : m_point_sampler);
pxAssert(shader == ShaderConvert::COPY || shader == ShaderConvert::RTA_CORRECTION || rects[0].wmask.wrgba == 0xf);
int rta_bit = (shader == ShaderConvert::RTA_CORRECTION) ? 16 : 0;
SetPipeline(
(rects[0].wmask.wrgba != 0xf) ? m_color_copy[rects[0].wmask.wrgba | rta_bit] : m_convert[static_cast<int>(shader)]);
pxAssert(HasVariableWriteMask(shader) || rects[0].wmask.wrgba == 0xf);
SetPipeline((rects[0].wmask.wrgba != 0xf) ?
m_color_copy[GetShaderIndexForMask(shader, rects[0].wmask.wrgba)] :
m_convert[static_cast<int>(shader)]);
if (ApplyUtilityState())
DrawIndexedPrimitive();

View File

@@ -470,6 +470,10 @@ private:
void DestroyResources();
protected:
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear) override;
public:
GSDeviceVK();
~GSDeviceVK() override;
@@ -525,10 +529,6 @@ public:
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;
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red,
bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY) override;
void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
PresentShader shader, float shaderTime, bool linear) override;
void DrawMultiStretchRects(