Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test: use software renderer blending logic in fbfetch blend #11387

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
18 changes: 18 additions & 0 deletions Source/Core/VideoBackends/OGL/OGLRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,24 @@ Renderer::Renderer(std::unique_ptr<GLContext> main_gl_context, float backbuffer_
}
else
{
if (GLExtensions::Supports("GL_EXT_shader_framebuffer_fetch"))
{
INFO_LOG_FMT(VIDEO, "GL_EXT_shader_framebuffer_fetch");
g_ogl_config.SupportedFramebufferFetch = EsFbFetchType::FbFetchExt;
}
else if (GLExtensions::Supports("GL_ARM_shader_framebuffer_fetch"))
{
INFO_LOG_FMT(VIDEO, "GL_ARM_shader_framebuffer_fetch");
g_ogl_config.SupportedFramebufferFetch = EsFbFetchType::FbFetchArm;
}
else
{
INFO_LOG_FMT(VIDEO, "Not supported");
g_ogl_config.SupportedFramebufferFetch = EsFbFetchType::FbFetchNone;
}
g_Config.backend_info.bSupportsFramebufferFetch =
g_ogl_config.SupportedFramebufferFetch != EsFbFetchType::FbFetchNone;

if (GLExtensions::Version() < 300)
{
PanicAlertFmtT("GPU: OGL ERROR: Need at least GLSL 1.30\n"
Expand Down
112 changes: 64 additions & 48 deletions Source/Core/VideoCommon/PixelShaderGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1844,75 +1844,91 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data)
{
using Common::EnumMap;
static constexpr EnumMap<const char*, SrcBlendFactor::InvDstAlpha> blend_src_factor{
"float3(0,0,0);", // ZERO
"float3(1,1,1);", // ONE
"initial_ocol0.rgb;", // DSTCLR
"float3(1,1,1) - initial_ocol0.rgb;", // INVDSTCLR
"src_color.aaa;", // SRCALPHA
"float3(1,1,1) - src_color.aaa;", // INVSRCALPHA
"initial_ocol0.aaa;", // DSTALPHA
"float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
"float3(0,0,0)", // ZERO
"float3(1,1,1)", // ONE
"initial_ocol0.rgb", // DSTCLR
"float3(1,1,1) - initial_ocol0.rgb", // INVDSTCLR
"src_color.aaa", // SRCALPHA
"float3(1,1,1) - src_color.aaa", // INVSRCALPHA
"initial_ocol0.aaa", // DSTALPHA
"float3(1,1,1) - initial_ocol0.aaa", // INVDSTALPHA
};
static constexpr EnumMap<const char*, SrcBlendFactor::InvDstAlpha> blend_src_factor_alpha{
"0.0;", // ZERO
"1.0;", // ONE
"initial_ocol0.a;", // DSTCLR
"1.0 - initial_ocol0.a;", // INVDSTCLR
"src_color.a;", // SRCALPHA
"1.0 - src_color.a;", // INVSRCALPHA
"initial_ocol0.a;", // DSTALPHA
"1.0 - initial_ocol0.a;", // INVDSTALPHA
"0.0", // ZERO
"1.0", // ONE
"initial_ocol0.a", // DSTCLR
"1.0 - initial_ocol0.a", // INVDSTCLR
"src_color.a", // SRCALPHA
"1.0 - src_color.a", // INVSRCALPHA
"initial_ocol0.a", // DSTALPHA
"1.0 - initial_ocol0.a", // INVDSTALPHA
};
static constexpr EnumMap<const char*, DstBlendFactor::InvDstAlpha> blend_dst_factor{
"float3(0,0,0);", // ZERO
"float3(1,1,1);", // ONE
"ocol0.rgb;", // SRCCLR
"float3(1,1,1) - ocol0.rgb;", // INVSRCCLR
"src_color.aaa;", // SRCALHA
"float3(1,1,1) - src_color.aaa;", // INVSRCALPHA
"initial_ocol0.aaa;", // DSTALPHA
"float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
"float3(0,0,0)", // ZERO
"float3(1,1,1)", // ONE
"ocol0.rgb", // SRCCLR
"float3(1,1,1) - ocol0.rgb", // INVSRCCLR
"src_color.aaa", // SRCALPHA
"float3(1,1,1) - src_color.aaa", // INVSRCALPHA
"initial_ocol0.aaa", // DSTALPHA
"float3(1,1,1) - initial_ocol0.aaa", // INVDSTALPHA
};
static constexpr EnumMap<const char*, DstBlendFactor::InvDstAlpha> blend_dst_factor_alpha{
"0.0;", // ZERO
"1.0;", // ONE
"ocol0.a;", // SRCCLR
"1.0 - ocol0.a;", // INVSRCCLR
"src_color.a;", // SRCALPHA
"1.0 - src_color.a;", // INVSRCALPHA
"initial_ocol0.a;", // DSTALPHA
"1.0 - initial_ocol0.a;", // INVDSTALPHA
"0.0", // ZERO
"1.0", // ONE
"ocol0.a", // SRCCLR
"1.0 - ocol0.a", // INVSRCCLR
"src_color.a", // SRCALPHA
"1.0 - src_color.a", // INVSRCALPHA
"initial_ocol0.a", // DSTALPHA
"1.0 - initial_ocol0.a", // INVDSTALPHA
};
out.Write("\tfloat4 src_color = {};\n"
"\tfloat4 blend_src;",
"\tint4 blend_src;\n",
uid_data->useDstAlpha ? "ocol1" : "ocol0");
out.Write("\tblend_src.rgb = {}\n", blend_src_factor[uid_data->blend_src_factor]);
out.Write("\tblend_src.a = {}\n", blend_src_factor_alpha[uid_data->blend_src_factor_alpha]);
out.Write("\tfloat4 blend_dst;\n");
out.Write("\tblend_dst.rgb = {}\n", blend_dst_factor[uid_data->blend_dst_factor]);
out.Write("\tblend_dst.a = {}\n", blend_dst_factor_alpha[uid_data->blend_dst_factor_alpha]);

out.Write("\tfloat4 blend_result;\n");
out.Write("\tblend_src.rgb = int3(({}) * 255.0);\n",
blend_src_factor[uid_data->blend_src_factor]);
out.Write("\tblend_src.a = int(({}) * 255.0);\n",
blend_src_factor_alpha[uid_data->blend_src_factor_alpha]);
out.Write("\tint4 blend_dst;\n");
out.Write("\tblend_dst.rgb = int3(({}) * 255.0);\n",
blend_dst_factor[uid_data->blend_dst_factor]);
out.Write("\tblend_dst.a = int(({}) * 255.0);\n",
blend_dst_factor_alpha[uid_data->blend_dst_factor_alpha]);

// add MSB of factors to make their range 0 -> 256
out.Write("\tblend_src += blend_src >> 7;\n"
"\tblend_dst += blend_dst >> 7;\n");

out.Write("\tint4 blend_result;\n");
if (uid_data->blend_subtract)
{
out.Write("\tblend_result.rgb = initial_ocol0.rgb * blend_dst.rgb - ocol0.rgb * "
"blend_src.rgb;\n");
// TODO: libogc docs say src/dest factor are ignored in subtract mode
// (we may be handling this elsewhere?)
out.Write("\tblend_result.rgb = int3(initial_ocol0.rgb * 255.0) * blend_dst.rgb "
"- int3(ocol0.rgb * 255.0) * blend_src.rgb;\n");
}
else
{
out.Write(
"\tblend_result.rgb = initial_ocol0.rgb * blend_dst.rgb + ocol0.rgb * blend_src.rgb;\n");
out.Write("\tblend_result.rgb = int3(initial_ocol0.rgb * 255.0) * blend_dst.rgb "
"+ int3(ocol0.rgb * 255.0) * blend_src.rgb;\n");
}

if (uid_data->blend_subtract_alpha)
out.Write("\tblend_result.a = initial_ocol0.a * blend_dst.a - ocol0.a * blend_src.a;\n");
{
out.Write("\tblend_result.a = int(initial_ocol0.a * 255.0) * blend_dst.a "
"- int(ocol0.a * 255.0) * blend_src.a;\n");
}
else
out.Write("\tblend_result.a = initial_ocol0.a * blend_dst.a + ocol0.a * blend_src.a;\n");
{
out.Write("\tblend_result.a = int(initial_ocol0.a * 255.0) * blend_dst.a "
"+ int(ocol0.a * 255.0) * blend_src.a;\n");
}
}
else
{
out.Write("\tfloat4 blend_result = ocol0;\n");
out.Write("\tint4 blend_result = int4(ocol0 * 255.0) * 256;\n");
}

out.Write("\treal_ocol0 = blend_result;\n");
out.Write("\treal_ocol0 = float4(clamp(blend_result >> 8, 0, 255)) / 255.0;\n");
}
9 changes: 6 additions & 3 deletions Source/Core/VideoCommon/ShaderCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,13 +641,13 @@ static GXPipelineUid ApplyDriverBugs(const GXPipelineUid& in)

if (g_ActiveConfig.backend_info.bSupportsFramebufferFetch)
{
bool fbfetch_blend = false;
bool fbfetch_blend = blend.blendenable;
if ((DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z) ||
!g_ActiveConfig.backend_info.bSupportsEarlyZ) &&
ps->ztest == EmulatedZ::ForcedEarly)
{
ps->ztest = EmulatedZ::EarlyWithFBFetch;
fbfetch_blend |= static_cast<bool>(out.blending_state.blendenable);
fbfetch_blend |= static_cast<bool>(blend.blendenable);
ps->no_dual_src = true;
}
fbfetch_blend |= blend.logicopenable && !g_ActiveConfig.backend_info.bSupportsLogicOp;
Expand All @@ -670,7 +670,10 @@ static GXPipelineUid ApplyDriverBugs(const GXPipelineUid& in)
ps->blend_dst_factor_alpha = blend.dstfactoralpha;
ps->blend_subtract = blend.subtract;
ps->blend_subtract_alpha = blend.subtractAlpha;
blend.blendenable = false;
blend.hex = 0;
blend.colorupdate = in.blending_state.colorupdate.Value();
blend.alphaupdate = in.blending_state.alphaupdate.Value();
blend.usedualsrc = false;
}
}
}
Expand Down
28 changes: 18 additions & 10 deletions Source/Core/VideoCommon/UberShaderPixel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1193,20 +1193,28 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
WriteSwitch(out, api_type, "blend_dst_factor", blendDstFactor, 4, true);
WriteSwitch(out, api_type, "blend_dst_factor_alpha", blendDstFactorAlpha, 4, true);

