Add quick menu option to watch shader files for changes and recompile automatically (Linux only for now)

This commit is contained in:
Brad Parker 2018-01-25 15:50:57 -05:00
parent f97ebfbf1f
commit f087b150c9
49 changed files with 428 additions and 77 deletions

View File

@ -10,6 +10,7 @@
- COMMON: Bugfix for issue related to 'Windows mouse pointer visible when running MESS or MAME cores'.
- COMMON: Fix bug 'Last item in a Playlist is ignored'.
- COMMON: New LED API. Driver implemented for Raspberry Pi, proof of concept implemented for core MAME 2003.
- COMMON: Add quick menu option to watch shader files for changes and recompile them automatically (Linux only for now).
- D3D8: Direct3D 8 can now work on systems that have Direct3D 8 installed.
- D3D9: Add menu support for MaterialUI/XMB.
- D3D10: Initial video driver implementation.

View File

@ -404,6 +404,9 @@ static const bool post_filter_record = false;
/* Screenshots post-shaded GPU output if available. */
static const bool gpu_screenshot = true;
/* Watch shader files for changes and auto-apply as necessary. */
static const bool video_shader_watch_files = false;
/* Screenshots named automatically. */
static const bool auto_screenshot_filename = true;

View File

@ -1211,6 +1211,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("rewind_enable", &settings->bools.rewind_enable, true, rewind_enable, false);
SETTING_BOOL("audio_sync", &settings->bools.audio_sync, true, audio_sync, false);
SETTING_BOOL("video_shader_enable", &settings->bools.video_shader_enable, true, shader_enable, false);
SETTING_BOOL("video_shader_watch_files", &settings->bools.video_shader_watch_files, true, video_shader_watch_files, false);
/* Let implementation decide if automatic, or 1:1 PAR. */
SETTING_BOOL("video_aspect_ratio_auto", &settings->bools.video_aspect_ratio_auto, true, aspect_ratio_auto, false);

View File

@ -81,6 +81,7 @@ typedef struct settings
bool video_aspect_ratio_auto;
bool video_scale_integer;
bool video_shader_enable;
bool video_shader_watch_files;
bool video_threaded;
bool video_font_enable;
bool video_disable_composition;

View File

@ -558,5 +558,7 @@ frontend_ctx_driver_t frontend_ctx_ctr = {
NULL, /* destroy_signal_handler_state */
NULL, /* attach_console */
NULL, /* detach_console */
NULL, /* watch_path_for_changes */
NULL, /* check_for_path_changes */
"ctr",
};

View File

@ -68,5 +68,7 @@ frontend_ctx_driver_t frontend_ctx_dos = {
NULL, /* destroy_sighandler_state */
NULL, /* attach_console */
NULL, /* detach_console */
NULL, /* watch_path_for_changes */
NULL, /* check_for_path_changes */
"dos",
};

View File

@ -260,5 +260,7 @@ frontend_ctx_driver_t frontend_ctx_emscripten = {
NULL, /* destroy_signal_handler_state */
NULL, /* attach_console */
NULL, /* detach_console */
NULL, /* watch_path_for_changes */
NULL, /* check_for_path_changes */
"emscripten"
};

View File

@ -559,5 +559,7 @@ frontend_ctx_driver_t frontend_ctx_gx = {
NULL, /* destroy_signal_handler_state */
NULL, /* attach_console */
NULL, /* detach_console */
NULL, /* watch_path_for_changes */
NULL, /* check_for_path_changes */
"gx",
};

View File

@ -44,5 +44,7 @@ frontend_ctx_driver_t frontend_ctx_null = {
#ifdef HAVE_LAKKA
NULL, /* get_lakka_version */
#endif
NULL, /* watch_path_for_changes */
NULL, /* check_for_path_changes */
"null",
};

View File

@ -632,5 +632,7 @@ frontend_ctx_driver_t frontend_ctx_ps3 = {
NULL, /* destroy_sighandler_state */
NULL, /* attach_console */
NULL, /* detach_console */
NULL, /* watch_path_for_changes */
NULL, /* check_for_path_changes */
"ps3",
};

