Rework index parameter to set_shader().

This commit is contained in:
Themaister 2013-01-08 03:46:18 +01:00
parent 8887eb4680
commit 551a464978
7 changed files with 179 additions and 97 deletions

View File

@ -229,7 +229,7 @@ static bool cmd_set_shader(const char *arg)
msg_queue_push(g_extern.msg_queue, msg, 1, 120); msg_queue_push(g_extern.msg_queue, msg, 1, 120);
RARCH_LOG("Applying shader \"%s\".\n", arg); RARCH_LOG("Applying shader \"%s\".\n", arg);
return video_set_shader_func(type, arg, (1ULL << RARCH_SHADER_MULTIPASS)); return video_set_shader_func(type, arg, RARCH_SHADER_INDEX_MULTIPASS);
} }
static const struct cmd_action_map action_map[] = { static const struct cmd_action_map action_map[] = {

View File

@ -136,13 +136,11 @@ enum rarch_shader_type
RARCH_SHADER_NONE RARCH_SHADER_NONE
}; };
enum rarch_shader_mask enum rarch_shader_index
{ {
RARCH_SHADER_MULTIPASS = 1, RARCH_SHADER_INDEX_MULTIPASS = 0,
RARCH_SHADER_PASS0, RARCH_SHADER_INDEX_PASS0 = 1,
RARCH_SHADER_PASS0_STOCK, RARCH_SHADER_INDEX_PASS1 = 2
RARCH_SHADER_PASS1,
RARCH_SHADER_PASS1_STOCK
}; };
typedef struct video_info typedef struct video_info
@ -233,7 +231,7 @@ typedef struct video_driver
// Is the window still active? // Is the window still active?
bool (*alive)(void *data); bool (*alive)(void *data);
bool (*focus)(void *data); // Does the window have focus? bool (*focus)(void *data); // Does the window have focus?
bool (*set_shader)(void *data, enum rarch_shader_type type, const char *path, unsigned mask); // Sets shader. Might not be implemented. bool (*set_shader)(void *data, enum rarch_shader_type type, const char *path, unsigned index); // Sets shader. Might not be implemented.
void (*free)(void *data); void (*free)(void *data);
const char *ident; const char *ident;

128
gfx/gl.c
View File

