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