From b527dd65c830a2b008816cf390d5be906e29bb23 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 15 Nov 2011 12:01:18 -0800 Subject: [PATCH] mesa: Track fixed-function fragment shader as a shader Previously the fixed-function fragment shader was tracked as a gl_program. This means that it shows up in the driver as a Mesa IR program instead of as a GLSL IR program. If a driver doesn't generate Mesa IR from the GLSL IR, that program is empty. If the program is empty there is either no rendering or a GPU hang. Signed-off-by: Ian Romanick Reviewed-by: Eric Anholt Acked-by: Kenneth Graunke --- src/mesa/drivers/dri/i965/brw_wm.c | 2 +- src/mesa/drivers/dri/i965/brw_wm_state.c | 4 ++-- src/mesa/drivers/dri/i965/gen6_wm_state.c | 4 +++- src/mesa/drivers/dri/i965/gen7_wm_state.c | 4 +++- src/mesa/main/mtypes.h | 2 ++ src/mesa/main/shaderapi.c | 29 +++++++++++++++++++++++ src/mesa/main/state.c | 10 ++++++++ 7 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c index cad0af8c1ac..7dee20b7f92 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.c +++ b/src/mesa/drivers/dri/i965/brw_wm.c @@ -543,7 +543,7 @@ brw_upload_wm_prog(struct brw_context *brw) if (!brw_search_cache(&brw->cache, BRW_WM_PROG, &key, sizeof(key), &brw->wm.prog_offset, &brw->wm.prog_data)) { - bool success = do_wm_prog(brw, ctx->Shader.CurrentFragmentProgram, fp, + bool success = do_wm_prog(brw, ctx->Shader._CurrentFragmentProgram, fp, &key); (void) success; assert(success); diff --git a/src/mesa/drivers/dri/i965/brw_wm_state.c b/src/mesa/drivers/dri/i965/brw_wm_state.c index e1791c20ea7..dd67795e743 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_state.c @@ -169,9 +169,9 @@ brw_upload_wm_unit(struct brw_context *brw) * If using the fragment shader backend, the program is always * 8-wide. If not, it's always 16. */ - if (ctx->Shader.CurrentFragmentProgram) { + if (ctx->Shader._CurrentFragmentProgram) { struct brw_shader *shader = (struct brw_shader *) - ctx->Shader.CurrentFragmentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]; + ctx->Shader._CurrentFragmentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]; if (shader != NULL && shader->ir != NULL) { wm->wm5.enable_8_pix = 1; diff --git a/src/mesa/drivers/dri/i965/gen6_wm_state.c b/src/mesa/drivers/dri/i965/gen6_wm_state.c index 0547eb8a0b3..3669811be55 100644 --- a/src/mesa/drivers/dri/i965/gen6_wm_state.c +++ b/src/mesa/drivers/dri/i965/gen6_wm_state.c @@ -135,7 +135,9 @@ upload_wm_state(struct brw_context *brw) dw5 |= GEN6_WM_LINE_END_CAP_AA_WIDTH_0_5; /* Use ALT floating point mode for ARB fragment programs, because they - * require 0^0 == 1. + * require 0^0 == 1. Even though _CurrentFragmentProgram is used for + * rendering, CurrentFragmentProgram is used for this check to + * differentiate between the GLSL and non-GLSL cases. */ if (ctx->Shader.CurrentFragmentProgram == NULL) dw2 |= GEN6_WM_FLOATING_POINT_MODE_ALT; diff --git a/src/mesa/drivers/dri/i965/gen7_wm_state.c b/src/mesa/drivers/dri/i965/gen7_wm_state.c index 1468fcc1278..32222f922d8 100644 --- a/src/mesa/drivers/dri/i965/gen7_wm_state.c +++ b/src/mesa/drivers/dri/i965/gen7_wm_state.c @@ -166,7 +166,9 @@ upload_ps_state(struct brw_context *brw) dw2 |= (ALIGN(brw->sampler.count, 4) / 4) << GEN7_PS_SAMPLER_COUNT_SHIFT; /* Use ALT floating point mode for ARB fragment programs, because they - * require 0^0 == 1. + * require 0^0 == 1. Even though _CurrentFragmentProgram is used for + * rendering, CurrentFragmentProgram is used for this check to + * differentiate between the GLSL and non-GLSL cases. */ if (intel->ctx.Shader.CurrentFragmentProgram == NULL) dw2 |= GEN7_PS_FLOATING_POINT_MODE_ALT; diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index bb46ba0c035..aca47379ca1 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2350,6 +2350,8 @@ struct gl_shader_state struct gl_shader_program *CurrentGeometryProgram; struct gl_shader_program *CurrentFragmentProgram; + 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 9372d6decf6..f3f13a02645 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -124,6 +124,8 @@ _mesa_free_shader_state(struct gl_context *ctx) NULL); _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentFragmentProgram, NULL); + _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram, + NULL); _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL); } @@ -876,6 +878,33 @@ use_shader_program(struct gl_context *ctx, GLenum type, if (*target != shProg) { FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + + /* If the shader is also bound as the current rendering shader, unbind + * it from that binding point as well. This ensures that the correct + * semantics of glDeleteProgram are maintained. + */ + switch (type) { +#if FEATURE_ARB_vertex_shader + case GL_VERTEX_SHADER: + /* Empty for now. */ + break; +#endif +#if FEATURE_ARB_geometry_shader4 + case GL_GEOMETRY_SHADER_ARB: + /* Empty for now. */ + break; +#endif +#if FEATURE_ARB_fragment_shader + case GL_FRAGMENT_SHADER: + if (*target == ctx->Shader._CurrentFragmentProgram) { + _mesa_reference_shader_program(ctx, + &ctx->Shader._CurrentFragmentProgram, + NULL); + } + break; +#endif + } + _mesa_reference_shader_program(ctx, target, shProg); return true; } diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 7e43563bd01..56bb797e625 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -43,6 +43,7 @@ #include "pixel.h" #include "program/program.h" #include "program/prog_parameter.h" +#include "shaderobj.h" #include "state.h" #include "stencil.h" #include "texenvprogram.h" @@ -252,12 +253,18 @@ update_program(struct gl_context *ctx) if (fsProg && fsProg->LinkStatus && fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]) { /* Use GLSL fragment shader */ + _mesa_reference_shader_program(ctx, + &ctx->Shader._CurrentFragmentProgram, + fsProg); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, (struct gl_fragment_program *) fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program); } else if (ctx->FragmentProgram._Enabled) { /* Use user-defined fragment program */ + _mesa_reference_shader_program(ctx, + &ctx->Shader._CurrentFragmentProgram, + NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, ctx->FragmentProgram.Current); } @@ -265,6 +272,9 @@ update_program(struct gl_context *ctx) /* Use fragment program generated from fixed-function state */ struct gl_shader_program *f = _mesa_get_fixed_func_fragment_program(ctx); + _mesa_reference_shader_program(ctx, + &ctx->Shader._CurrentFragmentProgram, + f); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, (struct gl_fragment_program *) f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program); -- 2.30.2