From caad4703aabcab27639022197741f52d941a12a3 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 15 Mar 2024 19:28:50 -0400 Subject: [PATCH] agx: always reserve sampler #0 for txf this is a lot simpler for non-monolithic programs and is unlikely to be a meaningful performance problem. Signed-off-by: Alyssa Rosenzweig Part-of: --- src/asahi/compiler/agx_compile.c | 34 +++---------------- src/asahi/compiler/agx_compile.h | 4 --- src/asahi/lib/agx_nir_lower_texture.c | 16 +++++++++ src/gallium/drivers/asahi/agx_state.c | 48 ++++++++++++--------------- 4 files changed, 43 insertions(+), 59 deletions(-) diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index efddb299b98..077d2a0b9f4 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -969,23 +969,6 @@ agx_translate_bindless_handle(agx_builder *b, nir_src *handle, agx_index *base) return agx_emit_extract(b, agx_src_index(handle), 1); } -/* - * Contrary to NIR, in the hardware txf requires a special sampler. The sampler - * cannot be arbitrary, since the hardware honours the clamps so particular - * configuration is required for correct out-of-bounds behaviour for txf. This - * helper gets the shader's txf sampler, allocating one if needed. - */ -static agx_index -agx_txf_sampler(agx_context *ctx) -{ - if (!ctx->out->uses_txf) { - ctx->out->txf_sampler = BITSET_LAST_BIT(ctx->nir->info.samplers_used); - ctx->out->uses_txf = true; - } - - return agx_immediate(ctx->out->txf_sampler); -} - static unsigned agx_expand_tex_to(agx_builder *b, nir_def *def, agx_index src, bool masked) { @@ -1078,8 +1061,8 @@ agx_emit_image_load(agx_builder *b, agx_index dst, nir_intrinsic_instr *intr) agx_index tmp = agx_vec_temp(b->shader, dst.size, 4); agx_instr *I = agx_image_load_to( - b, tmp, coords, lod, bindless, texture, agx_txf_sampler(b->shader), - agx_null(), agx_tex_dim(dim, is_array), lod_mode, 0, false); + b, tmp, coords, lod, bindless, texture, agx_immediate(0), agx_null(), + agx_tex_dim(dim, is_array), lod_mode, 0, false); I->mask = agx_expand_tex_to(b, &intr->def, tmp, true); return NULL; } @@ -1910,14 +1893,8 @@ agx_emit_tex(agx_builder *b, nir_tex_instr *instr) { agx_index coords = agx_null(), bindless = agx_immediate(0), texture = agx_immediate(instr->texture_index), - sampler = agx_immediate(instr->sampler_index), - lod = agx_immediate(0), compare = agx_null(), - packed_offset = agx_null(); - - bool txf = (instr->op == nir_texop_txf || instr->op == nir_texop_txf_ms); - - if (txf) - sampler = agx_txf_sampler(b->shader); + sampler = agx_immediate(0), lod = agx_immediate(0), + compare = agx_null(), packed_offset = agx_null(); for (unsigned i = 0; i < instr->num_srcs; ++i) { agx_index index = agx_src_index(&instr->src[i].src); @@ -1944,7 +1921,6 @@ agx_emit_tex(agx_builder *b, nir_tex_instr *instr) case nir_tex_src_texture_offset: texture = index; break; - case nir_tex_src_sampler_offset: case nir_tex_src_sampler_handle: sampler = index; break; @@ -2005,7 +1981,7 @@ agx_emit_tex(agx_builder *b, nir_tex_instr *instr) 0, !agx_is_null(packed_offset), !agx_is_null(compare), instr->op == nir_texop_lod, agx_gather_for_nir(instr)); - if (txf) + if (instr->op == nir_texop_txf || instr->op == nir_texop_txf_ms) I->op = AGX_OPCODE_TEXTURE_LOAD; /* Destination masking doesn't seem to work properly for gathers (because diff --git a/src/asahi/compiler/agx_compile.h b/src/asahi/compiler/agx_compile.h index 811c1cb4407..a051dceb6e1 100644 --- a/src/asahi/compiler/agx_compile.h +++ b/src/asahi/compiler/agx_compile.h @@ -109,10 +109,6 @@ struct agx_shader_info { /* Reads base vertex/instance */ bool uses_base_param; - /* Shader uses txf, requiring a workaround sampler in the given location */ - bool uses_txf; - unsigned txf_sampler; - /* Number of 16-bit registers used by the main shader and preamble * respectively. */ diff --git a/src/asahi/lib/agx_nir_lower_texture.c b/src/asahi/lib/agx_nir_lower_texture.c index 99870426612..f5fc2589dda 100644 --- a/src/asahi/lib/agx_nir_lower_texture.c +++ b/src/asahi/lib/agx_nir_lower_texture.c @@ -162,6 +162,8 @@ lower_buffer_texture(nir_builder *b, nir_tex_instr *tex) nir_instr_remove(&tex->instr); nir_builder_instr_insert(b, &tex->instr); nir_tex_instr_add_src(tex, nir_tex_src_backend1, coord2d); + nir_steal_tex_src(tex, nir_tex_src_sampler_handle); + nir_steal_tex_src(tex, nir_tex_src_sampler_offset); nir_block *else_block = nir_cursor_current_block(b->cursor); nir_pop_if(b, nif); @@ -292,6 +294,20 @@ lower_regular_texture(nir_builder *b, nir_instr *instr, UNUSED void *data) nir_tex_instr_add_src(tex, nir_tex_src_backend2, packed); } + /* We reserve bound sampler #0, so we offset bound samplers by 1 and + * otherwise map bound samplers as-is. + */ + nir_def *sampler = nir_steal_tex_src(tex, nir_tex_src_sampler_offset); + if (!sampler) + sampler = nir_imm_intN_t(b, tex->sampler_index, 16); + + if (!is_txf && + nir_tex_instr_src_index(tex, nir_tex_src_sampler_handle) < 0) { + + nir_tex_instr_add_src(tex, nir_tex_src_sampler_handle, + nir_iadd_imm(b, nir_u2u16(b, sampler), 1)); + } + return true; } diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index fd1b444e6ee..be6d70b48b6 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -2641,15 +2641,10 @@ agx_build_meta_shader(struct agx_context *ctx, meta_shader_builder_t builder, } static unsigned -sampler_count(struct agx_context *ctx, struct agx_compiled_shader *cs, - enum pipe_shader_type stage) +sampler_count(struct agx_context *ctx, enum pipe_shader_type stage) { - unsigned sampler_count = ctx->stage[stage].sampler_count; - - if (cs->info.uses_txf) - sampler_count = MAX2(sampler_count, cs->info.txf_sampler + 1); - - return sampler_count; + /* We reserve sampler #0 for txf so add 1 to the API count */ + return ctx->stage[stage].sampler_count + 1; } static inline enum agx_sampler_states @@ -2658,9 +2653,8 @@ translate_sampler_state_count(struct agx_context *ctx, enum pipe_shader_type stage) { /* Clamp to binding table maximum, anything larger will be bindless */ - return agx_translate_sampler_state_count( - MIN2(sampler_count(ctx, cs, stage), 16), - ctx->stage[stage].custom_borders); + return agx_translate_sampler_state_count(MIN2(sampler_count(ctx, stage), 16), + ctx->stage[stage].custom_borders); } /* @@ -2872,7 +2866,7 @@ agx_upload_samplers(struct agx_batch *batch, struct agx_compiled_shader *cs, { struct agx_context *ctx = batch->ctx; - unsigned nr_samplers = sampler_count(ctx, cs, stage); + unsigned nr_samplers = sampler_count(ctx, stage); bool custom_borders = ctx->stage[stage].custom_borders; size_t sampler_length = @@ -2881,23 +2875,25 @@ agx_upload_samplers(struct agx_batch *batch, struct agx_compiled_shader *cs, struct agx_ptr T = agx_pool_alloc_aligned(&batch->pool, sampler_length * nr_samplers, 64); - uint8_t *out_sampler = T.cpu; - for (unsigned i = 0; i < nr_samplers; ++i) { + /* Sampler #0 is reserved for txf */ + agx_pack(T.cpu, SAMPLER, cfg) { + /* Allow mipmapping. This is respected by txf, weirdly. */ + cfg.mip_filter = AGX_MIP_FILTER_NEAREST; + + /* Out-of-bounds reads must return 0 */ + cfg.wrap_s = AGX_WRAP_CLAMP_TO_BORDER; + cfg.wrap_t = AGX_WRAP_CLAMP_TO_BORDER; + cfg.wrap_r = AGX_WRAP_CLAMP_TO_BORDER; + cfg.border_colour = AGX_BORDER_COLOUR_TRANSPARENT_BLACK; + } + + /* Remaining samplers are API samplers */ + uint8_t *out_sampler = (uint8_t *)T.cpu + sampler_length; + for (unsigned i = 0; i < ctx->stage[stage].sampler_count; ++i) { struct agx_sampler_state *sampler = ctx->stage[stage].samplers[i]; struct agx_sampler_packed *out = (struct agx_sampler_packed *)out_sampler; - if (cs->info.uses_txf && i == cs->info.txf_sampler) { - agx_pack(out, SAMPLER, cfg) { - /* Allow mipmapping. This is respected by txf, weirdly. */ - cfg.mip_filter = AGX_MIP_FILTER_NEAREST; - - /* Out-of-bounds reads must return 0 */ - cfg.wrap_s = AGX_WRAP_CLAMP_TO_BORDER; - cfg.wrap_t = AGX_WRAP_CLAMP_TO_BORDER; - cfg.wrap_r = AGX_WRAP_CLAMP_TO_BORDER; - cfg.border_colour = AGX_BORDER_COLOUR_TRANSPARENT_BLACK; - } - } else if (sampler) { + if (sampler) { *out = sampler->desc; if (custom_borders) {