GS: Reduce MAD buffering draw size

It's silly to draw to the whole double-sized render target, but discard
half the pixels.

Also centralizes the constant setup, get rid of the duplication.
This commit is contained in:
Stenzek 2023-03-19 17:04:59 +10:00 committed by refractionpcsx2
parent b26acad721
commit 6ad222117d
16 changed files with 75 additions and 107 deletions

View File

@ -66,15 +66,11 @@ float4 ps_main3(PS_INPUT input) : SV_Target0
const int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
const int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
const int vpos = int(input.p.y) + lofs; // vertical position of destination texture
const float2 bofs = float2(0.0f, 0.5f * bank); // vertical offset of the current bank relative to source texture size
const float2 vscale = float2(1.0f, 2.0f); // scaling factor from source to destination texture
const float2 optr = input.t - bofs; // used to check if the current destination line is within the current bank
const float2 iptr = optr * vscale; // pointer to the current pixel in the source texture
// if the index of current destination line belongs to the current fiels we update it, otherwise
// we leave the old line in the destination buffer
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
return Texture.SampleLevel(Sampler, iptr, 0);
if ((vpos & 1) == field)
return Texture.SampleLevel(Sampler, input.t, 0);
else
discard;

View File

@ -60,15 +60,11 @@ void ps_main3()
int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
int vpos = int(gl_FragCoord.y) + lofs; // vertical position of destination texture
vec2 bofs = vec2(0.0f, 0.5f * float(bank)); // vertical offset of the current bank relative to source texture size
vec2 vscale = vec2(1.0f, 2.0f); // scaling factor from source to destination texture
vec2 optr = PSin_t - bofs; // used to check if the current destination line is within the current bank
vec2 iptr = optr * vscale; // pointer to the current pixel in the source texture
// if the index of current destination line belongs to the current fiels we update it, otherwise
// we leave the old line in the destination buffer
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
SV_Target0 = textureLod(TextureSampler, iptr, 0);
if ((vpos & 1) == field)
SV_Target0 = textureLod(TextureSampler, PSin_t, 0);
else
discard;
}

View File

@ -82,15 +82,11 @@ void ps_main3()
const int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
const int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
const int vpos = int(gl_FragCoord.y) + lofs; // vertical position of destination texture
const vec2 bofs = vec2(0.0f, 0.5f * bank); // vertical offset of the current bank relative to source texture size
const vec2 vscale = vec2(1.0f, 2.0f); // scaling factor from source to destination texture
const vec2 optr = v_tex - bofs; // used to check if the current destination line is within the current bank
const vec2 iptr = optr * vscale; // pointer to the current pixel in the source texture
// if the index of current destination line belongs to the current fiels we update it, otherwise
// we leave the old line in the destination buffer
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
o_col0 = textureLod(samp0, iptr, 0);
if ((vpos & 1) == field)
o_col0 = textureLod(samp0, v_tex, 0);
else
discard;
}

View File

