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 &¶m);
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 &¶msIn);
103 CallCapture(const std::string &customFunctionNameIn, ParamBuffer &¶msIn);
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 ¶m)
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 ¶m)
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 ¶m)
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 ¶mName);
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 ¶mName);
232
233 std::string getInlineStringSetVariableName(EntryPoint entryPoint,
234 const std::string ¶mName,
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 ¶mName, 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 ¶m, 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