GS: Get rid of second constant buffer for alpha pass

This commit is contained in:
Connor McLaughlin 2021-12-21 17:41:50 +10:00 committed by lightningterror
parent 08c00eed1e
commit 732de53d1b
7 changed files with 48 additions and 43 deletions

View File

@ -485,7 +485,7 @@ struct GSHWDrawConfig
ColorMaskSelector colormask;
DepthStencilSelector depth;
PSSelector ps;
PSConstantBuffer cb_ps;
float ps_aref;
} alpha_second_pass;
};

View File

@ -1583,7 +1583,17 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
if (config.alpha_second_pass.enable)
{
preprocessSel(config.alpha_second_pass.ps);
SetupPS(config.alpha_second_pass.ps, &config.alpha_second_pass.cb_ps, config.sampler);
if (config.cb_ps.FogColor_AREF.a != config.alpha_second_pass.ps_aref)
{
config.cb_ps.FogColor_AREF.a = config.alpha_second_pass.ps_aref;
SetupPS(config.alpha_second_pass.ps, &config.cb_ps, config.sampler);
}
else
{
// ps cbuffer hasn't changed, so don't bother checking
SetupPS(config.alpha_second_pass.ps, nullptr, config.sampler);
}
SetupOM(config.alpha_second_pass.depth, convertSel(config.alpha_second_pass.colormask, config.blend), config.blend.factor);
DrawIndexedPrimitive();

View File

@ -196,7 +196,7 @@ void GSDevice11::SetupPS(PSSelector sel, const GSHWDrawConfig::PSConstantBuffer*
i = m_ps.try_emplace(sel.key, std::move(ps)).first;
}
if (m_ps_cb_cache.Update(*cb))
if (cb && m_ps_cb_cache.Update(*cb))
{
m_ctx->UpdateSubresource(m_ps_cb.get(), 0, NULL, cb, 0, 0);
}

View File

@ -1099,7 +1099,7 @@ GSRendererNew::PRIM_OVERLAP GSRendererNew::PrimitiveOverlap()
return overlap;
}
void GSRendererNew::EmulateATST(GSHWDrawConfig::PSConstantBuffer& cb, GSHWDrawConfig::PSSelector& ps, bool pass_2)
void GSRendererNew::EmulateATST(float& AREF, GSHWDrawConfig::PSSelector& ps, bool pass_2)
{
static const u32 inverted_atst[] = {ATST_ALWAYS, ATST_NEVER, ATST_GEQUAL, ATST_GREATER, ATST_NOTEQUAL, ATST_LESS, ATST_LEQUAL, ATST_EQUAL};
@ -1113,27 +1113,27 @@ void GSRendererNew::EmulateATST(GSHWDrawConfig::PSConstantBuffer& cb, GSHWDrawCo
switch (atst)
{
case ATST_LESS:
cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f;
AREF = (float)m_context->TEST.AREF - 0.1f;
ps.atst = 1;
break;
case ATST_LEQUAL:
cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f + 1.0f;
AREF = (float)m_context->TEST.AREF - 0.1f + 1.0f;
ps.atst = 1;
break;
case ATST_GEQUAL:
cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f;
AREF = (float)m_context->TEST.AREF - 0.1f;
ps.atst = 2;
break;
case ATST_GREATER:
cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f + 1.0f;
AREF = (float)m_context->TEST.AREF - 0.1f + 1.0f;
ps.atst = 2;
break;
case ATST_EQUAL:
cb.FogColor_AREF.a = (float)m_context->TEST.AREF;
AREF = (float)m_context->TEST.AREF;
ps.atst = 3;
break;
case ATST_NOTEQUAL:
cb.FogColor_AREF.a = (float)m_context->TEST.AREF;
AREF = (float)m_context->TEST.AREF;
ps.atst = 4;
break;
case ATST_NEVER: // Draw won't be done so no need to implement it in shader
@ -1441,7 +1441,12 @@ void GSRendererNew::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
}
else
{
EmulateATST(m_conf.cb_ps, m_conf.ps, false);
float aref = m_conf.cb_ps.FogColor_AREF.a;
EmulateATST(aref, m_conf.ps, false);
// avoid redundant cbuffer updates
m_conf.cb_ps.FogColor_AREF.a = aref;
m_conf.alpha_second_pass.ps_aref = aref;
}
if (tex)
@ -1507,7 +1512,6 @@ void GSRendererNew::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
if (ate_second_pass)
{
ASSERT(!m_env.PABE.PABE);
memcpy(&m_conf.alpha_second_pass.cb_ps, &m_conf.cb_ps, sizeof(m_conf.cb_ps));
memcpy(&m_conf.alpha_second_pass.ps, &m_conf.ps, sizeof(m_conf.ps));
memcpy(&m_conf.alpha_second_pass.colormask, &m_conf.colormask, sizeof(m_conf.colormask));
memcpy(&m_conf.alpha_second_pass.depth, &m_conf.depth, sizeof(m_conf.depth));
@ -1516,13 +1520,13 @@ void GSRendererNew::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
{
// Enable ATE as first pass to update the depth
// of pixels that passed the alpha test
EmulateATST(m_conf.alpha_second_pass.cb_ps, m_conf.alpha_second_pass.ps, false);
EmulateATST(m_conf.alpha_second_pass.ps_aref, m_conf.alpha_second_pass.ps, false);
}
else
{
// second pass will process the pixels that failed
// the alpha test
EmulateATST(m_conf.alpha_second_pass.cb_ps, m_conf.alpha_second_pass.ps, true);
EmulateATST(m_conf.alpha_second_pass.ps_aref, m_conf.alpha_second_pass.ps, true);
}
@ -1575,10 +1579,10 @@ void GSRendererNew::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
return;
// RenderHW always renders first pass, replace first pass with second
memcpy(&m_conf.cb_ps, &m_conf.alpha_second_pass.cb_ps, sizeof(m_conf.cb_ps));
memcpy(&m_conf.ps, &m_conf.alpha_second_pass.ps, sizeof(m_conf.ps));
memcpy(&m_conf.colormask, &m_conf.alpha_second_pass.colormask, sizeof(m_conf.colormask));
memcpy(&m_conf.depth, &m_conf.alpha_second_pass.depth, sizeof(m_conf.depth));
m_conf.cb_ps.FogColor_AREF.a = m_conf.alpha_second_pass.ps_aref;
m_conf.alpha_second_pass.enable = false;
}

View File

@ -43,7 +43,7 @@ private:
inline void EmulateBlending(bool& DATE_GL42, bool& DATE_GL45);
inline void EmulateTextureSampler(const GSTextureCache::Source* tex);
inline void EmulateZbuffer();
inline void EmulateATST(GSHWDrawConfig::PSConstantBuffer& cb, GSHWDrawConfig::PSSelector& ps, bool pass_2);
inline void EmulateATST(float& AREF, GSHWDrawConfig::PSSelector& ps, bool pass_2);
public:
GSRendererNew();

View File

@ -1907,29 +1907,6 @@ __fi static void WriteToStreamBuffer(GL::StreamBuffer* sb, u32 index, u32 align,
glBindBufferRange(GL_UNIFORM_BUFFER, index, sb->GetGLBufferId(), res.buffer_offset, size);
}
void GSDeviceOGL::SetupCB(const GSHWDrawConfig::VSConstantBuffer* vs_cb, const GSHWDrawConfig::PSConstantBuffer* ps_cb)
{
GL_PUSH("UBO");
if (m_vs_cb_cache.Update(*vs_cb))
{
WriteToStreamBuffer(m_vertex_uniform_stream_buffer.get(), g_vs_cb_index,
m_uniform_buffer_alignment, vs_cb, sizeof(GSHWDrawConfig::VSConstantBuffer));
}
if (m_ps_cb_cache.Update(*ps_cb))
{
WriteToStreamBuffer(m_fragment_uniform_stream_buffer.get(), g_ps_cb_index,
m_uniform_buffer_alignment, ps_cb, sizeof(GSHWDrawConfig::PSConstantBuffer));
}
}
void GSDeviceOGL::SetupCBMisc(const GSVector4i& channel)
{
m_misc_cb_cache.ChannelShuffle = channel;
m_convert.cb->cache_upload(&m_misc_cb_cache);
}
void GSDeviceOGL::SetupPipeline(const VSSelector& vsel, const GSSelector& gsel, const PSSelector& psel)
{
auto i = m_ps.find(psel.key);
@ -2099,7 +2076,16 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
OMSetColorMaskState(config.colormask);
SetupOM(config.depth);
SetupCB(&config.cb_vs, &config.cb_ps);
if (m_vs_cb_cache.Update(config.cb_vs))
{
WriteToStreamBuffer(m_vertex_uniform_stream_buffer.get(), g_vs_cb_index,
m_uniform_buffer_alignment, &config.cb_vs, sizeof(config.cb_vs));
}
if (m_ps_cb_cache.Update(config.cb_ps))
{
WriteToStreamBuffer(m_fragment_uniform_stream_buffer.get(), g_ps_cb_index,
m_uniform_buffer_alignment, &config.cb_ps, sizeof(config.cb_ps));
}
GSSelector gssel;
if (config.gs.expand)
@ -2153,7 +2139,14 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
if (config.alpha_second_pass.enable)
{
SetupCB(&config.cb_vs, &config.alpha_second_pass.cb_ps);
// cbuffer will definitely be dirty if aref changes, no need to check it
if (config.cb_ps.FogColor_AREF.a != config.alpha_second_pass.ps_aref)
{
config.cb_ps.FogColor_AREF.a = config.alpha_second_pass.ps_aref;
WriteToStreamBuffer(m_fragment_uniform_stream_buffer.get(), g_ps_cb_index,
m_uniform_buffer_alignment, &config.cb_ps, sizeof(config.cb_ps));
}
SetupPipeline(vssel, gssel, config.alpha_second_pass.ps);
OMSetColorMaskState(config.alpha_second_pass.colormask);
SetupOM(config.alpha_second_pass.depth);

View File

@ -379,8 +379,6 @@ public:
void SelfShaderTest();
void SetupPipeline(const VSSelector& vsel, const GSSelector& gsel, const PSSelector& psel);
void SetupCB(const GSHWDrawConfig::VSConstantBuffer* vs_cb, const GSHWDrawConfig::PSConstantBuffer* ps_cb);
void SetupCBMisc(const GSVector4i& channel);
void SetupSampler(PSSamplerSelector ssel);
void SetupOM(OMDepthStencilSelector dssel);
GLuint GetSamplerID(PSSamplerSelector ssel);