summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/radeonsi/si_hw_context.c1
-rw-r--r--src/gallium/drivers/radeonsi/si_pipe.h18
-rw-r--r--src/gallium/drivers/radeonsi/si_state_draw.c22
3 files changed, 38 insertions, 3 deletions
diff --git a/src/gallium/drivers/radeonsi/si_hw_context.c b/src/gallium/drivers/radeonsi/si_hw_context.c
index f597218cf67..6c2734eac29 100644
--- a/src/gallium/drivers/radeonsi/si_hw_context.c
+++ b/src/gallium/drivers/radeonsi/si_hw_context.c
@@ -155,4 +155,5 @@ void si_begin_new_cs(struct si_context *ctx)
r600_postflush_resume_features(&ctx->b);
ctx->b.initial_gfx_cs_size = ctx->b.rings.gfx.cs->cdw;
+ si_invalidate_draw_sh_constants(ctx);
}
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 15ca9a559e5..e3cc09a0b85 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -34,6 +34,11 @@
#define SI_BIG_ENDIAN 0
#endif
+/* The base vertex can be any number, but we must pick one which
+ * will mean "unknown" for the purpose of state tracking and the number
+ * shouldn't be a commonly-used one. */
+#define SI_BASE_VERTEX_UNKNOWN INT_MIN
+
#define SI_TRACE_CS 0
#define SI_TRACE_CS_DWORDS 6
@@ -169,6 +174,11 @@ struct si_context {
bool db_depth_clear;
bool db_depth_disable_expclear;
unsigned ps_db_shader_control;
+
+ /* Draw state. */
+ int last_base_vertex;
+ int last_start_instance;
+ int last_sh_base_reg;
};
/* si_blit.c */
@@ -227,4 +237,12 @@ si_resource_create_custom(struct pipe_screen *screen,
PIPE_BIND_CUSTOM, usage, size));
}
+static INLINE void
+si_invalidate_draw_sh_constants(struct si_context *sctx)
+{
+ sctx->last_base_vertex = SI_BASE_VERTEX_UNKNOWN;
+ sctx->last_start_instance = -1; /* reset to an unknown value */
+ sctx->last_sh_base_reg = -1; /* reset to an unknown value */
+}
+
#endif
diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c
index a69d5962503..f9ff0e34c17 100644
--- a/src/gallium/drivers/radeonsi/si_state_draw.c
+++ b/src/gallium/drivers/radeonsi/si_state_draw.c
@@ -242,13 +242,29 @@ static void si_emit_draw_packets(struct si_context *sctx,
}
if (!info->indirect) {
+ int base_vertex;
+
radeon_emit(cs, PKT3(PKT3_NUM_INSTANCES, 0, 0));
radeon_emit(cs, info->instance_count);
- si_write_sh_reg_seq(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, 2);
- radeon_emit(cs, info->indexed ? info->index_bias : info->start);
- radeon_emit(cs, info->start_instance);
+ /* Base vertex and start instance. */
+ base_vertex = info->indexed ? info->index_bias : info->start;
+
+ if (base_vertex != sctx->last_base_vertex ||
+ sctx->last_base_vertex == SI_BASE_VERTEX_UNKNOWN ||
+ info->start_instance != sctx->last_start_instance ||
+ sh_base_reg != sctx->last_sh_base_reg) {
+ si_write_sh_reg_seq(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, 2);
+ radeon_emit(cs, base_vertex);
+ radeon_emit(cs, info->start_instance);
+
+ sctx->last_base_vertex = base_vertex;
+ sctx->last_start_instance = info->start_instance;
+ sctx->last_sh_base_reg = sh_base_reg;
+ }
} else {
+ si_invalidate_draw_sh_constants(sctx);
+
r600_context_bo_reloc(&sctx->b, &sctx->b.rings.gfx,
(struct r600_resource *)info->indirect,
RADEON_USAGE_READ, RADEON_PRIO_MIN);