Merge pull request #706 from libretro/shader-parameter

Shader parameter
This commit is contained in:
Twinaphex 2014-05-27 16:28:06 +02:00
commit a56d57c615
14 changed files with 380 additions and 70 deletions

View File

@ -358,6 +358,8 @@ typedef struct video_poke_interface
void (*show_mouse)(void *data, bool state);
void (*grab_mouse_toggle)(void *data);
struct gfx_shader *(*get_current_shader)(void *data);
} video_poke_interface_t;
typedef struct video_driver

View File

@ -43,6 +43,17 @@
#endif
#endif
#ifdef HAVE_SHADER_MANAGER
static inline struct gfx_shader *shader_manager_get_current_shader(rgui_handle_t *rgui, unsigned type)
{
struct gfx_shader *shader = type == RGUI_SETTINGS_SHADER_PRESET_PARAMETERS ? &rgui->shader : NULL;
if (!shader && driver.video_poke && driver.video_data && driver.video_poke->get_current_shader)
shader = driver.video_poke->get_current_shader(driver.video_data);
return shader;
}
#endif
static void menu_common_entries_init(void *data, unsigned menu_type)
{
rgui_handle_t *rgui = (rgui_handle_t*)data;
@ -51,6 +62,18 @@ static void menu_common_entries_init(void *data, unsigned menu_type)
switch (menu_type)
{
#ifdef HAVE_SHADER_MANAGER
case RGUI_SETTINGS_SHADER_PARAMETERS:
case RGUI_SETTINGS_SHADER_PRESET_PARAMETERS:
{
file_list_clear(rgui->selection_buf);
struct gfx_shader *shader = shader_manager_get_current_shader(rgui, menu_type);
if (shader)
for (i = 0; i < shader->num_parameters; i++)
file_list_push(rgui->selection_buf, shader->parameters[i].desc, RGUI_SETTINGS_SHADER_PARAMETER_0 + i, 0);
rgui->parameter_shader = shader;
break;
}
case RGUI_SETTINGS_SHADER_OPTIONS:
file_list_clear(rgui->selection_buf);
file_list_push(rgui->selection_buf, "Apply Shader Changes",
@ -60,6 +83,10 @@ static void menu_common_entries_init(void *data, unsigned menu_type)
RGUI_SETTINGS_SHADER_PRESET, 0);
file_list_push(rgui->selection_buf, "Save As Shader Preset",
RGUI_SETTINGS_SHADER_PRESET_SAVE, 0);
file_list_push(rgui->selection_buf, "Parameters (Current)",
RGUI_SETTINGS_SHADER_PARAMETERS, 0);
file_list_push(rgui->selection_buf, "Parameters (RGUI)",
RGUI_SETTINGS_SHADER_PRESET_PARAMETERS, 0);
file_list_push(rgui->selection_buf, "Shader Passes",
RGUI_SETTINGS_SHADER_PASSES, 0);
@ -506,6 +533,8 @@ static unsigned menu_common_type_is(unsigned type)
type == RGUI_SETTINGS_VIDEO_OPTIONS ||
type == RGUI_SETTINGS_FONT_OPTIONS ||
type == RGUI_SETTINGS_SHADER_OPTIONS ||
type == RGUI_SETTINGS_SHADER_PARAMETERS ||
type == RGUI_SETTINGS_SHADER_PRESET_PARAMETERS ||
type == RGUI_SETTINGS_AUDIO_OPTIONS ||
type == RGUI_SETTINGS_DISK_OPTIONS ||
type == RGUI_SETTINGS_PATH_OPTIONS ||
@ -673,7 +702,7 @@ static int menu_settings_iterate(void *data, unsigned action)
file_list_get_last(rgui->menu_stack, &dir, &menu_type);
if (rgui->need_refresh && !(menu_type == RGUI_FILE_DIRECTORY ||
menu_common_type_is(menu_type) == RGUI_SETTINGS_SHADER_OPTIONS||
menu_common_type_is(menu_type) == RGUI_SETTINGS_SHADER_OPTIONS ||
menu_common_type_is(menu_type) == RGUI_FILE_DIRECTORY ||
menu_type == RGUI_SETTINGS_VIDEO_SOFTFILTER ||
menu_type == RGUI_SETTINGS_AUDIO_DSP_FILTER ||
@ -700,6 +729,8 @@ static int menu_settings_iterate(void *data, unsigned action)
|| menu_type == RGUI_SETTINGS_VIDEO_OPTIONS
|| menu_type == RGUI_SETTINGS_FONT_OPTIONS
|| menu_type == RGUI_SETTINGS_SHADER_OPTIONS
|| menu_type == RGUI_SETTINGS_SHADER_PARAMETERS
|| menu_type == RGUI_SETTINGS_SHADER_PRESET_PARAMETERS
)
menu_common_entries_init(rgui, menu_type);
else
@ -1363,6 +1394,9 @@ static int menu_common_iterate(void *data, unsigned action)
unsigned pass = (menu_type - RGUI_SETTINGS_SHADER_0) / 3;
fill_pathname_join(rgui->shader.pass[pass].source.path,
dir, path, sizeof(rgui->shader.pass[pass].source.path));
// This will reset any changed parameters.
gfx_shader_resolve_parameters(NULL, &rgui->shader);
}
// Pop stack until we hit shader manager again.
@ -1673,7 +1707,10 @@ static void menu_common_shader_manager_init(void *data)
if (conf)
{
if (gfx_shader_read_conf_cgp(conf, &rgui->shader))
{
gfx_shader_resolve_relative(&rgui->shader, g_settings.video.shader_path);
gfx_shader_resolve_parameters(conf, &rgui->shader);
}
config_file_free(conf);
}
}
@ -1700,7 +1737,10 @@ static void menu_common_shader_manager_init(void *data)
if (conf)
{
if (gfx_shader_read_conf_cgp(conf, &rgui->shader))
{
gfx_shader_resolve_relative(&rgui->shader, cgp_path);
gfx_shader_resolve_parameters(conf, &rgui->shader);
}
config_file_free(conf);
}
}
@ -1733,6 +1773,7 @@ static void menu_common_shader_manager_set_preset(void *data, unsigned type, con
{
gfx_shader_read_conf_cgp(conf, shader);
gfx_shader_resolve_relative(shader, path);
gfx_shader_resolve_parameters(conf, shader);
config_file_free(conf);
}
@ -1758,9 +1799,20 @@ static void menu_common_shader_manager_get_str(void *data, char *type_str, size_
struct gfx_shader *shader = (struct gfx_shader*)data;
if (type == RGUI_SETTINGS_SHADER_APPLY)
*type_str = '\0';
else if (type >= RGUI_SETTINGS_SHADER_PARAMETER_0 && type <= RGUI_SETTINGS_SHADER_PARAMETER_LAST)
{
// rgui->parameter_shader here.
if (shader)
{
const struct gfx_shader_parameter *param = &shader->parameters[type - RGUI_SETTINGS_SHADER_PARAMETER_0];
snprintf(type_str, type_str_size, "%.2f [%.2f %.2f]", param->current, param->minimum, param->maximum);
}
else
*type_str = '\0';
}
else if (type == RGUI_SETTINGS_SHADER_PASSES)
snprintf(type_str, type_str_size, "%u", shader->passes);
else
else if (type >= RGUI_SETTINGS_SHADER_0 && type <= RGUI_SETTINGS_SHADER_LAST)
{
unsigned pass = (type - RGUI_SETTINGS_SHADER_0) / 3;
switch ((type - RGUI_SETTINGS_SHADER_0) % 3)
@ -1801,6 +1853,8 @@ static void menu_common_shader_manager_get_str(void *data, char *type_str, size_
}
}
}
else
*type_str = '\0';
#endif
}
@ -1959,10 +2013,42 @@ static int menu_common_shader_manager_setting_toggle(void *data, unsigned settin
break;
}
}
else if ((setting == RGUI_SETTINGS_SHADER_PARAMETERS || setting == RGUI_SETTINGS_SHADER_PRESET_PARAMETERS) && action == RGUI_ACTION_OK)
{
file_list_push(rgui->menu_stack, "", setting, rgui->selection_ptr);
menu_clear_navigation(rgui);
rgui->need_refresh = true;
}
else if (setting >= RGUI_SETTINGS_SHADER_PARAMETER_0 && setting <= RGUI_SETTINGS_SHADER_PARAMETER_LAST)
{
if (!rgui->parameter_shader)
return 0;
struct gfx_shader_parameter *param = &rgui->parameter_shader->parameters[setting - RGUI_SETTINGS_SHADER_PARAMETER_0];
switch (action)
{
case RGUI_ACTION_START:
param->current = param->initial;
break;
case RGUI_ACTION_LEFT:
param->current -= param->step;
break;
case RGUI_ACTION_RIGHT:
param->current += param->step;
break;
default:
break;
}
param->current = min(max(param->minimum, param->current), param->maximum);
}
else if ((setting == RGUI_SETTINGS_SHADER_APPLY || setting == RGUI_SETTINGS_SHADER_PASSES) &&
(driver.menu_ctx && driver.menu_ctx->backend && driver.menu_ctx->backend->setting_set))
driver.menu_ctx->backend->setting_set(rgui, setting, action);
else if ((dist_shader % 3) == 0 || setting == RGUI_SETTINGS_SHADER_PRESET)
else if (((dist_shader % 3) == 0 || setting == RGUI_SETTINGS_SHADER_PRESET))
{
dist_shader /= 3;
struct gfx_shader_pass *pass = setting == RGUI_SETTINGS_SHADER_PRESET ?
@ -3603,6 +3689,7 @@ static int menu_common_setting_set(void *data, unsigned setting, unsigned action
{
case RGUI_ACTION_START:
rgui->shader.passes = 0;
rgui->need_refresh = true;
break;
case RGUI_ACTION_LEFT:
@ -3626,9 +3713,8 @@ static int menu_common_setting_set(void *data, unsigned setting, unsigned action
break;
}
#ifndef HAVE_RMENU
rgui->need_refresh = true;
#endif
if (rgui->need_refresh)
gfx_shader_resolve_parameters(NULL, &rgui->shader);
break;
case RGUI_SETTINGS_SHADER_APPLY:
{

View File

@ -62,7 +62,11 @@ typedef enum
RGUI_SETTINGS_SHADER_FILTER,
RGUI_SETTINGS_SHADER_PRESET,
RGUI_SETTINGS_SHADER_APPLY,
RGUI_SETTINGS_SHADER_PARAMETERS, // Modifies current shader directly. Will not get saved to CGP.
RGUI_SETTINGS_SHADER_PRESET_PARAMETERS, // Modifies shader preset currently in RGUI.
RGUI_SETTINGS_SHADER_PASSES,
RGUI_SETTINGS_SHADER_PARAMETER_0,
RGUI_SETTINGS_SHADER_PARAMETER_LAST = RGUI_SETTINGS_SHADER_PARAMETER_0 + (GFX_MAX_PARAMETERS - 1),
RGUI_SETTINGS_SHADER_0,
RGUI_SETTINGS_SHADER_0_FILTER,
RGUI_SETTINGS_SHADER_0_SCALE,

View File

@ -316,6 +316,10 @@ static void rgui_render(void *data)
#ifdef HAVE_SHADER_MANAGER
else if (menu_type == RGUI_SETTINGS_SHADER_OPTIONS)
strlcpy(title, "SHADER OPTIONS", sizeof(title));
else if (menu_type == RGUI_SETTINGS_SHADER_PARAMETERS)
strlcpy(title, "SHADER PARAMETERS (CURRENT)", sizeof(title));
else if (menu_type == RGUI_SETTINGS_SHADER_PRESET_PARAMETERS)
strlcpy(title, "SHADER PARAMETERS (RGUI PRESET)", sizeof(title));
#endif
else if (menu_type == RGUI_SETTINGS_FONT_OPTIONS)
strlcpy(title, "FONT OPTIONS", sizeof(title));
@ -453,13 +457,18 @@ static void rgui_render(void *data)
strlcpy(type_str, "(DIR)", sizeof(type_str));
w = 5;
}
else if (type == RGUI_SETTINGS_SHADER_OPTIONS || type == RGUI_SETTINGS_SHADER_PRESET)
else if (type == RGUI_SETTINGS_SHADER_OPTIONS || type == RGUI_SETTINGS_SHADER_PRESET || type == RGUI_SETTINGS_SHADER_PARAMETERS || type == RGUI_SETTINGS_SHADER_PRESET_PARAMETERS)
strlcpy(type_str, "...", sizeof(type_str));
else if (type == RGUI_SETTINGS_SHADER_FILTER)
snprintf(type_str, sizeof(type_str), "%s",
g_settings.video.smooth ? "Linear" : "Nearest");
else if (driver.menu_ctx && driver.menu_ctx->backend && driver.menu_ctx->backend->shader_manager_get_str)
driver.menu_ctx->backend->shader_manager_get_str(&rgui->shader, type_str, sizeof(type_str), type);
{
if (type >= RGUI_SETTINGS_SHADER_PARAMETER_0 && type <= RGUI_SETTINGS_SHADER_PARAMETER_LAST)
driver.menu_ctx->backend->shader_manager_get_str(rgui->parameter_shader, type_str, sizeof(type_str), type);
else
driver.menu_ctx->backend->shader_manager_get_str(&rgui->shader, type_str, sizeof(type_str), type);
}
}
else
#endif

View File

@ -164,6 +164,7 @@ typedef struct
#ifdef HAVE_SHADER_MANAGER
struct gfx_shader shader;
struct gfx_shader *parameter_shader; // Points to either shader or graphics driver current shader.
#endif
unsigned current_pad;

View File

@ -978,6 +978,7 @@ static void gl_frame_fbo(void *data, const struct gl_tex_info *tex_info)
fbo_info->tex_size[0] = prev_rect->width;
fbo_info->tex_size[1] = prev_rect->height;
memcpy(fbo_info->coord, fbo_tex_coords, sizeof(fbo_tex_coords));
fbo_tex_info_cnt++;
glBindFramebuffer(RARCH_GL_FRAMEBUFFER, gl->fbo[i]);
@ -1002,8 +1003,6 @@ static void gl_frame_fbo(void *data, const struct gl_tex_info *tex_info)
gl_shader_set_coords(gl, &gl->coords, &gl->mvp);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
fbo_tex_info_cnt++;
}
#if defined(GL_FRAMEBUFFER_SRGB) && !defined(HAVE_OPENGLES)
@ -1018,6 +1017,16 @@ static void gl_frame_fbo(void *data, const struct gl_tex_info *tex_info)
set_texture_coords(fbo_tex_coords, xamt, yamt);
// Push final FBO to list.
fbo_info = &fbo_tex_info[gl->fbo_pass - 1];
fbo_info->tex = gl->fbo_texture[gl->fbo_pass - 1];
fbo_info->input_size[0] = prev_rect->img_width;
fbo_info->input_size[1] = prev_rect->img_height;
fbo_info->tex_size[0] = prev_rect->width;
fbo_info->tex_size[1] = prev_rect->height;
memcpy(fbo_info->coord, fbo_tex_coords, sizeof(fbo_tex_coords));
fbo_tex_info_cnt++;
// Render our FBO texture to back buffer.
gl_bind_backbuffer();
if (gl->shader)
@ -2909,6 +2918,12 @@ static void gl_show_mouse(void *data, bool state)
gl->ctx_driver->show_mouse(gl, state);
}
static struct gfx_shader *gl_get_current_shader(void *data)
{
gl_t *gl = (gl_t*)data;
return gl->shader ? gl->shader->get_current_shader() : NULL;
}
static const video_poke_interface_t gl_poke_interface = {
NULL,
#ifdef HAVE_FBO
@ -2924,6 +2939,9 @@ static const video_poke_interface_t gl_poke_interface = {
gl_set_osd_msg,
gl_show_mouse,
NULL,
gl_get_current_shader,
};
static void gl_get_poke_interface(void *data, const video_poke_interface_t **iface)

View File

@ -132,7 +132,6 @@ struct cg_program
};
static struct cg_program prg[GFX_MAX_SHADERS];
static const char **cg_arguments;
static bool cg_active;
static CGprofile cgVProf, cgFProf;
static unsigned active_index;
@ -145,6 +144,8 @@ static GLuint lut_textures[GFX_MAX_TEXTURES];
static CGparameter cg_attribs[PREV_TEXTURES + 1 + 4 + GFX_MAX_SHADERS];
static unsigned cg_attrib_index;
static char cg_alias_define[GFX_MAX_SHADERS][128];
static void gl_cg_reset_attrib(void)
{
unsigned i;
@ -288,7 +289,7 @@ static void gl_cg_set_params(void *data, unsigned width, unsigned height,
}
// Set FBO textures.
if (active_index > 2)
if (active_index)
{
for (i = 0; i < fbo_info_cnt; i++)
{
@ -313,6 +314,15 @@ static void gl_cg_set_params(void *data, unsigned width, unsigned height,
}
}
// #pragma parameters
for (i = 0; i < cg_shader->num_parameters; i++)
{
CGparameter param_v = cgGetNamedParameter(prg[active_index].vprg, cg_shader->parameters[i].id);
CGparameter param_f = cgGetNamedParameter(prg[active_index].fprg, cg_shader->parameters[i].id);
set_param_1f(param_v, cg_shader->parameters[i].current);
set_param_1f(param_f, cg_shader->parameters[i].current);
}
// Set state parameters
if (state_tracker)
{
@ -414,18 +424,30 @@ static bool load_program(unsigned index, const char *prog, bool path_is_file)
char *listing_f = NULL;
char *listing_v = NULL;
unsigned i, argc = 1;
const char *argv[2 + GFX_MAX_SHADERS] = {
"-DPARAMETER_UNIFORM",
NULL,
};
for (i = 0; i < GFX_MAX_SHADERS; i++)
{
if (*(cg_alias_define[i]))
argv[argc++] = cg_alias_define[i];
}
if (path_is_file)
{
prg[index].fprg = cgCreateProgramFromFile(cgCtx, CG_SOURCE, prog, cgFProf, "main_fragment", cg_arguments);
prg[index].fprg = cgCreateProgramFromFile(cgCtx, CG_SOURCE, prog, cgFProf, "main_fragment", argv);
SET_LISTING(f);
prg[index].vprg = cgCreateProgramFromFile(cgCtx, CG_SOURCE, prog, cgVProf, "main_vertex", cg_arguments);
prg[index].vprg = cgCreateProgramFromFile(cgCtx, CG_SOURCE, prog, cgVProf, "main_vertex", argv);
SET_LISTING(v);
}
else
{
prg[index].fprg = cgCreateProgram(cgCtx, CG_SOURCE, prog, cgFProf, "main_fragment", cg_arguments);
prg[index].fprg = cgCreateProgram(cgCtx, CG_SOURCE, prog, cgFProf, "main_fragment", argv);
SET_LISTING(f);
prg[index].vprg = cgCreateProgram(cgCtx, CG_SOURCE, prog, cgVProf, "main_vertex", cg_arguments);
prg[index].vprg = cgCreateProgram(cgCtx, CG_SOURCE, prog, cgVProf, "main_vertex", argv);
SET_LISTING(v);
}
@ -489,6 +511,7 @@ static bool load_plain(const char *path)
prg[1] = prg[0];
}
gfx_shader_resolve_parameters(NULL, cg_shader);
return true;
}
@ -580,14 +603,20 @@ static bool load_preset(const char *path)
return false;
}
config_file_free(conf);
gfx_shader_resolve_relative(cg_shader, path);
gfx_shader_resolve_parameters(conf, cg_shader);
config_file_free(conf);
if (cg_shader->passes > GFX_MAX_SHADERS - 3)
{
RARCH_WARN("Too many shaders ... Capping shader amount to %d.\n", GFX_MAX_SHADERS - 3);
cg_shader->passes = GFX_MAX_SHADERS - 3;
}
for (i = 0; i < cg_shader->passes; i++)
if (*cg_shader->pass[i].alias)
snprintf(cg_alias_define[i], sizeof(cg_alias_define[i]), "-D%s_ALIAS", cg_shader->pass[i].alias);
for (i = 0; i < cg_shader->passes; i++)
{
if (!load_shader(i))
@ -741,13 +770,16 @@ static void set_program_attributes(unsigned i)
prg[i].prev[j].coord = cgGetNamedParameter(prg[i].vprg, attr_buf_coord);
}
for (j = 0; j < i - 1; j++)
for (j = 0; j + 1 < i; j++)
{
char pass_str[64];
snprintf(pass_str, sizeof(pass_str), "PASS%u", j + 1);
set_pass_attrib(&prg[i], &prg[i].fbo[j], pass_str);
snprintf(pass_str, sizeof(pass_str), "PASSPREV%u", i - (j + 1));
set_pass_attrib(&prg[i], &prg[i].fbo[j], pass_str);
if (*cg_shader->pass[j].alias)
set_pass_attrib(&prg[i], &prg[i].fbo[j], cg_shader->pass[j].alias);
}
}
@ -789,6 +821,8 @@ static bool gl_cg_init(void *data, const char *path)
cgGLEnableProfile(cgFProf);
cgGLEnableProfile(cgVProf);
memset(cg_alias_define, 0, sizeof(cg_alias_define));
if (path && strcmp(path_get_extension(path), "cgp") == 0)
{
if (!load_preset(path))
@ -898,9 +932,9 @@ static bool gl_cg_mipmap_input(unsigned index)
return false;
}
void gl_cg_set_compiler_args(const char **argv)
static struct gfx_shader *gl_cg_get_current_shader(void)
{
cg_arguments = argv;
return cg_active ? cg_shader : NULL;
}
void gl_cg_invalidate_context(void)
@ -921,6 +955,7 @@ const gl_shader_backend_t gl_cg_backend = {
gl_cg_set_mvp,
gl_cg_get_prev_textures,
gl_cg_mipmap_input,
gl_cg_get_current_shader,
RARCH_SHADER_CG,
};

