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;
|
int DownsampleFactor = DOFFSET;
|
||||||
int2 ClampMin = int2(EMODA, EMODC);
|
int2 ClampMin = int2(EMODA, EMODC);
|
||||||
float Weight = BGColor.x;
|
float Weight = BGColor.x;
|
||||||
|
float step_multiplier = BGColor.y;
|
||||||
|
|
||||||
int2 coord = max(int2(input.p.xy) * DownsampleFactor, ClampMin);
|
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 yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||||
{
|
{
|
||||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
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;
|
output.c /= Weight;
|
||||||
return output;
|
return output;
|
||||||
|
|||||||
@ -70,6 +70,7 @@ void ps_depth_copy()
|
|||||||
uniform ivec2 ClampMin;
|
uniform ivec2 ClampMin;
|
||||||
uniform int DownsampleFactor;
|
uniform int DownsampleFactor;
|
||||||
uniform float Weight;
|
uniform float Weight;
|
||||||
|
uniform float StepMultiplier;
|
||||||
|
|
||||||
void ps_downsample_copy()
|
void ps_downsample_copy()
|
||||||
{
|
{
|
||||||
@ -78,7 +79,7 @@ void ps_downsample_copy()
|
|||||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||||
{
|
{
|
||||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
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;
|
SV_Target0 = result / Weight;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,7 +66,8 @@ layout(push_constant) uniform cb10
|
|||||||
int DownsampleFactor;
|
int DownsampleFactor;
|
||||||
int pad0;
|
int pad0;
|
||||||
float Weight;
|
float Weight;
|
||||||
vec3 pad1;
|
float step_multiplier;
|
||||||
|
vec2 pad1;
|
||||||
};
|
};
|
||||||
void ps_downsample_copy()
|
void ps_downsample_copy()
|
||||||
{
|
{
|
||||||
@ -75,7 +76,9 @@ void ps_downsample_copy()
|
|||||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||||
{
|
{
|
||||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
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;
|
o_col0 = result / Weight;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -970,7 +970,6 @@ void GraphicsSettingsWidget::onTextureReplacementChanged()
|
|||||||
m_texture.precacheTextureReplacements->setEnabled(enabled);
|
m_texture.precacheTextureReplacements->setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GraphicsSettingsWidget::onCaptureContainerChanged()
|
void GraphicsSettingsWidget::onCaptureContainerChanged()
|
||||||
{
|
{
|
||||||
const std::string container(
|
const std::string container(
|
||||||
|
|||||||
@ -136,6 +136,16 @@
|
|||||||
<string>Aggressive</string>
|
<string>Aggressive</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Normal (Maintain Upscale)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Aggressive (Maintain Upscale)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
|
|||||||
@ -456,6 +456,8 @@ enum class GSNativeScaling : u8
|
|||||||
Off,
|
Off,
|
||||||
Normal,
|
Normal,
|
||||||
Aggressive,
|
Aggressive,
|
||||||
|
NormalUpscaled,
|
||||||
|
AggressiveUpscaled,
|
||||||
MaxCount
|
MaxCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1465,14 +1465,15 @@ void GSDevice11::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32
|
|||||||
struct Uniforms
|
struct Uniforms
|
||||||
{
|
{
|
||||||
float weight;
|
float weight;
|
||||||
float pad0[3];
|
float step_multiplier;
|
||||||
|
float pad0[2];
|
||||||
GSVector2i clamp_min;
|
GSVector2i clamp_min;
|
||||||
int downsample_factor;
|
int downsample_factor;
|
||||||
int pad1;
|
int pad1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Uniforms cb = {
|
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);
|
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
|
||||||
|
|
||||||
const ShaderConvert shader = ShaderConvert::DOWNSAMPLE_COPY;
|
const ShaderConvert shader = ShaderConvert::DOWNSAMPLE_COPY;
|
||||||
|
|||||||
@ -1512,14 +1512,15 @@ void GSDevice12::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32
|
|||||||
struct Uniforms
|
struct Uniforms
|
||||||
{
|
{
|
||||||
float weight;
|
float weight;
|
||||||
float pad0[3];
|
float step_multiplier;
|
||||||
|
float pad0[2];
|
||||||
GSVector2i clamp_min;
|
GSVector2i clamp_min;
|
||||||
int downsample_factor;
|
int downsample_factor;
|
||||||
int pad1;
|
int pad1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Uniforms cb = {
|
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();
|
SetUtilityRootSignature();
|
||||||
SetUtilityPushConstants(&cb, sizeof(cb));
|
SetUtilityPushConstants(&cb, sizeof(cb));
|
||||||
|
|
||||||
|
|||||||
@ -3192,11 +3192,12 @@ void GSRendererHW::Draw()
|
|||||||
// 2 == Upscale, so likely putting it over the top of the render target.
|
// 2 == Upscale, so likely putting it over the top of the render target.
|
||||||
if (scale_draw == 1)
|
if (scale_draw == 1)
|
||||||
{
|
{
|
||||||
target_scale = 1.0f;
|
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;
|
m_downscale_source = src->m_from_target ? src->m_from_target->GetScale() > 1.0f : false;
|
||||||
}
|
}
|
||||||
else
|
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
|
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.
|
// 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;
|
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(),
|
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));
|
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)];
|
[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,
|
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));
|
DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, pipeline, false, LoadAction::DontCareIfFull, &uniform, sizeof(uniform));
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -72,6 +72,7 @@ struct GSMTLDownsamplePSUniform
|
|||||||
vector_uint2 clamp_min;
|
vector_uint2 clamp_min;
|
||||||
uint downsample_factor;
|
uint downsample_factor;
|
||||||
float weight;
|
float weight;
|
||||||
|
float step_multiplier;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GSMTLMainVertex
|
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 yoff = 0; yoff < uniform.downsample_factor; yoff++)
|
||||||
{
|
{
|
||||||
for (uint xoff = 0; xoff < uniform.downsample_factor; xoff++)
|
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;
|
result /= uniform.weight;
|
||||||
return result;
|
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("ClampMin");
|
||||||
m_convert.ps[i].RegisterUniform("DownsampleFactor");
|
m_convert.ps[i].RegisterUniform("DownsampleFactor");
|
||||||
m_convert.ps[i].RegisterUniform("Weight");
|
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.Uniform2iv(0, clamp_min.v);
|
||||||
prog.Uniform1i(1, downsample_factor);
|
prog.Uniform1i(1, downsample_factor);
|
||||||
prog.Uniform1f(2, static_cast<float>(downsample_factor * 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);
|
OMSetDepthStencilState(m_convert.dss);
|
||||||
OMSetBlendState(false);
|
OMSetBlendState(false);
|
||||||
|
|||||||
@ -3154,11 +3154,12 @@ void GSDeviceVK::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32
|
|||||||
int downsample_factor;
|
int downsample_factor;
|
||||||
int pad0;
|
int pad0;
|
||||||
float weight;
|
float weight;
|
||||||
float pad1[3];
|
float step_multiplier;
|
||||||
|
float pad1[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
const Uniforms uniforms = {
|
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));
|
SetUtilityPushConstants(&uniforms, sizeof(uniforms));
|
||||||
|
|
||||||
const ShaderConvert shader = ShaderConvert::DOWNSAMPLE_COPY;
|
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"),
|
FSUI_NSTR("Align to Native - with Texture Offset"),
|
||||||
};
|
};
|
||||||
static constexpr const char* s_native_scaling_options[] = {
|
static constexpr const char* s_native_scaling_options[] = {
|
||||||
FSUI_NSTR("Normal (Default)"),
|
FSUI_NSTR("Off (Default)"),
|
||||||
|
FSUI_NSTR("Normal"),
|
||||||
FSUI_NSTR("Aggressive"),
|
FSUI_NSTR("Aggressive"),
|
||||||
FSUI_NSTR("Off"),
|
FSUI_NSTR("Normal (Maintain Upscale)"),
|
||||||
|
FSUI_NSTR("Aggressive (Maintain Upscale)"),
|
||||||
};
|
};
|
||||||
static constexpr const char* s_round_sprite_options[] = {
|
static constexpr const char* s_round_sprite_options[] = {
|
||||||
FSUI_NSTR("Off (Default)"),
|
FSUI_NSTR("Off (Default)"),
|
||||||
|
|||||||
@ -3,4 +3,4 @@
|
|||||||
|
|
||||||
/// Version number for GS and other shaders. Increment whenever any of the contents of the
|
/// Version number for GS and other shaders. Increment whenever any of the contents of the
|
||||||
/// shaders change, to invalidate the cache.
|
/// 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