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