• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // frame_capture_test_utils:
7 //   Helper functions for capture and replay of traces.
8 //
9 
10 #ifndef UTIL_CAPTURE_FRAME_CAPTURE_TEST_UTILS_H_
11 #define UTIL_CAPTURE_FRAME_CAPTURE_TEST_UTILS_H_
12 
13 #include <iostream>
14 #include <map>
15 #include <memory>
16 #include <sstream>
17 #include <type_traits>
18 #include <vector>
19 
20 #include "common/angleutils.h"
21 #include "common/debug.h"
22 #include "common/frame_capture_utils.h"
23 #include "common/system_utils.h"
24 #include "trace_interface.h"
25 
26 #define USE_SYSTEM_ZLIB
27 #include "compression_utils_portable.h"
28 
29 #define ANGLE_MACRO_STRINGIZE_AUX(a) #a
30 #define ANGLE_MACRO_STRINGIZE(a) ANGLE_MACRO_STRINGIZE_AUX(a)
31 #define ANGLE_MACRO_CONCAT_AUX(a, b) a##b
32 #define ANGLE_MACRO_CONCAT(a, b) ANGLE_MACRO_CONCAT_AUX(a, b)
33 
34 namespace angle
35 {
36 
37 using ValidateSerializedStateCallback = void (*)(const char *, const char *, uint32_t);
38 
39 using GetSerializedContextStateFunc          = const char *(*)(uint32_t);
40 using SetValidateSerializedStateCallbackFunc = void (*)(ValidateSerializedStateCallback);
41 using SetupEntryPoints = void (*)(angle::TraceCallbacks *, angle::TraceFunctions **);
42 
43 class TraceLibrary : angle::NonCopyable, angle::TraceCallbacks
44 {
45   public:
46     TraceLibrary(const std::string &traceName,
47                  const TraceInfo &traceInfo,
48                  const std::string &baseDir);
49 
valid()50     bool valid() const
51     {
52         return (mTraceLibrary != nullptr) && (mTraceLibrary->getNative() != nullptr);
53     }
54 
setReplayResourceMode(const bool resourceMode)55     void setReplayResourceMode(const bool resourceMode)
56     {
57         mTraceFunctions->SetReplayResourceMode(
58             (resourceMode ? ReplayResourceMode::All : ReplayResourceMode::Active));
59     }
60 
setBinaryDataDir(const char * dataDir)61     void setBinaryDataDir(const char *dataDir)
62     {
63         mBinaryDataDir = dataDir;
64         mTraceFunctions->SetBinaryDataDir(dataDir);
65     }
66 
setDebugOutputDir(const char * dataDir)67     void setDebugOutputDir(const char *dataDir) { mDebugOutputDir = dataDir; }
68 
replayFrame(uint32_t frameIndex)69     void replayFrame(uint32_t frameIndex) { mTraceFunctions->ReplayFrame(frameIndex); }
70 
setupReplay()71     void setupReplay() { mTraceFunctions->SetupReplay(); }
72 
resetReplay()73     void resetReplay() { mTraceFunctions->ResetReplay(); }
74 
finishReplay()75     void finishReplay()
76     {
77         mTraceFunctions->FinishReplay();
78         mBinaryData = {};  // set to empty vector to release memory.
79     }
80 
setupFirstFrame()81     void setupFirstFrame() { mTraceFunctions->SetupFirstFrame(); }
82 
getSerializedContextState(uint32_t frameIndex)83     const char *getSerializedContextState(uint32_t frameIndex)
84     {
85         return callFunc<GetSerializedContextStateFunc>("GetSerializedContextState", frameIndex);
86     }
87 
setValidateSerializedStateCallback(ValidateSerializedStateCallback callback)88     void setValidateSerializedStateCallback(ValidateSerializedStateCallback callback)
89     {
90         return callFunc<SetValidateSerializedStateCallbackFunc>(
91             "SetValidateSerializedStateCallback", callback);
92     }
93 
setTraceGzPath(const std::string & traceGzPath)94     void setTraceGzPath(const std::string &traceGzPath)
95     {
96         mTraceFunctions->SetTraceGzPath(traceGzPath);
97     }
98 
99   private:
100     template <typename FuncT, typename... ArgsT>
callFunc(const char * funcName,ArgsT...args)101     typename std::invoke_result<FuncT, ArgsT...>::type callFunc(const char *funcName, ArgsT... args)
102     {
103         void *untypedFunc = mTraceLibrary->getSymbol(funcName);
104         if (!untypedFunc)
105         {
106             fprintf(stderr, "Error loading function: %s\n", funcName);
107             ASSERT(untypedFunc);
108         }
109         auto typedFunc = reinterpret_cast<FuncT>(untypedFunc);
110         return typedFunc(args...);
111     }
112 
113     uint8_t *LoadBinaryData(const char *fileName) override;
114 
115     std::unique_ptr<Library> mTraceLibrary;
116     std::vector<uint8_t> mBinaryData;
117     std::string mBinaryDataDir;
118     std::string mDebugOutputDir;
119     angle::TraceInfo mTraceInfo;
120     angle::TraceFunctions *mTraceFunctions = nullptr;
121 };
122 
123 bool LoadTraceNamesFromJSON(const std::string jsonFilePath, std::vector<std::string> *namesOut);
124 bool LoadTraceInfoFromJSON(const std::string &traceName,
125                            const std::string &traceJsonPath,
126                            TraceInfo *traceInfoOut);
127 
128 using TraceFunction    = std::vector<CallCapture>;
129 using TraceFunctionMap = std::map<std::string, TraceFunction>;
130 
131 void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &customFunctions);
132 void ReplayCustomFunctionCall(const CallCapture &call, const TraceFunctionMap &customFunctions);
133 
134 template <typename T>
135 struct AssertFalse : std::false_type
136 {};
137 
138 GLuint GetResourceIDMapValue(ResourceIDType resourceIDType, GLuint key);
139 
140 template <typename T>
141 T GetParamValue(ParamType type, const ParamValue &value);
142 
143 template <>
144 inline GLuint GetParamValue<GLuint>(ParamType type, const ParamValue &value)
145 {
146     ResourceIDType resourceIDType = GetResourceIDTypeFromParamType(type);
147     if (resourceIDType == ResourceIDType::InvalidEnum)
148     {
149         return value.GLuintVal;
150     }
151     else
152     {
153         return GetResourceIDMapValue(resourceIDType, value.GLuintVal);
154     }
155 }
156 
157 template <>
158 inline GLint GetParamValue<GLint>(ParamType type, const ParamValue &value)
159 {
160     return value.GLintVal;
161 }
162 
163 template <>
164 inline const void *GetParamValue<const void *>(ParamType type, const ParamValue &value)
165 {
166     return value.voidConstPointerVal;
167 }
168 
169 template <>
170 inline GLuint64 GetParamValue<GLuint64>(ParamType type, const ParamValue &value)
171 {
172     return value.GLuint64Val;
173 }
174 
175 template <>
176 inline GLint64 GetParamValue<GLint64>(ParamType type, const ParamValue &value)
177 {
178     return value.GLint64Val;
179 }
180 
181 template <>
182 inline const char *GetParamValue<const char *>(ParamType type, const ParamValue &value)
183 {
184     return value.GLcharConstPointerVal;
185 }
186 
187 template <>
188 inline void *GetParamValue<void *>(ParamType type, const ParamValue &value)
189 {
190     return value.voidPointerVal;
191 }
192 
193 #if defined(ANGLE_IS_64_BIT_CPU)
194 template <>
195 inline const EGLAttrib *GetParamValue<const EGLAttrib *>(ParamType type, const ParamValue &value)
196 {
197     return value.EGLAttribConstPointerVal;
198 }
199 #endif  // defined(ANGLE_IS_64_BIT_CPU)
200 
201 template <>
202 inline const EGLint *GetParamValue<const EGLint *>(ParamType type, const ParamValue &value)
203 {
204     return value.EGLintConstPointerVal;
205 }
206 
207 template <>
208 inline const GLchar *const *GetParamValue<const GLchar *const *>(ParamType type,
209                                                                  const ParamValue &value)
210 {
211     return value.GLcharConstPointerPointerVal;
212 }
213 
214 // On Apple platforms, std::is_same<uint64_t, long> is false despite being both 8 bits.
215 #if defined(ANGLE_PLATFORM_APPLE) || !defined(ANGLE_IS_64_BIT_CPU)
216 template <>
217 inline long GetParamValue<long>(ParamType type, const ParamValue &value)
218 {
219     return static_cast<long>(value.GLint64Val);
220 }
221 
222 template <>
223 inline unsigned long GetParamValue<unsigned long>(ParamType type, const ParamValue &value)
224 {
225     return static_cast<unsigned long>(value.GLuint64Val);
226 }
227 #endif  // defined(ANGLE_PLATFORM_APPLE)
228 
229 template <typename T>
GetParamValue(ParamType type,const ParamValue & value)230 T GetParamValue(ParamType type, const ParamValue &value)
231 {
232     static_assert(AssertFalse<T>::value, "No specialization for type.");
233 }
234 
235 template <typename T>
236 struct Traits;
237 
238 template <typename... Args>
239 struct Traits<void(Args...)>
240 {
241     static constexpr size_t NArgs = sizeof...(Args);
242     template <size_t Idx>
243     struct Arg
244     {
245         typedef typename std::tuple_element<Idx, std::tuple<Args...>>::type Type;
246     };
247 };
248 
249 template <typename Fn, size_t Idx>
250 using FnArg = typename Traits<Fn>::template Arg<Idx>::Type;
251 
252 template <typename Fn, size_t NArgs>
253 using EnableIfNArgs = typename std::enable_if_t<Traits<Fn>::NArgs == NArgs, int>;
254 
255 template <typename Fn, size_t Idx>
256 FnArg<Fn, Idx> Arg(const Captures &cap)
257 {
258     ASSERT(Idx < cap.size());
259     return GetParamValue<FnArg<Fn, Idx>>(cap[Idx].type, cap[Idx].value);
260 }
261 }  // namespace angle
262 
263 #endif  // UTIL_CAPTURE_FRAME_CAPTURE_TEST_UTILS_H_
264