mirror of https://github.com/PCSX2/pcsx2.git
GS/DX11: Implement merge feedback write
This commit is contained in:
parent
e2e25b7134
commit
68f18245a7
|
@ -18,6 +18,20 @@ struct VS_OUTPUT
|
|||
float4 c : COLOR;
|
||||
};
|
||||
|
||||
cbuffer cb0
|
||||
{
|
||||
float4 BGColor;
|
||||
int EMODA;
|
||||
int EMODC;
|
||||
};
|
||||
|
||||
static const float3x3 rgb2yuv =
|
||||
{
|
||||
{0.587, 0.114, 0.299},
|
||||
{-0.311, 0.500, -0.169},
|
||||
{-0.419, -0.081, 0.500}
|
||||
};
|
||||
|
||||
Texture2D Texture;
|
||||
SamplerState TextureSampler;
|
||||
|
||||
|
@ -357,12 +371,50 @@ PS_OUTPUT ps_convert_rgba_8i(PS_INPUT input)
|
|||
return output;
|
||||
}
|
||||
|
||||
// DUMMY
|
||||
PS_OUTPUT ps_yuv(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
output.c = input.p;
|
||||
float4 i = sample_c(input.t);
|
||||
float3 yuv = mul(rgb2yuv, i.gbr);
|
||||
|
||||
float Y = float(0xDB) / 255.0f * yuv.x + float(0x10) / 255.0f;
|
||||
float Cr = float(0xE0) / 255.0f * yuv.y + float(0x80) / 255.0f;
|
||||
float Cb = float(0xE0) / 255.0f * yuv.z + float(0x80) / 255.0f;
|
||||
|
||||
switch (EMODA)
|
||||
{
|
||||
case 0:
|
||||
output.c.a = i.a;
|
||||
break;
|
||||
case 1:
|
||||
output.c.a = Y;
|
||||
break;
|
||||
case 2:
|
||||
output.c.a = Y / 2.0f;
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
output.c.a = 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (EMODC)
|
||||
{
|
||||
case 0:
|
||||
output.c.rgb = i.rgb;
|
||||
break;
|
||||
case 1:
|
||||
output.c.rgb = float3(Y, Y, Y);
|
||||
break;
|
||||
case 2:
|
||||
output.c.rgb = float3(Y, Cb, Cr);
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
output.c.rgb = float3(i.a, i.a, i.a);
|
||||
break;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@ SamplerState Sampler;
|
|||
cbuffer cb0
|
||||
{
|
||||
float4 BGColor;
|
||||
int EMODA;
|
||||
int EMODC;
|
||||
int cb0_pad[2];
|
||||
};
|
||||
|
||||
struct PS_INPUT
|
||||
|
|
|
@ -74,6 +74,9 @@ class MergeConstantBuffer
|
|||
{
|
||||
public:
|
||||
GSVector4 BGColor;
|
||||
u32 EMODA;
|
||||
u32 EMODC;
|
||||
u32 pad[2];
|
||||
|
||||
MergeConstantBuffer() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
|
|
@ -724,21 +724,54 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
|||
|
||||
void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c)
|
||||
{
|
||||
const bool slbg = PMODE.SLBG;
|
||||
const bool mmod = PMODE.MMOD;
|
||||
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;
|
||||
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;
|
||||
|
||||
// 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
|
||||
ClearRenderTarget(dTex, c);
|
||||
|
||||
if (sTex[1] && !slbg)
|
||||
// Upload constant to select YUV algo, but skip constant buffer update if we don't need it
|
||||
if (feedback_write_2 || feedback_write_1 || sTex[0])
|
||||
{
|
||||
StretchRect(sTex[1], sRect[1], dTex, dRect[1], m_merge.ps[0].get(), nullptr, true);
|
||||
MergeConstantBuffer cb;
|
||||
cb.BGColor = c;
|
||||
cb.EMODA = EXTBUF.EMODA;
|
||||
cb.EMODC = EXTBUF.EMODC;
|
||||
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
|
||||
}
|
||||
|
||||
if (sTex[1] && (PMODE.SLBG == 0 || feedback_write_2_but_blend_bg))
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Save 2nd output
|
||||
if (feedback_write_2)
|
||||
{
|
||||
StretchRect(dTex, full_r, sTex[2], dRect[1], m_convert.ps[static_cast<int>(ShaderConvert::YUV)].get(),
|
||||
m_merge.cb.get(), nullptr, true);
|
||||
}
|
||||
|
||||
// Restore background color to process the normal merge
|
||||
if (feedback_write_2_but_blend_bg)
|
||||
ClearRenderTarget(dTex, c);
|
||||
|
||||
if (sTex[0])
|
||||
{
|
||||
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &c, 0, 0);
|
||||
// 1st output is enabled. It must be blended
|
||||
StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge.ps[PMODE.MMOD].get(), m_merge.cb.get(), m_merge.bs.get(), true);
|
||||
}
|
||||
|
||||
StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge.ps[mmod ? 1 : 0].get(), m_merge.cb.get(), m_merge.bs.get(), true);
|
||||
if (feedback_write_1)
|
||||
{
|
||||
StretchRect(dTex, full_r, sTex[2], dRect[0], m_convert.ps[static_cast<int>(ShaderConvert::YUV)].get(),
|
||||
m_merge.cb.get(), nullptr, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue