mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 02:38:04 +02:00
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 <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28483>
This commit is contained in:
parent
be81812a4b
commit
caad4703aa
4 changed files with 43 additions and 59 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue