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 "brw_nir.h"
47 #include "compiler/nir/nir_builder.h"
48
49 static bool
lower_shading_rate_output_instr(nir_builder * b,nir_instr * instr,UNUSED void * _state)50 lower_shading_rate_output_instr(nir_builder *b, nir_instr *instr,
51 UNUSED void *_state)
52 {
53 if (instr->type != nir_instr_type_intrinsic)
54 return false;
55
56 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
57 nir_intrinsic_op op = intrin->intrinsic;
58
59 if (op != nir_intrinsic_load_output &&
60 op != nir_intrinsic_store_output &&
61 op != nir_intrinsic_load_per_primitive_output &&
62 op != nir_intrinsic_store_per_primitive_output)
63 return false;
64
65 struct nir_io_semantics io = nir_intrinsic_io_semantics(intrin);
66 if (io.location != VARYING_SLOT_PRIMITIVE_SHADING_RATE)
67 return false;
68
69 bool is_store = op == nir_intrinsic_store_output ||
70 op == nir_intrinsic_store_per_primitive_output;
71
72 b->cursor = is_store ? nir_before_instr(instr) : nir_after_instr(instr);
73
74 if (is_store) {
75 assert(intrin->src[0].is_ssa);
76 nir_ssa_def *bit_field = intrin->src[0].ssa;
77 nir_ssa_def *fp16_x =
78 nir_i2f16(b,
79 nir_ishl(b, nir_imm_int(b, 1),
80 nir_ishr_imm(b, bit_field, 2)));
81 nir_ssa_def *fp16_y =
82 nir_i2f16(b,
83 nir_ishl(b, nir_imm_int(b, 1),
84 nir_iand_imm(b, bit_field, 0x3)));
85 nir_ssa_def *packed_fp16_xy = nir_pack_32_2x16_split(b, fp16_x, fp16_y);
86
87 nir_instr_rewrite_src(instr, &intrin->src[0],
88 nir_src_for_ssa(packed_fp16_xy));
89 } else {
90 nir_ssa_def *packed_fp16_xy = &intrin->dest.ssa;
91
92 nir_ssa_def *u32_x =
93 nir_i2i32(b, nir_unpack_32_2x16_split_x(b, packed_fp16_xy));
94 nir_ssa_def *u32_y =
95 nir_i2i32(b, nir_unpack_32_2x16_split_y(b, packed_fp16_xy));
96
97 nir_ssa_def *bit_field =
98 nir_ior(b, nir_ishl_imm(b, nir_ushr_imm(b, u32_x, 1), 2),
99 nir_ushr_imm(b, u32_y, 1));
100
101 nir_ssa_def_rewrite_uses_after(packed_fp16_xy, bit_field,
102 bit_field->parent_instr);
103 }
104
105 return true;
106 }
107
108 bool
brw_nir_lower_shading_rate_output(nir_shader * nir)109 brw_nir_lower_shading_rate_output(nir_shader *nir)
110 {
111 return nir_shader_instructions_pass(nir, lower_shading_rate_output_instr,
112 nir_metadata_block_index |
113 nir_metadata_dominance, NULL);
114 }
115