• 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_instr_fetch.h"
28 
29 #include "sfn_alu_defines.h"
30 #include "sfn_defines.h"
31 #include "sfn_valuefactory.h"
32 
33 #include <sstream>
34 
35 namespace r600 {
36 
37 using std::istringstream;
38 using std::string;
39 
FetchInstr(EVFetchInstr opcode,const RegisterVec4 & dst,const RegisterVec4::Swizzle & dest_swizzle,PRegister src,uint32_t src_offset,EVFetchType fetch_type,EVTXDataFormat data_format,EVFetchNumFormat num_format,EVFetchEndianSwap endian_swap,uint32_t resource_id,PRegister resource_offset)40 FetchInstr::FetchInstr(EVFetchInstr opcode,
41                        const RegisterVec4& dst,
42                        const RegisterVec4::Swizzle& dest_swizzle,
43                        PRegister src,
44                        uint32_t src_offset,
45                        EVFetchType fetch_type,
46                        EVTXDataFormat data_format,
47                        EVFetchNumFormat num_format,
48                        EVFetchEndianSwap endian_swap,
49                        uint32_t resource_id,
50                        PRegister resource_offset):
51     InstrWithVectorResult(dst, dest_swizzle, resource_id, resource_offset),
52     m_opcode(opcode),
53     m_src(src),
54     m_src_offset(src_offset),
55     m_fetch_type(fetch_type),
56     m_data_format(data_format),
57     m_num_format(num_format),
58     m_endian_swap(endian_swap),
59     m_mega_fetch_count(0),
60     m_array_base(0),
61     m_array_size(0),
62     m_elm_size(0)
63 {
64    switch (m_opcode) {
65    case vc_fetch:
66       m_opname = "VFETCH";
67       break;
68    case vc_semantic:
69       m_opname = "FETCH_SEMANTIC";
70       break;
71    case vc_get_buf_resinfo:
72       set_print_skip(mfc);
73       set_print_skip(fmt);
74       set_print_skip(ftype);
75       m_opname = "GET_BUF_RESINFO";
76       break;
77    case vc_read_scratch:
78       m_opname = "READ_SCRATCH";
79       break;
80    default:
81       unreachable("Unknown fetch instruction");
82    }
83 
84    if (m_src)
85       m_src->add_use(this);
86 }
87 
88 void
accept(ConstInstrVisitor & visitor) const89 FetchInstr::accept(ConstInstrVisitor& visitor) const
90 {
91    visitor.visit(*this);
92 }
93 
94 void
accept(InstrVisitor & visitor)95 FetchInstr::accept(InstrVisitor& visitor)
96 {
97    visitor.visit(this);
98 }
99 
100 bool
is_equal_to(const FetchInstr & rhs) const101 FetchInstr::is_equal_to(const FetchInstr& rhs) const
102 {
103    if (m_src) {
104       if (rhs.m_src) {
105          if (!m_src->equal_to(*rhs.m_src))
106             return false;
107       } else
108          return false;
109    } else if (rhs.m_src)
110       return false;
111 
112    if (!comp_dest(rhs.dst(), rhs.all_dest_swizzle()))
113       return false;
114 
115    if (m_tex_flags != rhs.m_tex_flags)
116       return false;
117 
118    if (resource_offset() && rhs.resource_offset()) {
119       if (!resource_offset()->equal_to(*rhs.resource_offset()))
120          return false;
121    } else if (!(!!resource_offset() == !!rhs.resource_offset()))
122       return false;
123 
124    return m_opcode == rhs.m_opcode && m_src_offset == rhs.m_src_offset &&
125           m_fetch_type == rhs.m_fetch_type && m_data_format == rhs.m_data_format &&
126           m_num_format == rhs.m_num_format && m_endian_swap == rhs.m_endian_swap &&
127           m_mega_fetch_count == rhs.m_mega_fetch_count &&
128           m_array_base == rhs.m_array_base && m_array_size == rhs.m_array_size &&
129           m_elm_size == rhs.m_elm_size && resource_id() == rhs.resource_id();
130 }
131 
132 bool
propagate_death()133 FetchInstr::propagate_death()
134 {
135    auto reg = m_src->as_register();
136    if (reg)
137       reg->del_use(this);
138    return true;
139 }
140 
141 bool
replace_source(PRegister old_src,PVirtualValue new_src)142 FetchInstr::replace_source(PRegister old_src, PVirtualValue new_src)
143 {
144    bool success = false;
145    auto new_reg = new_src->as_register();
146    if (new_reg) {
147       if (old_src->equal_to(*m_src)) {
148          m_src->del_use(this);
149          m_src = new_reg;
150          new_reg->add_use(this);
151          success = true;
152       }
153       success |= replace_resource_offset(old_src, new_reg);
154    }
155    return success;
156 }
157 
158 bool
do_ready() const159 FetchInstr::do_ready() const
160 {
161    for (auto i : required_instr()) {
162       if (!i->is_scheduled())
163          return false;
164    }
165 
166    bool result = m_src && m_src->ready(block_id(), index());
167    if (resource_offset())
168       result &= resource_offset()->ready(block_id(), index());
169    return result;
170 }
171 
172 void
do_print(std::ostream & os) const173 FetchInstr::do_print(std::ostream& os) const
174 {
175    os << m_opname << ' ';
176 
177    print_dest(os);
178 
179    os << " :";
180 
181    if (m_opcode != vc_get_buf_resinfo) {
182 
183       if (m_src && m_src->chan() < 7) {
184          os << " " << *m_src;
185          if (m_src_offset)
186             os << " + " << m_src_offset << "b";
187       }
188    }
189 
190    if (m_opcode != vc_read_scratch)
191       os << " RID:" << resource_id();
192 
193    print_resource_offset(os);
194 
195    if (!m_skip_print.test(ftype)) {
196       switch (m_fetch_type) {
197       case vertex_data:
198          os << " VERTEX";
199          break;
200       case instance_data:
201          os << " INSTANCE_DATA";
202          break;
203       case no_index_offset:
204          os << " NO_IDX_OFFSET";
205          break;
206       default:
207          unreachable("Unknown fetch instruction type");
208       }
209    }
210 
211    if (!m_skip_print.test(fmt)) {
212       os << " FMT(";
213       auto fmt = s_data_format_map.find(m_data_format);
214       if (fmt != s_data_format_map.end())
215          os << fmt->second << ",";
216       else
217          unreachable("unknown data format");
218 
219       if (m_tex_flags.test(format_comp_signed))
220          os << "S";
221       else
222          os << "U";
223 
224       switch (m_num_format) {
225       case vtx_nf_norm:
226          os << "NORM";
227          break;
228       case vtx_nf_int:
229          os << "INT";
230          break;
231       case vtx_nf_scaled:
232          os << "SCALED";
233          break;
234       default:
235          unreachable("Unknown number format");
236       }
237 
238       os << ")";
239    }
240 
241    if (m_array_base) {
242       if (m_opcode != vc_read_scratch)
243          os << " BASE:" << m_array_base;
244       else
245          os << " L[0x" << std::uppercase << std::hex << m_array_base << std::dec << "]";
246    }
247 
248    if (m_array_size)
249       os << " SIZE:" << m_array_size + 1;
250 
251    if (m_tex_flags.test(is_mega_fetch) && !m_skip_print.test(mfc))
252       os << " MFC:" << m_mega_fetch_count;
253 
254    if (m_elm_size)
255       os << " ES:" << m_elm_size;
256 
257    if (m_tex_flags.test(fetch_whole_quad))
258       os << " WQ";
259    if (m_tex_flags.test(use_const_field))
260       os << " UCF";
261    if (m_tex_flags.test(srf_mode))
262       os << " SRF";
263    if (m_tex_flags.test(buf_no_stride))
264       os << " BNS";
265    if (m_tex_flags.test(alt_const))
266       os << " AC";
267    if (m_tex_flags.test(use_tc))
268       os << " TC";
269    if (m_tex_flags.test(vpm))
270       os << " VPM";
271    if (m_tex_flags.test(uncached) && m_opcode != vc_read_scratch)
272       os << " UNCACHED";
273    if (m_tex_flags.test(indexed) && m_opcode != vc_read_scratch)
274       os << " INDEXED";
275 }
276 
277 Instr::Pointer
from_string(std::istream & is,ValueFactory & vf)278 FetchInstr::from_string(std::istream& is, ValueFactory& vf)
279 {
280    return from_string_impl(is, vc_fetch, vf);
281 }
282 
283 Instr::Pointer
from_string_impl(std::istream & is,EVFetchInstr opcode,ValueFactory & vf)284 FetchInstr::from_string_impl(std::istream& is, EVFetchInstr opcode, ValueFactory& vf)
285 {
286    std::string deststr;
287    is >> deststr;
288 
289    RegisterVec4::Swizzle dst_swz;
290    auto dest_reg = vf.dest_vec4_from_string(deststr, dst_swz, pin_group);
291 
292    char help;
293    is >> help;
294    assert(help == ':');
295 
296    string srcstr;
297    is >> srcstr;
298 
299    std::cerr << "Get source " << srcstr << "\n";
300 
301    auto src_reg = vf.src_from_string(srcstr)->as_register();
302    assert(src_reg);
303 
304    string res_id_str;
305    string next;
306    is >> next;
307 
308    int src_offset_val = 0;
309 
310    if (next == "+") {
311       is >> src_offset_val;
312       is >> help;
313       assert(help == 'b');
314       is >> res_id_str;
315    } else {
316       res_id_str = next;
317    }
318 
319    int res_id = int_from_string_with_prefix(res_id_str, "RID:");
320 
321    string fetch_type_str;
322    is >> fetch_type_str;
323 
324    EVFetchType fetch_type = vertex_data;
325    if (fetch_type_str == "VERTEX") {
326       fetch_type = vertex_data;
327    } else {
328       assert("Fetch type not yet implemented");
329    }
330 
331    string format_str;
332    is >> format_str;
333 
334    assert(!strncmp(format_str.c_str(), "FMT(", 4));
335    string data_format;
336    string num_format_str;
337 
338    istringstream fmt_stream(format_str.substr(4));
339    bool is_num_fmr = false;
340    assert(!fmt_stream.eof());
341 
342    do {
343       char c;
344       fmt_stream >> c;
345 
346       if (c == ',') {
347          is_num_fmr = true;
348          continue;
349       }
350 
351       if (!is_num_fmr)
352          data_format.append(1, c);
353       else
354          num_format_str.append(1, c);
355    } while (!fmt_stream.eof());
356 
357    EVTXDataFormat fmt = fmt_invalid;
358 
359    for (auto& [f, name] : s_data_format_map) {
360       if (data_format == name) {
361          fmt = f;
362          break;
363       }
364    }
365 
366    assert(fmt != fmt_invalid);
367 
368    bool fmt_signed = num_format_str[0] == 'S';
369    assert(fmt_signed || num_format_str[0] == 'U');
370 
371    size_t num_format_end = num_format_str.find(')');
372    num_format_str = num_format_str.substr(1, num_format_end - 1);
373 
374    EVFetchNumFormat num_fmt;
375    if (num_format_str == "NORM")
376       num_fmt = vtx_nf_norm;
377    else if (num_format_str == "INT")
378       num_fmt = vtx_nf_int;
379    else if (num_format_str == "SCALED")
380       num_fmt = vtx_nf_scaled;
381    else {
382       std::cerr << "Number format: '" << num_format_str << "' : ";
383       unreachable("Unknown number format");
384    }
385 
386    auto fetch = new FetchInstr(opcode,
387                                dest_reg,
388                                dst_swz,
389                                src_reg,
390                                src_offset_val,
391                                fetch_type,
392                                fmt,
393                                num_fmt,
394                                vtx_es_none,
395                                res_id,
396                                nullptr);
397    if (fmt_signed)
398       fetch->set_fetch_flag(format_comp_signed);
399 
400    while (!is.eof() && is.good()) {
401       std::string next_token;
402       is >> next_token;
403 
404       if (next_token.empty())
405          break;
406 
407       if (next_token.find(':') != string::npos) {
408          fetch->set_param_from_string(next_token);
409       } else {
410          fetch->set_flag_from_string(next_token);
411       }
412    }
413 
414    return fetch;
415 }
416 
417 void
set_param_from_string(const std::string & token)418 FetchInstr::set_param_from_string(const std::string& token)
419 {
420    if (token.substr(0, 4) == "MFC:")
421       set_mfc(int_from_string_with_prefix(token, "MFC:"));
422    else if (token.substr(0, 5) == "ARRB:")
423       set_array_base(int_from_string_with_prefix(token, "ARRB:"));
424    else if (token.substr(0, 5) == "ARRS:")
425       set_array_size(int_from_string_with_prefix(token, "ARRS:"));
426    else if (token.substr(0, 3) == "ES:")
427       set_element_size(int_from_string_with_prefix(token, "ES:"));
428    else {
429       std::cerr << "Token '" << token << "': ";
430       unreachable("Unknown token in fetch param list");
431    }
432 }
433 
434 void
set_flag_from_string(const std::string & token)435 FetchInstr::set_flag_from_string(const std::string& token)
436 {
437    auto flag = s_flag_map.find(token.c_str());
438    if (flag != s_flag_map.end())
439       set_fetch_flag(flag->second);
440    else {
441       std::cerr << "Token: " << token << " : ";
442       unreachable("Unknown token in fetch flag list");
443    }
444 }
445 
446 const std::map<const char *, FetchInstr::EFlags> FetchInstr::s_flag_map = {
447    {"WQ",       fetch_whole_quad},
448    {"UCF",      use_const_field },
449    {"SRF",      srf_mode        },
450    {"BNS",      buf_no_stride   },
451    {"AC",       alt_const       },
452    {"TC",       use_tc          },
453    {"VPM",      vpm             },
454    {"UNCACHED", uncached        },
455    {"INDEXED",  indexed         }
456 };
457 
458 const std::map<EVTXDataFormat, const char *> FetchInstr::s_data_format_map = {
459    {fmt_invalid,           "INVALID"          },
460    {fmt_8,                 "8"                },
461    {fmt_4_4,               "4_4"              },
462    {fmt_3_3_2,             "3_3_2"            },
463    {fmt_reserved_4,        "RESERVED_4"       },
464    {fmt_16,                "16"               },
465    {fmt_16_float,          "16F"              },
466    {fmt_8_8,               "8_8"              },
467    {fmt_5_6_5,             "5_6_5"            },
468    {fmt_6_5_5,             "6_5_5"            },
469    {fmt_1_5_5_5,           "1_5_5_5"          },
470    {fmt_4_4_4_4,           "4_4_4_4"          },
471    {fmt_5_5_5_1,           "5_5_5_1"          },
472    {fmt_32,                "32"               },
473    {fmt_32_float,          "32F"              },
474    {fmt_16_16,             "16_16"            },
475    {fmt_16_16_float,       "16_16F"           },
476    {fmt_8_24,              "8_24"             },
477    {fmt_8_24_float,        "8_24F"            },
478    {fmt_24_8,              "24_8"             },
479    {fmt_24_8_float,        "24_8F"            },
480    {fmt_10_11_11,          "10_11_11"         },
481    {fmt_10_11_11_float,    "10_11_11F"        },
482    {fmt_11_11_10,          "11_11_10"         },
483    {fmt_10_11_11_float,    "11_11_10F"        },
484    {fmt_2_10_10_10,        "2_10_10_10"       },
485    {fmt_8_8_8_8,           "8_8_8_8"          },
486    {fmt_10_10_10_2,        "10_10_10_2"       },
487    {fmt_x24_8_32_float,    "X24_8_32F"        },
488    {fmt_32_32,             "32_32"            },
489    {fmt_32_32_float,       "32_32F"           },
490    {fmt_16_16_16_16,       "16_16_16_16"      },
491    {fmt_16_16_16_16_float, "16_16_16_16F"     },
492    {fmt_reserved_33,       "RESERVED_33"      },
493    {fmt_32_32_32_32,       "32_32_32_32"      },
494    {fmt_32_32_32_32_float, "32_32_32_32F"     },
495    {fmt_reserved_36,       "RESERVED_36"      },
496    {fmt_1,                 "1"                },
497    {fmt_1_reversed,        "1_REVERSED"       },
498    {fmt_gb_gr,             "GB_GR"            },
499    {fmt_bg_rg,             "BG_RG"            },
500    {fmt_32_as_8,           "32_AS_8"          },
501    {fmt_32_as_8_8,         "32_AS_8_8"        },
502    {fmt_5_9_9_9_sharedexp, "5_9_9_9_SHAREDEXP"},
503    {fmt_8_8_8,             "8_8_8"            },
504    {fmt_16_16_16,          "16_16_16"         },
505    {fmt_16_16_16_float,    "16_16_16F"        },
506    {fmt_32_32_32,          "32_32_32"         },
507    {fmt_32_32_32_float,    "32_32_32F"        },
508    {fmt_bc1,               "BC1"              },
509    {fmt_bc2,               "BC2"              },
510    {fmt_bc3,               "BC3"              },
511    {fmt_bc4,               "BC4"              },
512    {fmt_bc5,               "BC5"              },
513    {fmt_apc0,              "APC0"             },
514    {fmt_apc1,              "APC1"             },
515    {fmt_apc2,              "APC2"             },
516    {fmt_apc3,              "APC3"             },
517    {fmt_apc4,              "APC4"             },
518    {fmt_apc5,              "APC5"             },
519    {fmt_apc6,              "APC6"             },
520    {fmt_apc7,              "APC7"             },
521    {fmt_ctx1,              "CTX1"             },
522    {fmt_reserved_63,       "RESERVED_63"      }
523 };
524 
QueryBufferSizeInstr(const RegisterVec4 & dst,const RegisterVec4::Swizzle & dst_swz,uint32_t resid)525 QueryBufferSizeInstr::QueryBufferSizeInstr(const RegisterVec4& dst,
526                                            const RegisterVec4::Swizzle& dst_swz,
527                                            uint32_t resid):
528     FetchInstr(vc_get_buf_resinfo,
529                dst,
530                dst_swz,
531                new Register(0, 7, pin_fully),
532                0,
533                no_index_offset,
534                fmt_32_32_32_32,
535                vtx_nf_norm,
536                vtx_es_none,
537                resid,
538                nullptr)
539 {
540    set_fetch_flag(format_comp_signed);
541    set_print_skip(mfc);
542    set_print_skip(fmt);
543    set_print_skip(ftype);
544 }
545 
546 Instr::Pointer
from_string(std::istream & is,ValueFactory & vf)547 QueryBufferSizeInstr::from_string(std::istream& is, ValueFactory& vf)
548 {
549    std::string deststr, res_id_str;
550    is >> deststr;
551 
552    char help;
553    is >> help;
554    assert(help == ':');
555 
556    is >> res_id_str;
557 
558    RegisterVec4::Swizzle dst_swz;
559    auto dst = vf.dest_vec4_from_string(deststr, dst_swz, pin_group);
560    int res_id = int_from_string_with_prefix(res_id_str, "RID:");
561 
562    return new QueryBufferSizeInstr(dst, dst_swz, res_id);
563 }
564 
LoadFromBuffer(const RegisterVec4 & dst,const RegisterVec4::Swizzle & dst_swizzle,PRegister addr,uint32_t addr_offset,uint32_t resid,PRegister res_offset,EVTXDataFormat data_format)565 LoadFromBuffer::LoadFromBuffer(const RegisterVec4& dst,
566                                const RegisterVec4::Swizzle& dst_swizzle,
567                                PRegister addr,
568                                uint32_t addr_offset,
569                                uint32_t resid,
570                                PRegister res_offset,
571                                EVTXDataFormat data_format):
572     FetchInstr(vc_fetch,
573                dst,
574                dst_swizzle,
575                addr,
576                addr_offset,
577                no_index_offset,
578                data_format,
579                vtx_nf_scaled,
580                vtx_es_none,
581                resid,
582                res_offset)
583 {
584    set_fetch_flag(format_comp_signed);
585    set_mfc(16);
586    override_opname("LOAD_BUF");
587    set_print_skip(mfc);
588    set_print_skip(fmt);
589    set_print_skip(ftype);
590 }
591 
592 Instr::Pointer
from_string(std::istream & is,ValueFactory & vf)593 LoadFromBuffer::from_string(std::istream& is, ValueFactory& vf)
594 {
595    std::string deststr;
596    is >> deststr;
597 
598    RegisterVec4::Swizzle dst_swz;
599    auto dst = vf.dest_vec4_from_string(deststr, dst_swz, pin_group);
600 
601    char help;
602    is >> help;
603    assert(help == ':');
604 
605    string addrstr;
606    is >> addrstr;
607    auto addr_reg = vf.src_from_string(addrstr)->as_register();
608 
609    string res_id_str;
610    string next;
611    is >> next;
612 
613    int addr_offset_val = 0;
614 
615    if (next == "+") {
616       is >> addr_offset_val;
617       is >> help;
618       assert(help == 'b');
619       is >> res_id_str;
620    } else {
621       res_id_str = next;
622    }
623 
624    int res_id = int_from_string_with_prefix(res_id_str, "RID:");
625 
626    next.clear();
627    is >> next;
628    PRegister res_offset = nullptr;
629    if (next == "+") {
630       string res_offset_str;
631       is >> res_offset_str;
632       res_offset = vf.src_from_string(res_offset_str)->as_register();
633    }
634 
635    auto fetch = new LoadFromBuffer(
636       dst, dst_swz, addr_reg, addr_offset_val, res_id, res_offset, fmt_32_32_32_32_float);
637    is >> next;
638    if (next == "SRF")
639       fetch->set_fetch_flag(srf_mode);
640 
641    return fetch;
642 }
643 
644 class AddrResolver : public RegisterVisitor {
645 public:
AddrResolver(LoadFromScratch * lfs)646    AddrResolver(LoadFromScratch *lfs):
647        m_lfs(lfs)
648    {
649    }
650 
visit(Register & value)651    void visit(Register& value)
652    {
653       m_lfs->set_fetch_flag(FetchInstr::indexed);
654       m_lfs->set_src(&value);
655       value.add_use(m_lfs);
656    }
visit(LocalArray & value)657    void visit(LocalArray& value)
658    {
659       unreachable("An array can't be a direct source for scratch reads");
660       (void)value;
661    }
visit(LocalArrayValue & value)662    void visit(LocalArrayValue& value)
663    {
664       unreachable("An array value can't be a direct source for scratch reads");
665       // TODO: an array element with constant offset could be used here
666       (void)value;
667    }
visit(UniformValue & value)668    void visit(UniformValue& value)
669    {
670       unreachable("A uniform can't be a direct source for scratch reads");
671       (void)value;
672    }
visit(LiteralConstant & value)673    void visit(LiteralConstant& value)
674    {
675       m_lfs->set_array_base(value.value());
676       m_lfs->set_src(new Register(0, 7, pin_none));
677    }
visit(InlineConstant & value)678    void visit(InlineConstant& value)
679    {
680       if (value.sel() == ALU_SRC_1_INT)
681          m_lfs->set_array_base(1);
682       else if (value.sel() != ALU_SRC_0)
683          unreachable("Scratch array base is an impossible inline constant");
684 
685       m_lfs->set_src(new Register(0, 7, pin_none));
686    }
687 
688    LoadFromScratch *m_lfs;
689 };
690 
LoadFromScratch(const RegisterVec4 & dst,const RegisterVec4::Swizzle & dst_swz,PVirtualValue addr,uint32_t scratch_size)691 LoadFromScratch::LoadFromScratch(const RegisterVec4& dst,
692                                  const RegisterVec4::Swizzle& dst_swz,
693                                  PVirtualValue addr,
694                                  uint32_t scratch_size):
695     FetchInstr(vc_read_scratch,
696                dst,
697                dst_swz,
698                nullptr,
699                0,
700                no_index_offset,
701                fmt_32_32_32_32,
702                vtx_nf_int,
703                vtx_es_none,
704                0,
705                nullptr)
706 {
707    set_fetch_flag(uncached);
708    set_fetch_flag(wait_ack);
709 
710    assert(scratch_size >= 1);
711    set_array_size(scratch_size - 1);
712    set_array_base(0);
713    AddrResolver ar(this);
714    addr->accept(ar);
715 
716    set_print_skip(mfc);
717    set_print_skip(fmt);
718    set_print_skip(ftype);
719    set_element_size(3);
720 }
721 
722 Instr::Pointer
from_string(std::istream & is,ValueFactory & vf)723 LoadFromScratch::from_string(std::istream& is, ValueFactory& vf)
724 {
725    std::string deststr;
726    is >> deststr;
727 
728    RegisterVec4::Swizzle dst_swz;
729    auto dest = vf.dest_vec4_from_string(deststr, dst_swz, pin_group);
730 
731    char help;
732    is >> help;
733    assert(help == ':');
734 
735    string addrstr;
736    is >> addrstr;
737    auto addr_reg = vf.src_from_string(addrstr);
738 
739    string offsetstr;
740    is >> offsetstr;
741    int size = int_from_string_with_prefix(offsetstr, "SIZE:");
742    assert(size >= 1);
743 
744    return new LoadFromScratch(dest, dst_swz, addr_reg, size);
745 }
746 
747 } // namespace r600
748