/* -*- mesa-c++ -*- * * Copyright (c) 2018 Collabora LTD * * Author: Gert Wollny * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * on the rights to use, copy, modify, merge, publish, distribute, sub * license, and/or sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "sfn_instruction_fetch.h" #include "gallium/drivers/r600/r600_pipe.h" namespace r600 { /* refactor this to add status create methods for specific tasks */ FetchInstruction::FetchInstruction(EVFetchInstr op, EVFetchType type, GPRVector dst, PValue src, int offset, int buffer_id, PValue buffer_offset, EBufferIndexMode cp_rel, bool use_const_field): Instruction(vtx), m_vc_opcode(op), m_fetch_type(type), m_endian_swap(vtx_es_none), m_src(src), m_dst(dst), m_offset(offset), m_is_mega_fetch(1), m_mega_fetch_count(16), m_buffer_id(buffer_id), m_semantic_id(0), m_buffer_index_mode(cp_rel), m_flags(0), m_uncached(false), m_indexed(false), m_array_base(0), m_array_size(0), m_elm_size(0), m_buffer_offset(buffer_offset), m_dest_swizzle({0,1,2,3}) { if (use_const_field) { m_flags.set(vtx_use_const_field); m_data_format = fmt_invalid; m_num_format = vtx_nf_norm; } else { m_flags.set(vtx_format_comp_signed); m_data_format = fmt_32_32_32_32_float; m_num_format = vtx_nf_scaled; } add_remappable_src_value(&m_src); add_remappable_src_value(&m_buffer_offset); add_remappable_dst_value(&m_dst); } /* Resource query */ FetchInstruction::FetchInstruction(EVFetchInstr vc_opcode, EVFetchType fetch_type, EVTXDataFormat data_format, EVFetchNumFormat num_format, EVFetchEndianSwap endian_swap, const PValue src, const GPRVector dst, uint32_t offset, bool is_mega_fetch, uint32_t mega_fetch_count, uint32_t buffer_id, uint32_t semantic_id, EBufferIndexMode buffer_index_mode, bool uncached, bool indexed, int array_base, int array_size, int elm_size, PValue buffer_offset, const std::array& dest_swizzle): Instruction(vtx), m_vc_opcode(vc_opcode), m_fetch_type(fetch_type), m_data_format(data_format), m_num_format(num_format), m_endian_swap(endian_swap), m_src(src), m_dst(dst), m_offset(offset), m_is_mega_fetch(is_mega_fetch), m_mega_fetch_count(mega_fetch_count), m_buffer_id(buffer_id), m_semantic_id(semantic_id), m_buffer_index_mode(buffer_index_mode), m_uncached(uncached), m_indexed(indexed), m_array_base(array_base), m_array_size(array_size), m_elm_size(elm_size), m_buffer_offset(buffer_offset), m_dest_swizzle(dest_swizzle) { add_remappable_src_value(&m_src); add_remappable_dst_value(&m_dst); add_remappable_src_value(&m_buffer_offset); } FetchInstruction::FetchInstruction(GPRVector dst, PValue src, int buffer_id, PValue buffer_offset, EVTXDataFormat format, EVFetchNumFormat num_format): Instruction(vtx), m_vc_opcode(vc_fetch), m_fetch_type(no_index_offset), m_data_format(format), m_num_format(num_format), m_endian_swap(vtx_es_none), m_src(src), m_dst(dst), m_offset(0), m_is_mega_fetch(0), m_mega_fetch_count(0), m_buffer_id(buffer_id), m_semantic_id(0), m_buffer_index_mode(bim_none), m_flags(0), m_uncached(false), m_indexed(false), m_array_base(0), m_array_size(0), m_elm_size(1), m_buffer_offset(buffer_offset), m_dest_swizzle({0,1,2,3}) { m_flags.set(vtx_format_comp_signed); add_remappable_src_value(&m_src); add_remappable_dst_value(&m_dst); add_remappable_src_value(&m_buffer_offset); } /* Resource query */ FetchInstruction::FetchInstruction(GPRVector dst, PValue src, int buffer_id, EBufferIndexMode cp_rel): Instruction(vtx), m_vc_opcode(vc_get_buf_resinfo), m_fetch_type(no_index_offset), m_data_format(fmt_32_32_32_32), m_num_format(vtx_nf_norm), m_endian_swap(vtx_es_none), m_src(src), m_dst(dst), m_offset(0), m_is_mega_fetch(0), m_mega_fetch_count(16), m_buffer_id(buffer_id), m_semantic_id(0), m_buffer_index_mode(cp_rel), m_flags(0), m_uncached(false), m_indexed(false), m_array_base(0), m_array_size(0), m_elm_size(0), m_dest_swizzle({0,1,2,3}) { m_flags.set(vtx_format_comp_signed); add_remappable_src_value(&m_src); add_remappable_dst_value(&m_dst); add_remappable_src_value(&m_buffer_offset); } FetchInstruction::FetchInstruction(GPRVector dst, PValue src, int scratch_size): Instruction(vtx), m_vc_opcode(vc_read_scratch), m_fetch_type(vertex_data), m_data_format(fmt_32_32_32_32), m_num_format(vtx_nf_int), m_endian_swap(vtx_es_none), m_dst(dst), m_offset(0), m_is_mega_fetch(0), m_mega_fetch_count(16), m_buffer_id(0), m_semantic_id(0), m_buffer_index_mode(bim_none), m_flags(0), m_uncached(true), m_array_base(0), m_array_size(0), m_elm_size(3), m_dest_swizzle({0,1,2,3}) { if (src->type() == Value::literal) { const auto& lv = static_cast(*src); m_array_base = lv.value(); m_indexed = false; m_src.reset(new GPRValue(0,0)); m_array_size = 0; } else { m_array_base = 0; m_src = src; m_indexed = true; m_array_size = scratch_size - 1; } add_remappable_src_value(&m_src); add_remappable_dst_value(&m_dst); add_remappable_src_value(&m_buffer_offset); } void FetchInstruction::replace_values(const ValueSet& candidates, PValue new_value) { if (!m_src) return; for (auto c: candidates) { for (int i = 0; i < 4; ++i) { if (*c == *m_dst.reg_i(i)) m_dst.set_reg_i(i, new_value); } if (*m_src == *c) m_src = new_value; } } bool FetchInstruction::is_equal_to(const Instruction& lhs) const { auto& l = static_cast(lhs); if (m_src) { if (!l.m_src) return false; if (*m_src != *l.m_src) return false; } else { if (l.m_src) return false; } return m_vc_opcode == l.m_vc_opcode && m_fetch_type == l.m_fetch_type && m_data_format == l.m_data_format && m_num_format == l.m_num_format && m_endian_swap == l.m_endian_swap && m_dst == l.m_dst && m_offset == l.m_offset && m_buffer_id == l.m_buffer_id && m_semantic_id == l.m_semantic_id && m_buffer_index_mode == l.m_buffer_index_mode && m_flags == l.m_flags && m_indexed == l.m_indexed && m_uncached == l.m_uncached; } void FetchInstruction::set_format(EVTXDataFormat fmt) { m_data_format = fmt; } void FetchInstruction::set_dest_swizzle(const std::array& swz) { m_dest_swizzle = swz; } void FetchInstruction::prelude_append(Instruction *instr) { assert(instr); m_prelude.push_back(PInstruction(instr)); } const std::vector& FetchInstruction::prelude() const { return m_prelude; } LoadFromScratch::LoadFromScratch(GPRVector dst, PValue src, int scratch_size): FetchInstruction(dst, src, scratch_size) { } FetchGDSOpResult::FetchGDSOpResult(const GPRVector dst, const PValue src): FetchInstruction(vc_fetch, no_index_offset, fmt_32, vtx_nf_int, vtx_es_none, src, dst, 0, false, 0xf, R600_IMAGE_IMMED_RESOURCE_OFFSET, 0, bim_none, false, false, 0, 0, 0, PValue(), {0,7,7,7}) { set_flag(vtx_srf_mode); set_flag(vtx_vpm); } FetchTCSIOParam::FetchTCSIOParam(GPRVector dst, PValue src, int offset): FetchInstruction(vc_fetch, no_index_offset, fmt_32_32_32_32, vtx_nf_scaled, vtx_es_none, src, dst, offset, false, 16, R600_LDS_INFO_CONST_BUFFER, 0, bim_none, false, false, 0, 0, 0, PValue(), {0,1,2,3}) { set_flag(vtx_srf_mode); set_flag(vtx_format_comp_signed); } static const char *fmt_descr[64] = { "INVALID", "8", "4_4", "3_3_2", "RESERVED_4", "16", "16F", "8_8", "5_6_5", "6_5_5", "1_5_5_5", "4_4_4_4", "5_5_5_1", "32", "32F", "16_16", "16_16F", "8_24", "8_24F", "24_8", "24_8F", "10_11_11", "10_11_11F", "11_11_10", "11_11_10F", "2_10_10_10", "8_8_8_8", "10_10_10_2", "X24_8_32F", "32_32", "32_32F", "16_16_16_16", "16_16_16_16F", "RESERVED_33", "32_32_32_32", "32_32_32_32F", "RESERVED_36", "1", "1_REVERSED", "GB_GR", "BG_RG", "32_AS_8", "32_AS_8_8", "5_9_9_9_SHAREDEXP", "8_8_8", "16_16_16", "16_16_16F", "32_32_32", "32_32_32F", "BC1", "BC2", "BC3", "BC4", "BC5", "APC0", "APC1", "APC2", "APC3", "APC4", "APC5", "APC6", "APC7", "CTX1", "RESERVED_63" }; void FetchInstruction::do_print(std::ostream& os) const { static const std::string num_format_char[] = {"norm", "int", "scaled"}; static const std::string endian_swap_code[] = { "noswap", "8in16", "8in32" }; static const char buffer_index_mode_char[] = "_01E"; static const char *flag_string[] = {"WQM", "CF", "signed", "no_zero", "nostride", "AC", "TC", "VPM"}; switch (m_vc_opcode) { case vc_fetch: os << "Fetch " << m_dst; break; case vc_semantic: os << "Fetch Semantic ID:" << m_semantic_id; break; case vc_get_buf_resinfo: os << "Fetch BufResinfo:" << m_dst; break; case vc_read_scratch: os << "MEM_READ_SCRATCH:" << m_dst; break; default: os << "Fetch ERROR"; return; } os << ", " << *m_src; if (m_offset) os << "+" << m_offset; os << " BUFID:" << m_buffer_id << " FMT:(" << fmt_descr[m_data_format] << " " << num_format_char[m_num_format] << " " << endian_swap_code[m_endian_swap] << ")"; if (m_buffer_index_mode > 0) os << " IndexMode:" << buffer_index_mode_char[m_buffer_index_mode]; if (m_is_mega_fetch) os << " MFC:" << m_mega_fetch_count; else os << " mfc*:" << m_mega_fetch_count; if (m_flags.any()) { os << " Flags:"; for( int i = 0; i < vtx_unknown; ++i) { if (m_flags.test(i)) os << ' ' << flag_string[i]; } } } }