Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Vulkan) Prefer IMMEDIATE mode without vsync #17009

Merged
merged 3 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading