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 SFN_SHADER_H 28 #define SFN_SHADER_H 29 30 #include "sfn_instr.h" 31 #include "sfn_instrfactory.h" 32 #include "sfn_instr_controlflow.h" 33 #include "gallium/drivers/r600/r600_shader.h" 34 #include "sfn_liverangeevaluator.h" 35 36 #include <bitset> 37 #include <memory> 38 #include <stack> 39 #include <vector> 40 41 struct nir_shader; 42 struct nir_cf_node; 43 struct nir_if; 44 struct nir_block; 45 struct nir_instr; 46 47 namespace r600 { 48 49 class ShaderIO { 50 public: 51 void set_sid(int sid); 52 void override_spi_sid(int spi_sid); 53 void print(std::ostream& os) const; 54 spi_sid()55 int spi_sid() const { return m_spi_sid;} sid()56 unsigned sid() const { return m_sid;} 57 location()58 int location() const {return m_location;} name()59 unsigned name() const { return m_name;} 60 pos()61 int pos() const { return m_pos;} set_pos(int pos)62 void set_pos(int pos) {m_pos = pos;} 63 is_param()64 bool is_param() const { return m_is_param;} set_is_param(bool val)65 void set_is_param(bool val) { m_is_param = val;} 66 set_gpr(int gpr)67 void set_gpr(int gpr) {m_gpr = gpr;} gpr()68 int gpr() const {return m_gpr;} 69 70 protected: 71 ShaderIO(const char *type, int loc, int name); 72 73 private: 74 75 virtual void do_print(std::ostream& os) const = 0; 76 77 const char *m_type; 78 int m_location{-1}; 79 int m_name{-1}; 80 int m_sid{0}; 81 int m_spi_sid{0}; 82 int m_pos{0}; 83 int m_is_param{false}; 84 int m_gpr{0}; 85 }; 86 87 class ShaderOutput : public ShaderIO { 88 public: 89 ShaderOutput(); 90 ShaderOutput(int location, int name, int writemask); 91 writemask()92 int writemask() const { return m_writemask;} 93 94 private: 95 void do_print(std::ostream& os) const override; 96 97 int m_writemask{0}; 98 }; 99 100 101 class ShaderInput : public ShaderIO { 102 public: 103 ShaderInput(); 104 ShaderInput(int location, int name); 105 void set_interpolator(int interp, int interp_loc, bool uses_interpolate_at_centroid); 106 void set_uses_interpolate_at_centroid(); set_need_lds_pos()107 void set_need_lds_pos() { m_need_lds_pos = true;} ij_index()108 int ij_index() const { return m_ij_index;} 109 interpolator()110 int interpolator() const{return m_interpolator;} interpolate_loc()111 int interpolate_loc() const {return m_interpolate_loc;} need_lds_pos()112 bool need_lds_pos() const {return m_need_lds_pos;} lds_pos()113 int lds_pos() const {return m_lds_pos;} set_lds_pos(int pos)114 void set_lds_pos(int pos) {m_lds_pos = pos;} 115 ring_offset()116 int ring_offset() const {return m_ring_offset;} set_ring_offset(int offs)117 void set_ring_offset(int offs) {m_ring_offset = offs;} uses_interpolate_at_centroid()118 bool uses_interpolate_at_centroid() const {return m_uses_interpolate_at_centroid;} 119 120 private: 121 void do_print(std::ostream& os) const override; 122 123 int m_interpolator{0}; 124 int m_interpolate_loc{0}; 125 int m_ij_index{0}; 126 bool m_uses_interpolate_at_centroid{false}; 127 bool m_need_lds_pos{false}; 128 int m_lds_pos{0}; 129 int m_ring_offset{0}; 130 }; 131 132 class Shader : public Allocate { 133 public: 134 using InputIterator = std::map<int, ShaderInput>::iterator; 135 using OutputIterator = std::map<int, ShaderOutput>::iterator; 136 137 using ShaderBlocks = std::list<Block::Pointer, Allocator<Block::Pointer>>; 138 139 Shader(const Shader& orig) = delete; 140 ~Shader()141 virtual ~Shader() {} 142 143 bool add_info_from_string(std::istream& is); 144 145 static Shader *translate_from_nir(nir_shader *nir, const pipe_stream_output_info *so_info, r600_shader *gs_shader, 146 r600_shader_key& key, r600_chip_class chip_class); 147 148 bool process(nir_shader *nir); 149 150 bool process_cf_node(nir_cf_node *node); 151 bool process_if(nir_if *node); 152 bool process_loop(nir_loop *node); 153 bool process_block(nir_block *node); 154 bool process_instr(nir_instr *instr); 155 void emit_instruction(PInst instr); 156 bool emit_atomic_local_shared(nir_intrinsic_instr* instr); 157 158 void print(std::ostream& os ) const; 159 void print_header(std::ostream& os ) const; 160 161 bool process_intrinsic(nir_intrinsic_instr *intr); 162 163 virtual bool load_input(nir_intrinsic_instr *intr) = 0; 164 virtual bool store_output(nir_intrinsic_instr *intr) = 0; 165 166 bool load_uniform(nir_intrinsic_instr *intr); 167 bool load_ubo(nir_intrinsic_instr *intr); 168 169 ValueFactory& value_factory(); 170 add_output(const ShaderOutput & output)171 void add_output(const ShaderOutput& output) { 172 m_outputs[output.location()] = output; 173 } 174 add_input(const ShaderInput & input)175 void add_input(const ShaderInput& input) { 176 m_inputs[input.location()] = input; 177 } 178 179 void set_input_gpr(int driver_lcation, int gpr); 180 find_input(int location)181 InputIterator find_input(int location) { return m_inputs.find(location);} 182 input_not_found()183 InputIterator input_not_found() {return m_inputs.end();} 184 185 OutputIterator find_output(int location); output_not_found()186 OutputIterator output_not_found() {return m_outputs.end();} 187 func()188 ShaderBlocks& func() { return m_root; } 189 void reset_function(ShaderBlocks& new_root); 190 191 void emit_instruction_from_string(const std::string &s); 192 193 void set_info(nir_shader *nir); 194 void get_shader_info(r600_shader *sh_info); 195 chip_class()196 r600_chip_class chip_class() const {return m_chip_class;}; set_chip_class(r600_chip_class cls)197 void set_chip_class(r600_chip_class cls) {m_chip_class = cls;}; 198 199 void start_new_block(int nesting_depth); 200 201 const ShaderOutput& output(int base) const; 202 203 LiveRangeMap prepare_live_range_map(); 204 set_last_txd(Instr * txd)205 void set_last_txd(Instr *txd){m_last_txd = txd;} last_txd()206 Instr *last_txd(){return m_last_txd;} 207 208 // Needed for keeping the memory access in order 209 void chain_scratch_read(Instr *instr); 210 void chain_ssbo_read(Instr *instr); 211 enabled_stream_buffers_mask()212 virtual uint32_t enabled_stream_buffers_mask() const {return 0;}; 213 noutputs()214 size_t noutputs() const { return m_outputs.size();} ninputs()215 size_t ninputs() const { return m_inputs.size();} 216 217 enum Flags { 218 sh_indirect_const_file, 219 sh_needs_scratch_space, 220 sh_needs_sbo_ret_address, 221 sh_uses_atomics, 222 sh_uses_images, 223 sh_uses_tex_buffer, 224 sh_writes_memory, 225 sh_txs_cube_array_comp, 226 sh_indirect_atomic, 227 sh_mem_barrier, 228 sh_legacy_math_rules, 229 sh_flags_count 230 }; 231 set_flag(Flags f)232 void set_flag(Flags f) {m_flags.set(f);} has_flag(Flags f)233 bool has_flag(Flags f) const {return m_flags.test(f);} 234 atomic_file_count()235 int atomic_file_count() const { return m_atomic_file_count; } 236 237 PRegister atomic_update(); 238 int remap_atomic_base(int base); 239 auto evaluate_resource_offset(nir_intrinsic_instr *instr, int src_id) -> std::pair<int, PRegister>; ssbo_image_offset()240 int ssbo_image_offset() const {return m_ssbo_image_offset;} rat_return_address()241 PRegister rat_return_address() {assert(m_rat_return_address); return m_rat_return_address;} 242 243 PRegister emit_load_to_register(PVirtualValue src); 244 245 protected: 246 enum ESlots { 247 es_face, 248 es_instanceid, 249 es_invocation_id, 250 es_patch_id, 251 es_pos, 252 es_rel_patch_id, 253 es_sample_mask_in, 254 es_sample_id, 255 es_sample_pos, 256 es_tess_factor_base, 257 es_vertexid, 258 es_tess_coord, 259 es_primitive_id, 260 es_helper_invocation, 261 es_last 262 }; 263 264 std::bitset<es_last> m_sv_values; 265 266 Shader(const char *type_id); 267 268 const ShaderInput& input(int base) const; 269 270 bool emit_simple_mov(nir_dest& dest, int chan, PVirtualValue src, Pin pin = pin_free); 271 272 template <typename T> 273 using IOMap = std::map<int, T, std::less<int>, Allocator<std::pair<const int, T>>>; 274 inputs()275 IOMap<ShaderInput>& inputs() {return m_inputs;} 276 277 private: 278 virtual bool process_stage_intrinsic(nir_intrinsic_instr *intr) = 0; 279 280 bool allocate_registers_from_string(std::istream& is, Pin pin); 281 bool allocate_arrays_from_string(std::istream& is); 282 283 bool read_chipclass(std::istream& is); 284 285 bool load_uniform_indirect(nir_intrinsic_instr *intr, PVirtualValue addr, int offset , int buffer_id); 286 287 bool scan_shader(const nir_function *impl); 288 bool scan_uniforms(nir_variable *uniform); 289 void allocate_reserved_registers(); 290 291 void allocate_local_registers(const exec_list *registers); 292 293 virtual int do_allocate_reserved_registers() = 0; 294 295 bool scan_instruction(nir_instr *instr); 296 virtual bool do_scan_instruction(nir_instr *instr) = 0; 297 298 void print_properties(std::ostream& os) const; 299 virtual void do_print_properties(std::ostream& os) const = 0; 300 301 bool read_output(std::istream& is); 302 bool read_input(std::istream& is); 303 virtual bool read_prop(std::istream& is) = 0; 304 305 bool emit_if_start(nir_if *if_stmt); 306 bool emit_control_flow(ControlFlowInstr::CFType type); 307 bool emit_store_scratch(nir_intrinsic_instr *intr); 308 bool emit_load_scratch(nir_intrinsic_instr *intr); 309 bool emit_local_store(nir_intrinsic_instr *intr); 310 bool emit_local_load(nir_intrinsic_instr* instr); 311 bool emit_load_tcs_param_base(nir_intrinsic_instr* instr, int offset); 312 bool emit_barrier(nir_intrinsic_instr* intr); 313 bool emit_shader_clock(nir_intrinsic_instr* instr); 314 bool emit_wait_ack(); 315 316 bool equal_to(const Shader& other) const; 317 void finalize(); 318 virtual void do_finalize(); 319 320 virtual void do_get_shader_info(r600_shader *sh_info); 321 322 ShaderBlocks m_root; 323 Block::Pointer m_current_block; 324 325 InstrFactory *m_instr_factory; 326 const char *m_type_id; 327 328 IOMap<ShaderOutput> m_outputs; 329 IOMap<ShaderInput> m_inputs; 330 r600_chip_class m_chip_class; 331 332 int m_scratch_size; 333 int m_next_block; 334 bool m_indirect_const_file{false}; 335 336 Instr *m_last_txd {nullptr}; 337 338 uint32_t m_indirect_files{0}; 339 std::bitset<sh_flags_count> m_flags; 340 uint32_t nhwatomic_ranges{0}; 341 std::vector<r600_shader_atomic> m_atomics; 342 343 uint32_t m_nhwatomic{0}; 344 uint32_t m_atomic_base{0}; 345 uint32_t m_next_hwatomic_loc{0}; 346 std::unordered_map<int, int> m_atomic_base_map; 347 uint32_t m_atomic_file_count{0}; 348 PRegister m_atomic_update{nullptr}; 349 PRegister m_rat_return_address{nullptr}; 350 351 int32_t m_ssbo_image_offset{0}; 352 uint32_t m_nloops{0}; 353 354 class InstructionChain : public InstrVisitor { 355 public: visit(AluInstr * instr)356 void visit(AluInstr *instr) override {(void) instr;} visit(AluGroup * instr)357 void visit(AluGroup *instr) override {(void) instr;} visit(TexInstr * instr)358 void visit(TexInstr *instr) override {(void) instr;} visit(ExportInstr * instr)359 void visit(ExportInstr *instr) override {(void) instr;} visit(FetchInstr * instr)360 void visit(FetchInstr *instr) override {(void) instr;} visit(Block * instr)361 void visit(Block *instr) override {(void) instr;} visit(ControlFlowInstr * instr)362 void visit(ControlFlowInstr *instr) override {(void) instr;} visit(IfInstr * instr)363 void visit(IfInstr *instr) override {(void) instr;} visit(StreamOutInstr * instr)364 void visit(StreamOutInstr *instr) override {(void) instr;} visit(MemRingOutInstr * instr)365 void visit(MemRingOutInstr *instr) override {(void) instr;} visit(EmitVertexInstr * instr)366 void visit(EmitVertexInstr *instr) override {(void) instr;} visit(WriteTFInstr * instr)367 void visit(WriteTFInstr *instr) override {(void) instr;} visit(LDSAtomicInstr * instr)368 void visit(LDSAtomicInstr *instr) override {(void) instr;} visit(LDSReadInstr * instr)369 void visit(LDSReadInstr *instr) override {(void) instr;} 370 371 void visit(ScratchIOInstr *instr) override; 372 void visit(GDSInstr *instr) override; 373 void visit(RatInstr *instr) override; 374 375 void apply(Instr *current, Instr **last); 376 377 Shader *this_shader{nullptr}; 378 Instr *last_scratch_instr{nullptr}; 379 Instr *last_gds_instr{nullptr}; 380 Instr *last_ssbo_instr{nullptr}; 381 bool prepare_mem_barrier{false}; 382 }; 383 384 InstructionChain m_chain_instr; 385 std::vector<Instr *> m_loops; 386 }; 387 388 389 std::pair<unsigned, unsigned> 390 r600_get_varying_semantic(unsigned varying_location); 391 392 } 393 394 #endif // SHADER_H 395