mirror of
https://github.com/libretro/RetroArch
synced 2025-03-12 13:13:30 +00:00
(Vulkan) Prefer IMMEDIATE mode without vsync (#17009)
* (Vulkan) Prefer IMMEDIATE mode without vsync * Clamp max_swapchain_images and hard_sync_frames * (Vulkan) Improve fastforward frameskip option hack
This commit is contained in:
parent
61a3397b67
commit
6713e3b7f7
@ -368,6 +368,8 @@
|
||||
|
||||
/* Vulkan specific */
|
||||
#define DEFAULT_MAX_SWAPCHAIN_IMAGES 3
|
||||
#define MINIMUM_MAX_SWAPCHAIN_IMAGES 2
|
||||
#define MAXIMUM_MAX_SWAPCHAIN_IMAGES 4
|
||||
|
||||
/* D3D1x specific */
|
||||
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
@ -391,6 +393,8 @@
|
||||
* 2: Etc ...
|
||||
*/
|
||||
#define DEFAULT_HARD_SYNC_FRAMES 0
|
||||
#define MINIMUM_HARD_SYNC_FRAMES 0
|
||||
#define MAXIMUM_HARD_SYNC_FRAMES 3
|
||||
|
||||
/* Sets how many milliseconds to delay after VSync before running the core.
|
||||
* Can reduce latency at cost of higher risk of stuttering.
|
||||
|
@ -3870,8 +3870,13 @@ static bool config_load_file(global_t *global,
|
||||
free(override_username);
|
||||
}
|
||||
|
||||
if (settings->uints.video_hard_sync_frames > 3)
|
||||
settings->uints.video_hard_sync_frames = 3;
|
||||
if (settings->uints.video_hard_sync_frames > MAXIMUM_HARD_SYNC_FRAMES)
|
||||
settings->uints.video_hard_sync_frames = MAXIMUM_HARD_SYNC_FRAMES;
|
||||
|
||||
if (settings->uints.video_max_swapchain_images < MINIMUM_MAX_SWAPCHAIN_IMAGES)
|
||||
settings->uints.video_max_swapchain_images = MINIMUM_MAX_SWAPCHAIN_IMAGES;
|
||||
if (settings->uints.video_max_swapchain_images > MAXIMUM_MAX_SWAPCHAIN_IMAGES)
|
||||
settings->uints.video_max_swapchain_images = MAXIMUM_MAX_SWAPCHAIN_IMAGES;
|
||||
|
||||
if (settings->uints.video_frame_delay > MAXIMUM_FRAME_DELAY)
|
||||
settings->uints.video_frame_delay = MAXIMUM_FRAME_DELAY;
|
||||
|
@ -1966,7 +1966,7 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
|
||||
{
|
||||
/* Do not bother creating a swapchain redundantly. */
|
||||
#ifdef VULKAN_DEBUG
|
||||
RARCH_LOG("[Vulkan]: Do not need to re-create swapchain.\n");
|
||||
RARCH_DBG("[Vulkan]: Do not need to re-create swapchain.\n");
|
||||
#endif
|
||||
vulkan_create_wait_fences(vk);
|
||||
|
||||
@ -2025,42 +2025,76 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
|
||||
vk->context.gpu, vk->vk_surface,
|
||||
&present_mode_count, present_modes);
|
||||
|
||||
#ifdef VULKAN_DEBUG
|
||||
for (i = 0; i < present_mode_count; i++)
|
||||
{
|
||||
RARCH_LOG("[Vulkan]: Swapchain supports present mode: %u.\n",
|
||||
present_modes[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
vk->context.swap_interval = swap_interval;
|
||||
|
||||
/* Prefer IMMEDIATE without vsync */
|
||||
for (i = 0; i < present_mode_count; i++)
|
||||
{
|
||||
if ( !swap_interval
|
||||
&& (present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR))
|
||||
{
|
||||
swapchain_present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
break;
|
||||
}
|
||||
else if (!swap_interval
|
||||
&& (present_modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR))
|
||||
&& !vsync
|
||||
&& present_modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)
|
||||
{
|
||||
swapchain_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||
break;
|
||||
}
|
||||
else if ( swap_interval
|
||||
&& (present_modes[i] == VK_PRESENT_MODE_FIFO_KHR))
|
||||
}
|
||||
|
||||
/* If still in FIFO with no swap interval, try MAILBOX */
|
||||
for (i = 0; i < present_mode_count; i++)
|
||||
{
|
||||
if ( !swap_interval
|
||||
&& swapchain_present_mode == VK_PRESENT_MODE_FIFO_KHR
|
||||
&& present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
|
||||
{
|
||||
/* Kind of tautological since FIFO must always be present. */
|
||||
swapchain_present_mode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
swapchain_present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VULKAN_DEBUG
|
||||
RARCH_LOG("[Vulkan]: Creating swapchain with present mode: %u\n",
|
||||
(unsigned)swapchain_present_mode);
|
||||
#endif
|
||||
/* Present mode logging */
|
||||
if (vk->swapchain == VK_NULL_HANDLE)
|
||||
{
|
||||
for (i = 0; i < present_mode_count; i++)
|
||||
{
|
||||
switch (present_modes[i])
|
||||
{
|
||||
case VK_PRESENT_MODE_IMMEDIATE_KHR:
|
||||
RARCH_DBG("[Vulkan]: Swapchain supports present mode: IMMEDIATE.\n");
|
||||
break;
|
||||
case VK_PRESENT_MODE_MAILBOX_KHR:
|
||||
RARCH_DBG("[Vulkan]: Swapchain supports present mode: MAILBOX.\n");
|
||||
break;
|
||||
case VK_PRESENT_MODE_FIFO_KHR:
|
||||
RARCH_DBG("[Vulkan]: Swapchain supports present mode: FIFO.\n");
|
||||
break;
|
||||
case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
|
||||
RARCH_DBG("[Vulkan]: Swapchain supports present mode: FIFO_RELAXED.\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (swapchain_present_mode)
|
||||
{
|
||||
case VK_PRESENT_MODE_IMMEDIATE_KHR:
|
||||
RARCH_DBG("[Vulkan]: Creating swapchain with present mode: IMMEDIATE.\n");
|
||||
break;
|
||||
case VK_PRESENT_MODE_MAILBOX_KHR:
|
||||
RARCH_DBG("[Vulkan]: Creating swapchain with present mode: MAILBOX.\n");
|
||||
break;
|
||||
case VK_PRESENT_MODE_FIFO_KHR:
|
||||
RARCH_DBG("[Vulkan]: Creating swapchain with present mode: FIFO.\n");
|
||||
break;
|
||||
case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
|
||||
RARCH_DBG("[Vulkan]: Creating swapchain with present mode: FIFO_RELAXED.\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(vk->context.gpu,
|
||||
vk->vk_surface, &format_count, NULL);
|
||||
@ -2175,11 +2209,6 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef VULKAN_DEBUG
|
||||
RARCH_LOG("[Vulkan]: Using swapchain size %ux%u.\n",
|
||||
swapchain_size.width, swapchain_size.height);
|
||||
#endif
|
||||
|
||||
/* Unless we have other reasons to clamp, we should prefer 3 images.
|
||||
* We hard sync against the swapchain, so if we have 2 images,
|
||||
* we would be unable to overlap CPU and GPU, which can get very slow
|
||||
|
@ -2709,17 +2709,18 @@ void video_driver_build_info(video_frame_info_t *video_info)
|
||||
video_info->runloop_is_paused = (runloop_st->flags & RUNLOOP_FLAG_PAUSED) ? true : false;
|
||||
video_info->runloop_is_slowmotion = (runloop_st->flags & RUNLOOP_FLAG_SLOWMOTION) ? true : false;
|
||||
video_info->fastforward_frameskip = settings->bools.fastforward_frameskip;
|
||||
video_info->frame_time_target = 1000000.0f / video_info->refresh_rate;
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef HAVE_VULKAN
|
||||
/* Vulkan in Windows does mailbox emulation
|
||||
* in fullscreen with vsync, effectively
|
||||
* discarding frames that can't be shown,
|
||||
* therefore do not do it twice. */
|
||||
* already discarding frames, therefore compensate
|
||||
* frameskip target to make it smoother and faster. */
|
||||
if ( video_info->fullscreen
|
||||
&& settings->bools.video_vsync
|
||||
&& string_is_equal(video_driver_get_ident(), "vulkan"))
|
||||
video_info->fastforward_frameskip = false;
|
||||
video_info->frame_time_target /= 2.0f;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -3409,9 +3410,9 @@ void video_driver_frame(const void *data, unsigned width,
|
||||
static retro_time_t last_time;
|
||||
static retro_time_t curr_time;
|
||||
static retro_time_t fps_time;
|
||||
static retro_time_t frame_time_accumulator;
|
||||
static float last_fps, frame_time;
|
||||
static uint64_t last_used_memory, last_total_memory;
|
||||
static uint16_t frame_time_accumulator;
|
||||
/* Mark the start of nonblock state for
|
||||
* ignoring initial previous frame time */
|
||||
static int8_t nonblock_active;
|
||||
@ -3494,9 +3495,9 @@ void video_driver_frame(const void *data, unsigned width,
|
||||
&& video_info.fastforward_frameskip)
|
||||
#endif
|
||||
{
|
||||
retro_time_t frame_time_accumulator_prev = frame_time_accumulator;
|
||||
retro_time_t frame_time_delta = new_time - last_time;
|
||||
retro_time_t frame_time_target = 1000000.0f / video_info.refresh_rate;
|
||||
uint16_t frame_time_accumulator_prev = frame_time_accumulator;
|
||||
uint16_t frame_time_delta = new_time - last_time;
|
||||
uint16_t frame_time_target = video_info.frame_time_target;
|
||||
|
||||
/* Ignore initial previous frame time
|
||||
* to prevent rubber band startup */
|
||||
|
@ -456,6 +456,8 @@ typedef struct video_frame_info
|
||||
uint32_t video_st_flags;
|
||||
uint16_t menu_st_flags;
|
||||
|
||||
uint16_t frame_time_target;
|
||||
|
||||
char stat_text[1024];
|
||||
|
||||
bool widgets_active;
|
||||
|
@ -14017,8 +14017,8 @@ static bool setting_append_list(
|
||||
general_write_handler,
|
||||
general_read_handler);
|
||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||
(*list)[list_info->index - 1].offset_by = 2;
|
||||
menu_settings_list_current_add_range(list, list_info, (*list)[list_info->index - 1].offset_by, 4, 1, true, true);
|
||||
(*list)[list_info->index - 1].offset_by = MINIMUM_MAX_SWAPCHAIN_IMAGES;
|
||||
menu_settings_list_current_add_range(list, list_info, (*list)[list_info->index - 1].offset_by, MAXIMUM_MAX_SWAPCHAIN_IMAGES, 1, true, true);
|
||||
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_CMD_APPLY_AUTO);
|
||||
MENU_SETTINGS_LIST_CURRENT_ADD_CMD(list, list_info, CMD_EVENT_REINIT);
|
||||
|
||||
@ -14089,7 +14089,7 @@ static bool setting_append_list(
|
||||
general_write_handler,
|
||||
general_read_handler);
|
||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||
menu_settings_list_current_add_range(list, list_info, 0, 3, 1, true, true);
|
||||
menu_settings_list_current_add_range(list, list_info, MINIMUM_HARD_SYNC_FRAMES, MAXIMUM_HARD_SYNC_FRAMES, 1, true, true);
|
||||
|
||||
if (video_driver_test_all_flags(GFX_CTX_FLAGS_ADAPTIVE_VSYNC))
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user