mesa/st/tests: Add tests for lifetime tracking with indirect addressing
authorGert Wollny <gw.fossdev@gmail.com>
Thu, 7 Dec 2017 12:57:21 +0000 (13:57 +0100)
committerBrian Paul <brianp@vmware.com>
Wed, 24 Jan 2018 17:34:00 +0000 (10:34 -0700)
Add a code line type that accepts one layer of indirect addressing and
add tests to check that temporary register access used for indirect
addressing is accounted for in the lifetime estimation.

Reviewed-by: Brian Paul <brianp@vmware.com>
Signed-off-by: Gert Wollny <gw.fossdev@gmail.com>
src/mesa/state_tracker/tests/st_tests_common.cpp
src/mesa/state_tracker/tests/st_tests_common.h
src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp

index 03d664dd4bbeff69a5dd45486fcf482e0321f767..ea01ca5555fdc05686280832d232191eed6fa771 100644 (file)
@@ -84,6 +84,30 @@ FakeCodeline::FakeCodeline(unsigned _op, const vector<pair<int,int>>& _dst,
    });
 }
 
+FakeCodeline::FakeCodeline(unsigned _op, const vector<tuple<int,int,int>>& _dst,
+                           const vector<tuple<int,int,int>>& _src,
+                           const vector<tuple<int,int,int>>&_to, RA with_reladdr):
+   op(_op),
+   max_temp_id(0)
+{
+   (void)with_reladdr;
+
+   transform(_dst.begin(), _dst.end(), std::back_inserter(dst),
+             [this](const tuple<int,int,int>& r) {
+      return create_dst_register(r);
+   });
+
+   transform(_src.begin(), _src.end(), std::back_inserter(src),
+             [this](const tuple<int,int,int>& r) {
+      return create_src_register(r);
+   });
+
+   transform(_to.begin(), _to.end(), std::back_inserter(tex_offsets),
+             [this](const tuple<int,int,int>& r) {
+      return create_src_register(r);
+   });
+}
+
 FakeCodeline::FakeCodeline(const glsl_to_tgsi_instruction& instr):
    op(instr.op),
    max_temp_id(0)
@@ -190,10 +214,43 @@ st_src_reg FakeCodeline::create_src_register(int src_idx, gl_register_file file)
    return retval;
 }
 
-st_dst_reg FakeCodeline::create_dst_register(int dst_idx)
+st_src_reg *FakeCodeline::create_rel_src_register(int idx)
 {
-   return create_dst_register(dst_idx, dst_idx < 0 ?
-                                 PROGRAM_OUTPUT : PROGRAM_TEMPORARY);
+   st_src_reg *retval = ralloc(mem_ctx, st_src_reg);
+   *retval = st_src_reg(PROGRAM_TEMPORARY, idx, GLSL_TYPE_INT);
+   if (max_temp_id < idx)
+      max_temp_id = idx;
+   return retval;
+}
+
+st_src_reg FakeCodeline::create_src_register(const tuple<int,int,int>& src)
+{
+   int src_idx = std::get<0>(src);
+   int relidx1 = std::get<1>(src);
+   int relidx2 = std::get<2>(src);
+
+   gl_register_file file = PROGRAM_TEMPORARY;
+   if (src_idx < 0)
+      file = PROGRAM_OUTPUT;
+   else if (relidx1 || relidx2) {
+      file = PROGRAM_ARRAY;
+   }
+
+   st_src_reg retval = create_src_register(src_idx, file);
+   if (src_idx >= 0) {
+      if (relidx1 || relidx2) {
+         retval.array_id = 1;
+
+         if (relidx1)
+            retval.reladdr = create_rel_src_register(relidx1);
+         if (relidx2) {
+            retval.reladdr2 = create_rel_src_register(relidx2);
+            retval.has_index2 = true;
+            retval.index2D = 10;
+         }
+      }
+   }
+   return retval;
 }
 
 st_dst_reg FakeCodeline::create_dst_register(int dst_idx,int writemask)
@@ -212,6 +269,12 @@ st_dst_reg FakeCodeline::create_dst_register(int dst_idx,int writemask)
    return st_dst_reg(file, writemask, GLSL_TYPE_INT, idx);
 }
 
