[Mesa-dev] [PATCH 05/21 v3] meta: Fix saving the program pipeline state
Chia-I Wu
olvaffe at gmail.com
Thu May 1 17:37:47 PDT 2014
On Fri, May 2, 2014 at 7:38 AM, Ian Romanick <idr at freedesktop.org> wrote:
> From: Ian Romanick <ian.d.romanick at intel.com>
>
> This code was broken in some odd ways before. Too much state was being
> saved, it was being restored in the wrong order, and in the wrong way.
> The biggest problem was that the pipeline object was restored before
> restoring the programs attached to the default pipeline.
>
> Fixes a regression in the glean texgen test.
>
> v3: Fairly significant re-write. I think it's much cleaner now, and it
> avoids a bug with some meta ops that use shaders (reported by Chia-I).
Thanks, it fixes the bug. The patch looks good to me. A few minor
comments/questions below.
> Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
> Cc: Chia-I Wu <olvaffe at gmail.com>
> ---
> src/mesa/drivers/common/meta.c | 86 ++++++++++++++++++++++++++----------------
> src/mesa/drivers/common/meta.h | 1 -
> 2 files changed, 53 insertions(+), 34 deletions(-)
>
> diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
> index ab86f9c..42b67ec 100644
> --- a/src/mesa/drivers/common/meta.c
> +++ b/src/mesa/drivers/common/meta.c
> @@ -577,19 +577,21 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
> }
>
> if (ctx->Extensions.ARB_separate_shader_objects) {
> - /* Warning it must be done before _mesa_UseProgram call */
> - _mesa_reference_pipeline_object(ctx, &save->_Shader, ctx->_Shader);
> - _mesa_reference_pipeline_object(ctx, &save->Pipeline,
> - ctx->Pipeline.Current);
> - _mesa_BindProgramPipeline(0);
> + if (ctx->Pipeline.Current != ctx->Pipeline.Default) {
It seems ctx->Pipeline.Current is never equal to
ctx->Pipeline.Default. You may check against NULL instead.
> + _mesa_reference_pipeline_object(ctx, &save->Pipeline,
> + ctx->Pipeline.Current);
> + _mesa_BindProgramPipeline(0);
> }
>
> - for (i = 0; i < MESA_SHADER_STAGES; i++) {
> + /* Save the shader state from ctx->Shader (instead of ctx->_Shader) so
> + * that we don't have to worry about the current pipeline state.
> + */
> + for (i = 0; i <= MESA_SHADER_FRAGMENT; i++) {
I am not familiar with MESA_SHADER_COMPUTE. If this will not give us
headaches in the future, I am fine with it.
> _mesa_reference_shader_program(ctx, &save->Shader[i],
> - ctx->_Shader->CurrentProgram[i]);
> + ctx->Shader.CurrentProgram[i]);
> }
> _mesa_reference_shader_program(ctx, &save->ActiveShader,
> - ctx->_Shader->ActiveProgram);
> + ctx->Shader.ActiveProgram);
>
> _mesa_UseProgram(0);
> }
> @@ -908,6 +910,14 @@ _mesa_meta_end(struct gl_context *ctx)
> }
>
> if (state & MESA_META_SHADER) {
> + static const GLenum targets[] = {
> + GL_VERTEX_SHADER,
> + GL_GEOMETRY_SHADER,
> + GL_FRAGMENT_SHADER,
> + };
> +
> + bool any_shader;
> +
> if (ctx->Extensions.ARB_vertex_program) {
> _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB,
> save->VertexProgramEnabled);
> @@ -929,37 +939,47 @@ _mesa_meta_end(struct gl_context *ctx)
> save->ATIFragmentShaderEnabled);
> }
>
> - /* Warning it must be done before _mesa_use_shader_program call */
> - if (ctx->Extensions.ARB_separate_shader_objects) {
> - _mesa_reference_pipeline_object(ctx, &ctx->_Shader, save->_Shader);
> - _mesa_reference_pipeline_object(ctx, &ctx->Pipeline.Current,
> - save->Pipeline);
> - _mesa_reference_pipeline_object(ctx, &save->Pipeline, NULL);
> - }
> + any_shader = false;
> + for (i = 0; i <= MESA_SHADER_FRAGMENT; i++) {
> + /* It is safe to call _mesa_use_shader_program even if the extension
> + * necessary for that program state is not supported. In that case,
> + * the saved program object must be NULL and the currently bound
> + * program object must be NULL. _mesa_use_shader_program is a no-op
> + * in that case.
> + */
> + _mesa_use_shader_program(ctx, targets[i],
> + save->Shader[i],
> + &ctx->Shader);
> +
> + /* Do this *before* killing the reference. :)
> + */
> + if (save->Shader[i] != NULL)
> + any_shader = true;
>
> - if (ctx->Extensions.ARB_vertex_shader) {
> - _mesa_use_shader_program(ctx, GL_VERTEX_SHADER,
> - save->Shader[MESA_SHADER_VERTEX],
> - ctx->_Shader);
> + _mesa_reference_shader_program(ctx, &save->Shader[i], NULL);
> }
>
> - if (_mesa_has_geometry_shaders(ctx))
> - _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB,
> - save->Shader[MESA_SHADER_GEOMETRY],
> - ctx->_Shader);
> + _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram,
> + save->ActiveShader);
> + _mesa_reference_shader_program(ctx, &save->ActiveShader, NULL);
>
> - if (ctx->Extensions.ARB_fragment_shader)
> - _mesa_use_shader_program(ctx, GL_FRAGMENT_SHADER,
> - save->Shader[MESA_SHADER_FRAGMENT],
> - ctx->_Shader);
> + /* If there were any stages set with programs, use ctx->Shader as the
> + * current shader state. Otherwise, use Pipeline.Default. The pipeline
> + * hasn't been restored yet, and that may modify ctx->_Shader further.
> + */
> + if (any_shader)
> + _mesa_reference_pipeline_object(ctx, &ctx->_Shader,
> + &ctx->Shader);
> + else
> + _mesa_reference_pipeline_object(ctx, &ctx->_Shader,
> + ctx->Pipeline.Default);
>
> - _mesa_reference_shader_program(ctx, &ctx->_Shader->ActiveProgram,
> - save->ActiveShader);
> + if (save->Pipeline) {
> + assert(ctx->Extensions.ARB_separate_shader_objects);
> + _mesa_bind_pipeline(ctx, save->Pipeline);
>
> - for (i = 0; i < MESA_SHADER_STAGES; i++)
> - _mesa_reference_shader_program(ctx, &save->Shader[i], NULL);
> - _mesa_reference_shader_program(ctx, &save->ActiveShader, NULL);
> - _mesa_reference_pipeline_object(ctx, &save->_Shader, NULL);
> + _mesa_reference_pipeline_object(ctx, &save->Pipeline, NULL);
> + }
> }
>
> if (state & MESA_META_STENCIL_TEST) {
> diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h
> index fde4f9a..0a34792 100644
> --- a/src/mesa/drivers/common/meta.h
> +++ b/src/mesa/drivers/common/meta.h
> @@ -121,7 +121,6 @@ struct save_state
> GLboolean ATIFragmentShaderEnabled;
> struct gl_shader_program *Shader[MESA_SHADER_STAGES];
> struct gl_shader_program *ActiveShader;
> - struct gl_pipeline_object *_Shader;
> struct gl_pipeline_object *Pipeline;
>
> /** MESA_META_STENCIL_TEST */
> --
> 1.8.1.4
>
--
olv at LunarG.com
More information about the mesa-dev
mailing list