@ -1709,75 +1709,73 @@ static bool gl_focus(void *data)
} }
#if defined(HAVE_GLSL) || defined(HAVE_CG) #if defined(HAVE_GLSL) || defined(HAVE_CG)
static bool gl_set_shader(void *data, enum rarch_shader_type type, const char *path, unsigned mask) static bool gl_set_shader(void *data, enum rarch_shader_type type, const char *path, unsigned index)
{ {
gl_t *gl = (gl_t*)data; gl_t *gl = (gl_t*)data;
if (mask & (1ULL << RARCH_SHADER_MULTIPASS)) if (type == RARCH_SHADER_NONE)
return false;
if (index == RARCH_SHADER_INDEX_MULTIPASS && !path)
{ {
RARCH_ERR("[GL]: Cannot set stock shader to multipass.\n");
return false;
}
if (!gl->shader && index != RARCH_SHADER_INDEX_MULTIPASS)
{
RARCH_ERR("[GL]: No shader core is init. Cannot set shader %s to pass %u.\n", path, index);
return false;
}
if (gl->shader && gl->shader->type != type)
{
RARCH_ERR("[GL]: Trying to set a specific shader pass %u, but that particular shader core is not initialized.\n", index);
return false;
}
// Need full teardown for multipass.
if (index == RARCH_SHADER_INDEX_MULTIPASS)
{
gl_shader_deinit(gl);
switch (type)
{
#ifdef HAVE_GLSL
case RARCH_SHADER_GLSL:
gl->shader = &gl_glsl_backend;
break;
#endif
#ifdef HAVE_CG
case RARCH_SHADER_CG:
gl->shader = &gl_cg_backend;
break;
#endif
default:
gl->shader = NULL;
break;
}
if (!gl->shader)
{
RARCH_ERR("[GL]: Cannot find shader core for path: %s.\n", path);
return false;
}
#ifdef HAVE_FBO #ifdef HAVE_FBO
gl_deinit_fbo(gl); gl_deinit_fbo(gl);
glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
#endif #endif
gl_shader_deinit(gl); bool ret = gl->shader->init(path);
} if (!ret)
{
gl->shader = NULL;
RARCH_WARN("[GL]: Failed to set multipass shader. Falling back to stock.\n");
return gl->shader->init(NULL);
}
switch (type)
{
#ifdef HAVE_GLSL
case RARCH_SHADER_GLSL:
if (mask & (1ULL << RARCH_SHADER_MULTIPASS))
{
if (!gl_glsl_init(path))
return false;
}
else if (mask & (1ULL << RARCH_SHADER_PASS0))
{
#if 0
/* TODO - doesn't seem to be added yet? */
if (!gl_glsl_load_shader(1, (mask & (1ULL << RARCH_SHADER_PASS0_STOCK)) ? NULL : path))
#endif
return false;
}
else if (mask & (1ULL << RARCH_SHADER_PASS1))
{
#if 0
/* TODO - doesn't seem to be added yet? */
if (!gl_glsl_load_shader(2, (mask & (1ULL << RARCH_SHADER_PASS1_STOCK)) ? NULL : path))
#endif
return false;
}
break;
#endif
#ifdef HAVE_CG
case RARCH_SHADER_CG:
if (mask & (1ULL << RARCH_SHADER_MULTIPASS))
{
if (!gl_cg_init(path))
return false;
}
else if (mask & (1ULL << RARCH_SHADER_PASS0))
{
if (!gl_cg_load_shader(1, (mask & (1ULL << RARCH_SHADER_PASS0_STOCK)) ? NULL : path))
return false;
}
else if (mask & (1ULL << RARCH_SHADER_PASS1))
{
if (!gl_cg_load_shader(2, (mask & (1ULL << RARCH_SHADER_PASS1_STOCK)) ? NULL : path))
return false;
}
break;
#endif
default:
RARCH_ERR("Invalid shader type in gl_set_shader().\n");
return false;
}
if (mask & (1ULL << RARCH_SHADER_MULTIPASS))
{
#ifdef HAVE_FBO #ifdef HAVE_FBO
// Set up render to texture again. // Set up render to texture again.
gl_init_fbo(gl, gl->tex_w, gl->tex_h); gl_init_fbo(gl, gl->tex_w, gl->tex_h);
@ -1786,9 +1784,19 @@ static bool gl_set_shader(void *data, enum rarch_shader_type type, const char *p
// Apparently need to set viewport for passes when we aren't using FBOs. // Apparently need to set viewport for passes when we aren't using FBOs.
gl_set_shader_viewport(gl, 0); gl_set_shader_viewport(gl, 0);
gl_set_shader_viewport(gl, 1); gl_set_shader_viewport(gl, 1);
return true;
} }
else // Replace a currently loaded shader directly.
{
if (index > gl->shader->num_shaders())
{
RARCH_ERR("Can only load shader for passes that already exist. "
"Attempted to set pass %u, but only %u passes exist.\n", index, gl->shader->num_shaders());
return false;
}
return true; return gl->shader->load_shader(index, path);
}
} }
#endif #endif

View File

@ -477,21 +477,30 @@ static bool load_plain(const char *path)
if (!load_stock()) if (!load_stock())
return false; return false;
RARCH_LOG("Loading Cg file: %s\n", path); if (path)
if (!load_program(1, path, true))
return false;
if (*g_settings.video.second_pass_shader && g_settings.video.render_to_texture)
{ {
if (!load_program(2, g_settings.video.second_pass_shader, true)) RARCH_LOG("Loading Cg file: %s\n", path);
if (!load_program(1, path, true))
return false; return false;
cg_shader_num = 2; if (*g_settings.video.second_pass_shader && g_settings.video.render_to_texture)
{
if (!load_program(2, g_settings.video.second_pass_shader, true))
return false;
cg_shader_num = 2;
}
else
{
prg[2] = prg[0];
cg_shader_num = 1;
}
} }
else else
{ {
prg[2] = prg[0]; RARCH_LOG("Loading stock Cg file.\n");
prg[2] = prg[1] = prg[0];
cg_shader_num = 1; cg_shader_num = 1;
} }
@ -1360,5 +1369,8 @@ const gl_shader_backend_t gl_cg_backend = {
gl_cg_shader_scale, gl_cg_shader_scale,
gl_cg_set_coords, gl_cg_set_coords,
gl_cg_set_mvp, gl_cg_set_mvp,
gl_cg_load_shader,
RARCH_SHADER_CG,
}; };

