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