Add shader hold hotkey and improve toggling logic (#17840)

This commit is contained in:
sonninnos 2025-05-08 00:56:59 +03:00 committed by GitHub
parent 0b547bdd49
commit 10738f532c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 261 additions and 82 deletions

View File

@ -488,6 +488,7 @@ static const struct cmd_map map[] = {
{ "DISK_PREV", RARCH_DISK_PREV },
{ "SHADER_TOGGLE", RARCH_SHADER_TOGGLE },
{ "SHADER_HOLD", RARCH_SHADER_HOLD },
{ "SHADER_NEXT", RARCH_SHADER_NEXT },
{ "SHADER_PREV", RARCH_SHADER_PREV },

View File

@ -472,6 +472,13 @@ static const struct retro_keybind retro_keybinds_1[] = {
RARCH_SHADER_TOGGLE, NO_BTN, NO_BTN, 0,
true
},
{
NULL, NULL,
AXIS_NONE, AXIS_NONE,
MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_HOLD, RETROK_UNKNOWN,
RARCH_SHADER_HOLD, NO_BTN, NO_BTN, 0,
true
},
{
NULL, NULL,
AXIS_NONE, AXIS_NONE,
@ -1114,6 +1121,13 @@ static const struct retro_keybind retro_keybinds_1[] = {
RARCH_SHADER_TOGGLE, NO_BTN, NO_BTN, 0,
true
},
{
NULL, NULL,
AXIS_NONE, AXIS_NONE,
MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_HOLD, RETROK_UNKNOWN,
RARCH_SHADER_HOLD, NO_BTN, NO_BTN, 0,
true
},
{
NULL, NULL,
AXIS_NONE, AXIS_NONE,
@ -1766,6 +1780,13 @@ static const struct retro_keybind retro_keybinds_1[] = {
RARCH_SHADER_TOGGLE, NO_BTN, NO_BTN, 0,
true
},
{
NULL, NULL,
AXIS_NONE, AXIS_NONE,
MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_HOLD, RETROK_UNKNOWN,
RARCH_SHADER_HOLD, NO_BTN, NO_BTN, 0,
true
},
{
NULL, NULL,
AXIS_NONE, AXIS_NONE,

View File

@ -373,6 +373,7 @@ const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = {
DECLARE_META_BIND(2, disk_prev, RARCH_DISK_PREV, MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_PREV),
DECLARE_META_BIND(2, shader_toggle, RARCH_SHADER_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_TOGGLE),
DECLARE_META_BIND(2, shader_hold, RARCH_SHADER_HOLD, MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_HOLD),
DECLARE_META_BIND(2, shader_next, RARCH_SHADER_NEXT, MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_NEXT),
DECLARE_META_BIND(2, shader_prev, RARCH_SHADER_PREV, MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_PREV),

View File

@ -73,6 +73,7 @@ typedef struct gl3
const gfx_ctx_driver_t *ctx_driver;
void *ctx_data;
gl3_filter_chain_t *filter_chain;
gl3_filter_chain_t *filter_chain_default;
GLuint *overlay_tex;
float *overlay_vertex_coord;
float *overlay_tex_coord;

View File

@ -551,6 +551,7 @@ struct vk_draw_triangles
typedef struct vk
{
vulkan_filter_chain_t *filter_chain;
vulkan_filter_chain_t *filter_chain_default;
vulkan_context_t *context;
void *ctx_data;
const gfx_ctx_driver_t *ctx_driver;

View File

@ -1004,6 +1004,7 @@ static uint32_t d3d11_get_flags(void *data)
#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_SLANG);
BIT32_SET(flags, GFX_CTX_FLAGS_SUBFRAME_SHADERS);
BIT32_SET(flags, GFX_CTX_FLAGS_FAST_TOGGLE_SHADERS);
#endif
return flags;
@ -3056,7 +3057,7 @@ static bool d3d11_gfx_frame(
texture = d3d11->frame.texture;
if (d3d11->shader_preset)
if (d3d11->shader_preset && video_info->shader_active)
{
for (i = 0; i < d3d11->shader_preset->passes; i++)
{

View File

@ -1152,6 +1152,7 @@ static uint32_t d3d12_get_flags(void *data)
#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_SLANG);
BIT32_SET(flags, GFX_CTX_FLAGS_SUBFRAME_SHADERS);
BIT32_SET(flags, GFX_CTX_FLAGS_FAST_TOGGLE_SHADERS);
#endif
return flags;
@ -3565,7 +3566,7 @@ static bool d3d12_gfx_frame(
texture = d3d12->frame.texture;
if (d3d12->shader_preset)
if (d3d12->shader_preset && video_info->shader_active)
{
cmd->lpVtbl->SetGraphicsRootSignature(cmd,
d3d12->desc.sl_rootSignature);

View File

@ -1332,6 +1332,10 @@ static void gl3_destroy_resources(gl3_t *gl)
gl3_filter_chain_free(gl->filter_chain);
gl->filter_chain = NULL;
if (gl->filter_chain_default)
gl3_filter_chain_free(gl->filter_chain_default);
gl->filter_chain_default = NULL;
glBindVertexArray(0);
if (gl->vao != 0)
glDeleteVertexArrays(1, &gl->vao);
@ -1710,14 +1714,17 @@ static bool gl3_init_default_filter_chain(gl3_t *gl)
if (!gl->ctx_driver)
return false;
gl->filter_chain = gl3_filter_chain_create_default(
if (gl->filter_chain_default)
return true;
gl->filter_chain_default = gl3_filter_chain_create_default(
gl->video_info.smooth
? GLSLANG_FILTER_CHAIN_LINEAR
: GLSLANG_FILTER_CHAIN_NEAREST);
if (!gl->filter_chain)
if (!gl->filter_chain_default)
{
RARCH_ERR("Failed to create filter chain.\n");
RARCH_ERR("[GLCore]: Failed to create default filter chain.\n");
return false;
}
@ -1726,6 +1733,9 @@ static bool gl3_init_default_filter_chain(gl3_t *gl)
static bool gl3_init_filter_chain_preset(gl3_t *gl, const char *shader_path)
{
if (!gl->ctx_driver)
return false;
gl->filter_chain = gl3_filter_chain_create_from_preset(
shader_path,
gl->video_info.smooth
@ -2107,7 +2117,7 @@ static void *gl3_init(const video_info_t *video,
if (!gl_check_error(&error_string))
{
RARCH_ERR("%s\n", error_string);
RARCH_ERR("[GLCore]: %s\n", error_string);
free(error_string);
goto error;
}
@ -2650,6 +2660,7 @@ static bool gl3_frame(void *data, const void *frame,
{
struct gl3_filter_chain_texture texture;
struct gl3_streamed_texture *streamed = NULL;
gl3_filter_chain_t *filter_chain = NULL;
gl3_t *gl = (gl3_t*)data;
unsigned width = video_info->width;
unsigned height = video_info->height;
@ -2734,26 +2745,44 @@ static bool gl3_frame(void *data, const void *frame,
texture.padded_width = streamed->width;
texture.padded_height = streamed->height;
}
gl3_filter_chain_set_frame_count(gl->filter_chain, frame_count);
/* Fast toggle shader filter chain logic */
filter_chain = gl->filter_chain;
if (!video_info->shader_active && gl->filter_chain != gl->filter_chain_default)
{
if (!gl->filter_chain_default)
gl3_init_default_filter_chain(gl);
if (gl->filter_chain_default)
filter_chain = gl->filter_chain_default;
else
return false;
}
if (!filter_chain && gl->filter_chain_default)
filter_chain = gl->filter_chain_default;
gl3_filter_chain_set_frame_count(filter_chain, frame_count);
#ifdef HAVE_REWIND
gl3_filter_chain_set_frame_direction(gl->filter_chain, state_manager_frame_is_reversed() ? -1 : 1);
gl3_filter_chain_set_frame_direction(filter_chain, state_manager_frame_is_reversed() ? -1 : 1);
#else
gl3_filter_chain_set_frame_direction(gl->filter_chain, 1);
gl3_filter_chain_set_frame_direction(filter_chain, 1);
#endif
gl3_filter_chain_set_frame_time_delta(gl->filter_chain, (uint32_t)video_driver_get_frame_time_delta_usec());
gl3_filter_chain_set_frame_time_delta(filter_chain, (uint32_t)video_driver_get_frame_time_delta_usec());
gl3_filter_chain_set_original_fps(gl->filter_chain, video_driver_get_original_fps());
gl3_filter_chain_set_original_fps(filter_chain, video_driver_get_original_fps());
gl3_filter_chain_set_rotation(gl->filter_chain, retroarch_get_rotation());
gl3_filter_chain_set_rotation(filter_chain, retroarch_get_rotation());
gl3_filter_chain_set_core_aspect(gl->filter_chain, video_driver_get_core_aspect());
gl3_filter_chain_set_core_aspect(filter_chain, video_driver_get_core_aspect());
/* OriginalAspectRotated: return 1/aspect for 90 and 270 rotated content */
uint32_t rot = retroarch_get_rotation();
float core_aspect_rot = video_driver_get_core_aspect();
if (rot == 1 || rot == 3)
core_aspect_rot = 1/core_aspect_rot;
gl3_filter_chain_set_core_aspect_rot(gl->filter_chain, core_aspect_rot);
gl3_filter_chain_set_core_aspect_rot(filter_chain, core_aspect_rot);
/* Sub-frame info for multiframe shaders (per real content frame).
Should always be 1 for non-use of subframes*/
@ -2765,13 +2794,13 @@ static bool gl3_frame(void *data, const void *frame,
|| video_info->runloop_is_paused
|| (gl->flags & GL3_FLAG_MENU_TEXTURE_ENABLE))
gl3_filter_chain_set_shader_subframes(
gl->filter_chain, 1);
filter_chain, 1);
else
gl3_filter_chain_set_shader_subframes(
gl->filter_chain, video_info->shader_subframes);
filter_chain, video_info->shader_subframes);
gl3_filter_chain_set_current_shader_subframe(
gl->filter_chain, 1);
filter_chain, 1);
}
#ifdef GL3_ROLLING_SCANLINE_SIMULATION
@ -2783,25 +2812,25 @@ static bool gl3_frame(void *data, const void *frame,
&& !video_info->runloop_is_paused
&& (!(gl->flags & GL3_FLAG_MENU_TEXTURE_ENABLE)))
gl3_filter_chain_set_simulate_scanline(
gl->filter_chain, true);
filter_chain, true);
else
gl3_filter_chain_set_simulate_scanline(
gl->filter_chain, false);
filter_chain, false);
#endif /* GL3_ROLLING_SCANLINE_SIMULATION */
gl3_filter_chain_set_input_texture(gl->filter_chain, &texture);
gl3_filter_chain_build_offscreen_passes(gl->filter_chain,
gl3_filter_chain_set_input_texture(filter_chain, &texture);
gl3_filter_chain_build_offscreen_passes(filter_chain,
&gl->filter_chain_vp);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
gl3_filter_chain_build_viewport_pass(gl->filter_chain,
gl3_filter_chain_build_viewport_pass(filter_chain,
&gl->filter_chain_vp,
(gl->flags & GL3_FLAG_HW_RENDER_BOTTOM_LEFT)
? gl->mvp.data
: gl->mvp_yflip.data);
gl3_filter_chain_end_frame(gl->filter_chain);
gl3_filter_chain_end_frame(filter_chain);
#ifdef HAVE_OVERLAY
if ((gl->flags & GL3_FLAG_OVERLAY_ENABLE) && overlay_behind_menu)
@ -2940,9 +2969,9 @@ static bool gl3_frame(void *data, const void *frame,
for (i = 1; i < (int) video_info->shader_subframes; i++)
{
gl3_filter_chain_set_shader_subframes(
gl->filter_chain, video_info->shader_subframes);
filter_chain, video_info->shader_subframes);
gl3_filter_chain_set_current_shader_subframe(
gl->filter_chain, i+1);
filter_chain, i+1);
if (!gl3_frame(gl, NULL, 0, 0, frame_count, 0, msg,
video_info))
@ -2975,6 +3004,7 @@ static uint32_t gl3_get_flags(void *data)
BIT32_SET(flags, GFX_CTX_FLAGS_SCREENSHOTS_SUPPORTED);
BIT32_SET(flags, GFX_CTX_FLAGS_OVERLAY_BEHIND_MENU_SUPPORTED);
BIT32_SET(flags, GFX_CTX_FLAGS_SUBFRAME_SHADERS);
BIT32_SET(flags, GFX_CTX_FLAGS_FAST_TOGGLE_SHADERS);
return flags;
}

View File

@ -2829,6 +2829,9 @@ static bool vulkan_init_default_filter_chain(vk_t *vk)
if (!vk->context)
return false;
if (vk->filter_chain_default)
return true;
info.device = vk->context->device;
info.gpu = vk->context->gpu;
info.memory_properties = &vk->context->memory_properties;
@ -2844,15 +2847,15 @@ static bool vulkan_init_default_filter_chain(vk_t *vk)
info.swapchain.render_pass = vk->render_pass;
info.swapchain.num_indices = vk->context->num_swapchain_images;
vk->filter_chain = vulkan_filter_chain_create_default(
vk->filter_chain_default = vulkan_filter_chain_create_default(
&info,
vk->video.smooth
? GLSLANG_FILTER_CHAIN_LINEAR
: GLSLANG_FILTER_CHAIN_NEAREST);
if (!vk->filter_chain)
if (!vk->filter_chain_default)
{
RARCH_ERR("Failed to create filter chain.\n");
RARCH_ERR("[Vulkan]: Failed to create default filter chain.\n");
return false;
}
@ -2901,6 +2904,9 @@ static bool vulkan_init_filter_chain_preset(vk_t *vk, const char *shader_path)
{
struct vulkan_filter_chain_create_info info;
if (!vk->context)
return false;
info.device = vk->context->device;
info.gpu = vk->context->gpu;
info.memory_properties = &vk->context->memory_properties;
@ -3106,6 +3112,9 @@ static void vulkan_free(void *data)
if (vk->filter_chain)
vulkan_filter_chain_free((vulkan_filter_chain_t*)vk->filter_chain);
if (vk->filter_chain_default)
vulkan_filter_chain_free((vulkan_filter_chain_t*)vk->filter_chain_default);
#ifdef VULKAN_HDR_SWAPCHAIN
if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT)
{
@ -3647,10 +3656,10 @@ static void vulkan_check_swapchain(vk_t *vk)
filter_info.num_indices = vk->context->num_swapchain_images;
if (
!vulkan_filter_chain_update_swapchain_info(
(vulkan_filter_chain_t*)vk->filter_chain,
(vk->filter_chain) ? vk->filter_chain : vk->filter_chain_default,
&filter_info)
)
RARCH_ERR("Failed to update filter chain info. This will probably lead to a crash ...\n");
RARCH_ERR("[Vulkan]: Failed to update filter chain info.\n");
}
static void vulkan_set_nonblock_state(void *data, bool state,
@ -4365,6 +4374,7 @@ static bool vulkan_frame(void *data, const void *frame,
VkCommandBufferBeginInfo begin_info;
VkSemaphore signal_semaphores[2];
vk_t *vk = (vk_t*)data;
vulkan_filter_chain_t *filter_chain = NULL;
bool waits_for_semaphores = false;
unsigned width = video_info->width;
unsigned height = video_info->height;
@ -4391,11 +4401,29 @@ static bool vulkan_frame(void *data, const void *frame,
unsigned swapchain_index =
vk->context->current_swapchain_index;
bool overlay_behind_menu = video_info->overlay_behind_menu;
bool use_main_buffer = true;
/* Fast toggle shader filter chain logic */
filter_chain = vk->filter_chain;
if (!video_info->shader_active && vk->filter_chain != vk->filter_chain_default)
{
if (!vk->filter_chain_default)
vulkan_init_default_filter_chain(vk);
if (vk->filter_chain_default)
filter_chain = vk->filter_chain_default;
else
return false;
}
if (!filter_chain && vk->filter_chain_default)
filter_chain = vk->filter_chain_default;
#ifdef VULKAN_HDR_SWAPCHAIN
bool use_main_buffer =
use_main_buffer =
( vk->context->flags & VK_CTX_FLAG_HDR_ENABLE)
&& (!vk->filter_chain || !vulkan_filter_chain_emits_hdr10(vk->filter_chain));
&& (!filter_chain || !vulkan_filter_chain_emits_hdr10(filter_chain));
#endif /* VULKAN_HDR_SWAPCHAIN */
/* Bookkeeping on start of frame. */
@ -4516,9 +4544,9 @@ static bool vulkan_frame(void *data, const void *frame,
/* Notify filter chain about the new sync index. */
vulkan_filter_chain_notify_sync_index(
(vulkan_filter_chain_t*)vk->filter_chain, frame_index);
(vulkan_filter_chain_t*)filter_chain, frame_index);
vulkan_filter_chain_set_frame_count(
(vulkan_filter_chain_t*)vk->filter_chain, frame_count);
(vulkan_filter_chain_t*)filter_chain, frame_count);
/* Sub-frame info for multiframe shaders (per real content frame).
Should always be 1 for non-use of subframes*/
@ -4531,13 +4559,13 @@ static bool vulkan_frame(void *data, const void *frame,
|| (vk->context->swap_interval > 1)
|| (vk->flags & VK_FLAG_MENU_ENABLE))
vulkan_filter_chain_set_shader_subframes(
(vulkan_filter_chain_t*)vk->filter_chain, 1);
(vulkan_filter_chain_t*)filter_chain, 1);
else
vulkan_filter_chain_set_shader_subframes(
(vulkan_filter_chain_t*)vk->filter_chain, video_info->shader_subframes);
(vulkan_filter_chain_t*)filter_chain, video_info->shader_subframes);
vulkan_filter_chain_set_current_shader_subframe(
(vulkan_filter_chain_t*)vk->filter_chain, 1);
(vulkan_filter_chain_t*)filter_chain, 1);
}
#ifdef VULKAN_ROLLING_SCANLINE_SIMULATION
@ -4551,32 +4579,32 @@ static bool vulkan_frame(void *data, const void *frame,
&& (!(vk->flags & VK_FLAG_MENU_ENABLE))
&& !(vk->context->swap_interval > 1))
vulkan_filter_chain_set_simulate_scanline(
(vulkan_filter_chain_t*)vk->filter_chain, true);
(vulkan_filter_chain_t*)filter_chain, true);
else
vulkan_filter_chain_set_simulate_scanline(
(vulkan_filter_chain_t*)vk->filter_chain, false);
(vulkan_filter_chain_t*)filter_chain, false);
#endif /* VULKAN_ROLLING_SCANLINE_SIMULATION */
#ifdef HAVE_REWIND
vulkan_filter_chain_set_frame_direction(
(vulkan_filter_chain_t*)vk->filter_chain,
(vulkan_filter_chain_t*)filter_chain,
state_manager_frame_is_reversed() ? -1 : 1);
#else
vulkan_filter_chain_set_frame_direction(
(vulkan_filter_chain_t*)vk->filter_chain,
(vulkan_filter_chain_t*)filter_chain,
1);
#endif
vulkan_filter_chain_set_frame_time_delta(
(vulkan_filter_chain_t*)vk->filter_chain, (uint32_t)video_driver_get_frame_time_delta_usec());
(vulkan_filter_chain_t*)filter_chain, (uint32_t)video_driver_get_frame_time_delta_usec());
vulkan_filter_chain_set_original_fps(
(vulkan_filter_chain_t*)vk->filter_chain, video_driver_get_original_fps());
(vulkan_filter_chain_t*)filter_chain, video_driver_get_original_fps());
vulkan_filter_chain_set_rotation(
(vulkan_filter_chain_t*)vk->filter_chain, retroarch_get_rotation());
(vulkan_filter_chain_t*)filter_chain, retroarch_get_rotation());
vulkan_filter_chain_set_core_aspect(
(vulkan_filter_chain_t*)vk->filter_chain, video_driver_get_core_aspect());
(vulkan_filter_chain_t*)filter_chain, video_driver_get_core_aspect());
/* OriginalAspectRotated: return 1/aspect for 90 and 270 rotated content */
uint32_t rot = retroarch_get_rotation();
@ -4584,7 +4612,7 @@ static bool vulkan_frame(void *data, const void *frame,
if (rot == 1 || rot == 3)
core_aspect_rot = 1/core_aspect_rot;
vulkan_filter_chain_set_core_aspect_rot(
(vulkan_filter_chain_t*)vk->filter_chain, core_aspect_rot);
(vulkan_filter_chain_t*)filter_chain, core_aspect_rot);
/* Render offscreen filter chain passes. */
{
@ -4648,13 +4676,13 @@ static bool vulkan_frame(void *data, const void *frame,
}
vulkan_filter_chain_set_input_texture((vulkan_filter_chain_t*)
vk->filter_chain, &input);
filter_chain, &input);
}
vulkan_set_viewport(vk, width, height, false, true);
vulkan_filter_chain_build_offscreen_passes(
(vulkan_filter_chain_t*)vk->filter_chain,
(vulkan_filter_chain_t*)filter_chain,
vk->cmd, &vk->vk_vp);
#if defined(HAVE_MENU)
@ -4712,7 +4740,7 @@ static bool vulkan_frame(void *data, const void *frame,
vkCmdBeginRenderPass(vk->cmd, &rp_info, VK_SUBPASS_CONTENTS_INLINE);
vulkan_filter_chain_build_viewport_pass(
(vulkan_filter_chain_t*)vk->filter_chain, vk->cmd,
(vulkan_filter_chain_t*)filter_chain, vk->cmd,
&vk->vk_vp, vk->mvp.data);
#ifdef HAVE_OVERLAY
@ -4802,7 +4830,7 @@ static bool vulkan_frame(void *data, const void *frame,
/* End the filter chain frame.
* This must happen outside a render pass.
*/
vulkan_filter_chain_end_frame((vulkan_filter_chain_t*)vk->filter_chain, vk->cmd);
vulkan_filter_chain_end_frame((vulkan_filter_chain_t*)filter_chain, vk->cmd);
if (
(backbuffer->image != VK_NULL_HANDLE)
@ -5115,9 +5143,9 @@ static bool vulkan_frame(void *data, const void *frame,
for (j = 1; j < (int) video_info->shader_subframes; j++)
{
vulkan_filter_chain_set_shader_subframes(
(vulkan_filter_chain_t*)vk->filter_chain, video_info->shader_subframes);
(vulkan_filter_chain_t*)filter_chain, video_info->shader_subframes);
vulkan_filter_chain_set_current_shader_subframe(
(vulkan_filter_chain_t*)vk->filter_chain, j+1);
(vulkan_filter_chain_t*)filter_chain, j+1);
if (!vulkan_frame(vk, NULL, 0, 0, frame_count, 0, msg,
video_info))
{
@ -5466,6 +5494,7 @@ static uint32_t vulkan_get_flags(void *data)
BIT32_SET(flags, GFX_CTX_FLAGS_SCREENSHOTS_SUPPORTED);
BIT32_SET(flags, GFX_CTX_FLAGS_OVERLAY_BEHIND_MENU_SUPPORTED);
BIT32_SET(flags, GFX_CTX_FLAGS_SUBFRAME_SHADERS);
BIT32_SET(flags, GFX_CTX_FLAGS_FAST_TOGGLE_SHADERS);
return flags;
}

View File

@ -248,7 +248,8 @@ enum display_flags
GFX_CTX_FLAGS_SCREENSHOTS_SUPPORTED,
GFX_CTX_FLAGS_OVERLAY_BEHIND_MENU_SUPPORTED,
GFX_CTX_FLAGS_CRT_SWITCHRES,
GFX_CTX_FLAGS_SUBFRAME_SHADERS
GFX_CTX_FLAGS_SUBFRAME_SHADERS,
GFX_CTX_FLAGS_FAST_TOGGLE_SHADERS
};
enum shader_uniform_type

View File

@ -2818,6 +2818,7 @@ void video_driver_build_info(video_frame_info_t *video_info)
#ifdef HAVE_MENU
struct menu_state *menu_st = menu_state_get_ptr();
#endif
uint8_t menu_shdr_flags = 0;
#ifdef HAVE_GFX_WIDGETS
dispgfx_widget_t *p_dispwidget = dispwidget_get_ptr();
#endif
@ -2826,6 +2827,12 @@ void video_driver_build_info(video_frame_info_t *video_info)
VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st);
VIDEO_DRIVER_THREADED_LOCK(video_st, is_threaded);
#endif
#ifdef HAVE_MENU
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
menu_shdr_flags = menu_shader_get()->flags;
#endif
#endif
custom_vp = &settings->video_vp_custom;
#ifdef HAVE_GFX_WIDGETS
@ -2896,6 +2903,7 @@ void video_driver_build_info(video_frame_info_t *video_info)
video_info->scale_width = video_st->scale_width;
video_info->scale_height = video_st->scale_height;
video_info->shader_active = !(menu_shdr_flags & SHDR_FLAG_DISABLED) ? true : false;
video_info->hdr_enable = settings->bools.video_hdr_enable;
video_info->libretro_running = false;

View File

@ -494,6 +494,7 @@ typedef struct video_frame_info
bool hdr_enable;
bool overlay_behind_menu;
bool scan_subframes;
bool shader_active;
} video_frame_info_t;
typedef void (*update_window_title_cb)(void*);

View File

@ -3140,27 +3140,41 @@ const char *video_shader_get_current_shader_preset(void)
return NULL;
}
void video_shader_toggle(settings_t *settings)
void video_shader_toggle(settings_t *settings, bool write)
{
bool toggle = !settings->bools.video_shader_enable;
bool enabled = settings->bools.video_shader_enable;
#ifdef HAVE_MENU
struct video_shader *menu_shdr = menu_shader_get();
struct menu_state *menu_st = menu_state_get_ptr();
menu_shdr->flags |= SHDR_FLAG_MODIFIED;
if (toggle)
menu_shdr->flags &= ~SHDR_FLAG_MODIFIED;
menu_shdr->flags &= ~SHDR_FLAG_TEMPORARY;
#endif
/* Cold start from hotkey requires enabling shaders initially */
if (!write && !enabled)
{
write = true;
enabled = true;
configuration_set_bool(settings, settings->bools.video_shader_enable, true);
}
#ifdef HAVE_MENU
else if (!write)
enabled = (menu_shdr->flags & SHDR_FLAG_DISABLED);
#endif
#ifdef HAVE_MENU
if (enabled)
menu_shdr->flags &= ~SHDR_FLAG_DISABLED;
else
menu_shdr->flags |= SHDR_FLAG_DISABLED;
if (!write && video_driver_test_all_flags(GFX_CTX_FLAGS_FAST_TOGGLE_SHADERS))
menu_shdr->flags |= SHDR_FLAG_TEMPORARY;
menu_st->flags |= MENU_ST_FLAG_ENTRIES_NEED_REFRESH
| MENU_ST_FLAG_PREVENT_POPULATE;
#endif
command_event(CMD_EVENT_SHADERS_APPLY_CHANGES, NULL);
/* TODO/FIXME: Due to general_write_handler being called twice,
* this has be done in this order in order to truly disable */
if (!toggle)
configuration_set_bool(settings, settings->bools.video_shader_enable, toggle);
}

View File

@ -88,7 +88,8 @@ enum video_shader_flags
/* Indicative of whether shader was modified -
* for instance from the menus */
SHDR_FLAG_MODIFIED = (1 << 1),
SHDR_FLAG_DISABLED = (1 << 2)
SHDR_FLAG_DISABLED = (1 << 2),
SHDR_FLAG_TEMPORARY = (1 << 3)
};
enum gfx_wrap_type
@ -289,7 +290,7 @@ bool video_shader_apply_shader(
const char *video_shader_get_preset_extension(enum rarch_shader_type type);
void video_shader_toggle(settings_t *settings);
void video_shader_toggle(settings_t *settings, bool write);
RETRO_END_DECLS

View File

@ -155,6 +155,7 @@ enum
RARCH_DISK_PREV,
RARCH_SHADER_TOGGLE,
RARCH_SHADER_HOLD,
RARCH_SHADER_NEXT,
RARCH_SHADER_PREV,

View File

@ -4039,6 +4039,14 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_META_SHADER_TOGGLE,
"Switches the currently selected shader on/off."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_HOLD,
"Shaders (Hold)"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_META_SHADER_HOLD,
"Keeps the currently selected shader on/off while key is pressed."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_NEXT,
"Next Shader"

View File

@ -451,6 +451,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_disk_next, ME
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_disk_prev, MENU_ENUM_SUBLABEL_INPUT_META_DISK_PREV)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_shader_toggle, MENU_ENUM_SUBLABEL_INPUT_META_SHADER_TOGGLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_shader_hold, MENU_ENUM_SUBLABEL_INPUT_META_SHADER_HOLD)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_shader_next, MENU_ENUM_SUBLABEL_INPUT_META_SHADER_NEXT)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_shader_prev, MENU_ENUM_SUBLABEL_INPUT_META_SHADER_PREV)
#ifdef HAVE_CHEATS
@ -2383,6 +2384,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case RARCH_SHADER_TOGGLE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_meta_shader_toggle);
return 0;
case RARCH_SHADER_HOLD:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_meta_shader_hold);
return 0;
case RARCH_CHEAT_TOGGLE:
#ifdef HAVE_CHEATS

