Skip to content

Commit

Permalink
(Vulkan) Prefer IMMEDIATE mode without vsync (#17009)
Browse files Browse the repository at this point in the history
* (Vulkan) Prefer IMMEDIATE mode without vsync

* Clamp max_swapchain_images and hard_sync_frames

* (Vulkan) Improve fastforward frameskip option hack
  • Loading branch information
sonninnos committed Sep 17, 2024
1 parent 61a3397 commit 6713e3b
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 38 deletions.
4 changes: 4 additions & 0 deletions config.def.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
9 changes: 7 additions & 2 deletions configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
81 changes: 55 additions & 26 deletions gfx/common/vulkan_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -2025,43 +2025,77 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
vk->context.gpu, vk->vk_surface,
&present_mode_count, present_modes);

#ifdef VULKAN_DEBUG
vk->context.swap_interval = swap_interval;

/* Prefer IMMEDIATE without vsync */
for (i = 0; i < present_mode_count; i++)
{
RARCH_LOG("[Vulkan]: Swapchain supports present mode: %u.\n",
present_modes[i]);
if ( !swap_interval
&& !vsync
&& present_modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)
{
swapchain_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
break;
}
}
#endif

vk->context.swap_interval = swap_interval;
/* If still in FIFO with no swap interval, try MAILBOX */
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_FIFO_KHR
&& 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))
}

/* Present mode logging */
if (vk->swapchain == VK_NULL_HANDLE)
{
for (i = 0; i < present_mode_count; i++)
{
swapchain_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
break;
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 if ( swap_interval
&& (present_modes[i] == VK_PRESENT_MODE_FIFO_KHR))
}
else
{
switch (swapchain_present_mode)
{
/* Kind of tautological since FIFO must always be present. */
swapchain_present_mode = VK_PRESENT_MODE_FIFO_KHR;
break;
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;
}
}

#ifdef VULKAN_DEBUG
RARCH_LOG("[Vulkan]: Creating swapchain with present mode: %u\n",
(unsigned)swapchain_present_mode);
#endif

vkGetPhysicalDeviceSurfaceFormatsKHR(vk->context.gpu,
vk->vk_surface, &format_count, NULL);
vkGetPhysicalDeviceSurfaceFormatsKHR(vk->context.gpu,
Expand Down Expand Up @@ -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
Expand Down
15 changes: 8 additions & 7 deletions gfx/video_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down
2 changes: 2 additions & 0 deletions gfx/video_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions menu/menu_setting.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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))
{
Expand Down

0 comments on commit 6713e3b

Please sign in to comment.