1 /*
2 * Copyright 2024 Igalia S.L.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "compiler/nir/nir_builder.h"
7 #include "ir3_nir.h"
8
9 /* Values written in VS/GS to gl_PrimitiveShadingRateEXT have to
10 * be translated into HW internal representation.
11 */
12 static const uint32_t vk_to_hw_shading_rate_lut[] = {
13 0, 4, 8, 11, 1, 5, 9, 11, 2, 6, 10, 11, 11, 11, 11, 11,
14 0, 1, 2, 11, 4, 5, 6, 11, 8, 9, 10, 11, 11, 11, 11, 11};
15
16 /* Values read from gl_ShadingRateEXT in FS have to be translated from
17 * HW representation.
18 */
19 static const uint32_t hw_to_vk_shading_rate_lut[] = {
20 0, 4, 8, 0, 1, 5, 9, 0, 2, 6, 10, 11, 11, 11, 11, 11,
21 0, 1, 2, 0, 4, 5, 6, 0, 8, 9, 10, 11, 11, 11, 11, 11};
22
23 static nir_deref_instr *
create_lut(nir_builder * b,const uint32_t * lut,uint32_t lut_size,const char * lut_name)24 create_lut(nir_builder *b, const uint32_t *lut, uint32_t lut_size,
25 const char *lut_name)
26 {
27 nir_variable *lut_var = nir_local_variable_create(
28 b->impl, glsl_array_type(glsl_uint_type(), lut_size, 0), lut_name);
29 nir_deref_instr *deref = nir_build_deref_var(b, lut_var);
30
31 for (uint32_t i = 0; i < lut_size; i++) {
32 nir_deref_instr *element =
33 nir_build_deref_array(b, deref, nir_imm_int(b, i));
34 nir_build_store_deref(b, &element->def, nir_imm_int(b, lut[i]), 0x1);
35 }
36
37 return deref;
38 }
39
40 static bool
nir_lower_frag_shading_rate(nir_builder * b,nir_intrinsic_instr * intr,UNUSED void * cb_data)41 nir_lower_frag_shading_rate(nir_builder *b, nir_intrinsic_instr *intr,
42 UNUSED void *cb_data)
43 {
44 if (intr->intrinsic != nir_intrinsic_load_frag_shading_rate)
45 return false;
46
47 b->cursor = nir_after_instr(&intr->instr);
48
49 nir_deref_instr *lut = create_lut(b, hw_to_vk_shading_rate_lut,
50 ARRAY_SIZE(hw_to_vk_shading_rate_lut),
51 "hw_to_vk_shading_rate_lut");
52 nir_deref_instr *result = nir_build_deref_array(b, lut, &intr->def);
53 nir_def *r = nir_build_load_deref(b, 1, 32, &result->def, 0);
54
55 nir_def_rewrite_uses_after(&intr->def, r, r->parent_instr);
56 return true;
57 }
58
59 bool
ir3_nir_lower_frag_shading_rate(nir_shader * shader)60 ir3_nir_lower_frag_shading_rate(nir_shader *shader)
61 {
62 assert(shader->info.stage == MESA_SHADER_FRAGMENT);
63 return nir_shader_intrinsics_pass(shader, nir_lower_frag_shading_rate,
64 nir_metadata_control_flow, NULL);
65 }
66
67 static bool
nir_lower_primitive_shading_rate(nir_builder * b,nir_intrinsic_instr * intr,UNUSED void * cb_data)68 nir_lower_primitive_shading_rate(nir_builder *b, nir_intrinsic_instr *intr,
69 UNUSED void *cb_data)
70 {
71 if (intr->intrinsic != nir_intrinsic_store_output)
72 return false;
73
74 unsigned loc = nir_intrinsic_io_semantics(intr).location;
75 if (loc != VARYING_SLOT_PRIMITIVE_SHADING_RATE)
76 return false;
77
78 b->cursor = nir_before_instr(&intr->instr);
79
80 nir_deref_instr *lut = create_lut(b, vk_to_hw_shading_rate_lut,
81 ARRAY_SIZE(vk_to_hw_shading_rate_lut),
82 "vk_to_hw_shading_rate_lut");
83 nir_deref_instr *result = nir_build_deref_array(b, lut, intr->src[0].ssa);
84 nir_def *r = nir_build_load_deref(b, 1, 32, &result->def, 0);
85
86 nir_src_rewrite(&intr->src[0], r);
87 return true;
88 }
89
90 bool
ir3_nir_lower_primitive_shading_rate(nir_shader * shader)91 ir3_nir_lower_primitive_shading_rate(nir_shader *shader)
92 {
93 assert(shader->info.stage != MESA_SHADER_FRAGMENT);
94 return nir_shader_intrinsics_pass(shader, nir_lower_primitive_shading_rate,
95 nir_metadata_control_flow, NULL);
96 }
97