@ -322,24 +322,49 @@ 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) {
const GSVector2i ds_i = dTex->GetSize();
const GSVector2 ds = GSVector2(static_cast<float>(ds_i.x), static_cast<float>(ds_i.y));
GSVector4 sRect = GSVector4(0.0f, 0.0f, 1.0f, 1.0f);
GSVector4 dRect = GSVector4(0.0f, yoffset, ds.x, ds.y + yoffset);
// Select the top or bottom half for MAD buffering.
if (shader == ShaderInterlace::MAD_BUFFER)
{
const float half_size = ds.y * 0.5f;
if ((bufIdx >> 1) == 1)
dRect.y += half_size;
else
dRect.w -= half_size;
}
const InterlaceConstantBuffer cb = {
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);
};
switch (mode)
{
case 0: // Weave
ResizeTarget(&m_weavebob, ds.x, ds.y);
DoInterlace(m_merge, m_weavebob, 0, false, offset, field);
do_interlace(m_merge, m_weavebob, ShaderInterlace::WEAVE, false, offset, field);
m_current = m_weavebob;
break;
case 1: // Bob
// Field is reversed here as we are countering the bounce.
ResizeTarget(&m_weavebob, ds.x, ds.y);
DoInterlace(m_merge, m_weavebob, 1, true, yoffset * (1 - field), 0);
do_interlace(m_merge, m_weavebob, ShaderInterlace::BOB, true, yoffset * (1 - field), 0);
m_current = m_weavebob;
break;
case 2: // Blend
ResizeTarget(&m_weavebob, ds.x, ds.y);
DoInterlace(m_merge, m_weavebob, 0, false, offset, field);
do_interlace(m_merge, m_weavebob, ShaderInterlace::WEAVE, false, offset, field);
ResizeTarget(&m_blend, ds.x, ds.y);
DoInterlace(m_weavebob, m_blend, 2, false, 0, 0);
do_interlace(m_weavebob, m_blend, ShaderInterlace::BLEND, false, 0, 0);
m_current = m_blend;
break;
case 3: // FastMAD Motion Adaptive Deinterlacing
@ -348,9 +373,9 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse
bufIdx |= field;
bufIdx &= 3;
ResizeTarget(&m_mad, ds.x, ds.y * 2.0f);
DoInterlace(m_merge, m_mad, 3, false, offset, bufIdx);
do_interlace(m_merge, m_mad, ShaderInterlace::MAD_BUFFER, false, offset, bufIdx);
ResizeTarget(&m_weavebob, ds.x, ds.y);
DoInterlace(m_mad, m_weavebob, 4, false, 0, bufIdx);
do_interlace(m_mad, m_weavebob, ShaderInterlace::MAD_RECONSTRUCT, false, 0, bufIdx);
m_current = m_weavebob;
break;
default:

View File

@ -55,6 +55,16 @@ enum class ShaderConvert
Count
};
enum class ShaderInterlace
{
WEAVE = 0,
BOB = 1,
BLEND = 2,
MAD_BUFFER = 3,
MAD_RECONSTRUCT = 4,
Count
};
static inline bool HasDepthOutput(ShaderConvert shader)
{
switch (shader)
@ -192,7 +202,6 @@ class InterlaceConstantBuffer
{
public:
GSVector4 ZrH; // data passed to the shader
InterlaceConstantBuffer() { memset(this, 0, sizeof(*this)); }
};
#pragma pack(pop)
@ -773,7 +782,7 @@ protected:
GSTexture* FetchSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format, bool clear, bool prefer_reuse);
virtual void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c, const bool linear) = 0;
virtual void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset, int bufIdx) = 0;
virtual void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) = 0;
virtual void DoFXAA(GSTexture* sTex, GSTexture* dTex) {}
virtual void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) {}

View File

@ -935,20 +935,11 @@ void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
}
}
void GSDevice11::DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset, int bufIdx)
void GSDevice11::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb)
{
const GSVector4 ds = GSVector4(dTex->GetSize());
const GSVector4 sRect(0, 0, 1, 1);
const GSVector4 dRect(0.0f, yoffset, ds.x, ds.y + yoffset);
InterlaceConstantBuffer cb;
cb.ZrH = GSVector4(static_cast<float>(bufIdx), 1.0f / ds.y, ds.y, MAD_SENSITIVITY);
m_ctx->UpdateSubresource(m_interlace.cb.get(), 0, nullptr, &cb, 0, 0);
StretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[shader].get(), m_interlace.cb.get(), linear);
StretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)].get(), m_interlace.cb.get(), linear);
}
void GSDevice11::DoFXAA(GSTexture* sTex, GSTexture* dTex)

View File

@ -127,7 +127,7 @@ private:
std::unique_ptr<GSDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GSTexture::Format format) final;
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c, const bool linear) final;
void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0, int bufIdx = 0) final;
void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) final;
void DoFXAA(GSTexture* sTex, GSTexture* dTex) final;
void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) final;

View File

