• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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