From: Alyssa Rosenzweig Date: Fri, 3 Mar 2023 04:02:05 +0000 (-0500) Subject: asahi, agx: Implement dummy samplers X-Git-Tag: upstream/23.3.3~11825 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=826649ba1959e56d527feccc31a8a466337a4a03;p=platform%2Fupstream%2Fmesa.git asahi, agx: Implement dummy samplers In NIR, texelFetch (txf) does not use a sampler, but in AGX, it does -- even though the contents of the sampler are semantically irrelevant. Rather than requiring the state tracker to bind a sampler anyway (indicated for texture buffers with PIPE_CAP_TEXTURE_BUFFER_SAMPLER), just add a dummy sampler ourselves if txf is used and there are otherwise no samplers. This is helpful because PIPE_CAP_TEXTURE_BUFFER_SAMPLER isn't honoured by Rusticl or seemingly mesa/st's PBO code, and after implementing this dummy sampler workaround in Panfrost for Rusticl, I realized this CAP is silly and shouldn't exist in the first place. (And I regret pushing for its reinclusion.) Signed-off-by: Alyssa Rosenzweig Part-of: --- diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index 0ea574e..cca0be0 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -1326,6 +1326,12 @@ agx_emit_tex(agx_builder *b, nir_tex_instr *instr) bool txf = (instr->op == nir_texop_txf || instr->op == nir_texop_txf_ms); + /* txf loads a texture without an associated sampler, but in the hardware + * there is an associated load of a sampler. This requires that the driver + * upload a dummy sampler. + */ + b->shader->out->needs_dummy_sampler |= txf; + for (unsigned i = 0; i < instr->num_srcs; ++i) { agx_index index = agx_src_index(&instr->src[i].src); diff --git a/src/asahi/compiler/agx_compile.h b/src/asahi/compiler/agx_compile.h index b3b1fcb..162fa6f 100644 --- a/src/asahi/compiler/agx_compile.h +++ b/src/asahi/compiler/agx_compile.h @@ -124,6 +124,9 @@ struct agx_shader_info { /* Shader is incompatible with triangle merging */ bool disable_tri_merging; + /* Shader needs a dummy sampler (for txf reads) */ + bool needs_dummy_sampler; + /* Number of 16-bit registers used by the main shader and preamble * respectively. */ diff --git a/src/gallium/drivers/asahi/agx_pipe.c b/src/gallium/drivers/asahi/agx_pipe.c index 20d3360..56a7dae 100644 --- a/src/gallium/drivers/asahi/agx_pipe.c +++ b/src/gallium/drivers/asahi/agx_pipe.c @@ -1281,7 +1281,6 @@ agx_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_SURFACE_SAMPLE_COUNT: case PIPE_CAP_SAMPLE_SHADING: case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: - case PIPE_CAP_TEXTURE_BUFFER_SAMPLER: case PIPE_CAP_IMAGE_LOAD_FORMATTED: case PIPE_CAP_IMAGE_STORE_FORMATTED: case PIPE_CAP_COMPUTE: diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index b6a055a..0cbd06a 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -1753,6 +1753,10 @@ agx_build_pipeline(struct agx_batch *batch, struct agx_compiled_shader *cs, unsigned nr_textures = ctx->stage[stage].texture_count; unsigned nr_samplers = ctx->stage[stage].sampler_count; bool custom_borders = ctx->stage[stage].custom_borders; + bool dummy_sampler = cs->info.needs_dummy_sampler && (nr_samplers == 0); + + if (dummy_sampler) + nr_samplers = 1; struct agx_ptr T_tex = agx_pool_alloc_aligned( &batch->pool, AGX_TEXTURE_LENGTH * nr_textures, 64); @@ -1798,24 +1802,31 @@ agx_build_pipeline(struct agx_batch *batch, struct agx_compiled_shader *cs, /* TODO: Dirty track me to save some CPU cycles and maybe improve caching */ uint8_t *out_sampler = T_samp.cpu; - for (unsigned i = 0; i < nr_samplers; ++i) { - struct agx_sampler_state *sampler = ctx->stage[stage].samplers[i]; - struct agx_sampler_packed *out = (struct agx_sampler_packed *)out_sampler; - - if (sampler) { - *out = sampler->desc; - - if (custom_borders) { - memcpy(out_sampler + AGX_SAMPLER_LENGTH, &sampler->border, - AGX_BORDER_LENGTH); + if (dummy_sampler) { + /* Configuration is irrelevant for the dummy sampler */ + agx_pack(out_sampler, SAMPLER, cfg) + ; + } else { + for (unsigned i = 0; i < nr_samplers; ++i) { + struct agx_sampler_state *sampler = ctx->stage[stage].samplers[i]; + struct agx_sampler_packed *out = + (struct agx_sampler_packed *)out_sampler; + + if (sampler) { + *out = sampler->desc; + + if (custom_borders) { + memcpy(out_sampler + AGX_SAMPLER_LENGTH, &sampler->border, + AGX_BORDER_LENGTH); + } else { + assert(!sampler->uses_custom_border && "invalid combination"); + } } else { - assert(!sampler->uses_custom_border && "invalid combination"); + memset(out, 0, sampler_length); } - } else { - memset(out, 0, sampler_length); - } - out_sampler += sampler_length; + out_sampler += sampler_length; + } } struct agx_usc_builder b =