(D3D11/12) Add waitable swapchains and max frame latency option

This commit is contained in:
sonninnos 2022-06-07 00:06:23 +03:00
parent 65901cb133
commit 0bb65fb39c
15 changed files with 132 additions and 17 deletions

View File

@ -335,8 +335,13 @@
/* Video VSYNC (recommended) */ /* Video VSYNC (recommended) */
#define DEFAULT_VSYNC true #define DEFAULT_VSYNC true
/* Vulkan specific */
#define DEFAULT_MAX_SWAPCHAIN_IMAGES 3 #define DEFAULT_MAX_SWAPCHAIN_IMAGES 3
/* D3D1x specific */
#define DEFAULT_MAX_FRAME_LATENCY 1
/* GL specific */
#define DEFAULT_ADAPTIVE_VSYNC false #define DEFAULT_ADAPTIVE_VSYNC false
/* Attempts to hard-synchronize CPU and GPU. /* Attempts to hard-synchronize CPU and GPU.

View File

@ -2250,6 +2250,7 @@ static struct config_uint_setting *populate_settings_uint(
SETTING_UINT("video_hard_sync_frames", &settings->uints.video_hard_sync_frames, true, DEFAULT_HARD_SYNC_FRAMES, false); SETTING_UINT("video_hard_sync_frames", &settings->uints.video_hard_sync_frames, true, DEFAULT_HARD_SYNC_FRAMES, false);
SETTING_UINT("video_frame_delay", &settings->uints.video_frame_delay, true, DEFAULT_FRAME_DELAY, false); SETTING_UINT("video_frame_delay", &settings->uints.video_frame_delay, true, DEFAULT_FRAME_DELAY, false);
SETTING_UINT("video_max_swapchain_images", &settings->uints.video_max_swapchain_images, true, DEFAULT_MAX_SWAPCHAIN_IMAGES, false); SETTING_UINT("video_max_swapchain_images", &settings->uints.video_max_swapchain_images, true, DEFAULT_MAX_SWAPCHAIN_IMAGES, false);
SETTING_UINT("video_max_frame_latency", &settings->uints.video_max_frame_latency, true, DEFAULT_MAX_FRAME_LATENCY, false);
SETTING_UINT("video_swap_interval", &settings->uints.video_swap_interval, true, DEFAULT_SWAP_INTERVAL, false); SETTING_UINT("video_swap_interval", &settings->uints.video_swap_interval, true, DEFAULT_SWAP_INTERVAL, false);
SETTING_UINT("video_rotation", &settings->uints.video_rotation, true, ORIENTATION_NORMAL, false); SETTING_UINT("video_rotation", &settings->uints.video_rotation, true, ORIENTATION_NORMAL, false);
SETTING_UINT("screen_orientation", &settings->uints.screen_orientation, true, ORIENTATION_NORMAL, false); SETTING_UINT("screen_orientation", &settings->uints.screen_orientation, true, ORIENTATION_NORMAL, false);

View File

@ -203,6 +203,7 @@ typedef struct settings
unsigned video_fullscreen_x; unsigned video_fullscreen_x;
unsigned video_fullscreen_y; unsigned video_fullscreen_y;
unsigned video_max_swapchain_images; unsigned video_max_swapchain_images;
unsigned video_max_frame_latency;
unsigned video_swap_interval; unsigned video_swap_interval;
unsigned video_hard_sync_frames; unsigned video_hard_sync_frames;
unsigned video_frame_delay; unsigned video_frame_delay;

View File

@ -172,6 +172,7 @@ typedef struct d3d11_shader_t
typedef struct typedef struct
{ {
unsigned cur_mon_id; unsigned cur_mon_id;
HANDLE frameLatencyWaitableObject;
DXGISwapChain swapChain; DXGISwapChain swapChain;
D3D11Device device; D3D11Device device;
D3D_FEATURE_LEVEL supportedFeatureLevel; D3D_FEATURE_LEVEL supportedFeatureLevel;

View File

@ -171,6 +171,7 @@ typedef struct
struct struct
{ {
HANDLE frameLatencyWaitableObject;
DXGISwapChain handle; DXGISwapChain handle;
D3D12Resource renderTargets[2]; D3D12Resource renderTargets[2];
#ifdef HAVE_DXGI_HDR #ifdef HAVE_DXGI_HDR

View File

@ -82,6 +82,15 @@ static D3D11Device cached_device_d3d11;
static D3D_FEATURE_LEVEL cached_supportedFeatureLevel; static D3D_FEATURE_LEVEL cached_supportedFeatureLevel;
static D3D11DeviceContext cached_context_d3d11; static D3D11DeviceContext cached_context_d3d11;
/* Waitable swap chain */
static void WaitOnSwapChain(HANDLE frameLatencyWaitableObject)
{
DWORD result = WaitForSingleObjectEx(
frameLatencyWaitableObject,
1000,
true);
}
static INLINE void d3d11_release_shader(d3d11_shader_t* shader) static INLINE void d3d11_release_shader(d3d11_shader_t* shader)
{ {
Release(shader->layout); Release(shader->layout);
@ -94,6 +103,7 @@ static uint32_t d3d11_get_flags(void *data)
{ {
uint32_t flags = 0; uint32_t flags = 0;
BIT32_SET(flags, GFX_CTX_FLAGS_CUSTOMIZABLE_FRAME_LATENCY);
BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING);
BIT32_SET(flags, GFX_CTX_FLAGS_OVERLAY_BEHIND_MENU_SUPPORTED); BIT32_SET(flags, GFX_CTX_FLAGS_OVERLAY_BEHIND_MENU_SUPPORTED);
#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) #if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
@ -1034,34 +1044,34 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11,
switch (d3d11->supportedFeatureLevel) switch (d3d11->supportedFeatureLevel)
{ {
case D3D_FEATURE_LEVEL_9_1: case D3D_FEATURE_LEVEL_9_1:
RARCH_LOG("[D3D11] Device created (Feature Level: 9.1)\n"); RARCH_LOG("[D3D11]: Device created (Feature Level: 9.1)\n");
break; break;
case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_2:
RARCH_LOG("[D3D11] Device created (Feature Level: 9.2)\n"); RARCH_LOG("[D3D11]: Device created (Feature Level: 9.2)\n");
break; break;
case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_3:
RARCH_LOG("[D3D11] Device created (Feature Level: 9.3)\n"); RARCH_LOG("[D3D11]: Device created (Feature Level: 9.3)\n");
break; break;
case D3D_FEATURE_LEVEL_10_0: case D3D_FEATURE_LEVEL_10_0:
RARCH_LOG("[D3D11] Device created (Feature Level: 10.0)\n"); RARCH_LOG("[D3D11]: Device created (Feature Level: 10.0)\n");
break; break;
case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_1:
RARCH_LOG("[D3D11] Device created (Feature Level: 10.1)\n"); RARCH_LOG("[D3D11]: Device created (Feature Level: 10.1)\n");
break; break;
case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_11_0:
RARCH_LOG("[D3D11] Device created (Feature Level: 11.0)\n"); RARCH_LOG("[D3D11]: Device created (Feature Level: 11.0)\n");
break; break;
case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_1:
RARCH_LOG("[D3D11] Device created (Feature Level: 11.1)\n"); RARCH_LOG("[D3D11]: Device created (Feature Level: 11.1)\n");
break; break;
case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_12_0:
RARCH_LOG("[D3D11] Device created (Feature Level: 12.0)\n"); RARCH_LOG("[D3D11]: Device created (Feature Level: 12.0)\n");
break; break;
case D3D_FEATURE_LEVEL_12_1: case D3D_FEATURE_LEVEL_12_1:
RARCH_LOG("[D3D11] Device created (Feature Level: 12.1)\n"); RARCH_LOG("[D3D11]: Device created (Feature Level: 12.1)\n");
break; break;
default: default:
RARCH_LOG("[D3D11] Device created (Feature Level: N/A)\n"); RARCH_LOG("[D3D11]: Device created (Feature Level: N/A)\n");
break; break;
} }
} }
@ -1080,6 +1090,7 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11,
d3d11->has_flip_model = true; d3d11->has_flip_model = true;
d3d11->has_allow_tearing = true; d3d11->has_allow_tearing = true;
desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
desc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
#endif #endif
@ -1090,6 +1101,7 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11,
&desc, NULL, (IDXGISwapChain1**)&d3d11->swapChain))) &desc, NULL, (IDXGISwapChain1**)&d3d11->swapChain)))
return false; return false;
#else #else
desc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
adapter->lpVtbl->GetParent( adapter->lpVtbl->GetParent(
@ -1154,6 +1166,17 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11,
#endif /* __WINRT__ */ #endif /* __WINRT__ */
if ((d3d11->frameLatencyWaitableObject = DXGIGetFrameLatencyWaitableObject(d3d11->swapChain)))
{
settings_t* settings = config_get_ptr();
UINT max_latency = settings->uints.video_max_frame_latency;
UINT cur_latency = 0;
DXGISetMaximumFrameLatency(d3d11->swapChain, max_latency);
DXGIGetMaximumFrameLatency(d3d11->swapChain, &cur_latency);
RARCH_LOG("[D3D11]: Requesting %u maximum frame latency, using %u.\n", max_latency, cur_latency);
}
#ifdef HAVE_DXGI_HDR #ifdef HAVE_DXGI_HDR
/* Check display HDR support and /* Check display HDR support and
initialize ST.2084 support to match initialize ST.2084 support to match
@ -1917,6 +1940,8 @@ static bool d3d11_gfx_frame(
{ {
UINT swapchain_flags = d3d11->has_allow_tearing UINT swapchain_flags = d3d11->has_allow_tearing
? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0; ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
swapchain_flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
#ifdef HAVE_DXGI_HDR #ifdef HAVE_DXGI_HDR
d3d11->hdr.enable = video_hdr_enable; d3d11->hdr.enable = video_hdr_enable;
@ -1992,6 +2017,8 @@ static bool d3d11_gfx_frame(
d3d11->hdr.max_fall); d3d11->hdr.max_fall);
#endif #endif
} }
else
WaitOnSwapChain(d3d11->frameLatencyWaitableObject);
{ {
D3D11Texture2D back_buffer; D3D11Texture2D back_buffer;

View File

@ -108,6 +108,15 @@ static void d3d12_gfx_sync(d3d12_video_t* d3d12)
} }
} }
/* Waitable swap chain */
static void WaitOnSwapChain(HANDLE frameLatencyWaitableObject)
{
DWORD result = WaitForSingleObjectEx(
frameLatencyWaitableObject,
1000,
true);
}
#ifdef HAVE_OVERLAY #ifdef HAVE_OVERLAY
static void d3d12_free_overlays(d3d12_video_t* d3d12) static void d3d12_free_overlays(d3d12_video_t* d3d12)
{ {
@ -1262,7 +1271,8 @@ static bool d3d12_init_swapchain(d3d12_video_t* d3d12,
#else #else
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
#endif #endif
desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
desc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
#ifdef __WINRT__ #ifdef __WINRT__
hr = DXGICreateSwapChainForCoreWindow(d3d12->factory, d3d12->queue.handle, corewindow, &desc, NULL, &d3d12->chain.handle); hr = DXGICreateSwapChainForCoreWindow(d3d12->factory, d3d12->queue.handle, corewindow, &desc, NULL, &d3d12->chain.handle);
@ -1275,6 +1285,17 @@ static bool d3d12_init_swapchain(d3d12_video_t* d3d12,
return false; return false;
} }
if ((d3d12->chain.frameLatencyWaitableObject = DXGIGetFrameLatencyWaitableObject(d3d12->chain.handle)))
{
settings_t* settings = config_get_ptr();
UINT max_latency = settings->uints.video_max_frame_latency;
UINT cur_latency = 0;
DXGISetMaximumFrameLatency(d3d12->chain.handle, max_latency);
DXGIGetMaximumFrameLatency(d3d12->chain.handle, &cur_latency);
RARCH_LOG("[D3D12]: Requesting %u maximum frame latency, using %u.\n", max_latency, cur_latency);
}
#ifdef HAVE_WINDOW #ifdef HAVE_WINDOW
DXGIMakeWindowAssociation(d3d12->factory, hwnd, DXGI_MWA_NO_ALT_ENTER); DXGIMakeWindowAssociation(d3d12->factory, hwnd, DXGI_MWA_NO_ALT_ENTER);
#endif #endif
@ -2039,6 +2060,11 @@ static bool d3d12_gfx_frame(
bool video_hdr_enable = video_info->hdr_enable; bool video_hdr_enable = video_info->hdr_enable;
DXGI_FORMAT back_buffer_format = d3d12->shader_preset && d3d12->shader_preset->passes ? glslang_format_to_dxgi(d3d12->pass[d3d12->shader_preset->passes - 1].semantics.format) : DXGI_FORMAT_R8G8B8A8_UNORM; DXGI_FORMAT back_buffer_format = d3d12->shader_preset && d3d12->shader_preset->passes ? glslang_format_to_dxgi(d3d12->pass[d3d12->shader_preset->passes - 1].semantics.format) : DXGI_FORMAT_R8G8B8A8_UNORM;
bool use_back_buffer = back_buffer_format != d3d12->chain.formats[d3d12->chain.bit_depth]; bool use_back_buffer = back_buffer_format != d3d12->chain.formats[d3d12->chain.bit_depth];
#endif
d3d12_gfx_sync(d3d12);
#ifdef HAVE_DXGI_HDR
if (d3d12->resize_chain || (d3d12->hdr.enable != video_hdr_enable)) if (d3d12->resize_chain || (d3d12->hdr.enable != video_hdr_enable))
#else #else
if (d3d12->resize_chain) if (d3d12->resize_chain)
@ -2147,6 +2173,8 @@ static bool d3d12_gfx_frame(
d3d12->hdr.max_fall); d3d12->hdr.max_fall);
#endif #endif
} }
else
WaitOnSwapChain(d3d12->chain.frameLatencyWaitableObject);
D3D12ResetCommandAllocator(d3d12->queue.allocator); D3D12ResetCommandAllocator(d3d12->queue.allocator);
@ -2646,9 +2674,6 @@ static bool d3d12_gfx_frame(
#endif #endif
DXGIPresent(d3d12->chain.handle, sync_interval, present_flags); DXGIPresent(d3d12->chain.handle, sync_interval, present_flags);
/* Sync after Present for minimal delay */
d3d12_gfx_sync(d3d12);
return true; return true;
} }
@ -2857,6 +2882,7 @@ static uint32_t d3d12_get_flags(void *data)
{ {
uint32_t flags = 0; uint32_t flags = 0;
BIT32_SET(flags, GFX_CTX_FLAGS_CUSTOMIZABLE_FRAME_LATENCY);
BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING);
BIT32_SET(flags, GFX_CTX_FLAGS_OVERLAY_BEHIND_MENU_SUPPORTED); BIT32_SET(flags, GFX_CTX_FLAGS_OVERLAY_BEHIND_MENU_SUPPORTED);
#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) #if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)

View File

@ -208,6 +208,7 @@ enum display_flags
GFX_CTX_FLAGS_GL_CORE_CONTEXT, GFX_CTX_FLAGS_GL_CORE_CONTEXT,
GFX_CTX_FLAGS_MULTISAMPLING, GFX_CTX_FLAGS_MULTISAMPLING,
GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES, GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES,
GFX_CTX_FLAGS_CUSTOMIZABLE_FRAME_LATENCY,
GFX_CTX_FLAGS_HARD_SYNC, GFX_CTX_FLAGS_HARD_SYNC,
GFX_CTX_FLAGS_BLACK_FRAME_INSERTION, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION,
GFX_CTX_FLAGS_MENU_FRAME_FILTERING, GFX_CTX_FLAGS_MENU_FRAME_FILTERING,

View File

@ -3586,6 +3586,10 @@ MSG_HASH(
MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES, MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES,
"video_max_swapchain_images" "video_max_swapchain_images"
) )
MSG_HASH(
MENU_ENUM_LABEL_VIDEO_MAX_FRAME_LATENCY,
"video_max_frame_latency"
)
MSG_HASH( MSG_HASH(
MENU_ENUM_LABEL_VIDEO_MESSAGE_POS_X, MENU_ENUM_LABEL_VIDEO_MESSAGE_POS_X,
"video_message_pos_x" "video_message_pos_x"

View File

@ -10893,12 +10893,20 @@ MSG_HASH(
) )
MSG_HASH( MSG_HASH(
MENU_ENUM_LABEL_VALUE_VIDEO_MAX_SWAPCHAIN_IMAGES, MENU_ENUM_LABEL_VALUE_VIDEO_MAX_SWAPCHAIN_IMAGES,
"Max swapchain images" "Max Swapchain Images"
) )
MSG_HASH( MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_MAX_SWAPCHAIN_IMAGES, MENU_ENUM_SUBLABEL_VIDEO_MAX_SWAPCHAIN_IMAGES,
"Tells the video driver to explicitly use a specified buffering mode." "Tells the video driver to explicitly use a specified buffering mode."
) )
MSG_HASH(
MENU_ENUM_LABEL_VALUE_VIDEO_MAX_FRAME_LATENCY,
"Max Frame Latency"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_MAX_FRAME_LATENCY,
"Tells the video driver to explicitly use a specified buffering mode."
)
MSG_HASH( MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_PARAMETERS, MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_PARAMETERS,
"Modifies the shader preset itself currently used in the menu." "Modifies the shader preset itself currently used in the menu."

View File

@ -353,10 +353,11 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_localap_enable, MENU_
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_timezone, MENU_ENUM_SUBLABEL_TIMEZONE) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_timezone, MENU_ENUM_SUBLABEL_TIMEZONE)
#endif #endif
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_user_language, MENU_ENUM_SUBLABEL_USER_LANGUAGE) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_user_language, MENU_ENUM_SUBLABEL_USER_LANGUAGE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_max_swapchain_images, MENU_ENUM_SUBLABEL_VIDEO_MAX_SWAPCHAIN_IMAGES ) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_max_swapchain_images, MENU_ENUM_SUBLABEL_VIDEO_MAX_SWAPCHAIN_IMAGES)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_max_frame_latency, MENU_ENUM_SUBLABEL_VIDEO_MAX_FRAME_LATENCY)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_online_updater, MENU_ENUM_SUBLABEL_ONLINE_UPDATER) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_online_updater, MENU_ENUM_SUBLABEL_ONLINE_UPDATER)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_fps_show, MENU_ENUM_SUBLABEL_FPS_SHOW) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_fps_show, MENU_ENUM_SUBLABEL_FPS_SHOW)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_fps_update_interval, MENU_ENUM_SUBLABEL_FPS_UPDATE_INTERVAL) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_fps_update_interval, MENU_ENUM_SUBLABEL_FPS_UPDATE_INTERVAL)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_framecount_show, MENU_ENUM_SUBLABEL_FRAMECOUNT_SHOW) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_framecount_show, MENU_ENUM_SUBLABEL_FRAMECOUNT_SHOW)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_memory_show, MENU_ENUM_SUBLABEL_MEMORY_SHOW) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_memory_show, MENU_ENUM_SUBLABEL_MEMORY_SHOW)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_memory_update_interval, MENU_ENUM_SUBLABEL_MEMORY_UPDATE_INTERVAL) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_memory_update_interval, MENU_ENUM_SUBLABEL_MEMORY_UPDATE_INTERVAL)
@ -4231,6 +4232,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES: case MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_max_swapchain_images); BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_max_swapchain_images);
break; break;
case MENU_ENUM_LABEL_VIDEO_MAX_FRAME_LATENCY:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_max_frame_latency);
break;
case MENU_ENUM_LABEL_NETPLAY_PING_SHOW: case MENU_ENUM_LABEL_NETPLAY_PING_SHOW:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_netplay_ping_show); BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_netplay_ping_show);
break; break;

