xref: /aosp_15_r20/external/mesa3d/src/intel/compiler/intel_nir_lower_shading_rate_output.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright (c) 2021 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 /*
25  * Lower the shading rate output from the bit field format described in the
26  * SPIRV spec :
27  *
28  * bit | name              | description
29  *   0 | Vertical2Pixels   | Fragment invocation covers 2 pixels vertically
30  *   1 | Vertical4Pixels   | Fragment invocation covers 4 pixels vertically
31  *   2 | Horizontal2Pixels | Fragment invocation covers 2 pixels horizontally
32  *   3 | Horizontal4Pixels | Fragment invocation covers 4 pixels horizontally
33  *
34  * into a single dword composed of 2 fp16 to be stored in the dword 0 of the
35  * VUE header.
36  *
37  * When no horizontal/vertical bits are set, the size in pixel size in that
38  * dimension is assumed to be 1.
39  *
40  * According to the specification, the shading rate output can be read &
41  * written. A read after a write should report a different value if the
42  * implementation decides on different primitive shading rate for some reason.
43  * This is never the case in our implementation.
44  */
45 
46 #include "intel_nir.h"
47 #include "compiler/nir/nir_builder.h"
48 
49 static bool
lower_shading_rate_output_instr(nir_builder * b,nir_intrinsic_instr * intrin,UNUSED void * _state)50 lower_shading_rate_output_instr(nir_builder *b, nir_intrinsic_instr *intrin,
51                                 UNUSED void *_state)
52 {
53    nir_intrinsic_op op = intrin->intrinsic;
54 
55    if (op != nir_intrinsic_load_output &&
56        op != nir_intrinsic_store_output &&
57        op != nir_intrinsic_load_per_primitive_output &&
58        op != nir_intrinsic_store_per_primitive_output)
59       return false;
60 
61    struct nir_io_semantics io = nir_intrinsic_io_semantics(intrin);
62    if (io.location != VARYING_SLOT_PRIMITIVE_SHADING_RATE)
63       return false;
64 
65    bool is_store = op == nir_intrinsic_store_output ||
66                    op == nir_intrinsic_store_per_primitive_output;
67 
68    b->cursor = is_store ? nir_before_instr(&intrin->instr) : nir_after_instr(&intrin->instr);
69 
70    if (is_store) {
71       nir_def *bit_field = intrin->src[0].ssa;
72       nir_def *fp16_x =
73          nir_i2f16(b,
74                    nir_ishl(b, nir_imm_int(b, 1),
75                             nir_ishr_imm(b, bit_field, 2)));
76       nir_def *fp16_y =
77          nir_i2f16(b,
78                    nir_ishl(b, nir_imm_int(b, 1),
79                             nir_iand_imm(b, bit_field, 0x3)));
80       nir_def *packed_fp16_xy = nir_pack_32_2x16_split(b, fp16_x, fp16_y);
81 
82       nir_src_rewrite(&intrin->src[0], packed_fp16_xy);
83    } else {
84       nir_def *packed_fp16_xy = &intrin->def;
85 
86       nir_def *u32_x =
87          nir_i2i32(b, nir_unpack_32_2x16_split_x(b, packed_fp16_xy));
88       nir_def *u32_y =
89          nir_i2i32(b, nir_unpack_32_2x16_split_y(b, packed_fp16_xy));
90 
91       nir_def *bit_field =
92          nir_ior(b, nir_ishl_imm(b, nir_ushr_imm(b, u32_x, 1), 2),
93                     nir_ushr_imm(b, u32_y, 1));
94 
95       nir_def_rewrite_uses_after(packed_fp16_xy, bit_field,
96                                      bit_field->parent_instr);
97    }
98 
99    return true;
100 }
101 
102 bool
intel_nir_lower_shading_rate_output(nir_shader * nir)103 intel_nir_lower_shading_rate_output(nir_shader *nir)
104 {
105    return nir_shader_intrinsics_pass(nir, lower_shading_rate_output_instr,
106                                        nir_metadata_control_flow, NULL);
107 }
108