out.Write(
" float4 blend_result;\n"
" if (blend_subtract)\n"
" blend_result.rgb = initial_ocol0.rgb * blend_dst.rgb - ocol0.rgb * blend_src.rgb;\n"
" else\n"
" blend_result.rgb = initial_ocol0.rgb * blend_dst.rgb + ocol0.rgb * "
"blend_src.rgb;\n");
out.Write(" int4 blend_src_real = int4(blend_src * 255.0);\n"
" blend_src_real += blend_src_real >> 7;\n"
" int4 blend_src_col = int4(ocol0 * 255.0);\n"
" int4 blend_dst_real = int4(blend_dst * 255.0);\n"
" blend_dst_real += blend_dst_real >> 7;\n"
" int4 blend_dst_col = int4(initial_ocol0 * 255.0);\n"
" int4 blend_result;\n"
" if (blend_subtract)\n"
" blend_result.rgb = blend_dst_col.rgb * blend_dst_real.rgb "
"- blend_src_col.rgb * blend_src_real.rgb;\n"
" else\n"
" blend_result.rgb = blend_dst_col.rgb * blend_dst_real.rgb "
"+ blend_src_col.rgb * blend_src_real.rgb;\n");

out.Write(" if (blend_subtract_alpha)\n"
" blend_result.a = initial_ocol0.a * blend_dst.a - ocol0.a * blend_src.a;\n"
" blend_result.a = blend_dst_col.a * blend_dst_real.a "
"- blend_src_col.a * blend_src_real.a;\n"
" else\n"
" blend_result.a = initial_ocol0.a * blend_dst.a + ocol0.a * blend_src.a;\n");
" blend_result.a = blend_dst_col.a * blend_dst_real.a "
"+ blend_src_col.a * blend_src_real.a;\n");

out.Write(" real_ocol0 = blend_result;\n");
out.Write(" real_ocol0 = float4(clamp(blend_result >> 8, 0, 255)) / 255.0;\n");

out.Write(" }} else {{\n"
" real_ocol0 = ocol0;\n"
Expand Down