View File

@ -518,6 +518,8 @@ frontend_ctx_driver_t frontend_ctx_psp = {
NULL, /* destroy_sighandler_state */
NULL, /* attach_console */
NULL, /* detach_console */
NULL, /* watch_path_for_changes */
NULL, /* check_for_path_changes */
#ifdef VITA
"vita",
#else

View File

@ -198,5 +198,7 @@ frontend_ctx_driver_t frontend_ctx_qnx = {
NULL, /* destroy_sighandler_state */
NULL, /* attach_console */
NULL, /* detach_console */
NULL, /* watch_path_for_changes */
NULL, /* check_for_path_changes */
"qnx",
};

View File

@ -27,6 +27,24 @@
#include <sys/utsname.h>
#include <sys/resource.h>
#ifdef __linux__
#include <linux/version.h>
/* inotify API was added in 2.6.13 */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
#define HAS_INOTIFY
#define INOTIFY_BUF_LEN (1024 * (sizeof(struct inotify_event) + 16))
#include <sys/inotify.h>
#include <net/net_socket.h>
#define VECTOR_LIST_TYPE int
#define VECTOR_LIST_NAME int
#include "../../libretro-common/lists/vector_list.c"
#undef VECTOR_LIST_TYPE
#undef VECTOR_LIST_NAME
#endif
#endif
#include <signal.h>
#include <pthread.h>
@ -45,6 +63,7 @@
#include <retro_dirent.h>
#include <retro_inline.h>
#include <compat/strl.h>
#include <compat/fopen_utf8.h>
#include <rhash.h>
#include <lists/file_list.h>
#include <file/file_path.h>
@ -81,7 +100,6 @@ enum
struct android_app *g_android;
static pthread_key_t thread_key;
static char screenshot_dir[PATH_MAX_LENGTH];
@ -104,6 +122,17 @@ static volatile sig_atomic_t unix_sighandler_quit;
static enum frontend_fork unix_fork_mode = FRONTEND_FORK_NONE;
#endif
#ifdef HAS_INOTIFY
typedef struct inotify_data
{
int fd;
int flags;
struct int_vector_list *wd_list;
struct string_list *path_list;
} inotify_data_t;
#endif
int system_property_get(const char *command,
const char *args, char *value)
{
@ -2223,6 +2252,183 @@ static void frontend_unix_destroy_signal_handler_state(void)
unix_sighandler_quit = 0;
}
/* To free change_data, call the function again with a NULL string_list while providing change_data again */
static void frontend_unix_watch_path_for_changes(struct string_list *list, int flags, path_change_data_t **change_data)
{
#ifdef HAS_INOTIFY
int major = 0;
int minor = 0;
int inotify_mask = 0, fd = 0;
unsigned i, krel = 0;
struct utsname buffer;
inotify_data_t *inotify_data;
if (!list)
{
if (change_data && *change_data)
{
/* free the original data */
inotify_data = (inotify_data_t*)((*change_data)->data);
if (inotify_data->wd_list->count > 0)
{
for (i = 0; i < inotify_data->wd_list->count; i++)
{
inotify_rm_watch(inotify_data->fd, inotify_data->wd_list->data[i]);
}
}
int_vector_list_free(inotify_data->wd_list);
string_list_free(inotify_data->path_list);
close(inotify_data->fd);
free(inotify_data);
free(*change_data);
return;
}
}
else if (list->size == 0)
return;
else
if (!change_data)
return;
if (uname(&buffer) != 0)
{
RARCH_WARN("watch_path_for_changes: Failed to get current kernel version.\n");
return;
}
/* get_os doesn't provide all three */
sscanf(buffer.release, "%d.%d.%u", &major, &minor, &krel);
/* check if we are actually running on a high enough kernel version as well */
if (major < 2)
{
RARCH_WARN("watch_path_for_changes: inotify unsupported on this kernel version (%d.%d.%u).\n", major, minor, krel);
return;
}
else if (major == 2)
{
if (minor < 6)
{
RARCH_WARN("watch_path_for_changes: inotify unsupported on this kernel version (%d.%d.%u).\n", major, minor, krel);
return;
}
else if (minor == 6)
{
if (krel < 13)
{
RARCH_WARN("watch_path_for_changes: inotify unsupported on this kernel version (%d.%d.%u).\n", major, minor, krel);
return;
}
else
{
/* anything >= 2.6.13 is supported */
}
}
else
{
/* anything >= 2.7 is supported */
}
}
else
{
/* anything >= 3 is supported */
}
fd = inotify_init();
if (fd < 0)
{
RARCH_WARN("watch_path_for_changes: Could not initialize inotify.\n");
return;
}
socket_nonblock(fd);
inotify_data = (inotify_data_t*)calloc(1, sizeof(*inotify_data));
inotify_data->fd = fd;
inotify_data->wd_list = int_vector_list_new();
inotify_data->path_list = string_list_new();
/* handle other flags here as new ones are added */
if (flags & PATH_CHANGE_TYPE_MODIFIED)
inotify_mask |= IN_MODIFY;
if (flags & PATH_CHANGE_TYPE_WRITE_FILE_CLOSED)
inotify_mask |= IN_CLOSE_WRITE;
inotify_data->flags = inotify_mask;
for (i = 0; i < list->size; i++)
{
int wd = inotify_add_watch(fd, list->elems[i].data, inotify_mask);
union string_list_elem_attr attr = {0};
RARCH_LOG("Watching file for changes: %s\n", list->elems[i].data);
int_vector_list_append(inotify_data->wd_list, wd);
string_list_append(inotify_data->path_list, list->elems[i].data, attr);
}
*change_data = (path_change_data_t*)calloc(1, sizeof(path_change_data_t));
(*change_data)->data = inotify_data;
#endif
}
static bool frontend_unix_check_for_path_changes(path_change_data_t *change_data)
{
#ifdef HAS_INOTIFY
inotify_data_t *inotify_data = (inotify_data_t*)(change_data->data);
char buffer[INOTIFY_BUF_LEN] = {0};
int length, i = 0;
while ((length = read(inotify_data->fd, buffer, INOTIFY_BUF_LEN)) > 0)
{
i = 0;
while (i < length)
{
struct inotify_event *event = (struct inotify_event *)&buffer[i];
if (event->mask & inotify_data->flags)
{
unsigned j;
/* A successful close does not guarantee that the data has been successfully saved to disk, as the kernel defers writes. It is not common for a file system to flush the buffers when the stream is closed.
* So we manually fsync() here to flush the data to disk, to make sure that the new data is immediately available when the file is re-read.
*/
for (j = 0; j < inotify_data->wd_list->count; j++)
{
if (inotify_data->wd_list->data[j] == event->wd)
{
/* found the right file, now sync it */
const char *path = inotify_data->path_list->elems[j].data;
FILE *fp = fopen_utf8(path, "rb");
RARCH_LOG("file change detected: %s\n", path);
if (fp)
{
fsync(fileno(fp));
fclose(fp);
}
}
}
return true;
}
i += sizeof(struct inotify_event) + event->len;
}
}
return false;
#else
return false;
#endif
}
frontend_ctx_driver_t frontend_ctx_unix = {
frontend_unix_get_env, /* environment_get */
frontend_unix_init, /* init */
@ -2264,6 +2470,8 @@ frontend_ctx_driver_t frontend_ctx_unix = {
#ifdef HAVE_LAKKA
frontend_unix_get_lakka_version, /* get_lakka_version */
#endif
frontend_unix_watch_path_for_changes,
frontend_unix_check_for_path_changes,
#ifdef ANDROID
"android"
#else

View File

@ -305,6 +305,8 @@ frontend_ctx_driver_t frontend_ctx_wiiu =
NULL, /* destroy_signal_handler_state */
NULL, /* attach_console */
NULL, /* detach_console */
NULL, /* watch_path_for_changes */
NULL, /* check_for_path_changes */
"wiiu",
NULL, /* get_video_driver */
};

View File

@ -584,5 +584,7 @@ frontend_ctx_driver_t frontend_ctx_win32 = {
NULL, /* destroy_sighandler_state */
frontend_win32_attach_console, /* attach_console */
frontend_win32_detach_console, /* detach_console */
NULL, /* watch_path_for_changes */
NULL, /* check_for_path_changes */
"win32"
};

View File

@ -1444,5 +1444,7 @@ frontend_ctx_driver_t frontend_ctx_xdk = {
NULL, /* destroy_sighandler_state */
NULL, /* attach_console */
NULL, /* detach_console */
NULL, /* watch_path_for_changes */
NULL, /* check_for_path_changes */
"xdk",
};

View File

@ -91,5 +91,7 @@ frontend_ctx_driver_t frontend_ctx_qnx = {
NULL, /* destroy_sighandler_state */
NULL, /* attach_console */
NULL, /* detach_console */
NULL, /* watch_path_for_changes */
NULL, /* check_for_path_changes */
"xenon",
};

View File

@ -384,4 +384,29 @@ void frontend_driver_destroy_signal_handler_state(void)
return;
frontend->destroy_signal_handler_state();
}
bool frontend_driver_can_watch_for_changes(void)
{
frontend_ctx_driver_t *frontend = frontend_get_ptr();
if (!frontend || !frontend->watch_path_for_changes)
return false;
return true;
}
void frontend_driver_watch_path_for_changes(struct string_list *list, int flags, path_change_data_t **change_data)
{
frontend_ctx_driver_t *frontend = frontend_get_ptr();
if (!frontend || !frontend->watch_path_for_changes)
return;
frontend->watch_path_for_changes(list, flags, change_data);
}
bool frontend_driver_check_for_path_changes(path_change_data_t *change_data)
{
frontend_ctx_driver_t *frontend = frontend_get_ptr();
if (!frontend || !frontend->check_for_path_changes)
return false;
return frontend->check_for_path_changes(change_data);
}
#endif

View File

@ -22,6 +22,7 @@
#include <boolean.h>
#include <retro_common_api.h>
#include <lists/string_list.h>
RETRO_BEGIN_DECLS
@ -55,6 +56,17 @@ enum frontend_architecture
FRONTEND_ARCH_TILE
};
enum path_change_type
{
PATH_CHANGE_TYPE_MODIFIED = (1 << 0),
PATH_CHANGE_TYPE_WRITE_FILE_CLOSED = (1 << 1)
};
typedef struct path_change_data
{
void *data;
} path_change_data_t;
typedef void (*environment_get_t)(int *argc, char *argv[], void *args,
void *params_data);
typedef void (*process_args_t)(int *argc, char *argv[]);
@ -88,6 +100,8 @@ typedef struct frontend_ctx_driver
#ifdef HAVE_LAKKA
void (*get_lakka_version)(char *, size_t);
#endif
void (*watch_path_for_changes)(struct string_list *list, int flags, path_change_data_t **change_data);
bool (*check_for_path_changes)(path_change_data_t *change_data);
const char *ident;
@ -180,6 +194,12 @@ void frontend_driver_attach_console(void);
void frontend_driver_detach_console(void);
bool frontend_driver_can_watch_for_changes(void);
void frontend_driver_watch_path_for_changes(struct string_list *list, int flags, path_change_data_t **change_data);
bool frontend_driver_check_for_path_changes(path_change_data_t *change_data);
RETRO_END_DECLS
#endif