@ -823,30 +823,17 @@ void GSDevice12::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
static_cast<GSTexture12*>(dTex)->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
}
void GSDevice12::DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset, int bufIdx)
void GSDevice12::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb)
{
const GSVector2i ds_i = dTex->GetSize();
const GSVector4 ds = GSVector4(ds_i);
const GSVector4 sRect(0, 0, 1, 1);
const GSVector4 dRect(0.0f, yoffset, ds.x, ds.y + yoffset);
InterlaceConstantBuffer cb;
cb.ZrH = 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, shader, linear);
static_cast<GSTexture12*>(dTex)->TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
const GSVector4i rc(0, 0, ds_i.x, ds_i.y);
const GSVector4i rc = GSVector4i(dRect);
EndRenderPass();
OMSetRenderTargets(dTex, nullptr, rc);
SetUtilityRootSignature();
SetUtilityTexture(sTex, linear ? m_linear_sampler_cpu : m_point_sampler_cpu);
BeginRenderPassForStretchRect(static_cast<GSTexture12*>(dTex), rc, rc, false);
SetPipeline(m_interlace[shader].get());
BeginRenderPassForStretchRect(static_cast<GSTexture12*>(dTex), dTex->GetRect(), rc, false);
SetPipeline(m_interlace[static_cast<int>(shader)].get());
SetUtilityPushConstants(&cb, sizeof(cb));
DrawStretchRect(sRect, dRect, dTex->GetSize());
EndRenderPass();

View File

@ -184,7 +184,7 @@ private:
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE,
const GSRegEXTBUF& EXTBUF, const GSVector4& c, const bool linear) final;
void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0, int bufIdx = 0) final;
void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) final;
void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) final;
void DoFXAA(GSTexture* sTex, GSTexture* dTex) final;

View File

@ -352,7 +352,7 @@ 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, const GSVector4& c, const bool linear) override;
void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset, int bufIdx) override;
void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) override;
void DoFXAA(GSTexture* sTex, GSTexture* dTex) override;
void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) override;
@ -371,7 +371,7 @@ public:
std::unique_ptr<GSDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GSTexture::Format format) override;
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;
void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, id<MTLRenderPipelineState> pipeline, bool linear, LoadAction load_action, void* frag_uniform, size_t frag_uniform_len);
void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, id<MTLRenderPipelineState> pipeline, bool linear, LoadAction load_action, const void* frag_uniform, size_t frag_uniform_len);
void DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2i& ds);
/// Copy from a position in sTex to the same position in the currently active render encoder using the given fs pipeline and rect
void RenderCopy(GSTexture* sTex, id<MTLRenderPipelineState> pipeline, const GSVector4i& rect);

View File

