GS/HW: Use an enum instead of boolean to specify nearest/bilinear filtering.

This commit is contained in:
TJnotJT
2026-05-27 08:10:44 -04:00
committed by lightningterror
parent 1e2f60a9b8
commit 74f2f73ce6
17 changed files with 300 additions and 355 deletions
+40 -101
View File
@@ -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<float>(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<float>(ds_i.x), static_cast<float>(ds_i.y));
@@ -1005,28 +944,28 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse
GSVector4(static_cast<float>(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<int>(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<int>(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<ShaderConvert>(idx >> 2);
bool depth_out = (idx >> 0) & 1;
bool biln = (idx >> 1) & 1;
return ShaderConvertSelector(convert, 0xf, depth_out, biln);
Filter filter = static_cast<Filter>((idx >> 1) & 1);
return ShaderConvertSelector(convert, 0xf, depth_out, filter);
}
static constexpr bool RemapIndexIsValid(u32 idx)
{
ShaderConvert convert = static_cast<ShaderConvert>(idx >> 2);
bool depth_out = (idx >> 0) & 1;
bool biln = (idx >> 1) & 1;
if (HasVariableWriteMask(convert) && !depth_out && !biln)
Filter filter = static_cast<Filter>((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;
}
+45 -41
View File
@@ -15,6 +15,20 @@
#include <array>
#include <span>
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<u32>(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<Filter>(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<u32>(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.
+4 -4
View File
@@ -695,7 +695,7 @@ void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame)
const float shader_time = static_cast<float>(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<float>(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();
+1 -1
View File
@@ -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;
+29 -29
View File
@@ -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<u32>(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<float>(dTex->GetWidth()), static_cast<float>(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<int>(shader)].get(), m_interlace.cb.get(), linear);
DoStretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)].get(), m_interlace.cb.get(), 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<u8>(config.datm)].get(), nullptr, false);
primid_texture, GSVector4(config.drawarea), m_date.primid_init_ps[static_cast<u8>(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);
+6 -6
View File
@@ -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;
+20 -20
View File
@@ -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<GSTexture12*>(sTex), sRect, static_cast<GSTexture12*>(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<GSTexture12*>(sTex), sRect, nullptr, dRect,
m_present[static_cast<u32>(shader)].get(), linear, true);
m_present[static_cast<u32>(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<GSTexture12*>(sTex), sRect, static_cast<GSTexture12*>(dTex), dRect,
m_present[static_cast<int>(shader)].get(), linear, true);
m_present[static_cast<int>(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<GSTexture12*>(sTex), GSVector4::zero(), static_cast<GSTexture12*>(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<GSTexture12*>(sTex), GSVector4::zero(), static_cast<GSTexture12*>(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<GSTexture12*>(sTex), GSVector4::zero(), static_cast<GSTexture12*>(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<GSTexture12*>(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<GSTexture12*>(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<GSTexture12*>(dTex), dTex->GetRect(), clamped_rc, false);
SetPipeline(m_interlace[static_cast<int>(shader)].get());
SetUtilityPushConstants(&cb, sizeof(cb));
+6 -6
View File
@@ -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);
+4 -3
View File
@@ -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;
+15 -15
View File
@@ -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<float>((ds->m_valid.w + vertical_offset + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(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<float>((real_rect.w + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(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<float>((ds->m_valid.w + vertical_offset + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(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);
}
+36 -36
View File
@@ -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<u32>(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<float>(m_unscaled_size.x),
total_rect.y / static_cast<float>(m_unscaled_size.y),
(total_rect.z + (1.0f / m_scale)) / static_cast<float>(m_unscaled_size.x),
(total_rect.w + (1.0f / m_scale)) / static_cast<float>(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
{
+5 -5
View File
@@ -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<MTLRenderPipelineState> pipeline, std::optional<bool> 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<MTLRenderPipelineState> pipeline, std::optional<Filter> 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<MTLRenderPipelineState> 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)
+24 -23
View File
@@ -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<MTLCommandBuffer> 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<MTLCommandBuffer> 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<int>(shader)], linear, !can_discard ? LoadAction::DontCareIfFull : LoadAction::Load, &cb, sizeof(cb));
DoStretchRect(sTex, sRect, dTex, dRect, m_interlace_pipeline[static_cast<int>(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<MTLRenderPipelineState> pipeline, std::optional<bool> 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<MTLRenderPipelineState> pipeline, std::optional<Filter> 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<float>(ds.x), static_cast<float>(ds.y)));
}
@@ -1647,15 +1648,15 @@ void GSDeviceMTL::RenderCopy(GSTexture* sTex, id<MTLRenderPipelineState> 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<MTLRenderPipelineState> pipeline = GetConvertPipeline(shader);
pxAssertRel(pipeline, fmt::format("No pipeline for {}", ShaderEntryPoint(shader.Shader())).c_str());
std::optional<bool> linear_if_needed = shader.SupportsBilinear() ? std::nullopt : std::make_optional(linear);
std::optional<Filter> 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<GSTextureMTL*>(sTex)->GetTexture() atIndex:0];
[m_current_render.encoder setFragmentBytes:&cb length:sizeof(cb) atIndex:GSMTLBufferIndexUniforms];
DrawStretchRect(sRect, dRect, GSVector2(static_cast<float>(ds.x), static_cast<float>(ds.y)));
@@ -1698,7 +1699,7 @@ void GSDeviceMTL::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_r
id<MTLRenderPipelineState> 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<float>(dTex->GetWidth()), static_cast<float>(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<uint>(clamp_min.x), static_cast<uint>(clamp_min.x)}, downsample_factor,
static_cast<float>(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<MTLTexture> CreateDSAsRTTexture(id<MTLDevice> dev, NSUInteger width, NSUInteger height, MTLStorageMode storage, NSString* name)
+29 -29
View File
@@ -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<u8>(datm)], false);
DoStretchRect(rt, GSVector4(area) / GSVector4(rtsize).xyxy(), tex, GSVector4(area), m_date.primid_ps[static_cast<u8>(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<float>(dTex->GetWidth()), static_cast<float>(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<int>(shader)].Bind();
m_interlace.ps[static_cast<int>(shader)].Uniform4fv(0, cb.ZrH.F32);
DoStretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)], linear);
DoStretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(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);
+7 -7
View File
@@ -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;
+22 -22
View File
@@ -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<GSTextureVK*>(sTex), sRect, static_cast<GSTextureVK*>(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<GSTextureVK*>(sTex), sRect, nullptr, dRect,
m_present.at(static_cast<u32>(shader)), linear, true);
m_present.at(static_cast<u32>(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<GSTextureVK*>(sTex), sRect, static_cast<GSTextureVK*>(dTex), dRect,
m_present[static_cast<int>(shader)], linear, true);
m_present[static_cast<int>(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<GSTextureVK*>(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<GSTextureVK*>(sTex);
GSTextureVK* dTexVK = static_cast<GSTextureVK*>(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<GSTextureVK*>(sTex), GSVector4::zero(), static_cast<GSTextureVK*>(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<GSTextureVK*>(sTex), GSVector4::zero(), static_cast<GSTextureVK*>(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<GSTextureVK*>(sTex), GSVector4::zero(), static_cast<GSTextureVK*>(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<GSTextureVK*>(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<GSTextureVK*>(dTex), dTex->GetRect(), clamped_rc, false);
SetPipeline(m_interlace[static_cast<int>(shader)]);
SetUtilityPushConstants(&cb, sizeof(cb));
+7 -7
View File
@@ -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;