• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 // Copyright 2019 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 // FrameCapture.h:
7 //   ANGLE Frame capture inteface.
8 //
9 
10 #ifndef LIBANGLE_FRAME_CAPTURE_H_
11 #define LIBANGLE_FRAME_CAPTURE_H_
12 
13 #include "common/PackedEnums.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/angletypes.h"
16 #include "libANGLE/entry_points_utils.h"
17 #include "libANGLE/frame_capture_utils_autogen.h"
18 
19 namespace gl
20 {
21 enum class GLenumGroup;
22 }
23 
24 namespace angle
25 {
26 struct ParamCapture : angle::NonCopyable
27 {
28     ParamCapture();
29     ParamCapture(const char *nameIn, ParamType typeIn);
30     ~ParamCapture();
31 
32     ParamCapture(ParamCapture &&other);
33     ParamCapture &operator=(ParamCapture &&other);
34 
35     std::string name;
36     ParamType type;
37     ParamValue value;
38     gl::GLenumGroup enumGroup;  // only used for param type GLenum, GLboolean and GLbitfield
39     std::vector<std::vector<uint8_t>> data;
40     int arrayClientPointerIndex = -1;
41     size_t readBufferSizeBytes  = 0;
42 };
43 
44 class ParamBuffer final : angle::NonCopyable
45 {
46   public:
47     ParamBuffer();
48     ~ParamBuffer();
49 
50     ParamBuffer(ParamBuffer &&other);
51     ParamBuffer &operator=(ParamBuffer &&other);
52 
53     template <typename T>
54     void addValueParam(const char *paramName, ParamType paramType, T paramValue);
55     template <typename T>
56     void addEnumParam(const char *paramName,
57                       gl::GLenumGroup enumGroup,
58                       ParamType paramType,
59                       T paramValue);
60 
61     ParamCapture &getParam(const char *paramName, ParamType paramType, int index);
62     const ParamCapture &getParam(const char *paramName, ParamType paramType, int index) const;
63     ParamCapture &getParamFlexName(const char *paramName1,
64                                    const char *paramName2,
65                                    ParamType paramType,
66                                    int index);
67     const ParamCapture &getParamFlexName(const char *paramName1,
68                                          const char *paramName2,
69                                          ParamType paramType,
70                                          int index) const;
getReturnValue()71     const ParamCapture &getReturnValue() const { return mReturnValueCapture; }
72 
73     void addParam(ParamCapture &&param);
74     void addReturnValue(ParamCapture &&returnValue);
hasClientArrayData()75     bool hasClientArrayData() const { return mClientArrayDataParam != -1; }
76     ParamCapture &getClientArrayPointerParameter();
getReadBufferSize()77     size_t getReadBufferSize() const { return mReadBufferSize; }
78 
getParamCaptures()79     const std::vector<ParamCapture> &getParamCaptures() const { return mParamCaptures; }
80 
81     // These helpers allow us to track the ID of the buffer that was active when
82     // MapBufferRange was called.  We'll use it during replay to track the
83     // buffer's contents, as they can be modified by the host.
setMappedBufferID(gl::BufferID bufferID)84     void setMappedBufferID(gl::BufferID bufferID) { mMappedBufferID = bufferID; }
getMappedBufferID()85     gl::BufferID getMappedBufferID() const { return mMappedBufferID; }
86 
87   private:
88     std::vector<ParamCapture> mParamCaptures;
89     ParamCapture mReturnValueCapture;
90     int mClientArrayDataParam = -1;
91     size_t mReadBufferSize    = 0;
92     gl::BufferID mMappedBufferID;
93 };
94 
95 struct CallCapture
96 {
97     CallCapture(gl::EntryPoint entryPointIn, ParamBuffer &&paramsIn);
98     CallCapture(const std::string &customFunctionNameIn, ParamBuffer &&paramsIn);
99     ~CallCapture();
100 
101     CallCapture(CallCapture &&other);
102     CallCapture &operator=(CallCapture &&other);
103 
104     const char *name() const;
105 
106     gl::EntryPoint entryPoint;
107     std::string customFunctionName;
108     ParamBuffer params;
109 };
110 
111 class ReplayContext
112 {
113   public:
114     ReplayContext(size_t readBufferSizebytes, const gl::AttribArray<size_t> &clientArraysSizebytes);
115     ~ReplayContext();
116 
117     template <typename T>
getReadBufferPointer(const ParamCapture & param)118     T getReadBufferPointer(const ParamCapture &param)
119     {
120         ASSERT(param.readBufferSizeBytes > 0);
121         ASSERT(mReadBuffer.size() >= param.readBufferSizeBytes);
122         return reinterpret_cast<T>(mReadBuffer.data());
123     }
124     template <typename T>
getAsConstPointer(const ParamCapture & param)125     T getAsConstPointer(const ParamCapture &param)
126     {
127         if (param.arrayClientPointerIndex != -1)
128         {
129             return reinterpret_cast<T>(mClientArraysBuffer[param.arrayClientPointerIndex].data());
130         }
131 
132         if (!param.data.empty())
133         {
134             ASSERT(param.data.size() == 1);
135             return reinterpret_cast<T>(param.data[0].data());
136         }
137 
138         return nullptr;
139     }
140 
141     template <typename T>
getAsPointerConstPointer(const ParamCapture & param)142     T getAsPointerConstPointer(const ParamCapture &param)
143     {
144         static_assert(sizeof(typename std::remove_pointer<T>::type) == sizeof(uint8_t *),
145                       "pointer size not match!");
146 
147         ASSERT(!param.data.empty());
148         mPointersBuffer.clear();
149         mPointersBuffer.reserve(param.data.size());
150         for (const std::vector<uint8_t> &data : param.data)
151         {
152             mPointersBuffer.emplace_back(data.data());
153         }
154         return reinterpret_cast<T>(mPointersBuffer.data());
155     }
156 
getClientArraysBuffer()157     gl::AttribArray<std::vector<uint8_t>> &getClientArraysBuffer() { return mClientArraysBuffer; }
158 
159   private:
160     std::vector<uint8_t> mReadBuffer;
161     std::vector<const uint8_t *> mPointersBuffer;
162     gl::AttribArray<std::vector<uint8_t>> mClientArraysBuffer;
163 };
164 
165 // Helper to use unique IDs for each local data variable.
166 class DataCounters final : angle::NonCopyable
167 {
168   public:
169     DataCounters();
170     ~DataCounters();
171 
172     int getAndIncrement(gl::EntryPoint entryPoint, const std::string &paramName);
173 
174   private:
175     // <CallName, ParamName>
176     using Counter = std::pair<gl::EntryPoint, std::string>;
177     std::map<Counter, int> mData;
178 };
179 
180 // Used by the CPP replay to filter out unnecessary code.
181 using HasResourceTypeMap = angle::PackedEnumBitSet<ResourceIDType>;
182 
183 // Map of buffer ID to offset and size used when mapped
184 using BufferDataMap = std::map<gl::BufferID, std::pair<GLintptr, GLsizeiptr>>;
185 
186 // A dictionary of sources indexed by shader type.
187 using ProgramSources = gl::ShaderMap<std::string>;
188 
189 // Maps from IDs to sources.
190 using ShaderSourceMap  = std::map<gl::ShaderProgramID, std::string>;
191 using ProgramSourceMap = std::map<gl::ShaderProgramID, ProgramSources>;
192 
193 // Map from textureID to level and data
194 using TextureLevels       = std::map<GLint, std::vector<uint8_t>>;
195 using TextureLevelDataMap = std::map<gl::TextureID, TextureLevels>;
196 
197 class FrameCapture final : angle::NonCopyable
198 {
199   public:
200     FrameCapture();
201     ~FrameCapture();
202 
203     void captureCall(const gl::Context *context, CallCapture &&call);
204     void onEndFrame(const gl::Context *context);
enabled()205     bool enabled() const { return mEnabled; }
206 
207     bool isCapturing() const;
208     void replay(gl::Context *context);
209 
210   private:
211     void captureClientArraySnapshot(const gl::Context *context,
212                                     size_t vertexCount,
213                                     size_t instanceCount);
214     void captureMappedBufferSnapshot(const gl::Context *context, const CallCapture &call);
215 
216     void captureCompressedTextureData(const gl::Context *context, const CallCapture &call);
217 
218     void reset();
219     void maybeCaptureClientData(const gl::Context *context, CallCapture &call);
220     void maybeCapturePostCallUpdates(const gl::Context *context);
221 
222     static void ReplayCall(gl::Context *context,
223                            ReplayContext *replayContext,
224                            const CallCapture &call);
225 
226     std::vector<CallCapture> mSetupCalls;
227     std::vector<CallCapture> mFrameCalls;
228     std::vector<CallCapture> mTearDownCalls;
229 
230     // We save one large buffer of binary data for the whole CPP replay.
231     // This simplifies a lot of file management.
232     std::vector<uint8_t> mBinaryData;
233 
234     bool mEnabled = false;
235     std::string mOutDirectory;
236     std::string mCaptureLabel;
237     bool mCompression;
238     gl::AttribArray<int> mClientVertexArrayMap;
239     uint32_t mFrameIndex;
240     uint32_t mFrameStart;
241     uint32_t mFrameEnd;
242     gl::AttribArray<size_t> mClientArraySizes;
243     size_t mReadBufferSize;
244     HasResourceTypeMap mHasResourceType;
245     BufferDataMap mBufferDataMap;
246 
247     // Cache most recently compiled and linked sources.
248     ShaderSourceMap mCachedShaderSources;
249     ProgramSourceMap mCachedProgramSources;
250 
251     // Cache a shadow copy of texture level data
252     TextureLevels mCachedTextureLevels;
253     TextureLevelDataMap mCachedTextureLevelData;
254 };
255 
256 template <typename CaptureFuncT, typename... ArgsT>
CaptureCallToFrameCapture(CaptureFuncT captureFunc,bool isCallValid,gl::Context * context,ArgsT...captureParams)257 void CaptureCallToFrameCapture(CaptureFuncT captureFunc,
258                                bool isCallValid,
259                                gl::Context *context,
260                                ArgsT... captureParams)
261 {
262     FrameCapture *frameCapture = context->getFrameCapture();
263     if (!frameCapture->isCapturing())
264         return;
265 
266     CallCapture call = captureFunc(context->getState(), isCallValid, captureParams...);
267     frameCapture->captureCall(context, std::move(call));
268 }
269 
270 template <typename T>
addValueParam(const char * paramName,ParamType paramType,T paramValue)271 void ParamBuffer::addValueParam(const char *paramName, ParamType paramType, T paramValue)
272 {
273     ParamCapture capture(paramName, paramType);
274     InitParamValue(paramType, paramValue, &capture.value);
275     mParamCaptures.emplace_back(std::move(capture));
276 }
277 
278 template <typename T>
addEnumParam(const char * paramName,gl::GLenumGroup enumGroup,ParamType paramType,T paramValue)279 void ParamBuffer::addEnumParam(const char *paramName,
280                                gl::GLenumGroup enumGroup,
281                                ParamType paramType,
282                                T paramValue)
283 {
284     ParamCapture capture(paramName, paramType);
285     InitParamValue(paramType, paramValue, &capture.value);
286     capture.enumGroup = enumGroup;
287     mParamCaptures.emplace_back(std::move(capture));
288 }
289 
290 std::ostream &operator<<(std::ostream &os, const ParamCapture &capture);
291 
292 // Pointer capture helpers.
293 void CaptureMemory(const void *source, size_t size, ParamCapture *paramCapture);
294 void CaptureString(const GLchar *str, ParamCapture *paramCapture);
295 void CaptureStringLimit(const GLchar *str, uint32_t limit, ParamCapture *paramCapture);
296 
297 gl::Program *GetLinkedProgramForCapture(const gl::State &glState, gl::ShaderProgramID handle);
298 
299 // For GetIntegerv, GetFloatv, etc.
300 void CaptureGetParameter(const gl::State &glState,
301                          GLenum pname,
302                          size_t typeSize,
303                          ParamCapture *paramCapture);
304 
305 void CaptureGenHandlesImpl(GLsizei n, GLuint *handles, ParamCapture *paramCapture);
306 
307 template <typename T>
CaptureGenHandles(GLsizei n,T * handles,ParamCapture * paramCapture)308 void CaptureGenHandles(GLsizei n, T *handles, ParamCapture *paramCapture)
309 {
310     CaptureGenHandlesImpl(n, reinterpret_cast<GLuint *>(handles), paramCapture);
311 }
312 
313 template <ParamType ParamT, typename T>
314 void WriteParamValueReplay(std::ostream &os, const CallCapture &call, T value);
315 
316 template <>
317 void WriteParamValueReplay<ParamType::TGLboolean>(std::ostream &os,
318                                                   const CallCapture &call,
319                                                   GLboolean value);
320 
321 template <>
322 void WriteParamValueReplay<ParamType::TvoidConstPointer>(std::ostream &os,
323                                                          const CallCapture &call,
324                                                          const void *value);
325 
326 template <>
327 void WriteParamValueReplay<ParamType::TGLDEBUGPROCKHR>(std::ostream &os,
328                                                        const CallCapture &call,
329                                                        GLDEBUGPROCKHR value);
330 
331 template <>
332 void WriteParamValueReplay<ParamType::TGLDEBUGPROC>(std::ostream &os,
333                                                     const CallCapture &call,
334                                                     GLDEBUGPROC value);
335 
336 template <>
337 void WriteParamValueReplay<ParamType::TBufferID>(std::ostream &os,
338                                                  const CallCapture &call,
339                                                  gl::BufferID value);
340 
341 template <>
342 void WriteParamValueReplay<ParamType::TFenceNVID>(std::ostream &os,
343                                                   const CallCapture &call,
344                                                   gl::FenceNVID value);
345 
346 template <>
347 void WriteParamValueReplay<ParamType::TFramebufferID>(std::ostream &os,
348                                                       const CallCapture &call,
349                                                       gl::FramebufferID value);
350 
351 template <>
352 void WriteParamValueReplay<ParamType::TMemoryObjectID>(std::ostream &os,
353                                                        const CallCapture &call,
354                                                        gl::MemoryObjectID value);
355 
356 template <>
357 void WriteParamValueReplay<ParamType::TProgramPipelineID>(std::ostream &os,
358                                                           const CallCapture &call,
359                                                           gl::ProgramPipelineID value);
360 
361 template <>
362 void WriteParamValueReplay<ParamType::TQueryID>(std::ostream &os,
363                                                 const CallCapture &call,
364                                                 gl::QueryID value);
365 
366 template <>
367 void WriteParamValueReplay<ParamType::TRenderbufferID>(std::ostream &os,
368                                                        const CallCapture &call,
369                                                        gl::RenderbufferID value);
370 
371 template <>
372 void WriteParamValueReplay<ParamType::TSamplerID>(std::ostream &os,
373                                                   const CallCapture &call,
374                                                   gl::SamplerID value);
375 
376 template <>
377 void WriteParamValueReplay<ParamType::TSemaphoreID>(std::ostream &os,
378                                                     const CallCapture &call,
379                                                     gl::SemaphoreID value);
380 
381 template <>
382 void WriteParamValueReplay<ParamType::TShaderProgramID>(std::ostream &os,
383                                                         const CallCapture &call,
384                                                         gl::ShaderProgramID value);
385 
386 template <>
387 void WriteParamValueReplay<ParamType::TTextureID>(std::ostream &os,
388                                                   const CallCapture &call,
389                                                   gl::TextureID value);
390 
391 template <>
392 void WriteParamValueReplay<ParamType::TTransformFeedbackID>(std::ostream &os,
393                                                             const CallCapture &call,
394                                                             gl::TransformFeedbackID value);
395 
396 template <>
397 void WriteParamValueReplay<ParamType::TVertexArrayID>(std::ostream &os,
398                                                       const CallCapture &call,
399                                                       gl::VertexArrayID value);
400 
401 template <>
402 void WriteParamValueReplay<ParamType::TUniformLocation>(std::ostream &os,
403                                                         const CallCapture &call,
404                                                         gl::UniformLocation value);
405 
406 template <>
407 void WriteParamValueReplay<ParamType::TGLsync>(std::ostream &os,
408                                                const CallCapture &call,
409                                                GLsync value);
410 
411 // General fallback for any unspecific type.
412 template <ParamType ParamT, typename T>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,T value)413 void WriteParamValueReplay(std::ostream &os, const CallCapture &call, T value)
414 {
415     os << value;
416 }
417 }  // namespace angle
418 
419 #endif  // LIBANGLE_FRAME_CAPTURE_H_
420