View File

@ -20,7 +20,6 @@
#include "shader_common.h"
#include <stdint.h>
void gl_cg_set_compiler_args(const char **argv);
void gl_cg_invalidate_context(void); // Call when resetting GL context on PS3.
extern const gl_shader_backend_t gl_cg_backend;

View File

@ -54,6 +54,8 @@ struct gl_shader_backend
unsigned (*get_prev_textures)(void);
bool (*mipmap_input)(unsigned index);
struct gfx_shader *(*get_current_shader)(void);
enum rarch_shader_type type;
};

View File

@ -58,6 +58,8 @@ static state_tracker_t *gl_state_tracker;
static GLint gl_attribs[PREV_TEXTURES + 1 + 4 + GFX_MAX_SHADERS];
static unsigned gl_attrib_index;
static char glsl_alias_define[1024];
// Cache the VBO.
struct cache_vbo
{
@ -325,7 +327,7 @@ static bool compile_shader(GLuint shader, const char *define, const char *progra
RARCH_LOG("[GL]: Using GLSL version %u.\n", version_no);
}
const char *source[] = { version, define, program };
const char *source[] = { version, define, glsl_alias_define, program };
glShaderSource(shader, ARRAY_SIZE(source), source, NULL);
glCompileShader(shader);
@ -366,7 +368,7 @@ static GLuint compile_program(const char *vertex, const char *fragment, unsigned
{
RARCH_LOG("Found GLSL vertex shader.\n");
vert = glCreateShader(GL_VERTEX_SHADER);
if (!compile_shader(vert, "#define VERTEX\n", vertex))
if (!compile_shader(vert, "#define VERTEX\n#define PARAMETER_UNIFORM\n", vertex))
{
RARCH_ERR("Failed to compile vertex shader #%u\n", i);
return false;
@ -379,7 +381,7 @@ static GLuint compile_program(const char *vertex, const char *fragment, unsigned
{
RARCH_LOG("Found GLSL fragment shader.\n");
frag = glCreateShader(GL_FRAGMENT_SHADER);
if (!compile_shader(frag, "#define FRAGMENT\n", fragment))
if (!compile_shader(frag, "#define FRAGMENT\n#define PARAMETER_UNIFORM\n", fragment))
{
RARCH_ERR("Failed to compile fragment shader #%u\n", i);
return false;
@ -566,6 +568,9 @@ static void find_uniforms(unsigned pass, GLuint prog, struct shader_uniforms *un
find_uniforms_frame(prog, &uni->pass[i], frame_base);
snprintf(frame_base, sizeof(frame_base), "PassPrev%u", pass - (i + 1));
find_uniforms_frame(prog, &uni->pass[i], frame_base);
if (*glsl_shader->pass[i].alias)
find_uniforms_frame(prog, &uni->pass[i], glsl_shader->pass[i].alias);
}
clear_uniforms_frame(&uni->prev[0]);
@ -662,6 +667,8 @@ static bool gl_glsl_init(void *data, const char *path)
if (!glsl_shader)
return false;
config_file_t *conf = NULL;
if (path)
{
bool ret;
@ -674,12 +681,11 @@ static bool gl_glsl_init(void *data, const char *path)
}
else if (strcmp(path_get_extension(path), "glslp") == 0)
{
config_file_t *conf = config_file_new(path);
conf = config_file_new(path);
if (conf)
{
ret = gfx_shader_read_conf_cgp(conf, glsl_shader);
glsl_shader->modern = true;
config_file_free(conf);
}
else
ret = false;
@ -703,6 +709,13 @@ static bool gl_glsl_init(void *data, const char *path)
}
gfx_shader_resolve_relative(glsl_shader, path);
gfx_shader_resolve_parameters(conf, glsl_shader);
if (conf)
{
config_file_free(conf);
conf = NULL;
}
const char *stock_vertex = glsl_shader->modern ?
stock_vertex_modern : stock_vertex_legacy;
@ -729,6 +742,19 @@ static bool gl_glsl_init(void *data, const char *path)
}
#endif
// Find all aliases we use in our GLSLP and add #defines for them so
// that a shader can choose a fallback if we are not using a preset.
*glsl_alias_define = '\0';
for (i = 0; i < glsl_shader->passes; i++)
{
if (*glsl_shader->pass[i].alias)
{
char define[128];
snprintf(define, sizeof(define), "#define %s_ALIAS\n", glsl_shader->pass[i].alias);
strlcat(glsl_alias_define, define, sizeof(glsl_alias_define));
}
}
if (!(gl_program[0] = compile_program(stock_vertex, stock_fragment, 0)))
{
RARCH_ERR("GLSL stock programs failed to compile.\n");
@ -810,12 +836,6 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
const struct gl_tex_info *fbo_info, unsigned fbo_info_cnt)
{
(void)data;
// We enforce a certain layout for our various texture types in the texunits.
// - Regular frame (Texture) (always bound).
// - LUT textures (always bound).
// - Original texture (always bound if meaningful).
// - FBO textures (always bound if available).
// - Previous textures.
if (!glsl_enable || (gl_program[active_index] == 0))
return;
@ -853,21 +873,22 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
if (uni->frame_direction >= 0)
glUniform1i(uni->frame_direction, g_extern.frame_is_reverse ? -1 : 1);
unsigned texunit = 1;
for (i = 0; i < glsl_shader->luts; i++)
{
if (uni->lut_texture[i] >= 0)
{
// Have to rebind as HW render could override this.
glActiveTexture(GL_TEXTURE0 + i + 1);
glActiveTexture(GL_TEXTURE0 + texunit);
glBindTexture(GL_TEXTURE_2D, gl_teximage[i]);
glUniform1i(uni->lut_texture[i], i + 1);
glUniform1i(uni->lut_texture[i], texunit);
texunit++;
}
}
unsigned texunit = glsl_shader->luts + 1;
// Set original texture unless we're in first pass (pointless).
if (active_index > 1)
// Set original texture.
if (active_index)
{
if (uni->orig.texture >= 0)
{
@ -875,10 +896,9 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
glActiveTexture(GL_TEXTURE0 + texunit);
glUniform1i(uni->orig.texture, texunit);
glBindTexture(GL_TEXTURE_2D, info->tex);
texunit++;
}
texunit++;
if (uni->orig.texture_size >= 0)
glUniform2fv(uni->orig.texture_size, 1, info->tex_size);
@ -898,20 +918,16 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
size += 8;
}
// Bind new texture in the chain.
if (fbo_info_cnt > 0)
{
glActiveTexture(GL_TEXTURE0 + texunit + fbo_info_cnt - 1);
glBindTexture(GL_TEXTURE_2D, fbo_info[fbo_info_cnt - 1].tex);
}
// Bind FBO textures.
for (i = 0; i < fbo_info_cnt; i++)
{
if (uni->pass[i].texture)
{
glActiveTexture(GL_TEXTURE0 + texunit);
glBindTexture(GL_TEXTURE_2D, fbo_info[i].tex);
glUniform1i(uni->pass[i].texture, texunit);
texunit++;
texunit++;
}
if (uni->pass[i].texture_size >= 0)
glUniform2fv(uni->pass[i].texture_size, 1, fbo_info[i].tex_size);
@ -932,23 +948,6 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
}
}
}
else
{
// First pass, so unbind everything to avoid collitions.
// Unbind ORIG.
glActiveTexture(GL_TEXTURE0 + texunit);
glBindTexture(GL_TEXTURE_2D, 0);
GLuint base_tex = texunit + 1;
// Unbind any lurking FBO passes.
// Rendering to a texture that is bound to a texture unit
// sounds very shaky ... ;)
for (i = 0; i < glsl_shader->passes; i++)
{
glActiveTexture(GL_TEXTURE0 + base_tex + i);
glBindTexture(GL_TEXTURE_2D, 0);
}
}
// Set previous textures. Only bind if they're actually used.
for (i = 0; i < PREV_TEXTURES; i++)
@ -957,11 +956,10 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
{
glActiveTexture(GL_TEXTURE0 + texunit);
glBindTexture(GL_TEXTURE_2D, prev_info[i].tex);
glUniform1i(uni->prev[i].texture, texunit++);
glUniform1i(uni->prev[i].texture, texunit);
texunit++;
}
texunit++;
if (uni->prev[i].texture_size >= 0)
glUniform2fv(uni->prev[i].texture_size, 1, prev_info[i].tex_size);
@ -992,6 +990,14 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
glActiveTexture(GL_TEXTURE0);
// #pragma parameters
for (i = 0; i < glsl_shader->num_parameters; i++)
{
int location = glGetUniformLocation(gl_program[active_index], glsl_shader->parameters[i].id);
glUniform1f(location, glsl_shader->parameters[i].current);
}
// Set state parameters
if (gl_state_tracker)
{
static struct state_tracker_uniform info[GFX_MAX_VARIABLES];
@ -1163,6 +1169,11 @@ static bool gl_glsl_mipmap_input(unsigned index)
return false;
}
static struct gfx_shader *gl_glsl_get_current_shader(void)
{
return glsl_enable ? glsl_shader : NULL;
}
void gl_glsl_set_get_proc_address(gfx_ctx_proc_t (*proc)(const char*))
{
glsl_get_proc_address = proc;
@ -1188,6 +1199,7 @@ const gl_shader_backend_t gl_glsl_backend = {
gl_glsl_set_mvp,
gl_glsl_get_prev_textures,
gl_glsl_mipmap_input,
gl_glsl_get_current_shader,
RARCH_SHADER_GLSL,
};

View File

@ -435,6 +435,11 @@ static bool hlsl_mipmap_input(unsigned index)
return false;
}
static struct gfx_shader *hlsl_get_current_shader(void)
{
return NULL;
}
const gl_shader_backend_t hlsl_backend = {
hlsl_init,
hlsl_deinit,
@ -448,6 +453,7 @@ const gl_shader_backend_t hlsl_backend = {
hlsl_set_mvp,
NULL, /* hlsl_get_prev_textures */
hlsl_mipmap_input,
hlsl_get_current_shader,
RARCH_SHADER_HLSL,
};

View File

@ -105,6 +105,11 @@ static bool shader_parse_pass(config_file_t *conf, struct gfx_shader_pass *pass,
print_buf(mipmap_buf, "mipmap_input%u", i);
config_get_bool(conf, mipmap_buf, &pass->mipmap);
char alias_buf[64];
print_buf(alias_buf, "alias%u", i);
if (!config_get_array(conf, alias_buf, pass->alias, sizeof(pass->alias)))
*pass->alias = '\0';
// Scale
struct gfx_fbo_scale *scale = &pass->fbo;
char scale_type[64] = {0};
@ -268,10 +273,88 @@ static bool shader_parse_textures(config_file_t *conf, struct gfx_shader *shader
return true;
}
static struct gfx_shader_parameter *find_parameter(struct gfx_shader_parameter *params, unsigned num_params, const char *id)
{
unsigned i;
for (i = 0; i < num_params; i++)
{
if (!strcmp(params[i].id, id))
return &params[i];
}
return NULL;
}
bool gfx_shader_resolve_parameters(config_file_t *conf, struct gfx_shader *shader)
{
unsigned i;
shader->num_parameters = 0;
struct gfx_shader_parameter *param = &shader->parameters[shader->num_parameters];
// Find all parameters in our shaders.
for (i = 0; i < shader->passes; i++)
{
char line[2048];
FILE *file = fopen(shader->pass[i].source.path, "r");
if (!file)
continue;
while (shader->num_parameters < ARRAY_SIZE(shader->parameters) && fgets(line, sizeof(line), file))
{
int ret = sscanf(line, "#pragma parameter %64s \"%64[^\"]\" %f %f %f %f",
param->id, param->desc, &param->initial, &param->minimum, &param->maximum, &param->step);
if (ret >= 5)
{
param->id[63] = '\0';
param->desc[63] = '\0';
if (ret == 5)
param->step = 0.1f * (param->maximum - param->minimum);
RARCH_LOG("Found #pragma parameter %s (%s) %f %f %f %f\n",
param->desc, param->id, param->initial, param->minimum, param->maximum, param->step);
param->current = param->initial;
shader->num_parameters++;
param++;
}
}
fclose(file);
}
// Read in parameters which override the defaults.
if (conf)
{
char parameters[1024];
char *save = NULL;
const char *id;
if (!config_get_array(conf, "parameters", parameters, sizeof(parameters)))
return true;
for (id = strtok_r(parameters, ";", &save); id; id = strtok_r(NULL, ";", &save))
{
struct gfx_shader_parameter *param = find_parameter(shader->parameters, shader->num_parameters, id);
if (!param)
{
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, &param->current))
RARCH_WARN("[CGP/GLSLP]: Parameter %s is not set in preset.\n", id);
}
}
return true;
}
static bool shader_parse_imports(config_file_t *conf, struct gfx_shader *shader)
{
char imports[1024];
char *save;
char *save = NULL;
const char *id;
if (!config_get_array(conf, "imports", imports, sizeof(imports)))
return true;
@ -538,9 +621,32 @@ void gfx_shader_write_conf_cgp(config_file_t *conf, const struct gfx_shader *sha
print_buf(key, "mipmap_input%u", i);
config_set_bool(conf, key, pass->mipmap);
print_buf(key, "alias%u", i);
config_set_string(conf, key, pass->alias);
shader_write_fbo(conf, &pass->fbo, i);
}
if (shader->num_parameters)
{
char parameters[4096] = {0};
strlcpy(parameters, shader->parameters[0].id, sizeof(parameters));
for (i = 1; i < shader->num_parameters; i++)
{
// O(n^2), but number of parameters is very limited.
strlcat(parameters, ";", sizeof(parameters));
strlcat(parameters, shader->parameters[i].id, sizeof(parameters));
}
config_set_string(conf, "parameters", parameters);
for (i = 0; i < shader->num_parameters; i++)
{
char key[64];
config_set_float(conf, shader->parameters[i].id, shader->parameters[i].current);
}
}
if (shader->luts)
{
char textures[4096] = {0};

View File

@ -28,6 +28,7 @@ extern "C" {
#define GFX_MAX_SHADERS 16
#define GFX_MAX_TEXTURES 8
#define GFX_MAX_VARIABLES 64
#define GFX_MAX_PARAMETERS 64
enum gfx_scale_type
{
@ -65,6 +66,17 @@ struct gfx_fbo_scale
bool valid;
};
struct gfx_shader_parameter
{
char id[64];
char desc[64];
float current;
float minimum;
float initial;
float maximum;
float step;
};
struct gfx_shader_pass
{
struct
@ -77,6 +89,7 @@ struct gfx_shader_pass
} string;
} source;
char alias[64];
struct gfx_fbo_scale fbo;
enum gfx_filter_type filter;
enum gfx_wrap_type wrap;
@ -108,6 +121,9 @@ struct gfx_shader
unsigned luts;
struct gfx_shader_lut lut[GFX_MAX_TEXTURES];
struct gfx_shader_parameter parameters[GFX_MAX_PARAMETERS];
unsigned num_parameters;
unsigned variables;
struct state_tracker_uniform_info variable[GFX_MAX_VARIABLES];
char script_path[PATH_MAX];
@ -119,6 +135,7 @@ bool gfx_shader_read_conf_cgp(config_file_t *conf, struct gfx_shader *shader);
void gfx_shader_write_conf_cgp(config_file_t *conf, const struct gfx_shader *shader);
void gfx_shader_resolve_relative(struct gfx_shader *shader, const char *ref_path);
bool gfx_shader_resolve_parameters(config_file_t *conf, struct gfx_shader *shader);
enum rarch_shader_type gfx_shader_parse_type(const char *path, enum rarch_shader_type fallback);

View File

@ -751,6 +751,13 @@ static void thread_apply_state_changes(void *data)
slock_unlock(thr->frame.lock);
}
// This is read-only state which should not have any kind of race condition.
static struct gfx_shader *thread_get_current_shader(void *data)
{
thread_video_t *thr = (thread_video_t*)data;
return thr->poke ? thr->poke->get_current_shader(thr->driver_data) : NULL;
}
static const video_poke_interface_t thread_poke = {
thread_set_filtering,
#ifdef HAVE_FBO
@ -763,6 +770,12 @@ static const video_poke_interface_t thread_poke = {
thread_set_texture_frame,
thread_set_texture_enable,
#endif
NULL,
NULL,
NULL,
thread_get_current_shader,
};
static void thread_get_poke_interface(void *data, const video_poke_interface_t **iface)