View File

@ -2873,15 +2873,31 @@ void menu_shader_manager_apply_changes(
const char *dir_menu_config)
{
enum rarch_shader_type type = RARCH_SHADER_NONE;
settings_t *settings = config_get_ptr();
if (!shader)
return;
type = menu_shader_manager_get_type(shader);
/* Allow cold start from hotkey */
if ( type == RARCH_SHADER_NONE
&& settings->bools.video_shader_enable
&& !(shader->flags & SHDR_FLAG_DISABLED))
{
const char *preset = video_shader_get_current_shader_preset();
enum rarch_shader_type type = video_shader_parse_type(preset);
video_shader_apply_shader(settings, type, preset, false);
return;
}
/* Temporary state does not save anything */
if (shader->flags & SHDR_FLAG_TEMPORARY)
return;
if ( shader->passes
&& (type != RARCH_SHADER_NONE)
&& (!(shader->flags & SHDR_FLAG_DISABLED)))
&& type != RARCH_SHADER_NONE
&& !(shader->flags & SHDR_FLAG_DISABLED))
{
menu_shader_manager_save_preset(shader, NULL,
dir_video_shader, dir_menu_config, true);
@ -2889,6 +2905,9 @@ void menu_shader_manager_apply_changes(
}
menu_shader_manager_set_preset(NULL, type, NULL, true);
/* Reinforce disabled state on failure */
configuration_set_bool(settings, settings->bools.video_shader_enable, false);
}
static bool menu_shader_manager_save_preset_internal(

View File

@ -8136,7 +8136,8 @@ static void general_write_handler(rarch_setting_t *setting)
{
case MENU_ENUM_LABEL_VIDEO_SHADERS_ENABLE:
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
video_shader_toggle(settings);
video_shader_toggle(settings, true);
configuration_set_bool(settings, settings->bools.video_shader_enable, *setting->value.target.boolean);
#endif
break;
case MENU_ENUM_LABEL_VIDEO_THREADED:

View File

@ -1140,6 +1140,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_PREV,
MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_TOGGLE,
MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_HOLD,
MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_NEXT,
MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_PREV,
@ -1240,6 +1241,7 @@ enum msg_hash_enums
MENU_ENUM_SUBLABEL_INPUT_META_DISK_PREV,
MENU_ENUM_SUBLABEL_INPUT_META_SHADER_TOGGLE,
MENU_ENUM_SUBLABEL_INPUT_META_SHADER_HOLD,
MENU_ENUM_SUBLABEL_INPUT_META_SHADER_NEXT,
MENU_ENUM_SUBLABEL_INPUT_META_SHADER_PREV,

View File

@ -3091,9 +3091,23 @@ bool command_event(enum event_command cmd, void *data)
break;
case CMD_EVENT_SHADER_TOGGLE:
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
video_shader_toggle(settings);
video_shader_toggle(settings, false);
#endif
break;
case CMD_EVENT_SHADER_PRESET_LOADED:
ui_companion_event_command(cmd);
break;
case CMD_EVENT_SHADERS_APPLY_CHANGES:
#ifdef HAVE_MENU
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
menu_shader_manager_apply_changes(menu_shader_get(),
settings->paths.directory_video_shader,
settings->paths.directory_menu_config
);
#endif
#endif
ui_companion_event_command(cmd);
break;
case CMD_EVENT_AI_SERVICE_TOGGLE:
{
#ifdef HAVE_TRANSLATE
@ -3645,6 +3659,16 @@ bool command_event(enum event_command cmd, void *data)
runloop_st->runtime_shader_preset_path[0] = '\0';
#endif
#ifdef HAVE_MENU
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
/* Restore shader option state after temporary fast toggling */
if (menu_shader_get()->flags & SHDR_FLAG_TEMPORARY)
{
bool enabled = !(menu_shader_get()->flags & SHDR_FLAG_DISABLED);
configuration_set_bool(settings, settings->bools.video_shader_enable, enabled);
}
#endif
#endif
video_driver_restore_cached(settings);
if ( (flags & CONTENT_ST_FLAG_IS_INITED)
@ -4621,20 +4645,6 @@ bool command_event(enum event_command cmd, void *data)
return false;
#endif
break;
case CMD_EVENT_SHADER_PRESET_LOADED:
ui_companion_event_command(cmd);
break;
case CMD_EVENT_SHADERS_APPLY_CHANGES:
#ifdef HAVE_MENU
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
menu_shader_manager_apply_changes(menu_shader_get(),
settings->paths.directory_video_shader,
settings->paths.directory_menu_config
);
#endif
#endif
ui_companion_event_command(cmd);
break;
case CMD_EVENT_PAUSE_TOGGLE:
{
bool paused = (runloop_st->flags & RUNLOOP_FLAG_PAUSED) ? true : false;
@ -8538,6 +8548,17 @@ bool retroarch_main_quit(void)
}
#endif
#ifdef HAVE_MENU
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
/* Restore shader option state after temporary fast toggling */
if (menu_shader_get()->flags & SHDR_FLAG_TEMPORARY)
{
bool enabled = !(menu_shader_get()->flags & SHDR_FLAG_DISABLED);
configuration_set_bool(settings, settings->bools.video_shader_enable, enabled);
}
#endif
#endif
/* Save configs before quitting
* as for UWP depending on `OnSuspending` is not important as we can call it directly here
* specifically we need to get width,height which requires UI thread and it will not be available on exit

View File

@ -6793,6 +6793,18 @@ static enum runloop_state_enum runloop_check_state(
RARCH_SHADER_PREV, CMD_EVENT_SHADER_PREV,
RARCH_SHADER_TOGGLE, CMD_EVENT_SHADER_TOGGLE);
{
/* Check shader hold hotkey */
static bool old_shader_hold_button_state = false;
bool new_shader_hold_button_state = BIT256_GET(
current_bits, RARCH_SHADER_HOLD);
if (old_shader_hold_button_state != new_shader_hold_button_state)
command_event(CMD_EVENT_SHADER_TOGGLE, NULL);
old_shader_hold_button_state = new_shader_hold_button_state;
}
if (settings->bools.video_shader_watch_files)
{
static rarch_timer_t timer = {0};