mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-07-11 01:34:17 +02:00
GS/HW: Use an enum instead of boolean to specify nearest/bilinear filtering.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user