View File

@ -8617,6 +8617,14 @@ unsigned menu_displaylist_build_list(
count++; count++;
} }
if (video_driver_test_all_flags(GFX_CTX_FLAGS_CUSTOMIZABLE_FRAME_LATENCY))
{
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_VIDEO_MAX_FRAME_LATENCY,
PARSE_ONLY_UINT, false) == 0)
count++;
}
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_VRR_RUNLOOP_ENABLE, MENU_ENUM_LABEL_VRR_RUNLOOP_ENABLE,
PARSE_ONLY_BOOL, false) == 0) PARSE_ONLY_BOOL, false) == 0)
@ -9055,6 +9063,14 @@ unsigned menu_displaylist_build_list(
count++; count++;
} }
if (video_driver_test_all_flags(GFX_CTX_FLAGS_CUSTOMIZABLE_FRAME_LATENCY))
{
MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_VIDEO_MAX_FRAME_LATENCY,
PARSE_ONLY_UINT, false);
count++;
}
if (video_driver_test_all_flags(GFX_CTX_FLAGS_HARD_SYNC)) if (video_driver_test_all_flags(GFX_CTX_FLAGS_HARD_SYNC))
{ {
MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,

View File

@ -12507,6 +12507,23 @@ static bool setting_append_list(
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);
CONFIG_UINT(
list, list_info,
&settings->uints.video_max_frame_latency,
MENU_ENUM_LABEL_VIDEO_MAX_FRAME_LATENCY,
MENU_ENUM_LABEL_VALUE_VIDEO_MAX_FRAME_LATENCY,
DEFAULT_MAX_FRAME_LATENCY,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].offset_by = 1;
menu_settings_list_current_add_range(list, list_info, (*list)[list_info->index - 1].offset_by, 3, 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);
CONFIG_BOOL( CONFIG_BOOL(
list, list_info, list, list_info,
&settings->bools.video_hard_sync, &settings->bools.video_hard_sync,

View File

@ -1097,6 +1097,7 @@ enum msg_hash_enums
MENU_LABEL(VIDEO_FILTER_FLICKER), MENU_LABEL(VIDEO_FILTER_FLICKER),
MENU_LABEL(VIDEO_SOFT_FILTER), MENU_LABEL(VIDEO_SOFT_FILTER),
MENU_LABEL(VIDEO_MAX_SWAPCHAIN_IMAGES), MENU_LABEL(VIDEO_MAX_SWAPCHAIN_IMAGES),
MENU_LABEL(VIDEO_MAX_FRAME_LATENCY),
MENU_LABEL(VIDEO_GPU_SCREENSHOT), MENU_LABEL(VIDEO_GPU_SCREENSHOT),
MENU_LABEL(VIDEO_BLACK_FRAME_INSERTION), MENU_LABEL(VIDEO_BLACK_FRAME_INSERTION),
MENU_LABEL(VIDEO_FRAME_DELAY), MENU_LABEL(VIDEO_FRAME_DELAY),

View File

@ -354,6 +354,7 @@ QWidget *LatencyPage::widget()
} }
layout->add(MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES); layout->add(MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES);
layout->add(MENU_ENUM_LABEL_VIDEO_MAX_FRAME_LATENCY);
layout->add(MENU_ENUM_LABEL_VIDEO_FRAME_DELAY); layout->add(MENU_ENUM_LABEL_VIDEO_FRAME_DELAY);
layout->add(MENU_ENUM_LABEL_AUDIO_LATENCY); layout->add(MENU_ENUM_LABEL_AUDIO_LATENCY);
@ -1340,6 +1341,7 @@ QWidget *VideoPage::widget()
} }
syncGroup->add(MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES); syncGroup->add(MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES);
syncGroup->add(MENU_ENUM_LABEL_VIDEO_MAX_FRAME_LATENCY);
syncGroup->add(MENU_ENUM_LABEL_VRR_RUNLOOP_ENABLE); syncGroup->add(MENU_ENUM_LABEL_VRR_RUNLOOP_ENABLE);
miscGroup->add(MENU_ENUM_LABEL_SUSPEND_SCREENSAVER_ENABLE); miscGroup->add(MENU_ENUM_LABEL_SUSPEND_SCREENSAVER_ENABLE);