xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/asahi/agx_nir_lower_point_size.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2023 Valve Corporation
3  * SPDX-License-Identifier: MIT
4  */
5 #include "agx_state.h"
6 #include "nir.h"
7 #include "nir_builder.h"
8 #include "nir_builder_opcodes.h"
9 
10 /*
11  * gl_PointSize lowering. This runs late on a vertex shader. By this time, I/O
12  * has been lowered, and transform feedback has been written. Point size will
13  * thus only get consumed by the rasterizer, so we can clamp/replace. We do
14  * this instead of the mesa/st lowerings to avoid the variant. I wouldn't mind
15  * ripping this out some day...
16  */
17 
18 static bool
pass(nir_builder * b,nir_intrinsic_instr * intr,void * data)19 pass(nir_builder *b, nir_intrinsic_instr *intr, void *data)
20 {
21    b->cursor = nir_before_instr(&intr->instr);
22 
23    if ((intr->intrinsic != nir_intrinsic_store_output) ||
24        (nir_intrinsic_io_semantics(intr).location != VARYING_SLOT_PSIZ))
25       return false;
26 
27    /* The size we write must be clamped */
28    nir_def *size = nir_fmax(b, intr->src[0].ssa, nir_imm_float(b, 1.0f));
29 
30    /* Override it if the API requires */
31    nir_def *fixed_size = nir_load_fixed_point_size_agx(b);
32    size = nir_bcsel(b, nir_fgt_imm(b, fixed_size, 0.0), fixed_size, size);
33 
34    nir_src_rewrite(&intr->src[0], size);
35    return true;
36 }
37 
38 bool
agx_nir_lower_point_size(nir_shader * nir,bool insert_write)39 agx_nir_lower_point_size(nir_shader *nir, bool insert_write)
40 {
41    /* Lower existing point size write */
42    if (nir_shader_intrinsics_pass(nir, pass, nir_metadata_control_flow, NULL))
43       return true;
44 
45    if (!insert_write)
46       return false;
47 
48    /* If there's no existing point size write, insert one. This assumes there
49     * was a fixed point size set in the API. If not, GL allows undefined
50     * behaviour, which we implement by writing garbage.
51     */
52    nir_builder b =
53       nir_builder_at(nir_after_impl(nir_shader_get_entrypoint(nir)));
54 
55    nir_store_output(
56       &b, nir_load_fixed_point_size_agx(&b), nir_imm_int(&b, 0),
57       .io_semantics.location = VARYING_SLOT_PSIZ, .io_semantics.num_slots = 1,
58       .write_mask = nir_component_mask(1), .src_type = nir_type_float32);
59 
60    nir->info.outputs_written |= VARYING_BIT_PSIZ;
61    nir_metadata_preserve(b.impl, nir_metadata_control_flow);
62 
63    return true;
64 }
65