From d097ef4204e36c3667f16da59b4991cfb51e5005 Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Tue, 5 Jun 2018 22:26:40 +0200 Subject: [PATCH] mesa/st/glsl_to_tgsi: Add helper classes to apply array merging and interleaving v4: - Remove logic for evaluation of swizzles and merges since this was moved to array_live_range. This class now only handles the actual remapping. Signed-off-by: Gert Wollny Acked-by: Dave Airlie --- .../state_tracker/st_glsl_to_tgsi_array_merge.cpp | 100 +++++++++++++++++++++ .../state_tracker/st_glsl_to_tgsi_array_merge.h | 65 +++++++++++++- 2 files changed, 164 insertions(+), 1 deletion(-) diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi_array_merge.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi_array_merge.cpp index a93d6d0..43f0c64 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi_array_merge.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi_array_merge.cpp @@ -215,3 +215,103 @@ bool array_live_range::time_doesnt_overlap(const array_live_range& other) const return (other.last_access < first_access || last_access < other.first_access); } + +namespace tgsi_array_merge { + +array_remapping::array_remapping(): + target_id(0) +{ + for (int i = 0; i < 4; ++i) { + read_swizzle_map[i] = i; + } +} + +array_remapping::array_remapping(int trgt_array_id, const int8_t swizzle[]): + target_id(trgt_array_id) +{ + for (int i = 0; i < 4; ++i) { + read_swizzle_map[i] = swizzle[i]; + } +} + +void array_remapping::init_from(const array_live_range& range) +{ + target_id = range.is_mapped() ? range.final_target()->array_id(): 0; + for (int i = 0; i < 4; ++i) + read_swizzle_map[i] = range.remap_one_swizzle(i); +} + + +int array_remapping::map_writemask(int write_mask) const +{ + assert(is_valid()); + int result_write_mask = 0; + for (int i = 0; i < 4; ++i) { + if (1 << i & write_mask) { + assert(read_swizzle_map[i] >= 0); + result_write_mask |= 1 << read_swizzle_map[i]; + } + } + return result_write_mask; +} + +uint16_t array_remapping::move_read_swizzles(uint16_t original_swizzle) const +{ + assert(is_valid()); + /* Since + * + * dst.zw = src.xy in glsl actually is MOV dst.__zw src.__xy + * + * when interleaving the arrays the source swizzles must be moved + * according to the changed dst write mask. + */ + uint16_t out_swizzle = 0; + for (int idx = 0; idx < 4; ++idx) { + uint16_t orig_swz = GET_SWZ(original_swizzle, idx); + int new_idx = read_swizzle_map[idx]; + if (new_idx >= 0) + out_swizzle |= orig_swz << 3 * new_idx; + } + return out_swizzle; +} + +uint16_t array_remapping::map_swizzles(uint16_t old_swizzle) const +{ + uint16_t out_swizzle = 0; + for (int idx = 0; idx < 4; ++idx) { + uint16_t swz = read_swizzle_map[GET_SWZ(old_swizzle, idx)]; + out_swizzle |= swz << 3 * idx; + } + return out_swizzle; +} + +void array_remapping::print(std::ostream& os) const +{ + if (is_valid()) { + os << "[aid: " << target_id << " swz: "; + for (int i = 0; i < 4; ++i) + os << (read_swizzle_map[i] >= 0 ? xyzw[read_swizzle_map[i]] : '_'); + os << "]"; + } else { + os << "[unused]"; + } +} + +/* Required by the unit tests */ +bool operator == (const array_remapping& lhs, const array_remapping& rhs) +{ + if (lhs.target_id != rhs.target_id) + return false; + + if (lhs.target_id == 0) + return true; + + for (int i = 0; i < 4; ++i) { + if (lhs.read_swizzle_map[i] != rhs.read_swizzle_map[i]) + return false; + } + return true; +} + +/* end namespace tgsi_array_merge */ +} diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi_array_merge.h b/src/mesa/state_tracker/st_glsl_to_tgsi_array_merge.h index 028de2c..9e9443c 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi_array_merge.h +++ b/src/mesa/state_tracker/st_glsl_to_tgsi_array_merge.h @@ -95,4 +95,67 @@ std::ostream& operator << (std::ostream& os, const array_live_range& lt) { lt.print(os); return os; } -#endif \ No newline at end of file + +namespace tgsi_array_merge { + +/* Helper class to apply array merge and interleav to the shader. + * The interface is exposed here to make unit tests possible. + */ +class array_remapping { +public: + + /** Create an invalid mapping that is used as place-holder for + * arrays that are not mapped at all. + */ + array_remapping(); + + /* Predefined remapping, needed for testing */ + array_remapping(int trgt_array_id, const int8_t swizzle[]); + + /* Initialiaze the mapping from an array_live_range that has been + * processed by the array merge and interleave algorithm. + */ + void init_from(const array_live_range& range); + + /* (Re)-set target id, needed when the mapping is resolved */ + void set_target_id(int tid) {target_id = tid;} + + /* Defines a valid remapping */ + bool is_valid() const {return target_id > 0;} + + /* Translates the write mask to the new, interleaved component + * position + */ + int map_writemask(int original_write_mask) const; + + /* Translates all read swizzles to the new, interleaved component + * swizzles + */ + uint16_t map_swizzles(uint16_t original_swizzle) const; + + /* Move the read swizzles to the positiones that correspond to + * a changed write mask. + */ + uint16_t move_read_swizzles(uint16_t original_swizzle) const; + + unsigned target_array_id() const {return target_id;} + + void print(std::ostream& os) const; + + friend bool operator == (const array_remapping& lhs, + const array_remapping& rhs); + +private: + unsigned target_id; + int8_t read_swizzle_map[4]; +}; + +inline +std::ostream& operator << (std::ostream& os, const array_remapping& am) +{ + am.print(os); + return os; +} + +} +#endif -- 2.7.4