path: root/src/mesa/drivers/dri/i965
diff options
authorKenneth Graunke <>2013-01-08 17:00:13 -0800
committerKenneth Graunke <>2013-01-12 15:36:21 -0800
commit8c80bdc4a8d0b1c39cad8b8bfb1b982a498f0a8e (patch)
tree456e326bf812e7bd13f1bd72434a9c0121969d77 /src/mesa/drivers/dri/i965
parent2c4ad502ce12259160be6c73ebdd6e73a5d27c6f (diff)
i965: Move program_id to intel_screen instead of brw_context.
According to bug #54524, I regressed oglconform's multicontext test when I reenabled the fragment shader precompile. However, these test cases only passed by miraculous coincedence. We assign each fragment program a unique ID (brw_fragment_program::id which becomes brw_wm_prog_key::program_string_id) which we obtain by storing a per-context counter. The test case uses GLX context sharing to access the same fragment program from two different contexts. This means that we share a program cache. Before the precompile, if both contexts happened to use the same shaders in the same order, we'd obtain the same program_string_ids (by virtue of doing the same computation twice). However, the more likely scenario is that they completely disagree on program_string_id. This meant that we'd have two completely different fragment shaders in the cache with the same ID, tricking us to think they were the same (aside from NOS), so we'd render using the wrong program. This patch implements a simple fix suggested by Eric: it moves the global counter out of brw_context and into intel_screen, which is shared across all contexts. A mutex protects it from concurrent access. This is also the first direct usage of pthreads in the i965 driver. Fixes 10 subcases of oglconform's multicontext test. Bugzilla: Reviewed-by: Eric Anholt <>
Diffstat (limited to 'src/mesa/drivers/dri/i965')
2 files changed, 15 insertions, 7 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index c7fc5864d80..f3a3efed0dd 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -1053,9 +1053,6 @@ struct brw_context
int index;
bool begin_emitted;
} query;
- /* Used to give every program string a unique id
- */
- GLuint program_id;
int num_atoms;
const struct brw_tracked_state **atoms;
diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c
index 5bfdcca216b..75eb6bc6689 100644
--- a/src/mesa/drivers/dri/i965/brw_program.c
+++ b/src/mesa/drivers/dri/i965/brw_program.c
@@ -29,6 +29,7 @@
* Keith Whitwell <>
+#include <pthread.h>
#include "main/imports.h"
#include "main/enums.h"
#include "main/shaderobj.h"
@@ -41,6 +42,16 @@
#include "brw_context.h"
#include "brw_wm.h"
+static unsigned
+get_new_program_id(struct intel_screen *screen)
+ static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&m);
+ unsigned id = screen->program_id++;
+ pthread_mutex_unlock(&m);
+ return id;
static void brwBindProgram( struct gl_context *ctx,
GLenum target,
struct gl_program *prog )
@@ -67,7 +78,7 @@ static struct gl_program *brwNewProgram( struct gl_context *ctx,
struct brw_vertex_program *prog = CALLOC_STRUCT(brw_vertex_program);
if (prog) {
- prog->id = brw->program_id++;
+ prog->id = get_new_program_id(brw->intel.intelScreen);
return _mesa_init_vertex_program( ctx, &prog->program,
target, id );
@@ -79,7 +90,7 @@ static struct gl_program *brwNewProgram( struct gl_context *ctx,
struct brw_fragment_program *prog = CALLOC_STRUCT(brw_fragment_program);
if (prog) {
- prog->id = brw->program_id++;
+ prog->id = get_new_program_id(brw->intel.intelScreen);
return _mesa_init_fragment_program( ctx, &prog->program,
target, id );
@@ -123,7 +134,7 @@ brwProgramStringNotify(struct gl_context *ctx,
if (newFP == curFP)
brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM;
- newFP->id = brw->program_id++;
+ newFP->id = get_new_program_id(brw->intel.intelScreen);
else if (target == GL_VERTEX_PROGRAM_ARB) {
struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog;
@@ -136,7 +147,7 @@ brwProgramStringNotify(struct gl_context *ctx,
if (newVP->program.IsPositionInvariant) {
_mesa_insert_mvp_code(ctx, &newVP->program);
- newVP->id = brw->program_id++;
+ newVP->id = get_new_program_id(brw->intel.intelScreen);
/* Also tell tnl about it: