mirror of
https://github.com/libretro/RetroArch
synced 2025-02-09 00:40:09 +00:00
Merge pull request #3316 from Themaister/master
Vulkan: Add shader parameters
This commit is contained in:
commit
1ec84ca44d
@ -16,6 +16,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <streams/file_stream.h>
|
||||
#include <lists/string_list.h>
|
||||
@ -252,6 +253,9 @@ static glslang_format glslang_find_format(const char *fmt)
|
||||
|
||||
static bool glslang_parse_meta(const vector<string> &lines, glslang_meta *meta)
|
||||
{
|
||||
char id[64] = {};
|
||||
char desc[64] = {};
|
||||
|
||||
*meta = glslang_meta{};
|
||||
for (auto &line : lines)
|
||||
{
|
||||
@ -268,6 +272,46 @@ static bool glslang_parse_meta(const vector<string> &lines, glslang_meta *meta)
|
||||
str++;
|
||||
meta->name = str;
|
||||
}
|
||||
else if (line.find("#pragma parameter ") == 0)
|
||||
{
|
||||
float initial, minimum, maximum, step;
|
||||
int ret = sscanf(line.c_str(), "#pragma parameter %63s \"%63[^\"]\" %f %f %f %f",
|
||||
id, desc, &initial, &minimum, &maximum, &step);
|
||||
|
||||
if (ret == 5)
|
||||
{
|
||||
step = 0.1f * (maximum - minimum);
|
||||
ret = 6;
|
||||
}
|
||||
|
||||
if (ret == 6)
|
||||
{
|
||||
auto itr = find_if(begin(meta->parameters), end(meta->parameters), [&](const glslang_parameter ¶m) {
|
||||
return param.id == id;
|
||||
});
|
||||
|
||||
// Allow duplicate #pragma parameter, but only if they are exactly the same.
|
||||
if (itr != end(meta->parameters))
|
||||
{
|
||||
if (itr->desc != desc ||
|
||||
itr->initial != initial ||
|
||||
itr->minimum != minimum ||
|
||||
itr->maximum != maximum ||
|
||||
itr->step != step)
|
||||
{
|
||||
RARCH_ERR("[slang]: Duplicate parameters found for \"%s\", but arguments do not match.\n", id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
meta->parameters.push_back({ id, desc, initial, minimum, maximum, step });
|
||||
}
|
||||
else
|
||||
{
|
||||
RARCH_ERR("[slang]: Invalid #pragma parameter line: \"%s\".\n", line.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (line.find("#pragma format ") == 0)
|
||||
{
|
||||
if (meta->rt_format != SLANG_FORMAT_UNKNOWN)
|
||||
|
@ -63,8 +63,19 @@ enum glslang_format
|
||||
SLANG_FORMAT_UNKNOWN
|
||||
};
|
||||
|
||||
struct glslang_parameter
|
||||
{
|
||||
std::string id;
|
||||
std::string desc;
|
||||
float initial;
|
||||
float minimum;
|
||||
float maximum;
|
||||
float step;
|
||||
};
|
||||
|
||||
struct glslang_meta
|
||||
{
|
||||
std::vector<glslang_parameter> parameters;
|
||||
std::string name;
|
||||
glslang_format rt_format = SLANG_FORMAT_UNKNOWN;
|
||||
};
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
@ -323,7 +324,7 @@ struct CommonResources
|
||||
|
||||
unordered_map<string, slang_texture_semantic_map> texture_semantic_map;
|
||||
unordered_map<string, slang_texture_semantic_map> texture_semantic_uniform_map;
|
||||
unordered_map<string, slang_semantic> semantic_map;
|
||||
unique_ptr<video_shader> shader_preset;
|
||||
|
||||
VkDevice device;
|
||||
};
|
||||
@ -432,6 +433,8 @@ class Pass
|
||||
pass_number = pass;
|
||||
}
|
||||
|
||||
void add_parameter(unsigned parameter_index, const std::string &id);
|
||||
|
||||
void end_frame();
|
||||
void allocate_buffers();
|
||||
|
||||
@ -488,6 +491,7 @@ class Pass
|
||||
void build_semantic_vec4(uint8_t *data, slang_semantic semantic,
|
||||
unsigned width, unsigned height);
|
||||
void build_semantic_uint(uint8_t *data, slang_semantic semantic, uint32_t value);
|
||||
void build_semantic_parameter(uint8_t *data, unsigned index, float value);
|
||||
void build_semantic_texture_vec4(uint8_t *data,
|
||||
slang_texture_semantic semantic,
|
||||
unsigned width, unsigned height);
|
||||
@ -505,6 +509,16 @@ class Pass
|
||||
|
||||
size_t ubo_offset = 0;
|
||||
string pass_name;
|
||||
|
||||
struct Parameter
|
||||
{
|
||||
string id;
|
||||
unsigned index;
|
||||
unsigned semantic_index;
|
||||
};
|
||||
|
||||
vector<Parameter> parameters;
|
||||
vector<Parameter> filtered_parameters;
|
||||
};
|
||||
|
||||
// struct here since we're implementing the opaque typedef from C.
|
||||
@ -516,12 +530,12 @@ struct vulkan_filter_chain
|
||||
|
||||
inline void set_shader_preset(unique_ptr<video_shader> shader)
|
||||
{
|
||||
shader_preset = move(shader);
|
||||
common.shader_preset = move(shader);
|
||||
}
|
||||
|
||||
inline video_shader *get_shader_preset()
|
||||
{
|
||||
return shader_preset.get();
|
||||
return common.shader_preset.get();
|
||||
}
|
||||
|
||||
void set_pass_info(unsigned pass,
|
||||
@ -544,6 +558,7 @@ struct vulkan_filter_chain
|
||||
void set_pass_name(unsigned pass, const char *name);
|
||||
|
||||
void add_static_texture(unique_ptr<StaticTexture> texture);
|
||||
void add_parameter(unsigned pass, unsigned parameter_index, const std::string &id);
|
||||
void release_staging_buffers();
|
||||
|
||||
private:
|
||||
@ -563,8 +578,6 @@ struct vulkan_filter_chain
|
||||
vulkan_filter_chain_swapchain_info swapchain_info;
|
||||
unsigned current_sync_index;
|
||||
|
||||
unique_ptr<video_shader> shader_preset;
|
||||
|
||||
void flush();
|
||||
|
||||
void set_num_passes(unsigned passes);
|
||||
@ -610,6 +623,11 @@ void vulkan_filter_chain::set_swapchain_info(
|
||||
set_num_sync_indices(info.num_indices);
|
||||
}
|
||||
|
||||
void vulkan_filter_chain::add_parameter(unsigned pass, unsigned index, const std::string &id)
|
||||
{
|
||||
passes[pass]->add_parameter(index, id);
|
||||
}
|
||||
|
||||
void vulkan_filter_chain::set_num_sync_indices(unsigned num_indices)
|
||||
{
|
||||
execute_deferred();
|
||||
@ -852,7 +870,6 @@ bool vulkan_filter_chain::init_alias()
|
||||
{
|
||||
common.texture_semantic_map.clear();
|
||||
common.texture_semantic_uniform_map.clear();
|
||||
common.semantic_map.clear();
|
||||
|
||||
unsigned i = 0;
|
||||
for (auto &pass : passes)
|
||||
@ -1213,6 +1230,11 @@ Pass::~Pass()
|
||||
clear_vk();
|
||||
}
|
||||
|
||||
void Pass::add_parameter(unsigned index, const std::string &id)
|
||||
{
|
||||
parameters.push_back({ id, index, unsigned(parameters.size()) });
|
||||
}
|
||||
|
||||
void Pass::set_shader(VkShaderStageFlags stage,
|
||||
const uint32_t *spirv,
|
||||
size_t spirv_words)
|
||||
@ -1693,15 +1715,33 @@ bool Pass::build()
|
||||
pass_info.rt_format, pass_info.max_levels));
|
||||
}
|
||||
|
||||
unordered_map<string, slang_semantic_map> semantic_map;
|
||||
unsigned j = 0;
|
||||
for (auto ¶m : parameters)
|
||||
{
|
||||
if (!set_unique_map(semantic_map, param.id,
|
||||
slang_semantic_map{ SLANG_SEMANTIC_FLOAT_PARAMETER, j }))
|
||||
return false;
|
||||
j++;
|
||||
}
|
||||
|
||||
reflection = slang_reflection{};
|
||||
reflection.pass_number = pass_number;
|
||||
reflection.texture_semantic_map = &common->texture_semantic_map;
|
||||
reflection.texture_semantic_uniform_map = &common->texture_semantic_uniform_map;
|
||||
reflection.semantic_map = &common->semantic_map;
|
||||
reflection.semantic_map = &semantic_map;
|
||||
|
||||
if (!slang_reflect_spirv(vertex_shader, fragment_shader, &reflection))
|
||||
return false;
|
||||
|
||||
// Filter out parameters which we will never use anyways.
|
||||
filtered_parameters.clear();
|
||||
for (unsigned i = 0; i < reflection.semantic_float_parameters.size(); i++)
|
||||
{
|
||||
if (reflection.semantic_float_parameters[i].uniform)
|
||||
filtered_parameters.push_back(parameters[i]);
|
||||
}
|
||||
|
||||
if (!init_pipeline())
|
||||
return false;
|
||||
|
||||
@ -1801,6 +1841,13 @@ void Pass::build_semantic_vec4(uint8_t *data, slang_semantic semantic,
|
||||
}
|
||||
}
|
||||
|
||||
void Pass::build_semantic_parameter(uint8_t *data, unsigned index, float value)
|
||||
{
|
||||
// We will have filtered out stale parameters.
|
||||
if (data)
|
||||
*reinterpret_cast<float*>(data + reflection.semantic_float_parameters[index].ubo_offset) = value;
|
||||
}
|
||||
|
||||
void Pass::build_semantic_uint(uint8_t *data, slang_semantic semantic,
|
||||
uint32_t value)
|
||||
{
|
||||
@ -1853,6 +1900,13 @@ void Pass::build_semantics(VkDescriptorSet set, uint8_t *buffer,
|
||||
// ORIGINAL_HISTORY[0] is an alias of ORIGINAL.
|
||||
build_semantic_texture_array(set, buffer, SLANG_TEXTURE_SEMANTIC_ORIGINAL_HISTORY, 0, original);
|
||||
|
||||
// Parameters.
|
||||
for (auto ¶m : filtered_parameters)
|
||||
{
|
||||
float value = common->shader_preset->parameters[param.index].current;
|
||||
build_semantic_parameter(buffer, param.semantic_index, value);
|
||||
}
|
||||
|
||||
// Previous inputs.
|
||||
unsigned i = 0;
|
||||
for (auto &texture : common->original_history)
|
||||
@ -2736,7 +2790,6 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
|
||||
return nullptr;
|
||||
|
||||
video_shader_resolve_relative(shader.get(), path);
|
||||
video_shader_resolve_parameters(conf.get(), shader.get());
|
||||
|
||||
bool last_pass_is_fbo = shader->pass[shader->passes - 1].fbo.valid;
|
||||
auto tmpinfo = *info;
|
||||
@ -2749,6 +2802,8 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
|
||||
if (shader->luts && !vulkan_filter_chain_load_luts(info, chain.get(), shader.get()))
|
||||
return nullptr;
|
||||
|
||||
shader->num_parameters = 0;
|
||||
|
||||
for (unsigned i = 0; i < shader->passes; i++)
|
||||
{
|
||||
const video_shader_pass *pass = &shader->pass[i];
|
||||
@ -2765,6 +2820,49 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto &meta_param : output.meta.parameters)
|
||||
{
|
||||
if (shader->num_parameters >= GFX_MAX_PARAMETERS)
|
||||
{
|
||||
RARCH_ERR("[Vulkan]: Exceeded maximum number of parameters.\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto itr = find_if(shader->parameters, shader->parameters + shader->num_parameters,
|
||||
[&](const video_shader_parameter ¶m) {
|
||||
return meta_param.id == param.id;
|
||||
});
|
||||
|
||||
if (itr != shader->parameters + shader->num_parameters)
|
||||
{
|
||||
// Allow duplicate #pragma parameter, but only if they are exactly the same.
|
||||
if (meta_param.desc != itr->desc ||
|
||||
meta_param.initial != itr->initial ||
|
||||
meta_param.minimum != itr->minimum ||
|
||||
meta_param.maximum != itr->maximum ||
|
||||
meta_param.step != itr->step)
|
||||
{
|
||||
RARCH_ERR("[Vulkan]: Duplicate parameters found for \"%s\", but arguments do not match.\n",
|
||||
itr->id);
|
||||
return nullptr;
|
||||
}
|
||||
chain->add_parameter(i, itr - shader->parameters, meta_param.id);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ¶m = shader->parameters[shader->num_parameters];
|
||||
strlcpy(param.id, meta_param.id.c_str(), sizeof(param.id));
|
||||
strlcpy(param.desc, meta_param.desc.c_str(), sizeof(param.desc));
|
||||
param.current = meta_param.initial;
|
||||
param.initial = meta_param.initial;
|
||||
param.minimum = meta_param.minimum;
|
||||
param.maximum = meta_param.maximum;
|
||||
param.step = meta_param.step;
|
||||
chain->add_parameter(i, shader->num_parameters, meta_param.id);
|
||||
shader->num_parameters++;
|
||||
}
|
||||
}
|
||||
|
||||
chain->set_shader(i,
|
||||
VK_SHADER_STAGE_VERTEX_BIT,
|
||||
output.vertex.data(),
|
||||
@ -2917,6 +3015,9 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
|
||||
sizeof(opaque_frag) / sizeof(uint32_t));
|
||||
}
|
||||
|
||||
if (!video_shader_resolve_current_parameters(conf.get(), shader.get()))
|
||||
return nullptr;
|
||||
|
||||
chain->set_shader_preset(move(shader));
|
||||
|
||||
if (!chain->init())
|
||||
|
@ -134,13 +134,18 @@ static slang_texture_semantic slang_uniform_name_to_texture_semantic(
|
||||
}
|
||||
|
||||
static slang_semantic slang_uniform_name_to_semantic(
|
||||
const unordered_map<string, slang_semantic> &semantic_map,
|
||||
const string &name)
|
||||
const unordered_map<string, slang_semantic_map> &semantic_map,
|
||||
const string &name, unsigned *index)
|
||||
{
|
||||
auto itr = semantic_map.find(name);
|
||||
if (itr != end(semantic_map))
|
||||
return itr->second;
|
||||
{
|
||||
*index = itr->second.index;
|
||||
return itr->second.semantic;
|
||||
}
|
||||
|
||||
// No builtin semantics are arrayed.
|
||||
*index = 0;
|
||||
unsigned i = 0;
|
||||
for (auto n : semantic_uniform_names)
|
||||
{
|
||||
@ -183,6 +188,29 @@ static bool set_ubo_texture_offset(slang_reflection *reflection,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool set_ubo_float_parameter_offset(slang_reflection *reflection,
|
||||
unsigned index, size_t offset, unsigned num_components)
|
||||
{
|
||||
resize_minimum(reflection->semantic_float_parameters, index + 1);
|
||||
auto &sem = reflection->semantic_float_parameters[index];
|
||||
|
||||
if (sem.uniform)
|
||||
{
|
||||
if (sem.ubo_offset != offset)
|
||||
{
|
||||
RARCH_ERR("[slang]: Vertex and fragment have different offsets for same parameter #%u (%u vs. %u).\n",
|
||||
index,
|
||||
unsigned(sem.ubo_offset),
|
||||
unsigned(offset));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
sem.uniform = true;
|
||||
sem.ubo_offset = offset;
|
||||
sem.num_components = num_components;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool set_ubo_offset(slang_reflection *reflection, slang_semantic semantic,
|
||||
size_t offset, unsigned num_components)
|
||||
{
|
||||
@ -230,6 +258,10 @@ static bool validate_type_for_semantic(const SPIRType &type, slang_semantic sem)
|
||||
// uint
|
||||
return type.basetype == SPIRType::UInt && type.vecsize == 1 && type.columns == 1;
|
||||
|
||||
case SLANG_SEMANTIC_FLOAT_PARAMETER:
|
||||
// float
|
||||
return type.basetype == SPIRType::Float && type.vecsize == 1 && type.columns == 1;
|
||||
|
||||
default:
|
||||
// vec4
|
||||
return type.basetype == SPIRType::Float && type.vecsize == 4 && type.columns == 1;
|
||||
@ -253,8 +285,9 @@ static bool add_active_buffer_ranges(const Compiler &compiler, const Resource &r
|
||||
auto &name = compiler.get_member_name(resource.base_type_id, range.index);
|
||||
auto &type = compiler.get_type(compiler.get_type(resource.base_type_id).member_types[range.index]);
|
||||
|
||||
unsigned sem_index = 0;
|
||||
unsigned tex_sem_index = 0;
|
||||
auto sem = slang_uniform_name_to_semantic(*reflection->semantic_map, name);
|
||||
auto sem = slang_uniform_name_to_semantic(*reflection->semantic_map, name, &sem_index);
|
||||
auto tex_sem = slang_uniform_name_to_texture_semantic(*reflection->texture_semantic_uniform_map,
|
||||
name, &tex_sem_index);
|
||||
|
||||
@ -273,8 +306,18 @@ static bool add_active_buffer_ranges(const Compiler &compiler, const Resource &r
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (sem)
|
||||
{
|
||||
case SLANG_SEMANTIC_FLOAT_PARAMETER:
|
||||
if (!set_ubo_float_parameter_offset(reflection, sem_index, range.offset, type.vecsize))
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!set_ubo_offset(reflection, sem, range.offset, type.vecsize))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (tex_sem != SLANG_INVALID_TEXTURE_SEMANTIC)
|
||||
{
|
||||
@ -510,6 +553,16 @@ static bool slang_reflect(const Compiler &vertex_compiler, const Compiler &fragm
|
||||
}
|
||||
}
|
||||
|
||||
RARCH_LOG("[slang]:\n");
|
||||
RARCH_LOG("[slang]: Parameters:\n");
|
||||
unsigned i = 0;
|
||||
for (auto ¶m : reflection->semantic_float_parameters)
|
||||
{
|
||||
if (param.uniform)
|
||||
RARCH_LOG("[slang]: #%u (Offset: %u)\n", i, param.ubo_offset);
|
||||
i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -59,10 +59,16 @@ enum slang_texture_semantic
|
||||
|
||||
enum slang_semantic
|
||||
{
|
||||
// mat4, MVP
|
||||
SLANG_SEMANTIC_MVP = 0,
|
||||
// vec4, viewport size of current pass
|
||||
SLANG_SEMANTIC_OUTPUT = 1,
|
||||
// vec4, viewport size of final pass
|
||||
SLANG_SEMANTIC_FINAL_VIEWPORT = 2,
|
||||
// uint, frame count with modulo
|
||||
SLANG_SEMANTIC_FRAME_COUNT = 3,
|
||||
// float, user defined parameter, arrayed
|
||||
SLANG_SEMANTIC_FLOAT_PARAMETER = 4,
|
||||
|
||||
SLANG_NUM_SEMANTICS,
|
||||
SLANG_INVALID_SEMANTIC = -1
|
||||
@ -100,6 +106,12 @@ struct slang_texture_semantic_map
|
||||
unsigned index;
|
||||
};
|
||||
|
||||
struct slang_semantic_map
|
||||
{
|
||||
slang_semantic semantic;
|
||||
unsigned index;
|
||||
};
|
||||
|
||||
struct slang_reflection
|
||||
{
|
||||
slang_reflection();
|
||||
@ -110,10 +122,11 @@ struct slang_reflection
|
||||
|
||||
std::vector<slang_texture_semantic_meta> semantic_textures[SLANG_NUM_TEXTURE_SEMANTICS];
|
||||
slang_semantic_meta semantics[SLANG_NUM_SEMANTICS];
|
||||
std::vector<slang_semantic_meta> semantic_float_parameters;
|
||||
|
||||
const std::unordered_map<std::string, slang_texture_semantic_map> *texture_semantic_map = nullptr;
|
||||
const std::unordered_map<std::string, slang_texture_semantic_map> *texture_semantic_uniform_map = nullptr;
|
||||
const std::unordered_map<std::string, slang_semantic> *semantic_map = nullptr;
|
||||
const std::unordered_map<std::string, slang_semantic_map> *semantic_map = nullptr;
|
||||
unsigned pass_number = 0;
|
||||
};
|
||||
|
||||
|
@ -391,6 +391,48 @@ static struct video_shader_parameter *video_shader_parse_find_parameter(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* video_shader_set_current_parameters:
|
||||
* @conf : Preset file to read from.
|
||||
* @shader : Shader passes handle.
|
||||
*
|
||||
* Reads the current value for all parameters from config file.
|
||||
*
|
||||
* Returns: true (1) if successful, otherwise false (0).
|
||||
**/
|
||||
bool video_shader_resolve_current_parameters(config_file_t *conf,
|
||||
struct video_shader *shader)
|
||||
{
|
||||
if (!conf)
|
||||
return false;
|
||||
|
||||
/* Read in parameters which override the defaults. */
|
||||
char parameters[4096] = {0};
|
||||
const char *id = NULL;
|
||||
char *save = NULL;
|
||||
|
||||
if (!config_get_array(conf, "parameters",
|
||||
parameters, sizeof(parameters)))
|
||||
return true;
|
||||
|
||||
for (id = strtok_r(parameters, ";", &save); id;
|
||||
id = strtok_r(NULL, ";", &save))
|
||||
{
|
||||
struct video_shader_parameter *parameter = (struct video_shader_parameter*)
|
||||
video_shader_parse_find_parameter(shader->parameters, shader->num_parameters, id);
|
||||
|
||||
if (!parameter)
|
||||
{
|
||||
RARCH_WARN("[CGP/GLSLP]: Parameter %s is set in the preset, but no shader uses this parameter, ignoring.\n", id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!config_get_float(conf, id, ¶meter->current))
|
||||
RARCH_WARN("[CGP/GLSLP]: Parameter %s is not set in preset.\n", id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* video_shader_resolve_parameters:
|
||||
* @conf : Preset file to read from.
|
||||
@ -447,33 +489,8 @@ bool video_shader_resolve_parameters(config_file_t *conf,
|
||||
filestream_close(file);
|
||||
}
|
||||
|
||||
if (conf)
|
||||
{
|
||||
/* Read in parameters which override the defaults. */
|
||||
char parameters[4096] = {0};
|
||||
const char *id = NULL;
|
||||
char *save = NULL;
|
||||
|
||||
if (!config_get_array(conf, "parameters",
|
||||
parameters, sizeof(parameters)))
|
||||
return true;
|
||||
|
||||
for (id = strtok_r(parameters, ";", &save); id;
|
||||
id = strtok_r(NULL, ";", &save))
|
||||
{
|
||||
struct video_shader_parameter *parameter = (struct video_shader_parameter*)
|
||||
video_shader_parse_find_parameter(shader->parameters, shader->num_parameters, id);
|
||||
|
||||
if (!parameter)
|
||||
{
|
||||
RARCH_WARN("[CGP/GLSLP]: Parameter %s is set in the preset, but no shader uses this parameter, ignoring.\n", id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!config_get_float(conf, id, ¶meter->current))
|
||||
RARCH_WARN("[CGP/GLSLP]: Parameter %s is not set in preset.\n", id);
|
||||
}
|
||||
}
|
||||
if (conf && !video_shader_resolve_current_parameters(conf, shader))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -192,6 +192,18 @@ void video_shader_write_conf_cgp(config_file_t *conf,
|
||||
void video_shader_resolve_relative(struct video_shader *shader,
|
||||
const char *ref_path);
|
||||
|
||||
/**
|
||||
* video_shader_resolve_parameters:
|
||||
* @conf : Preset file to read from.
|
||||
* @shader : Shader passes handle.
|
||||
*
|
||||
* Reads the current value for all parameters from config file.
|
||||
*
|
||||
* Returns: true (1) if successful, otherwise false (0).
|
||||
**/
|
||||
bool video_shader_resolve_current_parameters(config_file_t *conf,
|
||||
struct video_shader *shader);
|
||||
|
||||
/**
|
||||
* video_shader_resolve_parameters:
|
||||
* @conf : Preset file to read from.
|
||||
|
Loading…
x
Reference in New Issue
Block a user