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_st_tests_h 25 #define mesa_st_tests_h 26 27 #include "state_tracker/st_glsl_to_tgsi_temprename.h" 28 #include "state_tracker/st_glsl_to_tgsi_array_merge.h" 29 #include "gtest/gtest.h" 30 31 #include <utility> 32 33 #define MP(X, W) std::make_pair(X, W) 34 #define MT(X,Y,Z) std::make_tuple(X,Y,Z) 35 36 /* Use this to make the compiler pick the swizzle constructor below */ 37 struct SWZ {}; 38 39 /* Use this to make the compiler pick the constructor with reladdr below */ 40 struct RA {}; 41 42 /* Use this to make the compiler pick the constructor with array below */ 43 struct ARR {}; 44 45 /* A line to describe a TGSI instruction for building mock shaders. */ 46 struct FakeCodeline { FakeCodelineFakeCodeline47 FakeCodeline(tgsi_opcode _op): op(_op), max_temp_id(0), max_array_id(0) {} 48 FakeCodeline(tgsi_opcode _op, const std::vector<int>& _dst, const std::vector<int>& _src, 49 const std::vector<int>&_to); 50 51 FakeCodeline(tgsi_opcode _op, const std::vector<std::pair<int,int>>& _dst, 52 const std::vector<std::pair<int, const char *>>& _src, 53 const std::vector<std::pair<int, const char *>>&_to, SWZ with_swizzle); 54 55 FakeCodeline(tgsi_opcode _op, const std::vector<std::tuple<int,int,int>>& _dst, 56 const std::vector<std::tuple<int,int,int>>& _src, 57 const std::vector<std::tuple<int,int,int>>&_to, RA with_reladdr); 58 59 FakeCodeline(tgsi_opcode _op, const std::vector<std::tuple<int, int, int> > &_dst, 60 const std::vector<std::tuple<int,int, const char*>>& _src, 61 const std::vector<std::tuple<int,int, const char*>>&_to, ARR with_array); 62 63 FakeCodeline(const glsl_to_tgsi_instruction& inst); 64 get_max_reg_idFakeCodeline65 int get_max_reg_id() const { return max_temp_id;} get_max_array_idFakeCodeline66 int get_max_array_id() const { return max_array_id;} 67 68 glsl_to_tgsi_instruction *get_codeline() const; 69 70 static void set_mem_ctx(void *ctx); 71 72 friend bool operator == (const FakeCodeline& lsh, const FakeCodeline& rhs); 73 74 void print(std::ostream& os) const; 75 private: 76 st_src_reg create_src_register(int src_idx); 77 st_src_reg create_src_register(int src_idx, const char *swizzle); 78 st_src_reg create_src_register(int src_idx, gl_register_file file); 79 st_src_reg create_src_register(const std::tuple<int,int,int>& src); 80 st_src_reg *create_rel_src_register(int idx); 81 st_src_reg create_array_src_register(const std::tuple<int,int,const char*>& r); 82 st_dst_reg create_array_dst_register(const std::tuple<int,int,int>& r); 83 84 st_dst_reg create_dst_register(int dst_idx); 85 st_dst_reg create_dst_register(int dst_idx, int writemask); 86 st_dst_reg create_dst_register(int dst_idx, gl_register_file file); 87 st_dst_reg create_dst_register(const std::tuple<int,int,int>& dest); 88 89 template <typename st_reg> 90 void read_reg(const st_reg& s); 91 92 tgsi_opcode op; 93 std::vector<st_dst_reg> dst; 94 std::vector<st_src_reg> src; 95 std::vector<st_src_reg> tex_offsets; 96 97 int max_temp_id; 98 int max_array_id; 99 static void *mem_ctx; 100 }; 101 102 inline std::ostream& operator << (std::ostream& os, const FakeCodeline& line) 103 { 104 line.print(os); 105 return os; 106 } 107 108 /* A few constants that will not be tracked as temporary registers 109 by the fake shader. 110 */ 111 const int in0 = -1; 112 const int in1 = -2; 113 const int in2 = -3; 114 115 const int out0 = -1; 116 const int out1 = -2; 117 const int out2 = -3; 118 119 class FakeShader { 120 public: 121 FakeShader(const std::vector<FakeCodeline>& source); 122 FakeShader(exec_list *tgsi_prog); 123 124 exec_list* get_program(void *ctx) const; 125 int get_num_temps() const; 126 int get_num_arrays() const; 127 128 size_t length() const; 129 130 const FakeCodeline& line(unsigned i) const; 131 132 private: 133 134 std::vector<FakeCodeline> program; 135 int num_temps; 136 int num_arrays; 137 }; 138 139 using temp_lt_expect = std::vector<std::vector<int>>; 140 using array_lt_expect = std::vector<array_live_range>; 141 142 class MesaTestWithMemCtx : public testing::Test { 143 void SetUp(); 144 void TearDown(); 145 protected: 146 void *mem_ctx; 147 }; 148 149 class LifetimeEvaluatorTest : public MesaTestWithMemCtx { 150 protected: 151 void run(const std::vector<FakeCodeline>& code, const temp_lt_expect& e); 152 void run(const std::vector<FakeCodeline>& code, const array_lt_expect& e); 153 private: 154 using life_range_result=std::pair<std::vector<register_live_range>, 155 std::vector<array_live_range>>; 156 life_range_result run(const std::vector<FakeCodeline>& code, bool& success); 157 158 virtual void check(const std::vector<register_live_range>& result, 159 const temp_lt_expect& e) = 0; 160 virtual void check(const std::vector<array_live_range>& lifetimes, 161 const array_lt_expect& e) = 0; 162 }; 163 164 /* This is a test class to check the exact life times of 165 * registers. */ 166 class LifetimeEvaluatorExactTest : public LifetimeEvaluatorTest { 167 protected: 168 void check(const std::vector<register_live_range>& result, 169 const temp_lt_expect& e); 170 171 void check(const std::vector<array_live_range>& result, 172 const array_lt_expect& e); 173 }; 174 175 /* This test class checks that the life time covers at least 176 * in the expected range. It is used for cases where we know that 177 * a the implementation could be improved on estimating the minimal 178 * life time. 179 */ 180 class LifetimeEvaluatorAtLeastTest : public LifetimeEvaluatorTest { 181 protected: 182 void check(const std::vector<register_live_range>& result, const temp_lt_expect& e); 183 void check(const std::vector<array_live_range>& result, 184 const array_lt_expect& e); 185 }; 186 187 /* With this test class the renaming mapping estimation is tested */ 188 class RegisterRemappingTest : public MesaTestWithMemCtx { 189 protected: 190 void run(const std::vector<register_live_range>& lt, 191 const std::vector<int> &expect); 192 }; 193 194 /* With this test class the combined lifetime estimation and renaming 195 * mepping estimation is tested 196 */ 197 class RegisterLifetimeAndRemappingTest : public RegisterRemappingTest { 198 protected: 199 using RegisterRemappingTest::run; 200 void run(const std::vector<FakeCodeline>& code, const std::vector<int> &expect); 201 }; 202 203 #endif 204