View File

@ -39,6 +39,9 @@ struct gl_shader_backend
void (*shader_scale)(unsigned index, struct gl_fbo_scale *scale); void (*shader_scale)(unsigned index, struct gl_fbo_scale *scale);
bool (*set_coords)(const struct gl_coords *coords); bool (*set_coords)(const struct gl_coords *coords);
bool (*set_mvp)(const math_matrix *mat); bool (*set_mvp)(const math_matrix *mat);
bool (*load_shader)(unsigned index, const char *path);
enum rarch_shader_type type;
}; };
#endif #endif

View File

@ -894,6 +894,8 @@ static bool link_program(GLuint prog)
static bool compile_programs(GLuint *gl_prog, struct shader_program *progs, size_t num) static bool compile_programs(GLuint *gl_prog, struct shader_program *progs, size_t num)
{ {
bool ret = true;
for (unsigned i = 0; i < num; i++) for (unsigned i = 0; i < num; i++)
{ {
gl_prog[i] = pglCreateProgram(); gl_prog[i] = pglCreateProgram();
@ -901,7 +903,8 @@ static bool compile_programs(GLuint *gl_prog, struct shader_program *progs, size
if (gl_prog[i] == 0) if (gl_prog[i] == 0)
{ {
RARCH_ERR("Failed to create GL program #%u.\n", i); RARCH_ERR("Failed to create GL program #%u.\n", i);
return false; ret = false;
goto end;
} }
if (progs[i].vertex) if (progs[i].vertex)
@ -911,11 +914,11 @@ static bool compile_programs(GLuint *gl_prog, struct shader_program *progs, size
if (!compile_shader(shader, progs[i].vertex)) if (!compile_shader(shader, progs[i].vertex))
{ {
RARCH_ERR("Failed to compile vertex shader #%u\n", i); RARCH_ERR("Failed to compile vertex shader #%u\n", i);
return false; ret = false;
goto end;
} }
pglAttachShader(gl_prog[i], shader); pglAttachShader(gl_prog[i], shader);
free(progs[i].vertex);
} }
if (progs[i].fragment) if (progs[i].fragment)
@ -925,11 +928,11 @@ static bool compile_programs(GLuint *gl_prog, struct shader_program *progs, size
if (!compile_shader(shader, progs[i].fragment)) if (!compile_shader(shader, progs[i].fragment))
{ {
RARCH_ERR("Failed to compile fragment shader #%u\n", i); RARCH_ERR("Failed to compile fragment shader #%u\n", i);
return false; ret = false;
goto end;
} }
pglAttachShader(gl_prog[i], shader); pglAttachShader(gl_prog[i], shader);
free(progs[i].fragment);
} }
if (progs[i].vertex || progs[i].fragment) if (progs[i].vertex || progs[i].fragment)
@ -938,7 +941,8 @@ static bool compile_programs(GLuint *gl_prog, struct shader_program *progs, size
if (!link_program(gl_prog[i])) if (!link_program(gl_prog[i]))
{ {
RARCH_ERR("Failed to link program #%u\n", i); RARCH_ERR("Failed to link program #%u\n", i);
return false; ret = false;
goto end;
} }
GLint location = pglGetUniformLocation(gl_prog[i], "rubyTexture"); GLint location = pglGetUniformLocation(gl_prog[i], "rubyTexture");
@ -947,7 +951,16 @@ static bool compile_programs(GLuint *gl_prog, struct shader_program *progs, size
} }
} }
return true; end:
for (unsigned i = 0; i < num; i++)
{
free(progs[i].vertex);
free(progs[i].fragment);
progs[i].vertex = NULL;
progs[i].fragment = NULL;
}
return ret;
} }
static void gl_glsl_reset_attrib(void) static void gl_glsl_reset_attrib(void)
@ -1014,6 +1027,56 @@ static void find_uniforms(GLuint prog, struct shader_uniforms *uni)
pglUseProgram(0); pglUseProgram(0);
} }
static void gl_glsl_delete_shader(GLuint prog)
{
GLsizei count;
GLuint shaders[2] = {0};
pglGetAttachedShaders(prog, 2, &count, shaders);
for (GLsizei i = 0; i < count; i++)
{
pglDetachShader(prog, shaders[i]);
pglDeleteShader(shaders[i]);
}
pglDeleteProgram(prog);
}
static bool gl_glsl_load_shader(unsigned index, const char *path)
{
pglUseProgram(0);
if (gl_program[index] != gl_program[0])
{
gl_glsl_delete_shader(gl_program[index]);
gl_program[index] = 0;
}
if (path)
{
struct shader_program prog = {0};
unsigned progs = get_xml_shaders(path, &prog, 1);
if (progs != 1)
return false;
if (!compile_programs(&gl_program[index], &prog, 1))
{
RARCH_ERR("Failed to compile shader: %s.\n", path);
return false;
}
find_uniforms(gl_program[index], &gl_uniforms[index]);
}
else
{
gl_program[index] = gl_program[0];
gl_uniforms[index] = gl_uniforms[0];
}
pglUseProgram(gl_program[active_index]);
return true;
}
// Platforms with broken get_proc_address. // Platforms with broken get_proc_address.
// Assume functions are available without proc_address. // Assume functions are available without proc_address.
#undef LOAD_GL_SYM #undef LOAD_GL_SYM
@ -1129,7 +1192,12 @@ bool gl_glsl_init(const char *path)
unsigned secondary_progs = get_xml_shaders(g_settings.video.second_pass_shader, progs, 1); unsigned secondary_progs = get_xml_shaders(g_settings.video.second_pass_shader, progs, 1);
if (secondary_progs == 1) if (secondary_progs == 1)
{ {
compile_programs(&gl_program[2], progs, 1); if (!compile_programs(&gl_program[2], progs, 1))
{
RARCH_ERR("Failed to compile second pass shader.\n");
return false;
}
num_progs++; num_progs++;
} }
else else
@ -1185,17 +1253,7 @@ void gl_glsl_deinit(void)
if (gl_program[i] == 0 || (i && gl_program[i] == gl_program[0])) if (gl_program[i] == 0 || (i && gl_program[i] == gl_program[0]))
continue; continue;
GLsizei count; gl_glsl_delete_shader(gl_program[i]);
GLuint shaders[2];
pglGetAttachedShaders(gl_program[i], 2, &count, shaders);
for (GLsizei j = 0; j < count; j++)
{
pglDetachShader(gl_program[i], shaders[j]);
pglDeleteShader(shaders[j]);
}
pglDeleteProgram(gl_program[i]);
} }
glDeleteTextures(gl_teximage_cnt, gl_teximage); glDeleteTextures(gl_teximage_cnt, gl_teximage);
@ -1507,5 +1565,8 @@ const gl_shader_backend_t gl_glsl_backend = {
gl_glsl_shader_scale, gl_glsl_shader_scale,
gl_glsl_set_coords, gl_glsl_set_coords,
gl_glsl_set_mvp, gl_glsl_set_mvp,
gl_glsl_load_shader,
RARCH_SHADER_GLSL,
}; };

View File

@ -2342,7 +2342,7 @@ static void check_shader_dir(void)
msg_queue_push(g_extern.msg_queue, msg, 1, 120); msg_queue_push(g_extern.msg_queue, msg, 1, 120);
RARCH_LOG("Applying shader \"%s\".\n", shader); RARCH_LOG("Applying shader \"%s\".\n", shader);
if (!video_set_shader_func(type, shader, (1ULL << RARCH_SHADER_MULTIPASS))) if (!video_set_shader_func(type, shader, RARCH_SHADER_INDEX_MULTIPASS))
RARCH_WARN("Failed to apply shader.\n"); RARCH_WARN("Failed to apply shader.\n");
} }