Limit supersampling on high-resolution displays by opt-in policy

This commit is contained in:
Shokunin
2026-10-21 08:45:11 -07:00
parent 5025b7cdf8
commit 7a015840db
8 changed files with 44 additions and 5 deletions
+5
View File
@@ -702,6 +702,7 @@ player's `settings.toml`, and a game may ship a default the same way:
[video]
internal_resolution = "4k" # native | 720p | 1080p | 1440p | 4k | 5k | 8k | display, or a number of lines
resolution_reference_lines = 240 # game.toml only: the title's usual display height (120..1024)
supersample_disable_at_lines = 0 # game.toml only: supersample 1.0 at/above this display height (0 = off, 240..8640)
match_display_max_lines = 0 # game.toml only: cap on the display height Match display uses (0 = none, 240..8640)
```
@@ -712,6 +713,10 @@ past the full-VRAM surface. The high-resolution window then engages, and
dynamic resolution cannot step there. A title whose GPU budget is set for
4K lines sets 2160.
`supersample_disable_at_lines` uses the physical monitor height before the cap.
At or above its threshold the effective factor is 1.0; the saved factor is
retained for smaller monitors. Zero preserves the default behaviour.
A preset is a target height. The runtime renders at the integer scale
`S = ceil(target / resolution_reference_lines)`: at the default 240 lines,
720p is 3x, 1080p is 5x (1200 lines, area-resolved to 1080), 1440p 6x, 4K 9x,
+2
View File
@@ -213,6 +213,8 @@ on a fixed region -> next.
## 5. Status / Log (update every session)
- **2026-10-21 (BRIEF-4 Stage 1):** Reused #722 display-height cap and added opt-in `supersample_disable_at_lines`; unchanged defaults for other titles. Resolution, replay, config-parser and R4 default checks pass on Windows and macOS. R4 fullscreen 8K route cap restores 60 Hz but completion gaps remain (6 quiet / 7 loaded); no stage acceptance claimed. See R4 `analysis/STATUS.md`.
- **2026-10-21 (BRIEF-4 Stage 1):** Port recorded-route measurement support from `a9da7fce`; validation pending. No guest timing changes.
- **2026-10-07 — DuckStation texture authoring fidelity (beads-qi66).**
+7
View File
@@ -780,6 +780,13 @@ static RuntimeConfig parse_runtime_block(const toml::value& cfg, const fs::path&
}
rt.video_match_display_max_lines = static_cast<int>(n);
}
if (video.contains("supersample_disable_at_lines")) {
const auto n = toml::find<int64_t>(video, "supersample_disable_at_lines");
if (n != 0 && (n < 240 || n > 8640))
throw std::runtime_error(fmt::format(
"[video] supersample_disable_at_lines must be 0 or 240..8640: {}", n));
rt.video_supersample_disable_at_lines = static_cast<int>(n);
}
if (video.contains("window_width")) {
const auto n = toml::find<int64_t>(video, "window_width");
if (n < 640 || n > 7680) {
+2
View File
@@ -472,6 +472,8 @@ struct RuntimeConfig {
/* [video] match_display_max_lines: cap on the display height Match
* display (and its dynamic-resolution floor) resolves against; 0 = none. */
int video_match_display_max_lines = 0;
/* Disable target supersampling on displays at least this tall (0 = off). */
int video_supersample_disable_at_lines = 0;
// Optional initial window width declared by the title profile. Zero keeps
// the historical fit-to-display behavior; player settings may override it.
@@ -226,14 +226,17 @@ static void test_internal_resolution_game_toml() {
"resolution_reference_lines defaults to 240");
check(gc.runtime.video_match_display_max_lines == 0,
"match_display_max_lines defaults to 0 (no cap)");
check(gc.runtime.video_supersample_disable_at_lines == 0, "display SS policy defaults off");
fs::remove(p);
p = write_game_toml("psxrecomp_ir_match_cap.toml",
"[video]\n"
"internal_resolution = \"display\"\n"
"match_display_max_lines = 2160\n");
"match_display_max_lines = 2160\n"
"supersample_disable_at_lines = 2160\n");
gc = PSXRecompV4::load_game_config(p);
check(gc.runtime.video_match_display_max_lines == 2160, "match_display_max_lines parses");
check(gc.runtime.video_supersample_disable_at_lines == 2160, "display SS policy parses");
fs::remove(p);
p = write_game_toml("psxrecomp_ir_4k.toml",
@@ -257,6 +260,7 @@ static void test_internal_resolution_game_toml() {
"internal_resolution = 1\n",
"resolution_reference_lines = 50\n",
"match_display_max_lines = 100\n",
"supersample_disable_at_lines = 100\n",
"supersampling = 33\n" }) {
p = write_game_toml("psxrecomp_ir_bad.toml", std::string("[video]\n") + bad);
bool rejected = false;
+7
View File
@@ -143,6 +143,13 @@ static inline int psx_ss_parse_milli(const char *s) {
return (int)m;
}
/* Opt-in display policy; keep the saved factor intact for smaller displays. */
static inline int psx_ir_display_supersample(int ss_milli, int display_px_h,
int disable_at_lines) {
return disable_at_lines > 0 && display_px_h >= disable_at_lines
? PSX_SS_MILLI_MIN : ss_milli;
}
/* psx_resolve_internal_scale with the supersample factor on the target. */
static inline int psx_resolve_internal_scale_ss(int value, int ref_lines,
int display_px_h, int s_max,
+11 -4
View File
@@ -1279,6 +1279,11 @@ static int g_video_ss_milli = 1000; /* [video] supersample / PSX_SUPER
* full-VRAM surface, where the high-resolution window engages and dynamic
* resolution cannot step; a title can cap it at, say, 4K lines. */
static int g_video_match_max_lines = 0;
static int g_video_ss_disable_at_lines = 0;
static int display_supersample(SDL_Window *window) {
return psx_ir_display_supersample(g_video_ss_milli,
psx_sdl_display_pixel_height(window), g_video_ss_disable_at_lines);
}
static int match_display_px_h(SDL_Window *window) {
const int h = psx_sdl_display_pixel_height(window);
return (g_video_match_max_lines > 0 && h > g_video_match_max_lines)
@@ -1463,7 +1468,7 @@ static void apply_internal_resolution(int display_px_h) {
if (preset == PSX_IR_UNSET) return;
g_video_scale = psx_resolve_internal_scale_ss(preset, g_video_ref_lines,
display_px_h, video_scale_ceiling(),
g_video_ss_milli);
display_supersample(nullptr));
}
/* The value the launcher row starts on: the preset, or the legacy factor shown
@@ -17972,6 +17977,7 @@ int main(int argc, char** argv) {
g_video_internal_res = gc.runtime.video_internal_resolution;
g_video_ref_lines = gc.runtime.video_resolution_reference_lines;
g_video_match_max_lines = gc.runtime.video_match_display_max_lines;
g_video_ss_disable_at_lines = gc.runtime.video_supersample_disable_at_lines;
g_video_dynres = gc.runtime.video_dynamic_resolution ? 1 : 0;
g_video_dynres_min = gc.runtime.video_dynamic_resolution_min;
if (gc.runtime.video_window_width > 0) {
@@ -20462,9 +20468,10 @@ session_reboot:
else if (!std::strcmp(e, "fxaa_hq")) g_video_post_aa = GL_POST_AA_FXAA_HQ;
else std::fprintf(stdout, "psxrecomp: PSX_AA_MODE=%s not understood (off, fxaa, fxaa_hq)\n", e);
}
if (g_video_ss_milli != 1000)
const int effective_ss = display_supersample(nullptr);
if (effective_ss != 1000 || effective_ss != g_video_ss_milli)
std::fprintf(stdout, "psxrecomp: supersample %.3gx on the internal-resolution target\n",
g_video_ss_milli / 1000.0);
effective_ss / 1000.0);
apply_internal_resolution(match_display_px_h(nullptr));
if (g_video_scale < 1) g_video_scale = 1;
if (const char* e = std::getenv("PSX_DYNRES"))
@@ -21112,7 +21119,7 @@ session_reboot:
const int dh = match_display_px_h(sdl_window);
const int s = psx_resolve_internal_scale_ss(PSX_IR_DISPLAY, g_video_ref_lines,
dh, GL_MAX_INTERNAL_SCALE,
g_video_ss_milli);
display_supersample(sdl_window));
gr_set_scale(s);
g_video_requested_scale = s;
std::fprintf(stdout, "psxrecomp: internal resolution Match display: "
@@ -222,6 +222,11 @@ int main() {
expect("ss clamps to the ceiling", psx_resolve_internal_scale_ss(4320, 240, 0, 32, 4000), 32);
expect("ss unknown display stays 1", psx_resolve_internal_scale_ss(PSX_IR_DISPLAY, 240, 0, 32, 2000), 1);
expect("ss policy opt-out", psx_ir_display_supersample(1500, 4320, 0), 1500);
expect("ss below threshold", psx_ir_display_supersample(1500, 2159, 2160), 1500);
expect("ss at threshold", psx_ir_display_supersample(1500, 2160, 2160), 1000);
expect("ss on 8K", psx_ir_display_supersample(1500, 4320, 2160), 1000);
expect("ss unknown display", psx_ir_display_supersample(1500, 0, 2160), 1500);
launcher_round_trips();
if (g_failures) return 1;