From 74f2f73ce65caceaa6259259d4030e57ea0c9172 Mon Sep 17 00:00:00 2001 From: TJnotJT Date: Wed, 27 May 2026 08:10:44 -0400 Subject: [PATCH] GS/HW: Use an enum instead of boolean to specify nearest/bilinear filtering. --- pcsx2/GS/Renderers/Common/GSDevice.cpp | 141 ++++++---------------- pcsx2/GS/Renderers/Common/GSDevice.h | 86 ++++++------- pcsx2/GS/Renderers/Common/GSRenderer.cpp | 8 +- pcsx2/GS/Renderers/Common/GSTexture.cpp | 2 +- pcsx2/GS/Renderers/DX11/GSDevice11.cpp | 58 ++++----- pcsx2/GS/Renderers/DX11/GSDevice11.h | 12 +- pcsx2/GS/Renderers/DX12/GSDevice12.cpp | 40 +++--- pcsx2/GS/Renderers/DX12/GSDevice12.h | 12 +- pcsx2/GS/Renderers/HW/GSHwHack.cpp | 7 +- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 30 ++--- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 72 +++++------ pcsx2/GS/Renderers/Metal/GSDeviceMTL.h | 10 +- pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm | 47 ++++---- pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp | 58 ++++----- pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h | 14 +-- pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp | 44 +++---- pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h | 14 +-- 17 files changed, 300 insertions(+), 355 deletions(-) diff --git a/pcsx2/GS/Renderers/Common/GSDevice.cpp b/pcsx2/GS/Renderers/Common/GSDevice.cpp index 7a80856ec8..8fd3d45871 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.cpp +++ b/pcsx2/GS/Renderers/Common/GSDevice.cpp @@ -804,122 +804,60 @@ GSTexture* GSDevice::CreateCompatible(GSTexture* tex, int w, int h, bool clear, } void GSDevice::DoStretchRectWithAssertions(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, - const GSVector4& dRect, ShaderConvertSelector shader, bool linear) + const GSVector4& dRect, ShaderConvertSelector shader, Filter filter) { pxAssert((dTex && dTex->IsDepthLike()) == shader.Float32Output()); - pxAssert(!(linear && shader.SupportsBilinear())); // Don't allow HW bilinear if SW bilinear is required. + pxAssert(!(filter == Biln && shader.SupportsBilinear())); // Don't allow HW bilinear if SW bilinear is required. GL_INS("StretchRect(%s) {%d,%d} %dx%d -> {%d,%d) %dx%d", ShaderConvertName(shader.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, shader, linear); + DoStretchRect(sTex, sRect, dTex, dRect, shader, filter); } void GSDevice::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear) + ShaderConvertSelector shader, Filter filter) { - DoStretchRectWithAssertions(sTex, sRect, dTex, dRect, shader, linear); + DoStretchRectWithAssertions(sTex, sRect, dTex, dRect, shader, filter); } -void GSDevice::StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvertSelector shader, bool linear) +void GSDevice::StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvertSelector shader, Filter filter) { - StretchRect(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, shader, linear); + StretchRect(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, shader, filter); } -void GSDevice::StretchRect(GSTexture* sTex, GSTexture* dTex, ShaderConvertSelector shader, bool linear) +void GSDevice::StretchRect(GSTexture* sTex, GSTexture* dTex, ShaderConvertSelector shader, Filter filter) { - StretchRect(sTex, dTex, GSVector4(dTex->GetRect()), shader, linear); + StretchRect(sTex, dTex, GSVector4(dTex->GetRect()), shader, filter); } void GSDevice::StretchRectAuto(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - bool linear, u32 src_bpp, u32 dst_bpp) + Filter filter, u32 src_bpp, u32 dst_bpp) { ShaderConvertSelector shader = GetConvertShader(sTex, dTex, src_bpp, dst_bpp); - if (shader.SupportsBilinear() && linear) + if (shader.SupportsBilinear() && filter == Biln) { // Bilinear is emulated in the shader. - shader.SetBiln(true); - linear = false; + shader.SetFilter(Biln); + filter = Nearest; } - StretchRect(sTex, sRect, dTex, dRect, shader, linear); + StretchRect(sTex, sRect, dTex, dRect, shader, filter); } -void GSDevice::StretchRectAuto(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, bool linear, u32 src_bpp, u32 dst_bpp) +void GSDevice::StretchRectAuto(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, Filter filter, u32 src_bpp, u32 dst_bpp) { - StretchRectAuto(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, linear, src_bpp, dst_bpp); - } - -void GSDevice::StretchRectAuto(GSTexture* sTex, GSTexture* dTex, bool linear, u32 src_bpp, u32 dst_bpp) -{ - StretchRectAuto(sTex, dTex, GSVector4(dTex->GetRect()), linear, src_bpp, dst_bpp); + StretchRectAuto(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, filter, src_bpp, dst_bpp); } -void GSDevice::StretchRectNearest(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader) +void GSDevice::StretchRectAuto(GSTexture* sTex, GSTexture* dTex, Filter filter, u32 src_bpp, u32 dst_bpp) { - StretchRect(sTex, sRect, dTex, dRect, shader, false); -} - -void GSDevice::StretchRectNearest(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvertSelector shader) -{ - StretchRectNearest(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, shader); -} - -void GSDevice::StretchRectNearest(GSTexture* sTex, GSTexture* dTex, ShaderConvertSelector shader) -{ - StretchRectNearest(sTex, dTex, GSVector4(dTex->GetRect()), shader); -} - -void GSDevice::StretchRectAutoNearest(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, u32 src_bpp, u32 dst_bpp) -{ - StretchRectAuto(sTex, sRect, dTex, dRect, false, src_bpp, dst_bpp); -} - -void GSDevice::StretchRectAutoNearest(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, u32 src_bpp, u32 dst_bpp) -{ - StretchRectAutoNearest(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, src_bpp, dst_bpp); -} - -void GSDevice::StretchRectAutoNearest(GSTexture* sTex, GSTexture* dTex, u32 src_bpp, u32 dst_bpp) -{ - StretchRectAutoNearest(sTex, dTex, GSVector4(dTex->GetRect()), src_bpp, dst_bpp); -} - -void GSDevice::StretchRectBiln(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader) -{ - StretchRect(sTex, sRect, dTex, dRect, shader, true); -} - -void GSDevice::StretchRectBiln(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvertSelector shader) -{ - StretchRectBiln(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, shader); -} - -void GSDevice::StretchRectBiln(GSTexture* sTex, GSTexture* dTex, ShaderConvertSelector shader) -{ - StretchRectBiln(sTex, dTex, GSVector4(dTex->GetRect()), shader); -} - -void GSDevice::StretchRectAutoBiln(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, u32 src_bpp, u32 dst_bpp) -{ - StretchRectAuto(sTex, sRect, dTex, dRect, true, src_bpp, dst_bpp); -} - -void GSDevice::StretchRectAutoBiln(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, u32 src_bpp, u32 dst_bpp) -{ - StretchRectAutoBiln(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, src_bpp, dst_bpp); -} - -void GSDevice::StretchRectAutoBiln(GSTexture* sTex, GSTexture* dTex, u32 src_bpp, u32 dst_bpp) -{ - StretchRectAutoBiln(sTex, dTex, GSVector4(dTex->GetRect()), src_bpp, dst_bpp); + StretchRectAuto(sTex, dTex, GSVector4(dTex->GetRect()), filter, src_bpp, dst_bpp); } void GSDevice::StretchRectAutoMask(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, u32 src_bpp, u32 dst_bpp) { - StretchRect(sTex, sRect, dTex, dRect, GetConvertShaderMask(sTex, dTex, src_bpp, dst_bpp, red, green, blue, alpha), false); + StretchRect(sTex, sRect, dTex, dRect, GetConvertShaderMask(sTex, dTex, src_bpp, dst_bpp, red, green, blue, alpha), Nearest); } void GSDevice::StretchRectAutoMask(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, u32 src_bpp, u32 dst_bpp) @@ -939,7 +877,8 @@ void GSDevice::DrawMultiStretchRects( for (u32 i = 0; i < num_rects; i++) { const MultiStretchRect& sr = rects[i]; - g_gs_device->StretchRect(sr.src, sr.src_rect, dTex, sr.dst_rect, shader.SetMask(rects[0].wmask.wrgba).SetBiln(sr.linear)); + g_gs_device->StretchRect(sr.src, sr.src_rect, dTex, sr.dst_rect, + shader.SetMask(rects[0].wmask.wrgba).SetFilter(sr.filter), sr.filter); } } @@ -947,7 +886,7 @@ void GSDevice::SortMultiStretchRects(MultiStretchRect* rects, u32 num_rects) { // Depending on num_rects, insertion sort may be better here. std::sort(rects, rects + num_rects, [](const MultiStretchRect& lhs, const MultiStretchRect& rhs) { - return lhs.src < rhs.src || lhs.linear < rhs.linear; + return lhs.src < rhs.src || lhs.filter < rhs.filter; }); } @@ -973,7 +912,7 @@ void GSDevice::ClearCurrent() void GSDevice::Merge(GSTexture* sTex[3], GSVector4* sRect, GSVector4* dRect, const GSVector2i& fs, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c) { if (ResizeRenderTarget(&m_merge, fs.x, fs.y, false, false)) - DoMerge(sTex, sRect, m_merge, dRect, PMODE, EXTBUF, c, GSConfig.PCRTCOffsets); + DoMerge(sTex, sRect, m_merge, dRect, PMODE, EXTBUF, c, BilnIf(GSConfig.PCRTCOffsets)); m_current = m_merge; } @@ -984,7 +923,7 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse float offset = yoffset * static_cast(field); offset = GSConfig.DisableInterlaceOffset ? 0.0f : offset; - auto do_interlace = [this](GSTexture* sTex, GSTexture* dTex, ShaderInterlace shader, bool linear, float yoffset, int bufIdx) { + auto do_interlace = [this](GSTexture* sTex, GSTexture* dTex, ShaderInterlace shader, Filter filter, float yoffset, int bufIdx) { const GSVector2i ds_i = dTex->GetSize(); const GSVector2 ds = GSVector2(static_cast(ds_i.x), static_cast(ds_i.y)); @@ -1005,28 +944,28 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse GSVector4(static_cast(bufIdx), 1.0f / ds.y, ds.y, MAD_SENSITIVITY) }; - GL_PUSH("DoInterlace %dx%d Shader:%d Linear:%d", ds_i.x, ds_i.y, static_cast(shader), linear); - DoInterlace(sTex, sRect, dTex, dRect, shader, linear, cb); + GL_PUSH("DoInterlace %dx%d Shader:%d Filter:%d", ds_i.x, ds_i.y, static_cast(shader), filter); + DoInterlace(sTex, sRect, dTex, dRect, shader, filter, cb); }; switch (mode) { case 0: // Weave ResizeRenderTarget(&m_weavebob, ds.x, ds.y, true, false); - do_interlace(m_merge, m_weavebob, ShaderInterlace::WEAVE, false, offset, field); + do_interlace(m_merge, m_weavebob, ShaderInterlace::WEAVE, Nearest, offset, field); m_current = m_weavebob; break; case 1: // Bob // Field is reversed here as we are countering the bounce. ResizeRenderTarget(&m_weavebob, ds.x, ds.y, true, false); - do_interlace(m_merge, m_weavebob, ShaderInterlace::BOB, true, yoffset * (1 - field), 0); + do_interlace(m_merge, m_weavebob, ShaderInterlace::BOB, Biln, yoffset * (1 - field), 0); m_current = m_weavebob; break; case 2: // Blend ResizeRenderTarget(&m_weavebob, ds.x, ds.y, true, false); - do_interlace(m_merge, m_weavebob, ShaderInterlace::WEAVE, false, offset, field); + do_interlace(m_merge, m_weavebob, ShaderInterlace::WEAVE, Nearest, offset, field); ResizeRenderTarget(&m_blend, ds.x, ds.y, true, false); - do_interlace(m_weavebob, m_blend, ShaderInterlace::BLEND, false, 0, 0); + do_interlace(m_weavebob, m_blend, ShaderInterlace::BLEND, Biln, 0, 0); m_current = m_blend; break; case 3: // FastMAD Motion Adaptive Deinterlacing @@ -1035,9 +974,9 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse bufIdx |= field; bufIdx &= 3; ResizeRenderTarget(&m_mad, ds.x, ds.y * 2.0f, true, false); - do_interlace(m_merge, m_mad, ShaderInterlace::MAD_BUFFER, false, offset, bufIdx); + do_interlace(m_merge, m_mad, ShaderInterlace::MAD_BUFFER, Nearest, offset, bufIdx); ResizeRenderTarget(&m_weavebob, ds.x, ds.y, true, false); - do_interlace(m_mad, m_weavebob, ShaderInterlace::MAD_RECONSTRUCT, false, 0, bufIdx); + do_interlace(m_mad, m_weavebob, ShaderInterlace::MAD_RECONSTRUCT, Nearest, 0, bufIdx); m_current = m_weavebob; break; default: @@ -1094,7 +1033,7 @@ void GSDevice::Resize(int width, int height) { const GSVector4 sRect(0, 0, 1, 1); const GSVector4 dRect(0, 0, s.x, s.y); - StretchRectAutoNearest(m_current, sRect, dTex, dRect); + StretchRectAuto(m_current, sRect, dTex, dRect, Nearest); m_current = dTex; } } @@ -1125,7 +1064,7 @@ bool GSDevice::ResizeRenderTarget(GSTexture** t, int w, int h, bool preserve_con { constexpr GSVector4 sRect = GSVector4::cxpr(0, 0, 1, 1); const GSVector4 dRect = GSVector4(orig_tex->GetRect()); - StretchRectBiln(orig_tex, sRect, new_tex, dRect, ShaderConvert::COPY); + StretchRect(orig_tex, sRect, new_tex, dRect, ShaderConvert::COPY, Biln); } if (orig_tex) @@ -1148,7 +1087,7 @@ void GSDevice::BeginDSAsRT(GSTexture* ds, const GSVector4i& drawarea) m_ds_as_rt = g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::DepthColor, false, true); const GSVector4 dRect(drawarea); const GSVector4 sRect(dRect.x / w, dRect.y / h, dRect.z / w, dRect.w / h); - StretchRectAutoNearest(ds, sRect, m_ds_as_rt, dRect); + StretchRectAuto(ds, sRect, m_ds_as_rt, dRect, Nearest); } void GSDevice::EndDSAsRT() @@ -1830,20 +1769,20 @@ static constexpr ShaderConvertSelector GetRemappedShader(u32 idx) { ShaderConvert convert = static_cast(idx >> 2); bool depth_out = (idx >> 0) & 1; - bool biln = (idx >> 1) & 1; - return ShaderConvertSelector(convert, 0xf, depth_out, biln); + Filter filter = static_cast((idx >> 1) & 1); + return ShaderConvertSelector(convert, 0xf, depth_out, filter); } static constexpr bool RemapIndexIsValid(u32 idx) { ShaderConvert convert = static_cast(idx >> 2); bool depth_out = (idx >> 0) & 1; - bool biln = (idx >> 1) & 1; - if (HasVariableWriteMask(convert) && !depth_out && !biln) + Filter filter = static_cast((idx >> 1) & 1); + if (HasVariableWriteMask(convert) && !depth_out && filter == Nearest) return false; // Handled as variable write mask if (depth_out && !HasFloat32Output(convert)) return false; - if (biln && !SupportsBilinear(convert)) + if (filter == Biln && !SupportsBilinear(convert)) return false; return true; } diff --git a/pcsx2/GS/Renderers/Common/GSDevice.h b/pcsx2/GS/Renderers/Common/GSDevice.h index b8db94914d..5d6edecaab 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.h +++ b/pcsx2/GS/Renderers/Common/GSDevice.h @@ -15,6 +15,20 @@ #include #include +enum class Filter +{ + Nearest = 0, + Biln = 1, +}; + +static inline constexpr Filter Nearest = Filter::Nearest; +static inline constexpr Filter Biln = Filter::Biln; + +static inline constexpr Filter BilnIf(bool biln) +{ + return biln ? Biln : Nearest; +} + enum class ShaderConvert { COPY = 0, @@ -249,7 +263,7 @@ class ShaderConvertSelector u32 shader : 8; // Main shader u32 mask : 8; // Variable color mask u32 depth_out : 1; // Depth texture output - u32 biln : 1; // Shader bilinear (HW bilinear is specified separately) + u32 filter : 1; // Shader filter (HW filter is specified separately) }; u32 key; @@ -259,10 +273,10 @@ class ShaderConvertSelector public: constexpr ShaderConvertSelector(ShaderConvert shader = ShaderConvert::COPY, u8 mask = 0xf, - bool depth_out = false, bool biln = false) + bool depth_out = false, Filter filter = Filter::Nearest) : fields { static_cast(shader) } { - *this = SetMask(mask).SetDepthOutput(depth_out).SetBiln(biln); + *this = SetMask(mask).SetDepthOutput(depth_out).SetFilter(filter); } constexpr ShaderConvert Shader() const @@ -280,9 +294,19 @@ public: return ShaderConvertWriteMask(Shader()); } + constexpr Filter GetFilter() const + { + return static_cast(fields.filter); + } + constexpr bool Biln() const { - return fields.biln; + return GetFilter() == Filter::Biln; + } + + constexpr bool Nearest() const + { + return GetFilter() == Filter::Nearest; } constexpr bool SupportsBilinear() const @@ -364,10 +388,10 @@ public: return tmp; } - constexpr ShaderConvertSelector SetBiln(bool biln) const + constexpr ShaderConvertSelector SetFilter(Filter filter) const { ShaderConvertSelector tmp = *this; - tmp.fields.biln = SupportsBilinear() && biln; + tmp.fields.filter = static_cast(SupportsBilinear() ? filter : Filter::Nearest); return tmp; } @@ -399,10 +423,10 @@ public: u32 Index() const { - if (VariableWriteMask() && !fields.depth_out && !fields.biln) + if (VariableWriteMask() && !fields.depth_out && Nearest()) return GetShaderIndexForMask(Shader(), fields.mask) + NUM_REMAPPED_SHADERS; u32 remapped = INDEX_REMAP[(fields.depth_out << 0) + - (fields.biln << 1) + + (fields.filter << 1) + (fields.shader << 2)]; pxAssert(remapped < NUM_REMAPPED_SHADERS); return remapped; @@ -1317,7 +1341,7 @@ public: GSVector4 src_rect; GSVector4 dst_rect; GSTexture* src; - bool linear; + Filter filter; GSHWDrawConfig::ColorMaskSelector wmask; // 0xf for all channels by default }; @@ -1394,8 +1418,8 @@ protected: virtual GSTexture* CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format) = 0; GSTexture* FetchSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format, bool clear, bool prefer_unused_texture); - virtual void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) = 0; - virtual void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) = 0; + virtual void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const Filter filter) = 0; + virtual void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, Filter filter, const InterlaceConstantBuffer& cb) = 0; virtual void DoFXAA(GSTexture* sTex, GSTexture* dTex) = 0; virtual void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) = 0; @@ -1411,14 +1435,14 @@ protected: protected: // Entry point to the renderer-specific StretchRect code. virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear) = 0; + ShaderConvertSelector shader, Filter filter) = 0; virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, const GSVector4& dRect, - PresentShader shader, bool linear) + PresentShader shader, Filter filter) { pxFailRel("Not implemented"); } void DoStretchRectWithAssertions(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear); + ShaderConvertSelector shader, Filter filter); public: GSDevice(); virtual ~GSDevice(); @@ -1550,36 +1574,16 @@ public: virtual void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) = 0; // StretchRect - all options - void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvertSelector shader = ShaderConvert::COPY, bool linear = false); - void StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvertSelector shader = ShaderConvert::COPY, bool linear = false); - void StretchRect(GSTexture* sTex, GSTexture* dTex, ShaderConvertSelector shader = ShaderConvert::COPY, bool linear = false); + void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvertSelector shader, Filter filter); + void StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvertSelector shader, Filter filter); + void StretchRect(GSTexture* sTex, GSTexture* dTex, ShaderConvertSelector shader, Filter filter); // StretchRect - infer shader based on formats - void StretchRectAuto(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool linear, + void StretchRectAuto(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, Filter filter, u32 src_bpp = 32, u32 dst_bpp = 32); - void StretchRectAuto(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, bool linear, + void StretchRectAuto(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, Filter filter, u32 src_bpp = 32, u32 dst_bpp = 32); - void StretchRectAuto(GSTexture* sTex, GSTexture* dTex, bool linear, u32 src_bpp = 32, u32 dst_bpp = 32); - - // StretchRect - nearest filter - void StretchRectNearest(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvertSelector shader = ShaderConvert::COPY); - void StretchRectNearest(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvertSelector shader = ShaderConvert::COPY); - void StretchRectNearest(GSTexture* sTex, GSTexture* dTex, ShaderConvertSelector shader = ShaderConvert::COPY); - - // StretchRect - nearest filter, infer shader based on formats - void StretchRectAutoNearest(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, u32 src_bpp = 32, u32 dst_bpp = 32); - void StretchRectAutoNearest(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, u32 src_bpp = 32, u32 dst_bpp = 32); - void StretchRectAutoNearest(GSTexture* sTex, GSTexture* dTex, u32 src_bpp = 32, u32 dst_bpp = 32); - - // StretchRect - linear filter - void StretchRectBiln(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvertSelector shader = ShaderConvert::COPY); - void StretchRectBiln(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvertSelector shader = ShaderConvert::COPY); - void StretchRectBiln(GSTexture* sTex, GSTexture* dTex, ShaderConvertSelector shader = ShaderConvert::COPY); - - // StretchRect - linear filter, infer shader based on formats - void StretchRectAutoBiln(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, u32 src_bpp = 32, u32 dst_bpp = 32); - void StretchRectAutoBiln(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, u32 src_bpp = 32, u32 dst_bpp = 32); - void StretchRectAutoBiln(GSTexture* sTex, GSTexture* dTex, u32 src_bpp = 32, u32 dst_bpp = 32); + void StretchRectAuto(GSTexture* sTex, GSTexture* dTex, Filter filter, u32 src_bpp = 32, u32 dst_bpp = 32); // StretchRect - nearest filter, infer shader based on formats, specify channel mask void StretchRectAutoMask(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, u32 src_bpp = 32, u32 dst_bpp = 32); @@ -1587,7 +1591,7 @@ public: void StretchRectAutoMask(GSTexture* sTex, GSTexture* dTex, bool red, bool green, bool blue, bool alpha, u32 src_bpp = 32, u32 dst_bpp = 32); /// Performs a screen blit for display. If dTex is null, it assumes you are writing to the system framebuffer/swap chain. - virtual void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, bool linear) = 0; + virtual void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, Filter filter) = 0; /// Same as doing StretchRect for each item, except tries to batch together rectangles in as few draws as possible. /// The provided list should be sorted by texture, the implementations only check if it's the same as the last. diff --git a/pcsx2/GS/Renderers/Common/GSRenderer.cpp b/pcsx2/GS/Renderers/Common/GSRenderer.cpp index d841789f1e..c4e8dae68a 100644 --- a/pcsx2/GS/Renderers/Common/GSRenderer.cpp +++ b/pcsx2/GS/Renderers/Common/GSRenderer.cpp @@ -695,7 +695,7 @@ void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame) const float shader_time = static_cast(Common::Timer::ConvertValueToSeconds(current_time - m_shader_time_start)); g_gs_device->PresentRect(current, src_uv, nullptr, draw_rect, - s_tv_shader_indices[GSConfig.TVShader], shader_time, GSConfig.LinearPresent != GSPostBilinearMode::Off); + s_tv_shader_indices[GSConfig.TVShader], shader_time, BilnIf(GSConfig.LinearPresent != GSPostBilinearMode::Off)); } EndPresentFrame(); @@ -818,7 +818,7 @@ void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame) GSTexture* temp = g_gs_device->CreateRenderTarget(size.x, size.y, GSTexture::Format::Color, false); if (temp) { - g_gs_device->StretchRect(current, temp, GSVector4(0, 0, size.x, size.y)); + g_gs_device->StretchRect(current, temp, GSVector4(0, 0, size.x, size.y), ShaderConvert::COPY, Biln); GSCapture::DeliverVideoFrame(temp); g_gs_device->Recycle(temp); } @@ -972,7 +972,7 @@ void GSRenderer::PresentCurrentFrame() const float shader_time = static_cast(Common::Timer::ConvertValueToSeconds(current_time - m_shader_time_start)); g_gs_device->PresentRect(current, src_uv, nullptr, draw_rect, - s_tv_shader_indices[GSConfig.TVShader], shader_time, GSConfig.LinearPresent != GSPostBilinearMode::Off); + s_tv_shader_indices[GSConfig.TVShader], shader_time, BilnIf(GSConfig.LinearPresent != GSPostBilinearMode::Off)); } EndPresentFrame(); @@ -1086,7 +1086,7 @@ bool GSRenderer::SaveSnapshotToMemory(u32 window_width, u32 window_height, bool if (dl) { const GSVector4i rc(0, 0, draw_width, draw_height); - g_gs_device->StretchRect(current, src_uv, rt, GSVector4(rc), ShaderConvert::TRANSPARENCY_FILTER); + g_gs_device->StretchRect(current, src_uv, rt, GSVector4(rc), ShaderConvert::TRANSPARENCY_FILTER, Biln); dl->CopyFromTexture(rc, rt, rc, 0); dl->Flush(); diff --git a/pcsx2/GS/Renderers/Common/GSTexture.cpp b/pcsx2/GS/Renderers/Common/GSTexture.cpp index 488f4ffafc..1a115c1f6d 100644 --- a/pcsx2/GS/Renderers/Common/GSTexture.cpp +++ b/pcsx2/GS/Renderers/Common/GSTexture.cpp @@ -29,7 +29,7 @@ bool GSTexture::Save(const std::string& fn) return false; } - g_gs_device->StretchRectAutoNearest(this, temp); + g_gs_device->StretchRectAuto(this, temp, Nearest); const bool res = temp->Save(fn); g_gs_device->Recycle(temp); return res; diff --git a/pcsx2/GS/Renderers/DX11/GSDevice11.cpp b/pcsx2/GS/Renderers/DX11/GSDevice11.cpp index 64e7b6ee56..a081a7ef87 100644 --- a/pcsx2/GS/Renderers/DX11/GSDevice11.cpp +++ b/pcsx2/GS/Renderers/DX11/GSDevice11.cpp @@ -1409,20 +1409,20 @@ void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, } void GSDevice11::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear) + ShaderConvertSelector shader, Filter filter) { const u8 mask = shader.Mask(); shader = shader.SetMask(); // Mask is handled separately from program. - linear &= !shader.SupportsBilinear(); // Don't allow HW bilinear if SW bilinear is needed. - DoStretchRect(sTex, sRect, dTex, dRect, GetConvertShader(shader), nullptr, m_convert.bs[mask].get(), linear); + filter = shader.SupportsBilinear() ? Nearest : filter; // Don't allow HW bilinear if SW bilinear is needed. + DoStretchRect(sTex, sRect, dTex, dRect, GetConvertShader(shader), nullptr, m_convert.bs[mask].get(), filter); } -void GSDevice11::DoStretchRect(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, Filter filter) { - DoStretchRect(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(), filter); } -void GSDevice11::DoStretchRect(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, Filter filter) { g_perfmon.Put(GSPerfMon::TextureCopies, 1); @@ -1483,7 +1483,7 @@ void GSDevice11::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTextur // ps PSSetShaderResource(0, sTex); - PSSetSamplerState(linear ? m_convert.ln.get() : m_convert.pt.get()); + PSSetSamplerState(filter == Biln ? m_convert.ln.get() : m_convert.pt.get()); PSSetShader(ps, ps_cb); // draw @@ -1491,7 +1491,7 @@ void GSDevice11::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTextur DrawPrimitive(); } -void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, bool linear) +void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, Filter filter) { g_perfmon.Put(GSPerfMon::TextureCopies, 1); @@ -1548,7 +1548,7 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* // ps PSSetShaderResource(0, sTex); - PSSetSamplerState(linear ? m_convert.ln.get() : m_convert.pt.get()); + PSSetSamplerState(filter == Biln ? m_convert.ln.get() : m_convert.pt.get()); PSSetShader(m_present.ps[static_cast(shader)].get(), m_present.ps_cb.get()); // draw @@ -1571,7 +1571,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; - DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, GetConvertShader(shader), m_merge.cb.get(), nullptr, false); + DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, GetConvertShader(shader), m_merge.cb.get(), nullptr, Nearest); } void GSDevice11::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM) @@ -1590,7 +1590,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; - DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, GetConvertShader(shader), m_merge.cb.get(), nullptr, false); + DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, GetConvertShader(shader), m_merge.cb.get(), nullptr, Nearest); } void GSDevice11::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 downsample_factor, const GSVector2i& clamp_min, const GSVector4& dRect) @@ -1610,7 +1610,7 @@ void GSDevice11::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 UpdateSubresource(m_merge.cb.get(), &cb, &m_merge.cb_uniforms, sizeof(cb)); const ShaderConvert shader = ShaderConvert::DOWNSAMPLE_COPY; - DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, GetConvertShader(shader), m_merge.cb.get(), nullptr, false); + DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, GetConvertShader(shader), m_merge.cb.get(), nullptr, Nearest); } void GSDevice11::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvertSelector shader) @@ -1628,7 +1628,7 @@ void GSDevice11::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_re const GSVector2 ds(static_cast(dTex->GetWidth()), static_cast(dTex->GetHeight())); GSTexture* last_tex = rects[0].src; - bool last_linear = rects[0].linear; + Filter last_filter = rects[0].filter; u8 last_wmask = rects[0].wmask.wrgba; u32 first = 0; @@ -1636,7 +1636,7 @@ void GSDevice11::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_re for (u32 i = 1; i < num_rects; i++) { - if (rects[i].src == last_tex && rects[i].linear == last_linear && rects[i].wmask.wrgba == last_wmask) + if (rects[i].src == last_tex && rects[i].filter == last_filter && rects[i].wmask.wrgba == last_wmask) { count++; continue; @@ -1644,7 +1644,7 @@ void GSDevice11::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_re DoMultiStretchRects(rects + first, count, ds); last_tex = rects[i].src; - last_linear = rects[i].linear; + last_filter = rects[i].filter; last_wmask = rects[i].wmask.wrgba; first += count; count = 1; @@ -1699,14 +1699,14 @@ void GSDevice11::DoMultiStretchRects(const MultiStretchRect* rects, u32 num_rect CommitClear(rects[0].src); PSSetShaderResource(0, rects[0].src); - PSSetSamplerState(rects[0].linear ? m_convert.ln.get() : m_convert.pt.get()); + PSSetSamplerState(rects[0].filter == Biln ? m_convert.ln.get() : m_convert.pt.get()); OMSetBlendState(m_convert.bs[rects[0].wmask.wrgba].get(), 0.0f); DrawIndexedPrimitive(); } -void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) +void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const Filter filter) { const GSVector4 full_r(0.0f, 0.0f, 1.0f, 1.0f); const bool feedback_write_2 = PMODE.EN2 && sTex[2] != nullptr && EXTBUF.FBIN == 1; @@ -1729,14 +1729,14 @@ void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, { // 2nd output is enabled and selected. Copy it to destination so we can blend it with 1st output // Note: value outside of dRect must contains the background color (c) - StretchRect(sTex[1], sRect[1], dTex, PMODE.SLBG ? dRect[2] : dRect[1], ShaderConvert::COPY, linear); + StretchRect(sTex[1], sRect[1], dTex, PMODE.SLBG ? dRect[2] : dRect[1], ShaderConvert::COPY, filter); } // Save 2nd output if (feedback_write_2) { DoStretchRect(dTex, full_r, sTex[2], dRect[2], GetConvertShader(ShaderConvert::YUV), - m_merge.cb.get(), nullptr, linear); + m_merge.cb.get(), nullptr, filter); } // Restore background color to process the normal merge @@ -1746,21 +1746,21 @@ void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, if (sTex[0]) { // 1st output is enabled. It must be blended - DoStretchRect(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(), filter); } if (feedback_write_1) { DoStretchRect(dTex, full_r, sTex[2], dRect[2], GetConvertShader(ShaderConvert::YUV), - m_merge.cb.get(), nullptr, linear); + m_merge.cb.get(), nullptr, filter); } } -void GSDevice11::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) +void GSDevice11::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, Filter filter, const InterlaceConstantBuffer& cb) { UpdateSubresource(m_interlace.cb.get(), &cb, &m_interlace.cb_uniforms, sizeof(cb)); - DoStretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast(shader)].get(), m_interlace.cb.get(), linear); + DoStretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast(shader)].get(), m_interlace.cb.get(), filter); } void GSDevice11::DoFXAA(GSTexture* sTex, GSTexture* dTex) @@ -1786,7 +1786,7 @@ void GSDevice11::DoFXAA(GSTexture* sTex, GSTexture* dTex) return; } - DoStretchRect(sTex, sRect, dTex, dRect, m_fxaa_ps.get(), nullptr, true); + DoStretchRect(sTex, sRect, dTex, dRect, m_fxaa_ps.get(), nullptr, Biln); } void GSDevice11::DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) @@ -1798,7 +1798,7 @@ void GSDevice11::DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float para UpdateSubresource(m_shadeboost.cb.get(), params, &m_shadeboost.cb_uniforms, sizeof(float) * 4); - DoStretchRect(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(), Nearest); } void GSDevice11::SetupVS(VSSelector sel, const GSHWDrawConfig::VSConstantBuffer* cb) @@ -2835,7 +2835,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config) const GSVector2i size = config.rt->GetSize(); const GSVector4 dRect(config.colclip_update_area); const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy(); - StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false); + StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, Nearest); Recycle(colclip_rt); g_gs_device->SetColorClipTexture(nullptr); @@ -2863,7 +2863,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config) const GSVector4 dRect = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea); const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy(); - StretchRect(config.rt, sRect, colclip_rt, dRect, ShaderConvert::COLCLIP_INIT, false); + StretchRect(config.rt, sRect, colclip_rt, dRect, ShaderConvert::COLCLIP_INIT, Nearest); } } @@ -2879,7 +2879,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config) } 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(config.datm)].get(), nullptr, false); + primid_texture, GSVector4(config.drawarea), m_date.primid_init_ps[static_cast(config.datm)].get(), nullptr, Nearest); } else if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil || (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne && !need_barrier)) @@ -3048,7 +3048,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config) const GSVector2i size = config.rt->GetSize(); const GSVector4 dRect(config.colclip_update_area); const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy(); - StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false); + StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, Nearest); Recycle(colclip_rt); g_gs_device->SetColorClipTexture(nullptr); diff --git a/pcsx2/GS/Renderers/DX11/GSDevice11.h b/pcsx2/GS/Renderers/DX11/GSDevice11.h index c57cd129ce..09cba5b515 100644 --- a/pcsx2/GS/Renderers/DX11/GSDevice11.h +++ b/pcsx2/GS/Renderers/DX11/GSDevice11.h @@ -102,8 +102,8 @@ private: void PopTimestampQuery(); void KickTimestampQuery(); - void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) override; - void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) override; + void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const Filter filter) override; + void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, Filter filter, const InterlaceConstantBuffer& cb) override; void DoFXAA(GSTexture* sTex, GSTexture* dTex) override; void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) override; @@ -279,7 +279,7 @@ private: protected: virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear) override; + ShaderConvertSelector shader, Filter filter) override; public: GSDevice11(); ~GSDevice11() override; @@ -331,9 +331,9 @@ public: 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, 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 DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, Filter filter); + void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, Filter filter); + void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, Filter filter) 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; void FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 downsample_factor, const GSVector2i& clamp_min, const GSVector4& dRect) override; diff --git a/pcsx2/GS/Renderers/DX12/GSDevice12.cpp b/pcsx2/GS/Renderers/DX12/GSDevice12.cpp index c85e994870..f4bd0cb22b 100644 --- a/pcsx2/GS/Renderers/DX12/GSDevice12.cpp +++ b/pcsx2/GS/Renderers/DX12/GSDevice12.cpp @@ -1669,24 +1669,24 @@ void GSDevice12::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, } void GSDevice12::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear) + ShaderConvertSelector shader, Filter filter) { pxAssert(dTex); - linear &= !shader.SupportsBilinear(); // Don't allow HW bilinear if SW bilinear is needed. + filter = shader.SupportsBilinear() ? Nearest : filter; // Don't allow HW bilinear if SW bilinear is needed. const bool allow_discard = (shader.Mask() == 0xf); DoStretchRect(static_cast(sTex), sRect, static_cast(dTex), dRect, - GetConvertPipeline(shader), linear, allow_discard); + GetConvertPipeline(shader), filter, allow_discard); } void GSDevice12::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, const GSVector4& dRect, - PresentShader shader, bool linear) + PresentShader shader, Filter filter) { DoStretchRect(static_cast(sTex), sRect, nullptr, dRect, - m_present[static_cast(shader)].get(), linear, true); + m_present[static_cast(shader)].get(), filter, true); } void GSDevice12::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - PresentShader shader, float shaderTime, bool linear) + PresentShader shader, float shaderTime, Filter filter) { DisplayConstantBuffer cb; cb.SetSource(sRect, sTex->GetSize()); @@ -1696,7 +1696,7 @@ void GSDevice12::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* SetUtilityPushConstants(&cb, sizeof(cb)); DoStretchRect(static_cast(sTex), sRect, static_cast(dTex), dRect, - m_present[static_cast(shader)].get(), linear, true); + m_present[static_cast(shader)].get(), filter, true); } void GSDevice12::UpdateCLUTTexture( @@ -1717,7 +1717,7 @@ void GSDevice12::UpdateCLUTTexture( const GSVector4 dRect(0, 0, dSize, 1); const ShaderConvert shader = (dSize == 16) ? ShaderConvert::CLUT_4 : ShaderConvert::CLUT_8; DoStretchRect(static_cast(sTex), GSVector4::zero(), static_cast(dTex), dRect, - GetConvertPipeline(shader), false, true); + GetConvertPipeline(shader), Nearest, true); } void GSDevice12::ConvertToIndexedTexture( @@ -1739,7 +1739,7 @@ void GSDevice12::ConvertToIndexedTexture( const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight()); const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I; DoStretchRect(static_cast(sTex), GSVector4::zero(), static_cast(dTex), dRect, - GetConvertPipeline(shader), false, true); + GetConvertPipeline(shader), Nearest, true); } void GSDevice12::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 downsample_factor, const GSVector2i& clamp_min, const GSVector4& dRect) @@ -1762,14 +1762,14 @@ void GSDevice12::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 //const GSVector4 dRect = GSVector4(dTex->GetRect()); const ShaderConvert shader = ShaderConvert::DOWNSAMPLE_COPY; DoStretchRect(static_cast(sTex), GSVector4::zero(), static_cast(dTex), dRect, - GetConvertPipeline(shader), false, true); + GetConvertPipeline(shader), Nearest, true); } void GSDevice12::DrawMultiStretchRects( const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvertSelector shader) { GSTexture* last_tex = rects[0].src; - bool last_linear = rects[0].linear; + Filter last_filter = rects[0].filter; u8 last_wmask = rects[0].wmask.wrgba; u32 first = 0; @@ -1790,7 +1790,7 @@ void GSDevice12::DrawMultiStretchRects( for (u32 i = 1; i < num_rects; i++) { - if (rects[i].src == last_tex && rects[i].linear == last_linear && rects[i].wmask.wrgba == last_wmask) + if (rects[i].src == last_tex && rects[i].filter == last_filter && rects[i].wmask.wrgba == last_wmask) { count++; continue; @@ -1798,7 +1798,7 @@ void GSDevice12::DrawMultiStretchRects( DoMultiStretchRects(rects + first, count, static_cast(dTex), shader); last_tex = rects[i].src; - last_linear = rects[i].linear; + last_filter = rects[i].filter; last_wmask = rects[i].wmask.wrgba; first += count; count = 1; @@ -1877,7 +1877,7 @@ void GSDevice12::DoMultiStretchRects( if (!InRenderPass()) BeginRenderPassForStretchRect(dTex, rc, rc, false); SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - SetUtilityTexture(rects[0].src, rects[0].linear ? m_linear_sampler_cpu : m_point_sampler_cpu); + SetUtilityTexture(rects[0].src, rects[0].filter == Biln ? m_linear_sampler_cpu : m_point_sampler_cpu); SetPipeline(GetConvertPipeline(shader.SetMask(rects[0].wmask.wrgba))); @@ -1910,7 +1910,7 @@ void GSDevice12::BeginRenderPassForStretchRect( } void GSDevice12::DoStretchRect(GSTexture12* sTex, const GSVector4& sRect, GSTexture12* dTex, const GSVector4& dRect, - const ID3D12PipelineState* pipeline, bool linear, bool allow_discard) + const ID3D12PipelineState* pipeline, Filter filter, bool allow_discard) { if (sTex->GetResourceState() != GSTexture12::ResourceState::PixelShaderResource) { @@ -1920,7 +1920,7 @@ void GSDevice12::DoStretchRect(GSTexture12* sTex, const GSVector4& sRect, GSText } SetUtilityRootSignature(); - SetUtilityTexture(sTex, linear ? m_linear_sampler_cpu : m_point_sampler_cpu); + SetUtilityTexture(sTex, filter == Biln ? m_linear_sampler_cpu : m_point_sampler_cpu); SetPipeline(pipeline); const bool is_present = (!dTex); @@ -1974,7 +1974,7 @@ void GSDevice12::DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, } void GSDevice12::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, - const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) + const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const Filter filter) { GL_PUSH("DoMerge"); @@ -1982,7 +1982,7 @@ void GSDevice12::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, const bool feedback_write_2 = PMODE.EN2 && sTex[2] != nullptr && EXTBUF.FBIN == 1; const bool feedback_write_1 = PMODE.EN1 && sTex[2] != nullptr && EXTBUF.FBIN == 0; const bool feedback_write_2_but_blend_bg = feedback_write_2 && PMODE.SLBG == 1; - const D3D12DescriptorHandle& sampler = linear ? m_linear_sampler_cpu : m_point_sampler_cpu; + const D3D12DescriptorHandle& sampler = filter == Biln ? m_linear_sampler_cpu : m_point_sampler_cpu; // Merge the 2 source textures (sTex[0],sTex[1]). Final results go to dTex. Feedback write will go to sTex[2]. // If either 2nd output is disabled or SLBG is 1, a background color will be used. // Note: background color is also used when outside of the unit rectangle area @@ -2109,7 +2109,7 @@ void GSDevice12::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, } void GSDevice12::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) + ShaderInterlace shader, Filter filter, const InterlaceConstantBuffer& cb) { static_cast(dTex)->TransitionToState(GSTexture12::ResourceState::RenderTarget); @@ -2119,7 +2119,7 @@ void GSDevice12::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* EndRenderPass(); OMSetRenderTargets(dTex, nullptr, nullptr, clamped_rc); SetUtilityRootSignature(); - SetUtilityTexture(sTex, linear ? m_linear_sampler_cpu : m_point_sampler_cpu); + SetUtilityTexture(sTex, filter == Biln ? m_linear_sampler_cpu : m_point_sampler_cpu); BeginRenderPassForStretchRect(static_cast(dTex), dTex->GetRect(), clamped_rc, false); SetPipeline(m_interlace[static_cast(shader)].get()); SetUtilityPushConstants(&cb, sizeof(cb)); diff --git a/pcsx2/GS/Renderers/DX12/GSDevice12.h b/pcsx2/GS/Renderers/DX12/GSDevice12.h index 8708ea5003..6b4e7e4881 100644 --- a/pcsx2/GS/Renderers/DX12/GSDevice12.h +++ b/pcsx2/GS/Renderers/DX12/GSDevice12.h @@ -397,9 +397,9 @@ private: GSTexture::Type type, int width, int height, int levels, GSTexture::Format format) override; void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, - const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) final; + const GSRegEXTBUF& EXTBUF, u32 c, const Filter filter) final; void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) final; + ShaderInterlace shader, Filter filter, const InterlaceConstantBuffer& cb) final; void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) final; void DoFXAA(GSTexture* sTex, GSTexture* dTex) final; @@ -440,9 +440,9 @@ private: protected: virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear) override; + ShaderConvertSelector shader, Filter filter) override; virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, const GSVector4& dRect, - PresentShader shader, bool linear) override; + PresentShader shader, Filter filter) override; public: GSDevice12(); ~GSDevice12() override; @@ -488,7 +488,7 @@ public: void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override; void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - PresentShader shader, float shaderTime, bool linear) override; + PresentShader shader, float shaderTime, Filter filter) 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, @@ -502,7 +502,7 @@ public: void BeginRenderPassForStretchRect( GSTexture12* dTex, const GSVector4i& dtex_rc, const GSVector4i& dst_rc, bool allow_discard = true); void DoStretchRect(GSTexture12* sTex, const GSVector4& sRect, GSTexture12* dTex, const GSVector4& dRect, - const ID3D12PipelineState* pipeline, bool linear, bool allow_discard); + const ID3D12PipelineState* pipeline, Filter filter, bool allow_discard); void DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2i& ds); void SetupDATE(GSTexture* rt, GSTexture* ds, SetDATM datm, const GSVector4i& bbox); diff --git a/pcsx2/GS/Renderers/HW/GSHwHack.cpp b/pcsx2/GS/Renderers/HW/GSHwHack.cpp index fa9582ad9c..6de02192e7 100644 --- a/pcsx2/GS/Renderers/HW/GSHwHack.cpp +++ b/pcsx2/GS/Renderers/HW/GSHwHack.cpp @@ -1142,7 +1142,7 @@ bool GSHwHack::OI_SonicUnleashed(GSRendererHW& r, GSTexture* rt, GSTexture* ds, if (!tex) return false; - g_gs_device->StretchRectAutoNearest(rt_again->m_texture, source_rect, tex, dRect); + g_gs_device->StretchRectAuto(rt_again->m_texture, source_rect, tex, dRect, Nearest); g_gs_device->Recycle(rt_again->m_texture); rt_again->m_texture = tex; @@ -1358,9 +1358,10 @@ bool GSHwHack::MV_Growlanser(GSRendererHW& r) GL_INS("MV_Growlanser: %x -> %x %dx%d", RSBP, RDBP, src->GetUnscaledWidth(), src->GetUnscaledHeight()); - g_gs_device->StretchRectAutoNearest( + g_gs_device->StretchRectAuto( src->GetTexture(), GSVector4(rc) / GSVector4(src->GetUnscaledSize()).xyxy(), - dst->GetTexture(), GSVector4(rc) * GSVector4(dst->GetScale())); + dst->GetTexture(), GSVector4(rc) * GSVector4(dst->GetScale()), + Nearest); s_last_hacked_move_n = r.s_n; return true; diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index e725ea7a28..c13192c6b3 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -3017,10 +3017,10 @@ void GSRendererHW::Draw() GL_CACHE("HW: Pre-draw resolve of colclip! Address: %x", FRAME.TBP0); GSTexture* colclip_texture = g_gs_device->GetColorClipTexture(); const GSVector4 colclip_texture_dims = GSVector4(GSVector4i(colclip_texture->GetSize()).xyxy()); - g_gs_device->StretchRectNearest( + g_gs_device->StretchRect( colclip_texture, GSVector4(m_conf.colclip_update_area) / colclip_texture_dims, old_rt->m_texture, GSVector4(m_conf.colclip_update_area), - ShaderConvert::COLCLIP_RESOLVE); + ShaderConvert::COLCLIP_RESOLVE, Nearest); g_gs_device->Recycle(colclip_texture); @@ -4221,7 +4221,7 @@ void GSRendererHW::Draw() static_cast((ds->m_valid.w + vertical_offset + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast(g_texture_cache->GetTemporaryZ()->GetHeight())); GL_CACHE("HW: RT in RT Z copy back draw %lld z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset); - g_gs_device->StretchRectAutoNearest(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect)); + g_gs_device->StretchRectAuto(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect), Nearest); } g_texture_cache->InvalidateTemporaryZ(); @@ -4237,7 +4237,7 @@ void GSRendererHW::Draw() sRect = sRect.min(GSVector4(1.0f)); dRect = dRect.min_u32(GSVector4i(ds->m_unscaled_size.x * ds->m_scale, ds->m_unscaled_size.y * ds->m_scale).xyxy()); - g_gs_device->StretchRectAutoNearest(ds->m_texture, sRect, g_texture_cache->GetTemporaryZ(), GSVector4(dRect)); + g_gs_device->StretchRectAuto(ds->m_texture, sRect, g_texture_cache->GetTemporaryZ(), GSVector4(dRect), Nearest); z_address_info.rect_since = GSVector4i::zero(); g_texture_cache->SetTemporaryZInfo(z_address_info); } @@ -4284,7 +4284,7 @@ void GSRendererHW::Draw() if (m_cached_ctx.TEST.ZTST > ZTST_ALWAYS || !dRect.rintersect(GSVector4i(GSVector4(m_r) * ds->m_scale)).eq(dRect)) { - g_gs_device->StretchRectAutoNearest(ds->m_texture, sRect, tex, GSVector4(dRect)); + g_gs_device->StretchRectAuto(ds->m_texture, sRect, tex, GSVector4(dRect), Nearest); } g_texture_cache->SetTemporaryZ(tex); g_texture_cache->SetTemporaryZInfo(ds->m_TEX0.TBP0, page_offset, rt_page_offset); @@ -4874,7 +4874,7 @@ void GSRendererHW::Draw() { if (GSTexture* tex = g_gs_device->CreateDepthStencil(new_w * ds->m_scale, new_h * ds->m_scale, true)) { - g_gs_device->StretchRectAutoNearest(g_texture_cache->GetTemporaryZ(), tex); + g_gs_device->StretchRectAuto(g_texture_cache->GetTemporaryZ(), tex, Nearest); g_texture_cache->InvalidateTemporaryZ(); g_texture_cache->SetTemporaryZ(tex); } @@ -5180,7 +5180,7 @@ void GSRendererHW::Draw() static_cast((real_rect.w + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast(g_texture_cache->GetTemporaryZ()->GetHeight())); GL_CACHE("HW: RT in RT Z copy back draw %lld z_vert_offset %d rt_vert_offset %d z_horz_offset %d rt_horz_offset %d", s_n, z_vertical_offset, vertical_offset, z_horizontal_offset, horizontal_offset); - g_gs_device->StretchRectAutoNearest(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect)); + g_gs_device->StretchRectAuto(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect), Nearest); } else if (m_temp_z_full_copy) { @@ -5192,7 +5192,7 @@ void GSRendererHW::Draw() static_cast((ds->m_valid.w + vertical_offset + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast(g_texture_cache->GetTemporaryZ()->GetHeight())); GL_CACHE("HW: RT in RT Z copy back draw %lld z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset); - g_gs_device->StretchRectAutoNearest(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect)); + g_gs_device->StretchRectAuto(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect), Nearest); } m_temp_z_full_copy = false; @@ -5222,10 +5222,10 @@ void GSRendererHW::Draw() { GSTexture* colclip_texture = g_gs_device->GetColorClipTexture(); const GSVector4 colclip_texture_dims = GSVector4(GSVector4i(colclip_texture->GetSize()).xyxy()); - g_gs_device->StretchRectNearest( + g_gs_device->StretchRect( colclip_texture, GSVector4(m_conf.colclip_update_area) / colclip_texture_dims, rt->m_texture, GSVector4(m_conf.colclip_update_area), - ShaderConvert::COLCLIP_RESOLVE); + ShaderConvert::COLCLIP_RESOLVE, Nearest); } const u64 frame = g_perfmon.GetFrame(); @@ -7004,10 +7004,10 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, DATEOptio { GL_CACHE("HW: Pre-Blend resolve of colclip due to size change! Address: %x", rt->m_TEX0.TBP0); const GSVector4 colclip_texture_dims = GSVector4(GSVector4i(colclip_texture->GetSize()).xyxy()); - g_gs_device->StretchRectNearest( + g_gs_device->StretchRect( colclip_texture, GSVector4(m_conf.colclip_update_area) / colclip_texture_dims, rt->m_texture, GSVector4(m_conf.colclip_update_area), - ShaderConvert::COLCLIP_RESOLVE); + ShaderConvert::COLCLIP_RESOLVE, Nearest); g_gs_device->Recycle(colclip_texture); @@ -8216,7 +8216,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c { GSVector4 src_rect = GSVector4(tmm.coverage) / GSVector4(GSVector4i::loadh(src_unscaled_size).zwzw()); const GSVector4 dst_rect = GSVector4(tmm.coverage); - g_gs_device->StretchRectAutoNearest(src_target->m_texture, src_rect, src_copy.get(), dst_rect); + g_gs_device->StretchRectAuto(src_target->m_texture, src_rect, src_copy.get(), dst_rect, Nearest); } else { @@ -8248,7 +8248,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c const GSVector4 src_rect = GSVector4(copy_range) / GSVector4(src_unscaled_size).xyxy(); const GSVector4 dst_rect = (GSVector4(copy_range) - GSVector4(offset).xyxy()) * scale; - g_gs_device->StretchRectAutoNearest(src_target->m_texture, src_rect, src_copy.get(), dst_rect); + g_gs_device->StretchRectAuto(src_target->m_texture, src_rect, src_copy.get(), dst_rect, Nearest); } m_conf.tex = src_copy.get(); } @@ -10119,7 +10119,7 @@ bool GSRendererHW::OI_BlitFMV(GSTextureCache::Target* _rt, GSTextureCache::Sourc th = new_height; const GSVector4 sRect(m_vt.m_min.t.x / tw, m_vt.m_min.t.y / th, m_vt.m_max.t.x / tw, m_vt.m_max.t.y / th); const GSVector4i r_full_new(0, 0, tw, th); - g_gs_device->StretchRectAuto(tex->m_texture, sRect, rt, dRect, m_vt.IsRealLinear()); + g_gs_device->StretchRectAuto(tex->m_texture, sRect, rt, dRect, BilnIf(m_vt.IsRealLinear())); g_gs_device->CopyRect(rt, tex->m_texture, r_full_new, 0, 0); g_gs_device->Recycle(rt); } diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 3983d03b57..0ba7cb98ae 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -2376,7 +2376,7 @@ void GSTextureCache::CombineAlignedInsideTargets(Target* target, GSTextureCache: { if (!valid_color || (!valid_alpha && (GSUtil::GetChannelMask(t->m_TEX0.PSM) & 0x8))) GL_CACHE("Warning: CombineAlignedInsideTargets: Depth copy with invalid lower 24 bits or invalid upper 8 bits."); - g_gs_device->StretchRectAutoNearest(t->m_texture, source_rect, target->m_texture, target_drect); + g_gs_device->StretchRectAuto(t->m_texture, source_rect, target->m_texture, target_drect, Nearest); } target->m_valid_rgb |= t->m_valid_rgb; @@ -2929,8 +2929,8 @@ GSTextureCache::Target* GSTextureCache::LookupDrawTarget(GIFRegTEX0 TEX0, const else if (dst_match->m_texture->GetState() == GSTexture::State::Dirty) { dst_match->UnscaleRTAlpha(); - g_gs_device->StretchRectAutoNearest(dst_match->m_texture, FullSrcRect, dst->m_texture, - rescaler.m_dRect, src_bpp, dst_bpp); + g_gs_device->StretchRectAuto(dst_match->m_texture, FullSrcRect, dst->m_texture, + rescaler.m_dRect, Nearest, src_bpp, dst_bpp); } } @@ -2996,7 +2996,7 @@ GSTextureCache::Target* GSTextureCache::ProcessTargetAfterLookup(RescaleHelper& else { g_gs_device->StretchRectAuto(dst->m_texture, FullSrcRect, tex, rescaler.m_dRect, - type == RenderTarget && !preserve_scale); + BilnIf(type == RenderTarget && !preserve_scale)); } m_target_memory_usage = (m_target_memory_usage - dst->m_texture->GetMemUsage()) + tex->GetMemUsage(); @@ -3029,7 +3029,7 @@ GSTextureCache::Target* GSTextureCache::ProcessTargetAfterLookup(RescaleHelper& GSTexture* tex = g_gs_device->CreateCompatible(dst->m_texture, rescaler.m_new_scaled_size, false); if (!tex) return nullptr; - g_gs_device->StretchRectAutoNearest(dst->m_texture, FullSrcRect, tex, rescaler.m_dRect, 32, 24); + g_gs_device->StretchRectAuto(dst->m_texture, FullSrcRect, tex, rescaler.m_dRect, Nearest, 32, 24); g_gs_device->Recycle(dst->m_texture); dst->m_texture = tex; @@ -3098,7 +3098,7 @@ GSTextureCache::Target* GSTextureCache::ProcessTargetAfterLookup(RescaleHelper& if (!tex) return nullptr; - g_gs_device->StretchRectAutoNearest(dst->m_texture, source_rect, tex, rescaler.m_dRect); + g_gs_device->StretchRectAuto(dst->m_texture, source_rect, tex, rescaler.m_dRect, Nearest); m_target_memory_usage = m_target_memory_usage + tex->GetMemUsage(); @@ -3117,7 +3117,7 @@ GSTextureCache::Target* GSTextureCache::ProcessTargetAfterLookup(RescaleHelper& if (!tex) return nullptr; - g_gs_device->StretchRectAutoNearest(dst->m_texture, source_rect, tex, rescaler.m_dRect); + g_gs_device->StretchRectAuto(dst->m_texture, source_rect, tex, rescaler.m_dRect, Nearest); m_target_memory_usage = (m_target_memory_usage - dst->m_texture->GetMemUsage()) + tex->GetMemUsage(); @@ -3195,9 +3195,9 @@ GSTextureCache::Target* GSTextureCache::ProcessTargetAfterLookup(RescaleHelper& return nullptr; } - g_gs_device->StretchRectAutoNearest(dst_match->m_texture, GSVector4(0, 0, 1, 1), + g_gs_device->StretchRectAuto(dst_match->m_texture, GSVector4(0, 0, 1, 1), dst->m_texture, GSVector4(dst->GetUnscaledRect()) * GSVector4(dst->GetScale()), - 32, GSLocalMemory::m_psm[dst->m_TEX0.PSM].trbpp); + Nearest, 32, GSLocalMemory::m_psm[dst->m_TEX0.PSM].trbpp); dst_match->m_valid_rgb = !used; dst_match->m_was_dst_matched = true; @@ -3809,8 +3809,8 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons const u32 dst_bpp = GSLocalMemory::m_psm[dst->m_TEX0.PSM].trbpp; const u32 src_bpp = (dst_bpp == 16) ? 16 : 32; - g_gs_device->StretchRectAutoNearest(old_dst->m_texture, GSVector4(0, 0, 1, 1), - dst->m_texture, GSVector4(old_dst->GetUnscaledRect()) * GSVector4(dst->GetScale()), src_bpp, dst_bpp); + g_gs_device->StretchRectAuto(old_dst->m_texture, GSVector4(0, 0, 1, 1), + dst->m_texture, GSVector4(old_dst->GetUnscaledRect()) * GSVector4(dst->GetScale()), Nearest, src_bpp, dst_bpp); break; } @@ -4150,7 +4150,7 @@ void GSTextureCache::Target::ScaleRTAlpha() // Only copy up the valid area, since there's no point in "correcting" nothing. const GSVector4 dRect(m_texture->GetRect().rintersect(valid_rect)); const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy(); - g_gs_device->StretchRectNearest(m_texture, sRect, temp_rt, dRect, ShaderConvert::RTA_CORRECTION); + g_gs_device->StretchRect(m_texture, sRect, temp_rt, dRect, ShaderConvert::RTA_CORRECTION, Nearest); g_gs_device->Recycle(m_texture); m_texture = temp_rt; } @@ -4175,7 +4175,7 @@ void GSTextureCache::Target::UnscaleRTAlpha() // Only copy up the valid area, since there's no point in "correcting" nothing. const GSVector4 dRect(m_texture->GetRect().rintersect(valid_rect)); const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy(); - g_gs_device->StretchRectNearest(m_texture, sRect, temp_rt, dRect, ShaderConvert::RTA_DECORRECTION); + g_gs_device->StretchRect(m_texture, sRect, temp_rt, dRect, ShaderConvert::RTA_DECORRECTION, Nearest); g_gs_device->Recycle(m_texture); m_texture = temp_rt; } @@ -4234,7 +4234,7 @@ void GSTextureCache::ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb, t->m_unscaled_size.y, t->m_TEX0.TBP0, real_h, dispfb.TBP0, y_offset, needed_height); // Fill the new texture with the old data, and discard the old texture. - g_gs_device->StretchRectAutoNearest(old_texture, new_texture, GSVector4(old_texture->GetSize()).zwxy()); + g_gs_device->StretchRectAuto(old_texture, new_texture, GSVector4(old_texture->GetSize()).zwxy(), Nearest); m_target_memory_usage = (m_target_memory_usage - old_texture->GetMemUsage()) + new_texture->GetMemUsage(); g_gs_device->Recycle(old_texture); t->m_texture = new_texture; @@ -4371,9 +4371,9 @@ bool GSTextureCache::CopyRGBFromDepthToColor(Target* dst, Target* depth_src) { const GSVector4 convert_rect = GSVector4(depth_src->GetUnscaledRect().rintersect(GSVector4i::loadh(new_size))); // Update RGB bits only. - g_gs_device->StretchRectAutoNearest( + g_gs_device->StretchRectAuto( depth_src->m_texture, convert_rect / GSVector4(depth_src->GetUnscaledSize()).xyxy(), - tex, convert_rect * GSVector4(dst->GetScale()), 32, 24); + tex, convert_rect * GSVector4(dst->GetScale()), Nearest, 32, 24); } // Copy in alpha if we're a new texture. @@ -5420,8 +5420,8 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u const GSVector4 src_rect = GSVector4(scaled_sx, scaled_sy, scaled_sx + scaled_w, scaled_sy + scaled_h); const GSVector4 tmp_rect = src_rect / (GSVector4(tmp_texture->GetSize()).xyxy()); const GSVector4 dst_rect = GSVector4(scaled_dx, scaled_dy, (scaled_dx + scaled_w), (scaled_dy + scaled_h)); - g_gs_device->StretchRectAutoNearest(src->m_texture, tmp_rect, tmp_texture, src_rect); - g_gs_device->StretchRectAutoNearest(tmp_texture, tmp_rect, dst->m_texture, dst_rect); + g_gs_device->StretchRectAuto(src->m_texture, tmp_rect, tmp_texture, src_rect, Nearest); + g_gs_device->StretchRectAuto(tmp_texture, tmp_rect, dst->m_texture, dst_rect, Nearest); } else { @@ -5455,13 +5455,13 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u } else if (src->m_type != dst->m_type) { - g_gs_device->StretchRectAutoNearest(src->m_texture, src_rect, dst->m_texture, scaled_src_rect, - dpsm_s.trbpp == 16 ? 16 : 32, dpsm_s.trbpp); + g_gs_device->StretchRectAuto(src->m_texture, src_rect, dst->m_texture, scaled_src_rect, + Nearest, dpsm_s.trbpp == 16 ? 16 : 32, dpsm_s.trbpp); } else if (src->m_texture->IsDepthLike()) { const GSVector4 dst_rect = GSVector4(scaled_dx, scaled_dy, (scaled_dx + scaled_w), (scaled_dy + scaled_h)); - g_gs_device->StretchRectAutoNearest(src->m_texture, src_rect, dst->m_texture, dst_rect); + g_gs_device->StretchRectAuto(src->m_texture, src_rect, dst->m_texture, dst_rect, Nearest); } else { @@ -5703,7 +5703,7 @@ void GSTextureCache::CopyPages(Target* src, u32 sbw, u32 src_offset, Target* dst rc.src = src->m_texture; rc.src_rect = GSVector4(src_rect) / src_size; rc.dst_rect = GSVector4(dst_rect) * dst_scale; - rc.linear = false; + rc.filter = Nearest; rc.wmask.wrgba = 0xf; } @@ -6090,7 +6090,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con if (dst->m_rt_alpha_scale) { const GSVector4 sRectF = GSVector4(area) / GSVector4(1, 1, sTex->GetWidth(), sTex->GetHeight()); - g_gs_device->StretchRectNearest(sTex, sRectF, dTex, GSVector4(area), ShaderConvert::RTA_DECORRECTION); + g_gs_device->StretchRect(sTex, sRectF, dTex, GSVector4(area), ShaderConvert::RTA_DECORRECTION, Nearest); } else g_gs_device->CopyRect(sTex, dTex, area, 0, 0); @@ -6402,8 +6402,8 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con if (dst->m_rt_alpha_scale) { const GSVector4 sRectF = GSVector4(sRect) / GSVector4(1, 1, sTex->GetWidth(), sTex->GetHeight()); - g_gs_device->StretchRectNearest( - sTex, sRectF, dTex, GSVector4(destX, destY, sRect.width(), sRect.height()), ShaderConvert::RTA_DECORRECTION); + g_gs_device->StretchRect( + sTex, sRectF, dTex, GSVector4(destX, destY, sRect.width(), sRect.height()), ShaderConvert::RTA_DECORRECTION, Nearest); } else g_gs_device->CopyRect(sTex, dTex, sRect, destX, destY); @@ -6442,7 +6442,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con g_gs_device->FilteredDownsampleTexture(dst->m_texture, tmpTex, downsample_factor, GSVector2i(0, 0), dRect); } else - g_gs_device->StretchRectAutoNearest(sTex, tmpTex, dRect); + g_gs_device->StretchRectAuto(sTex, tmpTex, dRect, Nearest); g_gs_device->ConvertToIndexedTexture(tmpTex, 1, x_offset, y_offset, std::max(dst->m_TEX0.TBW, 1u) * 64, dst->m_TEX0.PSM, dTex, @@ -6472,7 +6472,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con shader = ShaderConvert::RTA_DECORRECTION; const GSVector4 sRectF = GSVector4(sRect) / GSVector4(1, 1, sTex->GetWidth(), sTex->GetHeight()); - g_gs_device->StretchRectNearest(sTex, sRectF, dTex, GSVector4(destX, destY, new_size.x, new_size.y), shader); + g_gs_device->StretchRect(sTex, sRectF, dTex, GSVector4(destX, destY, new_size.x, new_size.y), shader, Nearest); } #ifdef PCSX2_DEVBUILD @@ -6727,7 +6727,7 @@ GSTextureCache::Source* GSTextureCache::CreateMergedSource(GIFRegTEX0 TEX0, GIFR // Upload texture -> render target. const bool linear = (scale != 1.0f); copy_queue[copy_count++] = {GSVector4(rect) / GSVector4(lmtex->GetSize()).xyxy(), - GSVector4(rect) * GSVector4(scale).xyxy(), lmtex, linear, 0xf}; + GSVector4(rect) * GSVector4(scale).xyxy(), lmtex, BilnIf(linear), 0xf}; }; // The idea: loop through pages that this texture covers, find targets which overlap, and copy them in. @@ -6853,7 +6853,7 @@ GSTextureCache::Source* GSTextureCache::CreateMergedSource(GIFRegTEX0 TEX0, GIFR GSVector4(t->m_texture->GetSize()).xyxy(), GSVector4(dst_x, dst_y, dst_x + copy_width, dst_y + copy_height) * GSVector4(scale).xyxy(), - t->m_texture, linear, 0xf}; + t->m_texture, BilnIf(linear), 0xf}; } row_page++; @@ -7212,7 +7212,7 @@ GSTexture* GSTextureCache::LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVec if (!tex) return nullptr; - g_gs_device->StretchRectAutoNearest(t->m_texture, tex); + g_gs_device->StretchRectAuto(t->m_texture, tex, Nearest); m_target_memory_usage = (m_target_memory_usage - t->m_texture->GetMemUsage()) + tex->GetMemUsage(); g_gs_device->Recycle(t->m_texture); @@ -7361,7 +7361,7 @@ void GSTextureCache::Read(Target* t, const GSVector4i& r) GSTexture* tmp = g_gs_device->CreateRenderTarget(drc.z, drc.w, fmt, false); if (tmp) { - g_gs_device->StretchRectNearest(t->m_texture, src, tmp, GSVector4(drc), ps_shader); + g_gs_device->StretchRect(t->m_texture, src, tmp, GSVector4(drc), ps_shader, Nearest); dltex->get()->CopyFromTexture(drc, tmp, drc, 0, true); g_gs_device->Recycle(tmp); } @@ -7960,7 +7960,7 @@ void GSTextureCache::Target::Update(bool cannot_scale) drect.src = t; drect.src_rect = GSVector4(update_r - t_offset) / t_sizef; drect.dst_rect = GSVector4(update_r) * GSVector4(m_scale); - drect.linear = linear && (m_dirty[i].req_linear || override_linear); + drect.filter = BilnIf(linear && (m_dirty[i].req_linear || override_linear)); // Copy the new GS memory content into the destination texture. if (m_type == RenderTarget) @@ -8029,12 +8029,12 @@ void GSTextureCache::Target::Update(bool cannot_scale) (z_address_info.offset + total_rect.y) * m_scale, (total_rect.z + (1.0f / m_scale)) * m_scale, (z_address_info.offset + total_rect.w + (1.0f / m_scale)) * m_scale); - g_gs_device->StretchRectAutoNearest(m_texture, + g_gs_device->StretchRectAuto(m_texture, GSVector4(total_rect.x / static_cast(m_unscaled_size.x), total_rect.y / static_cast(m_unscaled_size.y), (total_rect.z + (1.0f / m_scale)) / static_cast(m_unscaled_size.x), (total_rect.w + (1.0f / m_scale)) / static_cast(m_unscaled_size.y)), - g_texture_cache->GetTemporaryZ(), GSVector4(dRect)); + g_texture_cache->GetTemporaryZ(), GSVector4(dRect), Nearest); } } } @@ -8183,13 +8183,13 @@ bool GSTextureCache::Target::ResizeTexture(int new_unscaled_width, int new_unsca // Can't do partial copies in DirectX for depth textures, and it's probably not ideal in other // APIs either. So use a fullscreen quad setting depth instead. // Use bilinear to avoid artifacts with upscaling. At native this is equivalent to nearest. - g_gs_device->StretchRectAutoBiln(m_texture, tex, GSVector4(rc)); + g_gs_device->StretchRectAuto(m_texture, tex, GSVector4(rc), Biln); } else { if (require_new_rect) { - g_gs_device->StretchRectAutoNearest(m_texture, tex, GSVector4(rc)); + g_gs_device->StretchRectAuto(m_texture, tex, GSVector4(rc), Nearest); } else { diff --git a/pcsx2/GS/Renderers/Metal/GSDeviceMTL.h b/pcsx2/GS/Renderers/Metal/GSDeviceMTL.h index 200339f4f3..2664dbee28 100644 --- a/pcsx2/GS/Renderers/Metal/GSDeviceMTL.h +++ b/pcsx2/GS/Renderers/Metal/GSDeviceMTL.h @@ -379,8 +379,8 @@ public: GSTexture* CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format) override; - void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) override; - void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) override; + void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const Filter filter) override; + void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, Filter filter, const InterlaceConstantBuffer& cb) override; void DoFXAA(GSTexture* sTex, GSTexture* dTex) override; void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) override; @@ -420,11 +420,11 @@ public: void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override; void BeginStretchRect(NSString* name, GSTexture* dTex, MTLLoadAction action); - void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, id pipeline, std::optional linear, LoadAction load_action, const void* frag_uniform, size_t frag_uniform_len); + void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, id pipeline, std::optional filter, LoadAction load_action, const void* frag_uniform, size_t frag_uniform_len); 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 pipeline, const GSVector4i& rect); - void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, bool linear) override; + void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, Filter filter) override; void DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvertSelector shader) 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; @@ -473,7 +473,7 @@ public: protected: using GSDevice::DoStretchRect; // Suppress overloaded virtual function warning virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear) override; + ShaderConvertSelector shader, Filter filter) override; }; static constexpr bool IsCommandBufferCompleted(MTLCommandBufferStatus status) diff --git a/pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm b/pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm index b11b4d4f18..f3ee441fa6 100644 --- a/pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm +++ b/pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm @@ -601,7 +601,7 @@ GSTexture* GSDeviceMTL::CreateSurface(GSTexture::Type type, int width, int heigh } }} -void GSDeviceMTL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) +void GSDeviceMTL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const Filter filter) { @autoreleasepool { id cmdbuf = GetRenderCmdBuf(); GSScopedDebugGroupMTL dbg(cmdbuf, @"DoMerge"); @@ -623,12 +623,12 @@ void GSDeviceMTL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, { // 2nd output is enabled and selected. Copy it to destination so we can blend it with 1st output // Note: value outside of dRect must contains the background color (c) - StretchRect(sTex[1], sRect[1], dTex, dRect[1], ShaderConvert::COPY, linear); + StretchRect(sTex[1], sRect[1], dTex, dRect[1], ShaderConvert::COPY, filter); } // Save 2nd output if (feedback_write_2) // FIXME I'm not sure dRect[1] is always correct - DoStretchRect(dTex, full_r, sTex[2], dRect[1], GetConvertPipeline(ShaderConvert::YUV), linear, LoadAction::DontCareIfFull, &cb_yuv, sizeof(cb_yuv)); + DoStretchRect(dTex, full_r, sTex[2], dRect[1], GetConvertPipeline(ShaderConvert::YUV), filter, LoadAction::DontCareIfFull, &cb_yuv, sizeof(cb_yuv)); if (feedback_write_2_but_blend_bg) ClearRenderTarget(dTex, c); @@ -642,26 +642,27 @@ void GSDeviceMTL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, if (PMODE.MMOD == 1) { // Blend with a constant alpha - DoStretchRect(sTex[0], sRect[0], dTex, dRect[0], pipeline, linear, LoadAction::Load, &cb_c, sizeof(cb_c)); + DoStretchRect(sTex[0], sRect[0], dTex, dRect[0], pipeline, filter, LoadAction::Load, &cb_c, sizeof(cb_c)); } else { // Blend with 2 * input alpha - DoStretchRect(sTex[0], sRect[0], dTex, dRect[0], pipeline, linear, LoadAction::Load, nullptr, 0); + DoStretchRect(sTex[0], sRect[0], dTex, dRect[0], pipeline, filter, LoadAction::Load, nullptr, 0); } } if (feedback_write_1) // FIXME I'm not sure dRect[0] is always correct - StretchRect(dTex, full_r, sTex[2], dRect[0], ShaderConvert::YUV, linear); + StretchRect(dTex, full_r, sTex[2], dRect[0], ShaderConvert::YUV, filter); }} -void GSDeviceMTL::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) +void GSDeviceMTL::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, Filter filter, const InterlaceConstantBuffer& cb) { @autoreleasepool { id cmdbuf = GetRenderCmdBuf(); GSScopedDebugGroupMTL dbg(cmdbuf, @"DoInterlace"); const bool can_discard = shader == ShaderInterlace::WEAVE || shader == ShaderInterlace::MAD_BUFFER; - DoStretchRect(sTex, sRect, dTex, dRect, m_interlace_pipeline[static_cast(shader)], linear, !can_discard ? LoadAction::DontCareIfFull : LoadAction::Load, &cb, sizeof(cb)); + DoStretchRect(sTex, sRect, dTex, dRect, m_interlace_pipeline[static_cast(shader)], filter, + !can_discard ? LoadAction::DontCareIfFull : LoadAction::Load, &cb, sizeof(cb)); }} void GSDeviceMTL::DoFXAA(GSTexture* sTex, GSTexture* dTex) @@ -1580,7 +1581,7 @@ void GSDeviceMTL::BeginStretchRect(NSString* name, GSTexture* dTex, MTLLoadActio MRESetDSS(dsel); } -void GSDeviceMTL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, id pipeline, std::optional linear, LoadAction load_action, const void* frag_uniform, size_t frag_uniform_len) +void GSDeviceMTL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, id pipeline, std::optional filter, LoadAction load_action, const void* frag_uniform, size_t frag_uniform_len) { FlushClears(sTex); @@ -1601,8 +1602,8 @@ void GSDeviceMTL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTextu if (frag_uniform && frag_uniform_len) [m_current_render.encoder setFragmentBytes:frag_uniform length:frag_uniform_len atIndex:GSMTLBufferIndexUniforms]; - if (linear) - MRESetSampler(*linear ? SamplerSelector::Linear() : SamplerSelector::Point()); + if (filter) + MRESetSampler(*filter == Biln ? SamplerSelector::Linear() : SamplerSelector::Point()); DrawStretchRect(sRect, dRect, GSVector2(static_cast(ds.x), static_cast(ds.y))); } @@ -1647,15 +1648,15 @@ void GSDeviceMTL::RenderCopy(GSTexture* sTex, id pipelin } void GSDeviceMTL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear) + ShaderConvertSelector shader, Filter filter) { @autoreleasepool { const LoadAction load_action = (shader.Mask() == 0xf) ? LoadAction::DontCareIfFull : LoadAction::Load; id pipeline = GetConvertPipeline(shader); pxAssertRel(pipeline, fmt::format("No pipeline for {}", ShaderEntryPoint(shader.Shader())).c_str()); - std::optional linear_if_needed = shader.SupportsBilinear() ? std::nullopt : std::make_optional(linear); + std::optional filter_if_needed = shader.SupportsBilinear() ? std::nullopt : std::make_optional(filter); - DoStretchRect(sTex, sRect, dTex, dRect, pipeline, linear_if_needed, load_action, nullptr, 0); + DoStretchRect(sTex, sRect, dTex, dRect, pipeline, filter_if_needed, load_action, nullptr, 0); }} static_assert(sizeof(DisplayConstantBuffer) == sizeof(GSMTLPresentPSUniform)); @@ -1668,7 +1669,7 @@ static_assert(offsetof(DisplayConstantBuffer, SourceResolution) == offsetof(G static_assert(offsetof(DisplayConstantBuffer, RcpSourceResolution) == offsetof(GSMTLPresentPSUniform, rcp_source_resolution)); static_assert(offsetof(DisplayConstantBuffer, TimeAndPad.x) == offsetof(GSMTLPresentPSUniform, time)); -void GSDeviceMTL::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, bool linear) +void GSDeviceMTL::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, Filter filter) { @autoreleasepool { GSVector2i ds = dTex ? dTex->GetSize() : GetWindowSize(); DisplayConstantBuffer cb; @@ -1679,13 +1680,13 @@ void GSDeviceMTL::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture if (dTex) { - DoStretchRect(sTex, sRect, dTex, dRect, pipe, linear, LoadAction::DontCareIfFull, &cb, sizeof(cb)); + DoStretchRect(sTex, sRect, dTex, dRect, pipe, filter, LoadAction::DontCareIfFull, &cb, sizeof(cb)); } else { // !dTex → Use current draw encoder [m_current_render.encoder setRenderPipelineState:pipe]; - [m_current_render.encoder setFragmentSamplerState:m_sampler_hw[linear ? SamplerSelector::Linear().key : SamplerSelector::Point().key] atIndex:0]; + [m_current_render.encoder setFragmentSamplerState:m_sampler_hw[filter == Biln ? SamplerSelector::Linear().key : SamplerSelector::Point().key] atIndex:0]; [m_current_render.encoder setFragmentTexture:static_cast(sTex)->GetTexture() atIndex:0]; [m_current_render.encoder setFragmentBytes:&cb length:sizeof(cb) atIndex:GSMTLBufferIndexUniforms]; DrawStretchRect(sRect, dRect, GSVector2(static_cast(ds.x), static_cast(ds.y))); @@ -1698,7 +1699,7 @@ void GSDeviceMTL::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_r id pipeline = nullptr; GSTexture* sTex = rects[0].src; - bool linear = rects[0].linear; + Filter filter = rects[0].filter; u8 wmask = rects[0].wmask.wrgba; const GSVector2 ds(static_cast(dTex->GetWidth()), static_cast(dTex->GetHeight())); @@ -1721,7 +1722,7 @@ void GSDeviceMTL::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_r pxAssertRel(pipeline, fmt::format("No pipeline for {}", ShaderEntryPoint(shader.Shader())).c_str()); MRESetPipeline(pipeline); } - MRESetSampler(linear ? SamplerSelector::Linear() : SamplerSelector::Point()); + MRESetSampler(filter == Biln ? SamplerSelector::Linear() : SamplerSelector::Point()); MRESetTexture(sTex, GSMTLTextureIndexNonHW); [enc drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:index_count @@ -1737,11 +1738,11 @@ void GSDeviceMTL::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_r for (u32 i = 0; i < num_rects; i++) { const MultiStretchRect& rect = rects[i]; - if (rect.src != sTex || rect.linear != linear || rect.wmask.wrgba != wmask) + if (rect.src != sTex || rect.filter != filter || rect.wmask.wrgba != wmask) { flush(i); sTex = rect.src; - linear = rect.linear; + filter = rect.filter; wmask = rect.wmask.wrgba; } *write++ = CalcStrechRectPoints(rect.src_rect, rect.dst_rect, ds); @@ -1772,7 +1773,7 @@ void GSDeviceMTL::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 off GSMTLIndexedConvertPSUniform uniform = { sScale, SBW, DBW, SPSM }; const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight()); - DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, pipeline, false, LoadAction::DontCareIfFull, &uniform, sizeof(uniform)); + DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, pipeline, Nearest, LoadAction::DontCareIfFull, &uniform, sizeof(uniform)); }} void GSDeviceMTL::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 downsample_factor, const GSVector2i& clamp_min, const GSVector4& dRect) @@ -1785,7 +1786,7 @@ void GSDeviceMTL::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u3 GSMTLDownsamplePSUniform uniform = { {static_cast(clamp_min.x), static_cast(clamp_min.x)}, downsample_factor, static_cast(downsample_factor * downsample_factor), (GSConfig.UserHacks_NativeScaling > GSNativeScaling::Aggressive) ? 2.0f : 1.0f }; - DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, pipeline, false, LoadAction::DontCareIfFull, &uniform, sizeof(uniform)); + DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, pipeline, Nearest, LoadAction::DontCareIfFull, &uniform, sizeof(uniform)); }} static id CreateDSAsRTTexture(id dev, NSUInteger width, NSUInteger height, MTLStorageMode storage, NSString* name) diff --git a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp index a4eababa9d..050eaaeebf 100644 --- a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp +++ b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp @@ -1424,7 +1424,7 @@ GSTexture* GSDeviceOGL::InitPrimDateTexture(GSTexture* rt, const GSVector4i& are return nullptr; GL_PUSH("PrimID Destination Alpha Clear"); - DoStretchRect(rt, GSVector4(area) / GSVector4(rtsize).xyxy(), tex, GSVector4(area), m_date.primid_ps[static_cast(datm)], false); + DoStretchRect(rt, GSVector4(area) / GSVector4(rtsize).xyxy(), tex, GSVector4(area), m_date.primid_ps[static_cast(datm)], Nearest); return tex; } @@ -1601,7 +1601,7 @@ std::string GSDeviceOGL::GetPSSource(const PSSelector& sel) } // Copy a sub part of texture (same as below but force a conversion) -void GSDeviceOGL::BlitRect(GSTexture* sTex, const GSVector4i& r, const GSVector2i& dsize, bool at_origin, bool linear) +void GSDeviceOGL::BlitRect(GSTexture* sTex, const GSVector4i& r, const GSVector2i& dsize, bool at_origin, Filter filter) { g_perfmon.Put(GSPerfMon::TextureCopies, 1); @@ -1620,7 +1620,7 @@ void GSDeviceOGL::BlitRect(GSTexture* sTex, const GSVector4i& r, const GSVector2 OMSetBlendState(); OMSetColorMaskState(); PSSetShaderResource(0, sTex); - PSSetSamplerState(linear ? m_convert.ln : m_convert.pt); + PSSetSamplerState(filter == Biln ? m_convert.ln : m_convert.pt); DrawStretchRect(float_r / (GSVector4(sTex->GetSize()).xyxy()), float_r, dsize); glEnable(GL_SCISSOR_TEST); @@ -1673,22 +1673,22 @@ void GSDeviceOGL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r } void GSDeviceOGL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear) + ShaderConvertSelector shader, Filter filter) { const u8 mask = shader.Mask(); shader = shader.SetMask(); // Mask is handled separately from program. - linear &= !shader.SupportsBilinear(); // Don't allow HW bilinear if SW bilinear is needed. - DoStretchRect(sTex, sRect, dTex, dRect, GetConvertProgram(shader), false, OMColorMaskSelector(mask), linear); + filter = shader.SupportsBilinear() ? Nearest : filter; // Don't allow HW bilinear if SW bilinear is needed. + DoStretchRect(sTex, sRect, dTex, dRect, GetConvertProgram(shader), false, OMColorMaskSelector(mask), filter); } void GSDeviceOGL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - const GLProgram& ps, bool linear) + const GLProgram& ps, Filter filter) { - DoStretchRect(sTex, sRect, dTex, dRect, ps, false, OMColorMaskSelector(), linear); + DoStretchRect(sTex, sRect, dTex, dRect, ps, false, OMColorMaskSelector(), filter); } void GSDeviceOGL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - const GLProgram& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear) + const GLProgram& ps, bool alpha_blend, OMColorMaskSelector cms, Filter filter) { CommitClear(sTex, true); @@ -1723,7 +1723,7 @@ void GSDeviceOGL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTextu // ************************************ PSSetShaderResource(0, sTex); - PSSetSamplerState(linear ? m_convert.ln : m_convert.pt); + PSSetSamplerState(filter == Biln ? m_convert.ln : m_convert.pt); // ************************************ // Draw @@ -1731,7 +1731,7 @@ void GSDeviceOGL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTextu DrawStretchRect(sRect, dRect, dTex->GetSize()); } -void GSDeviceOGL::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, bool linear) +void GSDeviceOGL::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, Filter filter) { CommitClear(sTex, true); @@ -1758,7 +1758,7 @@ void GSDeviceOGL::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture OMSetColorMaskState(); PSSetShaderResource(0, sTex); - PSSetSamplerState(linear ? m_convert.ln : m_convert.pt); + PSSetSamplerState(filter == Biln ? m_convert.ln : m_convert.pt); // Flip y axis only when we render in the backbuffer // By default everything is render in the wrong order (ie dx). @@ -1883,7 +1883,7 @@ void GSDeviceOGL::DrawMultiStretchRects( const GSVector2 ds(static_cast(dTex->GetWidth()), static_cast(dTex->GetHeight())); GSTexture* last_tex = rects[0].src; - bool last_linear = rects[0].linear; + Filter last_filter = rects[0].filter; u8 last_wmask = rects[0].wmask.wrgba; u32 first = 0; @@ -1891,7 +1891,7 @@ void GSDeviceOGL::DrawMultiStretchRects( for (u32 i = 1; i < num_rects; i++) { - if (rects[i].src == last_tex && rects[i].linear == last_linear && rects[i].wmask.wrgba == last_wmask) + if (rects[i].src == last_tex && rects[i].filter == last_filter && rects[i].wmask.wrgba == last_wmask) { count++; continue; @@ -1899,7 +1899,7 @@ void GSDeviceOGL::DrawMultiStretchRects( DoMultiStretchRects(rects + first, count, ds); last_tex = rects[i].src; - last_linear = rects[i].linear; + last_filter = rects[i].filter; last_wmask = rects[i].wmask.wrgba; first += count; count = 1; @@ -1959,12 +1959,12 @@ void GSDeviceOGL::DoMultiStretchRects(const MultiStretchRect* rects, u32 num_rec m_index_stream_buffer->Unmap(icount * sizeof(u16)); PSSetShaderResource(0, rects[0].src); - PSSetSamplerState(rects[0].linear ? m_convert.ln : m_convert.pt); + PSSetSamplerState(rects[0].filter == Biln ? m_convert.ln : m_convert.pt); OMSetColorMaskState(rects[0].wmask); DrawIndexedPrimitive(); } -void GSDeviceOGL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) +void GSDeviceOGL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const Filter filter) { GL_PUSH("DoMerge"); @@ -1983,7 +1983,7 @@ void GSDeviceOGL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, { // 2nd output is enabled and selected. Copy it to destination so we can blend it with 1st output // Note: value outside of dRect must contains the background color (c) - StretchRect(sTex[1], sRect[1], dTex, PMODE.SLBG ? dRect[2] : dRect[1], ShaderConvert::COPY, linear); + StretchRect(sTex[1], sRect[1], dTex, PMODE.SLBG ? dRect[2] : dRect[1], ShaderConvert::COPY, filter); } // Upload constant to select YUV algo @@ -1996,7 +1996,7 @@ void GSDeviceOGL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, // Save 2nd output if (feedback_write_2) - StretchRect(dTex, full_r, sTex[2], dRect[2], ShaderConvert::YUV, linear); + StretchRect(dTex, full_r, sTex[2], dRect[2], ShaderConvert::YUV, filter); // Restore background color to process the normal merge if (feedback_write_2_but_blend_bg) @@ -2013,27 +2013,27 @@ 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); - DoStretchRect(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(), filter); } else { // Blend with 2 * input alpha - DoStretchRect(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(), filter); } } if (feedback_write_1) - StretchRect(dTex, full_r, sTex[2], dRect[2], ShaderConvert::YUV, linear); + StretchRect(dTex, full_r, sTex[2], dRect[2], ShaderConvert::YUV, filter); } -void GSDeviceOGL::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) +void GSDeviceOGL::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, Filter filter, const InterlaceConstantBuffer& cb) { OMSetColorMaskState(); m_interlace.ps[static_cast(shader)].Bind(); m_interlace.ps[static_cast(shader)].Uniform4fv(0, cb.ZrH.F32); - DoStretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast(shader)], linear); + DoStretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast(shader)], filter); } bool GSDeviceOGL::CompileFXAAProgram() @@ -2072,7 +2072,7 @@ void GSDeviceOGL::DoFXAA(GSTexture* sTex, GSTexture* dTex) const GSVector4 sRect(0, 0, 1, 1); const GSVector4 dRect(0, 0, s.x, s.y); - DoStretchRect(sTex, sRect, dTex, dRect, m_fxaa.ps, true); + DoStretchRect(sTex, sRect, dTex, dRect, m_fxaa.ps, Biln); } bool GSDeviceOGL::CompileShadeBoostProgram() @@ -2106,7 +2106,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); - DoStretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps, false); + DoStretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps, Nearest); } void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, SetDATM datm, const GSVector4i& bbox) @@ -2726,7 +2726,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config) const GSVector2i size = config.rt->GetSize(); const GSVector4 dRect(config.colclip_update_area); const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy(); - StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false); + StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, Nearest); Recycle(colclip_rt); g_gs_device->SetColorClipTexture(nullptr); @@ -2760,7 +2760,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config) const GSVector4 dRect = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea); const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy(); - StretchRect(config.rt, sRect, colclip_rt, dRect, ShaderConvert::COLCLIP_INIT, false); + StretchRect(config.rt, sRect, colclip_rt, dRect, ShaderConvert::COLCLIP_INIT, Nearest); } } @@ -3053,7 +3053,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config) const GSVector2i size = config.rt->GetSize(); const GSVector4 dRect(config.colclip_update_area); const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy(); - StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false); + StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, Nearest); Recycle(colclip_rt); g_gs_device->SetColorClipTexture(nullptr); diff --git a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h index 5e1cfebca9..a2ab98d899 100644 --- a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h +++ b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h @@ -263,8 +263,8 @@ private: GSTexture* CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format) override; - void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) override; - void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) override; + void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const Filter filter) override; + void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, Filter filter, const InterlaceConstantBuffer& cb) override; bool CompileFXAAProgram(); void DoFXAA(GSTexture* sTex, GSTexture* dTex) override; @@ -290,7 +290,7 @@ private: protected: virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear) override; + ShaderConvertSelector shader, Filter filter) override; public: GSDeviceOGL(); virtual ~GSDeviceOGL(); @@ -348,11 +348,11 @@ public: void InsertDebugMessage(DebugMessageCategory category, const char* fmt, ...) override; // 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 BlitRect(GSTexture* sTex, const GSVector4i& r, const GSVector2i& dsize, bool at_origin, Filter filter); - 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 DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, Filter filter); + void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool alpha_blend, OMColorMaskSelector cms, Filter filter); + void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, Filter filter) 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; void FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 downsample_factor, const GSVector2i& clamp_min, const GSVector4& dRect) override; diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp index 19b23c7f08..f8b50de6f6 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp @@ -2922,24 +2922,24 @@ void GSDeviceVK::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, } void GSDeviceVK::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear) + ShaderConvertSelector shader, Filter filter) { pxAssert(dTex); - linear &= !shader.SupportsBilinear(); // Don't allow HW bilinear if SW bilinear is needed. + filter = shader.SupportsBilinear() ? Nearest : filter; // Don't allow HW bilinear if SW bilinear is needed. const bool allow_discard = (shader.Mask() == 0xf); DoStretchRect(static_cast(sTex), sRect, static_cast(dTex), dRect, - GetConvertPipeline(shader), linear, allow_discard); + GetConvertPipeline(shader), filter, allow_discard); } void GSDeviceVK::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, const GSVector4& dRect, - PresentShader shader, bool linear) + PresentShader shader, Filter filter) { DoStretchRect(static_cast(sTex), sRect, nullptr, dRect, - m_present.at(static_cast(shader)), linear, true); + m_present.at(static_cast(shader)), filter, true); } void GSDeviceVK::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - PresentShader shader, float shaderTime, bool linear) + PresentShader shader, float shaderTime, Filter filter) { DisplayConstantBuffer cb; cb.SetSource(sRect, sTex->GetSize()); @@ -2948,14 +2948,14 @@ void GSDeviceVK::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* SetUtilityPushConstants(&cb, sizeof(cb)); DoStretchRect(static_cast(sTex), sRect, static_cast(dTex), dRect, - m_present[static_cast(shader)], linear, true); + m_present[static_cast(shader)], filter, true); } void GSDeviceVK::DrawMultiStretchRects( const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvertSelector shader) { GSTexture* last_tex = rects[0].src; - bool last_linear = rects[0].linear; + Filter last_filter = rects[0].filter; u8 last_wmask = rects[0].wmask.wrgba; u32 first = 0; @@ -2976,7 +2976,7 @@ void GSDeviceVK::DrawMultiStretchRects( for (u32 i = 1; i < num_rects; i++) { - if (rects[i].src == last_tex && rects[i].linear == last_linear && rects[i].wmask.wrgba == last_wmask) + if (rects[i].src == last_tex && rects[i].filter == last_filter && rects[i].wmask.wrgba == last_wmask) { count++; continue; @@ -2984,7 +2984,7 @@ void GSDeviceVK::DrawMultiStretchRects( DoMultiStretchRects(rects + first, count, static_cast(dTex), shader); last_tex = rects[i].src; - last_linear = rects[i].linear; + last_filter = rects[i].filter; last_wmask = rects[i].wmask.wrgba; first += count; count = 1; @@ -3061,7 +3061,7 @@ void GSDeviceVK::DoMultiStretchRects( OMSetRenderTargets(dTex->IsRenderTarget() ? dTex : nullptr, dTex->IsDepthStencil() ? dTex : nullptr, rc); if (!InRenderPass()) BeginRenderPassForStretchRect(dTex, rc, rc, false); - SetUtilityTexture(rects[0].src, rects[0].linear ? m_linear_sampler : m_point_sampler); + SetUtilityTexture(rects[0].src, rects[0].filter == Biln ? m_linear_sampler : m_point_sampler); SetPipeline(GetConvertPipeline(shader.SetMask(rects[0].wmask.wrgba))); @@ -3113,7 +3113,7 @@ void GSDeviceVK::BeginRenderPassForStretchRect( } void GSDeviceVK::DoStretchRect(GSTextureVK* sTex, const GSVector4& sRect, GSTextureVK* dTex, const GSVector4& dRect, - VkPipeline pipeline, bool linear, bool allow_discard) + VkPipeline pipeline, Filter filter, bool allow_discard) { if (sTex->GetLayout() != GSTextureVK::Layout::ShaderReadOnly) { @@ -3122,7 +3122,7 @@ void GSDeviceVK::DoStretchRect(GSTextureVK* sTex, const GSVector4& sRect, GSText sTex->TransitionToLayout(GSTextureVK::Layout::ShaderReadOnly); } - SetUtilityTexture(sTex, linear ? m_linear_sampler : m_point_sampler); + SetUtilityTexture(sTex, filter == Biln ? m_linear_sampler : m_point_sampler); SetPipeline(pipeline); const bool is_present = (!dTex); @@ -3176,7 +3176,7 @@ void GSDeviceVK::DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, } void GSDeviceVK::BlitRect(GSTexture* sTex, const GSVector4i& sRect, u32 sLevel, GSTexture* dTex, - const GSVector4i& dRect, u32 dLevel, bool linear) + const GSVector4i& dRect, u32 dLevel, Filter filter) { GSTextureVK* sTexVK = static_cast(sTex); GSTextureVK* dTexVK = static_cast(dTex); @@ -3199,7 +3199,7 @@ void GSDeviceVK::BlitRect(GSTexture* sTex, const GSVector4i& sRect, u32 sLevel, vkCmdBlitImage(GetCurrentCommandBuffer(), sTexVK->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dTexVK->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &ib, - linear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST); + filter == Biln ? VK_FILTER_LINEAR : VK_FILTER_NEAREST); } void GSDeviceVK::UpdateCLUTTexture( @@ -3219,7 +3219,7 @@ void GSDeviceVK::UpdateCLUTTexture( const GSVector4 dRect(0, 0, dSize, 1); const ShaderConvert shader = (dSize == 16) ? ShaderConvert::CLUT_4 : ShaderConvert::CLUT_8; DoStretchRect(static_cast(sTex), GSVector4::zero(), static_cast(dTex), dRect, - GetConvertPipeline(shader), false, true); + GetConvertPipeline(shader), Nearest, true); } void GSDeviceVK::ConvertToIndexedTexture( @@ -3241,7 +3241,7 @@ void GSDeviceVK::ConvertToIndexedTexture( const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I; const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight()); DoStretchRect(static_cast(sTex), GSVector4::zero(), static_cast(dTex), dRect, - GetConvertPipeline(shader), false, true); + GetConvertPipeline(shader), Nearest, true); } void GSDeviceVK::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 downsample_factor, const GSVector2i& clamp_min, const GSVector4& dRect) @@ -3263,11 +3263,11 @@ void GSDeviceVK::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 const ShaderConvert shader = ShaderConvert::DOWNSAMPLE_COPY; //const GSVector4 dRect = GSVector4(dTex->GetRect()); DoStretchRect(static_cast(sTex), GSVector4::zero(), static_cast(dTex), dRect, - GetConvertPipeline(shader), false, true); + GetConvertPipeline(shader), Nearest, true); } void GSDeviceVK::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, - const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) + const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const Filter filter) { GL_PUSH("DoMerge"); @@ -3277,7 +3277,7 @@ void GSDeviceVK::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, const bool feedback_write_2 = PMODE.EN2 && sTex[2] != nullptr && EXTBUF.FBIN == 1; const bool feedback_write_1 = PMODE.EN1 && sTex[2] != nullptr && EXTBUF.FBIN == 0; const bool feedback_write_2_but_blend_bg = feedback_write_2 && PMODE.SLBG == 1; - const VkSampler& sampler = linear ? m_linear_sampler : m_point_sampler; + const VkSampler& sampler = filter == Biln ? m_linear_sampler : m_point_sampler; // Merge the 2 source textures (sTex[0],sTex[1]). Final results go to dTex. Feedback write will go to sTex[2]. // If either 2nd output is disabled or SLBG is 1, a background color will be used. // Note: background color is also used when outside of the unit rectangle area @@ -3388,7 +3388,7 @@ void GSDeviceVK::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, } void GSDeviceVK::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) + ShaderInterlace shader, Filter filter, const InterlaceConstantBuffer& cb) { static_cast(dTex)->TransitionToLayout(GSTextureVK::Layout::ColorAttachment); @@ -3397,7 +3397,7 @@ void GSDeviceVK::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* const GSVector4i clamped_rc = rc.rintersect(dtex_rc); EndRenderPass(); OMSetRenderTargets(dTex, nullptr, clamped_rc); - SetUtilityTexture(sTex, linear ? m_linear_sampler : m_point_sampler); + SetUtilityTexture(sTex, filter == Biln ? m_linear_sampler : m_point_sampler); BeginRenderPassForStretchRect(static_cast(dTex), dTex->GetRect(), clamped_rc, false); SetPipeline(m_interlace[static_cast(shader)]); SetUtilityPushConstants(&cb, sizeof(cb)); diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h index 3c7510b770..35ec780cf0 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h @@ -450,9 +450,9 @@ private: GSTexture::Type type, int width, int height, int levels, GSTexture::Format format) override; void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, - const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) final; + const GSRegEXTBUF& EXTBUF, u32 c, const Filter filter) final; void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) final; + ShaderInterlace shader, Filter filter, const InterlaceConstantBuffer& cb) final; void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) final; void DoFXAA(GSTexture* sTex, GSTexture* dTex) final; @@ -492,9 +492,9 @@ private: protected: virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - ShaderConvertSelector shader, bool linear) override; + ShaderConvertSelector shader, Filter filter) override; virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, const GSVector4& dRect, - PresentShader shader, bool linear) override; + PresentShader shader, Filter filter) override; public: GSDeviceVK(); ~GSDeviceVK() override; @@ -558,7 +558,7 @@ public: void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override; void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, - PresentShader shader, float shaderTime, bool linear) override; + PresentShader shader, float shaderTime, Filter filter) override; void DrawMultiStretchRects( const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvertSelector shader) override; void DoMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTextureVK* dTex, ShaderConvertSelector shader); @@ -566,11 +566,11 @@ public: void BeginRenderPassForStretchRect( GSTextureVK* dTex, const GSVector4i& dtex_rc, const GSVector4i& dst_rc, bool allow_discard = true); void DoStretchRect(GSTextureVK* sTex, const GSVector4& sRect, GSTextureVK* dTex, const GSVector4& dRect, - VkPipeline pipeline, bool linear, bool allow_discard); + VkPipeline pipeline, Filter filter, bool allow_discard); void DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2i& ds); void BlitRect(GSTexture* sTex, const GSVector4i& sRect, u32 sLevel, GSTexture* dTex, const GSVector4i& dRect, - u32 dLevel, bool linear); + u32 dLevel, Filter filter); void UpdateCLUTTexture( GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, GSTexture* dTex, u32 dOffset, u32 dSize) override;