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