Merge pull request #9140 from LazyBumHorse/shader_paths

much improved handling of relative shader paths
This commit is contained in:
Twinaphex 2019-07-20 21:54:58 +02:00 committed by GitHub
commit 388c4857d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 98 additions and 152 deletions

View File

@ -365,11 +365,9 @@ static bool d3d10_gfx_set_shader(void* data, enum rarch_shader_type type, const
d3d10->shader_preset = (struct video_shader*)calloc(1, sizeof(*d3d10->shader_preset));
if (!video_shader_read_conf_preset(conf, d3d10->shader_preset))
if (!video_shader_read_conf_preset(conf, d3d10->shader_preset, path))
goto error;
video_shader_resolve_relative(d3d10->shader_preset, path);
source = &d3d10->frame.texture[0];
for (i = 0; i < d3d10->shader_preset->passes; source = &d3d10->pass[i++].rt)
{

View File

@ -383,11 +383,9 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const
d3d11->shader_preset = (struct video_shader*)calloc(1, sizeof(*d3d11->shader_preset));
if (!video_shader_read_conf_preset(conf, d3d11->shader_preset))
if (!video_shader_read_conf_preset(conf, d3d11->shader_preset, path))
goto error;
video_shader_resolve_relative(d3d11->shader_preset, path);
source = &d3d11->frame.texture[0];
for (i = 0; i < d3d11->shader_preset->passes; source = &d3d11->pass[i++].rt)
{

View File

@ -364,11 +364,9 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const
d3d12->shader_preset = (struct video_shader*)calloc(1, sizeof(*d3d12->shader_preset));
if (!video_shader_read_conf_preset(conf, d3d12->shader_preset))
if (!video_shader_read_conf_preset(conf, d3d12->shader_preset, path))
goto error;
video_shader_resolve_relative(d3d12->shader_preset, path);
source = &d3d12->frame.texture[0];
for (i = 0; i < d3d12->shader_preset->passes; source = &d3d12->pass[i++].rt)
{

View File

@ -335,7 +335,7 @@ static bool d3d9_init_multipass(d3d9_video_t *d3d, const char *shader_path)
memset(&d3d->shader, 0, sizeof(d3d->shader));
if (!video_shader_read_conf_preset(conf, &d3d->shader))
if (!video_shader_read_conf_preset(conf, &d3d->shader, shader_path))
{
config_file_free(conf);
RARCH_ERR("[D3D9]: Failed to parse shader preset.\n");
@ -344,8 +344,6 @@ static bool d3d9_init_multipass(d3d9_video_t *d3d, const char *shader_path)
config_file_free(conf);
if (!string_is_empty(shader_path))
video_shader_resolve_relative(&d3d->shader, shader_path);
RARCH_LOG("[D3D9]: Found %u shaders.\n", d3d->shader.passes);
for (i = 0; i < d3d->shader.passes; i++)

View File

@ -1458,15 +1458,13 @@ static bool wiiu_gfx_set_shader(void *data,
wiiu->shader_preset = calloc(1, sizeof(*wiiu->shader_preset));
if (!video_shader_read_conf_preset(conf, wiiu->shader_preset))
if (!video_shader_read_conf_preset(conf, wiiu->shader_preset, path))
{
free(wiiu->shader_preset);
wiiu->shader_preset = NULL;
return false;
}
video_shader_resolve_relative(wiiu->shader_preset, path);
#if 0
video_shader_resolve_parameters(conf, wiiu->shader_preset);
#else

View File

@ -692,14 +692,13 @@ static bool gl_cg_load_preset(void *data, const char *path)
return false;
}
if (!video_shader_read_conf_preset(conf, cg->shader))
if (!video_shader_read_conf_preset(conf, cg->shader, path))
{
RARCH_ERR("Failed to parse CGP file.\n");
config_file_free(conf);
return false;
}
video_shader_resolve_relative(cg->shader, path);
video_shader_resolve_parameters(conf, cg->shader);
config_file_free(conf);

View File

@ -2413,11 +2413,9 @@ gl_core_filter_chain_t *gl_core_filter_chain_create_from_preset(
if (!conf)
return nullptr;
if (!video_shader_read_conf_preset(conf.get(), shader.get()))
if (!video_shader_read_conf_preset(conf.get(), shader.get(), path))
return nullptr;
video_shader_resolve_relative(shader.get(), path);
bool last_pass_is_fbo = shader->pass[shader->passes - 1].fbo.valid;
unique_ptr<gl_core_filter_chain> chain{ new gl_core_filter_chain(shader->passes + (last_pass_is_fbo ? 1 : 0)) };

View File

@ -903,7 +903,7 @@ static void *gl_glsl_init(void *data, const char *path)
conf = config_file_new_from_path_to_string(path);
if (conf)
{
ret = video_shader_read_conf_preset(conf, glsl->shader);
ret = video_shader_read_conf_preset(conf, glsl->shader, path);
glsl->shader->modern = true;
}
}
@ -934,8 +934,6 @@ static void *gl_glsl_init(void *data, const char *path)
}
}
if (!string_is_empty(path))
video_shader_resolve_relative(glsl->shader, path);
video_shader_resolve_parameters(conf, glsl->shader);
if (conf)

View File

@ -2890,11 +2890,9 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
if (!conf)
return nullptr;
if (!video_shader_read_conf_preset(conf.get(), shader.get()))
if (!video_shader_read_conf_preset(conf.get(), shader.get(), path))
return nullptr;
video_shader_resolve_relative(shader.get(), path);
bool last_pass_is_fbo = shader->pass[shader->passes - 1].fbo.valid;
auto tmpinfo = *info;
tmpinfo.num_passes = shader->passes + (last_pass_is_fbo ? 1 : 0);

View File

@ -102,13 +102,14 @@ static enum gfx_wrap_type wrap_str_to_mode(const char *wrap_mode)
* @conf : Preset file to read from.
* @pass : Shader passes handle.
* @i : Index of shader pass.
* @ref_path : Base path used to resolve relative paths
*
* Parses shader pass from preset file.
*
* Returns: true (1) if successful, otherwise false (0).
**/
static bool video_shader_parse_pass(config_file_t *conf,
struct video_shader_pass *pass, unsigned i)
struct video_shader_pass *pass, unsigned i, const char *ref_path)
{
char shader_name[64];
char filter_name_buf[64];
@ -125,41 +126,33 @@ static bool video_shader_parse_pass(config_file_t *conf,
char scale_type_x[64];
char scale_type_y[64];
char frame_count_mod[64];
size_t path_size = PATH_MAX_LENGTH * sizeof(char);
char *tmp_str = (char*)malloc(path_size);
char *tmp_path = NULL;
size_t path_size = PATH_MAX_LENGTH;
char *tmp_path = (char*)malloc(path_size);
struct gfx_fbo_scale *scale = NULL;
bool tmp_bool = false;
float fattr = 0.0f;
int iattr = 0;
fp_fbo_buf[0] = mipmap_buf[0] = alias_buf[0] =
scale_name_buf[0] = attr_name_buf[0] = scale_type[0] =
scale_type_x[0] = scale_type_y[0] = frame_count_mod[0] =
tmp_str[0] = shader_name[0] = filter_name_buf[0] =
wrap_name_buf[0] = wrap_mode[0] = frame_count_mod_buf[0] = '\0';
srgb_output_buf[0] = '\0';
if (!tmp_path)
return false;
fp_fbo_buf[0] = mipmap_buf[0] = alias_buf[0] =
scale_name_buf[0] = attr_name_buf[0] = scale_type[0] =
scale_type_x[0] = scale_type_y[0] = frame_count_mod[0] =
shader_name[0] = filter_name_buf[0] = wrap_name_buf[0] =
wrap_mode[0] = frame_count_mod_buf[0] = srgb_output_buf[0] = '\0';
/* Source */
snprintf(shader_name, sizeof(shader_name), "shader%u", i);
if (!config_get_path(conf, shader_name, tmp_str, path_size))
if (!config_get_path(conf, shader_name, tmp_path, path_size))
{
RARCH_ERR("Couldn't parse shader source (%s).\n", shader_name);
if (tmp_str)
free(tmp_str);
free(tmp_path);
return false;
}
tmp_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
strlcpy(tmp_path, tmp_str, path_size);
path_resolve_realpath(tmp_path, path_size);
if (!path_is_valid(tmp_path))
strlcpy(pass->source.path, tmp_str, sizeof(pass->source.path));
else
strlcpy(pass->source.path, tmp_path, sizeof(pass->source.path));
free(tmp_str);
fill_pathname_resolve_relative(pass->source.path,
ref_path, tmp_path, sizeof(pass->source.path));
free(tmp_path);
/* Smooth */
@ -314,22 +307,27 @@ static bool video_shader_parse_pass(config_file_t *conf,
* video_shader_parse_textures:
* @conf : Preset file to read from.
* @shader : Shader pass handle.
* @ref_path : Base path used to resolve relative paths
*
* Parses shader textures.
*
* Returns: true (1) if successful, otherwise false (0).
**/
static bool video_shader_parse_textures(config_file_t *conf,
struct video_shader *shader)
struct video_shader *shader, const char *ref_path)
{
size_t path_size = PATH_MAX_LENGTH * sizeof(char);
size_t path_size = PATH_MAX_LENGTH;
const char *id = NULL;
char *save = NULL;
char *textures = (char*)malloc(1024 * sizeof(char));
char *textures = (char*)malloc(1024 + path_size);
char *tmp_path = textures + 1024;
textures[0] = '\0';
if (!textures)
return false;
if (!config_get_array(conf, "textures", textures, 1024 * sizeof(char)))
textures[0] = '\0';
if (!config_get_array(conf, "textures", textures, 1024))
{
free(textures);
return true;
@ -345,28 +343,19 @@ static bool video_shader_parse_textures(config_file_t *conf,
char id_mipmap[64];
bool mipmap = false;
bool smooth = false;
char *tmp_path = NULL;
id_filter[0] = id_wrap[0] = wrap_mode[0] = id_mipmap[0] = '\0';
if (!config_get_array(conf, id, shader->lut[shader->luts].path,
sizeof(shader->lut[shader->luts].path)))
if (!config_get_array(conf, id, tmp_path, path_size))
{
RARCH_ERR("Cannot find path to texture \"%s\" ...\n", id);
free(textures);
return false;
}
tmp_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
tmp_path[0] = '\0';
strlcpy(tmp_path, shader->lut[shader->luts].path,
path_size);
path_resolve_realpath(tmp_path, path_size);
fill_pathname_resolve_relative(shader->lut[shader->luts].path,
ref_path, tmp_path, sizeof(shader->lut[shader->luts].path));
if (path_is_valid(tmp_path))
strlcpy(shader->lut[shader->luts].path,
tmp_path, sizeof(shader->lut[shader->luts].path));
free(tmp_path);
strlcpy(shader->lut[shader->luts].id, id,
sizeof(shader->lut[shader->luts].id));
@ -574,6 +563,7 @@ bool video_shader_resolve_parameters(config_file_t *conf,
* video_shader_read_conf_preset:
* @conf : Preset file to read from.
* @shader : Shader passes handle.
* @ref_path : Base path used to resolve relative paths
*
* Loads preset file and all associated state (passes,
* textures, imports, etc).
@ -581,7 +571,7 @@ bool video_shader_resolve_parameters(config_file_t *conf,
* Returns: true (1) if successful, otherwise false (0).
**/
bool video_shader_read_conf_preset(config_file_t *conf,
struct video_shader *shader)
struct video_shader *shader, const char* ref_path)
{
unsigned i;
union string_list_elem_attr attr;
@ -628,7 +618,7 @@ bool video_shader_read_conf_preset(config_file_t *conf,
for (i = 0; i < shader->passes; i++)
{
if (!video_shader_parse_pass(conf, &shader->pass[i], i))
if (!video_shader_parse_pass(conf, &shader->pass[i], i, ref_path))
{
if (file_list)
{
@ -658,7 +648,7 @@ bool video_shader_read_conf_preset(config_file_t *conf,
command_event(CMD_EVENT_SHADER_PRESET_LOADED, NULL);
if (!video_shader_parse_textures(conf, shader))
if (!video_shader_parse_textures(conf, shader, ref_path))
return false;
return true;
@ -722,14 +712,28 @@ static void shader_write_fbo(config_file_t *conf,
fbo->scale_y, fbo->abs_y, i);
}
static void make_relative_path_portable(char *path)
{
#ifdef _WIN32
/* use '/' instead of '\' for maximum portability */
if (!path_is_absolute(path))
{
char *p;
for (p = path; *p; p++)
if (*p == '\\')
*p = '/';
}
#endif
}
/**
* video_shader_write_conf_preset:
* @conf : Preset file to write to.
* @shader : Shader passes handle.
* @preset_path : Optional path to where the preset will be written.
*
* Saves preset and all associated state (passes,
* textures, imports, etc) to disk.
* Writes preset and all associated state (passes,
* textures, imports, etc) into @conf.
* If @preset_path is not NULL, shader paths are saved
* relative to it.
**/
@ -739,35 +743,42 @@ void video_shader_write_conf_preset(config_file_t *conf,
unsigned i;
char key[64];
size_t tmp_size = PATH_MAX_LENGTH;
char *tmp = (char*)malloc(tmp_size);
char *tmp_rel = (char*)malloc(tmp_size);
char *tmp_base = (char*)malloc(tmp_size);
char *tmp = (char*)malloc(3*tmp_size);
char *tmp_rel = tmp + tmp_size;
char *tmp_base = tmp + 2*tmp_size;
if (!tmp || !tmp_rel || !tmp_base)
if (!tmp)
return;
config_set_int(conf, "shaders", shader->passes);
if (shader->feedback_pass >= 0)
config_set_int(conf, "feedback_pass", shader->feedback_pass);
if (preset_path)
{
strlcpy(tmp_base, preset_path, tmp_size);
/* ensure we use a clean base like the shader passes and texture paths do */
path_resolve_realpath(tmp_base, tmp_size);
path_basedir(tmp_base);
}
for (i = 0; i < shader->passes; i++)
{
const struct video_shader_pass *pass = &shader->pass[i];
snprintf(key, sizeof(key), "shader%u", i);
strlcpy(tmp, pass->source.path, tmp_size);
if (preset_path)
{
strlcpy(tmp_base, preset_path, tmp_size);
path_basedir(tmp_base);
strlcpy(tmp, pass->source.path, tmp_size);
path_relative_to(tmp_rel, tmp, tmp_base, tmp_size);
make_relative_path_portable(tmp_rel);
config_set_path(conf, key, tmp_rel);
}
else
config_set_path(conf, key, tmp);
config_set_path(conf, key, pass->source.path);
if (pass->filter != RARCH_FILTER_UNSPEC)
@ -794,9 +805,6 @@ void video_shader_write_conf_preset(config_file_t *conf,
shader_write_fbo(conf, &pass->fbo, i);
}
free(tmp);
free(tmp_rel);
free(tmp_base);
if (shader->num_parameters)
{
@ -853,7 +861,16 @@ void video_shader_write_conf_preset(config_file_t *conf,
key[0] = '\0';
config_set_string(conf, shader->lut[i].id, shader->lut[i].path);
if (preset_path)
{
strlcpy(tmp, shader->lut[i].path, tmp_size);
path_relative_to(tmp_rel, tmp, tmp_base, tmp_size);
make_relative_path_portable(tmp_rel);
config_set_path(conf, shader->lut[i].id, tmp_rel);
}
else
config_set_path(conf, shader->lut[i].id, shader->lut[i].path);
if (shader->lut[i].filter != RARCH_FILTER_UNSPEC)
{
@ -874,6 +891,8 @@ void video_shader_write_conf_preset(config_file_t *conf,
}
}
}
free(tmp);
}
const char *video_shader_to_str(enum rarch_shader_type type)
@ -1010,46 +1029,6 @@ enum rarch_shader_type video_shader_parse_type(const char *path)
return video_shader_get_type_from_ext(path_get_extension(path), &is_preset);
}
/**
* video_shader_resolve_relative:
* @shader : Shader pass handle.
* @ref_path : Relative shader path.
*
* Resolves relative shader path (@ref_path) into absolute
* shader paths.
**/
void video_shader_resolve_relative(struct video_shader *shader,
const char *ref_path)
{
unsigned i;
size_t tmp_path_size = 4096 * sizeof(char);
char *tmp_path = (char*)malloc(tmp_path_size);
if (!tmp_path)
return;
tmp_path[0] = '\0';
for (i = 0; i < shader->passes; i++)
{
if (!*shader->pass[i].source.path)
continue;
strlcpy(tmp_path, shader->pass[i].source.path, tmp_path_size);
fill_pathname_resolve_relative(shader->pass[i].source.path,
ref_path, tmp_path, sizeof(shader->pass[i].source.path));
}
for (i = 0; i < shader->luts; i++)
{
strlcpy(tmp_path, shader->lut[i].path, tmp_path_size);
fill_pathname_resolve_relative(shader->lut[i].path,
ref_path, tmp_path, sizeof(shader->lut[i].path));
}
free(tmp_path);
}
bool video_shader_check_for_changes(void)
{
if (!file_change_data)

View File

@ -163,14 +163,14 @@ struct video_shader
* video_shader_read_conf_preset:
* @conf : Preset file to read from.
* @shader : Shader passes handle.
*
* @ref_path : Base path used to resolve relative paths
* Loads preset file and all associated state (passes,
* textures, imports, etc).
*
* Returns: true (1) if successful, otherwise false (0).
**/
bool video_shader_read_conf_preset(config_file_t *conf,
struct video_shader *shader);
struct video_shader *shader, const char* ref_path);
/**
* video_shader_write_conf_preset:
@ -178,25 +178,14 @@ bool video_shader_read_conf_preset(config_file_t *conf,
* @shader : Shader passes handle.
* @preset_path : Optional path to where the preset will be written.
*
* Saves preset and all associated state (passes,
* textures, imports, etc) to disk.
* Writes preset and all associated state (passes,
* textures, imports, etc) into @conf.
* If @preset_path is not NULL, shader paths are saved
* relative to it.
**/
void video_shader_write_conf_preset(config_file_t *conf,
struct video_shader *shader, const char *preset_path);
/**
* video_shader_resolve_relative:
* @shader : Shader pass handle.
* @ref_path : Relative shader path.
*
* Resolves relative shader path (@ref_path) into absolute
* shader paths.
**/
void video_shader_resolve_relative(struct video_shader *shader,
const char *ref_path);
/**
* video_shader_resolve_parameters:
* @conf : Preset file to read from.

View File

@ -804,7 +804,7 @@ void path_resolve_realpath(char *buf, size_t size)
void path_relative_to(char *out,
const char *path, const char *base, size_t size)
{
unsigned i;
size_t i;
const char *trimmed_path, *trimmed_base;
#ifdef _WIN32
@ -813,8 +813,8 @@ void path_relative_to(char *out,
&& path[1] == ':' && base[1] == ':'
&& path[0] != base[0])
{
out[0] = '\0';
strlcat(out, path, size);
strlcpy(out, path, size);
return;
}
#endif
@ -827,8 +827,8 @@ void path_relative_to(char *out,
/* Each segment of base turns into ".." */
out[0] = '\0';
for (i = 0; trimmed_base[i]; i++)
if (trimmed_base[i] == '/' || trimmed_base[i] == '\\')
strlcat(out, "../", size); /* Use '/' as universal separator */
if (trimmed_base[i] == path_default_slash_c())
strlcat(out, ".." path_default_slash(), size);
strlcat(out, trimmed_path, size);
}

View File

@ -138,12 +138,9 @@ bool menu_shader_manager_init(void)
if (
!string_is_empty(new_path) && conf &&
video_shader_read_conf_preset(conf, menu_driver_shader)
video_shader_read_conf_preset(conf, menu_driver_shader, new_path)
)
{
video_shader_resolve_relative(menu_driver_shader, new_path);
video_shader_resolve_parameters(conf, menu_driver_shader);
}
if (new_path)
free(new_path);
@ -194,11 +191,9 @@ bool menu_shader_manager_set_preset(void *data,
RARCH_LOG("Setting Menu shader: %s.\n", preset_path);
if (video_shader_read_conf_preset(conf, shader))
{
video_shader_resolve_relative(shader, preset_path);
if (video_shader_read_conf_preset(conf, shader, preset_path))
video_shader_resolve_parameters(conf, shader);
}
config_file_free(conf);
#ifdef HAVE_MENU