(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 */
|
/* Vulkan specific */
|
||||||
#define DEFAULT_MAX_SWAPCHAIN_IMAGES 3
|
#define DEFAULT_MAX_SWAPCHAIN_IMAGES 3
|
||||||
|
#define MINIMUM_MAX_SWAPCHAIN_IMAGES 2
|
||||||
|
#define MAXIMUM_MAX_SWAPCHAIN_IMAGES 4
|
||||||
|
|
||||||
/* D3D1x specific */
|
/* D3D1x specific */
|
||||||
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||||
|
@ -391,6 +393,8 @@
|
||||||
* 2: Etc ...
|
* 2: Etc ...
|
||||||
*/
|
*/
|
||||||
#define DEFAULT_HARD_SYNC_FRAMES 0
|
#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.
|
/* Sets how many milliseconds to delay after VSync before running the core.
|
||||||
* Can reduce latency at cost of higher risk of stuttering.
|
* 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);
|
free(override_username);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings->uints.video_hard_sync_frames > 3)
|
if (settings->uints.video_hard_sync_frames > MAXIMUM_HARD_SYNC_FRAMES)
|
||||||
settings->uints.video_hard_sync_frames = 3;
|
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)
|
if (settings->uints.video_frame_delay > MAXIMUM_FRAME_DELAY)
|
||||||
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. */
|
/* Do not bother creating a swapchain redundantly. */
|
||||||
#ifdef VULKAN_DEBUG
|
#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
|
#endif
|
||||||
vulkan_create_wait_fences(vk);
|
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,
|
vk->context.gpu, vk->vk_surface,
|
||||||
&present_mode_count, present_modes);
|
&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;
|
vk->context.swap_interval = swap_interval;
|
||||||
|
|
||||||
|
/* Prefer IMMEDIATE without vsync */
|
||||||
for (i = 0; i < present_mode_count; i++)
|
for (i = 0; i < present_mode_count; i++)
|
||||||
{
|
{
|
||||||
if ( !swap_interval
|
if ( !swap_interval
|
||||||
&& (present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR))
|
&& !vsync
|
||||||
{
|
&& present_modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)
|
||||||
swapchain_present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (!swap_interval
|
|
||||||
&& (present_modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR))
|
|
||||||
{
|
{
|
||||||
swapchain_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
swapchain_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||||
break;
|
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_MAILBOX_KHR;
|
||||||
swapchain_present_mode = VK_PRESENT_MODE_FIFO_KHR;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VULKAN_DEBUG
|
/* Present mode logging */
|
||||||
RARCH_LOG("[Vulkan]: Creating swapchain with present mode: %u\n",
|
if (vk->swapchain == VK_NULL_HANDLE)
|
||||||
(unsigned)swapchain_present_mode);
|
{
|
||||||
#endif
|
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,
|
vkGetPhysicalDeviceSurfaceFormatsKHR(vk->context.gpu,
|
||||||
vk->vk_surface, &format_count, NULL);
|
vk->vk_surface, &format_count, NULL);
|
||||||
|
@ -2175,11 +2209,6 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
|
||||||
return true;
|
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.
|
/* 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 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
|
* 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_paused = (runloop_st->flags & RUNLOOP_FLAG_PAUSED) ? true : false;
|
||||||
video_info->runloop_is_slowmotion = (runloop_st->flags & RUNLOOP_FLAG_SLOWMOTION) ? 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->fastforward_frameskip = settings->bools.fastforward_frameskip;
|
||||||
|
video_info->frame_time_target = 1000000.0f / video_info->refresh_rate;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifdef HAVE_VULKAN
|
#ifdef HAVE_VULKAN
|
||||||
/* Vulkan in Windows does mailbox emulation
|
/* Vulkan in Windows does mailbox emulation
|
||||||
* in fullscreen with vsync, effectively
|
* in fullscreen with vsync, effectively
|
||||||
* discarding frames that can't be shown,
|
* already discarding frames, therefore compensate
|
||||||
* therefore do not do it twice. */
|
* frameskip target to make it smoother and faster. */
|
||||||
if ( video_info->fullscreen
|
if ( video_info->fullscreen
|
||||||
&& settings->bools.video_vsync
|
&& settings->bools.video_vsync
|
||||||
&& string_is_equal(video_driver_get_ident(), "vulkan"))
|
&& string_is_equal(video_driver_get_ident(), "vulkan"))
|
||||||
video_info->fastforward_frameskip = false;
|
video_info->frame_time_target /= 2.0f;
|
||||||
#endif
|
#endif
|
||||||
#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 last_time;
|
||||||
static retro_time_t curr_time;
|
static retro_time_t curr_time;
|
||||||
static retro_time_t fps_time;
|
static retro_time_t fps_time;
|
||||||
static retro_time_t frame_time_accumulator;
|
|
||||||
static float last_fps, frame_time;
|
static float last_fps, frame_time;
|
||||||
static uint64_t last_used_memory, last_total_memory;
|
static uint64_t last_used_memory, last_total_memory;
|
||||||
|
static uint16_t frame_time_accumulator;
|
||||||
/* Mark the start of nonblock state for
|
/* Mark the start of nonblock state for
|
||||||
* ignoring initial previous frame time */
|
* ignoring initial previous frame time */
|
||||||
static int8_t nonblock_active;
|
static int8_t nonblock_active;
|
||||||
|
@ -3494,9 +3495,9 @@ void video_driver_frame(const void *data, unsigned width,
|
||||||
&& video_info.fastforward_frameskip)
|
&& video_info.fastforward_frameskip)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
retro_time_t frame_time_accumulator_prev = frame_time_accumulator;
|
uint16_t frame_time_accumulator_prev = frame_time_accumulator;
|
||||||
retro_time_t frame_time_delta = new_time - last_time;
|
uint16_t frame_time_delta = new_time - last_time;
|
||||||
retro_time_t frame_time_target = 1000000.0f / video_info.refresh_rate;
|
uint16_t frame_time_target = video_info.frame_time_target;
|
||||||
|
|
||||||
/* Ignore initial previous frame time
|
/* Ignore initial previous frame time
|
||||||
* to prevent rubber band startup */
|
* to prevent rubber band startup */
|
||||||
|
|
|
@ -456,6 +456,8 @@ typedef struct video_frame_info
|
||||||
uint32_t video_st_flags;
|
uint32_t video_st_flags;
|
||||||
uint16_t menu_st_flags;
|
uint16_t menu_st_flags;
|
||||||
|
|
||||||
|
uint16_t frame_time_target;
|
||||||
|
|
||||||
char stat_text[1024];
|
char stat_text[1024];
|
||||||
|
|
||||||
bool widgets_active;
|
bool widgets_active;
|
||||||
|
|
|
@ -14017,8 +14017,8 @@ static bool setting_append_list(
|
||||||
general_write_handler,
|
general_write_handler,
|
||||||
general_read_handler);
|
general_read_handler);
|
||||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||||
(*list)[list_info->index - 1].offset_by = 2;
|
(*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, 4, 1, true, true);
|
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);
|
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);
|
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_write_handler,
|
||||||
general_read_handler);
|
general_read_handler);
|
||||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
(*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))
|
if (video_driver_test_all_flags(GFX_CTX_FLAGS_ADAPTIVE_VSYNC))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue