1 /* 2 * Copyright © 2017 Gert Wollny 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 #ifndef MESA_GLSL_TO_TGSI_ARRAY_MERGE_H 25 #define MESA_GLSL_TO_TGSI_ARRAY_MERGE_H 26 27 28 #include "st_glsl_to_tgsi_private.h" 29 #include <iosfwd> 30 31 /* Until mesa/st officialy requires c++11 */ 32 #if __cplusplus < 201103L 33 #define nullptr 0 34 #endif 35 36 /* Helper class to merge the live ranges of an arrays. 37 * 38 * For arrays the array length, live range, and component access needs to 39 * be kept, because when live ranges are merged or arrays are interleaved 40 * one can only merge or interleave an array into another with equal or more 41 * elements. For interleaving it is also required that the sum of used swizzles 42 * is at most four. 43 */ 44 class array_live_range { 45 public: 46 array_live_range(); 47 array_live_range(unsigned aid, unsigned alength); 48 array_live_range(unsigned aid, unsigned alength, int first_access, 49 int last_access, int mask); 50 51 void set_live_range(int first_access, int last_access); set_begin(int _begin)52 void set_begin(int _begin){first_access = _begin;} set_end(int _end)53 void set_end(int _end){last_access = _end;} 54 void set_access_mask(int s); 55 56 static void merge(array_live_range *a, array_live_range *b); 57 static void interleave(array_live_range *a, array_live_range *b); 58 array_id()59 int array_id() const {return id;} target_array_id()60 int target_array_id() const {return target_array ? target_array->id : 0;} final_target()61 const array_live_range *final_target() const {return target_array ? 62 target_array->final_target() : this;} array_length()63 unsigned array_length() const { return length;} begin()64 int begin() const { return first_access;} end()65 int end() const { return last_access;} access_mask()66 int access_mask() const { return component_access_mask;} used_components()67 int used_components() const {return used_component_count;} 68 69 bool time_doesnt_overlap(const array_live_range& other) const; 70 71 void print(std::ostream& os) const; 72 is_mapped()73 bool is_mapped() const { return target_array != nullptr;} 74 75 int8_t remap_one_swizzle(int8_t idx) const; 76 77 private: 78 void init_swizzles(); 79 void set_target(array_live_range *target); 80 void merge_live_range_from(array_live_range *other); 81 void interleave_into(array_live_range *other); 82 83 unsigned id; 84 unsigned length; 85 int first_access; 86 int last_access; 87 uint8_t component_access_mask; 88 uint8_t used_component_count; 89 array_live_range *target_array; 90 int8_t swizzle_map[4]; 91 }; 92 93 inline 94 std::ostream& operator << (std::ostream& os, const array_live_range& lt) { 95 lt.print(os); 96 return os; 97 } 98 99 namespace tgsi_array_merge { 100 101 /* Helper class to apply array merge and interleav to the shader. 102 * The interface is exposed here to make unit tests possible. 103 */ 104 class array_remapping { 105 public: 106 107 /** Create an invalid mapping that is used as place-holder for 108 * arrays that are not mapped at all. 109 */ 110 array_remapping(); 111 112 /* Predefined remapping, needed for testing */ 113 array_remapping(int trgt_array_id, const int8_t swizzle[]); 114 115 /* Initialiaze the mapping from an array_live_range that has been 116 * processed by the array merge and interleave algorithm. 117 */ 118 void init_from(const array_live_range& range); 119 120 /* (Re)-set target id, needed when the mapping is resolved */ set_target_id(int tid)121 void set_target_id(int tid) {target_id = tid;} 122 123 /* Defines a valid remapping */ is_valid()124 bool is_valid() const {return target_id > 0;} 125 126 /* Translates the write mask to the new, interleaved component 127 * position 128 */ 129 int map_writemask(int original_write_mask) const; 130 131 /* Translates all read swizzles to the new, interleaved component 132 * swizzles 133 */ 134 uint16_t map_swizzles(uint16_t original_swizzle) const; 135 136 /* Move the read swizzles to the positiones that correspond to 137 * a changed write mask. 138 */ 139 uint16_t move_read_swizzles(uint16_t original_swizzle) const; 140 target_array_id()141 unsigned target_array_id() const {return target_id;} 142 143 void print(std::ostream& os) const; 144 145 friend bool operator == (const array_remapping& lhs, 146 const array_remapping& rhs); 147 148 private: 149 150 void interleave(int trgt_access_mask, int src_access_mask); 151 152 unsigned target_id; 153 int8_t read_swizzle_map[4]; 154 }; 155 156 inline 157 std::ostream& operator << (std::ostream& os, const array_remapping& am) 158 { 159 am.print(os); 160 return os; 161 } 162 163 /* Apply the array remapping (internal use, exposed here for testing) */ 164 bool get_array_remapping(int narrays, array_live_range *array_live_ranges, 165 array_remapping *remapping); 166 167 /* Apply the array remapping (internal use, exposed here for testing) */ 168 int remap_arrays(int narrays, unsigned *array_sizes, 169 exec_list *instructions, 170 array_remapping *map); 171 172 } 173 174 /** Remap the array access to finalize the array merging and interleaving. 175 * @param[in] narrays number of input arrays, 176 * @param[in,out] array_sizes length array of input arrays, on output the 177 * array sizes will be updated according to the remapping, 178 * @param[in,out] instructions TGSI program, on output the arrays access is 179 * remapped to the new array layout, 180 * @param[in] array_live_ranges live ranges and access information of the 181 * arrays. 182 * @returns number of remaining arrays 183 */ 184 int merge_arrays(int narrays, 185 unsigned *array_sizes, 186 exec_list *instructions, 187 class array_live_range *arr_live_ranges); 188 #endif 189