summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGert Wollny <gw.fossdev@gmail.com>2018-06-05 22:26:40 +0200
committerGert Wollny <gw.fossdev@gmail.com>2018-08-11 12:32:42 +0200
commitd097ef4204e36c3667f16da59b4991cfb51e5005 (patch)
tree5d63c6b77a2ccd4d3f3db72d5976f49b885ff96e
parentd54c2f92f93a811a853a7b8e87f016ccada04a91 (diff)
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 <gw.fossdev@gmail.com> Acked-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi_array_merge.cpp100
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi_array_merge.h65
2 files changed, 164 insertions, 1 deletions
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 a93d6d00f33..43f0c644b2c 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 028de2c9f5f..9e9443c427a 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