softpipe: fix dangling references to shaders in the TGSI executor
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).
This commit is contained in:
@@ -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);
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 );
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user