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
getSerializedContextState(uint32_t frameIndex)81 const char *getSerializedContextState(uint32_t frameIndex)
82 {
83 return callFunc<GetSerializedContextStateFunc>("GetSerializedContextState", frameIndex);
84 }
85
setValidateSerializedStateCallback(ValidateSerializedStateCallback callback)86 void setValidateSerializedStateCallback(ValidateSerializedStateCallback callback)
87 {
88 return callFunc<SetValidateSerializedStateCallbackFunc>(
89 "SetValidateSerializedStateCallback", callback);
90 }
91
setTraceGzPath(const std::string & traceGzPath)92 void setTraceGzPath(const std::string &traceGzPath)
93 {
94 mTraceFunctions->SetTraceGzPath(traceGzPath);
95 }
96
97 private:
98 template <typename FuncT, typename... ArgsT>
callFunc(const char * funcName,ArgsT...args)99 typename std::invoke_result<FuncT, ArgsT...>::type callFunc(const char *funcName, ArgsT... args)
100 {
101 void *untypedFunc = mTraceLibrary->getSymbol(funcName);
102 if (!untypedFunc)
103 {
104 fprintf(stderr, "Error loading function: %s\n", funcName);
105 ASSERT(untypedFunc);
106 }
107 auto typedFunc = reinterpret_cast<FuncT>(untypedFunc);
108 return typedFunc(args...);
109 }
110
111 uint8_t *LoadBinaryData(const char *fileName) override;
112
113 std::unique_ptr<Library> mTraceLibrary;
114 std::vector<uint8_t> mBinaryData;
115 std::string mBinaryDataDir;
116 std::string mDebugOutputDir;
117 angle::TraceInfo mTraceInfo;
118 angle::TraceFunctions *mTraceFunctions = nullptr;
119 };
120
121 bool LoadTraceNamesFromJSON(const std::string jsonFilePath, std::vector<std::string> *namesOut);
122 bool LoadTraceInfoFromJSON(const std::string &traceName,
123 const std::string &traceJsonPath,
124 TraceInfo *traceInfoOut);
125
126 using TraceFunction = std::vector<CallCapture>;
127 using TraceFunctionMap = std::map<std::string, TraceFunction>;
128
129 void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &customFunctions);
130 void ReplayCustomFunctionCall(const CallCapture &call, const TraceFunctionMap &customFunctions);
131
132 template <typename T>
133 struct AssertFalse : std::false_type
134 {};
135
136 GLuint GetResourceIDMapValue(ResourceIDType resourceIDType, GLuint key);
137
138 template <typename T>
139 T GetParamValue(ParamType type, const ParamValue &value);
140
141 template <>
142 inline GLuint GetParamValue<GLuint>(ParamType type, const ParamValue &value)
143 {
144 ResourceIDType resourceIDType = GetResourceIDTypeFromParamType(type);
145 if (resourceIDType == ResourceIDType::InvalidEnum)
146 {
147 return value.GLuintVal;
148 }
149 else
150 {
151 return GetResourceIDMapValue(resourceIDType, value.GLuintVal);
152 }
153 }
154
155 template <>
156 inline GLint GetParamValue<GLint>(ParamType type, const ParamValue &value)
157 {
158 return value.GLintVal;
159 }
160
161 template <>
162 inline const void *GetParamValue<const void *>(ParamType type, const ParamValue &value)
163 {
164 return value.voidConstPointerVal;
165 }
166
167 template <>
168 inline GLuint64 GetParamValue<GLuint64>(ParamType type, const ParamValue &value)
169 {
170 return value.GLuint64Val;
171 }
172
173 template <>
174 inline GLint64 GetParamValue<GLint64>(ParamType type, const ParamValue &value)
175 {
176 return value.GLint64Val;
177 }
178
179 template <>
180 inline const char *GetParamValue<const char *>(ParamType type, const ParamValue &value)
181 {
182 return value.GLcharConstPointerVal;
183 }
184
185 template <>
186 inline void *GetParamValue<void *>(ParamType type, const ParamValue &value)
187 {
188 return value.voidPointerVal;
189 }
190
191 #if defined(ANGLE_IS_64_BIT_CPU)
192 template <>
193 inline const EGLAttrib *GetParamValue<const EGLAttrib *>(ParamType type, const ParamValue &value)
194 {
195 return value.EGLAttribConstPointerVal;
196 }
197 #endif // defined(ANGLE_IS_64_BIT_CPU)
198
199 template <>
200 inline const EGLint *GetParamValue<const EGLint *>(ParamType type, const ParamValue &value)
201 {
202 return value.EGLintConstPointerVal;
203 }
204
205 template <>
206 inline const GLchar *const *GetParamValue<const GLchar *const *>(ParamType type,
207 const ParamValue &value)
208 {
209 return value.GLcharConstPointerPointerVal;
210 }
211
212 // On Apple platforms, std::is_same<uint64_t, long> is false despite being both 8 bits.
213 #if defined(ANGLE_PLATFORM_APPLE) || !defined(ANGLE_IS_64_BIT_CPU)
214 template <>
215 inline long GetParamValue<long>(ParamType type, const ParamValue &value)
216 {
217 return static_cast<long>(value.GLint64Val);
218 }
219
220 template <>
221 inline unsigned long GetParamValue<unsigned long>(ParamType type, const ParamValue &value)
222 {
223 return static_cast<unsigned long>(value.GLuint64Val);
224 }
225 #endif // defined(ANGLE_PLATFORM_APPLE)
226
227 template <typename T>
GetParamValue(ParamType type,const ParamValue & value)228 T GetParamValue(ParamType type, const ParamValue &value)
229 {
230 static_assert(AssertFalse<T>::value, "No specialization for type.");
231 }
232
233 template <typename T>
234 struct Traits;
235
236 template <typename... Args>
237 struct Traits<void(Args...)>
238 {
239 static constexpr size_t NArgs = sizeof...(Args);
240 template <size_t Idx>
241 struct Arg
242 {
243 typedef typename std::tuple_element<Idx, std::tuple<Args...>>::type Type;
244 };
245 };
246
247 template <typename Fn, size_t Idx>
248 using FnArg = typename Traits<Fn>::template Arg<Idx>::Type;
249
250 template <typename Fn, size_t NArgs>
251 using EnableIfNArgs = typename std::enable_if_t<Traits<Fn>::NArgs == NArgs, int>;
252
253 template <typename Fn, size_t Idx>
254 FnArg<Fn, Idx> Arg(const Captures &cap)
255 {
256 ASSERT(Idx < cap.size());
257 return GetParamValue<FnArg<Fn, Idx>>(cap[Idx].type, cap[Idx].value);
258 }
259 } // namespace angle
260
261 #endif // UTIL_CAPTURE_FRAME_CAPTURE_TEST_UTILS_H_
262