Governor level, calls and floor in the driver; floor and honest overlay in the menu code; the early presents default fixed

This commit is contained in:
Mihawk committed 2026-10-11 14:10:44 -04:00
1 parent 72a3bac0b3
commit 50a3d09ee7
2 files changed
+59 -20

No files matched your search

+39 -8
View File
@@ -41,6 +41,8 @@ unsigned ps5_fg_dup = 1;
float ps5_fg_target_fps = 119.88f;
/* The instant of the picture the last present showed (1: a real frame), set by the driver */
float ps5_fg_dbg_t = 1.0f;
/* 1: the core cannot keep its own rate, so frames are shown as it makes them (the driver reads it) */
int ps5_fg_floor;
/* The loaded core's frame rate, kept by the video setup (patches/series, 0121) for the driver's cadence check */
float ps5_fg_core_fps;
@@ -178,13 +180,15 @@ void ps5_fg_menu_help(const char *label, char *s, size_t len)
/* The driver calls this for every present; the message is refreshed about twice a second */
void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width, unsigned height,
unsigned long generated, unsigned long unique)
unsigned long generated, unsigned long unique, unsigned level, double gen_ms, unsigned long calls)
{
static unsigned calls;
const unsigned pictures = subframes / (ps5_fg_dup ? ps5_fg_dup : 1);
static unsigned long presents, last_generated;
static unsigned long gap_n[2], gap_off[2], last_unique;
static double new_per_s;
static unsigned long gap_n[2], gap_off[2], last_unique, last_calls;
static double new_per_s, calls_per_s;
static unsigned slow_windows;
static time_t floor_until;
static double gap_sum[2], gap_max[2];
static struct timespec last;
struct ps5_fg_options now;
@@ -238,10 +242,34 @@ void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width,
if ((t.tv_sec - last.tv_sec) * 1000000000L + (t.tv_nsec - last.tv_nsec) >= 2000000000L)
{
double seconds = (double)(t.tv_sec - last.tv_sec) + (double)(t.tv_nsec - last.tv_nsec) / 1e9;
new_per_s = (double)(unique - last_unique) / seconds;
new_per_s = (double)(unique - last_unique) / seconds;
calls_per_s = (double)(calls - last_calls) / seconds;
last_unique = unique;
RARCH_LOG("[FrameGen] pace: %.1f presents/s, %.1f generated/s, %.1f new frames/s\n", (double)presents / seconds,
(double)(generated - last_generated) / seconds, new_per_s);
last_calls = calls;
RARCH_LOG("[FrameGen] pace: %.1f presents/s, %.1f generated/s, %.1f new frames/s, core %.1f calls/s, governor level %u (%.2f ms a picture)\n",
(double)presents / seconds, (double)(generated - last_generated) / seconds, new_per_s, calls_per_s, level, gen_ms);
/* The floor: a core that cannot keep its own rate gains nothing from frames made between its frames, and the work
* only slows it more. It is shown as it makes its frames; every ten seconds the generator is tried again. */
if (ps5_fg_floor)
{
if (t.tv_sec >= floor_until)
{
ps5_fg_floor = 0;
slow_windows = 0;
}
}
else if (plan && ps5_fg_core_fps > 20.0f && calls_per_s < 0.85 * (double)ps5_fg_core_fps)
{
if (++slow_windows >= 2)
{
ps5_fg_floor = 1;
floor_until = t.tv_sec + 10;
RARCH_LOG("[FrameGen] floor: the core runs at %.1f of %.1f frames/s; frames are shown as it makes them for 10 s\n",
calls_per_s, (double)ps5_fg_core_fps);
}
}
else
slow_windows = 0;
RARCH_LOG("[FrameGen] spacing (ms): real n %lu mean %.2f max %.2f off %lu | generated n %lu mean %.2f max %.2f off %lu\n",
gap_n[0], gap_n[0] ? gap_sum[0] / (double)gap_n[0] : 0.0, gap_max[0], gap_off[0],
gap_n[1], gap_n[1] ? gap_sum[1] / (double)gap_n[1] : 0.0, gap_max[1], gap_off[1]);
@@ -259,12 +287,15 @@ void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width,
else if (pictures < 2)
snprintf(text, sizeof(text), "FrameGen: nothing to make - the game already runs at the Target Framerate (%s)",
ps5_fg_choice_name(PS5_FG_TARGET, now.target));
else if (ps5_fg_floor)
snprintf(text, sizeof(text), "FrameGen: core at %.0f fps (needs %.0f), too slow: frames shown as the core makes them",
calls_per_s, (double)ps5_fg_core_fps);
else if (!plan)
snprintf(text, sizeof(text), "FrameGen: paused (menu, fast-forward or pause)");
else
snprintf(text, sizeof(text), "FrameGen: %s game %.1f fps (%.1f new/s) -> %.0f fps cadence %u%s %ux%u generated %lu",
snprintf(text, sizeof(text), "FrameGen: %s game %.1f fps (%.1f new/s) -> %.0f fps cadence %u%s %ux%u generated %lu cost level %u (%.1f ms)",
ps5_fg_choice_name(PS5_FG_METHOD, now.method), (double)ps5_fg_core_fps, new_per_s, (double)ps5_fg_target_fps,
period ? period : 1, now.cadence ? " (forced)" : "", width, height, generated);
period ? period : 1, now.cadence ? " (forced)" : "", width, height, generated, level, gen_ms);
runloop_msg_queue_push(text, strlen(text), 1, 150, false, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
+20 -12
View File
@@ -4021,8 +4021,9 @@ EDITS += [('configuration.h',
'#include "vulkan_framegen.h"\n',
'#include "vulkan_framegen.h"\n'
'extern unsigned long ps5_fg_size_pixels_of(unsigned size); /* patches/series, 0120 */\n'
'extern int ps5_fg_floor; /* patches/series, 0121 */\n'
'extern void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width, unsigned height,\n'
' unsigned long generated);\n',
' unsigned long generated, unsigned long unique, unsigned level, double gen_ms, unsigned long calls);\n',
'ps5_fg_size_pixels_of(unsigned size); /* patches/series, 0120 */'),
('gfx/drivers/vulkan.c',
' vulkan_filter_chain_set_input_texture((vulkan_filter_chain_t*)\n'
@@ -4032,9 +4033,13 @@ EDITS += [('configuration.h',
' {\n'
' unsigned fg_w = 0, fg_h = 0;\n'
' unsigned long fg_n_made = 0;\n'
' unsigned fg_level = 0;\n'
' double fg_gen_ms = 0.0;\n'
' vk_framegen_stats(vk->framegen, &fg_w, &fg_h, &fg_n_made);\n'
' vk_framegen_governor(vk->framegen, &fg_level, &fg_gen_ms); /* patches/series, 0121 */\n'
' ps5_fg_osd(vk->framegen_plan && vk->framegen && config_get_ptr()->bools.video_framegen,\n'
' video_info->shader_subframes, vk->framegen_period, fg_w, fg_h, fg_n_made);\n'
' video_info->shader_subframes, vk->framegen_period, fg_w, fg_h, fg_n_made, vk_framegen_unique(vk->framegen),\n'
' fg_level, fg_gen_ms, vk->framegen_calls); /* patches/series, 0121 */\n'
' }\n'
'\n'
' vulkan_filter_chain_set_input_texture((vulkan_filter_chain_t*)\n'
@@ -4488,9 +4493,9 @@ EDITS += [('gfx/drivers/vulkan.c',
'unsigned framegen_presents; /* presents of this call'),
('gfx/drivers/vulkan.c',
' vulkan_filter_chain_t *filter_chain = NULL;\n bool waits_for_semaphores = false;\n',
' if (!(vk->context->flags & VK_CTX_FLAG_SWAP_INTERVAL_EMULATION_LOCK))\n vk->framegen_presents = video_info->shader_subframes; /* patches/series, 0121: presents of this call */\n'
' if (!(vk->context->flags & VK_CTX_FLAG_SWAP_INTERVAL_EMULATION_LOCK))\n {\n vk->framegen_presents = video_info->shader_subframes; /* patches/series, 0121: presents of this call */\n vk->framegen_calls++;\n }\n'
' vulkan_filter_chain_t *filter_chain = NULL;\n bool waits_for_semaphores = false;\n',
'presents of this call */\n'),
'vk->framegen_calls++;'),
('gfx/drivers/vulkan.c',
' (fg_n >= 2 && fg_n <= 4)\n',
' (fg_s >= 2 && fg_s <= 8) /* patches/series, 0121 */\n',
@@ -4511,14 +4516,6 @@ EDITS += [('gfx/drivers/vulkan.c',
' && !(video_info->shader_subframes > 1)\n && !black_frame_insertion\n && (!(vk->context->flags & VK_CTX_FLAG_SWAP_INTERVAL_EMULATION_LOCK)))\n',
' && !(vk->framegen_presents > 1) /* patches/series, 0121 */\n && !black_frame_insertion\n && (!(vk->context->flags & VK_CTX_FLAG_SWAP_INTERVAL_EMULATION_LOCK)))\n',
'!(vk->framegen_presents > 1) /* patches/series, 0121 */'),
('gfx/drivers/vulkan.c',
'extern void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width, unsigned height,\n unsigned long generated);\n',
'extern void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width, unsigned height,\n unsigned long generated, unsigned long unique); /* patches/series, 0121: and the new frames held */\n',
'unsigned long generated, unsigned long unique); /* patches/series, 0121'),
('gfx/drivers/vulkan.c',
' video_info->shader_subframes, vk->framegen_period, fg_w, fg_h, fg_n_made);\n',
' video_info->shader_subframes, vk->framegen_period, fg_w, fg_h, fg_n_made, vk_framegen_unique(vk->framegen)); /* patches/series, 0121 */\n',
'fg_n_made, vk_framegen_unique(vk->framegen)); /* patches/series, 0121 */'),
('retroarch.c',
' /* patches/series, 0121: Target Framerate. The pictures the display gets per second are the target (60 or\n * 120); a display at a multiple of it shows each picture that many times (dup). */\n {\n extern unsigned ps5_fg_dup;\n const float target = settings->uints.video_framegen_target == 60 ? 59.94f : 119.88f;\n unsigned dup = (unsigned)(display / target + 0.5f);\n float n;\n unsigned s;\n if (dup < 1)\n dup = 1;\n n = (display / (float)dup) / (float)input_fps;\n s = n < 1.5f ? 1 : n < 2.5f ? 2 : n < 3.5f ? 3 : 4;\n if (s * dup > 4)\n s = 4 / dup > 0 ? 4 / dup : 1;\n ps5_fg_dup = dup;\n RARCH_LOG("[FrameGen] Target Framerate %.0f: display %.3f Hz, game %.3f fps -> %ux, each shown %ux\\n", target, display, input_fps, s, dup);\n settings->uints.video_shader_subframes = s * dup;\n }\n',
' /* patches/series, 0121: Target Framerate. The pictures the display gets per second are the target (60 or\n * 120); a display at a multiple of it shows each picture that many times (dup). The game\'s rate is never\n * changed to fit: the number of pictures per game frame varies (the driver places each at its instant), and\n * the presents set here are the nominal ones, the pacing the runloop assumes. */\n {\n extern unsigned ps5_fg_dup;\n extern float ps5_fg_target_fps;\n const float target = settings->uints.video_framegen_target == 60 ? 59.94f : 119.88f;\n unsigned dup = (unsigned)(display / target + 0.5f);\n unsigned s;\n if (dup < 1)\n dup = 1;\n s = (unsigned)(target / (float)input_fps + 0.5f);\n if (input_fps > target * 1.06f || s < 1)\n {\n /* the game is already faster than the target: nothing to make */\n s = 1;\n dup = 1;\n }\n if (s * dup > 8)\n s = 8 / dup > 0 ? 8 / dup : 1;\n /* the nominal rate must not be below the game\'s, or the runloop would not sync to the display */\n if (s > 1 && display / (float)(s * dup) < (float)input_fps * 0.95f)\n s--;\n ps5_fg_dup = dup;\n ps5_fg_target_fps = target;\n RARCH_LOG("[FrameGen] Target Framerate %.0f: display %.3f Hz, game %.3f fps -> %.2f pictures per game frame, "\n "each shown %ux\\n", target, display, input_fps, (double)target / (double)input_fps, dup);\n settings->uints.video_shader_subframes = s * dup;\n }\n',
@@ -4550,6 +4547,17 @@ EDITS += [('gfx/drivers/vulkan.c',
' if (fg_final)\n vk_framegen_commit(vk->framegen);\n',
'ps5_fg_dbg_t = fg_shown_generated ? fg_t : 1.0f; } /* patches/series, 0121 */')]
# Frame generation, the governor's level, the calls and the floor in the status (patches/series, 0121)
EDITS += [('gfx/drivers/vulkan.c',
' unsigned framegen_presents; /* presents of this call (patches/series, 0121: the timeline) */\n',
' unsigned framegen_presents; /* presents of this call (patches/series, 0121: the timeline) */\n'
' unsigned long framegen_calls; /* calls (patches/series, 0121: the floor) */\n',
'unsigned long framegen_calls; /* calls (patches/series, 0121'),
('gfx/drivers/vulkan.c',
' && !(vk->context->swap_interval > 1);\n',
' && !(vk->context->swap_interval > 1)\n && !ps5_fg_floor; /* patches/series, 0121: a core too slow for its own rate is shown as it is */\n',
'&& !ps5_fg_floor; /* patches/series, 0121')]
# Changes that are withdrawn rather than deleted, by marker.
#
# An entry here names an insertion this driver no longer needs, and the