1 /*
2 * Copyright 2023 Valve Corporation
3 * Copyright 2023 Alyssa Rosenzweig
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include "agx_tilebuffer.h"
8 #include "nir_builder.h"
9
10 static nir_def *
mask_by_sample_id(nir_builder * b,nir_def * mask)11 mask_by_sample_id(nir_builder *b, nir_def *mask)
12 {
13 nir_def *id_mask =
14 nir_ishl(b, nir_imm_intN_t(b, 1, mask->bit_size), nir_load_sample_id(b));
15 return nir_iand(b, mask, id_mask);
16 }
17
18 static bool
lower_to_sample(nir_builder * b,nir_intrinsic_instr * intr,void * _)19 lower_to_sample(nir_builder *b, nir_intrinsic_instr *intr, void *_)
20 {
21 b->cursor = nir_before_instr(&intr->instr);
22
23 switch (intr->intrinsic) {
24 case nir_intrinsic_load_sample_pos: {
25 /* Lower sample positions to decode the packed fixed-point register:
26 *
27 * uint32_t packed = load_sample_positions();
28 * uint32_t shifted = packed >> (sample_id * 8);
29 *
30 * for (i = 0; i < 2; ++i) {
31 * uint8_t nibble = (shifted >> (i * 4)) & 0xF;
32 * xy[component] = ((float)nibble) / 16.0;
33 * }
34 */
35 nir_def *packed = nir_load_sample_positions_agx(b);
36
37 /* The n'th sample is the in the n'th byte of the register */
38 nir_def *shifted = nir_ushr(
39 b, packed, nir_u2u32(b, nir_imul_imm(b, nir_load_sample_id(b), 8)));
40
41 nir_def *xy[2];
42 for (unsigned i = 0; i < 2; ++i) {
43 /* Get the appropriate nibble */
44 nir_def *nibble =
45 nir_iand_imm(b, nir_ushr_imm(b, shifted, i * 4), 0xF);
46
47 /* Convert it from fixed point to float */
48 xy[i] = nir_fmul_imm(b, nir_u2f16(b, nibble), 1.0 / 16.0);
49
50 /* Upconvert if necessary */
51 xy[i] = nir_f2fN(b, xy[i], intr->def.bit_size);
52 }
53
54 /* Collect and rewrite */
55 nir_def_rewrite_uses(&intr->def, nir_vec2(b, xy[0], xy[1]));
56 nir_instr_remove(&intr->instr);
57 return true;
58 }
59
60 case nir_intrinsic_load_sample_mask_in: {
61 /* In OpenGL, gl_SampleMaskIn is only supposed to have the single bit set
62 * of the sample currently being shaded when sample shading is used. Mask
63 * by the sample ID to make that happen.
64 */
65 b->cursor = nir_after_instr(&intr->instr);
66 nir_def *old = &intr->def;
67 nir_def *lowered = mask_by_sample_id(b, old);
68 nir_def_rewrite_uses_after(old, lowered, lowered->parent_instr);
69 return true;
70 }
71
72 case nir_intrinsic_load_barycentric_sample: {
73 /* Lower fragment varyings with "sample" interpolation to
74 * interpolateAtSample() with the sample ID
75 */
76 b->cursor = nir_after_instr(&intr->instr);
77 nir_def *old = &intr->def;
78
79 nir_def *lowered = nir_load_barycentric_at_sample(
80 b, intr->def.bit_size, nir_load_sample_id(b),
81 .interp_mode = nir_intrinsic_interp_mode(intr));
82
83 nir_def_rewrite_uses_after(old, lowered, lowered->parent_instr);
84 return true;
85 }
86
87 default:
88 return false;
89 }
90 }
91
92 /*
93 * In a fragment shader using sample shading, lower intrinsics like
94 * load_sample_position to variants in terms of load_sample_id. Except for a
95 * possible API bit to force sample shading in shaders that don't otherwise need
96 * it, this pass does not depend on the shader key. In particular, it does not
97 * depend on the sample count. So it runs on fragment shaders at compile-time.
98 * The load_sample_id intrinsics themselves are lowered later, with different
99 * lowerings for monolithic vs epilogs.
100 *
101 * Note that fragment I/O (like store_local_pixel_agx and discard_agx) does not
102 * get lowered here, because that lowering is different for monolithic vs FS
103 * epilogs even though there's no dependency on sample count.
104 */
105 bool
agx_nir_lower_sample_intrinsics(nir_shader * shader)106 agx_nir_lower_sample_intrinsics(nir_shader *shader)
107 {
108 /* If sample shading is disabled, the unlowered shader will broadcast pixel
109 * values across the sample (the default). By definition, there are no sample
110 * position or sample barycentrics, as these trigger sample shading.
111 */
112 if (!shader->info.fs.uses_sample_shading)
113 return false;
114
115 return nir_shader_intrinsics_pass(
116 shader, lower_to_sample,
117 nir_metadata_block_index | nir_metadata_dominance, NULL);
118 }
119