X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Ffreedreno%2Fir3%2Fir3_gallium.c;h=fb83d0e7e6357e3137c5b616b3039c3403dd3070;hb=f0b91730a14bab95e5a59f62cb0159d549a5750e;hp=e605e531ecbad98d9b76f64b38034c9ebddac455;hpb=b15c46e6bf4cd375ae0b580bd1a0ec139e8dd3ef;p=mesa.git diff --git a/src/gallium/drivers/freedreno/ir3/ir3_gallium.c b/src/gallium/drivers/freedreno/ir3/ir3_gallium.c index e605e531ecb..fb83d0e7e63 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_gallium.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_gallium.c @@ -44,35 +44,25 @@ #include "ir3/ir3_nir.h" static void -dump_shader_info(struct ir3_shader_variant *v, struct pipe_debug_callback *debug) +dump_shader_info(struct ir3_shader_variant *v, bool binning_pass, + struct pipe_debug_callback *debug) { if (!unlikely(fd_mesa_debug & FD_DBG_SHADERDB)) return; - pipe_debug_message(debug, SHADER_INFO, "\n" - "SHADER-DB: %s prog %d/%d: %u instructions, %u dwords\n" - "SHADER-DB: %s prog %d/%d: %u half, %u full\n" - "SHADER-DB: %s prog %d/%d: %u const, %u constlen\n" - "SHADER-DB: %s prog %d/%d: %u (ss), %u (sy)\n" - "SHADER-DB: %s prog %d/%d: max_sun=%u\n", + pipe_debug_message(debug, SHADER_INFO, + "%s%s shader: %u inst, %u dwords, " + "%u half, %u full, %u constlen, " + "%u (ss), %u (sy), %d max_sun, %d loops\n", + binning_pass ? "B" : "", ir3_shader_stage(v->shader), - v->shader->id, v->id, v->info.instrs_count, v->info.sizedwords, - ir3_shader_stage(v->shader), - v->shader->id, v->id, v->info.max_half_reg + 1, v->info.max_reg + 1, - ir3_shader_stage(v->shader), - v->shader->id, v->id, - v->info.max_const + 1, v->constlen, - ir3_shader_stage(v->shader), - v->shader->id, v->id, v->info.ss, v->info.sy, - ir3_shader_stage(v->shader), - v->shader->id, v->id, - v->max_sun); + v->max_sun, v->loops); } struct ir3_shader_variant * @@ -91,7 +81,7 @@ ir3_shader_variant(struct ir3_shader *shader, struct ir3_shader_key key, v = ir3_shader_get_variant(shader, &key, binning_pass, &created); if (created) { - dump_shader_info(v, debug); + dump_shader_info(v, binning_pass, debug); } return v; @@ -133,7 +123,7 @@ ir3_shader_create(struct ir3_compiler *compiler, if (ir3_shader_debug & IR3_DBG_DISASM) { tgsi_dump(cso->tokens, 0); } - nir = ir3_tgsi_to_nir(compiler, cso->tokens, screen); + nir = tgsi_to_nir(cso->tokens, screen); } struct ir3_shader *shader = ir3_shader_from_nir(compiler, nir); @@ -145,9 +135,11 @@ ir3_shader_create(struct ir3_compiler *compiler, * (as otherwise nothing will trigger the shader to be * actually compiled) */ - static struct ir3_shader_key key; - memset(&key, 0, sizeof(key)); + static struct ir3_shader_key key; /* static is implicitly zeroed */ ir3_shader_variant(shader, key, false, debug); + + if (nir->info.stage != MESA_SHADER_FRAGMENT) + ir3_shader_variant(shader, key, true, debug); } return shader; } @@ -170,7 +162,7 @@ ir3_shader_create_compute(struct ir3_compiler *compiler, if (ir3_shader_debug & IR3_DBG_DISASM) { tgsi_dump(cso->prog, 0); } - nir = ir3_tgsi_to_nir(compiler, cso->prog, screen); + nir = tgsi_to_nir(cso->prog, screen); } struct ir3_shader *shader = ir3_shader_from_nir(compiler, nir); @@ -178,20 +170,6 @@ ir3_shader_create_compute(struct ir3_compiler *compiler, return shader; } -struct nir_shader * -ir3_tgsi_to_nir(struct ir3_compiler *compiler, - const struct tgsi_token *tokens, - struct pipe_screen *screen) -{ - if (!screen) { - const nir_shader_compiler_options *options = - ir3_get_compiler_options(compiler); - return tgsi_to_nir_noscreen(tokens, options); - } - - return tgsi_to_nir(tokens, screen); -} - /* This has to reach into the fd_context a bit more than the rest of * ir3, but it needs to be aligned with the compiler, so both agree * on which const regs hold what. And the logic is identical between @@ -222,45 +200,25 @@ ring_wfi(struct fd_batch *batch, struct fd_ringbuffer *ring) } static void -emit_user_consts(struct fd_context *ctx, const struct ir3_shader_variant *v, - struct fd_ringbuffer *ring, struct fd_constbuf_stateobj *constbuf) +emit_const(struct fd_screen *screen, struct fd_ringbuffer *ring, + const struct ir3_shader_variant *v, uint32_t dst_offset, + uint32_t offset, uint32_t size, + const void *user_buffer, struct pipe_resource *buffer) { - const unsigned index = 0; /* user consts are index 0 */ - - if (constbuf->enabled_mask & (1 << index)) { - struct pipe_constant_buffer *cb = &constbuf->cb[index]; - /* size in dwords, aligned to vec4. (This works at least - * with mesa/st, which seems to align constant buffer to - * 16 bytes) - */ - unsigned size = align(cb->buffer_size, 16) / 4; + assert(dst_offset + size <= v->constlen * 4); - /* in particular, with binning shader we may end up with - * unused consts, ie. we could end up w/ constlen that is - * smaller than first_driver_param. In that case truncate - * the user consts early to avoid HLSQ lockup caused by - * writing too many consts - */ - const struct ir3_const_state *const_state = &v->shader->const_state; - uint32_t max_const = MIN2(const_state->num_uniforms, v->constlen); - - /* and even if the start of the const buffer is before - * first_immediate, the end may not be: - */ - size = MIN2(size, 4 * max_const); - - if (size > 0) { - ring_wfi(ctx->batch, ring); - ctx->emit_const(ring, v->type, 0, - cb->buffer_offset, size, - cb->user_buffer, cb->buffer); - } - } + screen->emit_const(ring, v->type, dst_offset, + offset, size, user_buffer, buffer); +} +void +ir3_emit_user_consts(struct fd_screen *screen, const struct ir3_shader_variant *v, + struct fd_ringbuffer *ring, struct fd_constbuf_stateobj *constbuf) +{ struct ir3_ubo_analysis_state *state; state = &v->shader->ubo_state; - for (uint32_t i = 1; i < ARRAY_SIZE(state->range); i++) { + for (uint32_t i = 0; i < ARRAY_SIZE(state->range); i++) { struct pipe_constant_buffer *cb = &constbuf->cb[i]; if (state->range[i].start < state->range[i].end && @@ -268,17 +226,28 @@ emit_user_consts(struct fd_context *ctx, const struct ir3_shader_variant *v, uint32_t size = state->range[i].end - state->range[i].start; uint32_t offset = cb->buffer_offset + state->range[i].start; + + /* and even if the start of the const buffer is before + * first_immediate, the end may not be: + */ + size = MIN2(size, (16 * v->constlen) - state->range[i].offset); + + if (size == 0) + continue; + + /* things should be aligned to vec4: */ debug_assert((state->range[i].offset % 16) == 0); debug_assert((size % 16) == 0); debug_assert((offset % 16) == 0); - ctx->emit_const(ring, v->type, state->range[i].offset / 4, + + emit_const(screen, ring, v, state->range[i].offset / 4, offset, size / 4, cb->user_buffer, cb->buffer); } } } -static void -emit_ubos(struct fd_context *ctx, const struct ir3_shader_variant *v, +void +ir3_emit_ubos(struct fd_screen *screen, const struct ir3_shader_variant *v, struct fd_ringbuffer *ring, struct fd_constbuf_stateobj *constbuf) { const struct ir3_const_state *const_state = &v->shader->const_state; @@ -302,13 +271,14 @@ emit_ubos(struct fd_context *ctx, const struct ir3_shader_variant *v, } } - ring_wfi(ctx->batch, ring); - ctx->emit_const_bo(ring, v->type, false, offset * 4, params, prscs, offsets); + assert(offset * 4 + params < v->constlen * 4); + + screen->emit_const_bo(ring, v->type, false, offset * 4, params, prscs, offsets); } } -static void -emit_ssbo_sizes(struct fd_context *ctx, const struct ir3_shader_variant *v, +void +ir3_emit_ssbo_sizes(struct fd_screen *screen, const struct ir3_shader_variant *v, struct fd_ringbuffer *ring, struct fd_shaderbuf_stateobj *sb) { const struct ir3_const_state *const_state = &v->shader->const_state; @@ -323,14 +293,13 @@ emit_ssbo_sizes(struct fd_context *ctx, const struct ir3_shader_variant *v, sizes[off] = sb->sb[index].buffer_size; } - ring_wfi(ctx->batch, ring); - ctx->emit_const(ring, v->type, offset * 4, + emit_const(screen, ring, v, offset * 4, 0, ARRAY_SIZE(sizes), sizes, NULL); } } -static void -emit_image_dims(struct fd_context *ctx, const struct ir3_shader_variant *v, +void +ir3_emit_image_dims(struct fd_screen *screen, const struct ir3_shader_variant *v, struct fd_ringbuffer *ring, struct fd_shaderimg_stateobj *si) { const struct ir3_const_state *const_state = &v->shader->const_state; @@ -375,15 +344,14 @@ emit_image_dims(struct fd_context *ctx, const struct ir3_shader_variant *v, dims[off + 1] = ffs(dims[off + 0]) - 1; } } + uint32_t size = MIN2(ARRAY_SIZE(dims), v->constlen * 4 - offset * 4); - ring_wfi(ctx->batch, ring); - ctx->emit_const(ring, v->type, offset * 4, - 0, ARRAY_SIZE(dims), dims, NULL); + emit_const(screen, ring, v, offset * 4, 0, size, dims, NULL); } } -static void -emit_immediates(struct fd_context *ctx, const struct ir3_shader_variant *v, +void +ir3_emit_immediates(struct fd_screen *screen, const struct ir3_shader_variant *v, struct fd_ringbuffer *ring) { const struct ir3_const_state *const_state = &v->shader->const_state; @@ -400,8 +368,7 @@ emit_immediates(struct fd_context *ctx, const struct ir3_shader_variant *v, size *= 4; if (size > 0) { - ring_wfi(ctx->batch, ring); - ctx->emit_const(ring, v->type, base, + emit_const(screen, ring, v, base, 0, size, const_state->immediates[0].val, NULL); } } @@ -434,8 +401,9 @@ emit_tfbos(struct fd_context *ctx, const struct ir3_shader_variant *v, } } - ring_wfi(ctx->batch, ring); - ctx->emit_const_bo(ring, v->type, true, offset * 4, params, prscs, offsets); + assert(offset * 4 + params < v->constlen * 4); + + ctx->screen->emit_const_bo(ring, v->type, true, offset * 4, params, prscs, offsets); } } @@ -512,107 +480,117 @@ emit_common_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *rin constbuf = &ctx->constbuf[t]; shader_dirty = !!(dirty & FD_DIRTY_SHADER_PROG); - emit_user_consts(ctx, v, ring, constbuf); - emit_ubos(ctx, v, ring, constbuf); + ring_wfi(ctx->batch, ring); + + ir3_emit_user_consts(ctx->screen, v, ring, constbuf); + ir3_emit_ubos(ctx->screen, v, ring, constbuf); if (shader_dirty) - emit_immediates(ctx, v, ring); + ir3_emit_immediates(ctx->screen, v, ring); } if (dirty & (FD_DIRTY_SHADER_PROG | FD_DIRTY_SHADER_SSBO)) { struct fd_shaderbuf_stateobj *sb = &ctx->shaderbuf[t]; - emit_ssbo_sizes(ctx, v, ring, sb); + ring_wfi(ctx->batch, ring); + ir3_emit_ssbo_sizes(ctx->screen, v, ring, sb); } if (dirty & (FD_DIRTY_SHADER_PROG | FD_DIRTY_SHADER_IMAGE)) { struct fd_shaderimg_stateobj *si = &ctx->shaderimg[t]; - emit_image_dims(ctx, v, ring, si); + ring_wfi(ctx->batch, ring); + ir3_emit_image_dims(ctx->screen, v, ring, si); } } void -ir3_emit_vs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *ring, - struct fd_context *ctx, const struct pipe_draw_info *info) +ir3_emit_vs_driver_params(const struct ir3_shader_variant *v, + struct fd_ringbuffer *ring, struct fd_context *ctx, + const struct pipe_draw_info *info) { - debug_assert(v->type == MESA_SHADER_VERTEX); - - emit_common_consts(v, ring, ctx, PIPE_SHADER_VERTEX); + debug_assert(ir3_needs_vs_driver_params(v)); - /* emit driver params every time: */ - /* TODO skip emit if shader doesn't use driver params to avoid WFI.. */ - if (info) { - const struct ir3_const_state *const_state = &v->shader->const_state; - uint32_t offset = const_state->offsets.driver_param; - if (v->constlen > offset) { - uint32_t vertex_params[IR3_DP_VS_COUNT] = { - [IR3_DP_VTXID_BASE] = info->index_size ? - info->index_bias : info->start, - [IR3_DP_VTXCNT_MAX] = max_tf_vtx(ctx, v), - }; - /* if no user-clip-planes, we don't need to emit the - * entire thing: - */ - uint32_t vertex_params_size = 4; - - if (v->key.ucp_enables) { - struct pipe_clip_state *ucp = &ctx->ucp; - unsigned pos = IR3_DP_UCP0_X; - for (unsigned i = 0; pos <= IR3_DP_UCP7_W; i++) { - for (unsigned j = 0; j < 4; j++) { - vertex_params[pos] = fui(ucp->ucp[i][j]); - pos++; - } - } - vertex_params_size = ARRAY_SIZE(vertex_params); + const struct ir3_const_state *const_state = &v->shader->const_state; + uint32_t offset = const_state->offsets.driver_param; + uint32_t vertex_params[IR3_DP_VS_COUNT] = { + [IR3_DP_VTXID_BASE] = info->index_size ? + info->index_bias : info->start, + [IR3_DP_VTXCNT_MAX] = max_tf_vtx(ctx, v), + }; + /* if no user-clip-planes, we don't need to emit the + * entire thing: + */ + uint32_t vertex_params_size = 4; + + if (v->key.ucp_enables) { + struct pipe_clip_state *ucp = &ctx->ucp; + unsigned pos = IR3_DP_UCP0_X; + for (unsigned i = 0; pos <= IR3_DP_UCP7_W; i++) { + for (unsigned j = 0; j < 4; j++) { + vertex_params[pos] = fui(ucp->ucp[i][j]); + pos++; } + } + vertex_params_size = ARRAY_SIZE(vertex_params); + } - ring_wfi(ctx->batch, ring); - - bool needs_vtxid_base = - ir3_find_sysval_regid(v, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) != regid(63, 0); + bool needs_vtxid_base = + ir3_find_sysval_regid(v, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) != regid(63, 0); - /* for indirect draw, we need to copy VTXID_BASE from - * indirect-draw parameters buffer.. which is annoying - * and means we can't easily emit these consts in cmd - * stream so need to copy them to bo. - */ - if (info->indirect && needs_vtxid_base) { - struct pipe_draw_indirect_info *indirect = info->indirect; - struct pipe_resource *vertex_params_rsc = - pipe_buffer_create(&ctx->screen->base, + /* for indirect draw, we need to copy VTXID_BASE from + * indirect-draw parameters buffer.. which is annoying + * and means we can't easily emit these consts in cmd + * stream so need to copy them to bo. + */ + if (info->indirect && needs_vtxid_base) { + struct pipe_draw_indirect_info *indirect = info->indirect; + struct pipe_resource *vertex_params_rsc = + pipe_buffer_create(&ctx->screen->base, PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STREAM, vertex_params_size * 4); - unsigned src_off = info->indirect->offset;; - void *ptr; + unsigned src_off = info->indirect->offset;; + void *ptr; - ptr = fd_bo_map(fd_resource(vertex_params_rsc)->bo); - memcpy(ptr, vertex_params, vertex_params_size * 4); + ptr = fd_bo_map(fd_resource(vertex_params_rsc)->bo); + memcpy(ptr, vertex_params, vertex_params_size * 4); - if (info->index_size) { - /* indexed draw, index_bias is 4th field: */ - src_off += 3 * 4; - } else { - /* non-indexed draw, start is 3rd field: */ - src_off += 2 * 4; - } + if (info->index_size) { + /* indexed draw, index_bias is 4th field: */ + src_off += 3 * 4; + } else { + /* non-indexed draw, start is 3rd field: */ + src_off += 2 * 4; + } - /* copy index_bias or start from draw params: */ - ctx->mem_to_mem(ring, vertex_params_rsc, 0, - indirect->buffer, src_off, 1); + /* copy index_bias or start from draw params: */ + ctx->screen->mem_to_mem(ring, vertex_params_rsc, 0, + indirect->buffer, src_off, 1); - ctx->emit_const(ring, MESA_SHADER_VERTEX, offset * 4, 0, - vertex_params_size, NULL, vertex_params_rsc); + emit_const(ctx->screen, ring, v, offset * 4, 0, + vertex_params_size, NULL, vertex_params_rsc); - pipe_resource_reference(&vertex_params_rsc, NULL); - } else { - ctx->emit_const(ring, MESA_SHADER_VERTEX, offset * 4, 0, - vertex_params_size, vertex_params, NULL); - } + pipe_resource_reference(&vertex_params_rsc, NULL); + } else { + emit_const(ctx->screen, ring, v, offset * 4, 0, + vertex_params_size, vertex_params, NULL); + } - /* if needed, emit stream-out buffer addresses: */ - if (vertex_params[IR3_DP_VTXCNT_MAX] > 0) { - emit_tfbos(ctx, v, ring); - } - } + /* if needed, emit stream-out buffer addresses: */ + if (vertex_params[IR3_DP_VTXCNT_MAX] > 0) { + emit_tfbos(ctx, v, ring); + } +} + +void +ir3_emit_vs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *ring, + struct fd_context *ctx, const struct pipe_draw_info *info) +{ + debug_assert(v->type == MESA_SHADER_VERTEX); + + emit_common_consts(v, ring, ctx, PIPE_SHADER_VERTEX); + + /* emit driver params every time: */ + if (info && ir3_needs_vs_driver_params(v)) { + ring_wfi(ctx->batch, ring); + ir3_emit_vs_driver_params(v, ring, ctx, info); } } @@ -658,14 +636,14 @@ ir3_emit_cs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *rin 0x1000); indirect_offset = 0; - ctx->mem_to_mem(ring, indirect, 0, info->indirect, + ctx->screen->mem_to_mem(ring, indirect, 0, info->indirect, info->indirect_offset, 3); } else { pipe_resource_reference(&indirect, info->indirect); indirect_offset = info->indirect_offset; } - ctx->emit_const(ring, MESA_SHADER_COMPUTE, offset * 4, + emit_const(ctx->screen, ring, v, offset * 4, indirect_offset, 4, NULL, indirect); pipe_resource_reference(&indirect, NULL); @@ -678,9 +656,11 @@ ir3_emit_cs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *rin [IR3_DP_LOCAL_GROUP_SIZE_Y] = info->block[1], [IR3_DP_LOCAL_GROUP_SIZE_Z] = info->block[2], }; + uint32_t size = MIN2(ARRAY_SIZE(compute_params), + v->constlen * 4 - offset * 4); - ctx->emit_const(ring, MESA_SHADER_COMPUTE, offset * 4, 0, - ARRAY_SIZE(compute_params), compute_params, NULL); + emit_const(ctx->screen, ring, v, offset * 4, 0, size, + compute_params, NULL); } } }