• 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 #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