gallium/tgsi: Add a helper for initializing ureg from a shader_info.
[mesa.git] / src / mesa / state_tracker / st_glsl_to_tgsi_array_merge.h
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);
52 void set_begin(int _begin){first_access = _begin;}
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
59 int array_id() const {return id;}
60 int target_array_id() const {return target_array ? target_array->id : 0;}
61 const array_live_range *final_target() const {return target_array ?
62 target_array->final_target() : this;}
63 unsigned array_length() const { return length;}
64 int begin() const { return first_access;}
65 int end() const { return last_access;}
66 int access_mask() const { return component_access_mask;}
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
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 */
121 void set_target_id(int tid) {target_id = tid;}
122
123 /* Defines a valid remapping */
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
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