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);
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[] = {

View File

@ -136,13 +136,11 @@ enum rarch_shader_type
RARCH_SHADER_NONE
};
enum rarch_shader_mask
enum rarch_shader_index
{
RARCH_SHADER_MULTIPASS = 1,
RARCH_SHADER_PASS0,
RARCH_SHADER_PASS0_STOCK,
RARCH_SHADER_PASS1,
RARCH_SHADER_PASS1_STOCK
RARCH_SHADER_INDEX_MULTIPASS = 0,
RARCH_SHADER_INDEX_PASS0 = 1,
RARCH_SHADER_INDEX_PASS1 = 2
};
typedef struct video_info
@ -233,7 +231,7 @@ typedef struct video_driver
// Is the window still active?
bool (*alive)(void *data);
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);
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)
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;
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
gl_deinit_fbo(gl);
glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
#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
// Set up render to texture again.
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.
gl_set_shader_viewport(gl, 0);
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

View File

@ -477,21 +477,30 @@ static bool load_plain(const char *path)
if (!load_stock())
return false;
RARCH_LOG("Loading Cg file: %s\n", path);
if (!load_program(1, path, true))
return false;
if (*g_settings.video.second_pass_shader && g_settings.video.render_to_texture)
if (path)
{
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;
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
{
prg[2] = prg[0];
RARCH_LOG("Loading stock Cg file.\n");
prg[2] = prg[1] = prg[0];
cg_shader_num = 1;
}
@ -1360,5 +1369,8 @@ const gl_shader_backend_t gl_cg_backend = {
gl_cg_shader_scale,
gl_cg_set_coords,
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);
bool (*set_coords)(const struct gl_coords *coords);
bool (*set_mvp)(const math_matrix *mat);
bool (*load_shader)(unsigned index, const char *path);
enum rarch_shader_type type;
};
#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)
{
bool ret = true;
for (unsigned i = 0; i < num; i++)
{
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)
{
RARCH_ERR("Failed to create GL program #%u.\n", i);
return false;
ret = false;
goto end;
}
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))
{
RARCH_ERR("Failed to compile vertex shader #%u\n", i);
return false;
ret = false;
goto end;
}
pglAttachShader(gl_prog[i], shader);
free(progs[i].vertex);
}
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))
{
RARCH_ERR("Failed to compile fragment shader #%u\n", i);
return false;
ret = false;
goto end;
}
pglAttachShader(gl_prog[i], shader);
free(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]))
{
RARCH_ERR("Failed to link program #%u\n", i);
return false;
ret = false;
goto end;
}
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)
@ -1014,6 +1027,56 @@ static void find_uniforms(GLuint prog, struct shader_uniforms *uni)
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.
// Assume functions are available without proc_address.
#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);
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++;
}
else
@ -1185,17 +1253,7 @@ void gl_glsl_deinit(void)
if (gl_program[i] == 0 || (i && gl_program[i] == gl_program[0]))
continue;
GLsizei count;
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]);
gl_glsl_delete_shader(gl_program[i]);
}
glDeleteTextures(gl_teximage_cnt, gl_teximage);
@ -1507,5 +1565,8 @@ const gl_shader_backend_t gl_glsl_backend = {
gl_glsl_shader_scale,
gl_glsl_set_coords,
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);
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");
}