From 54329f47910288973f51601d112863523f805c10 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 00:24:30 +0200 Subject: [PATCH 01/14] Drop redundant video_driver_get_size calls --- gfx/drivers/gdi_gfx.c | 4 ++-- gfx/drivers/gl1.c | 4 ++-- gfx/drivers/gl2.c | 4 ++-- gfx/drivers/gl3.c | 3 ++- gfx/drivers/vg.c | 4 ++-- gfx/drivers/vulkan.c | 3 ++- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/gfx/drivers/gdi_gfx.c b/gfx/drivers/gdi_gfx.c index bd24a6da2ec8..f0387b070a8d 100644 --- a/gfx/drivers/gdi_gfx.c +++ b/gfx/drivers/gdi_gfx.c @@ -571,8 +571,8 @@ static void *gdi_init(const video_info_t *video, if (temp_width != 0 && temp_height != 0) video_driver_set_size(temp_width, temp_height); - - video_driver_get_size(&temp_width, &temp_height); + else + video_driver_get_size(&temp_width, &temp_height); RARCH_LOG("[GDI] Using resolution %ux%u.\n", temp_width, temp_height); diff --git a/gfx/drivers/gl1.c b/gfx/drivers/gl1.c index c04258f8702b..1a88590f4350 100644 --- a/gfx/drivers/gl1.c +++ b/gfx/drivers/gl1.c @@ -1285,8 +1285,8 @@ static void *gl1_init(const video_info_t *video, if (temp_width != 0 && temp_height != 0) video_driver_set_size(temp_width, temp_height); - - video_driver_get_size(&temp_width, &temp_height); + else + video_driver_get_size(&temp_width, &temp_height); RARCH_LOG("[GL1] Using resolution %ux%u.\n", temp_width, temp_height); diff --git a/gfx/drivers/gl2.c b/gfx/drivers/gl2.c index 5efbaf260e8c..af9b41522520 100644 --- a/gfx/drivers/gl2.c +++ b/gfx/drivers/gl2.c @@ -4657,8 +4657,8 @@ static void *gl2_init(const video_info_t *video, if (temp_width != 0 && temp_height != 0) video_driver_set_size(temp_width, temp_height); - - video_driver_get_size(&temp_width, &temp_height); + else + video_driver_get_size(&temp_width, &temp_height); gl->video_width = temp_width; gl->video_height = temp_height; diff --git a/gfx/drivers/gl3.c b/gfx/drivers/gl3.c index c9229106ca37..2f9aa431f679 100644 --- a/gfx/drivers/gl3.c +++ b/gfx/drivers/gl3.c @@ -3025,7 +3025,8 @@ static void *gl3_init(const video_info_t *video, if (temp_width != 0 && temp_height != 0) video_driver_set_size(temp_width, temp_height); - video_driver_get_size(&temp_width, &temp_height); + else + video_driver_get_size(&temp_width, &temp_height); gl->video_width = temp_width; gl->video_height = temp_height; diff --git a/gfx/drivers/vg.c b/gfx/drivers/vg.c index c52160dff63d..aa8ee5fdcd5d 100644 --- a/gfx/drivers/vg.c +++ b/gfx/drivers/vg.c @@ -197,8 +197,8 @@ static void *vg_init(const video_info_t *video, temp_width, temp_height); video_driver_set_size(temp_width, temp_height); } - - video_driver_get_size(&temp_width, &temp_height); + else + video_driver_get_size(&temp_width, &temp_height); vg->mScreenAspect = (float)temp_width / temp_height; diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index d933ba299f78..12c9ed83fa8e 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -4987,7 +4987,8 @@ static void *vulkan_init(const video_info_t *video, if (temp_width != 0 && temp_height != 0) video_driver_set_size(temp_width, temp_height); - video_driver_get_size(&temp_width, &temp_height); + else + video_driver_get_size(&temp_width, &temp_height); vk->video_width = temp_width; vk->video_height = temp_height; vk->translate_x = 0.0; From 2da65bbf43b9e66b80242a7c72b88ad7925274c8 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 00:25:04 +0200 Subject: [PATCH 02/14] Followup to previous commit --- gfx/common/d3d9_common.c | 11 ++++++++++- gfx/drivers/d3d8.c | 35 +++++++++++++++++++++-------------- gfx/drivers/d3d9cg.c | 24 +++++++++++------------- gfx/drivers/d3d9hlsl.c | 24 +++++++++++------------- 4 files changed, 53 insertions(+), 41 deletions(-) diff --git a/gfx/common/d3d9_common.c b/gfx/common/d3d9_common.c index 4a338418c515..8f02487dd154 100644 --- a/gfx/common/d3d9_common.c +++ b/gfx/common/d3d9_common.c @@ -336,13 +336,22 @@ void d3d9_make_d3dpp(d3d9_video_t *d3d, if (!windowed_enable) { #ifdef _XBOX + /* Xbox: query the actual display size and publish it to + * video_st. Use the same values directly for the d3dpp + * back-buffer rather than reading them back via + * video_driver_get_size (which would just return what we + * just wrote -- nothing else writes video_st->width / + * height except the video drivers themselves). */ unsigned width = 0; unsigned height = 0; d3d9_get_video_size(d3d, &width, &height); video_driver_set_size(width, height); -#endif + d3dpp->BackBufferWidth = width; + d3dpp->BackBufferHeight = height; +#else video_driver_get_size(&d3dpp->BackBufferWidth, &d3dpp->BackBufferHeight); +#endif } #ifdef _XBOX diff --git a/gfx/drivers/d3d8.c b/gfx/drivers/d3d8.c index f9f861623f96..32bb3ae55497 100644 --- a/gfx/drivers/d3d8.c +++ b/gfx/drivers/d3d8.c @@ -2104,14 +2104,23 @@ static void d3d8_make_d3dpp(void *data, if (!windowed_enable) { #ifdef _XBOX + /* Xbox: query the actual display size and publish it to + * video_st. Use the same values directly for the d3dpp + * back-buffer rather than reading them back via + * video_driver_get_size (which would just return what we + * just wrote -- nothing else writes video_st->width / + * height except the video drivers themselves). */ unsigned width = 0; unsigned height = 0; d3d8_get_video_size(d3d, &width, &height); video_driver_set_size(width, height); -#endif + d3dpp->BackBufferWidth = width; + d3dpp->BackBufferHeight = height; +#else video_driver_get_size(&d3dpp->BackBufferWidth, &d3dpp->BackBufferHeight); +#endif } #ifdef _XBOX @@ -2481,10 +2490,6 @@ static bool d3d8_init_internal(d3d8_video_t *d3d, HMONITOR hm_to_use; #endif struct video_shader_pass *pass = NULL; -#ifdef HAVE_WINDOW - unsigned win_width = 0; - unsigned win_height = 0; -#endif unsigned full_x = 0; unsigned full_y = 0; settings_t *settings = config_get_ptr(); @@ -2538,18 +2543,20 @@ static bool d3d8_init_internal(d3d8_video_t *d3d, unsigned new_width = info->fullscreen ? full_x : info->width; unsigned new_height = info->fullscreen ? full_y : info->height; video_driver_set_size(new_width, new_height); - } #ifdef HAVE_WINDOW - video_driver_get_size(&win_width, &win_height); - - if (!win32_set_video_mode(d3d, win_width, win_height, - info->fullscreen)) - { - RARCH_ERR("[D3D8] win32_set_video_mode failed.\n"); - return false; - } + /* Use new_width / new_height directly rather than reading + * them back via video_driver_get_size: nothing in the + * codebase writes video_st->width / height between the + * set_size above and this call except us. */ + if (!win32_set_video_mode(d3d, new_width, new_height, + info->fullscreen)) + { + RARCH_ERR("[D3D8] win32_set_video_mode failed.\n"); + return false; + } #endif + } memset(&d3d->shader, 0, sizeof(d3d->shader)); d3d->shader.passes = 1; diff --git a/gfx/drivers/d3d9cg.c b/gfx/drivers/d3d9cg.c index bd194f58c8a6..2e86bf9538b1 100644 --- a/gfx/drivers/d3d9cg.c +++ b/gfx/drivers/d3d9cg.c @@ -3918,10 +3918,6 @@ static bool d3d9_cg_init_internal(d3d9_video_t *d3d, RECT mon_rect; MONITORINFOEX current_mon; HMONITOR hm_to_use; -#endif -#ifdef HAVE_WINDOW - unsigned win_width = 0; - unsigned win_height = 0; #endif unsigned full_x = 0; unsigned full_y = 0; @@ -3978,18 +3974,20 @@ static bool d3d9_cg_init_internal(d3d9_video_t *d3d, unsigned new_width = info->fullscreen ? full_x : info->width; unsigned new_height = info->fullscreen ? full_y : info->height; video_driver_set_size(new_width, new_height); - } #ifdef HAVE_WINDOW - video_driver_get_size(&win_width, &win_height); - - if (!win32_set_video_mode(d3d, win_width, win_height, - info->fullscreen)) - { - RARCH_ERR("[D3D9 Cg] win32_set_video_mode failed.\n"); - return false; - } + /* Use new_width / new_height directly rather than reading + * them back via video_driver_get_size: nothing in the + * codebase writes video_st->width / height between the + * set_size above and this call except us. */ + if (!win32_set_video_mode(d3d, new_width, new_height, + info->fullscreen)) + { + RARCH_ERR("[D3D9 Cg] win32_set_video_mode failed.\n"); + return false; + } #endif + } d3d->video_info = *info; diff --git a/gfx/drivers/d3d9hlsl.c b/gfx/drivers/d3d9hlsl.c index 7bef5423ed27..e53d0f8dc4e4 100644 --- a/gfx/drivers/d3d9hlsl.c +++ b/gfx/drivers/d3d9hlsl.c @@ -7144,10 +7144,6 @@ static bool d3d9_hlsl_init_internal(d3d9_video_t *d3d, RECT mon_rect; MONITORINFOEX current_mon; HMONITOR hm_to_use; -#endif -#ifdef HAVE_WINDOW - unsigned win_width = 0; - unsigned win_height = 0; #endif unsigned full_x = 0; unsigned full_y = 0; @@ -7204,18 +7200,20 @@ static bool d3d9_hlsl_init_internal(d3d9_video_t *d3d, unsigned new_width = info->fullscreen ? full_x : info->width; unsigned new_height = info->fullscreen ? full_y : info->height; video_driver_set_size(new_width, new_height); - } #ifdef HAVE_WINDOW - video_driver_get_size(&win_width, &win_height); - - if (!win32_set_video_mode(d3d, win_width, win_height, - info->fullscreen)) - { - RARCH_ERR("[D3D9 HLSL] win32_set_video_mode failed.\n"); - return false; - } + /* Use new_width / new_height directly rather than reading + * them back via video_driver_get_size: nothing in the + * codebase writes video_st->width / height between the + * set_size above and this call except us. */ + if (!win32_set_video_mode(d3d, new_width, new_height, + info->fullscreen)) + { + RARCH_ERR("[D3D9 HLSL] win32_set_video_mode failed.\n"); + return false; + } #endif + } d3d->video_info = *info; From 5a60e25fd9400a4394cf4b5f35df41c2e033d23e Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 00:45:22 +0200 Subject: [PATCH 03/14] More video_driver_get_size removal --- gfx/drivers/d3d8.c | 66 ++++++++++++++++++++++++--------------- gfx/drivers/network_gfx.c | 18 +++++------ gfx/drivers/sixel_gfx.c | 19 +++++------ 3 files changed, 54 insertions(+), 49 deletions(-) diff --git a/gfx/drivers/d3d8.c b/gfx/drivers/d3d8.c index 32bb3ae55497..981d16ecb225 100644 --- a/gfx/drivers/d3d8.c +++ b/gfx/drivers/d3d8.c @@ -409,9 +409,8 @@ static void d3d8_set_vertices( unsigned pass, unsigned vert_width, unsigned vert_height, uint64_t frame_count) { - unsigned width, height; - - video_driver_get_size(&width, &height); + unsigned width = d3d->vp.full_width; + unsigned height = d3d->vp.full_height; if (chain->last_width != vert_width || chain->last_height != vert_height) { @@ -572,15 +571,14 @@ static bool d3d8_setup_init(void *data, bool rgb32 ) { - unsigned width, height; d3d8_video_t *d3d = (d3d8_video_t*)data; settings_t *settings = config_get_ptr(); LPDIRECT3DDEVICE8 d3dr = (LPDIRECT3DDEVICE8)d3d->dev; d3d8_renderchain_t *chain = (d3d8_renderchain_t*)d3d->renderchain_data; unsigned fmt = (rgb32) ? RETRO_PIXEL_FORMAT_XRGB8888 : RETRO_PIXEL_FORMAT_RGB565; video_viewport_t *custom_vp = &settings->video_vp_custom; - - video_driver_get_size(&width, &height); + unsigned width = d3d->vp.full_width; + unsigned height = d3d->vp.full_height; chain->dev = dev_data; chain->pixel_size = (fmt == RETRO_PIXEL_FORMAT_RGB565) @@ -1569,7 +1567,8 @@ static void d3d8_font_render_msg( if (!d3d) return; - video_driver_get_size(&width, &height); + width = d3d->vp.full_width; + height = d3d->vp.full_height; if (!width || !height) return; @@ -1781,21 +1780,18 @@ gfx_display_ctx_driver_t gfx_display_ctx_d3d8 = { static void d3d8_viewport_info(void *data, struct video_viewport *vp) { - unsigned width, height; d3d8_video_t *d3d = (d3d8_video_t*)data; if (!d3d || !vp) return; - video_driver_get_size(&width, &height); - vp->x = d3d->out_vp.X; vp->y = d3d->out_vp.Y; vp->width = d3d->out_vp.Width; vp->height = d3d->out_vp.Height; - vp->full_width = width; - vp->full_height = height; + vp->full_width = d3d->vp.full_width; + vp->full_height = d3d->vp.full_height; } static void d3d8_overlay_render(d3d8_video_t *d3d, @@ -2104,22 +2100,25 @@ static void d3d8_make_d3dpp(void *data, if (!windowed_enable) { #ifdef _XBOX - /* Xbox: query the actual display size and publish it to - * video_st. Use the same values directly for the d3dpp - * back-buffer rather than reading them back via - * video_driver_get_size (which would just return what we - * just wrote -- nothing else writes video_st->width / - * height except the video drivers themselves). */ + /* Xbox: query the actual display size, publish it to video_st + * and track it in d3d->vp.full_width/full_height so subsequent + * read sites (font_render_msg, viewport_info, etc.) can pull + * from the local field instead of locking video_st. */ unsigned width = 0; unsigned height = 0; d3d8_get_video_size(d3d, &width, &height); video_driver_set_size(width, height); + d3d->vp.full_width = width; + d3d->vp.full_height = height; d3dpp->BackBufferWidth = width; d3dpp->BackBufferHeight = height; #else - video_driver_get_size(&d3dpp->BackBufferWidth, - &d3dpp->BackBufferHeight); + /* Non-Xbox: by the time make_d3dpp runs, d3d8_init_internal + * has already published the size and written d3d->vp. + * full_width/full_height; read from there. */ + d3dpp->BackBufferWidth = d3d->vp.full_width; + d3dpp->BackBufferHeight = d3d->vp.full_height; #endif } @@ -2202,7 +2201,8 @@ static void d3d8_calculate_rect(void *data, struct video_viewport vp; d3d8_video_t *d3d = (d3d8_video_t*)data; - video_driver_get_size(width, height); + *width = d3d->vp.full_width; + *height = d3d->vp.full_height; vp.full_width = *width; vp.full_height = *height; @@ -2267,7 +2267,6 @@ static void d3d8_set_viewport(void *data, static bool d3d8_initialize(d3d8_video_t *d3d, const video_info_t *info) { struct LinkInfo link_info; - unsigned width, height; unsigned i = 0; bool ret = true; settings_t *settings = config_get_ptr(); @@ -2316,9 +2315,10 @@ static bool d3d8_initialize(d3d8_video_t *d3d, const video_info_t *info) ) return false; - video_driver_get_size(&width, &height); + /* d3d->vp.full_* was written by the caller (d3d8_init_internal + * has already called set_size at this point). */ d3d8_set_viewport(d3d, - width, height, false, true); + d3d->vp.full_width, d3d->vp.full_height, false, true); font_driver_init_osd(d3d, info, false, @@ -2413,6 +2413,8 @@ static void d3d8_set_resize(d3d8_video_t *d3d, d3d->video_info.width = new_width; d3d->video_info.height = new_height; video_driver_set_size(new_width, new_height); + d3d->vp.full_width = new_width; + d3d->vp.full_height = new_height; } static bool d3d8_alive(void *data) @@ -2424,8 +2426,14 @@ static bool d3d8_alive(void *data) bool quit = false; bool resize = false; - /* Needed because some context drivers don't track their sizes */ - video_driver_get_size(&temp_width, &temp_height); + /* Read from local bookkeeping rather than video_st (which + * would acquire context_lock + display_lock). d3d->vp.full_* + * is written at every set_size call site in this driver, so + * it stays in sync with video_st->width/height as long as no + * other code path writes them. In practice nothing does -- + * see video_driver.c audit. */ + temp_width = d3d->vp.full_width; + temp_height = d3d->vp.full_height; win32_check_window(NULL, &quit, &resize, &temp_width, &temp_height); @@ -2442,7 +2450,11 @@ static bool d3d8_alive(void *data) ret = !quit; if (temp_width != 0 && temp_height != 0) + { video_driver_set_size(temp_width, temp_height); + d3d->vp.full_width = temp_width; + d3d->vp.full_height = temp_height; + } return ret; } @@ -2543,6 +2555,8 @@ static bool d3d8_init_internal(d3d8_video_t *d3d, unsigned new_width = info->fullscreen ? full_x : info->width; unsigned new_height = info->fullscreen ? full_y : info->height; video_driver_set_size(new_width, new_height); + d3d->vp.full_width = new_width; + d3d->vp.full_height = new_height; #ifdef HAVE_WINDOW /* Use new_width / new_height directly rather than reading diff --git a/gfx/drivers/network_gfx.c b/gfx/drivers/network_gfx.c index ccd44f45aa1a..54a3e2741237 100644 --- a/gfx/drivers/network_gfx.c +++ b/gfx/drivers/network_gfx.c @@ -343,17 +343,13 @@ static void network_gfx_set_nonblock_state(void *a, bool b, bool c, unsigned d) static bool network_gfx_alive(void *data) { - unsigned temp_width = 0; - unsigned temp_height = 0; - bool quit = false; - bool resize = false; - network_video_t *network = (network_video_t*)data; - - video_driver_get_size(&temp_width, &temp_height); - - if (temp_width != 0 && temp_height != 0) - video_driver_set_size(temp_width, temp_height); - + /* The video_driver_get_size + conditional set_size dance that + * used to live here was a copy-paste from d3d8_alive, where the + * intermediate win32_check_window call mutates the fetched + * size on window resize. The network driver has no equivalent + * windowing step, so the get/set was reading and writing back + * the same values -- a pure no-op. Drop it. */ + (void)data; return true; } diff --git a/gfx/drivers/sixel_gfx.c b/gfx/drivers/sixel_gfx.c index c7ad186bcf2a..9364b2437afe 100644 --- a/gfx/drivers/sixel_gfx.c +++ b/gfx/drivers/sixel_gfx.c @@ -502,18 +502,13 @@ static bool sixel_gfx_frame(void *data, const void *frame, static bool sixel_gfx_alive(void *data) { - unsigned temp_width = 0; - unsigned temp_height = 0; - bool quit = false; - bool resize = false; - sixel_t *sixel = (sixel_t*)data; - - /* Needed because some context drivers don't track their sizes */ - video_driver_get_size(&temp_width, &temp_height); - - if (temp_width != 0 && temp_height != 0) - video_driver_set_size(temp_width, temp_height); - + /* The video_driver_get_size + conditional set_size dance that + * used to live here was a copy-paste from d3d8_alive, where the + * intermediate win32_check_window call mutates the fetched + * size on window resize. sixel has no equivalent windowing + * step, so the get/set was reading and writing back the same + * values -- a pure no-op. Drop it. */ + (void)data; return true; } From f548180cffc8eac9681426a34bc254a0795b6c52 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 00:56:14 +0200 Subject: [PATCH 04/14] Kill more video_driver_get_size calls now in d3d9 --- gfx/common/d3d9_common.c | 19 ++++++++------- gfx/drivers/d3d9cg.c | 51 +++++++++++++++++++++++----------------- gfx/drivers/d3d9hlsl.c | 41 ++++++++++++++++++++------------ 3 files changed, 67 insertions(+), 44 deletions(-) diff --git a/gfx/common/d3d9_common.c b/gfx/common/d3d9_common.c index 8f02487dd154..38c59c490c59 100644 --- a/gfx/common/d3d9_common.c +++ b/gfx/common/d3d9_common.c @@ -336,21 +336,24 @@ void d3d9_make_d3dpp(d3d9_video_t *d3d, if (!windowed_enable) { #ifdef _XBOX - /* Xbox: query the actual display size and publish it to - * video_st. Use the same values directly for the d3dpp - * back-buffer rather than reading them back via - * video_driver_get_size (which would just return what we - * just wrote -- nothing else writes video_st->width / - * height except the video drivers themselves). */ + /* Xbox: query the actual display size, publish it to video_st + * and track it in d3d->vp.full_width/full_height so subsequent + * read sites can pull from the local field instead of locking + * video_st. */ unsigned width = 0; unsigned height = 0; d3d9_get_video_size(d3d, &width, &height); video_driver_set_size(width, height); + d3d->vp.full_width = width; + d3d->vp.full_height = height; d3dpp->BackBufferWidth = width; d3dpp->BackBufferHeight = height; #else - video_driver_get_size(&d3dpp->BackBufferWidth, - &d3dpp->BackBufferHeight); + /* Non-Xbox: by the time make_d3dpp runs, d3d9_*_init_internal + * has already published the size and written d3d->vp. + * full_width/full_height; read from there. */ + d3dpp->BackBufferWidth = d3d->vp.full_width; + d3dpp->BackBufferHeight = d3d->vp.full_height; #endif } diff --git a/gfx/drivers/d3d9cg.c b/gfx/drivers/d3d9cg.c index 2e86bf9538b1..013bd5635382 100644 --- a/gfx/drivers/d3d9cg.c +++ b/gfx/drivers/d3d9cg.c @@ -1489,7 +1489,8 @@ static void d3d9_cg_font_render_msg( if (!d3d || !font || !msg || !*msg) return; - video_driver_get_size(&width, &height); + width = d3d->vp.full_width; + height = d3d->vp.full_height; if (!width || !height) return; @@ -1657,8 +1658,8 @@ static void d3d9_cg_font_render_msg( float _inv_vp_w, _inv_vp_h; float _inv_tex_w, _inv_tex_h; const struct font_glyph *_glyph_q = NULL; - unsigned _rl_width = 0; - unsigned _rl_height = 0; + unsigned _rl_width = d3d->vp.full_width; + unsigned _rl_height = d3d->vp.full_height; int _rx, _ry; unsigned _vert_count = 0; Vertex *_verts = NULL; @@ -1668,7 +1669,6 @@ static void d3d9_cg_font_render_msg( float _rl_pos_y = drop_pos_y; D3DCOLOR _rl_color = color_dark; - video_driver_get_size(&_rl_width, &_rl_height); if (_rl_width && _rl_height) { _verts = d3d9_cg_font_get_scratch(font, _rl_msg_len * 6); @@ -1771,8 +1771,8 @@ static void d3d9_cg_font_render_msg( float _inv_vp_w, _inv_vp_h; float _inv_tex_w, _inv_tex_h; const struct font_glyph *_glyph_q = NULL; - unsigned _rl_width = 0; - unsigned _rl_height = 0; + unsigned _rl_width = d3d->vp.full_width; + unsigned _rl_height = d3d->vp.full_height; int _rx, _ry; unsigned _vert_count = 0; Vertex *_verts = NULL; @@ -1782,7 +1782,6 @@ static void d3d9_cg_font_render_msg( float _rl_pos_y = line_y; D3DCOLOR _rl_color = color; - video_driver_get_size(&_rl_width, &_rl_height); if (_rl_width && _rl_height) { _verts = d3d9_cg_font_get_scratch(font, _rl_msg_len * 6); @@ -3664,7 +3663,10 @@ static void d3d9_cg_set_viewport(void *data, int y = 0; struct video_viewport vp; - video_driver_get_size(&width, &height); + /* Width/height parameters are intentionally overwritten here: + * the caller's values are not used (pre-existing behaviour). */ + width = d3d->vp.full_width; + height = d3d->vp.full_height; vp.full_width = width; vp.full_height = height; @@ -3712,7 +3714,6 @@ static void d3d9_cg_set_viewport(void *data, static bool d3d9_cg_initialize(d3d9_video_t *d3d, const video_info_t *info) { - unsigned width, height; bool ret = true; settings_t *settings = config_get_ptr(); @@ -3747,9 +3748,10 @@ static bool d3d9_cg_initialize(d3d9_video_t *d3d, const video_info_t *info) return false; } - video_driver_get_size(&width, &height); + /* d3d->vp.full_* was written by the caller (d3d9_cg_init_internal + * has already called set_size at this point). */ d3d9_cg_set_viewport(d3d, - width, height, false, true); + d3d->vp.full_width, d3d->vp.full_height, false, true); font_driver_init_osd(d3d, info, false, @@ -3974,6 +3976,8 @@ static bool d3d9_cg_init_internal(d3d9_video_t *d3d, unsigned new_width = info->fullscreen ? full_x : info->width; unsigned new_height = info->fullscreen ? full_y : info->height; video_driver_set_size(new_width, new_height); + d3d->vp.full_width = new_width; + d3d->vp.full_height = new_height; #ifdef HAVE_WINDOW /* Use new_width / new_height directly rather than reading @@ -4832,6 +4836,8 @@ static void d3d9_cg_set_resize(d3d9_video_t *d3d, d3d->video_info.width = new_width; d3d->video_info.height = new_height; video_driver_set_size(new_width, new_height); + d3d->vp.full_width = new_width; + d3d->vp.full_height = new_height; } static bool d3d9_cg_alive(void *data) @@ -4843,8 +4849,11 @@ static bool d3d9_cg_alive(void *data) bool resize = false; d3d9_video_t *d3d = (d3d9_video_t*)data; - /* Needed because some context drivers don't track their sizes */ - video_driver_get_size(&temp_width, &temp_height); + /* Read from local bookkeeping rather than video_st (which would + * acquire context_lock + display_lock). d3d->vp.full_* is + * written at every set_size call site in this driver. */ + temp_width = d3d->vp.full_width; + temp_height = d3d->vp.full_height; win32_check_window(NULL, &quit, &resize, &temp_width, &temp_height); @@ -4862,7 +4871,11 @@ static bool d3d9_cg_alive(void *data) if ( temp_width != 0 && temp_height != 0) + { video_driver_set_size(temp_width, temp_height); + d3d->vp.full_width = temp_width; + d3d->vp.full_height = temp_height; + } return ret; } @@ -4890,18 +4903,15 @@ void d3d9_cg_set_rotation(void *data, unsigned rot) void d3d9_cg_viewport_info(void *data, struct video_viewport *vp) { - unsigned width, height; d3d9_video_t *d3d = (d3d9_video_t*)data; - video_driver_get_size(&width, &height); - vp->x = d3d->out_vp.X; vp->y = d3d->out_vp.Y; vp->width = d3d->out_vp.Width; vp->height = d3d->out_vp.Height; - vp->full_width = width; - vp->full_height = height; + vp->full_width = d3d->vp.full_width; + vp->full_height = d3d->vp.full_height; } static INLINE bool d3d9_cg_device_get_render_target_data( @@ -4915,15 +4925,14 @@ static INLINE bool d3d9_cg_device_get_render_target_data( bool d3d9_cg_read_viewport(void *data, uint8_t *buffer, bool is_idle) { - unsigned width, height; D3DLOCKED_RECT rect; LPDIRECT3DSURFACE9 target = NULL; LPDIRECT3DSURFACE9 dest = NULL; bool ret = true; d3d9_video_t *d3d = (d3d9_video_t*)data; LPDIRECT3DDEVICE9 d3dr = d3d->dev; - - video_driver_get_size(&width, &height); + unsigned width = d3d->vp.full_width; + unsigned height = d3d->vp.full_height; if ( !SUCCEEDED(IDirect3DDevice9_GetRenderTarget(d3dr, 0, (LPDIRECT3DSURFACE9*)&target)) diff --git a/gfx/drivers/d3d9hlsl.c b/gfx/drivers/d3d9hlsl.c index e53d0f8dc4e4..e92094f9361b 100644 --- a/gfx/drivers/d3d9hlsl.c +++ b/gfx/drivers/d3d9hlsl.c @@ -1606,7 +1606,8 @@ static void d3d9_font_render_msg( if (!d3d) return; - video_driver_get_size(&width, &height); + width = d3d->vp.full_width; + height = d3d->vp.full_height; if (!width || !height) return; @@ -6901,7 +6902,10 @@ static void d3d9_hlsl_set_viewport(void *data, int y = 0; struct video_viewport vp; - video_driver_get_size(&width, &height); + /* Width/height parameters are intentionally overwritten here: + * the caller's values are not used (pre-existing behaviour). */ + width = d3d->vp.full_width; + height = d3d->vp.full_height; vp.full_width = width; vp.full_height = height; @@ -6963,7 +6967,6 @@ static void d3d9_hlsl_set_osd_msg(void *data, static bool d3d9_hlsl_initialize( d3d9_video_t *d3d, const video_info_t *info) { - unsigned width, height; bool ret = true; if (!d3d->d3d9) @@ -6998,9 +7001,10 @@ static bool d3d9_hlsl_initialize( return false; } - video_driver_get_size(&width, &height); + /* d3d->vp.full_* was written by the caller (d3d9_hlsl_init_internal + * has already called set_size at this point). */ d3d9_hlsl_set_viewport(d3d, - width, height, false, true); + d3d->vp.full_width, d3d->vp.full_height, false, true); font_driver_init_osd(d3d, info, false, @@ -7200,6 +7204,8 @@ static bool d3d9_hlsl_init_internal(d3d9_video_t *d3d, unsigned new_width = info->fullscreen ? full_x : info->width; unsigned new_height = info->fullscreen ? full_y : info->height; video_driver_set_size(new_width, new_height); + d3d->vp.full_width = new_width; + d3d->vp.full_height = new_height; #ifdef HAVE_WINDOW /* Use new_width / new_height directly rather than reading @@ -7285,18 +7291,15 @@ static void *d3d9_hlsl_init(const video_info_t *info, static void d3d9_hlsl_viewport_info(void *data, struct video_viewport *vp) { - unsigned width, height; d3d9_video_t *d3d = (d3d9_video_t*)data; - video_driver_get_size(&width, &height); - vp->x = d3d->out_vp.X; vp->y = d3d->out_vp.Y; vp->width = d3d->out_vp.Width; vp->height = d3d->out_vp.Height; - vp->full_width = width; - vp->full_height = height; + vp->full_width = d3d->vp.full_width; + vp->full_height = d3d->vp.full_height; } #ifdef HAVE_OVERLAY @@ -8173,6 +8176,8 @@ static void d3d9_hlsl_set_resize(d3d9_video_t *d3d, d3d->video_info.width = new_width; d3d->video_info.height = new_height; video_driver_set_size(new_width, new_height); + d3d->vp.full_width = new_width; + d3d->vp.full_height = new_height; } static bool d3d9_hlsl_alive(void *data) @@ -8184,8 +8189,11 @@ static bool d3d9_hlsl_alive(void *data) bool resize = false; d3d9_video_t *d3d = (d3d9_video_t*)data; - /* Needed because some context drivers don't track their sizes */ - video_driver_get_size(&temp_width, &temp_height); + /* Read from local bookkeeping rather than video_st (which would + * acquire context_lock + display_lock). d3d->vp.full_* is + * written at every set_size call site in this driver. */ + temp_width = d3d->vp.full_width; + temp_height = d3d->vp.full_height; win32_check_window(NULL, &quit, &resize, &temp_width, &temp_height); @@ -8203,7 +8211,11 @@ static bool d3d9_hlsl_alive(void *data) if ( temp_width != 0 && temp_height != 0) + { video_driver_set_size(temp_width, temp_height); + d3d->vp.full_width = temp_width; + d3d->vp.full_height = temp_height; + } return ret; } @@ -8264,15 +8276,14 @@ static INLINE bool d3d9_hlsl_device_get_render_target_data( static bool d3d9_hlsl_read_viewport(void *data, uint8_t *buffer, bool is_idle) { - unsigned width, height; D3DLOCKED_RECT rect; LPDIRECT3DSURFACE9 target = NULL; LPDIRECT3DSURFACE9 dest = NULL; bool ret = true; d3d9_video_t *d3d = (d3d9_video_t*)data; LPDIRECT3DDEVICE9 d3dr = d3d->dev; - - video_driver_get_size(&width, &height); + unsigned width = d3d->vp.full_width; + unsigned height = d3d->vp.full_height; if ( !(d3dr && From 5f38f4ac728505140070859af5fb0c127b789f23 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 01:10:07 +0200 Subject: [PATCH 05/14] Further round of kill redundant video_driver_get_size calls --- gfx/common/gdi_defines.h | 5 +++++ gfx/drivers/gdi_gfx.c | 14 ++++++++++++-- gfx/drivers/gl1.c | 38 +++++++++++++++++++++----------------- gfx/drivers/vg.c | 2 -- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/gfx/common/gdi_defines.h b/gfx/common/gdi_defines.h index 18f636ff5f45..9bbaa6d29e24 100644 --- a/gfx/common/gdi_defines.h +++ b/gfx/common/gdi_defines.h @@ -41,6 +41,11 @@ typedef struct gdi unsigned video_height; unsigned screen_width; unsigned screen_height; + /* Surface (window) size last published via video_driver_set_size, + * tracked here so gdi_alive can read it without locking. Distinct + * from video_width / video_height which is the core's frame size. */ + unsigned full_width; + unsigned full_height; unsigned menu_width; unsigned menu_height; diff --git a/gfx/drivers/gdi_gfx.c b/gfx/drivers/gdi_gfx.c index f0387b070a8d..d6bfce0b91dc 100644 --- a/gfx/drivers/gdi_gfx.c +++ b/gfx/drivers/gdi_gfx.c @@ -573,6 +573,8 @@ static void *gdi_init(const video_info_t *video, video_driver_set_size(temp_width, temp_height); else video_driver_get_size(&temp_width, &temp_height); + gdi->full_width = temp_width; + gdi->full_height = temp_height; RARCH_LOG("[GDI] Using resolution %ux%u.\n", temp_width, temp_height); @@ -793,9 +795,13 @@ static bool gdi_alive(void *data) bool quit = false; bool resize = false; bool ret = false; + gdi_t *gdi = (gdi_t*)data; - /* Needed because some context drivers don't track their sizes */ - video_driver_get_size(&temp_width, &temp_height); + /* Read from local bookkeeping rather than video_st (which would + * acquire context_lock + display_lock). gdi->full_{width,height} + * is written at every set_size call site in this driver. */ + temp_width = gdi->full_width; + temp_height = gdi->full_height; win32_check_window(NULL, &quit, &resize, &temp_width, &temp_height); @@ -803,7 +809,11 @@ static bool gdi_alive(void *data) ret = !quit; if (temp_width != 0 && temp_height != 0) + { video_driver_set_size(temp_width, temp_height); + gdi->full_width = temp_width; + gdi->full_height = temp_height; + } return ret; } diff --git a/gfx/drivers/gl1.c b/gfx/drivers/gl1.c index 1a88590f4350..ff90323c4b9f 100644 --- a/gfx/drivers/gl1.c +++ b/gfx/drivers/gl1.c @@ -1287,6 +1287,8 @@ static void *gl1_init(const video_info_t *video, video_driver_set_size(temp_width, temp_height); else video_driver_get_size(&temp_width, &temp_height); + gl1->vp.full_width = temp_width; + gl1->vp.full_height = temp_height; RARCH_LOG("[GL1] Using resolution %ux%u.\n", temp_width, temp_height); @@ -2008,8 +2010,11 @@ static bool gl1_alive(void *data) bool ret = false; gl1_t *gl1 = (gl1_t*)data; - /* Needed because some context drivers don't track their sizes */ - video_driver_get_size(&temp_width, &temp_height); + /* Read from local bookkeeping rather than video_st (which would + * acquire context_lock + display_lock). gl1->vp.full_* is + * written at every set_size call site in this driver. */ + temp_width = gl1->vp.full_width; + temp_height = gl1->vp.full_height; gl1->ctx_driver->check_window(gl1->ctx_data, &quit, &resize, &temp_width, &temp_height); @@ -2020,7 +2025,11 @@ static bool gl1_alive(void *data) ret = !quit; if (temp_width != 0 && temp_height != 0) + { video_driver_set_size(temp_width, temp_height); + gl1->vp.full_width = temp_width; + gl1->vp.full_height = temp_height; + } return ret; } @@ -2098,19 +2107,17 @@ static void gl1_set_rotation(void *data, static void gl1_viewport_info(void *data, struct video_viewport *vp) { - unsigned width, height; unsigned top_y, top_dist; gl1_t *gl1 = (gl1_t*)data; - video_driver_get_size(&width, &height); - + /* gl1->vp carries full_width/full_height (written at every + * set_size call site), so the struct copy populates them + * directly without a video_driver_get_size round-trip. */ *vp = gl1->vp; - vp->full_width = width; - vp->full_height = height; /* Adjust as GL viewport is bottom-up. */ top_y = vp->y + vp->height; - top_dist = height - top_y; + top_dist = vp->full_height - top_y; vp->y = top_dist; } @@ -2135,16 +2142,13 @@ static bool gl1_read_viewport(void *data, uint8_t *buffer, bool is_idle) /* Clamp to the region glReadPixels actually wrote. * gl1_readback() clamps its read to * min(vp.{w,h}, video_{width,height}), where video_{width,height} - * come from video_info and ultimately video_driver_get_size(). + * come from the surface size kept in gl1->vp.full_*. * gl1->video_{width,height} holds the core's frame size, not the - * window size, so we re-query here to match. Not a hot path. */ - unsigned vd_w = 0; - unsigned vd_h = 0; - unsigned rb_w = 0; - unsigned rb_h = 0; - video_driver_get_size(&vd_w, &vd_h); - rb_w = (gl1->vp.width > vd_w) ? vd_w : gl1->vp.width; - rb_h = (gl1->vp.height > vd_h) ? vd_h : gl1->vp.height; + * window size, so we read the surface size from gl1->vp.full_*. */ + unsigned vd_w = gl1->vp.full_width; + unsigned vd_h = gl1->vp.full_height; + unsigned rb_w = (gl1->vp.width > vd_w) ? vd_w : gl1->vp.width; + unsigned rb_h = (gl1->vp.height > vd_h) ? vd_h : gl1->vp.height; video_frame_convert_rgba_to_bgr( (const void*)gl1->readback_buffer_screenshot, buffer, diff --git a/gfx/drivers/vg.c b/gfx/drivers/vg.c index aa8ee5fdcd5d..99cffe86db04 100644 --- a/gfx/drivers/vg.c +++ b/gfx/drivers/vg.c @@ -175,8 +175,6 @@ static void *vg_init(const video_info_t *video, win_width, win_height, video->fullscreen)) goto error; - video_driver_get_size(&temp_width, &temp_height); - temp_width = 0; temp_height = 0; mode_width = 0; From 52d95fbf9832329cc8aeba293dd4c5624e79df69 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 01:20:20 +0200 Subject: [PATCH 06/14] Instead of direct calls to video_driver_set_aspect_ratio, go through command_event instead --- menu/menu_setting.c | 2 +- runloop.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 690fa44fcbf7..e709cec8bea7 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -8932,7 +8932,7 @@ static void general_write_handler(rarch_setting_t *setting) aspectratio_lut[ASPECT_RATIO_CUSTOM].value = (float)custom_vp->width / custom_vp->height; /* Update Aspect Ratio (only useful for 1:1 PAR) */ - video_driver_set_aspect_ratio(); + command_event(CMD_EVENT_VIDEO_SET_ASPECT_RATIO, NULL); } } break; diff --git a/runloop.c b/runloop.c index f4970e1ffed7..c8078db282fe 100644 --- a/runloop.c +++ b/runloop.c @@ -2449,7 +2449,7 @@ bool runloop_environment_cb(unsigned cmd, void *data) RARCH_LOG("[Environ] Setting audio latency to %u ms.\n", audio_latency_new); command_event(CMD_EVENT_REINIT, &reinit_flags); - video_driver_set_aspect_ratio(); + command_event(CMD_EVENT_VIDEO_SET_ASPECT_RATIO, NULL); /* Cannot continue recording with different * parameters. @@ -2688,7 +2688,7 @@ bool runloop_environment_cb(unsigned cmd, void *data) command_event(CMD_EVENT_REINIT, &reinit_flags); if (no_video_reinit) - video_driver_set_aspect_ratio(); + command_event(CMD_EVENT_VIDEO_SET_ASPECT_RATIO, NULL); if (video_switch_refresh_rate) video_display_server_set_refresh_rate(refresh_rate); @@ -2919,7 +2919,7 @@ bool runloop_environment_cb(unsigned cmd, void *data) /* Forces recomputation of aspect ratios if * using core-dependent aspect ratios. */ - video_driver_set_aspect_ratio(); + command_event(CMD_EVENT_VIDEO_SET_ASPECT_RATIO, NULL); /* Ignore frame delay target temporarily */ if (video_frame_delay_auto) From d483ed098b2ca1a24244e6f842fa59a2a9d4dd8c Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 01:27:03 +0200 Subject: [PATCH 07/14] menu/drivers: drop video_driver_get_size in xmb/ozone/materialui Substitute the per-handle cached size for video_driver_get_size across the three main menu drivers. All three handles now expose last_width / last_height fields populated every render frame, so input-time and layout-time code paths can read the size without acquiring video_st's context_lock + display_lock. ozone (menu/drivers/ozone.c) ozone_handle_t already carries last_width / last_height, written every frame in ozone_render whenever the size differs from the cached value. Six get_size sites converted: ozone_list_cache (after select / list change) ozone_sidebar_goto (sidebar nav) ozone_update_scroll (scroll position update) ozone_compute_entries_position (entries layout recompute) ozone_draw_entries (per-frame, render path) ozone_pointer_up (pointer release gesture) ozone_draw_entries also receives video_width / video_height as parameters from its render-path caller; the local video_info_width / video_info_height that this commit substitutes remain a separate set of variables (pre-existing). Both end up holding the same value at runtime. materialui (menu/drivers/materialui.c) materialui_handle_t already carries last_width / last_height, written every frame in materialui_render. Three sites converted: materialui_get_scroll (called from input-handling paths) materialui_pointer_down (touch-down: scrollbar drag check) materialui_pointer_up (touch-release: gesture dispatch) The substitution in materialui_get_scroll moves the read past the existing null check on mui. In materialui_pointer_up the read sits at the same line as the old get_size call so the early-return paths still bail before any size lookup. xmb (menu/drivers/xmb.c) Unlike the other two, xmb_handle_t did not previously carry last_width / last_height. Add them, and write them at two points: xmb_init -- one-shot, populated from the get_size already present in init xmb_frame -- every render call, sourced from video_info->{width,height} Six get_size sites then converted: xmb_selection_pointer_changed (cursor movement) xmb_list_open_new (list expansion) xmb_list_switch_new (tab / category switch) xmb_layout (layout recompute) xmb_list_cache (after a list change) xmb_pointer_up (touch-release gesture) The xmb_layout call site is reached through xmb_context_reset_ internal, which itself runs after init has primed the cache, so the field is always valid when read. The xmb_frame write is two unsigned stores after a null-check on xmb that already guards the rest of the function. Across all three drivers the init-time get_size is preserved by design: at the moment it runs, last_width / last_height are either zero (xmb, ozone freshly calloc'd) or being primed for the first time (materialui). That get is the only remaining get_size call in each of these files. Per-call savings: video_driver_get_size acquires context_lock plus, when threaded video is active, display_lock. These reads now go directly to handle fields with no synchronization. Most of the converted paths fire on user input rather than per-frame, but ozone_draw_entries and xmb_layout sit on the render / layout hot paths and do benefit from frame-rate scale savings. --- menu/drivers/materialui.c | 22 ++++++++++++--------- menu/drivers/ozone.c | 26 +++++++++---------------- menu/drivers/xmb.c | 40 ++++++++++++++++++++++++++++----------- 3 files changed, 51 insertions(+), 37 deletions(-) diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c index 1aa731ef3f7e..e4e5a31def19 100644 --- a/menu/drivers/materialui.c +++ b/menu/drivers/materialui.c @@ -3353,22 +3353,23 @@ static float materialui_get_scroll(materialui_handle_t *mui, gfx_display_t *p_disp) { size_t i; + unsigned height; materialui_node_t *node = NULL; struct menu_state *menu_st = menu_state_get_ptr(); menu_list_t *menu_list = menu_st->entries.list; file_list_t *list = MENU_LIST_GET_SELECTION(menu_list, 0); size_t selection = menu_st->selection_ptr; unsigned header_height = p_disp->header_height; - unsigned width = 0; - unsigned height = 0; float view_centre = 0.0f; float selection_centre = 0.0f; if (!mui || !list || !list->size) return 0; - /* Get current window size */ - video_driver_get_size(&width, &height); + /* Read cached size from mui rather than locking video_st via + * video_driver_get_size: mui->last_{width,height} is updated + * every frame in materialui_render. */ + height = mui->last_height; /* Get the vertical midpoint of the actual * list view - i.e. account for header + @@ -10789,14 +10790,12 @@ static int materialui_pointer_down(void *userdata, if ( (mui->flags & MUI_FLAG_SCROLLBAR_ACTIVE) && (!(mui->flags & MUI_FLAG_SHOW_FULLSCREEN_THUMBNAILS))) { - unsigned width; - unsigned height; int drag_margin_horz; int drag_margin_vert; gfx_display_t *p_disp = disp_get_ptr(); unsigned header_height = p_disp->header_height; - - video_driver_get_size(&width, &height); + unsigned width = mui->last_width; + unsigned height = mui->last_height; /* Check whether pointer down event is within * vertical list region */ @@ -11030,6 +11029,10 @@ static int materialui_pointer_up(void *userdata, if (!mui) return -1; + /* Read cached size from mui rather than locking video_st via + * video_driver_get_size: mui->last_{width,height} is updated + * every frame in materialui_render. */ + /* All input is ignored if user was previously * dragging the scrollbar */ if (mui->flags & MUI_FLAG_SCROLLBAR_DRAGGED) @@ -11060,7 +11063,8 @@ static int materialui_pointer_up(void *userdata, return 0; } - video_driver_get_size(&width, &height); + width = mui->last_width; + height = mui->last_height; switch (gesture) { diff --git a/menu/drivers/ozone.c b/menu/drivers/ozone.c index bdcb1b443c18..916664fe4645 100644 --- a/menu/drivers/ozone.c +++ b/menu/drivers/ozone.c @@ -4751,7 +4751,7 @@ static void ozone_list_cache(void *data, ozone->flags &= ~OZONE_FLAG_IS_PLAYLIST_OLD; /* Deep copy visible elements */ - video_driver_get_size(NULL, &video_info_height); + video_info_height = ozone->last_height; y = ozone->dimensions.header_height + ozone->dimensions.entry_padding_vertical; entries_end = MENU_LIST_GET_SELECTION(menu_list, 0)->size; selection_buf = MENU_LIST_GET_SELECTION(menu_list, 0); @@ -4860,14 +4860,12 @@ static void ozone_sidebar_goto(ozone_handle_t *ozone, size_t new_selection) #endif }; - unsigned video_info_height; + unsigned video_info_height = ozone->last_height; struct gfx_animation_ctx_entry entry; uintptr_t tag = (uintptr_t)ozone; struct menu_state *menu_st = menu_state_get_ptr(); menu_input_t *menu_input = &menu_st->input_state; - video_driver_get_size(NULL, &video_info_height); - if (ozone->categories_selection_ptr != new_selection) { ozone->categories_active_idx_old = ozone->categories_selection_ptr; @@ -5605,7 +5603,7 @@ static void ozone_content_metadata_line( static void ozone_update_scroll(ozone_handle_t *ozone, bool allow_animation, ozone_node_t *node) { - unsigned video_info_height; + unsigned video_info_height = ozone->last_height; gfx_animation_ctx_entry_t entry; float new_scroll = 0, entries_middle; float bottom_boundary, current_selection_middle_onscreen; @@ -5615,8 +5613,6 @@ static void ozone_update_scroll(ozone_handle_t *ozone, file_list_t *selection_buf = MENU_LIST_GET_SELECTION(menu_list, 0); uintptr_t tag = (uintptr_t)selection_buf; - video_driver_get_size(NULL, &video_info_height); - if (!node) return; @@ -5702,8 +5698,8 @@ static void ozone_compute_entries_position(ozone_handle_t *ozone, { size_t i; /* Compute entries height and adjust scrolling if needed */ - unsigned video_info_height; - unsigned video_info_width; + unsigned video_info_height = ozone->last_height; + unsigned video_info_width = ozone->last_width; struct menu_state *menu_st = menu_state_get_ptr(); menu_list_t *menu_list = menu_st->entries.list; file_list_t *selection_buf = NULL; @@ -5729,8 +5725,6 @@ static void ozone_compute_entries_position(ozone_handle_t *ozone, if (!selection_buf->size) return; - video_driver_get_size(&video_info_width, &video_info_height); - if (menu_show_sublabels) sublabel_max_width = ozone_get_sublabel_max_width(ozone, video_info_width, entry_padding); @@ -5842,7 +5836,8 @@ static void ozone_draw_entries( size_t i; uint32_t alpha_uint32; float bottom_boundary; - unsigned video_info_height, video_info_width; + unsigned video_info_height = ozone->last_height; + unsigned video_info_width = ozone->last_width; float last_border_alpha = -1.0f; bool menu_show_sublabels = settings->bools.menu_show_sublabels; bool use_smooth_ticker = settings->bools.menu_ticker_smooth; @@ -5874,8 +5869,6 @@ static void ozone_draw_entries( float invert = (ozone->flags & OZONE_FLAG_FADE_DIRECTION) ? -1 : 1; float alpha_anim = old_list ? alpha : 1.0f - alpha; - video_driver_get_size(&video_info_width, &video_info_height); - bottom_boundary = video_info_height - ozone->dimensions.header_height - ozone->dimensions.footer_height; @@ -13304,8 +13297,9 @@ static int ozone_pointer_up(void *userdata, menu_entry_t *entry, unsigned action) { - unsigned int width, height; ozone_handle_t *ozone = (ozone_handle_t*)userdata; + unsigned int width = ozone->last_width; + unsigned int height = ozone->last_height; struct menu_state *menu_st = menu_state_get_ptr(); menu_input_t *menu_input = &menu_st->input_state; menu_list_t *menu_list = menu_st->entries.list; @@ -13335,8 +13329,6 @@ static int ozone_pointer_up(void *userdata, return 0; } - video_driver_get_size(&width, &height); - switch (gesture) { case MENU_INPUT_GESTURE_TAP: diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index ff34f03b4873..66c9cc4eeb53 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -519,6 +519,14 @@ typedef struct xmb_handle * Prevents use-after-free on textures/fonts during driver * reinit under threaded video. */ uint32_t context_generation; + + /* Surface size last seen by xmb_frame. Updated every frame + * from video_info->{width,height} so non-render code paths + * (selection_pointer_changed, list_open_new, list_switch_new, + * list_cache, pointer_up, layout) can read the size without + * locking video_st via video_driver_get_size. */ + unsigned last_width; + unsigned last_height; } xmb_handle_t; /* Constant color templates — safe to share across threads. @@ -1896,7 +1904,7 @@ static void xmb_selection_pointer_changed( threshold = xmb->icon_size * 10; menu_st->entries.begin = num; - video_driver_get_size(NULL, &height); + height = xmb->last_height; /* On cursor movement within a playlist, invalidate any in-flight * icon thumbnail requests (they're for the previous cursor position @@ -2082,14 +2090,13 @@ static void xmb_list_open_new(xmb_handle_t *xmb, bool savestate_thumbnail, file_list_t *list, int dir, size_t current) { - unsigned i, height; + unsigned i; + unsigned height = xmb->last_height; size_t skip = 0; int threshold = xmb->icon_size * 10; size_t end = list ? list->size : 0; struct menu_state *menu_st = menu_state_get_ptr(); - video_driver_get_size(NULL, &height); - for (i = 0; i < end; i++) { float ia; @@ -2270,7 +2277,8 @@ static void xmb_animation_list_alpha(xmb_handle_t *xmb, bool fade_in) static void xmb_list_switch_new(xmb_handle_t *xmb, file_list_t *list, int dir, size_t current) { - unsigned i, height; + unsigned i; + unsigned height = xmb->last_height; unsigned last = 0; unsigned first = 0; size_t end = 0; @@ -2281,7 +2289,6 @@ static void xmb_list_switch_new(xmb_handle_t *xmb, if (end > 0) last = (unsigned)(end - 1); - video_driver_get_size(NULL, &height); xmb_calculate_visible_range(xmb, height, end, (unsigned)current, &first, &last); for (i = 0; i < end; i++) @@ -6470,7 +6477,9 @@ static void xmb_init_scale_mod(float *scale_mod, float scale_value) static void xmb_layout(xmb_handle_t *xmb) { - unsigned width, height, i; + unsigned i; + unsigned width = xmb->last_width; + unsigned height = xmb->last_height; struct menu_state *menu_st = menu_state_get_ptr(); menu_list_t *menu_list = menu_st->entries.list; file_list_t *selection_buf = MENU_LIST_GET_SELECTION(menu_list, 0); @@ -6478,7 +6487,6 @@ static void xmb_layout(xmb_handle_t *xmb) unsigned current = (unsigned)selection; unsigned end = (unsigned)MENU_LIST_GET_SELECTION(menu_list, 0)->size; - video_driver_get_size(&width, &height); xmb_init_scale_mod(xmb->scale_mod, config_get_ptr()->floats.menu_scale_factor * 100.0f); if (xmb->use_ps3_layout) @@ -8233,6 +8241,11 @@ static void xmb_frame(void *data, video_frame_info_t *video_info) if (!xmb) return; + /* Cache the per-frame size on the handle so non-render paths + * can read it without locking video_st. */ + xmb->last_width = video_width; + xmb->last_height = video_height; + /* Snapshot context generation — if xmb_context_destroy() * runs on the main thread while we are mid-render on the * video thread, the generation will change and we must @@ -9484,6 +9497,11 @@ static void *xmb_init(void **userdata, bool video_is_threaded) return NULL; } + /* Initialise last_{width,height} from the snapshot taken + * above; xmb_frame will refresh these every render. */ + xmb->last_width = width; + xmb->last_height = height; + xmb_init_scale_mod(xmb->scale_mod, settings->floats.menu_scale_factor * 100.0f); *userdata = xmb; @@ -9760,8 +9778,7 @@ static void xmb_list_cache(void *data, enum menu_list_type type, if (xmb->allow_horizontal_animation) { unsigned first = 0, last = 0; - unsigned height = 0; - video_driver_get_size(NULL, &height); + unsigned height = xmb->last_height; /* FIXME: this shouldn't be happening at all */ if (selection >= selection_buf->size) @@ -10188,7 +10205,8 @@ static int xmb_pointer_up(void *userdata, return 0; } - video_driver_get_size(&width, &height); + width = xmb->last_width; + height = xmb->last_height; margin_top = (int16_t)xmb->margins_screen_top; margin_left = (int16_t)xmb->margins_screen_left; margin_right = (int16_t)((float)width - xmb->margins_screen_left); From 1ee88d08de84dde57d2ac33e4b68ece504ca5dd2 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 01:56:08 +0200 Subject: [PATCH 08/14] gfx/drivers: drop dead prim_to_d3d helpers in d3d8/d3d9_cg/d3d9_hlsl Each of the three D3D fixed-pipeline drivers carries an identical gfx_display_prim_to_d3d{8,9_cg,9_hlsl}_enum helper plus a caller- side switch on draw->prim_type. Both are dead. Every gfx_display_ctx_draw_t in the codebase sets prim_type to GFX_DISPLAY_PRIM_TRIANGLESTRIP before invoking dispctx->draw. All 19 "prim_type =" assignments under gfx/, menu/, and gfx/widgets/ assign TRIANGLESTRIP -- never TRIANGLES, never NONE. Every local declaration of the draw struct assigns prim_type before the draw call (swept each one). At runtime the helper switch always hits the TRIANGLESTRIP arm and the caller's per-call branch always takes the tristrip path. The dead non-tristrip branch was also buggy: it mapped TRIANGLES to D3DPT_TRIANGLESTRIP (wrong primitive -- gl1/2/3 correctly map it to GL_TRIANGLES) and used count = vertices (wrong formula for DrawPrimitive, which takes PrimitiveCount; the right formula is vertices/3). And the helpers' TODO/FIXME default returned zero, which is not a legal D3DPRIMITIVETYPE value (the enum starts at D3DPT_POINTLIST = 1) -- a debug runtime would reject the call. Inline D3DPT_TRIANGLESTRIP at the DrawPrimitive site, drop the helpers and the dead caller branches, drop the now-unused D3DPRIMITIVETYPE locals. Document at each call site that this assumes TRIANGLESTRIP and would need to grow back into a switch if a future non-tristrip caller appears. While here, harden d3d9_cg and d3d9_hlsl against vertices < 3. Both used count = vertices - 2 unconditionally, which on an unsigned subtraction with vertices < 2 wraps to a huge primitive count and walks off the vertex buffer in the GPU. d3d8 already had this guard; the d3d9 pair did not. No caller passes < 3 vertices today, but the same "no caller does this" reasoning is what kept the dead switch alive, so add the guard symmetrically. Net -38 lines. No behavioural change for any existing caller. --- gfx/drivers/d3d8.c | 50 +++++++++++++----------------------------- gfx/drivers/d3d9cg.c | 37 ++++++++++++------------------- gfx/drivers/d3d9hlsl.c | 37 ++++++++++++------------------- 3 files changed, 43 insertions(+), 81 deletions(-) diff --git a/gfx/drivers/d3d8.c b/gfx/drivers/d3d8.c index 981d16ecb225..c21d08e7a058 100644 --- a/gfx/drivers/d3d8.c +++ b/gfx/drivers/d3d8.c @@ -657,23 +657,6 @@ static void *gfx_display_d3d8_get_default_mvp(void *data) return &id; } -static INT32 gfx_display_prim_to_d3d8_enum( - enum gfx_display_prim_type prim_type) -{ - switch (prim_type) - { - case GFX_DISPLAY_PRIM_TRIANGLES: - case GFX_DISPLAY_PRIM_TRIANGLESTRIP: - return D3DPT_TRIANGLESTRIP; - case GFX_DISPLAY_PRIM_NONE: - default: - break; - } - - /* TODO/FIXME - hack */ - return 0; -} - static void gfx_display_d3d8_blend_begin(void *data) { d3d8_video_t *d3d = (d3d8_video_t*)data; @@ -710,7 +693,6 @@ static void gfx_display_d3d8_draw(gfx_display_ctx_draw_t *draw, math_matrix_4x4 mop, m1, m2; LPDIRECT3DVERTEXBUFFER8 vbo; LPDIRECT3DDEVICE8 dev; - D3DPRIMITIVETYPE type; unsigned start = 0; unsigned count = 0; d3d8_video_t *d3d = (d3d8_video_t*)data; @@ -1005,32 +987,30 @@ static void gfx_display_d3d8_draw(gfx_display_ctx_draw_t *draw, IDirect3DDevice8_SetTextureStageState(dev, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - type = gfx_display_prim_to_d3d8_enum(draw->prim_type); start = d3d->menu_display.offset; - /* For tristrips, the primitive count is vertices - 2. Guard - * against vertices < 3 which would underflow the unsigned + /* Every caller in the codebase sets draw->prim_type to + * GFX_DISPLAY_PRIM_TRIANGLESTRIP, and the draw->coords vertices + * are laid out as a strip. Hard-code D3DPT_TRIANGLESTRIP and the + * (vertices - 2) primitive-count formula here. If a future + * caller passes TRIANGLES or another primitive type, this site + * will need to grow back into a switch -- but with no current + * non-tristrip caller, the dead branch was just buggy: it mapped + * TRIANGLES to D3DPT_TRIANGLESTRIP (the wrong type) and used + * count = vertices (the wrong count formula for D3D, which + * expects PrimitiveCount, not vertex count). + * + * Guard against vertices < 3 which would underflow the unsigned * subtraction and pass a huge primitive count to the GPU. */ - if (draw->prim_type == GFX_DISPLAY_PRIM_TRIANGLESTRIP) - { - if (draw->coords->vertices < 3) - { - d3d->menu_display.offset += draw->coords->vertices; - return; - } - count = draw->coords->vertices - 2; - } - else - count = draw->coords->vertices; - - if (count == 0) + if (draw->coords->vertices < 3) { d3d->menu_display.offset += draw->coords->vertices; return; } + count = draw->coords->vertices - 2; IDirect3DDevice8_BeginScene(dev); - IDirect3DDevice8_DrawPrimitive(dev, type, start, count); + IDirect3DDevice8_DrawPrimitive(dev, D3DPT_TRIANGLESTRIP, start, count); IDirect3DDevice8_EndScene(dev); d3d->menu_display.offset += draw->coords->vertices; diff --git a/gfx/drivers/d3d9cg.c b/gfx/drivers/d3d9cg.c index 013bd5635382..15ec8de43136 100644 --- a/gfx/drivers/d3d9cg.c +++ b/gfx/drivers/d3d9cg.c @@ -476,23 +476,6 @@ static const float d3d9_cg_tex_coords[8] = { 1, 0 }; -static INT32 gfx_display_prim_to_d3d9_cg_enum( - enum gfx_display_prim_type prim_type) -{ - switch (prim_type) - { - case GFX_DISPLAY_PRIM_TRIANGLES: - case GFX_DISPLAY_PRIM_TRIANGLESTRIP: - return D3DPT_TRIANGLESTRIP; - case GFX_DISPLAY_PRIM_NONE: - default: - break; - } - - /* TODO/FIXME - hack */ - return 0; -} - static void gfx_display_d3d9_cg_blend_begin(void *data) { d3d9_video_t *d3d = (d3d9_video_t*)data; @@ -672,7 +655,6 @@ static void gfx_display_d3d9_cg_draw(gfx_display_ctx_draw_t *draw, { unsigned i; LPDIRECT3DDEVICE9 dev; - D3DPRIMITIVETYPE type; bool has_vertex_data; unsigned start = 0; unsigned count = 0; @@ -1038,13 +1020,22 @@ static void gfx_display_d3d9_cg_draw(gfx_display_ctx_draw_t *draw, gfx_display_d3d9_cg_bind_texture(draw, d3d); - type = (D3DPRIMITIVETYPE)gfx_display_prim_to_d3d9_cg_enum(draw->prim_type); start = d3d->menu_display.offset; - count = draw->coords->vertices - - ((draw->prim_type == GFX_DISPLAY_PRIM_TRIANGLESTRIP) - ? 2 : 0); - IDirect3DDevice9_DrawPrimitive(dev, type, start, count); + /* Every caller in the codebase sets draw->prim_type to + * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so the per-call switch on the + * primitive type that used to live here was dead. See the + * matching comment in d3d8.c's gfx_display_d3d8_draw for why we + * also harden against vertices < 3 (the tristrip count formula + * vertices - 2 underflows the unsigned subtraction otherwise). */ + if (draw->coords->vertices < 3) + { + d3d->menu_display.offset += draw->coords->vertices; + return; + } + count = draw->coords->vertices - 2; + + IDirect3DDevice9_DrawPrimitive(dev, D3DPT_TRIANGLESTRIP, start, count); d3d->menu_display.offset += draw->coords->vertices; } diff --git a/gfx/drivers/d3d9hlsl.c b/gfx/drivers/d3d9hlsl.c index e92094f9361b..ee6fed27345d 100644 --- a/gfx/drivers/d3d9hlsl.c +++ b/gfx/drivers/d3d9hlsl.c @@ -709,23 +709,6 @@ static const float d3d9_hlsl_tex_coords[8] = { static LPDIRECT3DTEXTURE9 d3d9_hlsl_white_texture = NULL; -static INT32 gfx_display_prim_to_d3d9_hlsl_enum( - enum gfx_display_prim_type prim_type) -{ - switch (prim_type) - { - case GFX_DISPLAY_PRIM_TRIANGLES: - case GFX_DISPLAY_PRIM_TRIANGLESTRIP: - return D3DPT_TRIANGLESTRIP; - case GFX_DISPLAY_PRIM_NONE: - default: - break; - } - - /* TODO/FIXME - hack */ - return 0; -} - static void gfx_display_d3d9_hlsl_blend_begin(void *data) { d3d9_video_t *d3d = (d3d9_video_t*)data; @@ -777,7 +760,6 @@ static void gfx_display_d3d9_hlsl_draw(gfx_display_ctx_draw_t *draw, { unsigned i; LPDIRECT3DDEVICE9 dev; - D3DPRIMITIVETYPE type; bool has_vertex_data; unsigned start = 0; unsigned count = 0; @@ -1099,13 +1081,22 @@ static void gfx_display_d3d9_hlsl_draw(gfx_display_ctx_draw_t *draw, if (draw && draw->texture) gfx_display_d3d9_bind_texture(draw, d3d); - type = (D3DPRIMITIVETYPE)gfx_display_prim_to_d3d9_hlsl_enum(draw->prim_type); start = d3d->menu_display.offset; - count = draw->coords->vertices - - ((draw->prim_type == GFX_DISPLAY_PRIM_TRIANGLESTRIP) - ? 2 : 0); - IDirect3DDevice9_DrawPrimitive(dev, type, start, count); + /* Every caller in the codebase sets draw->prim_type to + * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so the per-call switch on the + * primitive type that used to live here was dead. See the + * matching comment in d3d8.c's gfx_display_d3d8_draw for why we + * also harden against vertices < 3 (the tristrip count formula + * vertices - 2 underflows the unsigned subtraction otherwise). */ + if (draw->coords->vertices < 3) + { + d3d->menu_display.offset += draw->coords->vertices; + return; + } + count = draw->coords->vertices - 2; + + IDirect3DDevice9_DrawPrimitive(dev, D3DPT_TRIANGLESTRIP, start, count); d3d->menu_display.offset += draw->coords->vertices; } From 696efa0f3d288d1861f18c4dc866255e30f7f045 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 02:05:06 +0200 Subject: [PATCH 09/14] gfx/drivers: drop dead prim_to_gl helpers in gl1/gl2/gl3 Companion to 1ee88d08de (the d3d helpers). Each of gl1, gl2, gl3 carries an identical gfx_display_prim_to_gl{1,,3}_enum helper that maps GFX_DISPLAY_PRIM_TRIANGLESTRIP -> GL_TRIANGLE_STRIP and GFX_DISPLAY_PRIM_TRIANGLES -> GL_TRIANGLES. Same dead-code argument as 1ee88d08de: every gfx_display_ctx_draw_t in the codebase sets prim_type to GFX_DISPLAY_PRIM_TRIANGLESTRIP before invoking dispctx->draw, all 15 "prim_type =" assignments under gfx/, menu/, and gfx/widgets/ assign TRIANGLESTRIP, and every local declaration assigns prim_type before the draw call. The TRIANGLES, NONE, and default arms are unreachable. Unlike the d3d helpers (which mapped TRIANGLES to the wrong primitive type and returned an illegal D3DPRIMITIVETYPE on the default branch), the gl helpers were correct in their dead branches -- TRIANGLES -> GL_TRIANGLES is the right mapping, and the "return 0" default falls back to GL_POINTS, a valid (if nonsensical for menu draws) GL enum. So this is purely dead-code removal, not a latent-bug fix. Inline GL_TRIANGLE_STRIP at the glDrawArrays call site, drop the helpers. gl3 has two glDrawArrays sites (the chain.active branch and the HAVE_SLANG else branch); both get the same treatment, and the explicit switch on prim_type at the second site collapses to a single glDrawArrays call as well. Document at the call sites that the constant assumes TRIANGLESTRIP. Net -48 lines. No behavioural change for any existing caller. --- gfx/drivers/gl1.c | 25 ++++++------------------- gfx/drivers/gl2.c | 25 ++++++------------------- gfx/drivers/gl3.c | 40 +++++++++------------------------------- 3 files changed, 21 insertions(+), 69 deletions(-) diff --git a/gfx/drivers/gl1.c b/gfx/drivers/gl1.c index ff90323c4b9f..c38412aa94e9 100644 --- a/gfx/drivers/gl1.c +++ b/gfx/drivers/gl1.c @@ -273,23 +273,6 @@ static void *gfx_display_gl1_get_default_mvp(void *data) return &gl1->mvp_no_rot; } -static GLenum gfx_display_prim_to_gl1_enum( - enum gfx_display_prim_type type) -{ - switch (type) - { - case GFX_DISPLAY_PRIM_TRIANGLESTRIP: - return GL_TRIANGLE_STRIP; - case GFX_DISPLAY_PRIM_TRIANGLES: - return GL_TRIANGLES; - case GFX_DISPLAY_PRIM_NONE: - default: - break; - } - - return 0; -} - static void gfx_display_gl1_blend_begin(void *data) { glEnable(GL_BLEND); @@ -366,8 +349,12 @@ static void gfx_display_gl1_draw(gfx_display_ctx_draw_t *draw, glColorPointer(4, GL_FLOAT, 0, draw->coords->color); glTexCoordPointer(2, GL_FLOAT, 0, draw->coords->tex_coord); - glDrawArrays(gfx_display_prim_to_gl1_enum( - draw->prim_type), 0, draw->coords->vertices); + /* Every caller in the codebase sets draw->prim_type to + * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so the per-call switch on the + * primitive type that used to live here was dead. Hard-code + * GL_TRIANGLE_STRIP; if a future caller passes TRIANGLES this + * will need to grow back into a switch. */ + glDrawArrays(GL_TRIANGLE_STRIP, 0, draw->coords->vertices); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); diff --git a/gfx/drivers/gl2.c b/gfx/drivers/gl2.c index af9b41522520..bde6f2429450 100644 --- a/gfx/drivers/gl2.c +++ b/gfx/drivers/gl2.c @@ -511,23 +511,6 @@ static void *gfx_display_gl2_get_default_mvp(void *data) return &gl->mvp_no_rot; } -static GLenum gfx_display_prim_to_gl_enum( - enum gfx_display_prim_type type) -{ - switch (type) - { - case GFX_DISPLAY_PRIM_TRIANGLESTRIP: - return GL_TRIANGLE_STRIP; - case GFX_DISPLAY_PRIM_TRIANGLES: - return GL_TRIANGLES; - case GFX_DISPLAY_PRIM_NONE: - default: - break; - } - - return 0; -} - static void gfx_display_gl2_blend_begin(void *data) { gl2_t *gl = (gl2_t*)data; @@ -650,8 +633,12 @@ static void gfx_display_gl2_draw(gfx_display_ctx_draw_t *draw, : (math_matrix_4x4*)&gl->mvp_no_rot); - glDrawArrays(gfx_display_prim_to_gl_enum( - draw->prim_type), 0, draw->coords->vertices); + /* Every caller in the codebase sets draw->prim_type to + * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so the per-call switch on the + * primitive type that used to live here was dead. Hard-code + * GL_TRIANGLE_STRIP; if a future caller passes TRIANGLES this + * will need to grow back into a switch. */ + glDrawArrays(GL_TRIANGLE_STRIP, 0, draw->coords->vertices); gl->coords.color = gl->white_color_ptr; } diff --git a/gfx/drivers/gl3.c b/gfx/drivers/gl3.c index 2f9aa431f679..5b29b09f8d7a 100644 --- a/gfx/drivers/gl3.c +++ b/gfx/drivers/gl3.c @@ -651,23 +651,6 @@ static void gfx_display_gl3_draw_pipeline( #endif } -static GLenum gfx_display_prim_to_gl3_enum( - enum gfx_display_prim_type type) -{ - switch (type) - { - case GFX_DISPLAY_PRIM_TRIANGLESTRIP: - return GL_TRIANGLE_STRIP; - case GFX_DISPLAY_PRIM_TRIANGLES: - return GL_TRIANGLES; - case GFX_DISPLAY_PRIM_NONE: - default: - break; - } - - return 0; -} - static void gfx_display_gl3_draw(gfx_display_ctx_draw_t *draw, void *data, unsigned video_width, unsigned video_height) { @@ -695,8 +678,12 @@ static void gfx_display_gl3_draw(gfx_display_ctx_draw_t *draw, draw->matrix_data ? (math_matrix_4x4*)draw->matrix_data : (math_matrix_4x4*)&gl->mvp_no_rot); - glDrawArrays(gfx_display_prim_to_gl3_enum( - draw->prim_type), 0, draw->coords->vertices); + /* Every caller in the codebase sets draw->prim_type to + * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so the per-call switch on + * the primitive type that used to live here was dead. + * Hard-code GL_TRIANGLE_STRIP; if a future caller passes + * TRIANGLES this will need to grow back into a switch. */ + glDrawArrays(GL_TRIANGLE_STRIP, 0, draw->coords->vertices); } #ifdef HAVE_SLANG else @@ -797,18 +784,9 @@ static void gfx_display_gl3_draw(gfx_display_ctx_draw_t *draw, glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)(uintptr_t)0); - switch (draw->prim_type) - { - case GFX_DISPLAY_PRIM_TRIANGLESTRIP: - glDrawArrays(GL_TRIANGLE_STRIP, 0, draw->coords->vertices); - break; - case GFX_DISPLAY_PRIM_TRIANGLES: - glDrawArrays(GL_TRIANGLES, 0, draw->coords->vertices); - break; - case GFX_DISPLAY_PRIM_NONE: - default: - break; - } + /* See the matching comment in the chain.active branch above: + * every caller passes TRIANGLESTRIP. */ + glDrawArrays(GL_TRIANGLE_STRIP, 0, draw->coords->vertices); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); From 6cd9ea6f0ffb780667077c8ec0926d0cf61b2fd3 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 02:14:43 +0200 Subject: [PATCH 10/14] gfx/drivers/metal: drop dead _toPrimitiveType helper Companion to 1ee88d08de and 2711c42727 (the d3d and gl helpers). MenuDisplay's private _toPrimitiveType: maps GFX_DISPLAY_PRIM_TRIANGLESTRIP -> MTLPrimitiveTypeTriangleStrip and falls through to MTLPrimitiveTypeTriangle for any other input. Same dead-code argument: every gfx_display_ctx_draw_t in the codebase sets prim_type to GFX_DISPLAY_PRIM_TRIANGLESTRIP before invoking the draw path, so the fallthrough to MTLPrimitiveTypeTriangle is unreachable. Inline MTLPrimitiveTypeTriangleStrip at the single -drawPrimitives: call site, drop the helper. Document at the call site that the constant assumes TRIANGLESTRIP. While here: note that the dead fallthrough returned MTLPrimitiveTypeTriangle (a triangle list) rather than something nonsensical, so unlike the d3d helpers this was not also a latent bug -- just dead. No behavioural change for any existing caller. --- gfx/drivers/metal.m | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/gfx/drivers/metal.m b/gfx/drivers/metal.m index 33ca2653636b..d0303581ea29 100644 --- a/gfx/drivers/metal.m +++ b/gfx/drivers/metal.m @@ -2197,13 +2197,6 @@ - (void)clearScissorRect [_context resetScissorRect]; } -- (MTLPrimitiveType)_toPrimitiveType:(enum gfx_display_prim_type)prim -{ - if (prim == GFX_DISPLAY_PRIM_TRIANGLESTRIP) - return MTLPrimitiveTypeTriangleStrip; - return MTLPrimitiveTypeTriangle; -} - - (void)drawPipeline:(gfx_display_ctx_draw_t *)draw { static struct video_coords blank_coords; @@ -2312,7 +2305,13 @@ - (void)draw:(gfx_display_ctx_draw_t *)draw [rce setVertexBytes:draw->backend_data length:draw->backend_data_size atIndex:BufferIndexUniforms]; [rce setVertexBuffer:range.buffer offset:range.offset atIndex:BufferIndexPositions]; [rce setFragmentBytes:draw->backend_data length:draw->backend_data_size atIndex:BufferIndexUniforms]; - [rce drawPrimitives:[self _toPrimitiveType:draw->prim_type] vertexStart:0 vertexCount:vertex_count]; + /* Every caller in the codebase sets draw->prim_type to + * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so the per-call mapping + * to MTLPrimitiveType that used to live in a private + * helper was dead. Hard-code MTLPrimitiveTypeTriangleStrip; + * if a future caller passes TRIANGLES this will need to + * grow back into a switch. */ + [rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:vertex_count]; return; #endif default: From 9915c52f08ebcb50e69bc1e8adcfff8db4b33112 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 02:35:28 +0200 Subject: [PATCH 11/14] gfx/drivers/vulkan: collapse display.pipelines to STRIP-only layout Continuation of the prim_type dead-code sweep (1ee88d08de, 696efa0f3d, 6cd9ea6f0f). Vulkan didn't have a prim_to_vk helper to delete, but the same dead pattern is present, expressed through array slot indexing instead of a switch statement. Old layout ---------- vk->display.pipelines was an 18-slot array (9 logical pipelines x 2 topologies) indexed by `(prim_type == TRIANGLESTRIP) << 1 | blend` for the display alpha-blend pair, and by to_menu_pipeline() returning `6 + 2*shader_idx + (prim_type == TRIANGLESTRIP)` for the menu shaders. Since every draw passes TRIANGLESTRIP (same audit as the d3d/gl/metal cleanups: 15 of 15 prim_type assignments in the codebase assign TRIANGLESTRIP, never TRIANGLES, never NONE), the LIST entries get built by init and never read. Slots [0], [1], [6], [8], [10], [12], [14], [16] -- the LIST variants -- were dead at runtime in every configuration. Slots [4] and [5] -- the HDR-only display pipelines populated by the for(i=4;i<6;i++) loop introduced in 12d188ee1d -- were also dead. Both iterations of that loop produce identical pipeline objects (no varying state between them) and no consumer ever indexes those slots. The dedicated vk->pipelines.hdr field built right above the dead loop is the actual HDR composition pipeline used by vulkan_run_hdr_pipeline at swapchain present. The dead [4,5] population looks like copy-paste residue from the SDR alpha-blend loop above it. New layout ---------- Drop the LIST variants and the dead HDR slots. Collapse to 8 slots, all TRIANGLE_STRIP: [0] alpha_blend, no blend [1] alpha_blend, blend [2] ribbon [3] ribbon_simple [4] snow_simple [5] snow [6] bokeh [7] snowflake Same layout for vk->display.pipelines_sdr (the parallel HDR-on SDR-offscreen variants). Consumer updates ---------------- - gfx_display_vk_draw at the disp_pipeline site: ((prim_type == TRIANGLESTRIP) << 1) | blend -> blend (always picks slot 0 or 1 in the new layout) - to_menu_pipeline drops its prim_type parameter and returns a constant 2..7 keyed off pipeline_id. - The overlay path's hardcoded vk->display.pipelines[3] ("Strip with blend") becomes vk->display.pipelines[1] (same pipeline, new slot number). Init loop changes ----------------- - The display alpha-blend build (was for(i=0;i<4;i++) varying topology and blend on i bits) becomes for(i=0;i<2;i++) with topology set once before the loop. - The menu shader build (was for(i=0;i> 1` for shader index and `i & 1` for topology) becomes for(i=0;i<6;i++), one iteration per shader. - Mirror changes for the SDR sibling loops. - The dead HDR-display loop at lines 3537-3542 (for(i=4;i<6;i++)) is removed. The vk->pipelines.hdr build right above it stays. Why STRIP for everything is fine -------------------------------- Same argument as the prior sweep commits: all menu draws are axis-aligned quads (4 vertices = 2 triangles). A tristrip issues N-2 triangles for N vertices; a list needs 3*N vertices for N triangles. For a quad: 4 vs 6 vertex shader invocations. STRIP is strictly cheaper per draw than LIST for this geometry, so there is no performance reason to keep the LIST pipelines. Init-time saving is small but real: 8 fewer vkCreateGraphicsPipelines calls per init in SDR builds, 10 fewer when HDR is on. Pipeline creation is one of Vulkan's more expensive operations on first compile (shader bytecode + state object). Most of the saving is in driver pipeline cache footprint and shader-module count; hot-path draws hit the same pipelines they did before, just at different slot numbers. Verification ------------ - clang -fsyntax-only -Wall on three configuration permutations: HDR + shaderpipeline, no HDR + shaderpipeline, no HDR + no shaderpipeline. All clean. - Brace and paren balance preserved against master. - Diff is +78/-75 (net +3 lines) because most additions are layout-documenting comments; the executable code shrinks substantially. --- gfx/drivers/vulkan.c | 153 ++++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 75 deletions(-) diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 12c9ed83fa8e..52d94e5a2ff3 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -298,9 +298,25 @@ typedef struct vk struct { - VkPipeline pipelines[9 * 2]; + /* Layout: every menu draw in the codebase uses + * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so this driver only keeps + * STRIP variants: + * [0] alpha_blend, no blend + * [1] alpha_blend, blend + * [2] ribbon + * [3] ribbon_simple + * [4] snow_simple + * [5] snow + * [6] bokeh + * [7] snowflake + * All entries are TRIANGLE_STRIP topology. The history of + * this array previously included parallel TRIANGLE_LIST + * variants in even slots, but no caller ever set prim_type to + * anything other than TRIANGLESTRIP, so the LIST pipelines + * were built and never used. */ + VkPipeline pipelines[8]; #ifdef VULKAN_HDR_SWAPCHAIN - VkPipeline pipelines_sdr[9 * 2]; /* SDR offscreen variants */ + VkPipeline pipelines_sdr[8]; /* SDR offscreen variants, same layout */ #endif struct vk_texture blank_texture; } display; @@ -1774,23 +1790,27 @@ static const float *gfx_display_vk_get_default_tex_coords(void) } #ifdef HAVE_SHADERPIPELINE -static unsigned to_menu_pipeline( - enum gfx_display_prim_type type, unsigned pipeline) +static unsigned to_menu_pipeline(unsigned pipeline) { + /* The display pipeline array slots [2..7] hold the six menu + * shader pipelines (ribbon, ribbon_simple, snow_simple, snow, + * bokeh, snowflake) in that order. VIDEO_SHADER_MENU through + * VIDEO_SHADER_MENU_6 are consecutive descending #defines, so + * the mapping is a simple offset. */ switch (pipeline) { case VIDEO_SHADER_MENU: - return 6 + (type == GFX_DISPLAY_PRIM_TRIANGLESTRIP); + return 2; case VIDEO_SHADER_MENU_2: - return 8 + (type == GFX_DISPLAY_PRIM_TRIANGLESTRIP); + return 3; case VIDEO_SHADER_MENU_3: - return 10 + (type == GFX_DISPLAY_PRIM_TRIANGLESTRIP); + return 4; case VIDEO_SHADER_MENU_4: - return 12 + (type == GFX_DISPLAY_PRIM_TRIANGLESTRIP); + return 5; case VIDEO_SHADER_MENU_5: - return 14 + (type == GFX_DISPLAY_PRIM_TRIANGLESTRIP); + return 6; case VIDEO_SHADER_MENU_6: - return 16 + (type == GFX_DISPLAY_PRIM_TRIANGLESTRIP); + return 7; default: break; } @@ -1987,7 +2007,7 @@ static void gfx_display_vk_draw(gfx_display_ctx_draw_t *draw, case VIDEO_SHADER_MENU_6: { struct vk_draw_triangles call; - unsigned idx = to_menu_pipeline(draw->prim_type, draw->pipeline_id); + unsigned idx = to_menu_pipeline(draw->pipeline_id); #ifdef VULKAN_HDR_SWAPCHAIN call.pipeline = (vk->flags & VK_FLAG_SDR_PIPELINE) @@ -2012,10 +2032,11 @@ static void gfx_display_vk_draw(gfx_display_ctx_draw_t *draw, default: { struct vk_draw_triangles call; + /* Slot 0 = no blend, slot 1 = blend. Both are TRIANGLE_STRIP + * (every menu draw is a tristrip; see the comment on + * display.pipelines for the layout). */ unsigned - disp_pipeline = - ((draw->prim_type == GFX_DISPLAY_PRIM_TRIANGLESTRIP) << 1) - | (((vk->flags & VK_FLAG_DISPLAY_BLEND) > 0) << 0); + disp_pipeline = ((vk->flags & VK_FLAG_DISPLAY_BLEND) > 0); #ifdef VULKAN_HDR_SWAPCHAIN call.pipeline = (vk->flags & VK_FLAG_SDR_PIPELINE) ? vk->display.pipelines_sdr[disp_pipeline] @@ -3499,13 +3520,12 @@ static void vulkan_init_pipelines(vk_t *vk) vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, 1, &pipe, NULL, &vk->pipelines.alpha_blend); - /* Build display pipelines. */ - for (i = 0; i < 4; i++) + /* Build display pipelines (STRIP topology only). + * [0]: blend off, [1]: blend on. */ + input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + for (i = 0; i < 2; i++) { - input_assembly.topology = i & 2 ? - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP : - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - blend_attachment.blendEnable = i & 1; + blend_attachment.blendEnable = i; vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, 1, &pipe, NULL, &vk->display.pipelines[i]); } @@ -3533,13 +3553,16 @@ static void vulkan_init_pipelines(vk_t *vk) vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, 1, &pipe, NULL, &vk->pipelines.hdr); - /* Build display hdr pipelines. */ - for (i = 4; i < 6; i++) - { - input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, - 1, &pipe, NULL, &vk->display.pipelines[i]); - } + /* The previous code built two additional display pipelines + * here (in old slots 4 and 5) using the hdr_frag shader. Both + * iterations of that loop produced identical pipeline objects + * (no varying state between them), and no consumer ever + * indexed slots 4 or 5 -- they were copy-paste residue from + * the SDR-side loop above and went unused even with HDR + * enabled. The dedicated `vk->pipelines.hdr` field built + * just above is the actual HDR composition pipeline; it is + * still used by vulkan_run_hdr_pipeline at the swapchain + * presentation path. */ vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL); @@ -3572,10 +3595,13 @@ static void vulkan_init_pipelines(vk_t *vk) * readback_render_pass. */ pipe.renderPass = vk->render_pass; - /* Other menu pipelines. */ - for (i = 0; i < (int)ARRAY_SIZE(vk->display.pipelines) - 6; i++) + /* Other menu pipelines. Six STRIP-only variants populate + * slots [2..7]: ribbon, ribbon_simple, snow_simple, snow, + * bokeh, snowflake. See display.pipelines for layout. */ + input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + for (i = 0; i < 6; i++) { - switch (i >> 1) + switch (i) { case 0: module_info.codeSize = sizeof(pipeline_ribbon_vert); @@ -3587,28 +3613,10 @@ static void vulkan_init_pipelines(vk_t *vk) module_info.pCode = pipeline_ribbon_simple_vert; break; - case 2: - module_info.codeSize = sizeof(alpha_blend_vert); - module_info.pCode = alpha_blend_vert; - break; - - case 3: - module_info.codeSize = sizeof(alpha_blend_vert); - module_info.pCode = alpha_blend_vert; - break; - - case 4: - module_info.codeSize = sizeof(alpha_blend_vert); - module_info.pCode = alpha_blend_vert; - break; - - case 5: + default: module_info.codeSize = sizeof(alpha_blend_vert); module_info.pCode = alpha_blend_vert; break; - - default: - break; } shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; @@ -3616,7 +3624,7 @@ static void vulkan_init_pipelines(vk_t *vk) vkCreateShaderModule(vk->context->device, &module_info, NULL, &shader_stages[0].module); - switch (i >> 1) + switch (i) { case 0: module_info.codeSize = sizeof(pipeline_ribbon_frag); @@ -3657,7 +3665,7 @@ static void vulkan_init_pipelines(vk_t *vk) vkCreateShaderModule(vk->context->device, &module_info, NULL, &shader_stages[1].module); - switch (i >> 1) + switch (i) { case 0: case 1: @@ -3670,12 +3678,8 @@ static void vulkan_init_pipelines(vk_t *vk) break; } - input_assembly.topology = i & 1 ? - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP : - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, - 1, &pipe, NULL, &vk->display.pipelines[6 + i]); + 1, &pipe, NULL, &vk->display.pipelines[2 + i]); vkDestroyShaderModule(vk->context->device, shader_stages[0].module, NULL); vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL); @@ -3731,16 +3735,15 @@ static void vulkan_init_pipelines(vk_t *vk) vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, 1, &pipe, NULL, &vk->pipelines.alpha_blend_sdr); - /* SDR display pipelines 0-3. + /* SDR display pipelines, slots [0..1]. STRIP-only, see the + * matching comment on the main display.pipelines build above. * Reuse the alpha_blend vertex shader (stages[0]) and * alpha_blend fragment shader (stages[1]) still alive * from just above. */ - for (i = 0; i < 4; i++) + input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + for (i = 0; i < 2; i++) { - input_assembly.topology = i & 2 ? - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP : - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - blend_attachment.blendEnable = i & 1; + blend_attachment.blendEnable = i; vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, 1, &pipe, NULL, &vk->display.pipelines_sdr[i]); } @@ -3749,10 +3752,12 @@ static void vulkan_init_pipelines(vk_t *vk) vkDestroyShaderModule(vk->context->device, shader_stages[0].module, NULL); vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL); - /* SDR menu shader pipelines 6+ */ - for (i = 0; i < (int)ARRAY_SIZE(vk->display.pipelines) - 6; i++) + /* SDR menu shader pipelines, slots [2..7]. STRIP-only; + * mirror of the main display.pipelines build. */ + input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + for (i = 0; i < 6; i++) { - switch (i >> 1) + switch (i) { case 0: module_info.codeSize = sizeof(pipeline_ribbon_vert); @@ -3772,7 +3777,7 @@ static void vulkan_init_pipelines(vk_t *vk) vkCreateShaderModule(vk->context->device, &module_info, NULL, &shader_stages[0].module); - switch (i >> 1) + switch (i) { case 0: module_info.codeSize = sizeof(pipeline_ribbon_frag); @@ -3806,7 +3811,7 @@ static void vulkan_init_pipelines(vk_t *vk) vkCreateShaderModule(vk->context->device, &module_info, NULL, &shader_stages[1].module); - switch (i >> 1) + switch (i) { case 0: case 1: @@ -3819,12 +3824,8 @@ static void vulkan_init_pipelines(vk_t *vk) break; } - input_assembly.topology = i & 1 ? - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP : - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, - 1, &pipe, NULL, &vk->display.pipelines_sdr[6 + i]); + 1, &pipe, NULL, &vk->display.pipelines_sdr[2 + i]); vkDestroyShaderModule(vk->context->device, shader_stages[0].module, NULL); vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL); @@ -8149,12 +8150,14 @@ static void vulkan_render_overlay(vk_t *vk, unsigned width, { int idx = base + i; struct vk_texture *tex = &vk->overlay.images[idx]; + /* Slot [1] is alpha-blend, TRIANGLE_STRIP (the only + * topology this driver builds; see display.pipelines). */ #ifdef VULKAN_HDR_SWAPCHAIN VkPipeline pipeline = (vk->flags & VK_FLAG_SDR_PIPELINE) - ? vk->display.pipelines_sdr[3] - : vk->display.pipelines[3]; /* Strip with blend */ + ? vk->display.pipelines_sdr[1] + : vk->display.pipelines[1]; #else - VkPipeline pipeline = vk->display.pipelines[3]; /* Strip with blend */ + VkPipeline pipeline = vk->display.pipelines[1]; #endif if (tex->image) From e78ec40f62f39a460ea5b841b658f0cff2a509d2 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 03:15:19 +0200 Subject: [PATCH 12/14] gfx: drop the now-vestigial prim_type field and enum The prim_type sweep across d3d/gl/metal/vulkan (1ee88d08de, 696efa0f3d, 6cd9ea6f0f, 9915c52f08) removed the dead per-driver dispatch branches that handled non-TRIANGLESTRIP cases. After those commits the field was set to GFX_DISPLAY_PRIM_TRIANGLESTRIP at every call site and read nowhere -- a vestigial concept the codebase still paid for in struct size, init code, and reader cognitive load. Survey before this commit: - 16 assignments of draw->prim_type, all to GFX_DISPLAY_PRIM_TRIANGLESTRIP (11 caller-side, 5 driver-side overrides for the menu shader path) - 0 reads that branched on the value - GFX_DISPLAY_PRIM_NONE and GFX_DISPLAY_PRIM_TRIANGLES: defined, never assigned anywhere in tree Removed: - enum gfx_display_prim_type (gfx/gfx_display.h) - struct gfx_display_ctx_draw::prim_type field - All 16 prim_type assignments - The "every caller sets prim_type to TRIANGLESTRIP, so the per-call switch was dead" comments left in d3d8.c, d3d9cg.c, d3d9hlsl.c, gl1.c, gl2.c, gl3.c, metal.m, and vulkan.c by the prior cleanup commits, replaced with shorter comments noting only the strip layout assumption (and the vertex underflow guard rationale, which is still relevant for d3d). Effects on consumers: - struct gfx_display_ctx_draw shrinks by sizeof(enum) + alignment padding (typically 4 bytes). The struct is stack-allocated at all call sites; no heap layout changes. - No ABI exposure to libretro cores -- gfx_display_ctx_draw_t is internal to RetroArch. - Out-of-tree menu driver forks that wrote draw.prim_type would see a compile error. In-tree consumers all updated. Verification: - clang -fsyntax-only -Wall on vulkan.c across three configurations (HDR + shaderpipeline, no HDR + shaderpipeline, no HDR + no shaderpipeline): clean. - clang -fsyntax-only on gfx/gfx_display.c, gfx/gfx_thumbnail.c, gfx/gfx_widgets.c, materialui.c, xmb.c: clean. - Brace and paren balance preserved against master in all 15 modified files. --- gfx/drivers/d3d8.c | 18 +++++------------- gfx/drivers/d3d9cg.c | 11 ++++------- gfx/drivers/d3d9hlsl.c | 11 ++++------- gfx/drivers/gl1.c | 6 +----- gfx/drivers/gl2.c | 6 +----- gfx/drivers/gl3.c | 7 +------ gfx/drivers/metal.m | 8 +------- gfx/drivers/vulkan.c | 14 +++++--------- gfx/gfx_display.c | 3 --- gfx/gfx_display.h | 8 -------- gfx/gfx_thumbnail.c | 1 - gfx/gfx_widgets.c | 1 - menu/drivers/materialui.c | 2 -- menu/drivers/ozone.c | 1 - menu/drivers/xmb.c | 3 --- 15 files changed, 22 insertions(+), 78 deletions(-) diff --git a/gfx/drivers/d3d8.c b/gfx/drivers/d3d8.c index c21d08e7a058..72c353970c40 100644 --- a/gfx/drivers/d3d8.c +++ b/gfx/drivers/d3d8.c @@ -989,19 +989,11 @@ static void gfx_display_d3d8_draw(gfx_display_ctx_draw_t *draw, start = d3d->menu_display.offset; - /* Every caller in the codebase sets draw->prim_type to - * GFX_DISPLAY_PRIM_TRIANGLESTRIP, and the draw->coords vertices - * are laid out as a strip. Hard-code D3DPT_TRIANGLESTRIP and the - * (vertices - 2) primitive-count formula here. If a future - * caller passes TRIANGLES or another primitive type, this site - * will need to grow back into a switch -- but with no current - * non-tristrip caller, the dead branch was just buggy: it mapped - * TRIANGLES to D3DPT_TRIANGLESTRIP (the wrong type) and used - * count = vertices (the wrong count formula for D3D, which - * expects PrimitiveCount, not vertex count). - * - * Guard against vertices < 3 which would underflow the unsigned - * subtraction and pass a huge primitive count to the GPU. */ + /* Menu draws issued by gfx_display always pass a triangle-strip layout + * (4 vertices = 2 triangles for a quad). D3D8 expects PrimitiveCount, + * not vertex count, hence (vertices - 2). Guard against vertices < 3 + * which would underflow the unsigned subtraction and pass a huge + * primitive count to the GPU. */ if (draw->coords->vertices < 3) { d3d->menu_display.offset += draw->coords->vertices; diff --git a/gfx/drivers/d3d9cg.c b/gfx/drivers/d3d9cg.c index 15ec8de43136..47eb9f977a63 100644 --- a/gfx/drivers/d3d9cg.c +++ b/gfx/drivers/d3d9cg.c @@ -1022,12 +1022,10 @@ static void gfx_display_d3d9_cg_draw(gfx_display_ctx_draw_t *draw, start = d3d->menu_display.offset; - /* Every caller in the codebase sets draw->prim_type to - * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so the per-call switch on the - * primitive type that used to live here was dead. See the - * matching comment in d3d8.c's gfx_display_d3d8_draw for why we - * also harden against vertices < 3 (the tristrip count formula - * vertices - 2 underflows the unsigned subtraction otherwise). */ + /* Menu draws use a triangle-strip layout. Harden against vertices < 3 + * (the count formula vertices - 2 would otherwise underflow the + * unsigned subtraction and pass a huge primitive count to the GPU -- + * see d3d8.c for the matching guard). */ if (draw->coords->vertices < 3) { d3d->menu_display.offset += draw->coords->vertices; @@ -1187,7 +1185,6 @@ static void gfx_display_d3d9_cg_draw_pipeline(gfx_display_ctx_draw_t *draw, blank_coords.vertices = 4; draw->coords = &blank_coords; - draw->prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; IDirect3DDevice9_SetRenderState(d3d->dev, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); diff --git a/gfx/drivers/d3d9hlsl.c b/gfx/drivers/d3d9hlsl.c index ee6fed27345d..139052d38398 100644 --- a/gfx/drivers/d3d9hlsl.c +++ b/gfx/drivers/d3d9hlsl.c @@ -1083,12 +1083,10 @@ static void gfx_display_d3d9_hlsl_draw(gfx_display_ctx_draw_t *draw, start = d3d->menu_display.offset; - /* Every caller in the codebase sets draw->prim_type to - * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so the per-call switch on the - * primitive type that used to live here was dead. See the - * matching comment in d3d8.c's gfx_display_d3d8_draw for why we - * also harden against vertices < 3 (the tristrip count formula - * vertices - 2 underflows the unsigned subtraction otherwise). */ + /* Menu draws use a triangle-strip layout. Harden against vertices < 3 + * (the count formula vertices - 2 would otherwise underflow the + * unsigned subtraction and pass a huge primitive count to the GPU -- + * see d3d8.c for the matching guard). */ if (draw->coords->vertices < 3) { d3d->menu_display.offset += draw->coords->vertices; @@ -1243,7 +1241,6 @@ static void gfx_display_d3d9_hlsl_draw_pipeline( * ca->coords.vertices (which ribbon needs at 8064). */ blank_coords.vertices = 4; draw->coords = &blank_coords; - draw->prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; /* Set blend state for particle effects */ IDirect3DDevice9_SetRenderState(d3d->dev, diff --git a/gfx/drivers/gl1.c b/gfx/drivers/gl1.c index c38412aa94e9..5c97b986554f 100644 --- a/gfx/drivers/gl1.c +++ b/gfx/drivers/gl1.c @@ -349,11 +349,7 @@ static void gfx_display_gl1_draw(gfx_display_ctx_draw_t *draw, glColorPointer(4, GL_FLOAT, 0, draw->coords->color); glTexCoordPointer(2, GL_FLOAT, 0, draw->coords->tex_coord); - /* Every caller in the codebase sets draw->prim_type to - * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so the per-call switch on the - * primitive type that used to live here was dead. Hard-code - * GL_TRIANGLE_STRIP; if a future caller passes TRIANGLES this - * will need to grow back into a switch. */ + /* Menu draws use a triangle-strip layout. */ glDrawArrays(GL_TRIANGLE_STRIP, 0, draw->coords->vertices); glDisableClientState(GL_COLOR_ARRAY); diff --git a/gfx/drivers/gl2.c b/gfx/drivers/gl2.c index bde6f2429450..464372cd81b2 100644 --- a/gfx/drivers/gl2.c +++ b/gfx/drivers/gl2.c @@ -633,11 +633,7 @@ static void gfx_display_gl2_draw(gfx_display_ctx_draw_t *draw, : (math_matrix_4x4*)&gl->mvp_no_rot); - /* Every caller in the codebase sets draw->prim_type to - * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so the per-call switch on the - * primitive type that used to live here was dead. Hard-code - * GL_TRIANGLE_STRIP; if a future caller passes TRIANGLES this - * will need to grow back into a switch. */ + /* Menu draws use a triangle-strip layout. */ glDrawArrays(GL_TRIANGLE_STRIP, 0, draw->coords->vertices); gl->coords.color = gl->white_color_ptr; diff --git a/gfx/drivers/gl3.c b/gfx/drivers/gl3.c index 5b29b09f8d7a..35907e1108e0 100644 --- a/gfx/drivers/gl3.c +++ b/gfx/drivers/gl3.c @@ -641,7 +641,6 @@ static void gfx_display_gl3_draw_pipeline( + 3 * sizeof(float), &yflip, sizeof(yflip)); draw->coords = &blank_coords; blank_coords.vertices = 4; - draw->prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; break; } } @@ -678,11 +677,7 @@ static void gfx_display_gl3_draw(gfx_display_ctx_draw_t *draw, draw->matrix_data ? (math_matrix_4x4*)draw->matrix_data : (math_matrix_4x4*)&gl->mvp_no_rot); - /* Every caller in the codebase sets draw->prim_type to - * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so the per-call switch on - * the primitive type that used to live here was dead. - * Hard-code GL_TRIANGLE_STRIP; if a future caller passes - * TRIANGLES this will need to grow back into a switch. */ + /* Menu draws use a triangle-strip layout. */ glDrawArrays(GL_TRIANGLE_STRIP, 0, draw->coords->vertices); } #ifdef HAVE_SLANG diff --git a/gfx/drivers/metal.m b/gfx/drivers/metal.m index d0303581ea29..89971c3dc86d 100644 --- a/gfx/drivers/metal.m +++ b/gfx/drivers/metal.m @@ -2227,7 +2227,6 @@ - (void)drawPipeline:(gfx_display_ctx_draw_t *)draw { draw->coords = &blank_coords; blank_coords.vertices = 4; - draw->prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; break; } } @@ -2305,12 +2304,7 @@ - (void)draw:(gfx_display_ctx_draw_t *)draw [rce setVertexBytes:draw->backend_data length:draw->backend_data_size atIndex:BufferIndexUniforms]; [rce setVertexBuffer:range.buffer offset:range.offset atIndex:BufferIndexPositions]; [rce setFragmentBytes:draw->backend_data length:draw->backend_data_size atIndex:BufferIndexUniforms]; - /* Every caller in the codebase sets draw->prim_type to - * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so the per-call mapping - * to MTLPrimitiveType that used to live in a private - * helper was dead. Hard-code MTLPrimitiveTypeTriangleStrip; - * if a future caller passes TRIANGLES this will need to - * grow back into a switch. */ + /* Menu draws use a triangle-strip layout. */ [rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:vertex_count]; return; #endif diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 52d94e5a2ff3..66f5aa60f836 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -298,9 +298,8 @@ typedef struct vk struct { - /* Layout: every menu draw in the codebase uses - * GFX_DISPLAY_PRIM_TRIANGLESTRIP, so this driver only keeps - * STRIP variants: + /* Layout: every menu draw uses a triangle-strip topology, so this + * driver only keeps STRIP variants: * [0] alpha_blend, no blend * [1] alpha_blend, blend * [2] ribbon @@ -309,11 +308,9 @@ typedef struct vk * [5] snow * [6] bokeh * [7] snowflake - * All entries are TRIANGLE_STRIP topology. The history of - * this array previously included parallel TRIANGLE_LIST - * variants in even slots, but no caller ever set prim_type to - * anything other than TRIANGLESTRIP, so the LIST pipelines - * were built and never used. */ + * All entries are TRIANGLE_STRIP topology. The history of this + * array previously included parallel TRIANGLE_LIST variants in + * even slots; they were built at init and never used. */ VkPipeline pipelines[8]; #ifdef VULKAN_HDR_SWAPCHAIN VkPipeline pipelines_sdr[8]; /* SDR offscreen variants, same layout */ @@ -1893,7 +1890,6 @@ static void gfx_display_vk_draw_pipeline( + 3 * sizeof(float), &yflip, sizeof(yflip)); draw->coords = &blank_coords; blank_coords.vertices = 4; - draw->prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; break; } diff --git a/gfx/gfx_display.c b/gfx/gfx_display.c index 19200dcc541f..d175f2db4920 100644 --- a/gfx/gfx_display.c +++ b/gfx/gfx_display.c @@ -520,7 +520,6 @@ void gfx_display_draw_quad( draw.texture = (texture && *texture) ? *texture : gfx_white_texture; - draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; draw.pipeline_id = 0; draw.scale_factor = 1.0f; draw.rotation = 0.0f; @@ -651,7 +650,6 @@ void gfx_display_draw_texture_slice( draw.height = height; draw.coords = &coords; draw.matrix_data = mymat; - draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; draw.pipeline_id = 0; coords.color = (const float*)(color == NULL ? colors : color); @@ -914,7 +912,6 @@ void gfx_display_draw_cursor( draw.coords = &coords; draw.matrix_data = NULL; draw.texture = texture; - draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; draw.pipeline_id = 0; draw.scale_factor = 1.0f; draw.rotation = 0.0f; diff --git a/gfx/gfx_display.h b/gfx/gfx_display.h index 0706f973d36d..cafd9db61c4c 100644 --- a/gfx/gfx_display.h +++ b/gfx/gfx_display.h @@ -83,13 +83,6 @@ enum menu_driver_id_type MENU_DRIVER_ID_XMB }; -enum gfx_display_prim_type -{ - GFX_DISPLAY_PRIM_NONE = 0, - GFX_DISPLAY_PRIM_TRIANGLESTRIP, - GFX_DISPLAY_PRIM_TRIANGLES -}; - enum gfx_display_driver_type { GFX_VIDEO_DRIVER_GENERIC = 0, @@ -165,7 +158,6 @@ struct gfx_display_ctx_draw float y; float rotation; float scale_factor; - enum gfx_display_prim_type prim_type; bool pipeline_active; }; diff --git a/gfx/gfx_thumbnail.c b/gfx/gfx_thumbnail.c index 624a7238652c..e2562592dcf1 100644 --- a/gfx/gfx_thumbnail.c +++ b/gfx/gfx_thumbnail.c @@ -1102,7 +1102,6 @@ void gfx_thumbnail_draw( draw.coords = &coords; draw.matrix_data = &mymat; draw.texture = thumb_texture; - draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; draw.pipeline_id = 0; /* Set thumbnail alignment within bounding box */ diff --git a/gfx/gfx_widgets.c b/gfx/gfx_widgets.c index 2b7ff979e0f0..62e2babcd9e7 100644 --- a/gfx/gfx_widgets.c +++ b/gfx/gfx_widgets.c @@ -721,7 +721,6 @@ void gfx_widgets_draw_icon( draw.coords = &coords; draw.matrix_data = &mymat; draw.texture = texture; - draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; draw.pipeline_id = 0; if (draw.height > 0 && draw.width > 0) diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c index e4e5a31def19..3f1989afda0e 100644 --- a/menu/drivers/materialui.c +++ b/menu/drivers/materialui.c @@ -2634,7 +2634,6 @@ static void materialui_draw_icon( draw.coords = &coords; draw.matrix_data = mymat; draw.texture = texture; - draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; draw.pipeline_id = 0; if (dispctx) @@ -6203,7 +6202,6 @@ static void materialui_render_background( draw.height = video_height; draw.coords = NULL; draw.matrix_data = NULL; - draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; draw.vertex = NULL; draw.tex_coord = NULL; draw.vertex_count = 4; diff --git a/menu/drivers/ozone.c b/menu/drivers/ozone.c index 916664fe4645..024c59db2679 100644 --- a/menu/drivers/ozone.c +++ b/menu/drivers/ozone.c @@ -3089,7 +3089,6 @@ static void ozone_draw_icon( draw.coords = &coords; draw.matrix_data = mymat; draw.texture = texture; - draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; draw.pipeline_id = 0; if (draw.height > 0 && draw.width > 0) diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 66c9cc4eeb53..bd6a2c63b572 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -1047,7 +1047,6 @@ static void xmb_draw_icon( draw.coords = &coords; draw.matrix_data = &mymat_tmp; draw.texture = texture; - draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; draw.pipeline_id = 0; if (shadows_enable) @@ -7574,7 +7573,6 @@ static void xmb_draw_bg( draw.vertex = NULL; draw.tex_coord = NULL; draw.vertex_count = 4; - draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; draw.pipeline_id = 0; draw.pipeline_active = (menu_shader_pipeline == XMB_SHADER_PIPELINE_WALLPAPER) ? false : true; @@ -7683,7 +7681,6 @@ static void xmb_draw_dark_layer( draw.tex_coord = NULL; draw.vertex_count = 4; draw.texture = 0; - draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP; draw.pipeline_id = 0; draw.pipeline_active = false; From 2dbccdbdf1fed63a026645b04c3acdc18d58c55f Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-SPFP6AQ\\twistedtechre" Date: Thu, 30 Apr 2026 03:29:33 +0200 Subject: [PATCH 13/14] gfx/drivers/vulkan: drop dead indexed_quads field and branch vk_draw_triangles' indexed_quads field was a code path for indexed quad drawing via the shared quad_ibo (vk->quad_ibo). It was never exercised on master: - Both call sites in gfx_display_vk_draw set call.indexed_quads to false (L1995, L2027 before this commit). - The if (call->indexed_quads && ...) branch in vulkan_draw_triangles was therefore unreachable. - The font path used to take this branch via vulkan_font_flush(), but that helper was inlined into vulkan_font_render_msg, where the indexed draw is now issued directly. The "always true for fonts" comment in vulkan_font_render_msg was documenting the pre-inlining state and survived as a stale reference. Remove: - bool indexed_quads from struct vk_draw_triangles - the two call.indexed_quads = false; assignments in gfx_display_vk_draw - the dead if/else in vulkan_draw_triangles, leaving the single vkCmdDraw that the live (else) branch always took - the obsolete "the runtime branch on indexed_quads" bullet in the vulkan_font_render_msg flush comment The shared quad_ibo (vk->quad_ibo) itself stays -- it is still consumed by vulkan_font_render_msg's inlined draw path and by vulkan_draw_quad (the menu compositing path) at L5965 and L5982. This commit only removes its dead-on-arrival use through the generic vulkan_draw_triangles dispatch. Effects: - struct vk_draw_triangles loses 1 byte + alignment padding (typically 4 bytes after the trailing unsigned). The struct is stack-allocated; no heap layout concerns. - vulkan_draw_triangles loses an unreachable branch and an IBO capacity check that always saw num_quads = 0. Verification: - clang -fsyntax-only -Wall on three configurations (HDR + SP, no HDR + SP, no HDR + no SP): all clean. - Brace and paren balance preserved against master. - Diff is +1/-30 lines. --- gfx/drivers/vulkan.c | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 66f5aa60f836..c9b99a1646c6 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -215,10 +215,6 @@ struct vk_draw_triangles VkSampler sampler; /* ptr alignment */ size_t uniform_size; unsigned vertices; - /* When true, vertices are groups of 4 (quads) and will be - * drawn with the shared index buffer via vkCmdDrawIndexed. - * When false, vertices are drawn directly via vkCmdDraw. */ - bool indexed_quads; }; typedef struct vk @@ -958,29 +954,7 @@ static void vulkan_draw_triangles(vk_t *vk, const struct vk_draw_triangles *call vkCmdBindVertexBuffers(vk->cmd, 0, 1, &call->vbo->buffer, &call->vbo->offset); - /* Use indexed draw for quad-based geometry. - * Quads use 4 vertices each with the shared index buffer, - * saving 33% VBO bandwidth compared to 6 vertices per quad. */ - if (call->indexed_quads && vk->quad_ibo.buffer != VK_NULL_HANDLE) - { - unsigned num_quads = call->vertices / 4; - /* Guard against exceeding IBO capacity to prevent - * out-of-bounds index reads - * (VUID-vkCmdDrawIndexed-indexSize-00463). */ - if (num_quads <= vk->quad_ibo.num_quads) - { - unsigned index_count = num_quads * 6; - vkCmdBindIndexBuffer(vk->cmd, vk->quad_ibo.buffer, - 0, VK_INDEX_TYPE_UINT16); - vkCmdDrawIndexed(vk->cmd, index_count, 1, 0, 0, 0); - } - else - vkCmdDraw(vk->cmd, call->vertices, 1, 0, 0); - } - else - { - vkCmdDraw(vk->cmd, call->vertices, 1, 0, 0); - } + vkCmdDraw(vk->cmd, call->vertices, 1, 0, 0); } @@ -2018,7 +1992,6 @@ static void gfx_display_vk_draw(gfx_display_ctx_draw_t *draw, call.uniform_size = draw->backend_data_size; call.vbo = ⦥ call.vertices = draw->coords->vertices; - call.indexed_quads = false; vulkan_draw_triangles(vk, &call); } @@ -2051,7 +2024,6 @@ static void gfx_display_vk_draw(gfx_display_ctx_draw_t *draw, call.uniform_size = sizeof(math_matrix_4x4); call.vbo = ⦥ call.vertices = draw->coords->vertices; - call.indexed_quads = false; vulkan_draw_triangles(vk, &call); } @@ -2536,7 +2508,6 @@ static void vulkan_font_render_msg( * Vulkan commands directly we eliminate: * - packing/unpacking through struct vk_draw_triangles * - the generic vulkan_draw_triangles() indirection - * - the runtime branch on indexed_quads (always true for fonts) * - the null-check on texture->image (always valid for fonts) */ From 33f3aba66996242a7942b733129c6340f824184d Mon Sep 17 00:00:00 2001 From: Eric Warmenhoven Date: Wed, 29 Apr 2026 22:06:54 -0400 Subject: [PATCH 14/14] tvos: fix appstore submission --- pkg/apple/make-frameworks.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/apple/make-frameworks.sh b/pkg/apple/make-frameworks.sh index b40ddf7a3f49..1467f22be1bd 100755 --- a/pkg/apple/make-frameworks.sh +++ b/pkg/apple/make-frameworks.sh @@ -114,6 +114,14 @@ MVK_PLATFORM_SUBDIR="${SWIFT_PLATFORM_TARGET_PREFIX}-$(echo $ARCHS_STANDARD_64_B if [ -d "${MOLTENVK_XCFRAMEWORK}/${MVK_PLATFORM_SUBDIR}/MoltenVK.framework" ] ; then echo copying moltenvk from "${MOLTENVK_XCFRAMEWORK}/${MVK_PLATFORM_SUBDIR}/MoltenVK.framework" cp -R "${MOLTENVK_XCFRAMEWORK}/${MVK_PLATFORM_SUBDIR}/MoltenVK.framework" "${OUTDIR}" + # tvOS App Store rejects arm64e; strip it from the fat MoltenVK binary + if [ "$PLATFORM_FAMILY_NAME" = "tvOS" -a "$APPSTORE_BUILD" = "1" ] ; then + MVK_BIN="${OUTDIR}/MoltenVK.framework/MoltenVK" + if lipo -info "$MVK_BIN" 2>/dev/null | grep -q arm64e ; then + echo "stripping arm64e from MoltenVK for tvOS App Store build" + lipo -remove arm64e "$MVK_BIN" -output "$MVK_BIN" + fi + fi codesign --force --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${OUTDIR}/MoltenVK.framework" fi