[Mesa-dev] [PATCH 3/3] r600g: only emit blocks when they are changed

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Wed Apr 13 11:36:17 PDT 2011


previously, we always emitted blocks that were set before a draw, after this
 patch the block only gets emitted when it is really changed.

Also added a force parameter to r600_context_pipe_state_set, because the
shader constant buffers need 2 registers in different blocks updated, even
if only one is dirty, so those blocks are always marked dirty when they
 are set.
---
 src/gallium/drivers/r600/evergreen_state.c         |   16 ++++----
 src/gallium/drivers/r600/r600.h                    |    2 +-
 src/gallium/drivers/r600/r600_state.c              |   16 ++++----
 src/gallium/drivers/r600/r600_state_common.c       |   22 +++++-----
 src/gallium/winsys/r600/drm/evergreen_hw_context.c |   33 ++++++++++++++-
 src/gallium/winsys/r600/drm/r600_hw_context.c      |   43 +++++++++++++++++--
 6 files changed, 97 insertions(+), 35 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index cff79fa..b8ebae0 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -65,7 +65,7 @@ static void evergreen_set_blend_color(struct pipe_context *ctx,
 
 	free(rctx->states[R600_PIPE_STATE_BLEND_COLOR]);
 	rctx->states[R600_PIPE_STATE_BLEND_COLOR] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 static void *evergreen_create_blend_state(struct pipe_context *ctx,
@@ -539,7 +539,7 @@ static void evergreen_set_clip_state(struct pipe_context *ctx,
 
 	free(rctx->states[R600_PIPE_STATE_CLIP]);
 	rctx->states[R600_PIPE_STATE_CLIP] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 static void evergreen_set_polygon_stipple(struct pipe_context *ctx,
@@ -591,7 +591,7 @@ static void evergreen_set_scissor_state(struct pipe_context *ctx,
 
 	free(rctx->states[R600_PIPE_STATE_SCISSOR]);
 	rctx->states[R600_PIPE_STATE_SCISSOR] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 static void evergreen_set_stencil_ref(struct pipe_context *ctx,
@@ -617,7 +617,7 @@ static void evergreen_set_stencil_ref(struct pipe_context *ctx,
 
 	free(rctx->states[R600_PIPE_STATE_STENCIL_REF]);
 	rctx->states[R600_PIPE_STATE_STENCIL_REF] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 static void evergreen_set_viewport_state(struct pipe_context *ctx,
@@ -643,7 +643,7 @@ static void evergreen_set_viewport_state(struct pipe_context *ctx,
 
 	free(rctx->states[R600_PIPE_STATE_VIEWPORT]);
 	rctx->states[R600_PIPE_STATE_VIEWPORT] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rstate,
@@ -876,7 +876,7 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
 
 	free(rctx->states[R600_PIPE_STATE_FRAMEBUFFER]);
 	rctx->states[R600_PIPE_STATE_FRAMEBUFFER] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 
 	if (state->zsbuf) {
 		evergreen_polygon_offset_update(rctx);
@@ -1276,7 +1276,7 @@ void evergreen_init_config(struct r600_pipe_context *rctx)
 
 	r600_pipe_state_add_reg(rstate, R_028810_PA_CL_CLIP_CNTL, 0x0, 0xFFFFFFFF, NULL);
 
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 void evergreen_polygon_offset_update(struct r600_pipe_context *rctx)
@@ -1324,7 +1324,7 @@ void evergreen_polygon_offset_update(struct r600_pipe_context *rctx)
 		r600_pipe_state_add_reg(&state,
 				R_028B78_PA_SU_POLY_OFFSET_DB_FMT_CNTL,
 				offset_db_fmt_cntl, 0xFFFFFFFF, NULL);
-		r600_context_pipe_state_set(&rctx->ctx, &state);
+		r600_context_pipe_state_set(&rctx->ctx, &state,FALSE);
 	}
 }
 
diff --git a/src/gallium/drivers/r600/r600.h b/src/gallium/drivers/r600/r600.h
index 4256a7e..d34f560 100644
--- a/src/gallium/drivers/r600/r600.h
+++ b/src/gallium/drivers/r600/r600.h
@@ -267,7 +267,7 @@ struct r600_draw {
 
 int r600_context_init(struct r600_context *ctx, struct radeon *radeon);
 void r600_context_fini(struct r600_context *ctx);
-void r600_context_pipe_state_set(struct r600_context *ctx, struct r600_pipe_state *state);
+void r600_context_pipe_state_set(struct r600_context *ctx, struct r600_pipe_state *state,boolean force);
 void r600_context_pipe_state_set_ps_resource(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid);
 void r600_context_pipe_state_set_vs_resource(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid);
 void r600_context_pipe_state_set_fs_resource(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid);
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index 3a863ae..1b1cfc8 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -91,7 +91,7 @@ void r600_polygon_offset_update(struct r600_pipe_context *rctx)
 		r600_pipe_state_add_reg(&state,
 				R_028DF8_PA_SU_POLY_OFFSET_DB_FMT_CNTL,
 				offset_db_fmt_cntl, 0xFFFFFFFF, NULL);
-		r600_context_pipe_state_set(&rctx->ctx, &state);
+		r600_context_pipe_state_set(&rctx->ctx, &state,FALSE);
 	}
 }
 
@@ -111,7 +111,7 @@ static void r600_set_blend_color(struct pipe_context *ctx,
 	r600_pipe_state_add_reg(rstate, R_028420_CB_BLEND_ALPHA, fui(state->color[3]), 0xFFFFFFFF, NULL);
 	free(rctx->states[R600_PIPE_STATE_BLEND_COLOR]);
 	rctx->states[R600_PIPE_STATE_BLEND_COLOR] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 static void *r600_create_blend_state(struct pipe_context *ctx,
@@ -602,7 +602,7 @@ static void r600_set_clip_state(struct pipe_context *ctx,
 
 	free(rctx->states[R600_PIPE_STATE_CLIP]);
 	rctx->states[R600_PIPE_STATE_CLIP] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 static void r600_set_polygon_stipple(struct pipe_context *ctx,
@@ -654,7 +654,7 @@ static void r600_set_scissor_state(struct pipe_context *ctx,
 
 	free(rctx->states[R600_PIPE_STATE_SCISSOR]);
 	rctx->states[R600_PIPE_STATE_SCISSOR] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 static void r600_set_stencil_ref(struct pipe_context *ctx,
@@ -680,7 +680,7 @@ static void r600_set_stencil_ref(struct pipe_context *ctx,
 
 	free(rctx->states[R600_PIPE_STATE_STENCIL_REF]);
 	rctx->states[R600_PIPE_STATE_STENCIL_REF] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 static void r600_set_viewport_state(struct pipe_context *ctx,
@@ -706,7 +706,7 @@ static void r600_set_viewport_state(struct pipe_context *ctx,
 
 	free(rctx->states[R600_PIPE_STATE_VIEWPORT]);
 	rctx->states[R600_PIPE_STATE_VIEWPORT] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rstate,
@@ -930,7 +930,7 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx,
 
 	free(rctx->states[R600_PIPE_STATE_FRAMEBUFFER]);
 	rctx->states[R600_PIPE_STATE_FRAMEBUFFER] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 
 	if (state->zsbuf) {
 		r600_polygon_offset_update(rctx);
@@ -1235,7 +1235,7 @@ void r600_init_config(struct r600_pipe_context *rctx)
 	r600_pipe_state_add_reg(rstate, R_028A94_VGT_MULTI_PRIM_IB_RESET_EN, 0x00000000, 0xFFFFFFFF, NULL);
 	r600_pipe_state_add_reg(rstate, R_028AA0_VGT_INSTANCE_STEP_RATE_0, 0x00000000, 0xFFFFFFFF, NULL);
 	r600_pipe_state_add_reg(rstate, R_028AA4_VGT_INSTANCE_STEP_RATE_1, 0x00000000, 0xFFFFFFFF, NULL);
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shader)
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 43dad0c..bd1a8fa 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -43,7 +43,7 @@ void r600_bind_blend_state(struct pipe_context *ctx, void *state)
 	rstate = &blend->rstate;
 	rctx->states[rstate->id] = rstate;
 	rctx->cb_target_mask = blend->cb_target_mask;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 void r600_bind_rs_state(struct pipe_context *ctx, void *state)
@@ -59,7 +59,7 @@ void r600_bind_rs_state(struct pipe_context *ctx, void *state)
 	rctx->rasterizer = rs;
 
 	rctx->states[rs->rstate.id] = &rs->rstate;
-	r600_context_pipe_state_set(&rctx->ctx, &rs->rstate);
+	r600_context_pipe_state_set(&rctx->ctx, &rs->rstate,FALSE);
 
 	if (rctx->family >= CHIP_CEDAR) {
 		evergreen_polygon_offset_update(rctx);
@@ -99,7 +99,7 @@ void r600_bind_state(struct pipe_context *ctx, void *state)
 	if (state == NULL)
 		return;
 	rctx->states[rstate->id] = rstate;
-	r600_context_pipe_state_set(&rctx->ctx, rstate);
+	r600_context_pipe_state_set(&rctx->ctx, rstate,FALSE);
 }
 
 void r600_delete_state(struct pipe_context *ctx, void *state)
@@ -127,7 +127,7 @@ void r600_bind_vertex_elements(struct pipe_context *ctx, void *state)
 						v->vmgr_elements);
 
 		rctx->states[v->rstate.id] = &v->rstate;
-		r600_context_pipe_state_set(&rctx->ctx, &v->rstate);
+		r600_context_pipe_state_set(&rctx->ctx, &v->rstate,FALSE);
 	}
 }
 
@@ -235,7 +235,7 @@ void r600_bind_ps_shader(struct pipe_context *ctx, void *state)
 	/* TODO delete old shader */
 	rctx->ps_shader = (struct r600_pipe_shader *)state;
 	if (state) {
-		r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_shader->rstate);
+		r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_shader->rstate,FALSE);
 	}
 }
 
@@ -246,7 +246,7 @@ void r600_bind_vs_shader(struct pipe_context *ctx, void *state)
 	/* TODO delete old shader */
 	rctx->vs_shader = (struct r600_pipe_shader *)state;
 	if (state) {
-		r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_shader->rstate);
+		r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_shader->rstate,FALSE);
 	}
 }
 
@@ -309,7 +309,7 @@ void r600_spi_update(struct r600_pipe_context *rctx)
 
 		r600_pipe_state_add_reg(&rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL);
 	}
-	r600_context_pipe_state_set(&rctx->ctx, &rstate);
+	r600_context_pipe_state_set(&rctx->ctx, &rstate,FALSE);
 }
 
 void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
@@ -340,7 +340,8 @@ void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
 		r600_pipe_state_add_reg(&rctx->vs_const_buffer,
 					R_028980_ALU_CONST_CACHE_VS_0,
 					offset >> 8, 0xFFFFFFFF, rbuffer->r.bo);
-		r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_const_buffer);
+		/* the buffer size always needs to be set together with the buffer, so we force it dirty */
+		r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_const_buffer,TRUE);
 
 		rstate = &rctx->vs_const_buffer_resource[index];
 		rstate->id = R600_PIPE_STATE_RESOURCE;
@@ -362,7 +363,8 @@ void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
 		r600_pipe_state_add_reg(&rctx->ps_const_buffer,
 					R_028940_ALU_CONST_CACHE_PS_0,
 					offset >> 8, 0xFFFFFFFF, rbuffer->r.bo);
-		r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_const_buffer);
+		/* the buffer size always needs to be set together with the buffer, so we force it dirty */
+		r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_const_buffer,TRUE);
 
 		rstate = &rctx->ps_const_buffer_resource[index];
 		rstate->id = R600_PIPE_STATE_RESOURCE;
@@ -517,7 +519,7 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 	r600_pipe_state_add_reg(&vgt, R_028238_CB_TARGET_MASK, rctx->cb_target_mask & mask, 0xFFFFFFFF, NULL);
 	r600_pipe_state_add_reg(&vgt, R_03CFF0_SQ_VTX_BASE_VTX_LOC, 0, 0xFFFFFFFF, NULL);
 	r600_pipe_state_add_reg(&vgt, R_03CFF4_SQ_VTX_START_INST_LOC, draw.info.start_instance, 0xFFFFFFFF, NULL);
-	r600_context_pipe_state_set(&rctx->ctx, &vgt);
+	r600_context_pipe_state_set(&rctx->ctx, &vgt,FALSE);
 
 	rdraw.vgt_num_indices = draw.info.count;
 	rdraw.vgt_num_instances = draw.info.instance_count;
diff --git a/src/gallium/winsys/r600/drm/evergreen_hw_context.c b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
index fcf73f8..d71e6c5 100644
--- a/src/gallium/winsys/r600/drm/evergreen_hw_context.c
+++ b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
@@ -637,6 +637,7 @@ static inline void evergreen_context_pipe_state_set_resource(struct r600_context
 {
 	struct r600_range *range;
 	struct r600_block *block;
+	boolean dirty = FALSE;
 
 	range = &ctx->range[CTX_RANGE_ID(ctx, offset)];
 	block = range->blocks[CTX_BLOCK_ID(ctx, offset)];
@@ -647,6 +648,11 @@ static inline void evergreen_context_pipe_state_set_resource(struct r600_context
 		LIST_DELINIT(&block->list);
 		return;
 	}
+
+	for(int i = 0; i < 8; i++)
+		if(block->reg[i] != state->regs[i].value)
+			dirty = TRUE;
+
 	block->reg[0] = state->regs[0].value;
 	block->reg[1] = state->regs[1].value;
 	block->reg[2] = state->regs[2].value;
@@ -660,14 +666,20 @@ static inline void evergreen_context_pipe_state_set_resource(struct r600_context
 		/* VERTEX RESOURCE, we preted there is 2 bo to relocate so
 		 * we have single case btw VERTEX & TEXTURE resource
 		 */
+		if(block->reloc[1].bo != state->regs[0].bo || block->reloc[2].bo != state->regs[0].bo)
+			dirty = TRUE;
+
 		r600_block_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[0].bo);
 		r600_block_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[0].bo);
 	} else {
 		/* TEXTURE RESOURCE */
+		if(block->reloc[1].bo != state->regs[2].bo || block->reloc[2].bo != state->regs[3].bo)
+			dirty = TRUE;
+
 		r600_block_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[2].bo);
 		r600_block_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[3].bo);
 	}
