mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-28 23:20:08 +01:00
asahi: make point size replacement dynamic
I'm not measuring a significant perf difference in -bshading:shading=phong:model=bunny -bideas -brefract so this seems Good Enough For Me. 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
7595dc9036
commit
5c7ce24896
4 changed files with 49 additions and 66 deletions
|
|
@ -1936,7 +1936,8 @@ system_value("api_sample_mask_agx", 1, bit_sizes=[16])
|
|||
# Loads the sample position array as fixed point packed into a 32-bit word
|
||||
system_value("sample_positions_agx", 1, bit_sizes=[32])
|
||||
|
||||
# Loads the fixed-function glPointSize() value
|
||||
# Loads the fixed-function glPointSize() value, or zero if the
|
||||
# shader-supplied value should be used.
|
||||
system_value("fixed_point_size_agx", 1, bit_sizes=[32])
|
||||
|
||||
# Bit mask of TEX locations that are replaced with point sprites
|
||||
|
|
|
|||
|
|
@ -5,60 +5,62 @@
|
|||
#include "agx_state.h"
|
||||
#include "nir.h"
|
||||
#include "nir_builder.h"
|
||||
#include "nir_builder_opcodes.h"
|
||||
|
||||
/*
|
||||
* gl_PointSize lowering. This runs late on a vertex shader (epilogue). By this
|
||||
* time, I/O has been lowered, and transform feedback has been written. Point
|
||||
* size will thus only get consumed by the rasterizer, so we can clamp/replace.
|
||||
* We do this instead of the mesa/st lowerings for better behaviour with lowered
|
||||
* I/O and vertex epilogues.
|
||||
* gl_PointSize lowering. This runs late on a vertex shader. By this time, I/O
|
||||
* has been lowered, and transform feedback has been written. Point size will
|
||||
* thus only get consumed by the rasterizer, so we can clamp/replace. We do
|
||||
* this instead of the mesa/st lowerings to avoid the variant. I wouldn't mind
|
||||
* ripping this out some day...
|
||||
*/
|
||||
|
||||
static bool
|
||||
pass(nir_builder *b, nir_intrinsic_instr *intr, void *data)
|
||||
{
|
||||
bool *fixed_point_size = data;
|
||||
b->cursor = nir_before_instr(&intr->instr);
|
||||
|
||||
if ((intr->intrinsic != nir_intrinsic_store_output) ||
|
||||
(nir_intrinsic_io_semantics(intr).location != VARYING_SLOT_PSIZ))
|
||||
return false;
|
||||
|
||||
if (*fixed_point_size) {
|
||||
/* We want to override point size. Remove this store. */
|
||||
nir_instr_remove(&intr->instr);
|
||||
} else {
|
||||
/* We want to use this point size. Clamp it. */
|
||||
nir_src_rewrite(&intr->src[0],
|
||||
nir_fmax(b, intr->src[0].ssa, nir_imm_float(b, 1.0f)));
|
||||
}
|
||||
/* The size we write must be clamped */
|
||||
nir_def *size = nir_fmax(b, intr->src[0].ssa, nir_imm_float(b, 1.0f));
|
||||
|
||||
/* Override it if the API requires */
|
||||
nir_def *fixed_size = nir_load_fixed_point_size_agx(b);
|
||||
size = nir_bcsel(b, nir_fgt_imm(b, fixed_size, 0.0), fixed_size, size);
|
||||
|
||||
nir_src_rewrite(&intr->src[0], size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
agx_nir_lower_point_size(nir_shader *nir, bool fixed_point_size)
|
||||
agx_nir_lower_point_size(nir_shader *nir, bool insert_write)
|
||||
{
|
||||
/* Handle existing point size write */
|
||||
bool progress = nir_shader_intrinsics_pass(
|
||||
nir, pass, nir_metadata_block_index | nir_metadata_dominance,
|
||||
&fixed_point_size);
|
||||
/* Lower existing point size write */
|
||||
if (nir_shader_intrinsics_pass(
|
||||
nir, pass, nir_metadata_block_index | nir_metadata_dominance, NULL))
|
||||
return true;
|
||||
|
||||
/* Write the fixed-function point size if we have one */
|
||||
if (fixed_point_size) {
|
||||
nir_builder b =
|
||||
nir_builder_at(nir_after_impl(nir_shader_get_entrypoint(nir)));
|
||||
if (!insert_write)
|
||||
return false;
|
||||
|
||||
nir_store_output(
|
||||
&b, nir_load_fixed_point_size_agx(&b), nir_imm_int(&b, 0),
|
||||
.io_semantics.location = VARYING_SLOT_PSIZ,
|
||||
.io_semantics.num_slots = 1, .write_mask = nir_component_mask(1));
|
||||
/* If there's no existing point size write, insert one. This assumes there
|
||||
* was a fixed point size set in the API. If not, GL allows undefined
|
||||
* behaviour, which we implement by writing garbage.
|
||||
*/
|
||||
nir_builder b =
|
||||
nir_builder_at(nir_after_impl(nir_shader_get_entrypoint(nir)));
|
||||
|
||||
nir->info.outputs_written |= VARYING_BIT_PSIZ;
|
||||
progress = true;
|
||||
nir_metadata_preserve(b.impl,
|
||||
nir_metadata_dominance | nir_metadata_block_index);
|
||||
}
|
||||
nir_store_output(&b, nir_load_fixed_point_size_agx(&b), nir_imm_int(&b, 0),
|
||||
.io_semantics.location = VARYING_SLOT_PSIZ,
|
||||
.io_semantics.num_slots = 1,
|
||||
.write_mask = nir_component_mask(1));
|
||||
|
||||
return progress;
|
||||
nir->info.outputs_written |= VARYING_BIT_PSIZ;
|
||||
nir_metadata_preserve(b.impl,
|
||||
nir_metadata_dominance | nir_metadata_block_index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1823,8 +1823,8 @@ agx_compile_variant(struct agx_device *dev, struct pipe_context *pctx,
|
|||
NIR_PASS(_, nir, lower_vbo, key->attribs);
|
||||
|
||||
if (key->hw) {
|
||||
NIR_PASS(_, nir, agx_nir_lower_point_size,
|
||||
key->next.hw.fixed_point_size);
|
||||
NIR_PASS(_, nir, agx_nir_lower_point_size, true);
|
||||
|
||||
NIR_PASS(_, nir, nir_shader_intrinsics_pass, agx_nir_lower_clip_m1_1,
|
||||
nir_metadata_block_index | nir_metadata_dominance, NULL);
|
||||
NIR_PASS(_, nir, agx_nir_lower_uvs, &uvs);
|
||||
|
|
@ -1976,10 +1976,11 @@ agx_compile_variant(struct agx_device *dev, struct pipe_context *pctx,
|
|||
}
|
||||
|
||||
if (gs_copy) {
|
||||
struct asahi_gs_shader_key *key = &key_->gs;
|
||||
/* Replace the point size write if present, but do not insert a write:
|
||||
* the GS rast program writes point size iff we have points.
|
||||
*/
|
||||
NIR_PASS(_, gs_copy, agx_nir_lower_point_size, false);
|
||||
|
||||
/* TODO: deduplicate */
|
||||
NIR_PASS(_, gs_copy, agx_nir_lower_point_size, key->fixed_point_size);
|
||||
NIR_PASS(_, gs_copy, nir_shader_intrinsics_pass, agx_nir_lower_clip_m1_1,
|
||||
nir_metadata_block_index | nir_metadata_dominance, NULL);
|
||||
|
||||
|
|
@ -2381,21 +2382,12 @@ agx_update_vs(struct agx_context *ctx, unsigned index_size_B)
|
|||
ctx->stage[PIPE_SHADER_GEOMETRY].shader || ctx->in_tess))
|
||||
return false;
|
||||
|
||||
enum mesa_prim rasterized_prim =
|
||||
rast_prim(ctx->batch->reduced_prim, ctx->rast->base.fill_front);
|
||||
|
||||
struct asahi_vs_shader_key key = {
|
||||
.hw = !((ctx->stage[PIPE_SHADER_TESS_EVAL].shader && !ctx->in_tess) ||
|
||||
ctx->stage[PIPE_SHADER_GEOMETRY].shader),
|
||||
};
|
||||
|
||||
if (key.hw) {
|
||||
/* If we are not rasterizing points, don't set fixed_point_size to
|
||||
* eliminate the useless point size write.
|
||||
*/
|
||||
key.next.hw.fixed_point_size = !ctx->rast->base.point_size_per_vertex &&
|
||||
rasterized_prim == MESA_PRIM_POINTS;
|
||||
} else {
|
||||
if (!key.hw) {
|
||||
key.next.sw.index_size_B = index_size_B;
|
||||
}
|
||||
|
||||
|
|
@ -2441,15 +2433,8 @@ agx_update_gs(struct agx_context *ctx, const struct pipe_draw_info *info,
|
|||
tgt->stride = gs->xfb_strides[i];
|
||||
}
|
||||
|
||||
enum mesa_prim rasterized_prim =
|
||||
rast_prim(gs->gs_mode, ctx->rast->base.fill_front);
|
||||
|
||||
struct asahi_gs_shader_key key = {
|
||||
.rasterizer_discard = ctx->rast->base.rasterizer_discard,
|
||||
|
||||
/* TODO: Deduplicate */
|
||||
.fixed_point_size = !ctx->rast->base.point_size_per_vertex &&
|
||||
rasterized_prim == MESA_PRIM_POINTS,
|
||||
};
|
||||
|
||||
return agx_update_shader(ctx, &ctx->gs, PIPE_SHADER_GEOMETRY,
|
||||
|
|
@ -5044,7 +5029,9 @@ agx_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
|
|||
}
|
||||
|
||||
if (IS_DIRTY(RS)) {
|
||||
batch->uniforms.fixed_point_size = ctx->rast->base.point_size;
|
||||
batch->uniforms.fixed_point_size =
|
||||
ctx->rast->base.point_size_per_vertex ? 0.0
|
||||
: ctx->rast->base.point_size;
|
||||
}
|
||||
|
||||
if (IS_DIRTY(QUERY)) {
|
||||
|
|
|
|||
|
|
@ -486,10 +486,6 @@ struct asahi_vs_shader_key {
|
|||
struct {
|
||||
uint8_t index_size_B;
|
||||
} sw;
|
||||
|
||||
struct {
|
||||
bool fixed_point_size;
|
||||
} hw;
|
||||
} next;
|
||||
};
|
||||
|
||||
|
|
@ -520,12 +516,9 @@ struct asahi_fs_shader_key {
|
|||
};
|
||||
|
||||
struct asahi_gs_shader_key {
|
||||
/* Rasterizer shader key */
|
||||
bool fixed_point_size;
|
||||
|
||||
/* If true, this GS is run only for its side effects (including XFB) */
|
||||
bool rasterizer_discard;
|
||||
bool padding[6];
|
||||
bool padding[7];
|
||||
};
|
||||
static_assert(sizeof(struct asahi_gs_shader_key) == 8, "no holes");
|
||||
|
||||
|
|
@ -980,7 +973,7 @@ void agx_set_cbuf_uniforms(struct agx_batch *batch,
|
|||
void agx_set_ssbo_uniforms(struct agx_batch *batch,
|
||||
enum pipe_shader_type stage);
|
||||
|
||||
bool agx_nir_lower_point_size(nir_shader *nir, bool fixed_point_size);
|
||||
bool agx_nir_lower_point_size(nir_shader *nir, bool insert_write);
|
||||
|
||||
bool agx_nir_lower_sysvals(nir_shader *shader, enum pipe_shader_type desc_stage,
|
||||
bool lower_draw_params);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue