GPU/HW: Add 'Force Round Upscaled Texture Coordinates'

This commit is contained in:
Stenzek 2024-06-16 19:06:46 +10:00
parent 1582b2ae5d
commit 8455c9c3c6
No known key found for this signature in database
14 changed files with 199 additions and 110 deletions

View file

@ -4142,6 +4142,7 @@ void FullscreenUI::DrawDisplaySettingsPage()
SettingsInterface* bsi = GetEditingSettingsInterface();
const bool game_settings = IsEditingGameSettings(bsi);
const u32 resolution_scale = GetEffectiveUIntSetting(bsi, "GPU", "ResolutionScale", 1);
BeginMenuButtons();
@ -4298,43 +4299,46 @@ void FullscreenUI::DrawDisplaySettingsPage()
"GPU", "UseSoftwareRendererForReadbacks", false);
}
if (is_hardware)
{
MenuHeading(FSUI_CSTR("Rendering"));
DrawIntListSetting(
bsi, FSUI_CSTR("Internal Resolution"),
FSUI_CSTR("Scales internal VRAM resolution by the specified multiplier. Some games require 1x VRAM resolution."),
"GPU", "ResolutionScale", 1, resolution_scales.data(), resolution_scales.size(), true, 0, is_hardware);
"GPU", "ResolutionScale", 1, resolution_scales.data(), resolution_scales.size(), true, 0);
DrawEnumSetting(
bsi, FSUI_CSTR("Texture Filtering"), FSUI_CSTR("Smooths out the blockiness of magnified textures on 3D objects."),
"GPU", "TextureFilter", Settings::DEFAULT_GPU_TEXTURE_FILTER, &Settings::ParseTextureFilterName,
&Settings::GetTextureFilterName, &Settings::GetTextureFilterDisplayName, GPUTextureFilter::Count, is_hardware);
DrawEnumSetting(bsi, FSUI_CSTR("Texture Filtering"),
FSUI_CSTR("Smooths out the blockiness of magnified textures on 3D objects."), "GPU",
"TextureFilter", Settings::DEFAULT_GPU_TEXTURE_FILTER, &Settings::ParseTextureFilterName,
&Settings::GetTextureFilterName, &Settings::GetTextureFilterDisplayName, GPUTextureFilter::Count);
DrawEnumSetting(bsi, FSUI_CSTR("Line Detection"),
FSUI_CSTR("Attempts to detect one pixel high/wide lines that rely on non-upscaled rasterization "
"behavior, filling in gaps introduced by upscaling."),
"GPU", "LineDetectMode", Settings::DEFAULT_GPU_LINE_DETECT_MODE, &Settings::ParseLineDetectModeName,
&Settings::GetLineDetectModeName, &Settings::GetLineDetectModeDisplayName, GPULineDetectMode::Count,
is_hardware);
resolution_scale > 1);
DrawToggleSetting(bsi, FSUI_CSTR("True Color Rendering"),
FSUI_CSTR("Disables dithering and uses the full 8 bits per channel of color information."), "GPU",
"TrueColor", true, is_hardware);
"TrueColor", true);
DrawToggleSetting(
bsi, FSUI_CSTR("True Color Debanding"),
FSUI_CSTR("Applies modern dithering techniques to further smooth out gradients when true color is enabled."), "GPU",
"Debanding", false, is_hardware && bsi->GetBoolValue("GPU", "TrueColor", false));
FSUI_CSTR("Applies modern dithering techniques to further smooth out gradients when true color is enabled."),
"GPU", "Debanding", false, bsi->GetBoolValue("GPU", "TrueColor", false));
DrawToggleSetting(bsi, FSUI_CSTR("Widescreen Hack"),
FSUI_CSTR("Increases the field of view from 4:3 to the chosen display aspect ratio in 3D games."),
"GPU", "WidescreenHack", false, is_hardware);
"GPU", "WidescreenHack", false);
DrawToggleSetting(
bsi, FSUI_CSTR("PGXP Geometry Correction"),
FSUI_CSTR("Reduces \"wobbly\" polygons by attempting to preserve the fractional component through memory "
"transfers."),
"GPU", "PGXPEnable", false);
}
MenuHeading(FSUI_CSTR("Screen Display"));
@ -4401,12 +4405,6 @@ void FullscreenUI::DrawDisplaySettingsPage()
"ScreenshotQuality", Settings::DEFAULT_DISPLAY_SCREENSHOT_QUALITY, 1, 100, "%d%%");
MenuHeading(FSUI_CSTR("Enhancements"));
DrawToggleSetting(
bsi, FSUI_CSTR("Scaled Dithering"),
FSUI_CSTR("Scales the dithering pattern with the internal rendering resolution, making it less noticeable. "
"Usually safe to enable."),
"GPU", "ScaledDithering", true, is_hardware);
DrawToggleSetting(
bsi, FSUI_CSTR("Disable Interlacing"),
FSUI_CSTR("Disables interlaced rendering and display in the GPU. Some games can render in 480p this way, "
@ -4421,10 +4419,29 @@ void FullscreenUI::DrawDisplaySettingsPage()
bsi, FSUI_CSTR("Force 4:3 For 24-Bit Display"),
FSUI_CSTR("Switches back to 4:3 display aspect ratio when displaying 24-bit content, usually FMVs."), "Display",
"Force4_3For24Bit", false);
if (is_hardware)
{
const GPUTextureFilter texture_filtering =
Settings::ParseTextureFilterName(
GetEffectiveTinyStringSetting(bsi, "GPU", "TextureFilter",
Settings::GetTextureFilterName(Settings::DEFAULT_GPU_TEXTURE_FILTER)))
.value_or(Settings::DEFAULT_GPU_TEXTURE_FILTER);
DrawToggleSetting(
bsi, FSUI_CSTR("Scaled Dithering"),
FSUI_CSTR("Scales the dithering pattern with the internal rendering resolution, making it less noticeable. "
"Usually safe to enable."),
"GPU", "ScaledDithering", true, resolution_scale > 1);
DrawToggleSetting(bsi, FSUI_CSTR("Chroma Smoothing For 24-Bit Display"),
FSUI_CSTR("Smooths out blockyness between colour transitions in 24-bit content, usually FMVs. Only "
"applies to the hardware renderers."),
FSUI_CSTR("Smooths out blockyness between colour transitions in 24-bit content, usually FMVs."),
"GPU", "ChromaSmoothing24Bit", false);
DrawToggleSetting(
bsi, FSUI_CSTR("Round Upscaled Texture Coordinates"),
FSUI_CSTR("Rounds texture coordinates instead of flooring when upscaling. Can fix misaligned "
"textures in some games, but break others, and is incompatible with texture filtering."),
"GPU", "ForceRoundTextureCoordinates", false,
resolution_scale > 1 && texture_filtering == GPUTextureFilter::Nearest);
MenuHeading(FSUI_CSTR("PGXP (Precision Geometry Transform Pipeline)"));
@ -4439,16 +4456,17 @@ void FullscreenUI::DrawDisplaySettingsPage()
bsi, FSUI_CSTR("Perspective Correct Colors"),
FSUI_CSTR("Uses perspective-correct interpolation for colors, which can improve visuals in some games."), "GPU",
"PGXPColorCorrection", false, pgxp_enabled);
DrawToggleSetting(bsi, FSUI_CSTR("Culling Correction"),
FSUI_CSTR("Increases the precision of polygon culling, reducing the number of holes in geometry."),
"GPU", "PGXPCulling", true, pgxp_enabled);
DrawToggleSetting(
bsi, FSUI_CSTR("Culling Correction"),
FSUI_CSTR("Increases the precision of polygon culling, reducing the number of holes in geometry."), "GPU",
"PGXPCulling", true, pgxp_enabled);
DrawToggleSetting(
bsi, FSUI_CSTR("Preserve Projection Precision"),
FSUI_CSTR("Adds additional precision to PGXP data post-projection. May improve visuals in some games."), "GPU",
"PGXPPreserveProjFP", false, pgxp_enabled);
DrawToggleSetting(bsi, FSUI_CSTR("Depth Buffer"),
FSUI_CSTR("Reduces polygon Z-fighting through depth testing. Low compatibility with games."), "GPU",
"PGXPDepthBuffer", false, pgxp_enabled && texture_correction_enabled);
FSUI_CSTR("Reduces polygon Z-fighting through depth testing. Low compatibility with games."),
"GPU", "PGXPDepthBuffer", false, pgxp_enabled && texture_correction_enabled);
DrawToggleSetting(bsi, FSUI_CSTR("CPU Mode"),
FSUI_CSTR("Uses PGXP for all instructions, not just memory operations."), "GPU", "PGXPCPU", false,
pgxp_enabled);
@ -4461,6 +4479,7 @@ void FullscreenUI::DrawDisplaySettingsPage()
DrawToggleSetting(bsi, FSUI_CSTR("Preload Replacement Textures"),
FSUI_CSTR("Loads all replacement texture to RAM, reducing stuttering at runtime."),
"TextureReplacements", "PreloadTextures", false);
}
EndMenuButtons();
}
@ -7591,6 +7610,8 @@ TRANSLATE_NOOP("FullscreenUI", "Rewind for {0} frames, lasting {1:.2f} seconds w
TRANSLATE_NOOP("FullscreenUI", "Rewind is disabled because runahead is enabled. Runahead will significantly increase system requirements.");
TRANSLATE_NOOP("FullscreenUI", "Rewind is not enabled. Please note that enabling rewind may significantly increase system requirements.");
TRANSLATE_NOOP("FullscreenUI", "Rich presence inactive or unsupported.");
TRANSLATE_NOOP("FullscreenUI", "Round Upscaled Texture Coordinates");
TRANSLATE_NOOP("FullscreenUI", "Rounds texture coordinates instead of flooring when upscaling. Can fix misaligned textures in some games, but break others.");
TRANSLATE_NOOP("FullscreenUI", "Runahead");
TRANSLATE_NOOP("FullscreenUI", "Runahead/Rewind");
TRANSLATE_NOOP("FullscreenUI", "Runs the software renderer in parallel for VRAM readbacks. On some systems, this may result in greater performance.");
@ -7675,7 +7696,7 @@ TRANSLATE_NOOP("FullscreenUI", "Simulates the system ahead of time and rolls bac
TRANSLATE_NOOP("FullscreenUI", "Skip Duplicate Frame Display");
TRANSLATE_NOOP("FullscreenUI", "Skips the presentation/display of frames that are not unique. Can result in worse frame pacing.");
TRANSLATE_NOOP("FullscreenUI", "Slow Boot");
TRANSLATE_NOOP("FullscreenUI", "Smooths out blockyness between colour transitions in 24-bit content, usually FMVs. Only applies to the hardware renderers.");
TRANSLATE_NOOP("FullscreenUI", "Smooths out blockyness between colour transitions in 24-bit content, usually FMVs.");
TRANSLATE_NOOP("FullscreenUI", "Smooths out the blockiness of magnified textures on 3D objects.");
TRANSLATE_NOOP("FullscreenUI", "Sort By");
TRANSLATE_NOOP("FullscreenUI", "Sort Reversed");

View file

@ -34,7 +34,7 @@ namespace GameDatabase {
enum : u32
{
GAME_DATABASE_CACHE_SIGNATURE = 0x45434C48,
GAME_DATABASE_CACHE_VERSION = 8,
GAME_DATABASE_CACHE_VERSION = 9,
};
static Entry* GetMutableEntry(std::string_view serial);
@ -63,6 +63,7 @@ static constexpr const std::array<const char*, static_cast<u32>(GameDatabase::Tr
"ForceInterpreter",
"ForceSoftwareRenderer",
"ForceSoftwareRendererForReadbacks",
"ForceRoundTextureCoordinates",
"ForceInterlacing",
"DisableTrueColor",
"DisableUpscaling",
@ -88,6 +89,7 @@ static constexpr const std::array<const char*, static_cast<u32>(GameDatabase::Tr
TRANSLATE_NOOP("GameDatabase", "Force Interpreter"),
TRANSLATE_NOOP("GameDatabase", "Force Software Renderer"),
TRANSLATE_NOOP("GameDatabase", "Force Software Renderer For Readbacks"),
TRANSLATE_NOOP("GameDatabase", "Force Round Texture Coordinates"),
TRANSLATE_NOOP("GameDatabase", "Force Interlacing"),
TRANSLATE_NOOP("GameDatabase", "Disable True Color"),
TRANSLATE_NOOP("GameDatabase", "Disable Upscaling"),
@ -434,6 +436,11 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes
settings.gpu_use_software_renderer_for_readbacks = true;
}
if (HasTrait(Trait::ForceRoundUpscaledTextureCoordinates))
{
settings.gpu_force_round_texcoords = true;
}
if (HasTrait(Trait::ForceInterlacing))
{
if (display_osd_messages && settings.gpu_disable_interlacing)

View file

@ -31,6 +31,7 @@ enum class Trait : u32
ForceInterpreter,
ForceSoftwareRenderer,
ForceSoftwareRendererForReadbacks,
ForceRoundUpscaledTextureCoordinates,
ForceInterlacing,
DisableTrueColor,
DisableUpscaling,

View file

@ -198,7 +198,9 @@ bool GPU_HW::Initialize()
m_per_sample_shading = g_settings.gpu_per_sample_shading && features.per_sample_shading;
m_true_color = g_settings.gpu_true_color;
m_debanding = g_settings.gpu_debanding;
m_scaled_dithering = g_settings.gpu_scaled_dithering;
m_scaled_dithering = (m_resolution_scale > 1 && g_settings.gpu_scaled_dithering);
m_force_round_texcoords = (m_resolution_scale > 1 && g_settings.gpu_force_round_texcoords &&
g_settings.gpu_texture_filter == GPUTextureFilter::Nearest);
m_texture_filtering = g_settings.gpu_texture_filter;
m_line_detect_mode = (m_resolution_scale > 1) ? g_settings.gpu_line_detect_mode : GPULineDetectMode::Disabled;
m_clamp_uvs = ShouldClampUVs();
@ -336,7 +338,10 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
const bool shaders_changed =
(m_resolution_scale != resolution_scale || m_multisamples != multisamples ||
m_true_color != g_settings.gpu_true_color || m_debanding != g_settings.gpu_debanding ||
m_per_sample_shading != per_sample_shading || m_scaled_dithering != g_settings.gpu_scaled_dithering ||
m_per_sample_shading != per_sample_shading ||
m_scaled_dithering != (resolution_scale > 1 && g_settings.gpu_scaled_dithering) ||
m_force_round_texcoords != (resolution_scale > 1 && g_settings.gpu_force_round_texcoords &&
g_settings.gpu_texture_filter == GPUTextureFilter::Nearest) ||
m_texture_filtering != g_settings.gpu_texture_filter || m_clamp_uvs != clamp_uvs ||
m_downsample_mode != downsample_mode ||
(m_downsample_mode == GPUDownsampleMode::Box &&
@ -386,7 +391,9 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
m_per_sample_shading = per_sample_shading;
m_true_color = g_settings.gpu_true_color;
m_debanding = g_settings.gpu_debanding;
m_scaled_dithering = g_settings.gpu_scaled_dithering;
m_scaled_dithering = (m_resolution_scale > 1 && g_settings.gpu_scaled_dithering);
m_force_round_texcoords = (m_resolution_scale > 1 && g_settings.gpu_force_round_texcoords &&
g_settings.gpu_texture_filter == GPUTextureFilter::Nearest);
m_texture_filtering = g_settings.gpu_texture_filter;
m_line_detect_mode = (m_resolution_scale > 1) ? g_settings.gpu_line_detect_mode : GPULineDetectMode::Disabled;
m_clamp_uvs = clamp_uvs;
@ -646,12 +653,14 @@ void GPU_HW::PrintSettingsToLog()
INFO_LOG("Multisampling: {}x{}", m_multisamples, m_per_sample_shading ? " (per sample shading)" : "");
INFO_LOG("Dithering: {}{}", m_true_color ? "Disabled" : "Enabled",
(!m_true_color && m_scaled_dithering) ? " (Scaled)" : ((m_true_color && m_debanding) ? " (Debanding)" : ""));
INFO_LOG("Force round texture coordinates: {}", m_force_round_texcoords ? "Enabled" : "Disabled");
INFO_LOG("Texture Filtering: {}", Settings::GetTextureFilterDisplayName(m_texture_filtering));
INFO_LOG("Dual-source blending: {}", m_supports_dual_source_blend ? "Supported" : "Not supported");
INFO_LOG("Clamping UVs: {}", m_clamp_uvs ? "YES" : "NO");
INFO_LOG("Depth buffer: {}", m_pgxp_depth_buffer ? "YES" : "NO");
INFO_LOG("Downsampling: {}", Settings::GetDownsampleModeDisplayName(m_downsample_mode));
INFO_LOG("Wireframe rendering: {}", Settings::GetGPUWireframeModeDisplayName(m_wireframe_mode));
INFO_LOG("Line detection: {}", Settings::GetLineDetectModeDisplayName(m_line_detect_mode));
INFO_LOG("Using software renderer for readbacks: {}", m_sw_renderer ? "YES" : "NO");
}
@ -858,8 +867,9 @@ bool GPU_HW::CompilePipelines()
{
const std::string fs = shadergen.GenerateBatchFragmentShader(
static_cast<BatchRenderMode>(render_mode), static_cast<GPUTransparencyMode>(transparency_mode),
static_cast<GPUTextureMode>(texture_mode), m_texture_filtering, ConvertToBoolUnchecked(dithering),
ConvertToBoolUnchecked(interlacing), ConvertToBoolUnchecked(check_mask));
static_cast<BatchTextureMode>(texture_mode), m_texture_filtering, m_force_round_texcoords,
ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing),
ConvertToBoolUnchecked(check_mask));
if (!(batch_fragment_shaders[render_mode][transparency_mode][texture_mode][check_mask][dithering]
[interlacing] = g_gpu_device->CreateShader(GPUShaderStage::Fragment,
@ -936,7 +946,7 @@ bool GPU_HW::CompilePipelines()
{
for (u8 check_mask = 0; check_mask < 2; check_mask++)
{
const bool textured = (static_cast<GPUTextureMode>(texture_mode) != GPUTextureMode::Disabled);
const bool textured = (static_cast<BatchTextureMode>(texture_mode) != BatchTextureMode::Disabled);
const bool use_shader_blending =
(render_mode == static_cast<u8>(BatchRenderMode::ShaderBlend) &&
((textured &&
@ -2498,7 +2508,7 @@ ALWAYS_INLINE_RELEASE bool GPU_HW::NeedsTwoPassRendering() const
// We need two-pass rendering when using BG-FG blending and texturing, as the transparency can be enabled
// on a per-pixel basis, and the opaque pixels shouldn't be blended at all.
return (m_batch.texture_mode != GPUTextureMode::Disabled &&
return (m_batch.texture_mode != BatchTextureMode::Disabled &&
(m_batch.transparency_mode == GPUTransparencyMode::BackgroundMinusForeground ||
(!m_supports_dual_source_blend && m_batch.transparency_mode != GPUTransparencyMode::Disabled)));
}
@ -2970,7 +2980,7 @@ void GPU_HW::DispatchRenderCommand()
{
const GPURenderCommand rc{m_render_command.bits};
GPUTextureMode texture_mode = GPUTextureMode::Disabled;
BatchTextureMode texture_mode = BatchTextureMode::Disabled;
if (rc.IsTexturingEnabled())
{
// texture page changed - check that the new page doesn't intersect the drawing area
@ -3030,9 +3040,9 @@ void GPU_HW::DispatchRenderCommand()
}
}
texture_mode = (m_draw_mode.mode_reg.texture_mode == GPUTextureMode::Reserved_Direct16Bit2) ?
GPUTextureMode::Direct16Bit :
m_draw_mode.mode_reg.texture_mode;
texture_mode = (m_draw_mode.mode_reg.texture_mode == GPUTextureMode::Reserved_Direct16Bit) ?
BatchTextureMode::Direct16Bit :
static_cast<BatchTextureMode>(m_draw_mode.mode_reg.texture_mode.GetValue());
}
// has any state changed which requires a new batch?
@ -3055,7 +3065,7 @@ void GPU_HW::DispatchRenderCommand()
// transparency mode change
const bool check_mask_before_draw = m_GPUSTAT.check_mask_before_draw;
if (transparency_mode != GPUTransparencyMode::Disabled &&
(texture_mode == GPUTextureMode::Disabled || !NeedsShaderBlending(transparency_mode, check_mask_before_draw)))
(texture_mode == BatchTextureMode::Disabled || !NeedsShaderBlending(transparency_mode, check_mask_before_draw)))
{
static constexpr float transparent_alpha[4][2] = {{0.5f, 0.5f}, {1.0f, 1.0f}, {1.0f, 1.0f}, {0.25f, 1.0f}};

View file

@ -33,6 +33,19 @@ public:
ShaderBlend
};
enum class BatchTextureMode : u8
{
Palette4Bit,
Palette8Bit,
Direct16Bit,
Disabled,
MaxCount,
};
static_assert(static_cast<u8>(BatchTextureMode::Palette4Bit) == static_cast<u8>(GPUTextureMode::Palette4Bit) &&
static_cast<u8>(BatchTextureMode::Palette8Bit) == static_cast<u8>(GPUTextureMode::Palette8Bit) &&
static_cast<u8>(BatchTextureMode::Direct16Bit) == static_cast<u8>(GPUTextureMode::Direct16Bit));
GPU_HW();
~GPU_HW() override;
@ -58,7 +71,7 @@ private:
MAX_BATCH_VERTEX_COUNTER_IDS = 65536 - 2,
MAX_VERTICES_FOR_RECTANGLE = 6 * (((MAX_PRIMITIVE_WIDTH + (TEXTURE_PAGE_WIDTH - 1)) / TEXTURE_PAGE_WIDTH) + 1u) *
(((MAX_PRIMITIVE_HEIGHT + (TEXTURE_PAGE_HEIGHT - 1)) / TEXTURE_PAGE_HEIGHT) + 1u),
NUM_TEXTURE_MODES = 4,
NUM_TEXTURE_MODES = static_cast<u32>(BatchTextureMode::MaxCount),
};
enum : u8
{
@ -88,7 +101,7 @@ private:
struct BatchConfig
{
GPUTextureMode texture_mode = GPUTextureMode::Disabled;
BatchTextureMode texture_mode = BatchTextureMode::Disabled;
GPUTransparencyMode transparency_mode = GPUTransparencyMode::Disabled;
bool dithering = false;
bool interlacing = false;
@ -235,6 +248,7 @@ private:
bool m_per_sample_shading : 1 = false;
bool m_scaled_dithering : 1 = false;
bool m_disable_color_perspective : 1 = false;
bool m_force_round_texcoords = false;
GPUTextureFilter m_texture_filtering = GPUTextureFilter::Nearest;
GPULineDetectMode m_line_detect_mode = GPULineDetectMode::Disabled;

View file

@ -630,15 +630,14 @@ void FilteredSampleFromVRAM(uint4 texpage, float2 coords, float4 uv_limits,
}
}
std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMode render_mode,
GPUTransparencyMode transparency, GPUTextureMode texture_mode,
GPUTextureFilter texture_filtering, bool dithering,
bool interlacing, bool check_mask)
std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(
GPU_HW::BatchRenderMode render_mode, GPUTransparencyMode transparency, GPU_HW::BatchTextureMode texture_mode,
GPUTextureFilter texture_filtering, bool force_round_texcoords, bool dithering, bool interlacing, bool check_mask)
{
// TODO: don't write depth for shader blend
DebugAssert(transparency == GPUTransparencyMode::Disabled || render_mode == GPU_HW::BatchRenderMode::ShaderBlend);
const bool textured = (texture_mode != GPUTextureMode::Disabled);
const bool textured = (texture_mode != GPU_HW::BatchTextureMode::Disabled);
const bool shader_blending = (render_mode == GPU_HW::BatchRenderMode::ShaderBlend &&
(transparency != GPUTransparencyMode::Disabled || check_mask));
const bool use_dual_source = (!shader_blending && m_supports_dual_source_blend &&
@ -656,9 +655,10 @@ std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMod
DefineMacro(ss, "CHECK_MASK_BIT", check_mask);
DefineMacro(ss, "TEXTURED", textured);
DefineMacro(ss, "PALETTE",
texture_mode == GPUTextureMode::Palette4Bit || texture_mode == GPUTextureMode::Palette8Bit);
DefineMacro(ss, "PALETTE_4_BIT", texture_mode == GPUTextureMode::Palette4Bit);
DefineMacro(ss, "PALETTE_8_BIT", texture_mode == GPUTextureMode::Palette8Bit);
texture_mode == GPU_HW::BatchTextureMode::Palette4Bit ||
texture_mode == GPU_HW::BatchTextureMode::Palette8Bit);
DefineMacro(ss, "PALETTE_4_BIT", texture_mode == GPU_HW::BatchTextureMode::Palette4Bit);
DefineMacro(ss, "PALETTE_8_BIT", texture_mode == GPU_HW::BatchTextureMode::Palette8Bit);
DefineMacro(ss, "DITHERING", dithering);
DefineMacro(ss, "DITHERING_SCALED", m_scaled_dithering);
// Debanding requires true color to work correctly.
@ -669,6 +669,7 @@ std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMod
DefineMacro(ss, "UV_LIMITS", m_uv_limits);
DefineMacro(ss, "USE_DUAL_SOURCE", use_dual_source);
DefineMacro(ss, "WRITE_MASK_AS_DEPTH", m_write_mask_as_depth);
DefineMacro(ss, "FORCE_ROUND_TEXCOORDS", force_round_texcoords);
WriteCommonFunctions(ss);
WriteBatchUniformBuffer(ss);
@ -727,7 +728,7 @@ uint2 FloatToIntegerCoords(float2 coords)
{
// With the vertex offset applied at 1x resolution scale, we want to round the texture coordinates.
// Floor them otherwise, as it currently breaks when upscaling as the vertex offset is not applied.
return uint2((RESOLUTION_SCALE == 1u) ? roundEven(coords) : floor(coords));
return uint2((RESOLUTION_SCALE == 1u || FORCE_ROUND_TEXCOORDS != 0) ? roundEven(coords) : floor(coords));
}
float4 SampleFromVRAM(uint4 texpage, float2 coords)

View file

@ -16,8 +16,9 @@ public:
std::string GenerateBatchVertexShader(bool textured, bool pgxp_depth);
std::string GenerateBatchFragmentShader(GPU_HW::BatchRenderMode render_mode, GPUTransparencyMode transparency,
GPUTextureMode texture_mode, GPUTextureFilter texture_filtering,
bool dithering, bool interlacing, bool check_mask);
GPU_HW::BatchTextureMode texture_mode, GPUTextureFilter texture_filtering,
bool force_round_texcoords, bool dithering, bool interlacing,
bool check_mask);
std::string GenerateWireframeGeometryShader();
std::string GenerateWireframeFragmentShader();
std::string GenerateVRAMReadFragmentShader();

View file

@ -53,8 +53,7 @@ enum class GPUTextureMode : u8
Palette4Bit = 0,
Palette8Bit = 1,
Direct16Bit = 2,
Reserved_Direct16Bit2 = 3, // Not used.
Disabled = 3 // Not a register value
Reserved_Direct16Bit = 3, // Not used.
};
IMPLEMENT_ENUM_CLASS_BITWISE_OPERATORS(GPUTextureMode);

View file

@ -197,6 +197,7 @@ void Settings::Load(SettingsInterface& si)
gpu_true_color = si.GetBoolValue("GPU", "TrueColor", true);
gpu_debanding = si.GetBoolValue("GPU", "Debanding", false);
gpu_scaled_dithering = si.GetBoolValue("GPU", "ScaledDithering", true);
gpu_force_round_texcoords = si.GetBoolValue("GPU", "ForceRoundTextureCoordinates", false);
gpu_texture_filter =
ParseTextureFilterName(
si.GetStringValue("GPU", "TextureFilter", GetTextureFilterName(DEFAULT_GPU_TEXTURE_FILTER)).c_str())
@ -495,6 +496,7 @@ void Settings::Save(SettingsInterface& si, bool ignore_base) const
si.SetBoolValue("GPU", "TrueColor", gpu_true_color);
si.SetBoolValue("GPU", "Debanding", gpu_debanding);
si.SetBoolValue("GPU", "ScaledDithering", gpu_scaled_dithering);
si.SetBoolValue("GPU", "ForceRoundTextureCoordinates", gpu_force_round_texcoords);
si.SetStringValue("GPU", "TextureFilter", GetTextureFilterName(gpu_texture_filter));
si.SetStringValue("GPU", "LineDetectMode", GetLineDetectModeName(gpu_line_detect_mode));
si.SetStringValue("GPU", "DownsampleMode", GetDownsampleModeName(gpu_downsample_mode));
@ -701,6 +703,7 @@ void Settings::FixIncompatibleSettings(bool display_osd_messages)
g_settings.gpu_true_color = false;
g_settings.gpu_debanding = false;
g_settings.gpu_scaled_dithering = false;
g_settings.gpu_force_round_texcoords = false;
g_settings.gpu_texture_filter = GPUTextureFilter::Nearest;
g_settings.gpu_line_detect_mode = GPULineDetectMode::Disabled;
g_settings.gpu_disable_interlacing = false;

View file

@ -117,6 +117,7 @@ struct Settings
bool gpu_true_color : 1 = true;
bool gpu_debanding : 1 = false;
bool gpu_scaled_dithering : 1 = true;
bool gpu_force_round_texcoords : 1 = false;
GPUTextureFilter gpu_texture_filter = DEFAULT_GPU_TEXTURE_FILTER;
GPULineDetectMode gpu_line_detect_mode = DEFAULT_GPU_LINE_DETECT_MODE;
GPUDownsampleMode gpu_downsample_mode = DEFAULT_GPU_DOWNSAMPLE_MODE;

View file

@ -4015,6 +4015,7 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
g_settings.gpu_true_color != old_settings.gpu_true_color ||
g_settings.gpu_debanding != old_settings.gpu_debanding ||
g_settings.gpu_scaled_dithering != old_settings.gpu_scaled_dithering ||
g_settings.gpu_force_round_texcoords != old_settings.gpu_force_round_texcoords ||
g_settings.gpu_texture_filter != old_settings.gpu_texture_filter ||
g_settings.gpu_line_detect_mode != old_settings.gpu_line_detect_mode ||
g_settings.gpu_disable_interlacing != old_settings.gpu_disable_interlacing ||

View file

@ -89,7 +89,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
connect(m_ui.adapter, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onAdapterChanged);
connect(m_ui.resolutionScale, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onTrueColorChanged);
&GraphicsSettingsWidget::updateResolutionDependentOptions);
connect(m_ui.textureFiltering, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::updateResolutionDependentOptions);
connect(m_ui.displayAspectRatio, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onAspectRatioChanged);
connect(m_ui.gpuDownsampleMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
@ -143,6 +145,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.scaledDithering, "GPU", "ScaledDithering", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useSoftwareRendererForReadbacks, "GPU",
"UseSoftwareRendererForReadbacks", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.forceRoundedTexcoords, "GPU", "ForceRoundTextureCoordinates",
false);
connect(m_ui.fullscreenMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onFullscreenModeChanged);
@ -230,7 +234,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
updateRendererDependentOptions();
onAspectRatioChanged();
onDownsampleModeChanged();
onTrueColorChanged();
updateResolutionDependentOptions();
onEnableAnyTextureReplacementsChanged();
onEnableVRAMWriteDumpingChanged();
onShowDebugSettingsChanged(QtHost::ShouldShowDebugOptions());
@ -373,6 +377,10 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
m_ui.useSoftwareRendererForReadbacks, tr("Software Renderer Readbacks"), tr("Unchecked"),
tr("Runs the software renderer in parallel for VRAM readbacks. On some systems, this may result in greater "
"performance when using graphical enhancements with the hardware renderer."));
dialog->registerWidgetHelp(
m_ui.forceRoundedTexcoords, tr("Round Upscaled Texture Coordinates"), tr("Unchecked"),
tr("Rounds texture coordinates instead of flooring when upscaling. Can fix misaligned textures in some games, but "
"break others, and is incompatible with texture filtering."));
// PGXP Tab
@ -796,6 +804,20 @@ void GraphicsSettingsWidget::onAspectRatioChanged()
m_ui.customAspectRatioSeparator->setVisible(is_custom);
}
void GraphicsSettingsWidget::updateResolutionDependentOptions()
{
const int scale = m_dialog->getEffectiveIntValue("GPU", "ResolutionScale", 1);
const GPUTextureFilter texture_filtering =
Settings::ParseTextureFilterName(
m_dialog
->getEffectiveStringValue("GPU", "TextureFilter",
Settings::GetTextureFilterName(Settings::DEFAULT_GPU_TEXTURE_FILTER))
.c_str())
.value_or(Settings::DEFAULT_GPU_TEXTURE_FILTER);
m_ui.forceRoundedTexcoords->setEnabled(scale > 1 && texture_filtering == GPUTextureFilter::Nearest);
onTrueColorChanged();
}
void GraphicsSettingsWidget::onMSAAModeChanged()
{
const int index = m_ui.msaaMode->currentIndex();
@ -816,8 +838,8 @@ void GraphicsSettingsWidget::onMSAAModeChanged()
void GraphicsSettingsWidget::onTrueColorChanged()
{
const int resolution_scale = m_ui.resolutionScale->currentIndex();
const bool true_color = m_ui.trueColor->isChecked();
const int resolution_scale = m_dialog->getEffectiveIntValue("GPU", "ResolutionScale", 1);
const bool true_color = m_dialog->getEffectiveBoolValue("GPU", "TrueColor", false);
const bool allow_scaled_dithering = (resolution_scale != 1 && !true_color);
const bool allow_debanding = true_color;
m_ui.scaledDithering->setEnabled(allow_scaled_dithering);

View file

@ -29,6 +29,7 @@ private Q_SLOTS:
void onAdapterChanged();
void onAspectRatioChanged();
void updateResolutionDependentOptions();
void onMSAAModeChanged();
void onTrueColorChanged();
void onDownsampleModeChanged();

View file

@ -468,10 +468,10 @@
</item>
<item row="2" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QCheckBox" name="debanding">
<item row="1" column="0">
<widget class="QCheckBox" name="gpuThread">
<property name="text">
<string>True Color Debanding</string>
<string>Threaded Rendering</string>
</property>
</widget>
</item>
@ -489,10 +489,17 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="gpuThread">
<item row="0" column="0">
<widget class="QCheckBox" name="debanding">
<property name="text">
<string>Threaded Rendering</string>
<string>True Color Debanding</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="forceRoundedTexcoords">
<property name="text">
<string>Round Upscaled Texture Coordinates</string>
</property>
</widget>
</item>