• 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 interface.
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/capture/frame_capture_utils_autogen.h"
17 #include "libANGLE/entry_points_utils.h"
18 
19 namespace gl
20 {
21 enum class GLenumGroup;
22 }
23 
24 namespace angle
25 {
26 
27 using ParamData = std::vector<std::vector<uint8_t>>;
28 struct ParamCapture : angle::NonCopyable
29 {
30     ParamCapture();
31     ParamCapture(const char *nameIn, ParamType typeIn);
32     ~ParamCapture();
33 
34     ParamCapture(ParamCapture &&other);
35     ParamCapture &operator=(ParamCapture &&other);
36 
37     std::string name;
38     ParamType type;
39     ParamValue value;
40     gl::GLenumGroup enumGroup;  // only used for param type GLenum, GLboolean and GLbitfield
41     ParamData data;
42     int dataNElements           = 0;
43     int arrayClientPointerIndex = -1;
44     size_t readBufferSizeBytes  = 0;
45 };
46 
47 class ParamBuffer final : angle::NonCopyable
48 {
49   public:
50     ParamBuffer();
51     ~ParamBuffer();
52 
53     ParamBuffer(ParamBuffer &&other);
54     ParamBuffer &operator=(ParamBuffer &&other);
55 
56     template <typename T>
57     void addValueParam(const char *paramName, ParamType paramType, T paramValue);
58     template <typename T>
59     void setValueParamAtIndex(const char *paramName, ParamType paramType, T paramValue, int index);
60     template <typename T>
61     void addEnumParam(const char *paramName,
62                       gl::GLenumGroup enumGroup,
63                       ParamType paramType,
64                       T paramValue);
65 
66     ParamCapture &getParam(const char *paramName, ParamType paramType, int index);
67     const ParamCapture &getParam(const char *paramName, ParamType paramType, int index) const;
68     ParamCapture &getParamFlexName(const char *paramName1,
69                                    const char *paramName2,
70                                    ParamType paramType,
71                                    int index);
72     const ParamCapture &getParamFlexName(const char *paramName1,
73                                          const char *paramName2,
74                                          ParamType paramType,
75                                          int index) const;
getReturnValue()76     const ParamCapture &getReturnValue() const { return mReturnValueCapture; }
77 
78     void addParam(ParamCapture &&param);
79     void addReturnValue(ParamCapture &&returnValue);
hasClientArrayData()80     bool hasClientArrayData() const { return mClientArrayDataParam != -1; }
81     ParamCapture &getClientArrayPointerParameter();
getReadBufferSize()82     size_t getReadBufferSize() const { return mReadBufferSize; }
83 
getParamCaptures()84     const std::vector<ParamCapture> &getParamCaptures() const { return mParamCaptures; }
85 
86     // These helpers allow us to track the ID of the buffer that was active when
87     // MapBufferRange was called.  We'll use it during replay to track the
88     // buffer's contents, as they can be modified by the host.
setMappedBufferID(gl::BufferID bufferID)89     void setMappedBufferID(gl::BufferID bufferID) { mMappedBufferID = bufferID; }
getMappedBufferID()90     gl::BufferID getMappedBufferID() const { return mMappedBufferID; }
91 
92   private:
93     std::vector<ParamCapture> mParamCaptures;
94     ParamCapture mReturnValueCapture;
95     int mClientArrayDataParam = -1;
96     size_t mReadBufferSize    = 0;
97     gl::BufferID mMappedBufferID;
98 };
99 
100 struct CallCapture
101 {
102     CallCapture(EntryPoint entryPointIn, ParamBuffer &&paramsIn);
103     CallCapture(const std::string &customFunctionNameIn, ParamBuffer &&paramsIn);
104     ~CallCapture();
105 
106     CallCapture(CallCapture &&other);
107     CallCapture &operator=(CallCapture &&other);
108 
109     const char *name() const;
110 
111     EntryPoint entryPoint;
112     std::string customFunctionName;
113     ParamBuffer params;
114     bool isActive = true;
115 };
116 
117 class ReplayContext
118 {
119   public:
120     ReplayContext(size_t readBufferSizebytes, const gl::AttribArray<size_t> &clientArraysSizebytes);
121     ~ReplayContext();
122 
123     template <typename T>
getReadBufferPointer(const ParamCapture & param)124     T getReadBufferPointer(const ParamCapture &param)
125     {
126         ASSERT(param.readBufferSizeBytes > 0);
127         ASSERT(mReadBuffer.size() >= param.readBufferSizeBytes);
128         return reinterpret_cast<T>(mReadBuffer.data());
129     }
130     template <typename T>
getAsConstPointer(const ParamCapture & param)131     T getAsConstPointer(const ParamCapture &param)
132     {
133         if (param.arrayClientPointerIndex != -1)
134         {
135             return reinterpret_cast<T>(mClientArraysBuffer[param.arrayClientPointerIndex].data());
136         }
137 
138         if (!param.data.empty())
139         {
140             ASSERT(param.data.size() == 1);
141             return reinterpret_cast<T>(param.data[0].data());
142         }
143 
144         return nullptr;
145     }
146 
147     template <typename T>
getAsPointerConstPointer(const ParamCapture & param)148     T getAsPointerConstPointer(const ParamCapture &param)
149     {
150         static_assert(sizeof(typename std::remove_pointer<T>::type) == sizeof(uint8_t *),
151                       "pointer size not match!");
152 
153         ASSERT(!param.data.empty());
154         mPointersBuffer.clear();
155         mPointersBuffer.reserve(param.data.size());
156         for (const std::vector<uint8_t> &data : param.data)
157         {
158             mPointersBuffer.emplace_back(data.data());
159         }
160         return reinterpret_cast<T>(mPointersBuffer.data());
161     }
162 
getClientArraysBuffer()163     gl::AttribArray<std::vector<uint8_t>> &getClientArraysBuffer() { return mClientArraysBuffer; }
164 
165   private:
166     std::vector<uint8_t> mReadBuffer;
167     std::vector<const uint8_t *> mPointersBuffer;
168     gl::AttribArray<std::vector<uint8_t>> mClientArraysBuffer;
169 };
170 
171 // Helper to use unique IDs for each local data variable.
172 class DataCounters final : angle::NonCopyable
173 {
174   public:
175     DataCounters();
176     ~DataCounters();
177 
178     int getAndIncrement(EntryPoint entryPoint, const std::string &paramName);
179 
180   private:
181     // <CallName, ParamName>
182     using Counter = std::pair<EntryPoint, std::string>;
183     std::map<Counter, int> mData;
184 };
185 
186 constexpr int kStringsNotFound = -1;
187 class StringCounters final : angle::NonCopyable
188 {
189   public:
190     StringCounters();
191     ~StringCounters();
192 
193     int getStringCounter(const std::vector<std::string> &str);
194     void setStringCounter(const std::vector<std::string> &str, int &counter);
195 
196   private:
197     std::map<std::vector<std::string>, int> mStringCounterMap;
198 };
199 
200 class DataTracker final : angle::NonCopyable
201 {
202   public:
203     DataTracker();
204     ~DataTracker();
205 
getCounters()206     DataCounters &getCounters() { return mCounters; }
getStringCounters()207     StringCounters &getStringCounters() { return mStringCounters; }
208 
209   private:
210     DataCounters mCounters;
211     StringCounters mStringCounters;
212 };
213 
214 class ReplayWriter final : angle::NonCopyable
215 {
216   public:
217     ReplayWriter();
218     ~ReplayWriter();
219 
220     void setFilenamePattern(const std::string &pattern);
221     void setCaptureLabel(const std::string &label);
222     void setSourcePrologue(const std::string &prologue);
223     void setHeaderPrologue(const std::string &prologue);
224 
225     void addPublicFunction(const std::string &functionProto,
226                            const std::stringstream &headerStream,
227                            const std::stringstream &bodyStream);
228     void addPrivateFunction(const std::string &functionProto,
229                             const std::stringstream &headerStream,
230                             const std::stringstream &bodyStream);
231     std::string getInlineVariableName(EntryPoint entryPoint, const std::string &paramName);
232 
233     std::string getInlineStringSetVariableName(EntryPoint entryPoint,
234                                                const std::string &paramName,
235                                                const std::vector<std::string> &strings,
236                                                bool *isNewEntryOut);
237 
238     void saveFrame(uint32_t frameIndex);
239     void saveIndexFilesAndHeader();
240     void saveSetupFile();
241 
242     std::vector<std::string> getAndResetWrittenFiles();
243 
244   private:
245     static std::string GetVarName(EntryPoint entryPoint, const std::string &paramName, int counter);
246 
247     void saveHeader();
248     void writeReplaySource(const std::string &filename);
249     void addWrittenFile(const std::string &filename);
250 
251     DataTracker mDataTracker;
252     std::string mFilenamePattern;
253     std::string mCaptureLabel;
254     std::string mSourcePrologue;
255     std::string mHeaderPrologue;
256 
257     std::vector<std::string> mReplayHeaders;
258     std::vector<std::string> mGlobalVariableDeclarations;
259 
260     std::vector<std::string> mPublicFunctionPrototypes;
261     std::vector<std::string> mPublicFunctions;
262 
263     std::vector<std::string> mPrivateFunctionPrototypes;
264     std::vector<std::string> mPrivateFunctions;
265 
266     std::vector<std::string> mWrittenFiles;
267 };
268 
269 using BufferCalls = std::map<GLuint, std::vector<CallCapture>>;
270 
271 // true means mapped, false means unmapped
272 using BufferMapStatusMap = std::map<GLuint, bool>;
273 
274 using FenceSyncSet   = std::set<GLsync>;
275 using FenceSyncCalls = std::map<GLsync, std::vector<CallCapture>>;
276 
277 using ResourceSet   = std::set<GLuint>;
278 using ResourceCalls = std::map<GLuint, std::vector<CallCapture>>;
279 
280 class TrackedResource final : angle::NonCopyable
281 {
282   public:
283     TrackedResource();
284     ~TrackedResource();
285 
getStartingResources()286     ResourceSet &getStartingResources() { return mStartingResources; }
getNewResources()287     ResourceSet &getNewResources() { return mNewResources; }
getResourcesToRegen()288     ResourceSet &getResourcesToRegen() { return mResourcesToRegen; }
getResourcesToRestore()289     ResourceSet &getResourcesToRestore() { return mResourcesToRestore; }
290 
291     void setGennedResource(GLuint id);
292     void setDeletedResource(GLuint id);
293     void setModifiedResource(GLuint id);
294     bool resourceIsGenerated(GLuint id);
295 
getResourceRegenCalls()296     ResourceCalls &getResourceRegenCalls() { return mResourceRegenCalls; }
getResourceRestoreCalls()297     ResourceCalls &getResourceRestoreCalls() { return mResourceRestoreCalls; }
298 
299   private:
300     // Resource regen calls will delete and gen a resource
301     ResourceCalls mResourceRegenCalls;
302     // Resource restore calls will restore the contents of a resource
303     ResourceCalls mResourceRestoreCalls;
304 
305     // Resources created during startup
306     ResourceSet mStartingResources;
307 
308     // Resources created during the run that need to be deleted
309     ResourceSet mNewResources;
310     // Resources deleted during the run that need to be recreated
311     ResourceSet mResourcesToRegen;
312     // Resources modified during the run that need to be restored
313     ResourceSet mResourcesToRestore;
314 };
315 
316 using TrackedResourceArray =
317     std::array<TrackedResource, static_cast<uint32_t>(ResourceIDType::EnumCount)>;
318 
319 // Helper to track resource changes during the capture
320 class ResourceTracker final : angle::NonCopyable
321 {
322   public:
323     ResourceTracker();
324     ~ResourceTracker();
325 
getBufferMapCalls()326     BufferCalls &getBufferMapCalls() { return mBufferMapCalls; }
getBufferUnmapCalls()327     BufferCalls &getBufferUnmapCalls() { return mBufferUnmapCalls; }
328 
getBufferBindingCalls()329     std::vector<CallCapture> &getBufferBindingCalls() { return mBufferBindingCalls; }
330 
331     void setBufferMapped(GLuint id);
332     void setBufferUnmapped(GLuint id);
333 
334     bool getStartingBuffersMappedCurrent(GLuint id) const;
335     bool getStartingBuffersMappedInitial(GLuint id) const;
336 
setStartingBufferMapped(GLuint id,bool mapped)337     void setStartingBufferMapped(GLuint id, bool mapped)
338     {
339         // Track the current state (which will change throughout the trace)
340         mStartingBuffersMappedCurrent[id] = mapped;
341 
342         // And the initial state, to compare during frame loop reset
343         mStartingBuffersMappedInitial[id] = mapped;
344     }
345 
346     void onShaderProgramAccess(gl::ShaderProgramID shaderProgramID);
getMaxShaderPrograms()347     uint32_t getMaxShaderPrograms() const { return mMaxShaderPrograms; }
348 
getStartingFenceSyncs()349     FenceSyncSet &getStartingFenceSyncs() { return mStartingFenceSyncs; }
getFenceSyncRegenCalls()350     FenceSyncCalls &getFenceSyncRegenCalls() { return mFenceSyncRegenCalls; }
getFenceSyncsToRegen()351     FenceSyncSet &getFenceSyncsToRegen() { return mFenceSyncsToRegen; }
352     void setDeletedFenceSync(GLsync sync);
353 
getTrackedResource(ResourceIDType type)354     TrackedResource &getTrackedResource(ResourceIDType type)
355     {
356         return mTrackedResources[static_cast<uint32_t>(type)];
357     }
358 
359   private:
360     // Buffer map calls will map a buffer with correct offset, length, and access flags
361     BufferCalls mBufferMapCalls;
362     // Buffer unmap calls will bind and unmap a given buffer
363     BufferCalls mBufferUnmapCalls;
364 
365     // Buffer binding calls to restore bindings recorded during MEC
366     std::vector<CallCapture> mBufferBindingCalls;
367 
368     // Whether a given buffer was mapped at the start of the trace
369     BufferMapStatusMap mStartingBuffersMappedInitial;
370     // The status of buffer mapping throughout the trace, modified with each Map/Unmap call
371     BufferMapStatusMap mStartingBuffersMappedCurrent;
372 
373     // Maximum accessed shader program ID.
374     uint32_t mMaxShaderPrograms = 0;
375 
376     // Fence sync objects created during MEC setup
377     FenceSyncSet mStartingFenceSyncs;
378     // Fence sync regen calls will create a fence sync objects
379     FenceSyncCalls mFenceSyncRegenCalls;
380     // Fence syncs to regen are a list of starting fence sync objects that were deleted and need to
381     // be regen'ed.
382     FenceSyncSet mFenceSyncsToRegen;
383 
384     TrackedResourceArray mTrackedResources;
385 };
386 
387 // Used by the CPP replay to filter out unnecessary code.
388 using HasResourceTypeMap = angle::PackedEnumBitSet<ResourceIDType>;
389 
390 // Map of ResourceType to IDs and range of setup calls
391 using ResourceIDToSetupCallsMap =
392     PackedEnumMap<ResourceIDType, std::map<GLuint, gl::Range<size_t>>>;
393 
394 // Map of buffer ID to offset and size used when mapped
395 using BufferDataMap = std::map<gl::BufferID, std::pair<GLintptr, GLsizeiptr>>;
396 
397 // A dictionary of sources indexed by shader type.
398 using ProgramSources = gl::ShaderMap<std::string>;
399 
400 // Maps from IDs to sources.
401 using ShaderSourceMap  = std::map<gl::ShaderProgramID, std::string>;
402 using ProgramSourceMap = std::map<gl::ShaderProgramID, ProgramSources>;
403 
404 // Map from textureID to level and data
405 using TextureLevels       = std::map<GLint, std::vector<uint8_t>>;
406 using TextureLevelDataMap = std::map<gl::TextureID, TextureLevels>;
407 
408 struct SurfaceParams
409 {
410     gl::Extents extents;
411     egl::ColorSpace colorSpace;
412 };
413 
414 // Map from ContextID to SurfaceParams
415 using SurfaceParamsMap = std::map<gl::ContextID, SurfaceParams>;
416 
417 using CallVector = std::vector<std::vector<CallCapture> *>;
418 
419 class FrameCapture final : angle::NonCopyable
420 {
421   public:
422     FrameCapture();
423     ~FrameCapture();
424 
getSetupCalls()425     std::vector<CallCapture> &getSetupCalls() { return mSetupCalls; }
clearSetupCalls()426     void clearSetupCalls() { mSetupCalls.clear(); }
427 
428     void reset();
429 
430   private:
431     std::vector<CallCapture> mSetupCalls;
432 };
433 
434 // Shared class for any items that need to be tracked by FrameCapture across shared contexts
435 class FrameCaptureShared final : angle::NonCopyable
436 {
437   public:
438     FrameCaptureShared();
439     ~FrameCaptureShared();
440 
441     void captureCall(const gl::Context *context, CallCapture &&call, bool isCallValid);
442     void checkForCaptureTrigger();
443     void onEndFrame(const gl::Context *context);
444     void onDestroyContext(const gl::Context *context);
445     void onMakeCurrent(const gl::Context *context, const egl::Surface *drawSurface);
enabled()446     bool enabled() const { return mEnabled; }
447 
448     bool isCapturing() const;
449     void replay(gl::Context *context);
450     uint32_t getFrameCount() const;
451 
452     // Returns a frame index starting from "1" as the first frame.
453     uint32_t getReplayFrameIndex() const;
454 
455     void trackBufferMapping(CallCapture *call,
456                             gl::BufferID id,
457                             GLintptr offset,
458                             GLsizeiptr length,
459                             bool writable);
460 
461     void trackTextureUpdate(const gl::Context *context, const CallCapture &call);
462 
463     const std::string &getShaderSource(gl::ShaderProgramID id) const;
464     void setShaderSource(gl::ShaderProgramID id, std::string sources);
465 
466     const ProgramSources &getProgramSources(gl::ShaderProgramID id) const;
467     void setProgramSources(gl::ShaderProgramID id, ProgramSources sources);
468 
469     // Load data from a previously stored texture level
470     const std::vector<uint8_t> &retrieveCachedTextureLevel(gl::TextureID id,
471                                                            gl::TextureTarget target,
472                                                            GLint level);
473 
474     // Create new texture level data and copy the source into it
475     void copyCachedTextureLevel(const gl::Context *context,
476                                 gl::TextureID srcID,
477                                 GLint srcLevel,
478                                 gl::TextureID dstID,
479                                 GLint dstLevel,
480                                 const CallCapture &call);
481 
482     // Create the location that should be used to cache texture level data
483     std::vector<uint8_t> &getCachedTextureLevelData(gl::Texture *texture,
484                                                     gl::TextureTarget target,
485                                                     GLint level,
486                                                     EntryPoint entryPoint);
487 
488     // Remove any cached texture levels on deletion
489     void deleteCachedTextureLevelData(gl::TextureID id);
490 
eraseBufferDataMapEntry(const gl::BufferID bufferId)491     void eraseBufferDataMapEntry(const gl::BufferID bufferId)
492     {
493         const auto &bufferDataInfo = mBufferDataMap.find(bufferId);
494         if (bufferDataInfo != mBufferDataMap.end())
495         {
496             mBufferDataMap.erase(bufferDataInfo);
497         }
498     }
499 
hasBufferData(gl::BufferID bufferID)500     bool hasBufferData(gl::BufferID bufferID)
501     {
502         const auto &bufferDataInfo = mBufferDataMap.find(bufferID);
503         if (bufferDataInfo != mBufferDataMap.end())
504         {
505             return true;
506         }
507         return false;
508     }
509 
getBufferDataOffsetAndLength(gl::BufferID bufferID)510     std::pair<GLintptr, GLsizeiptr> getBufferDataOffsetAndLength(gl::BufferID bufferID)
511     {
512         const auto &bufferDataInfo = mBufferDataMap.find(bufferID);
513         ASSERT(bufferDataInfo != mBufferDataMap.end());
514         return bufferDataInfo->second;
515     }
516 
setCaptureActive()517     void setCaptureActive() { mCaptureActive = true; }
setCaptureInactive()518     void setCaptureInactive() { mCaptureActive = false; }
isCaptureActive()519     bool isCaptureActive() { return mCaptureActive; }
usesMidExecutionCapture()520     bool usesMidExecutionCapture() { return mCaptureStartFrame > 1; }
521 
getWindowSurfaceContextID()522     gl::ContextID getWindowSurfaceContextID() const { return mWindowSurfaceContextID; }
523 
524     void markResourceSetupCallsInactive(std::vector<CallCapture> *setupCalls,
525                                         ResourceIDType type,
526                                         GLuint id,
527                                         gl::Range<size_t> range);
528 
updateReadBufferSize(size_t readBufferSize)529     void updateReadBufferSize(size_t readBufferSize)
530     {
531         mReadBufferSize = std::max(mReadBufferSize, readBufferSize);
532     }
533 
534     template <typename ResourceType>
handleGennedResource(ResourceType resourceID)535     void handleGennedResource(ResourceType resourceID)
536     {
537         if (isCaptureActive())
538         {
539             ResourceIDType idType    = GetResourceIDTypeFromType<ResourceType>::IDType;
540             TrackedResource &tracker = mResourceTracker.getTrackedResource(idType);
541             tracker.setGennedResource(resourceID.value);
542         }
543     }
544 
545     template <typename ResourceType>
resourceIsGenerated(ResourceType resourceID)546     bool resourceIsGenerated(ResourceType resourceID)
547     {
548         ResourceIDType idType    = GetResourceIDTypeFromType<ResourceType>::IDType;
549         TrackedResource &tracker = mResourceTracker.getTrackedResource(idType);
550         return tracker.resourceIsGenerated(resourceID.value);
551     }
552 
553     template <typename ResourceType>
handleDeletedResource(ResourceType resourceID)554     void handleDeletedResource(ResourceType resourceID)
555     {
556         if (isCaptureActive())
557         {
558             ResourceIDType idType    = GetResourceIDTypeFromType<ResourceType>::IDType;
559             TrackedResource &tracker = mResourceTracker.getTrackedResource(idType);
560             tracker.setDeletedResource(resourceID.value);
561         }
562     }
563 
564   private:
565     void writeJSON(const gl::Context *context);
566     void writeCppReplayIndexFiles(const gl::Context *context, bool writeResetContextCall);
567     void writeMainContextCppReplay(const gl::Context *context,
568                                    const std::vector<CallCapture> &setupCalls);
569 
570     void captureClientArraySnapshot(const gl::Context *context,
571                                     size_t vertexCount,
572                                     size_t instanceCount);
573     void captureMappedBufferSnapshot(const gl::Context *context, const CallCapture &call);
574 
575     void copyCompressedTextureData(const gl::Context *context, const CallCapture &call);
576     void captureCompressedTextureData(const gl::Context *context, const CallCapture &call);
577 
578     void reset();
579     void maybeOverrideEntryPoint(const gl::Context *context,
580                                  CallCapture &call,
581                                  std::vector<CallCapture> &newCalls);
582     void maybeCapturePreCallUpdates(const gl::Context *context,
583                                     CallCapture &call,
584                                     std::vector<CallCapture> *shareGroupSetupCalls,
585                                     ResourceIDToSetupCallsMap *resourceIDToSetupCalls);
586     template <typename ParamValueType>
587     void maybeGenResourceOnBind(CallCapture &call);
588     void maybeCapturePostCallUpdates(const gl::Context *context);
589     void maybeCaptureDrawArraysClientData(const gl::Context *context,
590                                           CallCapture &call,
591                                           size_t instanceCount);
592     void maybeCaptureDrawElementsClientData(const gl::Context *context,
593                                             CallCapture &call,
594                                             size_t instanceCount);
595     void updateCopyImageSubData(CallCapture &call);
596     void overrideProgramBinary(const gl::Context *context,
597                                CallCapture &call,
598                                std::vector<CallCapture> &outCalls);
599     void updateResourceCountsFromParamCapture(const ParamCapture &param, ResourceIDType idType);
600     void updateResourceCountsFromCallCapture(const CallCapture &call);
601 
602     void runMidExecutionCapture(const gl::Context *context);
603 
604     void scanSetupCalls(const gl::Context *context, std::vector<CallCapture> &setupCalls);
605 
606     static void ReplayCall(gl::Context *context,
607                            ReplayContext *replayContext,
608                            const CallCapture &call);
609 
610     std::vector<CallCapture> mFrameCalls;
611     gl::ContextID mLastContextId;
612 
613     // We save one large buffer of binary data for the whole CPP replay.
614     // This simplifies a lot of file management.
615     std::vector<uint8_t> mBinaryData;
616 
617     bool mEnabled;
618     bool mSerializeStateEnabled;
619     std::string mOutDirectory;
620     std::string mCaptureLabel;
621     bool mCompression;
622     gl::AttribArray<int> mClientVertexArrayMap;
623     uint32_t mFrameIndex;
624     uint32_t mCaptureStartFrame;
625     uint32_t mCaptureEndFrame;
626     bool mIsFirstFrame   = true;
627     bool mWroteIndexFile = false;
628     SurfaceParamsMap mDrawSurfaceParams;
629     gl::AttribArray<size_t> mClientArraySizes;
630     size_t mReadBufferSize;
631     HasResourceTypeMap mHasResourceType;
632     ResourceIDToSetupCallsMap mResourceIDToSetupCalls;
633     BufferDataMap mBufferDataMap;
634     bool mValidateSerializedState = false;
635     std::string mValidationExpression;
636     bool mTrimEnabled = true;
637     PackedEnumMap<ResourceIDType, uint32_t> mMaxAccessedResourceIDs;
638 
639     ResourceTracker mResourceTracker;
640     ReplayWriter mReplayWriter;
641 
642     // If you don't know which frame you want to start capturing at, use the capture trigger.
643     // Initialize it to the number of frames you want to capture, and then clear the value to 0 when
644     // you reach the content you want to capture. Currently only available on Android.
645     uint32_t mCaptureTrigger;
646 
647     bool mCaptureActive;
648     std::vector<uint32_t> mActiveFrameIndices;
649 
650     // Cache most recently compiled and linked sources.
651     ShaderSourceMap mCachedShaderSource;
652     ProgramSourceMap mCachedProgramSources;
653 
654     // Cache a shadow copy of texture level data
655     TextureLevelDataMap mCachedTextureLevelData;
656 
657     gl::ContextID mWindowSurfaceContextID;
658 
659     std::vector<CallCapture> mShareGroupSetupCalls;
660 };
661 
662 template <typename CaptureFuncT, typename... ArgsT>
CaptureCallToFrameCapture(CaptureFuncT captureFunc,bool isCallValid,gl::Context * context,ArgsT...captureParams)663 void CaptureCallToFrameCapture(CaptureFuncT captureFunc,
664                                bool isCallValid,
665                                gl::Context *context,
666                                ArgsT... captureParams)
667 {
668     FrameCaptureShared *frameCaptureShared = context->getShareGroup()->getFrameCaptureShared();
669     if (!frameCaptureShared->isCapturing())
670     {
671         return;
672     }
673 
674     CallCapture call = captureFunc(context->getState(), isCallValid, captureParams...);
675 
676     frameCaptureShared->captureCall(context, std::move(call), isCallValid);
677 }
678 
679 template <typename T>
addValueParam(const char * paramName,ParamType paramType,T paramValue)680 void ParamBuffer::addValueParam(const char *paramName, ParamType paramType, T paramValue)
681 {
682     ParamCapture capture(paramName, paramType);
683     InitParamValue(paramType, paramValue, &capture.value);
684     mParamCaptures.emplace_back(std::move(capture));
685 }
686 
687 template <typename T>
setValueParamAtIndex(const char * paramName,ParamType paramType,T paramValue,int index)688 void ParamBuffer::setValueParamAtIndex(const char *paramName,
689                                        ParamType paramType,
690                                        T paramValue,
691                                        int index)
692 {
693     ASSERT(mParamCaptures.size() > static_cast<size_t>(index));
694 
695     ParamCapture capture(paramName, paramType);
696     InitParamValue(paramType, paramValue, &capture.value);
697     mParamCaptures[index] = std::move(capture);
698 }
699 
700 template <typename T>
addEnumParam(const char * paramName,gl::GLenumGroup enumGroup,ParamType paramType,T paramValue)701 void ParamBuffer::addEnumParam(const char *paramName,
702                                gl::GLenumGroup enumGroup,
703                                ParamType paramType,
704                                T paramValue)
705 {
706     ParamCapture capture(paramName, paramType);
707     InitParamValue(paramType, paramValue, &capture.value);
708     capture.enumGroup = enumGroup;
709     mParamCaptures.emplace_back(std::move(capture));
710 }
711 
712 // Pointer capture helpers.
713 void CaptureMemory(const void *source, size_t size, ParamCapture *paramCapture);
714 void CaptureString(const GLchar *str, ParamCapture *paramCapture);
715 void CaptureStringLimit(const GLchar *str, uint32_t limit, ParamCapture *paramCapture);
716 void CaptureVertexPointerGLES1(const gl::State &glState,
717                                gl::ClientVertexArrayType type,
718                                const void *pointer,
719                                ParamCapture *paramCapture);
720 
721 gl::Program *GetProgramForCapture(const gl::State &glState, gl::ShaderProgramID handle);
722 
723 // For GetIntegerv, GetFloatv, etc.
724 void CaptureGetParameter(const gl::State &glState,
725                          GLenum pname,
726                          size_t typeSize,
727                          ParamCapture *paramCapture);
728 
729 void CaptureGetActiveUniformBlockivParameters(const gl::State &glState,
730                                               gl::ShaderProgramID handle,
731                                               gl::UniformBlockIndex uniformBlockIndex,
732                                               GLenum pname,
733                                               ParamCapture *paramCapture);
734 
735 template <typename T>
CaptureClearBufferValue(GLenum buffer,const T * value,ParamCapture * paramCapture)736 void CaptureClearBufferValue(GLenum buffer, const T *value, ParamCapture *paramCapture)
737 {
738     // Per the spec, color buffers have a vec4, the rest a single value
739     uint32_t valueSize = (buffer == GL_COLOR) ? 4 : 1;
740     CaptureMemory(value, valueSize * sizeof(T), paramCapture);
741 }
742 
743 void CaptureGenHandlesImpl(GLsizei n, GLuint *handles, ParamCapture *paramCapture);
744 
745 template <typename T>
CaptureGenHandles(GLsizei n,T * handles,ParamCapture * paramCapture)746 void CaptureGenHandles(GLsizei n, T *handles, ParamCapture *paramCapture)
747 {
748     paramCapture->dataNElements = n;
749     CaptureGenHandlesImpl(n, reinterpret_cast<GLuint *>(handles), paramCapture);
750 }
751 
752 template <typename T>
CaptureArray(T * elements,GLsizei n,ParamCapture * paramCapture)753 void CaptureArray(T *elements, GLsizei n, ParamCapture *paramCapture)
754 {
755     paramCapture->dataNElements = n;
756     CaptureMemory(elements, n * sizeof(T), paramCapture);
757 }
758 
759 void CaptureShaderStrings(GLsizei count,
760                           const GLchar *const *strings,
761                           const GLint *length,
762                           ParamCapture *paramCapture);
763 
764 template <ParamType ParamT, typename T>
765 void WriteParamValueReplay(std::ostream &os, const CallCapture &call, T value);
766 
767 template <>
768 void WriteParamValueReplay<ParamType::TGLboolean>(std::ostream &os,
769                                                   const CallCapture &call,
770                                                   GLboolean value);
771 
772 template <>
773 void WriteParamValueReplay<ParamType::TGLbooleanPointer>(std::ostream &os,
774                                                          const CallCapture &call,
775                                                          GLboolean *value);
776 
777 template <>
778 void WriteParamValueReplay<ParamType::TvoidConstPointer>(std::ostream &os,
779                                                          const CallCapture &call,
780                                                          const void *value);
781 
782 template <>
783 void WriteParamValueReplay<ParamType::TvoidPointer>(std::ostream &os,
784                                                     const CallCapture &call,
785                                                     void *value);
786 
787 template <>
788 void WriteParamValueReplay<ParamType::TGLfloatConstPointer>(std::ostream &os,
789                                                             const CallCapture &call,
790                                                             const GLfloat *value);
791 
792 template <>
793 void WriteParamValueReplay<ParamType::TGLuintConstPointer>(std::ostream &os,
794                                                            const CallCapture &call,
795                                                            const GLuint *value);
796 
797 template <>
798 void WriteParamValueReplay<ParamType::TGLDEBUGPROCKHR>(std::ostream &os,
799                                                        const CallCapture &call,
800                                                        GLDEBUGPROCKHR value);
801 
802 template <>
803 void WriteParamValueReplay<ParamType::TGLDEBUGPROC>(std::ostream &os,
804                                                     const CallCapture &call,
805                                                     GLDEBUGPROC value);
806 
807 template <>
808 void WriteParamValueReplay<ParamType::TBufferID>(std::ostream &os,
809                                                  const CallCapture &call,
810                                                  gl::BufferID value);
811 
812 template <>
813 void WriteParamValueReplay<ParamType::TFenceNVID>(std::ostream &os,
814                                                   const CallCapture &call,
815                                                   gl::FenceNVID value);
816 
817 template <>
818 void WriteParamValueReplay<ParamType::TFramebufferID>(std::ostream &os,
819                                                       const CallCapture &call,
820                                                       gl::FramebufferID value);
821 
822 template <>
823 void WriteParamValueReplay<ParamType::TMemoryObjectID>(std::ostream &os,
824                                                        const CallCapture &call,
825                                                        gl::MemoryObjectID value);
826 
827 template <>
828 void WriteParamValueReplay<ParamType::TProgramPipelineID>(std::ostream &os,
829                                                           const CallCapture &call,
830                                                           gl::ProgramPipelineID value);
831 
832 template <>
833 void WriteParamValueReplay<ParamType::TQueryID>(std::ostream &os,
834                                                 const CallCapture &call,
835                                                 gl::QueryID value);
836 
837 template <>
838 void WriteParamValueReplay<ParamType::TRenderbufferID>(std::ostream &os,
839                                                        const CallCapture &call,
840                                                        gl::RenderbufferID value);
841 
842 template <>
843 void WriteParamValueReplay<ParamType::TSamplerID>(std::ostream &os,
844                                                   const CallCapture &call,
845                                                   gl::SamplerID value);
846 
847 template <>
848 void WriteParamValueReplay<ParamType::TSemaphoreID>(std::ostream &os,
849                                                     const CallCapture &call,
850                                                     gl::SemaphoreID value);
851 
852 template <>
853 void WriteParamValueReplay<ParamType::TShaderProgramID>(std::ostream &os,
854                                                         const CallCapture &call,
855                                                         gl::ShaderProgramID value);
856 
857 template <>
858 void WriteParamValueReplay<ParamType::TTextureID>(std::ostream &os,
859                                                   const CallCapture &call,
860                                                   gl::TextureID value);
861 
862 template <>
863 void WriteParamValueReplay<ParamType::TTransformFeedbackID>(std::ostream &os,
864                                                             const CallCapture &call,
865                                                             gl::TransformFeedbackID value);
866 
867 template <>
868 void WriteParamValueReplay<ParamType::TVertexArrayID>(std::ostream &os,
869                                                       const CallCapture &call,
870                                                       gl::VertexArrayID value);
871 
872 template <>
873 void WriteParamValueReplay<ParamType::TUniformLocation>(std::ostream &os,
874                                                         const CallCapture &call,
875                                                         gl::UniformLocation value);
876 
877 template <>
878 void WriteParamValueReplay<ParamType::TUniformBlockIndex>(std::ostream &os,
879                                                           const CallCapture &call,
880                                                           gl::UniformBlockIndex value);
881 
882 template <>
883 void WriteParamValueReplay<ParamType::TGLsync>(std::ostream &os,
884                                                const CallCapture &call,
885                                                GLsync value);
886 
887 template <>
888 void WriteParamValueReplay<ParamType::TGLeglImageOES>(std::ostream &os,
889                                                       const CallCapture &call,
890                                                       GLeglImageOES value);
891 
892 template <>
893 void WriteParamValueReplay<ParamType::TGLubyte>(std::ostream &os,
894                                                 const CallCapture &call,
895                                                 GLubyte value);
896 
897 template <>
898 void WriteParamValueReplay<ParamType::TEGLContext>(std::ostream &os,
899                                                    const CallCapture &call,
900                                                    EGLContext value);
901 
902 template <>
903 void WriteParamValueReplay<ParamType::TEGLDisplay>(std::ostream &os,
904                                                    const CallCapture &call,
905                                                    EGLContext value);
906 
907 template <>
908 void WriteParamValueReplay<ParamType::TEGLSurface>(std::ostream &os,
909                                                    const CallCapture &call,
910                                                    EGLContext value);
911 
912 template <>
913 void WriteParamValueReplay<ParamType::TEGLDEBUGPROCKHR>(std::ostream &os,
914                                                         const CallCapture &call,
915                                                         EGLDEBUGPROCKHR value);
916 
917 template <>
918 void WriteParamValueReplay<ParamType::TEGLGetBlobFuncANDROID>(std::ostream &os,
919                                                               const CallCapture &call,
920                                                               EGLGetBlobFuncANDROID value);
921 
922 template <>
923 void WriteParamValueReplay<ParamType::TEGLSetBlobFuncANDROID>(std::ostream &os,
924                                                               const CallCapture &call,
925                                                               EGLSetBlobFuncANDROID value);
926 
927 // General fallback for any unspecific type.
928 template <ParamType ParamT, typename T>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,T value)929 void WriteParamValueReplay(std::ostream &os, const CallCapture &call, T value)
930 {
931     os << value;
932 }
933 }  // namespace angle
934 
935 template <typename T>
CaptureTextureAndSamplerParameter_params(GLenum pname,const T * param,angle::ParamCapture * paramCapture)936 void CaptureTextureAndSamplerParameter_params(GLenum pname,
937                                               const T *param,
938                                               angle::ParamCapture *paramCapture)
939 {
940     if (pname == GL_TEXTURE_BORDER_COLOR || pname == GL_TEXTURE_CROP_RECT_OES)
941     {
942         CaptureMemory(param, sizeof(T) * 4, paramCapture);
943     }
944     else
945     {
946         CaptureMemory(param, sizeof(T), paramCapture);
947     }
948 }
949 
950 #endif  // LIBANGLE_FRAME_CAPTURE_H_
951