GS/HW: Allow forcing Dither to 32bit for 16bit draws

This commit is contained in:
refractionpcsx2 2024-05-23 15:09:57 +01:00
parent 99e38bc458
commit 256babd337
8 changed files with 30 additions and 17 deletions

View File

@ -803,7 +803,7 @@ void ps_fbmask(inout float4 C, float2 pos_xy)
void ps_dither(inout float3 C, float As, float2 pos_xy)
{
if (PS_DITHER)
if (PS_DITHER > 0 && PS_DITHER < 3)
{
int2 fpos;
@ -833,7 +833,7 @@ void ps_color_clamp_wrap(inout float3 C)
{
// When dithering the bottom 3 bits become meaningless and cause lines in the picture
// so we need to limit the color depth on dithered items
if (SW_BLEND || PS_DITHER || PS_FBMASK)
if (SW_BLEND || (PS_DITHER > 0 && PS_DITHER < 3) || PS_FBMASK)
{
if (PS_DST_FMT == FMT_16 && PS_BLEND_MIX == 0 && PS_ROUND_INV)
C += 7.0f; // Need to round up, not down since the shader will invert
@ -843,7 +843,7 @@ void ps_color_clamp_wrap(inout float3 C)
C = clamp(C, (float3)0.0f, (float3)255.0f);
// In 16 bits format, only 5 bits of color are used. It impacts shadows computation of Castlevania
if (PS_DST_FMT == FMT_16 && (PS_BLEND_MIX == 0 || PS_DITHER))
if (PS_DST_FMT == FMT_16 && PS_DITHER != 3 && (PS_BLEND_MIX == 0 || PS_DITHER))
C = (float3)((int3)C & (int3)0xF8);
else if (PS_COLCLIP == 1 || PS_HDR == 1)
C = (float3)((int3)C & (int3)0xFF);

View File

@ -721,7 +721,7 @@ void ps_fbmask(inout vec4 C)
void ps_dither(inout vec3 C, float As)
{
#if PS_DITHER
#if PS_DITHER > 0 && PS_DITHER < 3
#if PS_DITHER == 2
ivec2 fpos = ivec2(gl_FragCoord.xy);
#else
@ -753,7 +753,7 @@ void ps_color_clamp_wrap(inout vec3 C)
{
// When dithering the bottom 3 bits become meaningless and cause lines in the picture
// so we need to limit the color depth on dithered items
#if SW_BLEND || PS_DITHER || PS_FBMASK
#if SW_BLEND || (PS_DITHER > 0 && PS_DITHER < 3) || PS_FBMASK
#if PS_DST_FMT == FMT_16 && PS_BLEND_MIX == 0 && PS_ROUND_INV
C += 7.0f; // Need to round up, not down since the shader will invert
@ -771,7 +771,7 @@ void ps_color_clamp_wrap(inout vec3 C)
// Warning: normally blending equation is mult(A, B) = A * B >> 7. GPU have the full accuracy
// GS: Color = 1, Alpha = 255 => output 1
// GPU: Color = 1/255, Alpha = 255/255 * 255/128 => output 1.9921875
#if PS_DST_FMT == FMT_16 && (PS_BLEND_MIX == 0 || PS_DITHER)
#if PS_DST_FMT == FMT_16 && PS_DITHER < 3 && (PS_BLEND_MIX == 0 || PS_DITHER)
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
C = vec3(ivec3(C) & ivec3(0xF8));
#elif PS_COLCLIP == 1 || PS_HDR == 1

View File

@ -985,7 +985,7 @@ void ps_fbmask(inout vec4 C)
void ps_dither(inout vec3 C, float As)
{
#if PS_DITHER
#if PS_DITHER > 0 && PS_DITHER < 3
ivec2 fpos;
#if PS_DITHER == 2
@ -1020,7 +1020,7 @@ void ps_color_clamp_wrap(inout vec3 C)
{
// When dithering the bottom 3 bits become meaningless and cause lines in the picture
// so we need to limit the color depth on dithered items
#if SW_BLEND || PS_DITHER || PS_FBMASK
#if SW_BLEND || (PS_DITHER > 0 && PS_DITHER < 3) || PS_FBMASK
#if PS_DST_FMT == FMT_16 && PS_BLEND_MIX == 0 && PS_ROUND_INV
C += 7.0f; // Need to round up, not down since the shader will invert
@ -1038,7 +1038,7 @@ void ps_color_clamp_wrap(inout vec3 C)
// Warning: normally blending equation is mult(A, B) = A * B >> 7. GPU have the full accuracy
// GS: Color = 1, Alpha = 255 => output 1
// GPU: Color = 1/255, Alpha = 255/255 * 255/128 => output 1.9921875
#if PS_DST_FMT == FMT_16 && (PS_BLEND_MIX == 0 || PS_DITHER)
#if PS_DST_FMT == FMT_16 && PS_DITHER != 3 && (PS_BLEND_MIX == 0 || PS_DITHER > 0)
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
C = vec3(ivec3(C) & ivec3(0xF8));
#elif PS_COLCLIP == 1 || PS_HDR == 1

View File

@ -568,6 +568,11 @@
<string>Unscaled (Default)</string>
</property>
</item>
<item>
<property name="text">
<string>Force 32bit</string>
</property>
</item>
</widget>
</item>
<item row="6" column="0">

View File

@ -4476,7 +4476,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
// Render pass 2: Add or subtract result of render pass 1(Cd) from Cs.
m_conf.blend_second_pass.enable = true;
m_conf.blend_second_pass.blend_hw = 0;
m_conf.blend_second_pass.dither = dither;
m_conf.blend_second_pass.dither = dither * GSConfig.Dithering;
m_conf.blend_second_pass.blend = {true, blend_second_pass.src, GSDevice::CONST_ONE, blend_second_pass.op, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0};
}
else if (alpha_c1_high_no_rta_correct && (blend_flag & BLEND_HW5))
@ -5868,17 +5868,24 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
m_conf.ps.fba = m_context->FBA.FBA;
if (m_conf.ps.dither)
if (m_conf.ps.dither || m_conf.blend_second_pass.dither)
{
const GIFRegDIMX& DIMX = m_draw_env->DIMX;
GL_DBG("DITHERING mode ENABLED (%d)", GSConfig.Dithering);
GL_DBG("DITHERING mode %d (%d)", (GSConfig.Dithering == 3) ? "Force 32bit" : ((GSConfig.Dithering == 0) ? "Disabled" : "Enabled"), GSConfig.Dithering);
if (m_conf.ps.dither || GSConfig.Dithering == 3)
m_conf.ps.dither = GSConfig.Dithering;
m_conf.ps.dither = GSConfig.Dithering;
m_conf.cb_ps.DitherMatrix[0] = GSVector4(DIMX.DM00, DIMX.DM01, DIMX.DM02, DIMX.DM03);
m_conf.cb_ps.DitherMatrix[1] = GSVector4(DIMX.DM10, DIMX.DM11, DIMX.DM12, DIMX.DM13);
m_conf.cb_ps.DitherMatrix[2] = GSVector4(DIMX.DM20, DIMX.DM21, DIMX.DM22, DIMX.DM23);
m_conf.cb_ps.DitherMatrix[3] = GSVector4(DIMX.DM30, DIMX.DM31, DIMX.DM32, DIMX.DM33);
}
else if (GSConfig.Dithering > 2)
{
m_conf.ps.dither = GSConfig.Dithering;
m_conf.blend_second_pass.dither = GSConfig.Dithering;
}
if (PRIM->FGE)
{

View File

@ -865,7 +865,7 @@ struct PSMain
void ps_dither(thread float4& C, float As)
{
if (PS_DITHER == 0)
if (PS_DITHER == 0 || PS_DITHER == 3)
return;
ushort2 fpos;
if (PS_DITHER == 2)
@ -891,7 +891,7 @@ struct PSMain
void ps_color_clamp_wrap(thread float4& C)
{
// When dithering the bottom 3 bits become meaningless and cause lines in the picture so we need to limit the color depth on dithered items
if (!SW_BLEND && !PS_DITHER && !PS_FBMASK)
if (!SW_BLEND && !(PS_DITHER > 0 && PS_DITHER < 3) && !PS_FBMASK)
return;
if (PS_DST_FMT == FMT_16 && PS_BLEND_MIX == 0 && PS_ROUND_INV)
@ -907,7 +907,7 @@ struct PSMain
// Warning: normally blending equation is mult(A, B) = A * B >> 7. GPU have the full accuracy
// GS: Color = 1, Alpha = 255 => output 1
// GPU: Color = 1/255, Alpha = 255/255 * 255/128 => output 1.9921875
if (PS_DST_FMT == FMT_16 && (PS_BLEND_MIX == 0 || PS_DITHER))
if (PS_DST_FMT == FMT_16 && PS_DITHER < 3 && (PS_BLEND_MIX == 0 || PS_DITHER))
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
C.rgb = float3(short3(C.rgb) & 0xF8);
else if (PS_COLCLIP || PS_HDR)

View File

@ -3536,6 +3536,7 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
FSUI_NSTR("Off"),
FSUI_NSTR("Scaled"),
FSUI_NSTR("Unscaled (Default)"),
FSUI_NSTR("Force 32bit"),
};
static constexpr const char* s_blending_options[] = {
FSUI_NSTR("Minimum"),

View File

@ -3,4 +3,4 @@
/// Version number for GS and other shaders. Increment whenever any of the contents of the
/// shaders change, to invalidate the cache.
static constexpr u32 SHADER_CACHE_VERSION = 48;
static constexpr u32 SHADER_CACHE_VERSION = 49;