xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r600/sfn/sfn_nir_lower_alu.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /* -*- mesa-c++  -*-
2  * Copyright 2022 Collabora LTD
3  * Author: Gert Wollny <[email protected]>
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "sfn_nir_lower_alu.h"
8 
9 #include "sfn_nir.h"
10 
11 namespace r600 {
12 
13 class Lower2x16 : public NirLowerInstruction {
14 private:
15    bool filter(const nir_instr *instr) const override;
16    nir_def *lower(nir_instr *instr) override;
17 };
18 
19 bool
filter(const nir_instr * instr) const20 Lower2x16::filter(const nir_instr *instr) const
21 {
22    if (instr->type != nir_instr_type_alu)
23       return false;
24    auto alu = nir_instr_as_alu(instr);
25    switch (alu->op) {
26    case nir_op_unpack_half_2x16:
27    case nir_op_pack_half_2x16:
28       return true;
29    default:
30       return false;
31    }
32 }
33 
34 nir_def *
lower(nir_instr * instr)35 Lower2x16::lower(nir_instr *instr)
36 {
37    nir_alu_instr *alu = nir_instr_as_alu(instr);
38 
39    switch (alu->op) {
40    case nir_op_unpack_half_2x16: {
41       nir_def *packed = nir_ssa_for_alu_src(b, alu, 0);
42       return nir_vec2(b,
43                       nir_unpack_half_2x16_split_x(b, packed),
44                       nir_unpack_half_2x16_split_y(b, packed));
45    }
46    case nir_op_pack_half_2x16: {
47       nir_def *src_vec2 = nir_ssa_for_alu_src(b, alu, 0);
48       return nir_pack_half_2x16_split(b,
49                                       nir_channel(b, src_vec2, 0),
50                                       nir_channel(b, src_vec2, 1));
51    }
52    default:
53       unreachable("Lower2x16 filter doesn't filter correctly");
54    }
55 }
56 
57 class LowerSinCos : public NirLowerInstruction {
58 public:
LowerSinCos(amd_gfx_level gxf_level)59    LowerSinCos(amd_gfx_level gxf_level):
60        m_gxf_level(gxf_level)
61    {
62    }
63 
64 private:
65    bool filter(const nir_instr *instr) const override;
66    nir_def *lower(nir_instr *instr) override;
67    amd_gfx_level m_gxf_level;
68 };
69 
70 bool
filter(const nir_instr * instr) const71 LowerSinCos::filter(const nir_instr *instr) const
72 {
73    if (instr->type != nir_instr_type_alu)
74       return false;
75 
76    auto alu = nir_instr_as_alu(instr);
77    switch (alu->op) {
78    case nir_op_fsin:
79    case nir_op_fcos:
80       return true;
81    default:
82       return false;
83    }
84 }
85 
86 nir_def *
lower(nir_instr * instr)87 LowerSinCos::lower(nir_instr *instr)
88 {
89    auto alu = nir_instr_as_alu(instr);
90 
91    assert(alu->op == nir_op_fsin || alu->op == nir_op_fcos);
92 
93    auto fract = nir_ffract(b,
94                            nir_ffma_imm12(b,
95                                           nir_ssa_for_alu_src(b, alu, 0),
96                                           0.15915494,
97                                           0.5));
98 
99    auto normalized =
100       m_gxf_level != R600
101          ? nir_fadd_imm(b, fract, -0.5)
102          : nir_ffma_imm12(b, fract, 2.0f * M_PI, -M_PI);
103 
104    if (alu->op == nir_op_fsin)
105       return nir_fsin_amd(b, normalized);
106    else
107       return nir_fcos_amd(b, normalized);
108 }
109 
110 class FixKcacheIndirectRead : public NirLowerInstruction {
111 private:
112    bool filter(const nir_instr *instr) const override;
113    nir_def *lower(nir_instr *instr) override;
114 };
115 
filter(const nir_instr * instr) const116 bool FixKcacheIndirectRead::filter(const nir_instr *instr) const
117 {
118    if (instr->type != nir_instr_type_intrinsic)
119       return false;
120 
121    auto intr = nir_instr_as_intrinsic(instr);
122    if (intr->intrinsic != nir_intrinsic_load_ubo)
123       return false;
124 
125    return nir_src_as_const_value(intr->src[0]) == nullptr;
126 }
127 
lower(nir_instr * instr)128 nir_def *FixKcacheIndirectRead::lower(nir_instr *instr)
129 {
130    auto intr = nir_instr_as_intrinsic(instr);
131    assert(nir_src_as_const_value(intr->src[0]) == nullptr);
132 
133    nir_def *result = &intr->def;
134    for (unsigned i = 14; i < b->shader->info.num_ubos; ++i) {
135       auto test_bufid = nir_imm_int(b, i);
136       auto direct_value =
137 	    nir_load_ubo(b, intr->num_components,
138 			 intr->def.bit_size,
139 			 test_bufid,
140 			 intr->src[1].ssa);
141       auto direct_load = nir_instr_as_intrinsic(direct_value->parent_instr);
142       nir_intrinsic_copy_const_indices(direct_load, intr);
143       result = nir_bcsel(b,
144 			 nir_ieq(b, test_bufid, intr->src[0].ssa),
145 	                 direct_value,
146 	                 result);
147    }
148    return result;
149 }
150 
151 } // namespace r600
152 
153 bool
r600_nir_lower_pack_unpack_2x16(nir_shader * shader)154 r600_nir_lower_pack_unpack_2x16(nir_shader *shader)
155 {
156    return r600::Lower2x16().run(shader);
157 }
158 
159 bool
r600_nir_lower_trigen(nir_shader * shader,amd_gfx_level gfx_level)160 r600_nir_lower_trigen(nir_shader *shader, amd_gfx_level gfx_level)
161 {
162    return r600::LowerSinCos(gfx_level).run(shader);
163 }
164 
165 bool
r600_nir_fix_kcache_indirect_access(nir_shader * shader)166 r600_nir_fix_kcache_indirect_access(nir_shader *shader)
167 {
168    return shader->info.num_ubos > 14 ?
169 	    r600::FixKcacheIndirectRead().run(shader) : false;
170 }
171