mirror of
https://github.com/PCSX2/pcsx2.git
synced 2025-12-16 04:08:48 +00:00
GS/HW: Add options to maintain upscale in Native Scaling
This will adjust how the box filter samples to simulate bilinear when upscaling
This commit is contained in:
parent
c5438ceca3
commit
44d66555cc
@ -80,6 +80,7 @@ PS_OUTPUT ps_downsample_copy(PS_INPUT input)
|
||||
int DownsampleFactor = DOFFSET;
|
||||
int2 ClampMin = int2(EMODA, EMODC);
|
||||
float Weight = BGColor.x;
|
||||
float step_multiplier = BGColor.y;
|
||||
|
||||
int2 coord = max(int2(input.p.xy) * DownsampleFactor, ClampMin);
|
||||
|
||||
@ -88,7 +89,7 @@ PS_OUTPUT ps_downsample_copy(PS_INPUT input)
|
||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||
{
|
||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
||||
output.c += Texture.Load(int3(coord + int2(xoff, yoff), 0));
|
||||
output.c += Texture.Load(int3(coord + int2(xoff * step_multiplier, yoff * step_multiplier), 0));
|
||||
}
|
||||
output.c /= Weight;
|
||||
return output;
|
||||
|
||||
@ -70,6 +70,7 @@ void ps_depth_copy()
|
||||
uniform ivec2 ClampMin;
|
||||
uniform int DownsampleFactor;
|
||||
uniform float Weight;
|
||||
uniform float StepMultiplier;
|
||||
|
||||
void ps_downsample_copy()
|
||||
{
|
||||
@ -78,7 +79,7 @@ void ps_downsample_copy()
|
||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||
{
|
||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
||||
result += texelFetch(TextureSampler, coord + ivec2(xoff, yoff), 0);
|
||||
result += texelFetch(TextureSampler, coord + ivec2(xoff * StepMultiplier, yoff * StepMultiplier), 0);
|
||||
}
|
||||
SV_Target0 = result / Weight;
|
||||
}
|
||||
|
||||
@ -66,7 +66,8 @@ layout(push_constant) uniform cb10
|
||||
int DownsampleFactor;
|
||||
int pad0;
|
||||
float Weight;
|
||||
vec3 pad1;
|
||||
float step_multiplier;
|
||||
vec2 pad1;
|
||||
};
|
||||
void ps_downsample_copy()
|
||||
{
|
||||
@ -75,7 +76,9 @@ void ps_downsample_copy()
|
||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||
{
|
||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
||||
result += texelFetch(samp0, coord + ivec2(xoff, yoff), 0);
|
||||
{
|
||||
result += texelFetch(samp0, coord + ivec2(xoff * step_multiplier, yoff * step_multiplier), 0);
|
||||
}
|
||||
}
|
||||
o_col0 = result / Weight;
|
||||
}
|
||||
|
||||
@ -970,7 +970,6 @@ void GraphicsSettingsWidget::onTextureReplacementChanged()
|
||||
m_texture.precacheTextureReplacements->setEnabled(enabled);
|
||||
}
|
||||
|
||||
|
||||
void GraphicsSettingsWidget::onCaptureContainerChanged()
|
||||
{
|
||||
const std::string container(
|
||||
|
||||
@ -136,6 +136,16 @@
|
||||
<string>Aggressive</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Normal (Maintain Upscale)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Aggressive (Maintain Upscale)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
|
||||
@ -456,6 +456,8 @@ enum class GSNativeScaling : u8
|
||||
Off,
|
||||
Normal,
|
||||
Aggressive,
|
||||
NormalUpscaled,
|
||||
AggressiveUpscaled,
|
||||
MaxCount
|
||||
};
|
||||
|
||||
|
||||
@ -1465,14 +1465,15 @@ void GSDevice11::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32
|
||||
struct Uniforms
|
||||
{
|
||||
float weight;
|
||||
float pad0[3];
|
||||
float step_multiplier;
|
||||
float pad0[2];
|
||||
GSVector2i clamp_min;
|
||||
int downsample_factor;
|
||||
int pad1;
|
||||
};
|
||||
|
||||
const Uniforms cb = {
|
||||
static_cast<float>(downsample_factor * downsample_factor), {}, clamp_min, static_cast<int>(downsample_factor), 0};
|
||||
static_cast<float>(downsample_factor * downsample_factor), (GSConfig.UserHacks_NativeScaling > GSNativeScaling::Aggressive) ? 2.0f : 1.0f, {}, clamp_min, static_cast<int>(downsample_factor), 0};
|
||||
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
|
||||
|
||||
const ShaderConvert shader = ShaderConvert::DOWNSAMPLE_COPY;
|
||||
|
||||
@ -1512,14 +1512,15 @@ void GSDevice12::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32
|
||||
struct Uniforms
|
||||
{
|
||||
float weight;
|
||||
float pad0[3];
|
||||
float step_multiplier;
|
||||
float pad0[2];
|
||||
GSVector2i clamp_min;
|
||||
int downsample_factor;
|
||||
int pad1;
|
||||
};
|
||||
|
||||
const Uniforms cb = {
|
||||
static_cast<float>(downsample_factor * downsample_factor), {}, clamp_min, static_cast<int>(downsample_factor), 0};
|
||||
static_cast<float>(downsample_factor * downsample_factor), (GSConfig.UserHacks_NativeScaling > GSNativeScaling::Aggressive) ? 2.0f : 1.0f, {}, clamp_min, static_cast<int>(downsample_factor), 0};
|
||||
SetUtilityRootSignature();
|
||||
SetUtilityPushConstants(&cb, sizeof(cb));
|
||||
|
||||
|
||||
@ -3192,11 +3192,12 @@ void GSRendererHW::Draw()
|
||||
// 2 == Upscale, so likely putting it over the top of the render target.
|
||||
if (scale_draw == 1)
|
||||
{
|
||||
if (!PRIM->ABE || GSConfig.UserHacks_NativeScaling < GSNativeScaling::NormalUpscaled)
|
||||
target_scale = 1.0f;
|
||||
m_downscale_source = src->m_from_target ? src->m_from_target->GetScale() > 1.0f : false;
|
||||
}
|
||||
else
|
||||
m_downscale_source = (GSConfig.UserHacks_NativeScaling != GSNativeScaling::Aggressive || !src->m_from_target) ? false : src->m_from_target->GetScale() > 1.0f; // Bad for GTA + Full Spectrum Warrior, good for Sacred Blaze + Parappa.
|
||||
m_downscale_source = ((GSConfig.UserHacks_NativeScaling != GSNativeScaling::Aggressive && GSConfig.UserHacks_NativeScaling != GSNativeScaling::AggressiveUpscaled) || !src->m_from_target) ? false : src->m_from_target->GetScale() > 1.0f; // Bad for GTA + Full Spectrum Warrior, good for Sacred Blaze + Parappa.
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3516,7 +3517,7 @@ void GSRendererHW::Draw()
|
||||
// Of course if this size is different (in width) or this is a shuffle happening, this will be bypassed.
|
||||
const bool preserve_downscale_draw = (GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && (std::abs(scale_draw) == 1 || (scale_draw == 0 && src && src->m_from_target && src->m_from_target->m_downscaled))) || is_possible_mem_clear == ClearType::ClearWithDraw;
|
||||
|
||||
rt = g_texture_cache->LookupTarget(FRAME_TEX0, t_size, ((src && src->m_scale != 1) && GSConfig.UserHacks_NativeScaling == GSNativeScaling::Normal && !possible_shuffle) ? GetTextureScaleFactor() : target_scale, GSTextureCache::RenderTarget, true,
|
||||
rt = g_texture_cache->LookupTarget(FRAME_TEX0, t_size, ((src && src->m_scale != 1) && (GSConfig.UserHacks_NativeScaling == GSNativeScaling::Normal || GSConfig.UserHacks_NativeScaling == GSNativeScaling::NormalUpscaled) && !possible_shuffle) ? GetTextureScaleFactor() : target_scale, GSTextureCache::RenderTarget, true,
|
||||
fm, false, force_preload, preserve_rt_rgb, preserve_rt_alpha, lookup_rect, possible_shuffle, is_possible_mem_clear && FRAME_TEX0.TBP0 != m_cached_ctx.ZBUF.Block(),
|
||||
GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && preserve_downscale_draw && is_possible_mem_clear != ClearType::NormalClear, src, ds, (no_ds || !ds) ? -1 : (m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0));
|
||||
|
||||
|
||||
@ -1754,7 +1754,7 @@ void GSDeviceMTL::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u3
|
||||
[NSException raise:@"StretchRect Missing Pipeline" format:@"No pipeline for %d", static_cast<int>(shader)];
|
||||
|
||||
GSMTLDownsamplePSUniform uniform = { {static_cast<uint>(clamp_min.x), static_cast<uint>(clamp_min.x)}, downsample_factor,
|
||||
static_cast<float>(downsample_factor * downsample_factor) };
|
||||
static_cast<float>(downsample_factor * downsample_factor), (GSConfig.UserHacks_NativeScaling > GSNativeScaling::Aggressive) ? 2.0f : 1.0f };
|
||||
|
||||
DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, pipeline, false, LoadAction::DontCareIfFull, &uniform, sizeof(uniform));
|
||||
}}
|
||||
|
||||
@ -72,6 +72,7 @@ struct GSMTLDownsamplePSUniform
|
||||
vector_uint2 clamp_min;
|
||||
uint downsample_factor;
|
||||
float weight;
|
||||
float step_multiplier;
|
||||
};
|
||||
|
||||
struct GSMTLMainVertex
|
||||
|
||||
@ -192,7 +192,7 @@ fragment float4 ps_downsample_copy(ConvertShaderData data [[stage_in]],
|
||||
for (uint yoff = 0; yoff < uniform.downsample_factor; yoff++)
|
||||
{
|
||||
for (uint xoff = 0; xoff < uniform.downsample_factor; xoff++)
|
||||
result += texture.read(coord + uint2(xoff, yoff), 0);
|
||||
result += texture.read(coord + uint2(xoff * uniform.step_multiplier, yoff * uniform.step_multiplier), 0);
|
||||
}
|
||||
result /= uniform.weight;
|
||||
return result;
|
||||
|
||||
@ -365,6 +365,7 @@ bool GSDeviceOGL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
m_convert.ps[i].RegisterUniform("ClampMin");
|
||||
m_convert.ps[i].RegisterUniform("DownsampleFactor");
|
||||
m_convert.ps[i].RegisterUniform("Weight");
|
||||
m_convert.ps[i].RegisterUniform("StepMultiplier");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1632,6 +1633,7 @@ void GSDeviceOGL::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u3
|
||||
prog.Uniform2iv(0, clamp_min.v);
|
||||
prog.Uniform1i(1, downsample_factor);
|
||||
prog.Uniform1f(2, static_cast<float>(downsample_factor * downsample_factor));
|
||||
prog.Uniform1f(3, (GSConfig.UserHacks_NativeScaling > GSNativeScaling::Aggressive) ? 2.0f : 1.0f);
|
||||
|
||||
OMSetDepthStencilState(m_convert.dss);
|
||||
OMSetBlendState(false);
|
||||
|
||||
@ -3154,11 +3154,12 @@ void GSDeviceVK::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32
|
||||
int downsample_factor;
|
||||
int pad0;
|
||||
float weight;
|
||||
float pad1[3];
|
||||
float step_multiplier;
|
||||
float pad1[2];
|
||||
};
|
||||
|
||||
const Uniforms uniforms = {
|
||||
clamp_min, static_cast<int>(downsample_factor), 0, static_cast<float>(downsample_factor * downsample_factor)};
|
||||
clamp_min, static_cast<int>(downsample_factor), 0, static_cast<float>(downsample_factor * downsample_factor), (GSConfig.UserHacks_NativeScaling > GSNativeScaling::Aggressive) ? 2.0f : 1.0f};
|
||||
SetUtilityPushConstants(&uniforms, sizeof(uniforms));
|
||||
|
||||
const ShaderConvert shader = ShaderConvert::DOWNSAMPLE_COPY;
|
||||
|
||||
@ -4573,9 +4573,11 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
|
||||
FSUI_NSTR("Align to Native - with Texture Offset"),
|
||||
};
|
||||
static constexpr const char* s_native_scaling_options[] = {
|
||||
FSUI_NSTR("Normal (Default)"),
|
||||
FSUI_NSTR("Off (Default)"),
|
||||
FSUI_NSTR("Normal"),
|
||||
FSUI_NSTR("Aggressive"),
|
||||
FSUI_NSTR("Off"),
|
||||
FSUI_NSTR("Normal (Maintain Upscale)"),
|
||||
FSUI_NSTR("Aggressive (Maintain Upscale)"),
|
||||
};
|
||||
static constexpr const char* s_round_sprite_options[] = {
|
||||
FSUI_NSTR("Off (Default)"),
|
||||
|
||||
@ -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 = 76;
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 77;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user