mirror of
https://github.com/mihawk-99/PS5_RetroArch.git
synced 2026-10-18 23:09:29 -05:00
Target Framerate (60/120), the timeline of pictures, any-cadence generation, present sequence log, honest overlay
This commit is contained in:
1 parent
da4cf320b9
commit
72a3bac0b3
3 files changed
+190
-43
No files matched your search
+21
-24
@@ -21,7 +21,7 @@
|
||||
enum ps5_fg_item
|
||||
{
|
||||
PS5_FG_ENABLE = 0,
|
||||
PS5_FG_SUBFRAMES,
|
||||
PS5_FG_TARGET,
|
||||
PS5_FG_METHOD,
|
||||
PS5_FG_CADENCE,
|
||||
PS5_FG_SIZE,
|
||||
@@ -33,7 +33,7 @@ enum ps5_fg_item
|
||||
struct ps5_fg_options
|
||||
{
|
||||
unsigned enable; /* 0 off, 1 on */
|
||||
unsigned subframes; /* presents per content frame, 1 (nothing generated) to 4 */
|
||||
unsigned target; /* 0 120 fps, 1 60 fps: the rate of the pictures the display gets */
|
||||
unsigned method; /* 0 neural, 1 blend, 2 repeat */
|
||||
unsigned cadence; /* 0 measured, else core frames per new frame, 1 to 4 */
|
||||
unsigned size; /* 0 4K, 1 1440p, 2 1080p, 3 720p: the most pixels the generator works at */
|
||||
@@ -47,8 +47,8 @@ static inline unsigned ps5_fg_choice_count(unsigned item)
|
||||
case PS5_FG_ENABLE:
|
||||
case PS5_FG_OSD:
|
||||
return 2;
|
||||
case PS5_FG_SUBFRAMES:
|
||||
return 5;
|
||||
case PS5_FG_TARGET:
|
||||
return 2;
|
||||
case PS5_FG_METHOD:
|
||||
return 3;
|
||||
case PS5_FG_CADENCE:
|
||||
@@ -63,7 +63,7 @@ static inline unsigned ps5_fg_choice_count(unsigned item)
|
||||
static inline const char *ps5_fg_item_name(unsigned item)
|
||||
{
|
||||
static const char *const names[PS5_FG_ITEM_COUNT] = {
|
||||
"Frame Generation", "Output Rate", "Method",
|
||||
"Frame Generation", "Target Framerate", "Method",
|
||||
"Content Frame Cadence", "Working Size", "Status On Screen",
|
||||
"Recommended Settings",
|
||||
};
|
||||
@@ -73,15 +73,15 @@ static inline const char *ps5_fg_item_name(unsigned item)
|
||||
static inline const char *ps5_fg_item_help(unsigned item)
|
||||
{
|
||||
static const char *const help[PS5_FG_ITEM_COUNT] = {
|
||||
"Makes the frames between a game's frames with a trained network. Needs Output Rate 2x or more.",
|
||||
"Presents per game frame. Auto picks the display's rate over the game's (2x for 60 fps games on a 120 Hz output). "
|
||||
"A rate the display cannot show makes the game run slow. Changing it restarts the video output.",
|
||||
"Makes the frames between a game's frames with a trained network, up to the Target Framerate.",
|
||||
"The frame rate of what you see. 120: a 60 fps game gets one made frame between each pair (30 fps games, three). "
|
||||
"60: a 30 fps game gets one; a 60 fps game is shown as it is. Changing it restarts the video output.",
|
||||
"Neural is the trained network. Blend and Repeat are the baselines to compare it with.",
|
||||
"Auto measures how often a game makes a new frame. Force 1 to 4 when a game's cadence is "
|
||||
"misjudged (30 fps games: 2).",
|
||||
"The most pixels the generator works at. Games that render larger are averaged down. Smaller is faster.",
|
||||
"Shows the method, the rate, the frame size and a count of generated frames over the game.",
|
||||
"Frame generation on, rate auto, neural, auto cadence, up to 4K, status off.",
|
||||
"Frame generation on, 120 fps, neural, auto cadence, up to 4K, status off.",
|
||||
};
|
||||
return item < PS5_FG_ITEM_COUNT ? help[item] : "";
|
||||
}
|
||||
@@ -90,7 +90,7 @@ static inline const char *ps5_fg_item_help(unsigned item)
|
||||
static inline const char *ps5_fg_choice_name(unsigned item, unsigned value)
|
||||
{
|
||||
static const char *const on_off[] = {"Off", "On"};
|
||||
static const char *const rates[] = {"Auto", "Off (1x)", "2x", "3x", "4x"};
|
||||
static const char *const rates[] = {"120 fps", "60 fps"};
|
||||
static const char *const methods[] = {"Neural", "Blend", "Repeat"};
|
||||
static const char *const cadence[] = {"Auto", "1", "2", "3", "4"};
|
||||
static const char *const sizes[] = {"Up to 4K", "Up to 1440p", "Up to 1080p", "Up to 720p"};
|
||||
@@ -99,8 +99,8 @@ static inline const char *ps5_fg_choice_name(unsigned item, unsigned value)
|
||||
case PS5_FG_ENABLE:
|
||||
case PS5_FG_OSD:
|
||||
return on_off[value & 1];
|
||||
case PS5_FG_SUBFRAMES:
|
||||
return value < 5 ? rates[value] : "";
|
||||
case PS5_FG_TARGET:
|
||||
return value < 2 ? rates[value] : "";
|
||||
case PS5_FG_METHOD:
|
||||
return value < 3 ? methods[value] : "";
|
||||
case PS5_FG_CADENCE:
|
||||
@@ -115,20 +115,20 @@ static inline const char *ps5_fg_choice_name(unsigned item, unsigned value)
|
||||
static inline void ps5_fg_defaults(struct ps5_fg_options *o)
|
||||
{
|
||||
o->enable = 1;
|
||||
o->subframes = 0;
|
||||
o->target = 0;
|
||||
o->method = 0;
|
||||
o->cadence = 0;
|
||||
o->size = 0;
|
||||
o->osd = 0;
|
||||
}
|
||||
|
||||
/* An item's value as its choice index (subframes 1..4 are choices 0..3). */
|
||||
/* An item's value as its choice index. */
|
||||
static inline unsigned ps5_fg_get(const struct ps5_fg_options *o, unsigned item)
|
||||
{
|
||||
switch (item)
|
||||
{
|
||||
case PS5_FG_ENABLE: return o->enable;
|
||||
case PS5_FG_SUBFRAMES: return o->subframes <= 4 ? o->subframes : 0;
|
||||
case PS5_FG_TARGET: return o->target ? 1 : 0;
|
||||
case PS5_FG_METHOD: return o->method;
|
||||
case PS5_FG_CADENCE: return o->cadence;
|
||||
case PS5_FG_SIZE: return o->size;
|
||||
@@ -148,7 +148,7 @@ static inline void ps5_fg_set(struct ps5_fg_options *o, unsigned item, unsigned
|
||||
switch (item)
|
||||
{
|
||||
case PS5_FG_ENABLE: o->enable = value; break;
|
||||
case PS5_FG_SUBFRAMES: o->subframes = value; break;
|
||||
case PS5_FG_TARGET: o->target = value; break;
|
||||
case PS5_FG_METHOD: o->method = value; break;
|
||||
case PS5_FG_CADENCE: o->cadence = value; break;
|
||||
case PS5_FG_SIZE: o->size = value; break;
|
||||
@@ -182,8 +182,8 @@ static inline int ps5_fg_save(const struct ps5_fg_options *o)
|
||||
if (!file)
|
||||
return -1;
|
||||
fprintf(file, "video_framegen = \"%s\"\n", o->enable ? "true" : "false");
|
||||
fprintf(file, "video_framegen_auto = \"%s\"\n", o->subframes == 0 ? "true" : "false");
|
||||
fprintf(file, "video_shader_subframes = \"%u\"\n", o->subframes ? o->subframes : 2);
|
||||
fprintf(file, "video_framegen_auto = \"true\"\n");
|
||||
fprintf(file, "video_framegen_target = \"%u\"\n", o->target ? 60 : 120);
|
||||
fprintf(file, "video_framegen_method = \"%u\"\n", o->method);
|
||||
fprintf(file, "video_framegen_cadence = \"%u\"\n", o->cadence);
|
||||
fprintf(file, "video_framegen_size = \"%u\"\n", o->size);
|
||||
@@ -195,8 +195,6 @@ static inline int ps5_fg_save(const struct ps5_fg_options *o)
|
||||
static inline void ps5_fg_load(struct ps5_fg_options *o)
|
||||
{
|
||||
char line[160];
|
||||
unsigned rate = o->subframes;
|
||||
int auto_rate = o->subframes == 0;
|
||||
FILE *file = fopen(PS5_FG_CONFIG_PATH, "r");
|
||||
if (!file)
|
||||
return;
|
||||
@@ -220,15 +218,14 @@ static inline void ps5_fg_load(struct ps5_fg_options *o)
|
||||
o->size = number % 4;
|
||||
else if (strstr(line, "video_framegen_osd"))
|
||||
o->osd = strncmp(value, "true", 4) == 0;
|
||||
else if (strstr(line, "video_framegen_target"))
|
||||
o->target = number == 60;
|
||||
else if (strstr(line, "video_framegen_auto"))
|
||||
auto_rate = strncmp(value, "true", 4) == 0;
|
||||
continue; /* (older files: the rate is the target's now) */
|
||||
else if (strstr(line, "video_framegen"))
|
||||
o->enable = strncmp(value, "true", 4) == 0;
|
||||
else if (strstr(line, "video_shader_subframes"))
|
||||
rate = number >= 1 && number <= 4 ? number : 2;
|
||||
}
|
||||
fclose(file);
|
||||
o->subframes = auto_rate ? 0 : rate;
|
||||
}
|
||||
|
||||
#endif
|
||||
+45
-19
@@ -35,6 +35,13 @@
|
||||
|
||||
#define PS5_FG_LABEL_FOLDER "ps5_framegen"
|
||||
|
||||
/* Presents of each picture (the display's rate over the target's), set with the rate (patches/series, 0121) */
|
||||
unsigned ps5_fg_dup = 1;
|
||||
/* The rate of the pictures the display gets: 119.88 or 59.94 (the Target Framerate), set with the rate */
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
@@ -84,11 +91,7 @@ static void ps5_fg_current(struct ps5_fg_options *o)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
o->enable = settings->bools.video_framegen ? 1 : 0;
|
||||
o->subframes = settings->bools.video_framegen_auto ? 0 : settings->uints.video_shader_subframes;
|
||||
if (o->subframes > 4)
|
||||
o->subframes = 1;
|
||||
if (!settings->bools.video_framegen_auto && o->subframes < 1)
|
||||
o->subframes = 1;
|
||||
o->target = settings->uints.video_framegen_target == 60 ? 1 : 0;
|
||||
o->method = settings->uints.video_framegen_method % 3;
|
||||
o->cadence = settings->uints.video_framegen_cadence % 5;
|
||||
o->size = settings->uints.video_framegen_size % 4;
|
||||
@@ -118,16 +121,15 @@ void ps5_fg_menu_step(const char *label, int direction)
|
||||
before = now;
|
||||
ps5_fg_step(&now, (unsigned)item, direction);
|
||||
settings->bools.video_framegen = now.enable != 0;
|
||||
settings->bools.video_framegen_auto = now.subframes == 0;
|
||||
if (now.subframes)
|
||||
settings->uints.video_shader_subframes = now.subframes;
|
||||
settings->bools.video_framegen_auto = true;
|
||||
settings->uints.video_framegen_target = now.target ? 60 : 120;
|
||||
settings->uints.video_framegen_method = now.method;
|
||||
settings->uints.video_framegen_cadence = now.cadence;
|
||||
settings->uints.video_framegen_size = now.size;
|
||||
settings->bools.video_framegen_osd = now.osd != 0;
|
||||
ps5_fg_save(&now);
|
||||
/* The rate is read when the video output starts: its timing follows it */
|
||||
if (now.subframes != before.subframes)
|
||||
if (now.target != before.target)
|
||||
command_event(CMD_EVENT_REINIT, NULL); /* (Auto picks its rate as the video output starts) */
|
||||
}
|
||||
|
||||
@@ -176,11 +178,13 @@ 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 generated, unsigned long unique)
|
||||
{
|
||||
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];
|
||||
static unsigned long gap_n[2], gap_off[2], last_unique;
|
||||
static double new_per_s;
|
||||
static double gap_sum[2], gap_max[2];
|
||||
static struct timespec last;
|
||||
struct ps5_fg_options now;
|
||||
@@ -191,6 +195,26 @@ void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width,
|
||||
return;
|
||||
presents++;
|
||||
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||
{
|
||||
/* the last presents: instant shown and ms since the one before (a line with the pace) */
|
||||
static float seq_t[24];
|
||||
static float seq_ms[24];
|
||||
static unsigned seq_n;
|
||||
static struct timespec seq_prev;
|
||||
if (seq_prev.tv_sec)
|
||||
seq_ms[seq_n % 24] = (float)((t.tv_sec - seq_prev.tv_sec) * 1e3 + (t.tv_nsec - seq_prev.tv_nsec) / 1e6);
|
||||
seq_t[seq_n % 24] = ps5_fg_dbg_t;
|
||||
seq_prev = t;
|
||||
seq_n++;
|
||||
if (seq_n % 240 == 0)
|
||||
{
|
||||
char line[400];
|
||||
unsigned q, o = 0;
|
||||
for (q = 0; q < 24 && o < sizeof(line) - 24; q++)
|
||||
o += (unsigned)snprintf(line + o, sizeof(line) - o, " %.2f@%.1f", seq_t[(seq_n + q) % 24], seq_ms[(seq_n + q) % 24]);
|
||||
RARCH_LOG("[FrameGen] seq:%s\n", line);
|
||||
}
|
||||
}
|
||||
if (last.tv_sec == 0)
|
||||
last = t;
|
||||
{
|
||||
@@ -214,8 +238,10 @@ 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;
|
||||
RARCH_LOG("[FrameGen] pace: %.1f presents/s, %.1f generated/s\n", (double)presents / seconds,
|
||||
(double)(generated - last_generated) / seconds);
|
||||
new_per_s = (double)(unique - last_unique) / 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);
|
||||
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]);
|
||||
@@ -230,15 +256,15 @@ void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width,
|
||||
ps5_fg_current(&now);
|
||||
if (!now.enable)
|
||||
snprintf(text, sizeof(text), "FrameGen: off");
|
||||
else if (subframes < 2)
|
||||
snprintf(text, sizeof(text), "FrameGen: waiting - the output rate is not a multiple of the game's (Output Rate %s)",
|
||||
ps5_fg_choice_name(PS5_FG_SUBFRAMES, now.subframes));
|
||||
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 (!plan)
|
||||
snprintf(text, sizeof(text), "FrameGen: paused (menu, fast-forward or pause)");
|
||||
else
|
||||
snprintf(text, sizeof(text), "FrameGen: %s %ux cadence %u%s %ux%u generated %lu",
|
||||
ps5_fg_choice_name(PS5_FG_METHOD, now.method), subframes, period ? period : 1,
|
||||
now.cadence ? " (forced)" : "", width, height, generated);
|
||||
snprintf(text, sizeof(text), "FrameGen: %s game %.1f fps (%.1f new/s) -> %.0f fps cadence %u%s %ux%u generated %lu",
|
||||
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);
|
||||
runloop_msg_queue_push(text, strlen(text), 1, 150, false, NULL,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
}
|
||||
|
||||
@@ -4426,6 +4426,130 @@ EDITS += [('configuration.h',
|
||||
' bool video_adaptive_vsync = settings->bools.video_adaptive_vsync;\n',
|
||||
'Output Rate Auto: the presents per game frame')]
|
||||
|
||||
# Frame generation, Target Framerate (patches/series, 0121): the rate of the pictures the display gets, 60 or 120. The
|
||||
# display runs at its own rate (119.88 Hz on this console); a target below it shows each picture "dup" times, the
|
||||
# presents of one picture being copies. shader_subframes is the presents per game frame: pictures x dup.
|
||||
EDITS += [('configuration.h',
|
||||
' unsigned video_framegen_cadence; /* patches/series, 0120: 0 measured, else core frames per new frame */\n',
|
||||
' unsigned video_framegen_cadence; /* patches/series, 0120: 0 measured, else core frames per new frame */\n'
|
||||
' unsigned video_framegen_target; /* patches/series, 0121: Target Framerate, 60 or 120 */\n',
|
||||
'unsigned video_framegen_target; /* patches/series, 0121'),
|
||||
('configuration.c',
|
||||
' SETTING_UINT("video_framegen_cadence", &settings->uints.video_framegen_cadence, true, 0, false); /* '
|
||||
'patches/series, 0120 */\n',
|
||||
' SETTING_UINT("video_framegen_cadence", &settings->uints.video_framegen_cadence, true, 0, false); /* '
|
||||
'patches/series, 0120 */\n'
|
||||
' SETTING_UINT("video_framegen_target", &settings->uints.video_framegen_target, true, 120, false); /* '
|
||||
'patches/series, 0121 */\n',
|
||||
'SETTING_UINT("video_framegen_target"'),
|
||||
('retroarch.c',
|
||||
' float n = display / (float)input_fps;\n'
|
||||
' unsigned s = n < 1.5f ? 1 : n < 2.5f ? 2 : n < 3.5f ? 3 : 4;\n'
|
||||
' RARCH_LOG("[FrameGen] Output Rate Auto: display %.3f Hz, game %.3f fps -> %ux\\n", display, '
|
||||
'input_fps, s);\n'
|
||||
' settings->uints.video_shader_subframes = s;\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). */\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',
|
||||
'Target Framerate. The pictures the display gets per second'),
|
||||
('gfx/drivers/vulkan.c',
|
||||
' const unsigned fg_n = video_info->shader_subframes;\n'
|
||||
' const unsigned fg_j = fg_nested ? vk->framegen_subframe : 1;\n',
|
||||
' /* patches/series, 0121: presents per game frame fg_s = pictures fg_n x copies of each (Target Framerate) */\n'
|
||||
' extern unsigned ps5_fg_dup;\n'
|
||||
' const unsigned fg_s = video_info->shader_subframes;\n'
|
||||
' const unsigned fg_dup = ps5_fg_dup >= 1 && fg_s % ps5_fg_dup == 0 ? ps5_fg_dup : 1;\n'
|
||||
' const unsigned fg_n = fg_s / fg_dup;\n'
|
||||
' const unsigned fg_j = ((fg_nested ? vk->framegen_subframe : 1) - 1) / fg_dup + 1;\n',
|
||||
'presents per game frame fg_s = pictures fg_n'),
|
||||
]
|
||||
|
||||
# Frame generation, the timeline (patches/series, 0121): the pictures of a group are placed at the instants the target
|
||||
# rate puts them at, the presents of each call vary, and the game is never run faster or slower to fit a multiple.
|
||||
EDITS += [('gfx/drivers/vulkan.c',
|
||||
" unsigned framegen_period; /* calls in a group: 1, or 2 for a game at half the core's rate */\n",
|
||||
" unsigned framegen_period; /* calls in a group: 1, or 2 for a game at half the core's rate */\n unsigned framegen_presents; /* presents of this call (patches/series, 0121: the timeline) */\n",
|
||||
'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'
|
||||
' vulkan_filter_chain_t *filter_chain = NULL;\n bool waits_for_semaphores = false;\n',
|
||||
'presents of this call */\n'),
|
||||
('gfx/drivers/vulkan.c',
|
||||
' (fg_n >= 2 && fg_n <= 4)\n',
|
||||
' (fg_s >= 2 && fg_s <= 8) /* patches/series, 0121 */\n',
|
||||
'(fg_s >= 2 && fg_s <= 8) /* patches/series, 0121 */'),
|
||||
('gfx/drivers/vulkan.c',
|
||||
' vk->framegen_call = 0;\n vk->framegen_group_open = true;\n',
|
||||
' vk->framegen_call = 0;\n vk->framegen_group_open = true;\n {\n /* patches/series, 0121: the pictures of the group, at the instants of the target rate */\n extern float ps5_fg_core_fps, ps5_fg_target_fps;\n vk_framegen_begin_group(vk->framegen, vk->framegen_period ? vk->framegen_period : 1,\n ps5_fg_core_fps, ps5_fg_target_fps, fg_dup);\n }\n',
|
||||
'vk_framegen_begin_group(vk->framegen'),
|
||||
('gfx/drivers/vulkan.c',
|
||||
" /* The present's place in the group */\n const unsigned fg_total = (vk->framegen_period ? vk->framegen_period : 1) * fg_n;\n bool fg_shown_generated = false;\n const unsigned fg_place = vk->framegen_call * fg_n + fg_j;\n if (fg_place < fg_total)\n {\n if (vk_framegen_generate(vk->framegen, vk->cmd, frame_index,\n (float)fg_place / (float)fg_total, &vk->framegen_frame))\n {\n input.image = vk->framegen_frame.image;\n input.view = vk->framegen_frame.view;\n input.layout = vk->framegen_frame.layout;\n input.width = vk->framegen_frame.width;\n input.height = vk->framegen_frame.height;\n input.format = vk->framegen_frame.format;\n input.physical_width = vk->framegen_frame.width;\n fg_shown_generated = true;\n }\n }\n else if (fg_place == fg_total)\n vk_framegen_commit(vk->framegen);\n",
|
||||
" /* The present's place in the call (patches/series, 0121: the timeline of the Target Framerate) */\n bool fg_shown_generated = false;\n bool fg_final = false;\n float fg_t = 0.0f;\n if (!fg_nested)\n vk->framegen_presents = vk_framegen_call_presents(vk->framegen, vk->framegen_call);\n if ( vk_framegen_picture(vk->framegen, vk->framegen_call, fg_nested ? vk->framegen_subframe : 1,\n vk->framegen_presents, &fg_t, &fg_final)\n && vk_framegen_generate(vk->framegen, vk->cmd, frame_index, fg_t, &vk->framegen_frame))\n {\n input.image = vk->framegen_frame.image;\n input.view = vk->framegen_frame.view;\n input.layout = vk->framegen_frame.layout;\n input.width = vk->framegen_frame.width;\n input.height = vk->framegen_frame.height;\n input.format = vk->framegen_frame.format;\n input.physical_width = vk->framegen_frame.width;\n fg_shown_generated = true;\n }\n if (fg_final)\n vk_framegen_commit(vk->framegen);\n",
|
||||
'vk_framegen_call_presents(vk->framegen, vk->framegen_call)'),
|
||||
('gfx/drivers/vulkan.c',
|
||||
' if ( (video_info->shader_subframes > 1)\n && (backbuffer->image != VK_NULL_HANDLE)\n && (vk->context->flags & VK_CTX_FLAG_HAS_ACQUIRED_SWAPCHAIN)\n && !black_frame_insertion\n && !input_driver_nonblock_state\n && !runloop_is_slowmotion\n && !runloop_is_paused\n && (!(vk->flags & VK_FLAG_MENU_ENABLE))\n && !(vk->context->swap_interval > 1)\n && (!(vk->context->flags & VK_CTX_FLAG_SWAP_INTERVAL_EMULATION_LOCK)))\n {\n vk->context->flags |= VK_CTX_FLAG_SWAP_INTERVAL_EMULATION_LOCK;\n for (j = 1; j < (int) video_info->shader_subframes; j++)\n',
|
||||
' if ( (vk->framegen_presents > 1) /* patches/series, 0121: the presents of this call */\n && (backbuffer->image != VK_NULL_HANDLE)\n && (vk->context->flags & VK_CTX_FLAG_HAS_ACQUIRED_SWAPCHAIN)\n && !black_frame_insertion\n && !input_driver_nonblock_state\n && !runloop_is_slowmotion\n && !runloop_is_paused\n && (!(vk->flags & VK_FLAG_MENU_ENABLE))\n && !(vk->context->swap_interval > 1)\n && (!(vk->context->flags & VK_CTX_FLAG_SWAP_INTERVAL_EMULATION_LOCK)))\n {\n vk->context->flags |= VK_CTX_FLAG_SWAP_INTERVAL_EMULATION_LOCK;\n for (j = 1; j < (int) vk->framegen_presents; j++)\n',
|
||||
'(vk->framegen_presents > 1) /* patches/series, 0121'),
|
||||
('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',
|
||||
'the nominal ones, the pacing the runloop assumes'),
|
||||
('retroarch.c',
|
||||
' shader_subframes,\n audio_max_timing_skew);\n',
|
||||
' shader_subframes,\n /* patches/series, 0121: the core runs at its own rate (the driver places the pictures), so the audio is not retimed */\n (settings->bools.video_framegen && settings->bools.video_framegen_auto && fabsf((settings->uints.video_framegen_target == 60 ? 59.94f : 119.88f) / (float)input_fps - floorf((settings->uints.video_framegen_target == 60 ? 59.94f : 119.88f) / (float)input_fps + 0.5f)) > 0.02f * ((settings->uints.video_framegen_target == 60 ? 59.94f : 119.88f) / (float)input_fps)) ? 0.0f : audio_max_timing_skew);\n',
|
||||
'so the audio is not retimed')]
|
||||
|
||||
# Frame generation, any cadence (patches/series, 0121): the last gap between new frames predicts the next, and a gap that
|
||||
# differs is not a reason to stop generating (a game that steps its animation unevenly would be left at the game's own rate).
|
||||
EDITS += [('gfx/drivers/vulkan.c',
|
||||
' if (fg_gap == vk->framegen_last_gap && fg_gap >= 1 && fg_gap <= 4)\n'
|
||||
' vk->framegen_period = fg_gap;\n',
|
||||
' if (fg_gap >= 1 && fg_gap <= 8) /* patches/series, 0121: the last gap predicts the next */\n'
|
||||
' vk->framegen_period = fg_gap;\n',
|
||||
'the last gap predicts the next */'),
|
||||
('gfx/drivers/vulkan.c',
|
||||
' if (fg_gap != (vk->framegen_period ? vk->framegen_period : 1))\n'
|
||||
' vk_framegen_invalidate(vk->framegen);\n',
|
||||
' if (fg_gap > 8) /* patches/series, 0121: only a pause or a cut breaks the sequence */\n'
|
||||
' vk_framegen_invalidate(vk->framegen);\n',
|
||||
'only a pause or a cut breaks the sequence */')]
|
||||
|
||||
# Frame generation, the sequence of presents in the status log (patches/series, 0121)
|
||||
EDITS += [('gfx/drivers/vulkan.c',
|
||||
' if (fg_final)\n vk_framegen_commit(vk->framegen);\n',
|
||||
' { extern float ps5_fg_dbg_t; ps5_fg_dbg_t = fg_shown_generated ? fg_t : 1.0f; } /* patches/series, 0121 */\n'
|
||||
' if (fg_final)\n vk_framegen_commit(vk->framegen);\n',
|
||||
'ps5_fg_dbg_t = fg_shown_generated ? fg_t : 1.0f; } /* 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
|
||||
|
||||
Reference in new issue
Block a user