[Mesa-dev] [PATCH] [RFC] r600g: cache shader variants instead of rebuilding

Vadim Girlin vadimgirlin at gmail.com
Sat Jun 9 11:48:34 CEST 2012


Shader variants are stored in the keymap, the key is based on the states
that require different hw shaders - currently it's rctx->two_side
(all gpus) and rctx->nr_cbufs (evergreen/cayman, when writes_all property
is set).

Improves performance for some apps, e.g. FlightGear -
see https://bugs.freedesktop.org/show_bug.cgi?id=50360

Signed-off-by: Vadim Girlin <vadimgirlin at gmail.com>
---

Tested on evergreen, no regressions.
Needs testing on r6xx/r7xx - I'm not sure about some changes.

 src/gallium/drivers/r600/evergreen_state.c   |    4 +-
 src/gallium/drivers/r600/r600_pipe.h         |   38 ++++-
 src/gallium/drivers/r600/r600_shader.c       |   17 +-
 src/gallium/drivers/r600/r600_state.c        |   23 +--
 src/gallium/drivers/r600/r600_state_common.c |  232 ++++++++++++++++++--------
 5 files changed, 218 insertions(+), 96 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index b618ca8..2bc1f67 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -1843,12 +1843,12 @@ void evergreen_init_state_functions(struct r600_context *rctx)
 
 	rctx->context.create_blend_state = evergreen_create_blend_state;
 	rctx->context.create_depth_stencil_alpha_state = evergreen_create_dsa_state;
-	rctx->context.create_fs_state = r600_create_shader_state;
+	rctx->context.create_fs_state = r600_create_shader_state_ps;
 	rctx->context.create_rasterizer_state = evergreen_create_rs_state;
 	rctx->context.create_sampler_state = evergreen_create_sampler_state;
 	rctx->context.create_sampler_view = evergreen_create_sampler_view;
 	rctx->context.create_vertex_elements_state = r600_create_vertex_elements;
-	rctx->context.create_vs_state = r600_create_shader_state;
+	rctx->context.create_vs_state = r600_create_shader_state_vs;
 	rctx->context.bind_blend_state = r600_bind_blend_state;
 	rctx->context.bind_depth_stencil_alpha_state = r600_bind_dsa_state;
 	rctx->context.bind_fragment_sampler_states = evergreen_bind_ps_sampler;
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index f2865d2..1cb4ab7 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -184,18 +184,38 @@ struct r600_vertex_element
 	struct r600_pipe_state		rstate;
 };
 
