softpipe: fix dangling references to shaders in the TGSI executor
authorBrian Paul <brianp@vmware.com>
Thu, 6 May 2010 21:10:51 +0000 (15:10 -0600)
committerBrian Paul <brianp@vmware.com>
Thu, 6 May 2010 21:19:02 +0000 (15:19 -0600)
If a shader was bound to the fragment shader TGSI executor and it was
then deleted and a new shader was allocated at the same address as the
old shader, the new fragment shader would not get properly bound to
the TGSI machine and we'd wind up using the old one.

This would not have been a problem if shaders were refcounted.

Now the TGSI machine is owned by the context rather than the quad
pipeline's shader stage so that the softpipe_delete_fs_state()
function can access it.

Fixes sporadic failures of the piglit fp-long-alu test (fd.o bug 27989).

src/gallium/drivers/softpipe/sp_context.c
src/gallium/drivers/softpipe/sp_context.h
src/gallium/drivers/softpipe/sp_quad_fs.c
src/gallium/drivers/softpipe/sp_state_fs.c

index f6e2b80d46e19baeb569ed46f49e7feed1cf2232..fea3520fa56a1b82921654d4aabb9a061f685536 100644 (file)
@@ -36,6 +36,7 @@
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
+#include "tgsi/tgsi_exec.h"
 #include "sp_clear.h"
 #include "sp_context.h"
 #include "sp_flush.h"
@@ -123,6 +124,8 @@ softpipe_destroy( struct pipe_context *pipe )
       }
    }
 
+   tgsi_exec_machine_destroy(softpipe->fs_machine);
+
    FREE( softpipe );
 }
 
@@ -293,6 +296,8 @@ softpipe_create_context( struct pipe_screen *screen,
       softpipe->vertex_tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe );
    }
 
+   softpipe->fs_machine = tgsi_exec_machine_create();
+
    /* setup quad rendering stages */
    softpipe->quad.shade = sp_quad_shade_stage(softpipe);
    softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe);
index 92607874b60912f4f0d3551be46b1d2615a87cfe..aa696257688be82f4af951320aa0f02eff1df1ee 100644 (file)
@@ -140,6 +140,8 @@ struct softpipe_context {
       struct sp_sampler_varient *frag_samplers_list[PIPE_MAX_SAMPLERS];
    } tgsi;
 
+   struct tgsi_exec_machine *fs_machine;
+
    /** The primitive drawing context */
    struct draw_context *draw;
 
index 8ae5a7f028b2985a2f8099d63b52c5a5b4995eaf..907e94b59b98ab924af61527346fdc5be9d47801 100644 (file)
@@ -50,8 +50,8 @@
 struct quad_shade_stage
 {
    struct quad_stage stage;  /**< base class */
-   struct tgsi_exec_machine *machine;
-   struct tgsi_exec_vector *inputs, *outputs;
+
+   /* no other fields at this time */
 };
 
 
@@ -70,9 +70,8 @@ quad_shade_stage(struct quad_stage *qs)
 static INLINE boolean
 shade_quad(struct quad_stage *qs, struct quad_header *quad)
 {
-   struct quad_shade_stage *qss = quad_shade_stage( qs );
    struct softpipe_context *softpipe = qs->softpipe;
-   struct tgsi_exec_machine *machine = qss->machine;
+   struct tgsi_exec_machine *machine = softpipe->fs_machine;
 
    /* run shader */
    return softpipe->fs->run( softpipe->fs, machine, quad );
@@ -108,9 +107,8 @@ shade_quads(struct quad_stage *qs,
             struct quad_header *quads[],
             unsigned nr)
 {
-   struct quad_shade_stage *qss = quad_shade_stage( qs );
    struct softpipe_context *softpipe = qs->softpipe;
-   struct tgsi_exec_machine *machine = qss->machine;
+   struct tgsi_exec_machine *machine = softpipe->fs_machine;
    unsigned i, pass = 0;
 
    for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
@@ -139,11 +137,10 @@ shade_quads(struct quad_stage *qs,
 static void
 shade_begin(struct quad_stage *qs)
 {
-   struct quad_shade_stage *qss = quad_shade_stage(qs);
    struct softpipe_context *softpipe = qs->softpipe;
 
    softpipe->fs->prepare( softpipe->fs, 
-                         qss->machine,
+                         softpipe->fs_machine,
                          (struct tgsi_sampler **)
                              softpipe->tgsi.frag_samplers_list );
 
@@ -154,10 +151,6 @@ shade_begin(struct quad_stage *qs)
 static void
 shade_destroy(struct quad_stage *qs)
 {
-   struct quad_shade_stage *qss = (struct quad_shade_stage *) qs;
-
-   tgsi_exec_machine_destroy(qss->machine);
-
    FREE( qs );
 }
 
@@ -174,16 +167,9 @@ sp_quad_shade_stage( struct softpipe_context *softpipe )
    qss->stage.run = shade_quads;
    qss->stage.destroy = shade_destroy;
 
-   qss->machine = tgsi_exec_machine_create();
-   if (!qss->machine)
-      goto fail;
-
    return &qss->stage;
 
 fail:
-   if (qss && qss->machine)
-      tgsi_exec_machine_destroy(qss->machine);
-
    FREE(qss);
    return NULL;
 }
index 7f072f5a2698eeeb8982600e5a731b449f2d3d3d..816e0c18bd2b898ca714dc086436f53c164ef5f3 100644 (file)
@@ -36,6 +36,7 @@
 #include "draw/draw_context.h"
 #include "draw/draw_vs.h"
 #include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_exec.h"
 #include "tgsi/tgsi_scan.h"
 #include "tgsi/tgsi_parse.h"
 
@@ -95,10 +96,18 @@ softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
 void
 softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
 {
+   struct softpipe_context *softpipe = softpipe_context(pipe);
    struct sp_fragment_shader *state = fs;
 
    assert(fs != softpipe_context(pipe)->fs);
-   
+
+   if (softpipe->fs_machine->Tokens == state->shader.tokens) {
+      /* unbind the shader from the tgsi executor if we're
+       * deleting it.
+       */
+      tgsi_exec_machine_bind_shader(softpipe->fs_machine, NULL, 0, NULL);
+   }
+
    state->delete( state );
 }