@ -595,21 +595,13 @@ void GSDeviceMTL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
StretchRect(dTex, full_r, sTex[2], dRect[0], ShaderConvert::YUV, linear);
}}
void GSDeviceMTL::DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset, int bufIdx)
void GSDeviceMTL::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb)
{ @autoreleasepool {
id<MTLCommandBuffer> cmdbuf = GetRenderCmdBuf();
GSScopedDebugGroupMTL dbg(cmdbuf, @"DoInterlace");
GSVector4 ds = GSVector4(dTex->GetSize());
GSVector4 sRect(0, 0, 1, 1);
GSVector4 dRect(0.f, yoffset, ds.x, ds.y + yoffset);
GSMTLInterlacePSUniform cb = {};
cb.ZrH = {static_cast<float>(bufIdx), 1.0f / ds.y, ds.y, MAD_SENSITIVITY};
const bool can_discard = shader == 0 || shader == 3;
DoStretchRect(sTex, sRect, dTex, dRect, m_interlace_pipeline[shader], linear, !can_discard ? LoadAction::DontCareIfFull : LoadAction::Load, &cb, sizeof(cb));
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));
}}
void GSDeviceMTL::DoFXAA(GSTexture* sTex, GSTexture* dTex)
@ -1124,7 +1116,7 @@ void GSDeviceMTL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r
[encoder endEncoding];
}}
void GSDeviceMTL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, id<MTLRenderPipelineState> pipeline, bool linear, LoadAction load_action, void* frag_uniform, size_t frag_uniform_len)
void GSDeviceMTL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, id<MTLRenderPipelineState> pipeline, bool linear, LoadAction load_action, const void* frag_uniform, size_t frag_uniform_len)
{
FlushClears(sTex);

View File

@ -38,7 +38,7 @@ fragment float4 ps_interlace0(ConvertShaderData data [[stage_in]], ConvertPSRes
// Bob shader
fragment float4 ps_interlace1(ConvertShaderData data [[stage_in]], ConvertPSRes res)
{
return res.sample_level(data.t);
return res.sample_level(data.t, 0);
}
@ -71,15 +71,11 @@ fragment float4 ps_interlace3(ConvertShaderData data [[stage_in]], ConvertPSRes
const int vres = int(uniform.ZrH.z) >> 1; // vertical resolution of source texture
const int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
const int vpos = int(data.p.y) + lofs; // vertical position of destination texture
const float2 bofs = float2(0.0f, 0.5f * bank); // vertical offset of the current bank relative to source texture size
const float2 vscale = float2(1.0f, 2.0f); // scaling factor from source to destination texture
const float2 optr = data.t - bofs; // used to check if the current destination line is within the current bank
const float2 iptr = optr * vscale; // pointer to the current pixel in the source texture
// if the index of current destination line belongs to the current fiels we update it, otherwise
// we leave the old line in the destination buffer
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
return res.sample_level(iptr, 0);
if ((vpos & 1) == field)
return res.sample_level(data.t, 0);
else
discard_fragment();

View File

@ -1453,21 +1453,14 @@ void GSDeviceOGL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
StretchRect(dTex, full_r, sTex[2], dRect[2], ShaderConvert::YUV, linear);
}
void GSDeviceOGL::DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset, int bufIdx)
void GSDeviceOGL::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb)
{
GL_PUSH("DoInterlace");
OMSetColorMaskState();
const GSVector4 ds = GSVector4(dTex->GetSize());
m_interlace.ps[static_cast<int>(shader)].Bind();
m_interlace.ps[static_cast<int>(shader)].Uniform4fv(0, cb.ZrH.F32);
const GSVector4 sRect(0, 0, 1, 1);
const GSVector4 dRect(0.0f, yoffset, ds.x, ds.y + yoffset);
m_interlace.ps[shader].Bind();
m_interlace.ps[shader].Uniform4f(0, bufIdx, 1.0f / ds.y, ds.y, MAD_SENSITIVITY);
StretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[shader], linear);
StretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)], linear);
}
void GSDeviceOGL::DoFXAA(GSTexture* sTex, GSTexture* dTex)

View File

@ -277,7 +277,7 @@ private:
GSTexture* CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format) final;
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c, const bool linear) final;
void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0, int bufIdx = 0) final;
void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) final;
void DoFXAA(GSTexture* sTex, GSTexture* dTex) final;
void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) final;

View File

@ -939,29 +939,16 @@ void GSDeviceVK::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
static_cast<GSTextureVK*>(dTex)->TransitionToLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
void GSDeviceVK::DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset, int bufIdx)
void GSDeviceVK::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb)
{
const GSVector2i ds_i = dTex->GetSize();
const GSVector4 ds = GSVector4(ds_i);
const GSVector4 sRect(0, 0, 1, 1);
const GSVector4 dRect(0.0f, yoffset, ds.x, ds.y + yoffset);
InterlaceConstantBuffer cb;
cb.ZrH = 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, shader, linear);
static_cast<GSTextureVK*>(dTex)->TransitionToLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
const GSVector4i rc(0, 0, ds_i.x, ds_i.y);
const GSVector4i rc = GSVector4i(dRect);
EndRenderPass();
OMSetRenderTargets(dTex, nullptr, rc, false);
SetUtilityTexture(sTex, linear ? m_linear_sampler : m_point_sampler);
BeginRenderPassForStretchRect(static_cast<GSTextureVK*>(dTex), rc, rc, false);
SetPipeline(m_interlace[shader]);
BeginRenderPassForStretchRect(static_cast<GSTextureVK*>(dTex), dTex->GetRect(), rc, false);
SetPipeline(m_interlace[static_cast<int>(shader)]);
SetUtilityPushConstants(&cb, sizeof(cb));
DrawStretchRect(sRect, dRect, dTex->GetSize());
EndRenderPass();

View File

@ -155,7 +155,7 @@ private:
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE,
const GSRegEXTBUF& EXTBUF, const GSVector4& c, const bool linear) final;
void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0, int bufIdx = 0) final;
void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) final;
void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) final;
void DoFXAA(GSTexture* sTex, GSTexture* dTex) final;