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 #ifndef INSTR_TEX_H 28 #define INSTR_TEX_H 29 30 #include "sfn_instr.h" 31 #include "sfn_shader.h" 32 #include "sfn_valuefactory.h" 33 34 namespace r600 { 35 36 class TexInstr : public InstrWithVectorResult { 37 public: 38 enum Opcode { 39 ld = FETCH_OP_LD, 40 get_resinfo = FETCH_OP_GET_TEXTURE_RESINFO, 41 get_nsamples = FETCH_OP_GET_NUMBER_OF_SAMPLES, 42 get_tex_lod = FETCH_OP_GET_LOD, 43 get_gradient_h = FETCH_OP_GET_GRADIENTS_H, 44 get_gradient_v = FETCH_OP_GET_GRADIENTS_V, 45 set_offsets = FETCH_OP_SET_TEXTURE_OFFSETS, 46 keep_gradients = FETCH_OP_KEEP_GRADIENTS, 47 set_gradient_h = FETCH_OP_SET_GRADIENTS_H, 48 set_gradient_v = FETCH_OP_SET_GRADIENTS_V, 49 sample = FETCH_OP_SAMPLE, 50 sample_l = FETCH_OP_SAMPLE_L, 51 sample_lb = FETCH_OP_SAMPLE_LB, 52 sample_lz = FETCH_OP_SAMPLE_LZ, 53 sample_g = FETCH_OP_SAMPLE_G, 54 sample_g_lb = FETCH_OP_SAMPLE_G_L, 55 gather4 = FETCH_OP_GATHER4, 56 gather4_o = FETCH_OP_GATHER4_O, 57 58 sample_c = FETCH_OP_SAMPLE_C, 59 sample_c_l = FETCH_OP_SAMPLE_C_L, 60 sample_c_lb = FETCH_OP_SAMPLE_C_LB, 61 sample_c_lz = FETCH_OP_SAMPLE_C_LZ, 62 sample_c_g = FETCH_OP_SAMPLE_C_G, 63 sample_c_g_lb = FETCH_OP_SAMPLE_C_G_L, 64 gather4_c = FETCH_OP_GATHER4_C, 65 gather4_c_o = FETCH_OP_GATHER4_C_O, 66 unknown = 255 67 }; 68 69 enum Flags { 70 x_unnormalized, 71 y_unnormalized, 72 z_unnormalized, 73 w_unnormalized, 74 grad_fine, 75 num_tex_flag 76 }; 77 78 static constexpr Flags TexFlags[] = {x_unnormalized, 79 y_unnormalized, 80 z_unnormalized, 81 w_unnormalized, 82 grad_fine, 83 num_tex_flag}; 84 85 struct Inputs { 86 Inputs(const nir_tex_instr& instr, ValueFactory& vf); 87 const nir_variable *sampler_deref; 88 const nir_variable *texture_deref; 89 RegisterVec4 coord; 90 PVirtualValue bias; 91 PVirtualValue comperator; 92 PVirtualValue lod; 93 RegisterVec4 ddx; 94 RegisterVec4 ddy; 95 nir_src *offset; 96 PVirtualValue gather_comp; 97 PVirtualValue ms_index; 98 PRegister texture_offset; 99 PRegister sampler_offset; 100 nir_src *backend1; 101 nir_src *backend2; 102 103 RegisterVec4::Swizzle swizzle_from_ncomps(int comps) const; 104 105 Opcode opcode; 106 107 private: 108 auto get_opcode(const nir_tex_instr& instr) -> Opcode; 109 }; 110 111 TexInstr(Opcode op, 112 const RegisterVec4& dest, 113 const RegisterVec4::Swizzle& dest_swizzle, 114 const RegisterVec4& src, 115 unsigned resource_id, 116 PRegister resource_offs, 117 int sampler_id = 0, 118 PRegister sampler_offset = nullptr); 119 120 TexInstr(const TexInstr& orig) = delete; 121 TexInstr(const TexInstr&& orig) = delete; 122 TexInstr& operator=(const TexInstr& orig) = delete; 123 TexInstr& operator=(const TexInstr&& orig) = delete; 124 125 void accept(ConstInstrVisitor& visitor) const override; 126 void accept(InstrVisitor& visitor) override; 127 src()128 const auto& src() const { return m_src; } src()129 auto& src() { return m_src; } 130 opcode()131 unsigned opcode() const { return m_opcode; } 132 sampler_id()133 unsigned sampler_id() const { return m_sampler.resource_id(); } sampler_offset()134 auto sampler_offset() const { return m_sampler.resource_offset(); } set_sampler_offset(PRegister offs)135 void set_sampler_offset(PRegister offs) { m_sampler.set_resource_offset(offs); } sampler_index_mode()136 auto sampler_index_mode() const { return m_sampler.resource_index_mode(); } 137 138 void set_offset(unsigned index, int32_t val); 139 int get_offset(unsigned index) const; 140 set_inst_mode(int inst_mode)141 void set_inst_mode(int inst_mode) { m_inst_mode = inst_mode; } inst_mode()142 int inst_mode() const { return m_inst_mode; } 143 set_tex_flag(Flags flag)144 void set_tex_flag(Flags flag) { m_tex_flags.set(flag); } has_tex_flag(Flags flag)145 bool has_tex_flag(Flags flag) const { return m_tex_flags.test(flag); } 146 147 void set_gather_comp(int cmp); 148 bool is_equal_to(const TexInstr& lhs) const; 149 150 static Opcode op_from_string(const std::string& s); 151 static Instr::Pointer from_string(std::istream& is, ValueFactory& value_fctory); 152 153 static bool from_nir(nir_tex_instr *tex, Shader& shader); 154 slots()155 uint32_t slots() const override { return 1; }; 156 prepare_instr()157 auto prepare_instr() const { return m_prepare_instr; } 158 159 bool replace_source(PRegister old_src, PVirtualValue new_src) override; 160 void update_indirect_addr(PRegister old_reg, PRegister addr) override; 161 162 uint8_t allowed_src_chan_mask() const override; 163 164 private: 165 bool do_ready() const override; 166 void do_print(std::ostream& os) const override; 167 bool propagate_death() override; 168 169 static const char *opname(Opcode code); 170 static bool is_gather(Opcode op); 171 172 void read_tex_coord_normalitazion(const std::string& next_token); 173 void set_tex_param(const std::string& next_token); 174 175 static auto prepare_source(nir_tex_instr *tex, const Inputs& inputs, Shader& shader) 176 -> RegisterVec4; 177 178 static bool emit_buf_txf(nir_tex_instr *tex, Inputs& src, Shader& shader); 179 static bool emit_tex_txs(nir_tex_instr *tex, 180 Inputs& src, 181 RegisterVec4::Swizzle dest_swz, 182 Shader& shader); 183 static bool emit_tex_lod(nir_tex_instr *tex, Inputs& src, Shader& shader); 184 static bool 185 emit_tex_texture_samples(nir_tex_instr *instr, Inputs& src, Shader& shader); 186 static bool emit_lowered_tex(nir_tex_instr *instr, Inputs& src, Shader& shader); 187 static void emit_set_gradients( 188 nir_tex_instr *tex, int texture_id, Inputs& src, TexInstr *irt, Shader& shader); 189 static void emit_set_offsets( 190 nir_tex_instr *tex, int texture_id, Inputs& src, TexInstr *irt, Shader& shader); 191 192 bool set_coord_offsets(nir_src *offset); 193 void set_rect_coordinate_flags(nir_tex_instr *instr); add_prepare_instr(TexInstr * ir)194 void add_prepare_instr(TexInstr *ir) { m_prepare_instr.push_back(ir); }; 195 void forward_set_blockid(int id, int index) override; 196 197 198 Opcode m_opcode; 199 200 RegisterVec4 m_src; 201 std::bitset<num_tex_flag> m_tex_flags; 202 int m_coord_offset[3]; 203 int m_inst_mode; 204 205 static const std::map<Opcode, std::string> s_opcode_map; 206 std::list<TexInstr *, Allocator<TexInstr *>> m_prepare_instr; 207 208 Resource m_sampler; 209 }; 210 211 bool 212 r600_nir_lower_tex_to_backend(nir_shader *shader, amd_gfx_level chip_class); 213 214 } // namespace r600 215 216 #endif // INSTR_TEX_H 217