View File

@ -3332,7 +3332,6 @@ static struct video_shader *video_shader_driver_get_current_shader_null(void *da
return NULL;
}
static void video_shader_driver_set_params_null(void *data, void *shader_data,
unsigned width, unsigned height,
unsigned tex_width, unsigned tex_height,

View File

@ -27,9 +27,12 @@
#include <string/stdstring.h>
#include <streams/interface_stream.h>
#include <streams/file_stream.h>
#include <lists/string_list.h>
#include "../msg_hash.h"
#include "../verbosity.h"
#include "../configuration.h"
#include "../frontend/frontend_driver.h"
#include "video_shader_parse.h"
#ifdef HAVE_SLANG
@ -53,6 +56,8 @@
#define SEMANTIC_TRANSITION_COUNT 0x3ef2af78U
#define SEMANTIC_PYTHON 0x15efc547U
static path_change_data_t *file_change_data = NULL;
/**
* wrap_mode_to_str:
* @type : Wrap type.
@ -755,6 +760,11 @@ bool video_shader_read_conf_cgp(config_file_t *conf,
{
unsigned i;
unsigned shaders = 0;
settings_t *settings = config_get_ptr();
struct string_list *file_list = NULL;
union string_list_elem_attr attr = {0};
(void)file_list;
memset(shader, 0, sizeof(*shader));
shader->type = RARCH_SHADER_CG;
@ -776,10 +786,31 @@ bool video_shader_read_conf_cgp(config_file_t *conf,
shader->passes = MIN(shaders, GFX_MAX_SHADERS);
if (settings->bools.video_shader_watch_files)
{
if (file_change_data)
frontend_driver_watch_path_for_changes(NULL, 0, &file_change_data);
file_change_data = NULL;
file_list = string_list_new();
string_list_append(file_list, conf->path, attr);
}
for (i = 0; i < shader->passes; i++)
{
if (!video_shader_parse_pass(conf, &shader->pass[i], i))
return false;
if (settings->bools.video_shader_watch_files)
{
string_list_append(file_list, shader->pass[i].source.path, attr);
}
}
if (settings->bools.video_shader_watch_files)
{
frontend_driver_watch_path_for_changes(file_list, PATH_CHANGE_TYPE_WRITE_FILE_CLOSED, &file_change_data);
string_list_free(file_list);
}
if (!video_shader_parse_textures(conf, shader))
@ -1198,3 +1229,10 @@ void video_shader_resolve_relative(struct video_shader *shader,
free(tmp_path);
}
bool video_shader_check_for_changes(void)
{
if (!file_change_data)
return false;
return frontend_driver_check_for_path_changes(file_change_data);
}

View File

@ -231,6 +231,8 @@ bool video_shader_resolve_parameters(config_file_t *conf,
enum rarch_shader_type video_shader_parse_type(const char *path,
enum rarch_shader_type fallback);
bool video_shader_check_for_changes(void);
RETRO_END_DECLS
#endif

View File

@ -3205,7 +3205,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")

View File

@ -3199,7 +3199,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")

View File

@ -3315,7 +3315,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")

View File

@ -3072,7 +3072,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")

View File

@ -5701,8 +5701,4 @@ MSG_HASH(
MSG_HASH(
MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Valores mas bajos favorecen el rendimiento y bajan la latencia a costa de la calidad, incrementar el valor aumentará la calidad a costa del rendimiento y latencia"
)
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")
)

View File

@ -3237,7 +3237,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")

View File

@ -3295,7 +3295,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Qualità del Resampler Audio")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Abbassare questo valore per favorire prestazioni/bassa latenza rispetto alla qualità audio, aumentare se si desidera una migliore qualità audio a scapito delle prestazioni/minore latenza.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Segnaposto")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Segnaposto sotto etichetta")

View File

@ -2990,7 +2990,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_LIBRETRO_INFO_PATH,
MSG_HASH(MENU_ENUM_SUBLABEL_JOYPAD_AUTOCONFIG_DIR,
"If a joypad is plugged in, that joypad will be autoconfigured if a config file corresponding to it is present inside this directory.")
MSG_HASH(MENU_ENUM_SUBLABEL_PLAYLIST_DIRECTORY,
"すべてのコレクションをこのフォルダに保存する。")
"すべてのプレイリストをこのフォルダに保存する。")
MSG_HASH(
MENU_ENUM_SUBLABEL_CACHE_DIRECTORY,
"If set to a directory, content which is temporarily extracted (e.g. from archives) will be extracted to this directory."
@ -3256,7 +3256,7 @@ MSG_HASH(MSG_GAME_REMAP_FILE_LOADED,
MSG_HASH(MSG_CORE_REMAP_FILE_LOADED,
"コアの優先ファイルをロードしました。")
MSG_HASH(MENU_ENUM_LABEL_VALUE_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST,
"Automatically add content to playlist")
"自動的にコンテンツをプレイリストに追加")
MSG_HASH(MENU_ENUM_SUBLABEL_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST,
"Automatically scans loaded content so they appear inside playlists.")
MSG_HASH(MSG_SCANNING_OF_FILE_FINISHED,
@ -3267,7 +3267,5 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_WATCH_FOR_CHANGES,
"シェーダーファイルの変更を監視")

View File

@ -3200,7 +3200,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")

View File

@ -931,6 +931,8 @@ MSG_HASH(MENU_ENUM_LABEL_SETTINGS_TAB,
"settings_tab")
MSG_HASH(MENU_ENUM_LABEL_SHADER_APPLY_CHANGES,
"shader_apply_changes")
MSG_HASH(MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES,
"video_shader_watch_files")
MSG_HASH(MENU_ENUM_LABEL_SHADER_OPTIONS,
"shader_options")
MSG_HASH(MENU_ENUM_LABEL_SHADER_PARAMETERS_ENTRY,
@ -1391,5 +1393,3 @@ MSG_HASH(MENU_ENUM_LABEL_VIDEO_WINDOW_OPACITY,
"video_window_opacity")
MSG_HASH(MENU_ENUM_LABEL_AUDIO_RESAMPLER_QUALITY,
"audio_resampler_quality")
MSG_HASH(MENU_ENUM_LABEL_SHADER_PLACEHOLDER,
"shader_placeholder")

View File

@ -3074,7 +3074,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")

View File

@ -3335,7 +3335,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")

View File

@ -4179,7 +4179,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")

View File

@ -3175,7 +3175,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")

View File

@ -3258,7 +3258,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")

View File

@ -1071,6 +1071,15 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
"saved to Shader Directory."
);
break;
case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES:
snprintf(s, len,
"Watch shader files for new changes. \n"
" \n"
"After saving changes to a shader on disk, \n"
"it will automatically be recompiled \n"
"and applied to the running content."
);
break;
case MENU_ENUM_LABEL_MENU_TOGGLE:
snprintf(s, len,
"Toggles menu.");

View File

@ -3405,7 +3405,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_WATCH_FOR_CHANGES,
"Watch shader files for changes")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_WATCH_FOR_CHANGES,
"Auto-apply changes made to shader files on disk.")

View File

@ -3223,7 +3223,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY,
"Audio Resampler Quality")
MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY,
"Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER,
"Shader Placeholder")
MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER,
"Shader Placeholder sublabel")

View File

@ -309,6 +309,30 @@ static void menu_action_setting_disp_set_label_pipeline(
}
static void menu_action_setting_disp_set_label_shader_watch_for_changes(
file_list_t* list,
unsigned *w, unsigned type, unsigned i,
const char *label,
char *s, size_t len,
const char *entry_label,
const char *path,
char *s2, size_t len2)
{
settings_t *settings = config_get_ptr();
*s = '\0';
*w = 19;
strlcpy(s2, path, len2);
if (settings)
{
if (settings->bools.video_shader_watch_files)
snprintf(s, len, "%s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_TRUE));
else
snprintf(s, len, "%s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FALSE));
}
}
static void menu_action_setting_disp_set_label_shader_num_passes(
file_list_t* list,
unsigned *w, unsigned type, unsigned i,
@ -1873,6 +1897,10 @@ static int menu_cbs_init_bind_get_string_representation_compare_label(
BIND_ACTION_GET_VALUE(cbs,
menu_action_setting_disp_set_label_shader_num_passes);
break;
case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES:
BIND_ACTION_GET_VALUE(cbs,
menu_action_setting_disp_set_label_shader_watch_for_changes);
break;
case MENU_ENUM_LABEL_XMB_RIBBON_ENABLE:
BIND_ACTION_GET_VALUE(cbs,
menu_action_setting_disp_set_label_pipeline);

View File

@ -324,6 +324,14 @@ static int action_left_shader_num_passes(unsigned type, const char *label,
return 0;
}
static int action_left_shader_watch_for_changes(unsigned type, const char *label,
bool wraparound)
{
settings_t *settings = config_get_ptr();
settings->bools.video_shader_watch_files = !settings->bools.video_shader_watch_files;
return 0;
}
static int action_left_video_resolution(unsigned type, const char *label,
bool wraparound)
{
@ -482,6 +490,9 @@ static int menu_cbs_init_bind_left_compare_label(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_VIDEO_SHADER_DEFAULT_FILTER:
BIND_ACTION_LEFT(cbs, action_left_shader_filter_default);
break;
case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES:
BIND_ACTION_LEFT(cbs, action_left_shader_watch_for_changes);
break;
case MENU_ENUM_LABEL_VIDEO_SHADER_NUM_PASSES:
BIND_ACTION_LEFT(cbs, action_left_shader_num_passes);
break;

View File

@ -327,6 +327,14 @@ static int action_right_shader_num_passes(unsigned type, const char *label,
return 0;
}
static int action_right_shader_watch_for_changes(unsigned type, const char *label,
bool wraparound)
{
settings_t *settings = config_get_ptr();
settings->bools.video_shader_watch_files = !settings->bools.video_shader_watch_files;
return 0;
}
static int action_right_video_resolution(unsigned type, const char *label,
bool wraparound)
{
@ -592,6 +600,9 @@ static int menu_cbs_init_bind_right_compare_label(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_VIDEO_SHADER_DEFAULT_FILTER:
BIND_ACTION_RIGHT(cbs, action_right_shader_filter_default);
break;
case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES:
BIND_ACTION_RIGHT(cbs, action_right_shader_watch_for_changes);
break;
case MENU_ENUM_LABEL_VIDEO_SHADER_NUM_PASSES:
BIND_ACTION_RIGHT(cbs, action_right_shader_num_passes);
break;

View File

@ -40,6 +40,8 @@
#include "../../input/input_driver.h"
#include "../../input/input_remapping.h"
#include "../../config.def.h"
#ifndef BIND_ACTION_START
#define BIND_ACTION_START(cbs, name) \
cbs->action_start = name; \
@ -166,6 +168,13 @@ static int action_start_shader_filter_pass(unsigned type, const char *label)
return menu_shader_manager_clear_pass_filter(pass);
}
static int action_start_shader_watch_for_changes(unsigned type, const char *label)
{
settings_t *settings = config_get_ptr();
settings->bools.video_shader_watch_files = video_shader_watch_files;
return 0;
}
static int action_start_shader_num_passes(unsigned type, const char *label)
{
return menu_shader_manager_clear_num_passes();
@ -279,6 +288,9 @@ static int menu_cbs_init_bind_start_compare_label(menu_file_list_cbs_t *cbs)
case MENU_ENUM_LABEL_VIDEO_SHADER_FILTER_PASS:
BIND_ACTION_START(cbs, action_start_shader_filter_pass);
break;
case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES:
BIND_ACTION_START(cbs, action_start_shader_watch_for_changes);
break;
case MENU_ENUM_LABEL_VIDEO_SHADER_NUM_PASSES:
BIND_ACTION_START(cbs, action_start_shader_num_passes);
break;

View File

@ -353,6 +353,7 @@ default_sublabel_macro(action_bind_sublabel_recording_output_directory,
default_sublabel_macro(action_bind_sublabel_recording_config_directory, MENU_ENUM_SUBLABEL_RECORDING_CONFIG_DIRECTORY)
default_sublabel_macro(action_bind_sublabel_video_font_path, MENU_ENUM_SUBLABEL_VIDEO_FONT_PATH)
default_sublabel_macro(action_bind_sublabel_shader_apply_changes, MENU_ENUM_SUBLABEL_SHADER_APPLY_CHANGES)
default_sublabel_macro(action_bind_sublabel_shader_watch_for_changes, MENU_ENUM_SUBLABEL_SHADER_WATCH_FOR_CHANGES)
default_sublabel_macro(action_bind_sublabel_shader_num_passes, MENU_ENUM_SUBLABEL_VIDEO_SHADER_NUM_PASSES)
default_sublabel_macro(action_bind_sublabel_shader_preset, MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET)
default_sublabel_macro(action_bind_sublabel_shader_preset_save_as, MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_AS)
@ -518,6 +519,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_SHADER_APPLY_CHANGES:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_shader_apply_changes);
break;
case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_shader_watch_for_changes);
break;
case MENU_ENUM_LABEL_VIDEO_FONT_PATH:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_font_path);
break;

View File

@ -1366,16 +1366,19 @@ static int menu_displaylist_parse_shader_options(menu_displaylist_info_t *info)
unsigned i;
unsigned pass_count = menu_shader_manager_get_amount_passes();
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER),
msg_hash_to_str(MENU_ENUM_LABEL_SHADER_PLACEHOLDER),
MENU_ENUM_LABEL_SHADER_PLACEHOLDER,
MENU_SETTING_ACTION, 0, 0);
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_APPLY_CHANGES),
msg_hash_to_str(MENU_ENUM_LABEL_SHADER_APPLY_CHANGES),
MENU_ENUM_LABEL_SHADER_APPLY_CHANGES,
MENU_SETTING_ACTION, 0, 0);
if (frontend_driver_can_watch_for_changes())
{
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_WATCH_FOR_CHANGES),
msg_hash_to_str(MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES),
MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES,
0, 0, 0);
}
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET),
msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET),

View File

@ -1467,12 +1467,12 @@ enum msg_hash_enums
MENU_ENUM_LABEL_ONSCREEN_KEYBOARD_OVERLAY_SETTINGS,
MENU_LABEL(SHADER_PLACEHOLDER),
MENU_LABEL(MULTIMEDIA_SETTINGS),
MENU_LABEL(PLAYLIST_SETTINGS),
MENU_LABEL(CORE_UPDATER_SETTINGS),
MENU_LABEL(LAKKA_SERVICES),
MENU_LABEL(SHADER_APPLY_CHANGES),
MENU_LABEL(SHADER_WATCH_FOR_CHANGES),
MENU_LABEL(SAVE_NEW_CONFIG),
MENU_LABEL(ONSCREEN_DISPLAY_SETTINGS),
MENU_LABEL(ONSCREEN_OVERLAY_SETTINGS),

View File

@ -2994,6 +2994,12 @@ static enum runloop_state runloop_check_state(
old_cheat_index_toggle = cheat_index_toggle;
}
if (settings->bools.video_shader_watch_files)
{
if (video_shader_check_for_changes())
command_event(CMD_EVENT_SHADERS_APPLY_CHANGES, NULL);
}
return RUNLOOP_STATE_ITERATE;
}

View File

@ -811,6 +811,9 @@ video_message_bgcolor_opacity = 1.0
# Screenshots output of GPU shaded material if available.
# video_gpu_screenshot = true
# Watch content shader files for changes and auto-apply as necessary.
# video_shader_watch_files = false
# Block SRAM from being overwritten when loading save states.
# Might potentially lead to buggy games.
# block_sram_overwrite = false