GFX: Remove fake context driver workaround from D3D/Metal

D3D9 Cg, D3D9 HLSL, D3D10, D3D11, D3D12, and Metal each had
a static gfx_ctx_driver_t installed during init so that
video_context_driver_get_flags() would return valid flags.
These drivers provide flags through their poke interface, not
through a context driver, but video_context_driver_get_flags()
only checked the context driver.

This affected any code path calling the function — shader
preset loading, Shaders menu visibility, shader type
validation, and shader manager initialization.

Fix: make video_context_driver_get_flags() merge flags from
both sources — context driver first, then OR in poke flags.

For GL/Vulkan: the context driver provides platform flags
(shader types, adaptive vsync, core context) and the poke
interface provides driver flags (hard sync, BFI, screenshots).
Both sets are now returned together.

For D3D/Metal: no context driver exists, so context flags are
empty.  The poke interface provides all flags.  This is what
the fake context was simulating.

With this change, the fake context workaround is unnecessary:

  video_driver.c:
    - video_context_driver_get_flags merges both flag sources
    - Shader preset loading moved from driver init to
      video_driver_init_internal, after poke registration
    - Guarded by !current_video_context.get_flags (skips
      GL/Vulkan which load shaders via real context driver)
    - Guarded by non-empty preset path (avoids pointless
      device reinit on D3D9 for NULL path)

  D3D9 Cg, D3D9 HLSL, D3D10, D3D11, D3D12:
    - Removed static fake_context variable
    - Removed fake context setup + shader loading from init

  Metal:
    - Removed 45-line fake context struct
    - Removed no-op metal_ctx_swap_interval
    - Removed fake context setup + shader loading from init
    - Direct metal_ctx_swap_buffers(NULL) call replaces
      indirect metal_fake_context.swap_buffers(NULL)
    - Removed unused shader_path variable

Note: D3D9 HLSL/Cg crash when toggling threaded video.
This is pre-existing and unrelated to this change.
This commit is contained in:
U-DESKTOP-SPFP6AQ\twistedtechre committed 2026-04-16 20:52:39 +02:00
1 parent f1b44d30d5
commit be2d747d31
7 files changed
+57 -129

No files matched your search

