diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 84dbbd784bb..e8500cfcbd3 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -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 diff --git a/src/gallium/drivers/asahi/agx_nir_lower_point_size.c b/src/gallium/drivers/asahi/agx_nir_lower_point_size.c index b8a8a4a2c23..4c08ff8fa13 100644 --- a/src/gallium/drivers/asahi/agx_nir_lower_point_size.c +++ b/src/gallium/drivers/asahi/agx_nir_lower_point_size.c @@ -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; } diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index aa166637189..84df7613f3a 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -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)) { diff --git a/src/gallium/drivers/asahi/agx_state.h b/src/gallium/drivers/asahi/agx_state.h index c5335c769cf..3edae8906d6 100644 --- a/src/gallium/drivers/asahi/agx_state.h +++ b/src/gallium/drivers/asahi/agx_state.h @@ -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);