2 * Copyright © 2017 Gert Wollny
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:
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
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.
24 #ifndef MESA_GLSL_TO_TGSI_ARRAY_MERGE_H
25 #define MESA_GLSL_TO_TGSI_ARRAY_MERGE_H
28 #include "st_glsl_to_tgsi_private.h"
31 /* Until mesa/st officialy requires c++11 */
32 #if __cplusplus < 201103L
36 /* Helper class to merge the live ranges of an arrays.
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
44 class 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
);
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
);
56 static void merge(array_live_range
*a
, array_live_range
*b
);
57 static void interleave(array_live_range
*a
, array_live_range
*b
);
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
;}
69 bool time_doesnt_overlap(const array_live_range
& other
) const;
71 void print(std::ostream
& os
) const;
73 bool is_mapped() const { return target_array
!= nullptr;}
75 int8_t remap_one_swizzle(int8_t idx
) const;
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
);
87 uint8_t component_access_mask
;
88 uint8_t used_component_count
;
89 array_live_range
*target_array
;
90 int8_t swizzle_map
[4];
94 std::ostream
& operator << (std::ostream
& os
, const array_live_range
& lt
) {
99 namespace tgsi_array_merge
{
101 /* Helper class to apply array merge and interleav to the shader.
102 * The interface is exposed here to make unit tests possible.
104 class array_remapping
{
107 /** Create an invalid mapping that is used as place-holder for
108 * arrays that are not mapped at all.
112 /* Predefined remapping, needed for testing */
113 array_remapping(int trgt_array_id
, const int8_t swizzle
[]);
115 /* Initialiaze the mapping from an array_live_range that has been
116 * processed by the array merge and interleave algorithm.
118 void init_from(const array_live_range
& range
);
120 /* (Re)-set target id, needed when the mapping is resolved */
121 void set_target_id(int tid
) {target_id
= tid
;}
123 /* Defines a valid remapping */
124 bool is_valid() const {return target_id
> 0;}
126 /* Translates the write mask to the new, interleaved component
129 int map_writemask(int original_write_mask
) const;
131 /* Translates all read swizzles to the new, interleaved component
134 uint16_t map_swizzles(uint16_t original_swizzle
) const;
136 /* Move the read swizzles to the positiones that correspond to
137 * a changed write mask.
139 uint16_t move_read_swizzles(uint16_t original_swizzle
) const;
141 unsigned target_array_id() const {return target_id
;}
143 void print(std::ostream
& os
) const;
145 friend bool operator == (const array_remapping
& lhs
,
146 const array_remapping
& rhs
);
150 void interleave(int trgt_access_mask
, int src_access_mask
);
153 int8_t read_swizzle_map
[4];
157 std::ostream
& operator << (std::ostream
& os
, const array_remapping
& am
)
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
);
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
);
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
182 * @returns number of remaining arrays
184 int merge_arrays(int narrays
,
185 unsigned *array_sizes
,
186 exec_list
*instructions
,
187 struct array_live_range
*arr_live_ranges
);