-12
View File
@@ -287,8 +287,6 @@ typedef struct
} d3d10_video_t;
/* Temporary workaround for d3d10 not being able to poll flags during init */
static gfx_ctx_driver_t d3d10_fake_context;
static uint32_t d3d10_get_flags(void *data);
#if defined(HAVE_DYLIB) && !defined(__WINRT__)
@@ -2661,16 +2659,6 @@ static void *d3d10_gfx_init(const video_info_t* video,
video->is_threaded,
FONT_DRIVER_RENDER_D3D10_API);
{
d3d10_fake_context.get_flags = d3d10_get_flags;
d3d10_fake_context.get_metrics = win32_get_metrics;
video_context_driver_set(&d3d10_fake_context);
#ifdef HAVE_SLANG
const char *shader_preset = video_shader_get_current_shader_preset();
enum rarch_shader_type type = video_shader_parse_type(shader_preset);
d3d10_gfx_set_shader(d3d10, type, shader_preset);
#endif
}
#if 0
if (video_driver_get_hw_context()->context_type == RETRO_HW_CONTEXT_D3D10)
-11
View File
@@ -433,8 +433,6 @@ typedef struct
#define D3D11_ROLLING_SCANLINE_SIMULATION
/* Temporary workaround for d3d11 not being able to poll flags during init */
static gfx_ctx_driver_t d3d11_fake_context;
static D3D11Device cached_device_d3d11;
static D3D_FEATURE_LEVEL cached_supportedFeatureLevel;
@@ -3690,15 +3688,6 @@ static void *d3d11_gfx_init(const video_info_t* video,
video->is_threaded,
FONT_DRIVER_RENDER_D3D11_API);
{
d3d11_fake_context.get_flags = d3d11_get_flags;
d3d11_fake_context.get_metrics = win32_get_metrics;
video_context_driver_set(&d3d11_fake_context);
const char *shader_preset = video_shader_get_current_shader_preset();
enum rarch_shader_type type = video_shader_parse_type(shader_preset);
d3d11_gfx_set_shader(d3d11, type, shader_preset);
}
if (video_driver_get_hw_context()->context_type == RETRO_HW_CONTEXT_D3D11)
{
d3d11->flags |= D3D11_ST_FLAG_HW_IFACE_ENABLE;
-12
View File
@@ -495,9 +495,6 @@ static D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_disable_desc = {
D3D12_COLOR_WRITE_ENABLE_ALL,
};
/* Temporary workaround for d3d12 not being able to poll flags during init */
static gfx_ctx_driver_t d3d12_fake_context;
#if defined(HAVE_DYLIB) && !defined(__WINRT__)
static dylib_t d3d12_dll;
@@ -4478,15 +4475,6 @@ static void *d3d12_gfx_init(const video_info_t* video,
video->is_threaded,
FONT_DRIVER_RENDER_D3D12_API);
{
d3d12_fake_context.get_flags = d3d12_get_flags;
d3d12_fake_context.get_metrics = win32_get_metrics;
video_context_driver_set(&d3d12_fake_context);
const char *shader_preset = video_shader_get_current_shader_preset();
enum rarch_shader_type type = video_shader_parse_type(shader_preset);
d3d12_gfx_set_shader(d3d12, type, shader_preset);
}
if (video_driver_get_hw_context()->context_type == RETRO_HW_CONTEXT_D3D12)
{
d3d12->flags |= D3D12_ST_FLAG_HW_IFACE_ENABLE;
-13
View File
@@ -395,9 +395,6 @@ static INLINE void d3d9_recompute_pass_sizes(
{ (WORD)(stream), (WORD)(offset * sizeof(float)), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, \
D3DDECLUSAGE_COLOR, (BYTE)(index) } \
/* TODO/FIXME - Temporary workaround for D3D9 not being able to poll flags during init */
static gfx_ctx_driver_t d3d9_cg_fake_context;
struct D3D9CGVertex
{
float x, y, z;
@@ -3894,16 +3891,6 @@ static bool d3d9_cg_init_internal(d3d9_video_t *d3d,
if (!d3d9_cg_initialize(d3d, &d3d->video_info))
return false;
d3d9_cg_fake_context.get_flags = d3d9_cg_get_flags;
d3d9_cg_fake_context.get_metrics = win32_get_metrics;
video_context_driver_set(&d3d9_cg_fake_context);
{
const char *shader_preset = video_shader_get_current_shader_preset();
enum rarch_shader_type type = video_shader_parse_type(shader_preset);
d3d9_cg_set_shader(d3d, type, shader_preset);
}
d3d_input_driver(settings->arrays.input_joypad_driver,
settings->arrays.input_joypad_driver, input, input_data);
-15
View File
@@ -376,9 +376,6 @@ static INLINE void d3d9_recompute_pass_sizes(
}
}
/* TODO/FIXME - Temporary workaround for D3D9 not being able to poll flags during init */
static gfx_ctx_driver_t d3d9_hlsl_fake_context;
/* =====================================================================
* SM3.0 CTAB (Constant Table) parser
*
@@ -7075,18 +7072,6 @@ static bool d3d9_hlsl_init_internal(d3d9_video_t *d3d,
if (!d3d9_hlsl_initialize(d3d, &d3d->video_info))
return false;
d3d9_hlsl_fake_context.get_flags = d3d9_hlsl_get_flags;
#ifndef _XBOX_
d3d9_hlsl_fake_context.get_metrics = win32_get_metrics;
#endif
video_context_driver_set(&d3d9_hlsl_fake_context);
{
const char *shader_preset = video_shader_get_current_shader_preset();
enum rarch_shader_type type = video_shader_parse_type(shader_preset);
d3d9_hlsl_set_shader(d3d, type, shader_preset);
}
d3d_input_driver(settings->arrays.input_joypad_driver,
settings->arrays.input_joypad_driver, input, input_data);
+1 -56
View File
@@ -2334,52 +2334,6 @@ static void metal_ctx_swap_buffers(void *data)
[md.context swapBuffers];
}
static void metal_ctx_swap_interval(void *data, int interval)
{
/* No-op: displaySyncEnabled is already set by metal_set_nonblock_state,
* and swap_interval is stored in metal_swap_interval for frame duplication. */
(void)data;
(void)interval;
}
static gfx_ctx_driver_t metal_fake_context = {
NULL, /* init */
NULL, /* destroy */
NULL, /* get_api */
NULL, /* bind_api */
metal_ctx_swap_interval, /* swap_interval */
NULL, /* set_video_mode */
NULL, /* get_video_size */
NULL, /* get_refresh_rate */
NULL, /* get_video_output_size */
NULL, /* get_video_output_prev */
NULL, /* get_video_output_next */
#ifdef HAVE_COCOATOUCH
metal_ctx_get_metrics,
#else
NULL,
#endif
NULL, /* translate_aspect */
NULL, /* update_title */
NULL, /* check_window */
NULL, /* set_resize */
NULL, /* has_focus */
NULL, /* suppress_screensaver */
false, /* has_windowed */
metal_ctx_swap_buffers, /* swap_buffers */
NULL, /* input_driver */
NULL, /* get_proc_address */
NULL, /* image_buffer_init */
NULL, /* image_buffer_write */
NULL, /* show_mouse */
"metal",
NULL, /* get_flags */
NULL, /* set_flags */
NULL,
NULL, /* get_context_data */
NULL /* make_current */
};
static bool metal_set_shader(void *data,
enum rarch_shader_type type, const char *path);
@@ -2388,7 +2342,6 @@ static void *metal_init(
input_driver_t **input,
void **input_data)
{
const char *shader_path;
MetalDriver *md = nil;
[apple_platform setViewType:APPLE_VIEW_TYPE_METAL];
@@ -2400,13 +2353,6 @@ static void *metal_init(
/* Store reference for context swap_buffers calls */
metal_ctx_data = (__bridge void *)md;
metal_fake_context.get_flags = metal_get_flags;
video_context_driver_set(&metal_fake_context);
shader_path = video_shader_get_current_shader_preset();
metal_set_shader((__bridge void *)md,
video_shader_parse_type(shader_path), shader_path);
return (__bridge_retained void *)md;
}
@@ -2439,8 +2385,7 @@ static bool metal_frame(void *data, const void *frame,
/* Call swap_buffers to acquire next drawable. This moves the blocking
* acquisition to AFTER presenting (like Vulkan), instead of BEFORE
* rendering. This is critical for proper 120Hz on ProMotion displays. */
if (metal_fake_context.swap_buffers)
metal_fake_context.swap_buffers(NULL);
metal_ctx_swap_buffers(NULL);
/* Frame duping for shader_subframes - present multiple times per core frame
* to match high refresh rate displays (e.g., 60fps core on 120Hz display).
+56 -10
View File
@@ -3429,19 +3429,40 @@ bool video_context_driver_get_ident(gfx_ctx_ident_t *ident)
bool video_context_driver_get_flags(gfx_ctx_flags_t *flags)
{
video_driver_state_t *video_st = &video_driver_st;
const gfx_ctx_driver_t *ctx = &video_st->current_video_context;
void *ctx_data = (void*)video_st->context_data;
if (!ctx->get_flags)
return false;
bool have_flags = false;
if (video_st->flags & VIDEO_FLAG_DEFERRED_VIDEO_CTX_DRIVER_SET_FLAGS)
/* Check the context driver (GL/Vulkan path). */
{
flags->flags = video_st->deferred_flag_data.flags;
video_st->flags &= ~VIDEO_FLAG_DEFERRED_VIDEO_CTX_DRIVER_SET_FLAGS;
const gfx_ctx_driver_t *ctx = &video_st->current_video_context;
void *ctx_data = (void*)video_st->context_data;
if (ctx->get_flags)
{
if (video_st->flags & VIDEO_FLAG_DEFERRED_VIDEO_CTX_DRIVER_SET_FLAGS)
{
flags->flags = video_st->deferred_flag_data.flags;
video_st->flags &= ~VIDEO_FLAG_DEFERRED_VIDEO_CTX_DRIVER_SET_FLAGS;
}
else
flags->flags = ctx->get_flags(ctx_data);
have_flags = true;
}
}
else
flags->flags = ctx->get_flags(ctx_data);
return true;
/* Merge in flags from the video driver's poke interface.
* D3D and Metal drivers provide all flags here (no context
* driver). GL drivers provide supplementary flags (hard
* sync, BFI, etc.) alongside the context driver's flags
* (shader types, adaptive vsync). */
{
const video_poke_interface_t *poke = video_st->poke;
if (poke && poke->get_flags)
{
flags->flags |= poke->get_flags(video_st->data);
have_flags = true;
}
}
return have_flags;
}
static bool video_driver_get_flags(gfx_ctx_flags_t *flags)
@@ -3896,6 +3917,31 @@ bool video_driver_init_internal(bool *video_is_threaded, bool verbosity_enabled)
video_st->current_video->poke_interface(
video_st->data, &video_st->poke);
/* Load the initial shader preset for drivers that don't
* load shaders during their own init(). GL and Vulkan
* drivers load shaders inside init() using their real
* context driver for flag queries. D3D and Metal drivers
* cannot do this because they don't have a context driver,
* so shader loading is deferred to here where the poke
* interface (which provides the same flags) is available.
*
* Previously each D3D/Metal driver installed a fake
* gfx_ctx_driver_t inside init() as a workaround.
* This centralized loading eliminates that workaround.
*
* The guard checks whether the context driver provides
* get_flags — if it does, the driver loaded its own
* shaders during init and we must not reload them here
* (which would tear down and rebuild the filter chain). */
if ( video_st->current_video->set_shader
&& !video_st->current_video_context.get_flags)
{
const char *shader_preset = video_shader_get_current_shader_preset();
enum rarch_shader_type type = video_shader_parse_type(shader_preset);
video_st->current_video->set_shader(
video_st->data, type, shader_preset);
}
if (video_st->current_video->viewport_info &&
(!custom_vp->width ||
!custom_vp->height))