diff options
Diffstat (limited to 'src/gallium/drivers/r600/r600_hw_context.c')
-rw-r--r-- | src/gallium/drivers/r600/r600_hw_context.c | 377 |
1 files changed, 0 insertions, 377 deletions
diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c index dda38e34583..c03c3b3eec1 100644 --- a/src/gallium/drivers/r600/r600_hw_context.c +++ b/src/gallium/drivers/r600/r600_hw_context.c @@ -114,182 +114,6 @@ err: return; } -static void r600_init_block(struct r600_context *ctx, - struct r600_block *block, - const struct r600_reg *reg, int index, int nreg, - unsigned opcode, unsigned offset_base) -{ - int i = index; - int j, n = nreg; - - /* initialize block */ - block->flags = 0; - block->status |= R600_BLOCK_STATUS_DIRTY; /* dirty all blocks at start */ - block->start_offset = reg[i].offset; - block->pm4[block->pm4_ndwords++] = PKT3(opcode, n, 0); - block->pm4[block->pm4_ndwords++] = (block->start_offset - offset_base) >> 2; - block->reg = &block->pm4[block->pm4_ndwords]; - block->pm4_ndwords += n; - block->nreg = n; - block->nreg_dirty = n; - LIST_INITHEAD(&block->list); - LIST_INITHEAD(&block->enable_list); - - for (j = 0; j < n; j++) { - if (reg[i+j].flags & REG_FLAG_DIRTY_ALWAYS) { - block->flags |= REG_FLAG_DIRTY_ALWAYS; - } - if (reg[i+j].flags & REG_FLAG_ENABLE_ALWAYS) { - if (!(block->status & R600_BLOCK_STATUS_ENABLED)) { - block->status |= R600_BLOCK_STATUS_ENABLED; - LIST_ADDTAIL(&block->enable_list, &ctx->enable_list); - LIST_ADDTAIL(&block->list,&ctx->dirty); - } - } - if (reg[i+j].flags & REG_FLAG_FLUSH_CHANGE) { - block->flags |= REG_FLAG_FLUSH_CHANGE; - } - - if (reg[i+j].flags & REG_FLAG_NEED_BO) { - block->nbo++; - assert(block->nbo < R600_BLOCK_MAX_BO); - block->pm4_bo_index[j] = block->nbo; - block->pm4[block->pm4_ndwords++] = PKT3(PKT3_NOP, 0, 0); - block->pm4[block->pm4_ndwords++] = 0x00000000; - block->reloc[block->nbo].bo_pm4_index = block->pm4_ndwords - 1; - } - } - /* check that we stay in limit */ - assert(block->pm4_ndwords < R600_BLOCK_MAX_REG); -} - -int r600_context_add_block(struct r600_context *ctx, const struct r600_reg *reg, unsigned nreg, - unsigned opcode, unsigned offset_base) -{ - struct r600_block *block; - struct r600_range *range; - int offset; - - for (unsigned i = 0, n = 0; i < nreg; i += n) { - /* ignore new block balise */ - if (reg[i].offset == GROUP_FORCE_NEW_BLOCK) { - n = 1; - continue; - } - - /* register that need relocation are in their own group */ - /* find number of consecutive registers */ - n = 0; - offset = reg[i].offset; - while (reg[i + n].offset == offset) { - n++; - offset += 4; - if ((n + i) >= nreg) - break; - if (n >= (R600_BLOCK_MAX_REG - 2)) - break; - } - - /* allocate new block */ - block = calloc(1, sizeof(struct r600_block)); - if (block == NULL) { - return -ENOMEM; - } - ctx->nblocks++; - for (int j = 0; j < n; j++) { - range = &ctx->range[CTX_RANGE_ID(reg[i + j].offset)]; - /* create block table if it doesn't exist */ - if (!range->blocks) - range->blocks = calloc(1 << HASH_SHIFT, sizeof(void *)); - if (!range->blocks) { - free(block); - return -1; - } - - range->blocks[CTX_BLOCK_ID(reg[i + j].offset)] = block; - } - - r600_init_block(ctx, block, reg, i, n, opcode, offset_base); - - } - return 0; -} - -/* initialize */ -void r600_context_fini(struct r600_context *ctx) -{ - struct r600_block *block; - struct r600_range *range; - - if (ctx->range) { - for (int i = 0; i < NUM_RANGES; i++) { - if (!ctx->range[i].blocks) - continue; - for (int j = 0; j < (1 << HASH_SHIFT); j++) { - block = ctx->range[i].blocks[j]; - if (block) { - for (int k = 0, offset = block->start_offset; k < block->nreg; k++, offset += 4) { - range = &ctx->range[CTX_RANGE_ID(offset)]; - range->blocks[CTX_BLOCK_ID(offset)] = NULL; - } - for (int k = 1; k <= block->nbo; k++) { - pipe_resource_reference((struct pipe_resource**)&block->reloc[k].bo, NULL); - } - free(block); - } - } - free(ctx->range[i].blocks); - } - } - free(ctx->blocks); -} - -int r600_setup_block_table(struct r600_context *ctx) -{ - /* setup block table */ - int c = 0; - ctx->blocks = calloc(ctx->nblocks, sizeof(void*)); - if (!ctx->blocks) - return -ENOMEM; - for (int i = 0; i < NUM_RANGES; i++) { - if (!ctx->range[i].blocks) - continue; - for (int j = 0, add; j < (1 << HASH_SHIFT); j++) { - if (!ctx->range[i].blocks[j]) - continue; - - add = 1; - for (int k = 0; k < c; k++) { - if (ctx->blocks[k] == ctx->range[i].blocks[j]) { - add = 0; - break; - } - } - if (add) { - assert(c < ctx->nblocks); - ctx->blocks[c++] = ctx->range[i].blocks[j]; - j += (ctx->range[i].blocks[j]->nreg) - 1; - } - } - } - return 0; -} - -int r600_context_init(struct r600_context *ctx) -{ - int r; - - r = r600_setup_block_table(ctx); - if (r) - goto out_err; - - ctx->max_db = 4; - return 0; -out_err: - r600_context_fini(ctx); - return r; -} - void r600_need_cs_space(struct r600_context *ctx, unsigned num_dw, boolean count_draw_in) { @@ -321,8 +145,6 @@ void r600_need_cs_space(struct r600_context *ctx, unsigned num_dw, } } - num_dw += ctx->pm4_dirty_cdwords; - /* The upper-bound of how much space a draw command would take. */ num_dw += R600_MAX_FLUSH_CS_DWORDS + R600_MAX_DRAW_CS_DWORDS; #if R600_TRACE_CS @@ -362,191 +184,6 @@ void r600_need_cs_space(struct r600_context *ctx, unsigned num_dw, } } -void r600_context_dirty_block(struct r600_context *ctx, - struct r600_block *block, - int dirty, int index) -{ - if ((index + 1) > block->nreg_dirty) - block->nreg_dirty = index + 1; - - if ((dirty != (block->status & R600_BLOCK_STATUS_DIRTY)) || !(block->status & R600_BLOCK_STATUS_ENABLED)) { - block->status |= R600_BLOCK_STATUS_DIRTY; - ctx->pm4_dirty_cdwords += block->pm4_ndwords; - if (!(block->status & R600_BLOCK_STATUS_ENABLED)) { - block->status |= R600_BLOCK_STATUS_ENABLED; - LIST_ADDTAIL(&block->enable_list, &ctx->enable_list); - } - LIST_ADDTAIL(&block->list,&ctx->dirty); - - if (block->flags & REG_FLAG_FLUSH_CHANGE) { - ctx->flags |= R600_CONTEXT_WAIT_3D_IDLE; - } - } -} - -/** - * If reg needs a reloc, this function will add it to its block's reloc list. - * @return true if reg needs a reloc, false otherwise - */ -static bool r600_reg_set_block_reloc(struct r600_pipe_reg *reg) -{ - unsigned reloc_id; - - if (!reg->block->pm4_bo_index[reg->id]) { - return false; - } - /* find relocation */ - reloc_id = reg->block->pm4_bo_index[reg->id]; - pipe_resource_reference( - (struct pipe_resource**)®->block->reloc[reloc_id].bo, - ®->bo->b.b); - reg->block->reloc[reloc_id].bo_usage = reg->bo_usage; - return true; -} - -/** - * This function will emit all the registers in state directly to the command - * stream allowing you to bypass the r600_context dirty list. - * - * This is used for dispatching compute shaders to avoid mixing compute and - * 3D states in the context's dirty list. - * - * @param pkt_flags Should be either 0 or RADEON_CP_PACKET3_COMPUTE_MODE. This - * value will be passed on to r600_context_block_emit_dirty an or'd against - * the PKT3 headers. - */ -void r600_context_pipe_state_emit(struct r600_context *ctx, - struct r600_pipe_state *state, - unsigned pkt_flags) -{ - unsigned i; - - /* Mark all blocks as dirty: - * Since two registers can be in the same block, we need to make sure - * we mark all the blocks dirty before we emit any of them. If we were - * to mark blocks dirty and emit them in the same loop, like this: - * - * foreach (reg in state->regs) { - * mark_dirty(reg->block) - * emit_block(reg->block) - * } - * - * Then if we have two registers in this state that are in the same - * block, we would end up emitting that block twice. - */ - for (i = 0; i < state->nregs; i++) { - struct r600_pipe_reg *reg = &state->regs[i]; - /* Mark all the registers in the block as dirty */ - reg->block->nreg_dirty = reg->block->nreg; - reg->block->status |= R600_BLOCK_STATUS_DIRTY; - /* Update the reloc for this register if necessary. */ - r600_reg_set_block_reloc(reg); - } - - /* Emit the registers writes */ - for (i = 0; i < state->nregs; i++) { - struct r600_pipe_reg *reg = &state->regs[i]; - if (reg->block->status & R600_BLOCK_STATUS_DIRTY) { - r600_context_block_emit_dirty(ctx, reg->block, pkt_flags); - } - } -} - -void r600_context_pipe_state_set(struct r600_context *ctx, struct r600_pipe_state *state) -{ - struct r600_block *block; - int dirty; - for (int i = 0; i < state->nregs; i++) { - unsigned id; - struct r600_pipe_reg *reg = &state->regs[i]; - - block = reg->block; - id = reg->id; - - dirty = block->status & R600_BLOCK_STATUS_DIRTY; - - if (reg->value != block->reg[id]) { - block->reg[id] = reg->value; - dirty |= R600_BLOCK_STATUS_DIRTY; - } - if (block->flags & REG_FLAG_DIRTY_ALWAYS) - dirty |= R600_BLOCK_STATUS_DIRTY; - if (r600_reg_set_block_reloc(reg)) { - /* always force dirty for relocs for now */ - dirty |= R600_BLOCK_STATUS_DIRTY; - } - - if (dirty) - r600_context_dirty_block(ctx, block, dirty, id); - } -} - -/** - * @param pkt_flags should be set to RADEON_CP_PACKET3_COMPUTE_MODE if this - * block will be used for compute shaders. - */ -void r600_context_block_emit_dirty(struct r600_context *ctx, struct r600_block *block, - unsigned pkt_flags) -{ - struct radeon_winsys_cs *cs = ctx->rings.gfx.cs; - int optional = block->nbo == 0 && !(block->flags & REG_FLAG_DIRTY_ALWAYS); - int cp_dwords = block->pm4_ndwords, start_dword = 0; - int new_dwords = 0; - int nbo = block->nbo; - - if (block->nreg_dirty == 0 && optional) { - goto out; - } - - if (nbo) { - for (int j = 0; j < block->nreg; j++) { - if (block->pm4_bo_index[j]) { - /* find relocation */ - struct r600_block_reloc *reloc = &block->reloc[block->pm4_bo_index[j]]; - if (reloc->bo) { - block->pm4[reloc->bo_pm4_index] = - r600_context_bo_reloc(ctx, &ctx->rings.gfx, reloc->bo, reloc->bo_usage); - } else { - block->pm4[reloc->bo_pm4_index] = 0; - } - nbo--; - if (nbo == 0) - break; - - } - } - } - - optional &= (block->nreg_dirty != block->nreg); - if (optional) { - new_dwords = block->nreg_dirty; - start_dword = cs->cdw; - cp_dwords = new_dwords + 2; - } - memcpy(&cs->buf[cs->cdw], block->pm4, cp_dwords * 4); - - /* We are applying the pkt_flags after copying the register block to - * the the command stream, because it is possible this block will be - * emitted with a different pkt_flags, and we don't want to store the - * pkt_flags in the block. - */ - cs->buf[cs->cdw] |= pkt_flags; - cs->cdw += cp_dwords; - - if (optional) { - uint32_t newword; - - newword = cs->buf[start_dword]; - newword &= PKT_COUNT_C; - newword |= PKT_COUNT_S(new_dwords); - cs->buf[start_dword] = newword; - } -out: - block->status ^= R600_BLOCK_STATUS_DIRTY; - block->nreg_dirty = 0; - LIST_DELINIT(&block->list); -} - void r600_flush_emit(struct r600_context *rctx) { struct radeon_winsys_cs *cs = rctx->rings.gfx.cs; @@ -737,10 +374,8 @@ void r600_context_flush(struct r600_context *ctx, unsigned flags) void r600_begin_new_cs(struct r600_context *ctx) { - struct r600_block *enable_block = NULL; unsigned shader; - ctx->pm4_dirty_cdwords = 0; ctx->flags = 0; ctx->gtt = 0; ctx->vram = 0; @@ -806,18 +441,6 @@ void r600_begin_new_cs(struct r600_context *ctx) r600_resume_nontimer_queries(ctx); } - /* set all valid group as dirty so they get reemited on - * next draw command - */ - LIST_FOR_EACH_ENTRY(enable_block, &ctx->enable_list, enable_list) { - if(!(enable_block->status & R600_BLOCK_STATUS_DIRTY)) { - LIST_ADDTAIL(&enable_block->list,&ctx->dirty); - enable_block->status |= R600_BLOCK_STATUS_DIRTY; - } - ctx->pm4_dirty_cdwords += enable_block->pm4_ndwords; - enable_block->nreg_dirty = enable_block->nreg; - } - /* Re-emit the draw state. */ ctx->last_primitive_type = -1; ctx->last_start_instance = -1; |