[Mesa-dev] [PATCH 07/15] r600g: add a new simple API for state emission

Marek Olšák maraeo at gmail.com
Mon Jan 30 12:23:10 PST 2012


---
 src/gallium/drivers/r600/r600_hw_context.c   |    6 ++++
 src/gallium/drivers/r600/r600_pipe.c         |    2 +
 src/gallium/drivers/r600/r600_pipe.h         |   42 ++++++++++++++++++++++++++
 src/gallium/drivers/r600/r600_state_common.c |    4 ++
 4 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c
index aa01d0d..3399466 100644
--- a/src/gallium/drivers/r600/r600_hw_context.c
+++ b/src/gallium/drivers/r600/r600_hw_context.c
@@ -931,11 +931,17 @@ out_err:
 void r600_need_cs_space(struct r600_context *ctx, unsigned num_dw,
 			boolean count_draw_in)
 {
+	struct r600_atom *state;
+
 	/* The number of dwords we already used in the CS so far. */
 	num_dw += ctx->cs->cdw;
 
 	if (count_draw_in) {
 		/* The number of dwords all the dirty states would take. */
+		LIST_FOR_EACH_ENTRY(state, &ctx->dirty_states, head) {
+			num_dw += state->num_dw;
+		}
+
 		num_dw += ctx->pm4_dirty_cdwords;
 
 		/* The upper-bound of how much a draw command would take. */
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index bd68eff..b927625 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -282,6 +282,8 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
 		return NULL;
 	}
 
+	LIST_INITHEAD(&rctx->dirty_states);
+
 	r600_get_backend_mask(rctx); /* this emits commands and must be last */
 
 	return &rctx->context;
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 0aaec4b..78b6d83 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -48,6 +48,25 @@
 #define R600_BIG_ENDIAN 0
 #endif
 
+enum r600_atom_flags {
+	/* When set, atoms are added at the beginning of the dirty list
+	 * instead of the end. */
+	EMIT_EARLY = (1 << 0)
+};
+
+/* This encapsulates a state or an operation which can emitted into the GPU
+ * command stream. It's not limited to states only, it can be used for anything
+ * that wants to write commands into the CS (e.g. cache flushes). */
+struct r600_atom {
+	void (*emit)(struct r600_context *ctx, struct r600_atom *state);
+
+	unsigned		num_dw;
+	enum r600_atom_flags	flags;
+	bool			dirty;
+
+	struct list_head	head;
+};
+
 enum r600_pipe_state_id {
 	R600_PIPE_STATE_BLEND = 0,
 	R600_PIPE_STATE_BLEND_COLOR,
@@ -251,6 +270,9 @@ struct r600_context {
 
 	unsigned default_ps_gprs, default_vs_gprs;
 
+	/* States based on r600_state. */
+	struct list_head		dirty_states;
+
 	/* Below are variables from the old r600_context.
 	 */
 	struct radeon_winsys_cs	*cs;
@@ -290,6 +312,26 @@ struct r600_context {
 	unsigned		*vs_so_stride_in_dw;
 };
 
+static INLINE void r600_emit_atom(struct r600_context *rctx, struct r600_atom *atom)
+{
+	atom->emit(rctx, atom);
+	atom->dirty = false;
+	if (atom->head.next && atom->head.prev)
+		LIST_DELINIT(&atom->head);
+}
+
+static INLINE void r600_atom_dirty(struct r600_context *rctx, struct r600_atom *state)
+{
+	if (!state->dirty) {
+		if (state->flags & EMIT_EARLY) {
+			LIST_ADD(&state->head, &rctx->dirty_states);
+		} else {
+			LIST_ADDTAIL(&state->head, &rctx->dirty_states);
+		}
+		state->dirty = true;
+	}
+}
+
 /* evergreen_state.c */
 void evergreen_init_state_functions(struct r600_context *rctx);
 void evergreen_init_config(struct r600_context *rctx);
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index c3a8e3d..0c06ad0 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -671,6 +671,7 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)
 	struct pipe_index_buffer ib = {};
 	unsigned prim, mask, ls_mask = 0;
 	struct r600_block *dirty_block = NULL, *next_block = NULL;
+	struct r600_atom *state = NULL, *next_state = NULL;
 
 	if ((!info.count && (info.indexed || !info.count_from_stream_output)) ||
 	    (info.indexed && !rctx->vbuf_mgr->index_buffer.buffer) ||
@@ -788,6 +789,9 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)
 	/* Emit states. */
 	r600_need_cs_space(rctx, 0, TRUE);
 
+	LIST_FOR_EACH_ENTRY_SAFE(state, next_state, &rctx->dirty_states, head) {
+		r600_emit_atom(rctx, state);
+	}
 	LIST_FOR_EACH_ENTRY_SAFE(dirty_block, next_block, &rctx->dirty,list) {
 		r600_context_block_emit_dirty(rctx, dirty_block);
 	}
-- 
1.7.5.4



More information about the mesa-dev mailing list