From: Marek Olšák Date: Mon, 30 Jan 2012 00:23:14 +0000 (+0100) Subject: r600g: add a new simple API for state emission X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2fe521fa419ee153afb6295289dc5e95d3229858;p=mesa.git r600g: add a new simple API for state emission --- diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c index aa01d0d3c5f..3399466f9ad 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 bd68eff8f73..b92762526cd 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 0aaec4be9b0..78b6d83fe30 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 c3a8e3da098..0c06ad05319 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); }