mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
Limit supersampling on high-resolution displays by opt-in policy
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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).**
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user