GS/HW: Properly disable dual source output between multipass blending.

Fixes api warning on dx11: The Pixel Shader expects a Render Target View bound to slot 1, but none is bound.

Might also fix some potential crashes on intel gpus on all apis (mostly dx11/12).
This commit is contained in:
lightningterror 2025-12-07 08:53:05 +01:00
parent 23cd5a9da7
commit d83417ba0d
6 changed files with 17 additions and 8 deletions

View File

@ -762,9 +762,10 @@ struct alignas(16) GSHWDrawConfig
struct BlendMultiPass
{
BlendState blend;
u8 blend_hw; /*HWBlendType*/
u8 dither;
bool enable;
bool enable : 1;
u8 no_color1 : 1;
u8 blend_hw : 3; // HWBlendType
u8 dither : 2;
};
static_assert(sizeof(BlendMultiPass) == 8, "blend multi pass is 8 bytes");

View File

@ -1908,7 +1908,7 @@ void GSDevice11::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, u8
} };
// clang-format on
bd.RenderTarget[0].BlendEnable = TRUE;
bd.RenderTarget[0].BlendEnable = bsel.blend.enable;
bd.RenderTarget[0].BlendOp = s_d3d11_blend_ops[bsel.blend.op];
bd.RenderTarget[0].SrcBlend = s_d3d11_blend_factors[bsel.blend.src_factor];
bd.RenderTarget[0].DestBlend = s_d3d11_blend_factors[bsel.blend.dst_factor];
@ -2765,6 +2765,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
if (config.blend_multi_pass.enable)
{
config.ps.no_color1 = config.blend_multi_pass.no_color1;
config.ps.blend_hw = config.blend_multi_pass.blend_hw;
config.ps.dither = config.blend_multi_pass.dither;
SetupPS(config.ps, &config.cb_ps, config.sampler);

View File

@ -4045,6 +4045,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
SetBlendConstants(config.blend_multi_pass.blend.constant);
pipe.bs = config.blend_multi_pass.blend;
pipe.ps.no_color1 = config.blend_multi_pass.no_color1;
pipe.ps.blend_hw = config.blend_multi_pass.blend_hw;
pipe.ps.dither = config.blend_multi_pass.dither;
if (BindDrawPipeline(pipe))

View File

@ -6334,6 +6334,11 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
m_conf.blend_multi_pass.enable = true;
m_conf.blend_multi_pass.blend = {true, GSDevice::DST_ALPHA, GSDevice::CONST_ONE, GSDevice::OP_REV_SUBTRACT, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0};
}
// Remove second color output when unused. Works around bugs in some drivers (e.g. Intel).
m_conf.blend_multi_pass.no_color1 = !m_conf.blend_multi_pass.enable ||
(!GSDevice::IsDualSourceBlendFactor(m_conf.blend_multi_pass.blend.src_factor) &&
!GSDevice::IsDualSourceBlendFactor(m_conf.blend_multi_pass.blend.dst_factor));
}
if (!m_conf.blend_multi_pass.enable && blend_flag & BLEND_HW1)
@ -6364,9 +6369,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
// Remove second color output when unused. Works around bugs in some drivers (e.g. Intel).
m_conf.ps.no_color1 = !GSDevice::IsDualSourceBlendFactor(m_conf.blend.src_factor) &&
!GSDevice::IsDualSourceBlendFactor(m_conf.blend.dst_factor) &&
!GSDevice::IsDualSourceBlendFactor(m_conf.blend_multi_pass.blend.src_factor) &&
!GSDevice::IsDualSourceBlendFactor(m_conf.blend_multi_pass.blend.dst_factor);
!GSDevice::IsDualSourceBlendFactor(m_conf.blend.dst_factor);
}
// Notify the shader that it needs to invert rounding
@ -7770,6 +7773,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
{
if (m_conf.blend_multi_pass.enable)
{
m_conf.blend_multi_pass.no_color1 = false;
m_conf.blend_multi_pass.blend.src_factor_alpha = GSDevice::SRC1_ALPHA;
m_conf.blend_multi_pass.blend.dst_factor_alpha = GSDevice::INV_SRC1_ALPHA;
}

View File

@ -2694,10 +2694,11 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
{
OMSetBlendState();
}
psel.ps.no_color1 = config.blend_multi_pass.no_color1;
psel.ps.blend_hw = config.blend_multi_pass.blend_hw;
psel.ps.dither = config.blend_multi_pass.dither;
SetupPipeline(psel);
SendHWDraw(config, config.require_one_barrier, config.require_full_barrier);
DrawIndexedPrimitive();
}
if (config.alpha_second_pass.enable)

View File

@ -5877,6 +5877,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
SetBlendConstants(config.blend_multi_pass.blend.constant);
pipe.bs = config.blend_multi_pass.blend;
pipe.ps.no_color1 = config.blend_multi_pass.no_color1;
pipe.ps.blend_hw = config.blend_multi_pass.blend_hw;
pipe.ps.dither = config.blend_multi_pass.dither;
if (BindDrawPipeline(pipe))