-	if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
+	if ((!(block->status & R600_BLOCK_STATUS_DIRTY) && dirty) || !(block->status & R600_BLOCK_STATUS_ENABLED)) {
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
@@ -700,6 +712,7 @@ static inline void evergreen_context_pipe_state_set_sampler(struct r600_context
 {
 	struct r600_range *range;
 	struct r600_block *block;
+	boolean dirty = FALSE;
 
 	range = &ctx->range[CTX_RANGE_ID(ctx, offset)];
 	block = range->blocks[CTX_BLOCK_ID(ctx, offset)];
@@ -708,10 +721,15 @@ static inline void evergreen_context_pipe_state_set_sampler(struct r600_context
 		LIST_DELINIT(&block->list);
 		return;
 	}
+
+	for(int i = 0; i < 3; i++)
+		if(block->reg[i] != state->regs[i].value)
+			dirty = TRUE;
+
 	block->reg[0] = state->regs[0].value;
 	block->reg[1] = state->regs[1].value;
 	block->reg[2] = state->regs[2].value;
-	if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
+	if ((!(block->status & R600_BLOCK_STATUS_DIRTY) && dirty) || !(block->status & R600_BLOCK_STATUS_ENABLED)) {
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
@@ -724,6 +742,7 @@ static inline void evergreen_context_pipe_state_set_sampler_border(struct r600_c
 	unsigned fake_offset = (offset - R_00A400_TD_PS_SAMPLER0_BORDER_INDEX) * 0x100 + 0x40000 + id * 0x1C;
 	struct r600_range *range;
 	struct r600_block *block;
+	boolean dirty = FALSE;
 
 	range = &ctx->range[CTX_RANGE_ID(ctx, fake_offset)];
 	block = range->blocks[CTX_BLOCK_ID(ctx, fake_offset)];
@@ -735,12 +754,20 @@ static inline void evergreen_context_pipe_state_set_sampler_border(struct r600_c
 	if (state->nregs <= 3) {
 		return;
 	}
+
+	if(block->reg[0] != id)
+		dirty = TRUE;
+
+	for(int i = 1; i < 5; i++)
+		if(block->reg[i] != state->regs[i+2].value)
+			dirty = TRUE;
+
 	block->reg[0] = id;
 	block->reg[1] = state->regs[3].value;
 	block->reg[2] = state->regs[4].value;
 	block->reg[3] = state->regs[5].value;
 	block->reg[4] = state->regs[6].value;
-	if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
+	if ((!(block->status & R600_BLOCK_STATUS_DIRTY) && dirty) || !(block->status & R600_BLOCK_STATUS_ENABLED)) {
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c b/src/gallium/winsys/r600/drm/r600_hw_context.c
index a365f16..aaaffc2 100644
--- a/src/gallium/winsys/r600/drm/r600_hw_context.c
+++ b/src/gallium/winsys/r600/drm/r600_hw_context.c
@@ -832,26 +832,35 @@ void r600_context_bo_reloc(struct r600_context *ctx, u32 *pm4, struct r600_bo *r
 	*pm4 = bo->reloc_id;
 }
 
-void r600_context_pipe_state_set(struct r600_context *ctx, struct r600_pipe_state *state)
+void r600_context_pipe_state_set(struct r600_context *ctx, struct r600_pipe_state *state,boolean force)
 {
 	struct r600_range *range;
 	struct r600_block *block;
 
 	for (int i = 0; i < state->nregs; i++) {
 		unsigned id;
+		boolean dirty=force;
 
 		range = &ctx->range[CTX_RANGE_ID(ctx, state->regs[i].offset)];
 		block = range->blocks[CTX_BLOCK_ID(ctx, state->regs[i].offset)];
 		id = (state->regs[i].offset - block->start_offset) >> 2;
+
+		if((block->reg[id] ^ state->regs[i].value) & state->regs[i].mask)
+			dirty = TRUE;
+
 		block->reg[id] &= ~state->regs[i].mask;
 		block->reg[id] |= state->regs[i].value;
 		if (block->pm4_bo_index[id]) {
 			/* find relocation */
 			id = block->pm4_bo_index[id];
+
+			if(block->reloc[id].bo != state->regs[i].bo)
+				dirty = TRUE;
+
 			r600_block_bo_reference(ctx->radeon, &block->reloc[id].bo, state->regs[i].bo);
 			state->regs[i].bo->fence = ctx->radeon->fence;
 		}
-		if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
+		if ((!(block->status & R600_BLOCK_STATUS_DIRTY) && dirty) || !(block->status & R600_BLOCK_STATUS_ENABLED)) {
 			block->status |= R600_BLOCK_STATUS_ENABLED;
 			block->status |= R600_BLOCK_STATUS_DIRTY;
 			ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
@@ -864,6 +873,7 @@ static inline void r600_context_pipe_state_set_resource(struct r600_context *ctx
 {
 	struct r600_range *range;
 	struct r600_block *block;
+	boolean dirty = FALSE;
 
 	range = &ctx->range[CTX_RANGE_ID(ctx, offset)];
 	block = range->blocks[CTX_BLOCK_ID(ctx, offset)];
@@ -874,6 +884,11 @@ static inline void r600_context_pipe_state_set_resource(struct r600_context *ctx
 		LIST_DELINIT(&block->list);
 		return;
 	}
+
+	for(int i = 0; i < 7; i++)
+		if(block->reg[i] != state->regs[i].value)
+			dirty = TRUE;
+
 	block->reg[0] = state->regs[0].value;
 	block->reg[1] = state->regs[1].value;
 	block->reg[2] = state->regs[2].value;
@@ -886,17 +901,23 @@ static inline void r600_context_pipe_state_set_resource(struct r600_context *ctx
 		/* VERTEX RESOURCE, we preted there is 2 bo to relocate so
 		 * we have single case btw VERTEX & TEXTURE resource
 		 */
+		if(block->reloc[1].bo != state->regs[0].bo || block->reloc[2].bo != state->regs[0].bo)
+			dirty = TRUE;
+
 		r600_block_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[0].bo);
 		r600_block_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[0].bo);
 		state->regs[0].bo->fence = ctx->radeon->fence;
 	} else {
 		/* TEXTURE RESOURCE */
+		if(block->reloc[1].bo != state->regs[2].bo || block->reloc[2].bo != state->regs[3].bo)
+			dirty = TRUE;
+
 		r600_block_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[2].bo);
 		r600_block_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[3].bo);
 		state->regs[2].bo->fence = ctx->radeon->fence;
 		state->regs[3].bo->fence = ctx->radeon->fence;
 	}
-	if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
+	if ((!(block->status & R600_BLOCK_STATUS_DIRTY) && dirty) || !(block->status & R600_BLOCK_STATUS_ENABLED)) {
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
@@ -929,6 +950,7 @@ static inline void r600_context_pipe_state_set_sampler(struct r600_context *ctx,
 {
 	struct r600_range *range;
 	struct r600_block *block;
+	boolean dirty = false;
 
 	range = &ctx->range[CTX_RANGE_ID(ctx, offset)];
 	block = range->blocks[CTX_BLOCK_ID(ctx, offset)];
@@ -937,10 +959,15 @@ static inline void r600_context_pipe_state_set_sampler(struct r600_context *ctx,
 		LIST_DELINIT(&block->list);
 		return;
 	}
+
+	for(int i = 0; i < 3; i++)
+		if(block->reg[i] != state->regs[i].value)
+			dirty = TRUE;
+
 	block->reg[0] = state->regs[0].value;
 	block->reg[1] = state->regs[1].value;
 	block->reg[2] = state->regs[2].value;
-	if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
+	if ((!(block->status & R600_BLOCK_STATUS_DIRTY) && dirty) || !(block->status & R600_BLOCK_STATUS_ENABLED)) {
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
@@ -952,6 +979,7 @@ static inline void r600_context_pipe_state_set_sampler_border(struct r600_contex
 {
 	struct r600_range *range;
 	struct r600_block *block;
+	boolean dirty = FALSE;
 
 	range = &ctx->range[CTX_RANGE_ID(ctx, offset)];
 	block = range->blocks[CTX_BLOCK_ID(ctx, offset)];
@@ -963,11 +991,16 @@ static inline void r600_context_pipe_state_set_sampler_border(struct r600_contex
 	if (state->nregs <= 3) {
 		return;
 	}
+
+	for(int i = 0; i < 4; i++)
+		if(block->reg[i] != state->regs[i+3].value)
+			dirty = TRUE;
+
 	block->reg[0] = state->regs[3].value;
 	block->reg[1] = state->regs[4].value;
 	block->reg[2] = state->regs[5].value;
 	block->reg[3] = state->regs[6].value;
-	if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
+	if ((!(block->status & R600_BLOCK_STATUS_DIRTY) && dirty) || !(block->status & R600_BLOCK_STATUS_ENABLED)) {
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
-- 
1.7.3.4



More information about the mesa-dev mailing list