• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mesa-c++  -*-
2  *
3  * Copyright (c) 2022 Collabora LTD
4  *
5  * Author: Gert Wollny <gert.wollny@collabora.com>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * on the rights to use, copy, modify, merge, publish, distribute, sub
11  * license, and/or sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26 
27 #include "sfn_nir_lower_alu.h"
28 #include "sfn_nir.h"
29 
30 namespace r600 {
31 
32 class Lower2x16 : public NirLowerInstruction {
33 private:
34    bool filter(const nir_instr *instr) const override;
35    nir_ssa_def *lower(nir_instr *instr) override;
36 };
37 
38 
filter(const nir_instr * instr) const39 bool Lower2x16::filter(const nir_instr *instr) const
40 {
41    if (instr->type != nir_instr_type_alu)
42       return false;
43    auto alu = nir_instr_as_alu(instr);
44    switch (alu->op) {
45    case nir_op_unpack_half_2x16:
46    case nir_op_pack_half_2x16:
47       return true;
48    default:
49       return false;
50    }
51 }
52 
lower(nir_instr * instr)53 nir_ssa_def *Lower2x16::lower(nir_instr *instr)
54 {
55    nir_alu_instr *alu = nir_instr_as_alu(instr);
56 
57    switch (alu->op) {
58    case nir_op_unpack_half_2x16: {
59       nir_ssa_def *packed = nir_ssa_for_alu_src(b, alu, 0);
60       return  nir_vec2(b, nir_unpack_half_2x16_split_x(b, packed),
61                        nir_unpack_half_2x16_split_y(b, packed));
62 
63    }
64    case nir_op_pack_half_2x16: {
65       nir_ssa_def *src_vec2 = nir_ssa_for_alu_src(b, alu, 0);
66       return nir_pack_half_2x16_split(b, nir_channel(b, src_vec2, 0),
67                                       nir_channel(b, src_vec2, 1));
68    }
69    default:
70       unreachable("Lower2x16 filter doesn't filter correctly");
71    }
72 }
73 
74 class LowerSinCos : public NirLowerInstruction {
75 public:
LowerSinCos(amd_gfx_level gxf_level)76    LowerSinCos(amd_gfx_level gxf_level): m_gxf_level(gxf_level){}
77 private:
78    bool filter(const nir_instr *instr) const override;
79    nir_ssa_def *lower(nir_instr *instr) override;
80    amd_gfx_level m_gxf_level;
81 };
82 
filter(const nir_instr * instr) const83 bool LowerSinCos::filter(const nir_instr *instr) const
84 {
85    if (instr->type != nir_instr_type_alu)
86       return false;
87 
88    auto alu = nir_instr_as_alu(instr);
89    switch (alu->op) {
90    case nir_op_fsin:
91    case nir_op_fcos:
92       return true;
93    default:
94       return false;
95    }
96 }
97 
lower(nir_instr * instr)98 nir_ssa_def *LowerSinCos::lower(nir_instr *instr)
99 {
100    auto alu = nir_instr_as_alu(instr);
101 
102    assert(alu->op == nir_op_fsin ||
103           alu->op == nir_op_fcos);
104 
105    auto fract = nir_ffract(b,
106                            nir_ffma(b,
107                                     nir_ssa_for_alu_src(b, alu, 0),
108                                     nir_imm_float(b, 0.15915494),
109                                     nir_imm_float(b, 0.5)));
110 
111    auto normalized =
112          m_gxf_level != R600 ?
113                            nir_fadd(b, fract, nir_imm_float(b, -0.5)) :
114                            nir_ffma(b, fract, nir_imm_float(b, 2.0f * M_PI),
115                                     nir_imm_float(b, -M_PI));
116 
117    if (alu->op == nir_op_fsin)
118       return nir_fsin_amd(b, normalized);
119    else
120       return nir_fcos_amd(b, normalized);
121 }
122 
123 
124 } // namespace r600
125 
126 
r600_nir_lower_pack_unpack_2x16(nir_shader * shader)127 bool r600_nir_lower_pack_unpack_2x16(nir_shader *shader)
128 {
129    return r600::Lower2x16().run(shader);
130 }
131 
r600_nir_lower_trigen(nir_shader * shader,amd_gfx_level gfx_level)132 bool r600_nir_lower_trigen(nir_shader *shader, amd_gfx_level gfx_level)
133 {
134    return r600::LowerSinCos(gfx_level).run(shader);
135 }
136