+struct r600_pipe_shader;
+
+struct r600_pipe_shader_selector {
+	struct r600_pipe_shader *current;
+	struct keymap           *shaders;
+
+	struct tgsi_token       *tokens;
+	struct pipe_stream_output_info  so;
+
+	unsigned	num_shaders;
+
+	/* PIPE_SHADER_[VERTEX|FRAGMENT|...] */
+	unsigned	type;
+
+	/* 1 on evergreen+ when the shader contains
+	 * TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS, otherwise it's 0.
+	 * Used to determine whether we need to include nr_cbufs in the key */
+	unsigned	eg_fs_write_all;
+};
+
 struct r600_pipe_shader {
+	struct r600_pipe_shader_selector *selector;
 	struct r600_shader		shader;
 	struct r600_pipe_state		rstate;
 	struct r600_resource		*bo;
 	struct r600_resource		*bo_fetch;
 	struct r600_vertex_element	vertex_elements;
-	struct tgsi_token		*tokens;
 	unsigned	sprite_coord_enable;
 	unsigned	flatshade;
 	unsigned	pa_cl_vs_out_cntl;
-	unsigned        ps_cb_shader_mask;
-	struct pipe_stream_output_info	so;
+	unsigned	ps_cb_shader_mask;
+	unsigned	key;
 };
 
 struct r600_pipe_sampler_state {
@@ -271,8 +291,8 @@ struct r600_context {
 	struct pipe_stencil_ref		stencil_ref;
 	struct pipe_viewport_state	viewport;
 	struct pipe_clip_state		clip;
-	struct r600_pipe_shader 	*ps_shader;
-	struct r600_pipe_shader 	*vs_shader;
+	struct r600_pipe_shader_selector 	*ps_shader;
+	struct r600_pipe_shader_selector 	*vs_shader;
 	struct r600_pipe_compute	*cs_shader;
 	struct r600_pipe_rasterizer	*rasterizer;
 	struct r600_pipe_state          vgt;
@@ -436,8 +456,6 @@ int r600_compute_shader_create(struct pipe_context * ctx,
 	LLVMModuleRef mod,  struct r600_bytecode * bytecode);
 #endif
 void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *shader);
-int r600_find_vs_semantic_index(struct r600_shader *vs,
-				struct r600_shader *ps, int id);
 
 /* r600_state.c */
 void r600_set_scissor_state(struct r600_context *rctx,
@@ -497,8 +515,10 @@ void r600_sampler_view_destroy(struct pipe_context *ctx,
 			       struct pipe_sampler_view *state);
 void r600_delete_state(struct pipe_context *ctx, void *state);
 void r600_bind_vertex_elements(struct pipe_context *ctx, void *state);
-void *r600_create_shader_state(struct pipe_context *ctx,
-			       const struct pipe_shader_state *state);
+void *r600_create_shader_state_ps(struct pipe_context *ctx,
+                   const struct pipe_shader_state *state);
+void *r600_create_shader_state_vs(struct pipe_context *ctx,
+                   const struct pipe_shader_state *state);
 void r600_bind_ps_shader(struct pipe_context *ctx, void *state);
 void r600_bind_vs_shader(struct pipe_context *ctx, void *state);
 void r600_delete_ps_shader(struct pipe_context *ctx, void *state);
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index 63b9a03..a35ad74 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -109,6 +109,7 @@ int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *s
 {
 	static int dump_shaders = -1;
 	struct r600_context *rctx = (struct r600_context *)ctx;
+	struct r600_pipe_shader_selector *sel = shader->selector;
 	int r;
 
 	/* Would like some magic "get_bool_option_once" routine.
@@ -118,16 +119,16 @@ int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *s
 
 	if (dump_shaders) {
 		fprintf(stderr, "--------------------------------------------------------------\n");
-		tgsi_dump(shader->tokens, 0);
+		tgsi_dump(sel->tokens, 0);
 
-		if (shader->so.num_outputs) {
+		if (sel->so.num_outputs) {
 			unsigned i;
 			fprintf(stderr, "STREAMOUT\n");
-			for (i = 0; i < shader->so.num_outputs; i++) {
-				unsigned mask = ((1 << shader->so.output[i].num_components) - 1) <<
-						shader->so.output[i].start_component;
+			for (i = 0; i < sel->so.num_outputs; i++) {
+				unsigned mask = ((1 << sel->so.output[i].num_components) - 1) <<
+						sel->so.output[i].start_component;
 				fprintf(stderr, "  %i: MEM_STREAM0_BUF%i OUT[%i].%s%s%s%s\n", i,
-					shader->so.output[i].output_buffer, shader->so.output[i].register_index,
+					sel->so.output[i].output_buffer, sel->so.output[i].register_index,
 				        mask & 1 ? "x" : "_",
 				        (mask >> 1) & 1 ? "y" : "_",
 				        (mask >> 2) & 1 ? "z" : "_",
@@ -1118,8 +1119,8 @@ static int process_twoside_color_inputs(struct r600_shader_ctx *ctx)
 static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_shader *pipeshader)
 {
 	struct r600_shader *shader = &pipeshader->shader;
-	struct tgsi_token *tokens = pipeshader->tokens;
-	struct pipe_stream_output_info so = pipeshader->so;
+	struct tgsi_token *tokens = pipeshader->selector->tokens;
+	struct pipe_stream_output_info so = pipeshader->selector->so;
 	struct tgsi_full_immediate *immediate;
 	struct tgsi_full_property *property;
 	struct r600_shader_ctx ctx;
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index 124eba2..d94c16b 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -1806,12 +1806,12 @@ void r600_init_state_functions(struct r600_context *rctx)
 
 	rctx->context.create_blend_state = r600_create_blend_state;
 	rctx->context.create_depth_stencil_alpha_state = r600_create_dsa_state;
-	rctx->context.create_fs_state = r600_create_shader_state;
+	rctx->context.create_fs_state = r600_create_shader_state_ps;
 	rctx->context.create_rasterizer_state = r600_create_rs_state;
 	rctx->context.create_sampler_state = r600_create_sampler_state;
 	rctx->context.create_sampler_view = r600_create_sampler_view;
 	rctx->context.create_vertex_elements_state = r600_create_vertex_elements;
-	rctx->context.create_vs_state = r600_create_shader_state;
+	rctx->context.create_vs_state = r600_create_shader_state_vs;
 	rctx->context.bind_blend_state = r600_bind_blend_state;
 	rctx->context.bind_depth_stencil_alpha_state = r600_bind_dsa_state;
 	rctx->context.bind_fragment_sampler_states = r600_bind_ps_samplers;
@@ -1847,6 +1847,7 @@ void r600_init_state_functions(struct r600_context *rctx)
 	rctx->context.set_stream_output_targets = r600_set_so_targets;
 }
 
+/* Adjust GPR allocation on R6xx/R7xx */
 void r600_adjust_gprs(struct r600_context *rctx)
 {
 	struct r600_pipe_state rstate;
@@ -1855,22 +1856,22 @@ void r600_adjust_gprs(struct r600_context *rctx)
 	unsigned tmp;
 	int diff;
 
-	if (rctx->chip_class >= EVERGREEN)
-		return;
-
-	if (!rctx->ps_shader || !rctx->vs_shader)
-		return;
+	/* XXX: Following call moved from r600_bind_[ps|vs]_shader,
+	 * it seems eg+ doesn't need it, r6xx/7xx probably need it only for
+	 * adjusting the GPR allocation?
+	 * Do we need this if we aren't really changing config below? */
+	r600_inval_shader_cache(rctx);
 
-	if (rctx->ps_shader->shader.bc.ngpr > rctx->default_ps_gprs)
+	if (rctx->ps_shader->current->shader.bc.ngpr > rctx->default_ps_gprs)
 	{
-		diff = rctx->ps_shader->shader.bc.ngpr - rctx->default_ps_gprs;
+		diff = rctx->ps_shader->current->shader.bc.ngpr - rctx->default_ps_gprs;
 		num_vs_gprs -= diff;
 		num_ps_gprs += diff;
 	}
 
-	if (rctx->vs_shader->shader.bc.ngpr > rctx->default_vs_gprs)
+	if (rctx->vs_shader->current->shader.bc.ngpr > rctx->default_vs_gprs)
 	{
-		diff = rctx->vs_shader->shader.bc.ngpr - rctx->default_vs_gprs;
+		diff = rctx->vs_shader->current->shader.bc.ngpr - rctx->default_vs_gprs;
 		num_ps_gprs -= diff;
 		num_vs_gprs += diff;
 	}
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 00e1bd0..047da9b 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -29,6 +29,7 @@
 
 #include "util/u_blitter.h"
 #include "util/u_upload_mgr.h"
+#include "util/u_keymap.h"
 #include "tgsi/tgsi_parse.h"
 #include <byteswap.h>
 
@@ -429,83 +430,197 @@ void *r600_create_vertex_elements(struct pipe_context *ctx,
 	return v;
 }
 
-void *r600_create_shader_state(struct pipe_context *ctx,
-			       const struct pipe_shader_state *state)
+/* Compute the key for the hw shader variant */
+static INLINE unsigned r600_shader_selector_key(struct pipe_context * ctx,
+		struct r600_pipe_shader_selector * sel)
 {
-	struct r600_pipe_shader *shader = CALLOC_STRUCT(r600_pipe_shader);
-	int r;
+	struct r600_context *rctx = (struct r600_context *)ctx;
+	unsigned key;
 
-	shader->tokens = tgsi_dup_tokens(state->tokens);
-	shader->so = state->stream_output;
+	if (sel->type == PIPE_SHADER_FRAGMENT) {
+		key = rctx->two_side;
+		if (sel->eg_fs_write_all)
+			key |= rctx->nr_cbufs << 1;
+	} else
+		key = 0;
 
-	r =  r600_pipe_shader_create(ctx, shader);
-	if (r) {
-		return NULL;
-	}
-	return shader;
+	return key;
 }
 
-void r600_bind_ps_shader(struct pipe_context *ctx, void *state)
+/* Select the hw shader variant depending on the current state.
+ * (*dirty) is set to 1 if current variant was changed */
+static int r600_shader_select(struct pipe_context *ctx,
+        struct r600_pipe_shader_selector* sel,
+        unsigned *dirty)
 {
+	unsigned key;
 	struct r600_context *rctx = (struct r600_context *)ctx;
+	struct r600_pipe_shader * shader;
+	int r;
 
-	if (!state) {
-		state = rctx->dummy_pixel_shader;
+	key = r600_shader_selector_key(ctx, sel);
+
+	/* Check if we don't need to change anything.
+	 * This path is also used for most shaders that don't need multiple
+	 * variants, it will cost just a computation of the key and this
+	 * test. */
+	if (likely(sel->current && sel->current->key == key)) {
+		return 0;
 	}
 
-	rctx->ps_shader = (struct r600_pipe_shader *)state;
+	// if we have a single variant in the cache, it's also current, so no need
+	// to lookup
+	if (sel->num_shaders > 1) {
+		shader = (struct r600_pipe_shader *)util_keymap_lookup(sel->shaders, &key);
+#if 0
+		printf("r600_shader_select %p lookup result %p, key %u, type %u\n",
+				sel, shader, key, sel->type);
+#endif
+	}
+	else
+		shader = NULL;
+
+	if (unlikely(!shader)) {
+		shader = CALLOC(1, sizeof(struct r600_pipe_shader));
+		shader->selector = sel;
+
+		r = r600_pipe_shader_create(ctx, shader);
+		if (unlikely(r)) {
+			R600_ERR("Failed to build shader variant (type=%u, key=%u) %d\n",
+					sel->type, key, r);
+			sel->current = NULL;
+			return r;
+		}
 
-	r600_inval_shader_cache(rctx);
-	r600_context_pipe_state_set(rctx, &rctx->ps_shader->rstate);
+		/* We don't know the value of eg_fs_write_all property until we built
+		 * at least one variant, so we may need to recompute the key (include
+		 * rctx->nr_cbufs) after building first variant. */
+		if (sel->type == PIPE_SHADER_FRAGMENT &&
+				sel->num_shaders == 0 &&
+				rctx->chip_class >= EVERGREEN &&
+				shader->shader.fs_write_all) {
+			sel->eg_fs_write_all = 1;
+			key = r600_shader_selector_key(ctx, sel);
+		}
 
-	rctx->cb_color_control &= C_028808_MULTIWRITE_ENABLE;
-	rctx->cb_color_control |= S_028808_MULTIWRITE_ENABLE(!!rctx->ps_shader->shader.fs_write_all);
+		shader->key = key;
+		util_keymap_insert(sel->shaders, &key, shader, NULL);
+		sel->num_shaders++;
+	}
 
-	if (rctx->ps_shader && rctx->vs_shader) {
+	if (dirty)
+		*dirty = 1;
+
+	/* Moved from r600_bind_[ps|vs]_shader, different shader variants
+	 * may use different number of GPRs, so we need to update it. */
+	/* FIXME: we never did it after rebuilding the shaders, is it required? */
+	if (rctx->chip_class < EVERGREEN && rctx->ps_shader && rctx->vs_shader) {
 		r600_adjust_gprs(rctx);
 	}
+
+	sel->current = shader;
+	return 0;
+}
+
+static void r600_pipe_shader_keymap_delete_func(
+		const struct keymap *map,
+		const void *key, void *data,
+		void *user)
+{
+	struct pipe_context *ctx = (struct pipe_context*)user;
+	struct r600_pipe_shader *shader = (struct r600_pipe_shader*)data;
+
+	r600_pipe_shader_destroy(ctx, shader);
+	free(shader);
+}
+
+static void *r600_create_shader_state(struct pipe_context *ctx,
+			       const struct pipe_shader_state *state,
+			       unsigned pipe_shader_type)
+{
+	struct r600_pipe_shader_selector *sel = CALLOC_STRUCT(r600_pipe_shader_selector);
+	int r;
+
+	sel->type = pipe_shader_type;
+	sel->tokens = tgsi_dup_tokens(state->tokens);
+	sel->so = state->stream_output;
+	sel->shaders = util_new_keymap(sizeof(unsigned), 16,
+			r600_pipe_shader_keymap_delete_func);
+
+	r = r600_shader_select(ctx, sel, NULL);
+	if (r)
+	    return NULL;
+
+	return sel;
+}
+
+void *r600_create_shader_state_ps(struct pipe_context *ctx,
+		const struct pipe_shader_state *state)
+{
+	return r600_create_shader_state(ctx, state, PIPE_SHADER_FRAGMENT);
+}
+
+void *r600_create_shader_state_vs(struct pipe_context *ctx,
+		const struct pipe_shader_state *state)
+{
+	return r600_create_shader_state(ctx, state, PIPE_SHADER_VERTEX);
+}
+
+void r600_bind_ps_shader(struct pipe_context *ctx, void *state)
+{
+	struct r600_context *rctx = (struct r600_context *)ctx;
+
+	if (!state)
+		state = rctx->dummy_pixel_shader;
+
+	rctx->ps_shader = (struct r600_pipe_shader_selector *)state;
+	r600_context_pipe_state_set(rctx, &rctx->ps_shader->current->rstate);
+
+	rctx->cb_color_control &= C_028808_MULTIWRITE_ENABLE;
+	rctx->cb_color_control |= S_028808_MULTIWRITE_ENABLE(!!rctx->ps_shader->current->shader.fs_write_all);
 }
 
 void r600_bind_vs_shader(struct pipe_context *ctx, void *state)
 {
 	struct r600_context *rctx = (struct r600_context *)ctx;
 
-	rctx->vs_shader = (struct r600_pipe_shader *)state;
+	rctx->vs_shader = (struct r600_pipe_shader_selector *)state;
 	if (state) {
-		r600_inval_shader_cache(rctx);
-		r600_context_pipe_state_set(rctx, &rctx->vs_shader->rstate);
-	}
-	if (rctx->ps_shader && rctx->vs_shader) {
-		r600_adjust_gprs(rctx);
+		r600_context_pipe_state_set(rctx, &rctx->vs_shader->current->rstate);
 	}
 }
 
+static void r600_delete_shader_selector(struct pipe_context *ctx,
+		struct r600_pipe_shader_selector *sel)
+{
+	free(sel->tokens);
+	util_delete_keymap(sel->shaders, ctx);
+	free(sel);
+}
+
+
 void r600_delete_ps_shader(struct pipe_context *ctx, void *state)
 {
 	struct r600_context *rctx = (struct r600_context *)ctx;
-	struct r600_pipe_shader *shader = (struct r600_pipe_shader *)state;
+	struct r600_pipe_shader_selector *sel = (struct r600_pipe_shader_selector *)state;
 
-	if (rctx->ps_shader == shader) {
+	if (rctx->ps_shader == sel) {
 		rctx->ps_shader = NULL;
 	}
 
-	free(shader->tokens);
-	r600_pipe_shader_destroy(ctx, shader);
-	free(shader);
+	r600_delete_shader_selector(ctx, sel);
 }
 
 void r600_delete_vs_shader(struct pipe_context *ctx, void *state)
 {
 	struct r600_context *rctx = (struct r600_context *)ctx;
-	struct r600_pipe_shader *shader = (struct r600_pipe_shader *)state;
+	struct r600_pipe_shader_selector *sel = (struct r600_pipe_shader_selector *)state;
 
-	if (rctx->vs_shader == shader) {
+	if (rctx->vs_shader == sel) {
 		rctx->vs_shader = NULL;
 	}
 
-	free(shader->tokens);
-	r600_pipe_shader_destroy(ctx, shader);
-	free(shader);
+	r600_delete_shader_selector(ctx, sel);
 }
 
 static void r600_update_alpha_ref(struct r600_context *rctx)
@@ -661,24 +776,10 @@ void r600_set_so_targets(struct pipe_context *ctx,
 	rctx->streamout_append_bitmask = append_bitmask;
 }
 
-static int r600_shader_rebuild(struct pipe_context * ctx, struct r600_pipe_shader * shader)
-{
-	struct r600_context *rctx = (struct r600_context *)ctx;
-	int r;
-
-	r600_pipe_shader_destroy(ctx, shader);
-	r = r600_pipe_shader_create(ctx, shader);
-	if (r) {
-		return r;
-	}
-	r600_context_pipe_state_set(rctx, &shader->rstate);
-
-	return 0;
-}
-
 static void r600_update_derived_state(struct r600_context *rctx)
 {
 	struct pipe_context * ctx = (struct pipe_context*)rctx;
+	unsigned ps_dirty = 0;
 
 	if (!rctx->blitter->running) {
 		if (rctx->have_depth_fb || rctx->have_depth_texture)
@@ -689,30 +790,29 @@ static void r600_update_derived_state(struct r600_context *rctx)
 		r600_update_sampler_states(rctx);
 	}
 
-	if ((rctx->ps_shader->shader.two_side != rctx->two_side) ||
-	    ((rctx->chip_class >= EVERGREEN) && rctx->ps_shader->shader.fs_write_all &&
-	     (rctx->ps_shader->shader.nr_cbufs != rctx->nr_cbufs))) {
-		r600_shader_rebuild(&rctx->context, rctx->ps_shader);
-	}
+	r600_shader_select(ctx, rctx->ps_shader, &ps_dirty);
 
 	if (rctx->alpha_ref_dirty) {
 		r600_update_alpha_ref(rctx);
 	}
 
 	if (rctx->ps_shader && ((rctx->sprite_coord_enable &&
-		(rctx->ps_shader->sprite_coord_enable != rctx->sprite_coord_enable)) ||
-		(rctx->rasterizer && rctx->rasterizer->flatshade != rctx->ps_shader->flatshade))) {
+		(rctx->ps_shader->current->sprite_coord_enable != rctx->sprite_coord_enable)) ||
+		(rctx->rasterizer && rctx->rasterizer->flatshade != rctx->ps_shader->current->flatshade))) {
 
 		if (rctx->chip_class >= EVERGREEN)
-			evergreen_pipe_shader_ps(ctx, rctx->ps_shader);
+			evergreen_pipe_shader_ps(ctx, rctx->ps_shader->current);
 		else
-			r600_pipe_shader_ps(ctx, rctx->ps_shader);
+			r600_pipe_shader_ps(ctx, rctx->ps_shader->current);
 
-		r600_context_pipe_state_set(rctx, &rctx->ps_shader->rstate);
+		ps_dirty = 1;
 	}
 
+	if (ps_dirty)
+		r600_context_pipe_state_set(rctx, &rctx->ps_shader->current->rstate);
+
 	if (rctx->dual_src_blend)
-		rctx->cb_shader_mask = rctx->ps_shader->ps_cb_shader_mask | rctx->fb_cb_shader_mask;
+		rctx->cb_shader_mask = rctx->ps_shader->current->ps_cb_shader_mask | rctx->fb_cb_shader_mask;
 	else
 		rctx->cb_shader_mask = rctx->fb_cb_shader_mask;
 }
@@ -827,12 +927,12 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)
 	if (rctx->chip_class <= R700)
 		r600_pipe_state_mod_reg(&rctx->vgt, rctx->cb_color_control);
 	r600_pipe_state_mod_reg(&rctx->vgt,
-				rctx->vs_shader->pa_cl_vs_out_cntl |
-				(rctx->rasterizer->clip_plane_enable & rctx->vs_shader->shader.clip_dist_write));
+				rctx->vs_shader->current->pa_cl_vs_out_cntl |
+				(rctx->rasterizer->clip_plane_enable & rctx->vs_shader->current->shader.clip_dist_write));
 	r600_pipe_state_mod_reg(&rctx->vgt,
 				rctx->pa_cl_clip_cntl |
-				(rctx->vs_shader->shader.clip_dist_write ||
-				 rctx->vs_shader->shader.vs_prohibit_ucps ?
+				(rctx->vs_shader->current->shader.clip_dist_write ||
+				 rctx->vs_shader->current->shader.vs_prohibit_ucps ?
 				 0 : rctx->rasterizer->clip_plane_enable & 0x3F));
 
 	r600_context_pipe_state_set(rctx, &rctx->vgt);
-- 
1.7.10.2



More information about the mesa-dev mailing list