From 84eba3ef71dfa822e5ff0463032cdd2e3515b888 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 13 Oct 2010 13:58:44 -0700 Subject: Track separate programs for each stage The assumption is that all stages are the same program or that varyings are passed between stages using built-in varyings. --- src/mesa/drivers/common/meta.c | 30 ++++-- src/mesa/drivers/dri/i965/brw_fs.cpp | 6 +- src/mesa/drivers/dri/i965/brw_wm_state.c | 4 +- src/mesa/main/context.c | 150 +++++++++++++++++++--------- src/mesa/main/mtypes.h | 10 +- src/mesa/main/shaderapi.c | 89 ++++++++++++++--- src/mesa/main/state.c | 16 +-- src/mesa/main/texenvprogram.c | 9 +- src/mesa/main/texstate.c | 33 +++--- src/mesa/state_tracker/st_atom_rasterizer.c | 5 +- src/mesa/state_tracker/st_draw.c | 20 +++- src/mesa/state_tracker/st_program.c | 38 +++++-- src/mesa/swrast/s_fragprog.c | 2 +- 13 files changed, 297 insertions(+), 115 deletions(-) diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c index 9946bf1990..1bfd76a665 100644 --- a/src/mesa/drivers/common/meta.c +++ b/src/mesa/drivers/common/meta.c @@ -143,7 +143,10 @@ struct save_state struct gl_vertex_program *VertexProgram; GLboolean FragmentProgramEnabled; struct gl_fragment_program *FragmentProgram; - GLuint Shader; + GLuint VertexShader; + GLuint GeometryShader; + GLuint FragmentShader; + GLuint ActiveShader; /** META_STENCIL_TEST */ struct gl_stencil_attrib Stencil; @@ -433,8 +436,15 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) } if (ctx->Extensions.ARB_shader_objects) { - save->Shader = ctx->Shader.CurrentProgram ? - ctx->Shader.CurrentProgram->Name : 0; + save->VertexShader = ctx->Shader.CurrentVertexProgram ? + ctx->Shader.CurrentVertexProgram->Name : 0; + save->GeometryShader = ctx->Shader.CurrentGeometryProgram ? + ctx->Shader.CurrentGeometryProgram->Name : 0; + save->FragmentShader = ctx->Shader.CurrentFragmentProgram ? + ctx->Shader.CurrentFragmentProgram->Name : 0; + save->ActiveShader = ctx->Shader.ActiveProgram ? + ctx->Shader.ActiveProgram->Name : 0; + _mesa_UseProgramObjectARB(0); } } @@ -664,9 +674,17 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL); } - if (ctx->Extensions.ARB_shader_objects) { - _mesa_UseProgramObjectARB(save->Shader); - } + if (ctx->Extensions.ARB_vertex_shader) + _mesa_UseShaderProgramEXT(GL_VERTEX_SHADER, save->VertexShader); + + if (ctx->Extensions.ARB_geometry_shader4) + _mesa_UseShaderProgramEXT(GL_GEOMETRY_SHADER_ARB, + save->GeometryShader); + + if (ctx->Extensions.ARB_fragment_shader) + _mesa_UseShaderProgramEXT(GL_FRAGMENT_SHADER, save->FragmentShader); + + _mesa_ActiveProgramEXT(save->ActiveShader); } if (state & META_STENCIL_TEST) { diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 4919394bc8..5f6deb841c 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -1186,7 +1186,7 @@ fs_visitor::visit(ir_texture *ir) assert(!ir->projector); sampler = _mesa_get_sampler_uniform_value(ir->sampler, - ctx->Shader.CurrentProgram, + ctx->Shader.CurrentFragmentProgram, &brw->fragment_program->Base); sampler = c->fp->program.Base.SamplerUnits[sampler]; @@ -3093,7 +3093,7 @@ fs_visitor::generate_code() if (INTEL_DEBUG & DEBUG_WM) { printf("Native code for fragment shader %d:\n", - ctx->Shader.CurrentProgram->Name); + ctx->Shader.CurrentFragmentProgram->Name); } if_depth_in_loop[loop_stack_depth] = 0; @@ -3320,7 +3320,7 @@ brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; - struct gl_shader_program *prog = ctx->Shader.CurrentProgram; + struct gl_shader_program *prog = ctx->Shader.CurrentFragmentProgram; if (!prog) return GL_FALSE; diff --git a/src/mesa/drivers/dri/i965/brw_wm_state.c b/src/mesa/drivers/dri/i965/brw_wm_state.c index 433ccc66f0..9a27b93710 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_state.c @@ -137,9 +137,9 @@ wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key) /* If using the fragment shader backend, the program is always * 8-wide. */ - if (ctx->Shader.CurrentProgram) { + if (ctx->Shader.CurrentFragmentProgram) { struct brw_shader *shader = (struct brw_shader *) - ctx->Shader.CurrentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]; + ctx->Shader.CurrentFragmentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]; if (shader != NULL && shader->ir != NULL) { key->is_glsl = GL_TRUE; diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 3e265fb308..3ebe54926f 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1697,11 +1697,10 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) if (ctx->NewState) _mesa_update_state(ctx); - if (ctx->Shader.CurrentProgram) { - struct gl_shader_program *const prog = ctx->Shader.CurrentProgram; + if (ctx->Shader.CurrentVertexProgram) { + vert_from_glsl_shader = true; - /* The current shader program must be successfully linked */ - if (!prog->LinkStatus) { + if (!ctx->Shader.CurrentVertexProgram->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(shader not linked)", where); return GL_FALSE; @@ -1709,34 +1708,56 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) #if 0 /* not normally enabled */ { char errMsg[100]; - if (!_mesa_validate_shader_program(ctx, prog, errMsg)) { + if (!_mesa_validate_shader_program(ctx, + ctx->Shader.CurrentVertexProgram, + errMsg)) { _mesa_warning(ctx, "Shader program %u is invalid: %s", - prog->Name, errMsg); + ctx->Shader.CurrentVertexProgram->Name, errMsg); } } #endif + } - /* Figure out which shader stages are provided by the GLSL program. For - * any stages that are not provided, the corresponding assembly shader - * target will be validated below. - */ - vert_from_glsl_shader = - prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL; - geom_from_glsl_shader = - prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL; - frag_from_glsl_shader = - prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL; + if (ctx->Shader.CurrentGeometryProgram) { + geom_from_glsl_shader = true; + + if (!ctx->Shader.CurrentGeometryProgram->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(shader not linked)", where); + return GL_FALSE; + } +#if 0 /* not normally enabled */ + { + char errMsg[100]; + if (!_mesa_validate_shader_program(ctx, + ctx->Shader.CurrentGeometryProgram, + errMsg)) { + _mesa_warning(ctx, "Shader program %u is invalid: %s", + ctx->Shader.CurrentGeometryProgram->Name, errMsg); + } + } +#endif } - /* If drawing to integer-valued color buffers, there must be an - * active fragment shader (GL_EXT_texture_integer). - */ - if (ctx->DrawBuffer && ctx->DrawBuffer->_IntegerColor) { - if (!frag_from_glsl_shader) { + if (ctx->Shader.CurrentFragmentProgram) { + frag_from_glsl_shader = true; + + if (!ctx->Shader.CurrentFragmentProgram->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(integer format but no fragment shader)", where); + "%s(shader not linked)", where); return GL_FALSE; } +#if 0 /* not normally enabled */ + { + char errMsg[100]; + if (!_mesa_validate_shader_program(ctx, + ctx->Shader.CurrentFragmentProgram, + errMsg)) { + _mesa_warning(ctx, "Shader program %u is invalid: %s", + ctx->Shader.CurrentFragmentProgram->Name, errMsg); + } + } +#endif } /* Any shader stages that are not supplied by the GLSL shader and have @@ -1754,11 +1775,21 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) */ (void) geom_from_glsl_shader; - if (!frag_from_glsl_shader - && ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(fragment program not valid)", where); - return GL_FALSE; + if (!frag_from_glsl_shader) { + if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(fragment program not valid)", where); + return GL_FALSE; + } + + /* If drawing to integer-valued color buffers, there must be an + * active fragment shader (GL_EXT_texture_integer). + */ + if (ctx->DrawBuffer && ctx->DrawBuffer->_IntegerColor) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(integer format but no fragment shader)", where); + return GL_FALSE; + } } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { @@ -1769,26 +1800,51 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) #ifdef DEBUG if (ctx->Shader.Flags & GLSL_LOG) { - struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; - if (shProg) { - if (!shProg->_Used) { - /* This is the first time this shader is being used. - * Append shader's constants/uniforms to log file. - */ - GLuint i; - for (i = 0; i < shProg->NumShaders; i++) { - struct gl_shader *sh = shProg->Shaders[i]; - if (sh->Type == GL_VERTEX_SHADER) { - _mesa_append_uniforms_to_file(sh, - &shProg->VertexProgram->Base); - } - else if (sh->Type == GL_FRAGMENT_SHADER) { - _mesa_append_uniforms_to_file(sh, - &shProg->FragmentProgram->Base); - } - } - shProg->_Used = GL_TRUE; - } + struct gl_shader_program *shProg[MESA_SHADER_TYPES]; + unsigned i; + + shProg[MESA_SHADER_VERTEX] = ctx->Shader.CurrentVertexProgram; + shProg[MESA_SHADER_GEOMETRY] = ctx->Shader.CurrentGeometryProgram; + shProg[MESA_SHADER_FRAGMENT] = ctx->Shader.CurrentFragmentProgram; + + for (i = 0; i < MESA_SHADER_TYPES; i++) { + struct gl_shader *sh; + + if (shProg[i] == NULL || shProg[i]->_Used + || shProg[i]->_LinkedShaders[i] == NULL) + continue; + + /* This is the first time this shader is being used. + * Append shader's constants/uniforms to log file. + * + * The logic is a little odd here. We only want to log data for each + * shader target that will actually be used, and we only want to log + * it once. It's possible to have a program bound to the vertex + * shader target that also supplied a fragment shader. If that + * program isn't also bound to the fragment shader target we don't + * want to log its fragment data. + */ + sh = shProg[i]->_LinkedShaders[i]; + switch (sh->Type) { + case GL_VERTEX_SHADER: + _mesa_append_uniforms_to_file(sh, &shProg[i]->VertexProgram->Base); + break; + + case GL_GEOMETRY_SHADER_ARB: + _mesa_append_uniforms_to_file(sh, + &shProg[i]->GeometryProgram->Base); + break; + + case GL_FRAGMENT_SHADER: + _mesa_append_uniforms_to_file(sh, + &shProg[i]->FragmentProgram->Base); + break; + } + } + + for (i = 0; i < MESA_SHADER_TYPES; i++) { + if (shProg[i] != NULL) + shProg[i]->_Used = GL_TRUE; } } #endif diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 7863ef382d..1b8a80416c 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2142,9 +2142,15 @@ struct gl_shader_program struct gl_shader_state { /** - * Program used for rendering. + * Programs used for rendering + * + * There is a separate program set for each shader stage. If + * GL_EXT_separate_shader_objects is not supported, each of these must point + * to \c NULL or to the same program. */ - struct gl_shader_program *CurrentProgram; + struct gl_shader_program *CurrentVertexProgram; + struct gl_shader_program *CurrentGeometryProgram; + struct gl_shader_program *CurrentFragmentProgram; /** * Program used by glUniform calls. diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 26c9a181aa..e6c7f7aa3f 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -116,7 +116,11 @@ _mesa_init_shader_state(struct gl_context *ctx) void _mesa_free_shader_state(struct gl_context *ctx) { - _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL); + _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentVertexProgram, NULL); + _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentGeometryProgram, + NULL); + _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentFragmentProgram, + NULL); _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL); } @@ -846,7 +850,10 @@ link_program(struct gl_context *ctx, GLuint program) if (!shProg) return; - if (obj->Active && shProg == ctx->Shader.CurrentProgram) { + if (obj->Active + && (shProg == ctx->Shader.CurrentVertexProgram + || shProg == ctx->Shader.CurrentGeometryProgram + || shProg == ctx->Shader.CurrentFragmentProgram)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glLinkProgram(transform feedback active"); return; @@ -926,6 +933,54 @@ active_program(struct gl_context *ctx, struct gl_shader_program *shProg, } } +/** + */ +static bool +use_shader_program(struct gl_context *ctx, GLenum type, + struct gl_shader_program *shProg) +{ + struct gl_shader_program **target; + + switch (type) { +#if FEATURE_ARB_vertex_shader + case GL_VERTEX_SHADER: + target = &ctx->Shader.CurrentVertexProgram; + if ((shProg == NULL) + || (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)) { + shProg = NULL; + } + break; +#endif +#if FEATURE_ARB_geometry_shader4 + case GL_GEOMETRY_SHADER_ARB: + target = &ctx->Shader.CurrentGeometryProgram; + if ((shProg == NULL) + || (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] == NULL)) { + shProg = NULL; + } + break; +#endif +#if FEATURE_ARB_fragment_shader + case GL_FRAGMENT_SHADER: + target = &ctx->Shader.CurrentFragmentProgram; + if ((shProg == NULL) + || (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)) { + shProg = NULL; + } + break; +#endif + default: + return false; + } + + if (*target != shProg) { + _mesa_reference_shader_program(ctx, target, shProg); + return true; + } + + return false; +} + /** * Use the named shader program for subsequent rendering. */ @@ -935,6 +990,7 @@ _mesa_use_program(struct gl_context *ctx, GLuint program) struct gl_shader_program *shProg; struct gl_transform_feedback_object *obj = ctx->TransformFeedback.CurrentObject; + bool changed = false; if (obj->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -942,12 +998,6 @@ _mesa_use_program(struct gl_context *ctx, GLuint program) return; } - if (ctx->Shader.CurrentProgram && - ctx->Shader.CurrentProgram->Name == program) { - /* no-op */ - return; - } - if (program) { shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram"); if (!shProg) { @@ -959,8 +1009,6 @@ _mesa_use_program(struct gl_context *ctx, GLuint program) return; } - active_program(ctx, shProg, "glUseProgram"); - /* debug code */ if (ctx->Shader.Flags & GLSL_USE_PROG) { print_shader_info(shProg); @@ -970,9 +1018,15 @@ _mesa_use_program(struct gl_context *ctx, GLuint program) shProg = NULL; } - if (ctx->Shader.CurrentProgram != shProg) { + changed = use_shader_program(ctx, GL_VERTEX_SHADER, shProg); + changed = use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, shProg) + || changed; + changed = use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg) + || changed; + active_program(ctx, shProg, "glUseProgram"); + + if (changed) { FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); - _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg); } if (ctx->Driver.UseProgram) @@ -1643,7 +1697,8 @@ void GLAPIENTRY _mesa_UseShaderProgramEXT(GLenum type, GLuint program) { GET_CURRENT_CONTEXT(ctx); - struct gl_shader_program *shProg; + struct gl_shader_program *shProg = NULL; + bool changed = false; if (!validate_shader_target(ctx, type)) { _mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)"); @@ -1669,8 +1724,12 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program) } } - _mesa_error(ctx, GL_INVALID_OPERATION, - "glUseShaderProgramEXT(NOT YET IMPLEMENTED)"); + changed = use_shader_program(ctx, type, shProg); + if (changed) + FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + + if (ctx->Driver.UseProgram) + ctx->Driver.UseProgram(ctx, shProg); return; } diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 5529732de0..05f4165c44 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -247,7 +247,9 @@ update_program_enables(struct gl_context *ctx) static GLbitfield update_program(struct gl_context *ctx) { - const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; + const struct gl_shader_program *vsProg = ctx->Shader.CurrentVertexProgram; + const struct gl_shader_program *gsProg = ctx->Shader.CurrentGeometryProgram; + const struct gl_shader_program *fsProg = ctx->Shader.CurrentFragmentProgram; const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current; const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current; const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current; @@ -269,10 +271,10 @@ update_program(struct gl_context *ctx) * come up, or matter. */ - if (shProg && shProg->LinkStatus && shProg->FragmentProgram) { + if (fsProg && fsProg->LinkStatus && fsProg->FragmentProgram) { /* Use shader programs */ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, - shProg->FragmentProgram); + fsProg->FragmentProgram); } else if (ctx->FragmentProgram._Enabled) { /* use user-defined vertex program */ @@ -292,10 +294,10 @@ update_program(struct gl_context *ctx) _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); } - if (shProg && shProg->LinkStatus && shProg->GeometryProgram) { + if (gsProg && gsProg->LinkStatus && gsProg->GeometryProgram) { /* Use shader programs */ _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, - shProg->GeometryProgram); + gsProg->GeometryProgram); } else { /* no fragment program */ _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL); @@ -305,10 +307,10 @@ update_program(struct gl_context *ctx) * _mesa_get_fixed_func_vertex_program() needs to know active * fragprog inputs. */ - if (shProg && shProg->LinkStatus && shProg->VertexProgram) { + if (vsProg && vsProg->LinkStatus && vsProg->VertexProgram) { /* Use shader programs */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, - shProg->VertexProgram); + vsProg->VertexProgram); } else if (ctx->VertexProgram._Enabled) { /* use user-defined vertex program */ diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c index 4647a9c440..a8bffe416d 100644 --- a/src/mesa/main/texenvprogram.c +++ b/src/mesa/main/texenvprogram.c @@ -310,9 +310,10 @@ static GLuint translate_tex_src_bit( GLbitfield bit ) static GLbitfield get_fp_input_mask( struct gl_context *ctx ) { /* _NEW_PROGRAM */ - const GLboolean vertexShader = (ctx->Shader.CurrentProgram && - ctx->Shader.CurrentProgram->LinkStatus && - ctx->Shader.CurrentProgram->VertexProgram); + const GLboolean vertexShader = + (ctx->Shader.CurrentVertexProgram && + ctx->Shader.CurrentVertexProgram->LinkStatus && + ctx->Shader.CurrentVertexProgram->VertexProgram); const GLboolean vertexProgram = ctx->VertexProgram._Enabled; GLbitfield fp_inputs = 0x0; @@ -377,7 +378,7 @@ static GLbitfield get_fp_input_mask( struct gl_context *ctx ) * validation (see additional comments in state.c). */ if (vertexShader) - vprog = ctx->Shader.CurrentProgram->VertexProgram; + vprog = ctx->Shader.CurrentVertexProgram->VertexProgram; else vprog = ctx->VertexProgram.Current; diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c index 1b0d760fae..f4d77189f2 100644 --- a/src/mesa/main/texstate.c +++ b/src/mesa/main/texstate.c @@ -496,23 +496,28 @@ update_texture_state( struct gl_context *ctx ) struct gl_vertex_program *vprog = NULL; GLbitfield enabledFragUnits = 0x0; - if (ctx->Shader.CurrentProgram && - ctx->Shader.CurrentProgram->LinkStatus) { - fprog = ctx->Shader.CurrentProgram->FragmentProgram; - vprog = ctx->Shader.CurrentProgram->VertexProgram; + if (ctx->Shader.CurrentVertexProgram && + ctx->Shader.CurrentVertexProgram->LinkStatus) { + vprog = ctx->Shader.CurrentVertexProgram->VertexProgram; + } else if (ctx->VertexProgram._Enabled) { + /* XXX enable this if/when non-shader vertex programs get + * texture fetches: + vprog = ctx->VertexProgram.Current; + */ } - else { - if (ctx->FragmentProgram._Enabled) { - fprog = ctx->FragmentProgram.Current; - } - if (ctx->VertexProgram._Enabled) { - /* XXX enable this if/when non-shader vertex programs get - * texture fetches: - vprog = ctx->VertexProgram.Current; - */ - } + + if (ctx->Shader.CurrentFragmentProgram && + ctx->Shader.CurrentFragmentProgram->LinkStatus) { + fprog = ctx->Shader.CurrentFragmentProgram->FragmentProgram; + } + else if (ctx->FragmentProgram._Enabled) { + fprog = ctx->FragmentProgram.Current; } + /* FINISHME: Geometry shader texture accesses should also be considered + * FINISHME: here. + */ + /* TODO: only set this if there are actual changes */ ctx->NewState |= _NEW_TEXTURE; diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c index 451299cef0..f92ca13d5e 100644 --- a/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/src/mesa/state_tracker/st_atom_rasterizer.c @@ -96,9 +96,8 @@ static void update_raster_state( struct st_context *st ) */ if (ctx->VertexProgram._Current) { if (ctx->VertexProgram._Enabled || - (ctx->Shader.CurrentProgram && - ctx->Shader.CurrentProgram->VertexProgram && - ctx->Shader.CurrentProgram->LinkStatus)) { + (ctx->Shader.CurrentVertexProgram && + ctx->Shader.CurrentVertexProgram->LinkStatus)) { /* user-defined vertex program or shader */ raster->light_twoside = ctx->VertexProgram.TwoSideEnabled; } diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 5387499eb9..61a0e1b087 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -547,11 +547,21 @@ setup_index_buffer(struct gl_context *ctx, static void check_uniforms(struct gl_context *ctx) { - const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; - if (shProg && shProg->LinkStatus) { - GLuint i; - for (i = 0; i < shProg->Uniforms->NumUniforms; i++) { - const struct gl_uniform *u = &shProg->Uniforms->Uniforms[i]; + struct gl_shader_program *shProg[3] = { + ctx->Shader.CurrentVertexProgram, + ctx->Shader.CurrentGeometryProgram, + ctx->Shader.CurrentFragmentProgram, + }; + unsigned j; + + for (j = 0; j < 3; j++) { + unsigned i; + + if (shProg[j] == NULL || !shProg[j]->LinkStatus) + continue; + + for (i = 0; i < shProg[j]->Uniforms->NumUniforms; i++) { + const struct gl_uniform *u = &shProg[j]->Uniforms->Uniforms[i]; if (!u->Initialized) { _mesa_warning(ctx, "Using shader with uninitialized uniform: %s", diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 95e6bd7dac..6a5d741b61 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -718,12 +718,38 @@ st_translate_geometry_program(struct st_context *st, void st_print_shaders(struct gl_context *ctx) { - struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; - if (shProg) { - GLuint i; - for (i = 0; i < shProg->NumShaders; i++) { - printf("GLSL shader %u of %u:\n", i, shProg->NumShaders); - printf("%s\n", shProg->Shaders[i]->Source); + struct gl_shader_program *shProg[3] = { + ctx->Shader.CurrentVertexProgram, + ctx->Shader.CurrentGeometryProgram, + ctx->Shader.CurrentFragmentProgram, + }; + unsigned j; + + for (j = 0; j < 3; j++) { + unsigned i; + + if (shProg[j] == NULL) + continue; + + for (i = 0; i < shProg[j]->NumShaders; i++) { + struct gl_shader *sh; + + switch (shProg[j]->Shaders[i]->Type) { + case GL_VERTEX_SHADER: + sh = (i != 0) ? NULL : shProg[j]->Shaders[i]; + break; + case GL_GEOMETRY_SHADER_ARB: + sh = (i != 1) ? NULL : shProg[j]->Shaders[i]; + break; + case GL_FRAGMENT_SHADER: + sh = (i != 2) ? NULL : shProg[j]->Shaders[i]; + break; + } + + if (sh != NULL) { + printf("GLSL shader %u of %u:\n", i, shProg[j]->NumShaders); + printf("%s\n", sh->Source); + } } } } diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c index e421d218d7..e391043f4d 100644 --- a/src/mesa/swrast/s_fragprog.c +++ b/src/mesa/swrast/s_fragprog.c @@ -169,7 +169,7 @@ init_machine(struct gl_context *ctx, struct gl_program_machine *machine, machine->Samplers = program->Base.SamplerUnits; /* if running a GLSL program (not ARB_fragment_program) */ - if (ctx->Shader.CurrentProgram) { + if (ctx->Shader.CurrentFragmentProgram) { /* Store front/back facing value */ machine->Attribs[FRAG_ATTRIB_FACE][col][0] = 1.0F - span->facing; } -- cgit v1.2.3