+st_dst_reg FakeCodeline::create_dst_register(int dst_idx)
+{
+   return create_dst_register(dst_idx, dst_idx < 0 ?
+                                 PROGRAM_OUTPUT : PROGRAM_TEMPORARY);
+}
+
 st_dst_reg FakeCodeline::create_dst_register(int dst_idx, gl_register_file file)
 {
    st_dst_reg retval;
@@ -230,6 +293,32 @@ st_dst_reg FakeCodeline::create_dst_register(int dst_idx, gl_register_file file)
    return retval;
 }
 
+st_dst_reg FakeCodeline::create_dst_register(const tuple<int,int,int>& dst)
+{
+   int dst_idx = std::get<0>(dst);
+   int relidx1 = std::get<1>(dst);
+   int relidx2 = std::get<2>(dst);
+
+   gl_register_file file = PROGRAM_TEMPORARY;
+   if (dst_idx < 0)
+      file = PROGRAM_OUTPUT;
+   else if (relidx1 || relidx2) {
+      file = PROGRAM_ARRAY;
+   }
+   st_dst_reg retval = create_dst_register(dst_idx, file);
+
+   if (relidx1 || relidx2) {
+      if (relidx1)
+         retval.reladdr = create_rel_src_register(relidx1);
+      if (relidx2) {
+         retval.reladdr2 = create_rel_src_register(relidx2);
+         retval.has_index2 = true;
+         retval.index2D = 10;
+      }
+   }
+   return retval;
+}
+
 glsl_to_tgsi_instruction *FakeCodeline::get_codeline() const
 {
    glsl_to_tgsi_instruction *next_instr = new(mem_ctx) glsl_to_tgsi_instruction();
index cea8a5ce08e8ac2a5d62d5053ab3ab296f42c174..2e188329231af379b5cc4aa6f188d473dc5b4907 100644 (file)
 /* Use this to make the compiler pick the swizzle constructor below */
 struct SWZ {};
 
+/* Use this to make the compiler pick the constructor with reladdr below */
+struct RA {};
+
 /* A line to describe a TGSI instruction for building mock shaders. */
 struct FakeCodeline {
-   FakeCodeline(unsigned _op): op(_op), max_temp_id(0){}
+   FakeCodeline(unsigned _op): op(_op), max_temp_id(0) {}
    FakeCodeline(unsigned _op, const std::vector<int>& _dst, const std::vector<int>& _src,
                 const std::vector<int>&_to);
 
@@ -45,6 +48,10 @@ struct FakeCodeline {
                 const std::vector<std::pair<int, const char *>>& _src,
                 const std::vector<std::pair<int, const char *>>&_to, SWZ with_swizzle);
 
+   FakeCodeline(unsigned _op, const std::vector<std::tuple<int,int,int>>& _dst,
+                const std::vector<std::tuple<int,int,int>>& _src,
+                const std::vector<std::tuple<int,int,int>>&_to, RA with_reladdr);
+
    FakeCodeline(const glsl_to_tgsi_instruction& inst);
 
    int get_max_reg_id() const { return max_temp_id;}
@@ -60,10 +67,13 @@ private:
    st_src_reg create_src_register(int src_idx);
    st_src_reg create_src_register(int src_idx, const char *swizzle);
    st_src_reg create_src_register(int src_idx, gl_register_file file);
+   st_src_reg create_src_register(const std::tuple<int,int,int>& src);
+   st_src_reg *create_rel_src_register(int idx);
 
    st_dst_reg create_dst_register(int dst_idx);
    st_dst_reg create_dst_register(int dst_idx, int writemask);
    st_dst_reg create_dst_register(int dst_idx, gl_register_file file);
+   st_dst_reg create_dst_register(const std::tuple<int,int,int>& dest);
 
    template <typename st_reg>
    void read_reg(const st_reg& s);
index a1dc28a387510649edf534ef0eb806c8a6edc062..a3b0f0e02f98e0d068e4b856bbf5e3a8c3eb53ec 100644 (file)
@@ -1568,6 +1568,92 @@ TEST_F(LifetimeEvaluatorExactTest, NestedLoopWithWriteAfterBreak)
    run (code, temp_lt_expect({{-1,-1}, {0,8}}));
 }
 
+
+#define MT(X,Y,Z) std::make_tuple(X,Y,Z)
+/* Check lifetime estimation with a relative addressing in src.
+ * Note, since the lifetime estimation always extends the lifetime
+ * at to at least one instruction after the last write, for the
+ * test the last read must be at least two instructions after the
+ * last write to obtain a proper test.
+ */
+
+TEST_F(LifetimeEvaluatorExactTest, ReadIndirectReladdr1)
+{
+   const vector<FakeCodeline> code = {
+      { TGSI_OPCODE_MOV, {1}, {in1}, {}},
+      { TGSI_OPCODE_MOV, {2}, {in0}, {}},
+      { TGSI_OPCODE_MOV, {MT(3,0,0)}, {MT(2,1,0)}, {}, RA()},
+      { TGSI_OPCODE_MOV, {out0}, {3}, {}},
+      { TGSI_OPCODE_END}
+   };
+   run (code, temp_lt_expect({{-1,-1}, {0,2}, {1,2}, {2,3}}));
+}
+
+/* Check lifetime estimation with a relative addressing in src */
+TEST_F(LifetimeEvaluatorExactTest, ReadIndirectReladdr2)
+{
+   const vector<FakeCodeline> code = {
+      { TGSI_OPCODE_MOV , {1}, {in1}, {}},
+      { TGSI_OPCODE_MOV , {2}, {in0}, {}},
+      { TGSI_OPCODE_MOV , {MT(3,0,0)}, {MT(4,0,1)}, {}, RA()},
+      { TGSI_OPCODE_MOV , {out0}, {3}, {}},
+      { TGSI_OPCODE_END}
+   };
+   run (code, temp_lt_expect({{-1,-1}, {0,2}, {1,2},{2,3}}));
+}
+
+/* Check lifetime estimation with a relative addressing in src */
+TEST_F(LifetimeEvaluatorExactTest, ReadIndirectTexOffsReladdr1)
+{
+   const vector<FakeCodeline> code = {
+      { TGSI_OPCODE_MOV , {1}, {in1}, {}},
+      { TGSI_OPCODE_MOV , {2}, {in0}, {}},
+      { TGSI_OPCODE_MOV , {MT(3,0,0)}, {MT(in2,0,0)}, {MT(5,1,0)}, RA()},
+      { TGSI_OPCODE_MOV , {out0}, {3}, {}},
+      { TGSI_OPCODE_END}
+   };
+   run (code, temp_lt_expect({{-1,-1}, {0,2}, {1,2}, {2,3}}));
+}
+
+/* Check lifetime estimation with a relative addressing in src */
+TEST_F(LifetimeEvaluatorExactTest, ReadIndirectTexOffsReladdr2)
+{
+   const vector<FakeCodeline> code = {
+      { TGSI_OPCODE_MOV , {1}, {in1}, {}},
+      { TGSI_OPCODE_MOV , {2}, {in0}, {}},
+      { TGSI_OPCODE_MOV , {MT(3,0,0)}, {MT(in2,0,0)}, {MT(2,0,1)}, RA()},
+      { TGSI_OPCODE_MOV , {out0}, {3}, {}},
+      { TGSI_OPCODE_END}
+   };
+   run (code, temp_lt_expect({{-1,-1}, {0,2}, {1,2}, {2,3}}));
+}
+
+/* Check lifetime estimation with a relative addressing in dst */
+TEST_F(LifetimeEvaluatorExactTest, WriteIndirectReladdr1)
+{
+   const vector<FakeCodeline> code = {
+      { TGSI_OPCODE_MOV , {1}, {in0}, {}},
+      { TGSI_OPCODE_MOV , {1}, {in1}, {}},
+      { TGSI_OPCODE_MOV , {MT(5,1,0)}, {MT(in1,0,0)}, {}, RA()},
+      { TGSI_OPCODE_END}
+   };
+   run (code, temp_lt_expect({{-1,-1}, {0,2}}));
+}
+
+/* Check lifetime estimation with a relative addressing in dst */
+TEST_F(LifetimeEvaluatorExactTest, WriteIndirectReladdr2)
+{
+   const vector<FakeCodeline> code = {
+      { TGSI_OPCODE_MOV , {1}, {in0}, {}},
+      { TGSI_OPCODE_MOV , {2}, {in1}, {}},
+      { TGSI_OPCODE_MOV , {MT(5,0,1)}, {MT(in1,0,0)}, {}, RA()},
+      { TGSI_OPCODE_MOV , {out0}, {in0}, {}},
+      { TGSI_OPCODE_MOV , {out1}, {2}, {}},
+      { TGSI_OPCODE_END}
+   };
+   run (code, temp_lt_expect({{-1,-1}, {0,2}, {1,4}}));
+}
+
 /* Test remapping table of registers. The tests don't assume
  * that the sorting algorithm used to sort the lifetimes
  * based on their 'begin' is stable.