1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // FrameCapture.cpp:
7*8975f5c5SAndroid Build Coastguard Worker // ANGLE Frame capture implementation.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/capture/FrameCapture.h"
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker #include <cerrno>
13*8975f5c5SAndroid Build Coastguard Worker #include <cstring>
14*8975f5c5SAndroid Build Coastguard Worker #include <fstream>
15*8975f5c5SAndroid Build Coastguard Worker #include <queue>
16*8975f5c5SAndroid Build Coastguard Worker #include <string>
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Worker #include "sys/stat.h"
19*8975f5c5SAndroid Build Coastguard Worker
20*8975f5c5SAndroid Build Coastguard Worker #include "common/aligned_memory.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "common/angle_version_info.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "common/frame_capture_utils.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "common/gl_enum_utils.h"
24*8975f5c5SAndroid Build Coastguard Worker #include "common/mathutil.h"
25*8975f5c5SAndroid Build Coastguard Worker #include "common/serializer/JsonSerializer.h"
26*8975f5c5SAndroid Build Coastguard Worker #include "common/string_utils.h"
27*8975f5c5SAndroid Build Coastguard Worker #include "common/system_utils.h"
28*8975f5c5SAndroid Build Coastguard Worker #include "gpu_info_util/SystemInfo.h"
29*8975f5c5SAndroid Build Coastguard Worker #include "image_util/storeimage.h"
30*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Config.h"
31*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
32*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.inl.h"
33*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Display.h"
34*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/EGLSync.h"
35*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Fence.h"
36*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Framebuffer.h"
37*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/GLES1Renderer.h"
38*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Query.h"
39*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ResourceMap.h"
40*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Shader.h"
41*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Surface.h"
42*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/VertexArray.h"
43*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/capture/capture_egl_autogen.h"
44*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/capture/capture_gles_1_0_autogen.h"
45*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/capture/capture_gles_2_0_autogen.h"
46*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/capture/capture_gles_3_0_autogen.h"
47*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/capture/capture_gles_3_1_autogen.h"
48*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/capture/capture_gles_3_2_autogen.h"
49*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/capture/capture_gles_ext_autogen.h"
50*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/capture/serialize.h"
51*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/entry_points_utils.h"
52*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/queryconversions.h"
53*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/queryutils.h"
54*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/driver_utils.h"
55*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/validationEGL.h"
56*8975f5c5SAndroid Build Coastguard Worker #include "third_party/ceval/ceval.h"
57*8975f5c5SAndroid Build Coastguard Worker
58*8975f5c5SAndroid Build Coastguard Worker #define USE_SYSTEM_ZLIB
59*8975f5c5SAndroid Build Coastguard Worker #include "compression_utils_portable.h"
60*8975f5c5SAndroid Build Coastguard Worker
61*8975f5c5SAndroid Build Coastguard Worker #if !ANGLE_CAPTURE_ENABLED
62*8975f5c5SAndroid Build Coastguard Worker # error Frame capture must be enabled to include this file.
63*8975f5c5SAndroid Build Coastguard Worker #endif // !ANGLE_CAPTURE_ENABLED
64*8975f5c5SAndroid Build Coastguard Worker
65*8975f5c5SAndroid Build Coastguard Worker namespace angle
66*8975f5c5SAndroid Build Coastguard Worker {
67*8975f5c5SAndroid Build Coastguard Worker namespace
68*8975f5c5SAndroid Build Coastguard Worker {
69*8975f5c5SAndroid Build Coastguard Worker
70*8975f5c5SAndroid Build Coastguard Worker // TODO: Consolidate to C output and remove option. http://anglebug.com/42266223
71*8975f5c5SAndroid Build Coastguard Worker
72*8975f5c5SAndroid Build Coastguard Worker constexpr char kEnabledVarName[] = "ANGLE_CAPTURE_ENABLED";
73*8975f5c5SAndroid Build Coastguard Worker constexpr char kOutDirectoryVarName[] = "ANGLE_CAPTURE_OUT_DIR";
74*8975f5c5SAndroid Build Coastguard Worker constexpr char kFrameStartVarName[] = "ANGLE_CAPTURE_FRAME_START";
75*8975f5c5SAndroid Build Coastguard Worker constexpr char kFrameEndVarName[] = "ANGLE_CAPTURE_FRAME_END";
76*8975f5c5SAndroid Build Coastguard Worker constexpr char kTriggerVarName[] = "ANGLE_CAPTURE_TRIGGER";
77*8975f5c5SAndroid Build Coastguard Worker constexpr char kCaptureLabelVarName[] = "ANGLE_CAPTURE_LABEL";
78*8975f5c5SAndroid Build Coastguard Worker constexpr char kCompressionVarName[] = "ANGLE_CAPTURE_COMPRESSION";
79*8975f5c5SAndroid Build Coastguard Worker constexpr char kSerializeStateVarName[] = "ANGLE_CAPTURE_SERIALIZE_STATE";
80*8975f5c5SAndroid Build Coastguard Worker constexpr char kValidationVarName[] = "ANGLE_CAPTURE_VALIDATION";
81*8975f5c5SAndroid Build Coastguard Worker constexpr char kValidationExprVarName[] = "ANGLE_CAPTURE_VALIDATION_EXPR";
82*8975f5c5SAndroid Build Coastguard Worker constexpr char kSourceExtVarName[] = "ANGLE_CAPTURE_SOURCE_EXT";
83*8975f5c5SAndroid Build Coastguard Worker constexpr char kSourceSizeVarName[] = "ANGLE_CAPTURE_SOURCE_SIZE";
84*8975f5c5SAndroid Build Coastguard Worker constexpr char kForceShadowVarName[] = "ANGLE_CAPTURE_FORCE_SHADOW";
85*8975f5c5SAndroid Build Coastguard Worker
86*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kBinaryAlignment = 16;
87*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kFunctionSizeLimit = 5000;
88*8975f5c5SAndroid Build Coastguard Worker
89*8975f5c5SAndroid Build Coastguard Worker // Limit based on MSVC Compiler Error C2026
90*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kStringLengthLimit = 16380;
91*8975f5c5SAndroid Build Coastguard Worker
92*8975f5c5SAndroid Build Coastguard Worker // Default limit to number of bytes in a capture source files.
93*8975f5c5SAndroid Build Coastguard Worker constexpr char kDefaultSourceFileExt[] = "cpp";
94*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kDefaultSourceFileSizeThreshold = 400000;
95*8975f5c5SAndroid Build Coastguard Worker
96*8975f5c5SAndroid Build Coastguard Worker // Android debug properties that correspond to the above environment variables
97*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidEnabled[] = "debug.angle.capture.enabled";
98*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidOutDir[] = "debug.angle.capture.out_dir";
99*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidFrameStart[] = "debug.angle.capture.frame_start";
100*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidFrameEnd[] = "debug.angle.capture.frame_end";
101*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidTrigger[] = "debug.angle.capture.trigger";
102*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidCaptureLabel[] = "debug.angle.capture.label";
103*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidCompression[] = "debug.angle.capture.compression";
104*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidValidation[] = "debug.angle.capture.validation";
105*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidValidationExpr[] = "debug.angle.capture.validation_expr";
106*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidSourceExt[] = "debug.angle.capture.source_ext";
107*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidSourceSize[] = "debug.angle.capture.source_size";
108*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidForceShadow[] = "debug.angle.capture.force_shadow";
109*8975f5c5SAndroid Build Coastguard Worker
110*8975f5c5SAndroid Build Coastguard Worker struct FramebufferCaptureFuncs
111*8975f5c5SAndroid Build Coastguard Worker {
FramebufferCaptureFuncsangle::__anoncf31a3f40111::FramebufferCaptureFuncs112*8975f5c5SAndroid Build Coastguard Worker FramebufferCaptureFuncs(bool isGLES1)
113*8975f5c5SAndroid Build Coastguard Worker {
114*8975f5c5SAndroid Build Coastguard Worker if (isGLES1)
115*8975f5c5SAndroid Build Coastguard Worker {
116*8975f5c5SAndroid Build Coastguard Worker // From GL_OES_framebuffer_object
117*8975f5c5SAndroid Build Coastguard Worker framebufferTexture2D = &gl::CaptureFramebufferTexture2DOES;
118*8975f5c5SAndroid Build Coastguard Worker framebufferRenderbuffer = &gl::CaptureFramebufferRenderbufferOES;
119*8975f5c5SAndroid Build Coastguard Worker bindFramebuffer = &gl::CaptureBindFramebufferOES;
120*8975f5c5SAndroid Build Coastguard Worker genFramebuffers = &gl::CaptureGenFramebuffersOES;
121*8975f5c5SAndroid Build Coastguard Worker bindRenderbuffer = &gl::CaptureBindRenderbufferOES;
122*8975f5c5SAndroid Build Coastguard Worker genRenderbuffers = &gl::CaptureGenRenderbuffersOES;
123*8975f5c5SAndroid Build Coastguard Worker renderbufferStorage = &gl::CaptureRenderbufferStorageOES;
124*8975f5c5SAndroid Build Coastguard Worker }
125*8975f5c5SAndroid Build Coastguard Worker else
126*8975f5c5SAndroid Build Coastguard Worker {
127*8975f5c5SAndroid Build Coastguard Worker framebufferTexture2D = &gl::CaptureFramebufferTexture2D;
128*8975f5c5SAndroid Build Coastguard Worker framebufferRenderbuffer = &gl::CaptureFramebufferRenderbuffer;
129*8975f5c5SAndroid Build Coastguard Worker bindFramebuffer = &gl::CaptureBindFramebuffer;
130*8975f5c5SAndroid Build Coastguard Worker genFramebuffers = &gl::CaptureGenFramebuffers;
131*8975f5c5SAndroid Build Coastguard Worker bindRenderbuffer = &gl::CaptureBindRenderbuffer;
132*8975f5c5SAndroid Build Coastguard Worker genRenderbuffers = &gl::CaptureGenRenderbuffers;
133*8975f5c5SAndroid Build Coastguard Worker renderbufferStorage = &gl::CaptureRenderbufferStorage;
134*8975f5c5SAndroid Build Coastguard Worker }
135*8975f5c5SAndroid Build Coastguard Worker }
136*8975f5c5SAndroid Build Coastguard Worker
137*8975f5c5SAndroid Build Coastguard Worker decltype(&gl::CaptureFramebufferTexture2D) framebufferTexture2D;
138*8975f5c5SAndroid Build Coastguard Worker decltype(&gl::CaptureFramebufferRenderbuffer) framebufferRenderbuffer;
139*8975f5c5SAndroid Build Coastguard Worker decltype(&gl::CaptureBindFramebuffer) bindFramebuffer;
140*8975f5c5SAndroid Build Coastguard Worker decltype(&gl::CaptureGenFramebuffers) genFramebuffers;
141*8975f5c5SAndroid Build Coastguard Worker decltype(&gl::CaptureBindRenderbuffer) bindRenderbuffer;
142*8975f5c5SAndroid Build Coastguard Worker decltype(&gl::CaptureGenRenderbuffers) genRenderbuffers;
143*8975f5c5SAndroid Build Coastguard Worker decltype(&gl::CaptureRenderbufferStorage) renderbufferStorage;
144*8975f5c5SAndroid Build Coastguard Worker };
145*8975f5c5SAndroid Build Coastguard Worker
146*8975f5c5SAndroid Build Coastguard Worker struct VertexArrayCaptureFuncs
147*8975f5c5SAndroid Build Coastguard Worker {
VertexArrayCaptureFuncsangle::__anoncf31a3f40111::VertexArrayCaptureFuncs148*8975f5c5SAndroid Build Coastguard Worker VertexArrayCaptureFuncs(bool isGLES1)
149*8975f5c5SAndroid Build Coastguard Worker {
150*8975f5c5SAndroid Build Coastguard Worker if (isGLES1)
151*8975f5c5SAndroid Build Coastguard Worker {
152*8975f5c5SAndroid Build Coastguard Worker // From GL_OES_vertex_array_object
153*8975f5c5SAndroid Build Coastguard Worker bindVertexArray = &gl::CaptureBindVertexArrayOES;
154*8975f5c5SAndroid Build Coastguard Worker deleteVertexArrays = &gl::CaptureDeleteVertexArraysOES;
155*8975f5c5SAndroid Build Coastguard Worker genVertexArrays = &gl::CaptureGenVertexArraysOES;
156*8975f5c5SAndroid Build Coastguard Worker isVertexArray = &gl::CaptureIsVertexArrayOES;
157*8975f5c5SAndroid Build Coastguard Worker }
158*8975f5c5SAndroid Build Coastguard Worker else
159*8975f5c5SAndroid Build Coastguard Worker {
160*8975f5c5SAndroid Build Coastguard Worker bindVertexArray = &gl::CaptureBindVertexArray;
161*8975f5c5SAndroid Build Coastguard Worker deleteVertexArrays = &gl::CaptureDeleteVertexArrays;
162*8975f5c5SAndroid Build Coastguard Worker genVertexArrays = &gl::CaptureGenVertexArrays;
163*8975f5c5SAndroid Build Coastguard Worker isVertexArray = &gl::CaptureIsVertexArray;
164*8975f5c5SAndroid Build Coastguard Worker }
165*8975f5c5SAndroid Build Coastguard Worker }
166*8975f5c5SAndroid Build Coastguard Worker
167*8975f5c5SAndroid Build Coastguard Worker decltype(&gl::CaptureBindVertexArray) bindVertexArray;
168*8975f5c5SAndroid Build Coastguard Worker decltype(&gl::CaptureDeleteVertexArrays) deleteVertexArrays;
169*8975f5c5SAndroid Build Coastguard Worker decltype(&gl::CaptureGenVertexArrays) genVertexArrays;
170*8975f5c5SAndroid Build Coastguard Worker decltype(&gl::CaptureIsVertexArray) isVertexArray;
171*8975f5c5SAndroid Build Coastguard Worker };
172*8975f5c5SAndroid Build Coastguard Worker
GetDefaultOutDirectory()173*8975f5c5SAndroid Build Coastguard Worker std::string GetDefaultOutDirectory()
174*8975f5c5SAndroid Build Coastguard Worker {
175*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_ANDROID)
176*8975f5c5SAndroid Build Coastguard Worker std::string path = "/sdcard/Android/data/";
177*8975f5c5SAndroid Build Coastguard Worker
178*8975f5c5SAndroid Build Coastguard Worker // Linux interface to get application id of the running process
179*8975f5c5SAndroid Build Coastguard Worker FILE *cmdline = fopen("/proc/self/cmdline", "r");
180*8975f5c5SAndroid Build Coastguard Worker char applicationId[512];
181*8975f5c5SAndroid Build Coastguard Worker if (cmdline)
182*8975f5c5SAndroid Build Coastguard Worker {
183*8975f5c5SAndroid Build Coastguard Worker fread(applicationId, 1, sizeof(applicationId), cmdline);
184*8975f5c5SAndroid Build Coastguard Worker fclose(cmdline);
185*8975f5c5SAndroid Build Coastguard Worker
186*8975f5c5SAndroid Build Coastguard Worker // Some package may have application id as <app_name>:<cmd_name>
187*8975f5c5SAndroid Build Coastguard Worker char *colonSep = strchr(applicationId, ':');
188*8975f5c5SAndroid Build Coastguard Worker if (colonSep)
189*8975f5c5SAndroid Build Coastguard Worker {
190*8975f5c5SAndroid Build Coastguard Worker *colonSep = '\0';
191*8975f5c5SAndroid Build Coastguard Worker }
192*8975f5c5SAndroid Build Coastguard Worker }
193*8975f5c5SAndroid Build Coastguard Worker else
194*8975f5c5SAndroid Build Coastguard Worker {
195*8975f5c5SAndroid Build Coastguard Worker ERR() << "not able to lookup application id";
196*8975f5c5SAndroid Build Coastguard Worker }
197*8975f5c5SAndroid Build Coastguard Worker
198*8975f5c5SAndroid Build Coastguard Worker constexpr char kAndroidOutputSubdir[] = "/angle_capture/";
199*8975f5c5SAndroid Build Coastguard Worker path += std::string(applicationId) + kAndroidOutputSubdir;
200*8975f5c5SAndroid Build Coastguard Worker
201*8975f5c5SAndroid Build Coastguard Worker // Check for existence of output path
202*8975f5c5SAndroid Build Coastguard Worker struct stat dir_stat;
203*8975f5c5SAndroid Build Coastguard Worker if (stat(path.c_str(), &dir_stat) == -1)
204*8975f5c5SAndroid Build Coastguard Worker {
205*8975f5c5SAndroid Build Coastguard Worker ERR() << "Output directory '" << path
206*8975f5c5SAndroid Build Coastguard Worker << "' does not exist. Create it over adb using mkdir.";
207*8975f5c5SAndroid Build Coastguard Worker }
208*8975f5c5SAndroid Build Coastguard Worker
209*8975f5c5SAndroid Build Coastguard Worker return path;
210*8975f5c5SAndroid Build Coastguard Worker #else
211*8975f5c5SAndroid Build Coastguard Worker return std::string("./");
212*8975f5c5SAndroid Build Coastguard Worker #endif // defined(ANGLE_PLATFORM_ANDROID)
213*8975f5c5SAndroid Build Coastguard Worker }
214*8975f5c5SAndroid Build Coastguard Worker
GetCaptureTrigger()215*8975f5c5SAndroid Build Coastguard Worker std::string GetCaptureTrigger()
216*8975f5c5SAndroid Build Coastguard Worker {
217*8975f5c5SAndroid Build Coastguard Worker // Use the GetAndSet variant to improve future lookup times
218*8975f5c5SAndroid Build Coastguard Worker return GetAndSetEnvironmentVarOrUnCachedAndroidProperty(kTriggerVarName, kAndroidTrigger);
219*8975f5c5SAndroid Build Coastguard Worker }
220*8975f5c5SAndroid Build Coastguard Worker
operator <<(std::ostream & os,gl::ContextID contextId)221*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, gl::ContextID contextId)
222*8975f5c5SAndroid Build Coastguard Worker {
223*8975f5c5SAndroid Build Coastguard Worker os << static_cast<int>(contextId.value);
224*8975f5c5SAndroid Build Coastguard Worker return os;
225*8975f5c5SAndroid Build Coastguard Worker }
226*8975f5c5SAndroid Build Coastguard Worker
227*8975f5c5SAndroid Build Coastguard Worker // Used to indicate that "shared" should be used to identify the files.
228*8975f5c5SAndroid Build Coastguard Worker constexpr gl::ContextID kSharedContextId = {0};
229*8975f5c5SAndroid Build Coastguard Worker // Used to indicate no context ID should be output.
230*8975f5c5SAndroid Build Coastguard Worker constexpr gl::ContextID kNoContextId = {std::numeric_limits<uint32_t>::max()};
231*8975f5c5SAndroid Build Coastguard Worker
232*8975f5c5SAndroid Build Coastguard Worker struct FmtCapturePrefix
233*8975f5c5SAndroid Build Coastguard Worker {
FmtCapturePrefixangle::__anoncf31a3f40111::FmtCapturePrefix234*8975f5c5SAndroid Build Coastguard Worker FmtCapturePrefix(gl::ContextID contextIdIn, const std::string &captureLabelIn)
235*8975f5c5SAndroid Build Coastguard Worker : contextId(contextIdIn), captureLabel(captureLabelIn)
236*8975f5c5SAndroid Build Coastguard Worker {}
237*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextId;
238*8975f5c5SAndroid Build Coastguard Worker const std::string &captureLabel;
239*8975f5c5SAndroid Build Coastguard Worker };
240*8975f5c5SAndroid Build Coastguard Worker
operator <<(std::ostream & os,const FmtCapturePrefix & fmt)241*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const FmtCapturePrefix &fmt)
242*8975f5c5SAndroid Build Coastguard Worker {
243*8975f5c5SAndroid Build Coastguard Worker if (fmt.captureLabel.empty())
244*8975f5c5SAndroid Build Coastguard Worker {
245*8975f5c5SAndroid Build Coastguard Worker os << "angle_capture";
246*8975f5c5SAndroid Build Coastguard Worker }
247*8975f5c5SAndroid Build Coastguard Worker else
248*8975f5c5SAndroid Build Coastguard Worker {
249*8975f5c5SAndroid Build Coastguard Worker os << fmt.captureLabel;
250*8975f5c5SAndroid Build Coastguard Worker }
251*8975f5c5SAndroid Build Coastguard Worker
252*8975f5c5SAndroid Build Coastguard Worker if (fmt.contextId == kSharedContextId)
253*8975f5c5SAndroid Build Coastguard Worker {
254*8975f5c5SAndroid Build Coastguard Worker os << "_shared";
255*8975f5c5SAndroid Build Coastguard Worker }
256*8975f5c5SAndroid Build Coastguard Worker
257*8975f5c5SAndroid Build Coastguard Worker return os;
258*8975f5c5SAndroid Build Coastguard Worker }
259*8975f5c5SAndroid Build Coastguard Worker
260*8975f5c5SAndroid Build Coastguard Worker enum class ReplayFunc
261*8975f5c5SAndroid Build Coastguard Worker {
262*8975f5c5SAndroid Build Coastguard Worker Replay,
263*8975f5c5SAndroid Build Coastguard Worker Setup,
264*8975f5c5SAndroid Build Coastguard Worker SetupInactive,
265*8975f5c5SAndroid Build Coastguard Worker Reset,
266*8975f5c5SAndroid Build Coastguard Worker };
267*8975f5c5SAndroid Build Coastguard Worker
268*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kNoPartId = std::numeric_limits<uint32_t>::max();
269*8975f5c5SAndroid Build Coastguard Worker
270*8975f5c5SAndroid Build Coastguard Worker // In C, when you declare or define a function that takes no parameters, you must explicitly say the
271*8975f5c5SAndroid Build Coastguard Worker // function takes "void" parameters. When you're calling the function you omit this void. It's
272*8975f5c5SAndroid Build Coastguard Worker // therefore necessary to know how we're using a function to know if we should emi the "void".
273*8975f5c5SAndroid Build Coastguard Worker enum FuncUsage
274*8975f5c5SAndroid Build Coastguard Worker {
275*8975f5c5SAndroid Build Coastguard Worker Prototype,
276*8975f5c5SAndroid Build Coastguard Worker Definition,
277*8975f5c5SAndroid Build Coastguard Worker Call,
278*8975f5c5SAndroid Build Coastguard Worker };
279*8975f5c5SAndroid Build Coastguard Worker
operator <<(std::ostream & os,FuncUsage usage)280*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, FuncUsage usage)
281*8975f5c5SAndroid Build Coastguard Worker {
282*8975f5c5SAndroid Build Coastguard Worker os << "(";
283*8975f5c5SAndroid Build Coastguard Worker if (usage != FuncUsage::Call)
284*8975f5c5SAndroid Build Coastguard Worker {
285*8975f5c5SAndroid Build Coastguard Worker os << "void";
286*8975f5c5SAndroid Build Coastguard Worker }
287*8975f5c5SAndroid Build Coastguard Worker os << ")";
288*8975f5c5SAndroid Build Coastguard Worker return os;
289*8975f5c5SAndroid Build Coastguard Worker }
290*8975f5c5SAndroid Build Coastguard Worker
291*8975f5c5SAndroid Build Coastguard Worker struct FmtReplayFunction
292*8975f5c5SAndroid Build Coastguard Worker {
FmtReplayFunctionangle::__anoncf31a3f40111::FmtReplayFunction293*8975f5c5SAndroid Build Coastguard Worker FmtReplayFunction(gl::ContextID contextIdIn,
294*8975f5c5SAndroid Build Coastguard Worker FuncUsage usageIn,
295*8975f5c5SAndroid Build Coastguard Worker uint32_t frameIndexIn,
296*8975f5c5SAndroid Build Coastguard Worker uint32_t partIdIn = kNoPartId)
297*8975f5c5SAndroid Build Coastguard Worker : contextId(contextIdIn), usage(usageIn), frameIndex(frameIndexIn), partId(partIdIn)
298*8975f5c5SAndroid Build Coastguard Worker {}
299*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextId;
300*8975f5c5SAndroid Build Coastguard Worker FuncUsage usage;
301*8975f5c5SAndroid Build Coastguard Worker uint32_t frameIndex;
302*8975f5c5SAndroid Build Coastguard Worker uint32_t partId;
303*8975f5c5SAndroid Build Coastguard Worker };
304*8975f5c5SAndroid Build Coastguard Worker
operator <<(std::ostream & os,const FmtReplayFunction & fmt)305*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const FmtReplayFunction &fmt)
306*8975f5c5SAndroid Build Coastguard Worker {
307*8975f5c5SAndroid Build Coastguard Worker os << "Replay";
308*8975f5c5SAndroid Build Coastguard Worker
309*8975f5c5SAndroid Build Coastguard Worker if (fmt.contextId == kSharedContextId)
310*8975f5c5SAndroid Build Coastguard Worker {
311*8975f5c5SAndroid Build Coastguard Worker os << "Shared";
312*8975f5c5SAndroid Build Coastguard Worker }
313*8975f5c5SAndroid Build Coastguard Worker
314*8975f5c5SAndroid Build Coastguard Worker os << "Frame" << fmt.frameIndex;
315*8975f5c5SAndroid Build Coastguard Worker
316*8975f5c5SAndroid Build Coastguard Worker if (fmt.partId != kNoPartId)
317*8975f5c5SAndroid Build Coastguard Worker {
318*8975f5c5SAndroid Build Coastguard Worker os << "Part" << fmt.partId;
319*8975f5c5SAndroid Build Coastguard Worker }
320*8975f5c5SAndroid Build Coastguard Worker os << fmt.usage;
321*8975f5c5SAndroid Build Coastguard Worker return os;
322*8975f5c5SAndroid Build Coastguard Worker }
323*8975f5c5SAndroid Build Coastguard Worker
324*8975f5c5SAndroid Build Coastguard Worker struct FmtSetupFunction
325*8975f5c5SAndroid Build Coastguard Worker {
FmtSetupFunctionangle::__anoncf31a3f40111::FmtSetupFunction326*8975f5c5SAndroid Build Coastguard Worker FmtSetupFunction(uint32_t partIdIn, gl::ContextID contextIdIn, FuncUsage usageIn)
327*8975f5c5SAndroid Build Coastguard Worker : partId(partIdIn), contextId(contextIdIn), usage(usageIn)
328*8975f5c5SAndroid Build Coastguard Worker {}
329*8975f5c5SAndroid Build Coastguard Worker
330*8975f5c5SAndroid Build Coastguard Worker uint32_t partId;
331*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextId;
332*8975f5c5SAndroid Build Coastguard Worker FuncUsage usage;
333*8975f5c5SAndroid Build Coastguard Worker };
334*8975f5c5SAndroid Build Coastguard Worker
operator <<(std::ostream & os,const FmtSetupFunction & fmt)335*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const FmtSetupFunction &fmt)
336*8975f5c5SAndroid Build Coastguard Worker {
337*8975f5c5SAndroid Build Coastguard Worker os << "SetupReplayContext";
338*8975f5c5SAndroid Build Coastguard Worker
339*8975f5c5SAndroid Build Coastguard Worker if (fmt.contextId == kSharedContextId)
340*8975f5c5SAndroid Build Coastguard Worker {
341*8975f5c5SAndroid Build Coastguard Worker os << "Shared";
342*8975f5c5SAndroid Build Coastguard Worker }
343*8975f5c5SAndroid Build Coastguard Worker else
344*8975f5c5SAndroid Build Coastguard Worker {
345*8975f5c5SAndroid Build Coastguard Worker os << fmt.contextId;
346*8975f5c5SAndroid Build Coastguard Worker }
347*8975f5c5SAndroid Build Coastguard Worker
348*8975f5c5SAndroid Build Coastguard Worker if (fmt.partId != kNoPartId)
349*8975f5c5SAndroid Build Coastguard Worker {
350*8975f5c5SAndroid Build Coastguard Worker os << "Part" << fmt.partId;
351*8975f5c5SAndroid Build Coastguard Worker }
352*8975f5c5SAndroid Build Coastguard Worker os << fmt.usage;
353*8975f5c5SAndroid Build Coastguard Worker return os;
354*8975f5c5SAndroid Build Coastguard Worker }
355*8975f5c5SAndroid Build Coastguard Worker
356*8975f5c5SAndroid Build Coastguard Worker struct FmtSetupInactiveFunction
357*8975f5c5SAndroid Build Coastguard Worker {
FmtSetupInactiveFunctionangle::__anoncf31a3f40111::FmtSetupInactiveFunction358*8975f5c5SAndroid Build Coastguard Worker FmtSetupInactiveFunction(uint32_t partIdIn, gl::ContextID contextIdIn, FuncUsage usageIn)
359*8975f5c5SAndroid Build Coastguard Worker : partId(partIdIn), contextId(contextIdIn), usage(usageIn)
360*8975f5c5SAndroid Build Coastguard Worker {}
361*8975f5c5SAndroid Build Coastguard Worker
362*8975f5c5SAndroid Build Coastguard Worker uint32_t partId;
363*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextId;
364*8975f5c5SAndroid Build Coastguard Worker FuncUsage usage;
365*8975f5c5SAndroid Build Coastguard Worker };
366*8975f5c5SAndroid Build Coastguard Worker
operator <<(std::ostream & os,const FmtSetupInactiveFunction & fmt)367*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const FmtSetupInactiveFunction &fmt)
368*8975f5c5SAndroid Build Coastguard Worker {
369*8975f5c5SAndroid Build Coastguard Worker if ((fmt.usage == FuncUsage::Call) && (fmt.partId == kNoPartId))
370*8975f5c5SAndroid Build Coastguard Worker {
371*8975f5c5SAndroid Build Coastguard Worker os << "if (gReplayResourceMode == angle::ReplayResourceMode::All)\n {\n ";
372*8975f5c5SAndroid Build Coastguard Worker }
373*8975f5c5SAndroid Build Coastguard Worker os << "SetupReplayContext";
374*8975f5c5SAndroid Build Coastguard Worker
375*8975f5c5SAndroid Build Coastguard Worker if (fmt.contextId == kSharedContextId)
376*8975f5c5SAndroid Build Coastguard Worker {
377*8975f5c5SAndroid Build Coastguard Worker os << "Shared";
378*8975f5c5SAndroid Build Coastguard Worker }
379*8975f5c5SAndroid Build Coastguard Worker else
380*8975f5c5SAndroid Build Coastguard Worker {
381*8975f5c5SAndroid Build Coastguard Worker os << fmt.contextId;
382*8975f5c5SAndroid Build Coastguard Worker }
383*8975f5c5SAndroid Build Coastguard Worker
384*8975f5c5SAndroid Build Coastguard Worker os << "Inactive";
385*8975f5c5SAndroid Build Coastguard Worker
386*8975f5c5SAndroid Build Coastguard Worker if (fmt.partId != kNoPartId)
387*8975f5c5SAndroid Build Coastguard Worker {
388*8975f5c5SAndroid Build Coastguard Worker os << "Part" << fmt.partId;
389*8975f5c5SAndroid Build Coastguard Worker }
390*8975f5c5SAndroid Build Coastguard Worker
391*8975f5c5SAndroid Build Coastguard Worker os << fmt.usage;
392*8975f5c5SAndroid Build Coastguard Worker
393*8975f5c5SAndroid Build Coastguard Worker if ((fmt.usage == FuncUsage::Call) && (fmt.partId == kNoPartId))
394*8975f5c5SAndroid Build Coastguard Worker {
395*8975f5c5SAndroid Build Coastguard Worker os << ";\n }";
396*8975f5c5SAndroid Build Coastguard Worker }
397*8975f5c5SAndroid Build Coastguard Worker return os;
398*8975f5c5SAndroid Build Coastguard Worker }
399*8975f5c5SAndroid Build Coastguard Worker
400*8975f5c5SAndroid Build Coastguard Worker struct FmtResetFunction
401*8975f5c5SAndroid Build Coastguard Worker {
FmtResetFunctionangle::__anoncf31a3f40111::FmtResetFunction402*8975f5c5SAndroid Build Coastguard Worker FmtResetFunction(uint32_t partIdIn, gl::ContextID contextIdIn, FuncUsage usageIn)
403*8975f5c5SAndroid Build Coastguard Worker : partId(partIdIn), contextId(contextIdIn), usage(usageIn)
404*8975f5c5SAndroid Build Coastguard Worker {}
405*8975f5c5SAndroid Build Coastguard Worker
406*8975f5c5SAndroid Build Coastguard Worker uint32_t partId;
407*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextId;
408*8975f5c5SAndroid Build Coastguard Worker FuncUsage usage;
409*8975f5c5SAndroid Build Coastguard Worker };
410*8975f5c5SAndroid Build Coastguard Worker
operator <<(std::ostream & os,const FmtResetFunction & fmt)411*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const FmtResetFunction &fmt)
412*8975f5c5SAndroid Build Coastguard Worker {
413*8975f5c5SAndroid Build Coastguard Worker os << "ResetReplayContext";
414*8975f5c5SAndroid Build Coastguard Worker
415*8975f5c5SAndroid Build Coastguard Worker if (fmt.contextId == kSharedContextId)
416*8975f5c5SAndroid Build Coastguard Worker {
417*8975f5c5SAndroid Build Coastguard Worker os << "Shared";
418*8975f5c5SAndroid Build Coastguard Worker }
419*8975f5c5SAndroid Build Coastguard Worker else
420*8975f5c5SAndroid Build Coastguard Worker {
421*8975f5c5SAndroid Build Coastguard Worker os << fmt.contextId;
422*8975f5c5SAndroid Build Coastguard Worker }
423*8975f5c5SAndroid Build Coastguard Worker
424*8975f5c5SAndroid Build Coastguard Worker if (fmt.partId != kNoPartId)
425*8975f5c5SAndroid Build Coastguard Worker {
426*8975f5c5SAndroid Build Coastguard Worker os << "Part" << fmt.partId;
427*8975f5c5SAndroid Build Coastguard Worker }
428*8975f5c5SAndroid Build Coastguard Worker os << fmt.usage;
429*8975f5c5SAndroid Build Coastguard Worker return os;
430*8975f5c5SAndroid Build Coastguard Worker }
431*8975f5c5SAndroid Build Coastguard Worker
432*8975f5c5SAndroid Build Coastguard Worker struct FmtFunction
433*8975f5c5SAndroid Build Coastguard Worker {
FmtFunctionangle::__anoncf31a3f40111::FmtFunction434*8975f5c5SAndroid Build Coastguard Worker FmtFunction(ReplayFunc funcTypeIn,
435*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextIdIn,
436*8975f5c5SAndroid Build Coastguard Worker FuncUsage usageIn,
437*8975f5c5SAndroid Build Coastguard Worker uint32_t frameIndexIn,
438*8975f5c5SAndroid Build Coastguard Worker uint32_t partIdIn)
439*8975f5c5SAndroid Build Coastguard Worker : funcType(funcTypeIn),
440*8975f5c5SAndroid Build Coastguard Worker contextId(contextIdIn),
441*8975f5c5SAndroid Build Coastguard Worker usage(usageIn),
442*8975f5c5SAndroid Build Coastguard Worker frameIndex(frameIndexIn),
443*8975f5c5SAndroid Build Coastguard Worker partId(partIdIn)
444*8975f5c5SAndroid Build Coastguard Worker {}
445*8975f5c5SAndroid Build Coastguard Worker
446*8975f5c5SAndroid Build Coastguard Worker ReplayFunc funcType;
447*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextId;
448*8975f5c5SAndroid Build Coastguard Worker FuncUsage usage;
449*8975f5c5SAndroid Build Coastguard Worker uint32_t frameIndex;
450*8975f5c5SAndroid Build Coastguard Worker uint32_t partId;
451*8975f5c5SAndroid Build Coastguard Worker };
452*8975f5c5SAndroid Build Coastguard Worker
operator <<(std::ostream & os,const FmtFunction & fmt)453*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const FmtFunction &fmt)
454*8975f5c5SAndroid Build Coastguard Worker {
455*8975f5c5SAndroid Build Coastguard Worker switch (fmt.funcType)
456*8975f5c5SAndroid Build Coastguard Worker {
457*8975f5c5SAndroid Build Coastguard Worker case ReplayFunc::Replay:
458*8975f5c5SAndroid Build Coastguard Worker os << FmtReplayFunction(fmt.contextId, fmt.usage, fmt.frameIndex, fmt.partId);
459*8975f5c5SAndroid Build Coastguard Worker break;
460*8975f5c5SAndroid Build Coastguard Worker
461*8975f5c5SAndroid Build Coastguard Worker case ReplayFunc::Setup:
462*8975f5c5SAndroid Build Coastguard Worker os << FmtSetupFunction(fmt.partId, fmt.contextId, fmt.usage);
463*8975f5c5SAndroid Build Coastguard Worker break;
464*8975f5c5SAndroid Build Coastguard Worker
465*8975f5c5SAndroid Build Coastguard Worker case ReplayFunc::SetupInactive:
466*8975f5c5SAndroid Build Coastguard Worker os << FmtSetupInactiveFunction(fmt.partId, fmt.contextId, fmt.usage);
467*8975f5c5SAndroid Build Coastguard Worker break;
468*8975f5c5SAndroid Build Coastguard Worker
469*8975f5c5SAndroid Build Coastguard Worker case ReplayFunc::Reset:
470*8975f5c5SAndroid Build Coastguard Worker os << FmtResetFunction(fmt.partId, fmt.contextId, fmt.usage);
471*8975f5c5SAndroid Build Coastguard Worker break;
472*8975f5c5SAndroid Build Coastguard Worker
473*8975f5c5SAndroid Build Coastguard Worker default:
474*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
475*8975f5c5SAndroid Build Coastguard Worker break;
476*8975f5c5SAndroid Build Coastguard Worker }
477*8975f5c5SAndroid Build Coastguard Worker
478*8975f5c5SAndroid Build Coastguard Worker return os;
479*8975f5c5SAndroid Build Coastguard Worker }
480*8975f5c5SAndroid Build Coastguard Worker
481*8975f5c5SAndroid Build Coastguard Worker struct FmtGetSerializedContextStateFunction
482*8975f5c5SAndroid Build Coastguard Worker {
FmtGetSerializedContextStateFunctionangle::__anoncf31a3f40111::FmtGetSerializedContextStateFunction483*8975f5c5SAndroid Build Coastguard Worker FmtGetSerializedContextStateFunction(gl::ContextID contextIdIn,
484*8975f5c5SAndroid Build Coastguard Worker FuncUsage usageIn,
485*8975f5c5SAndroid Build Coastguard Worker uint32_t frameIndexIn)
486*8975f5c5SAndroid Build Coastguard Worker : contextId(contextIdIn), usage(usageIn), frameIndex(frameIndexIn)
487*8975f5c5SAndroid Build Coastguard Worker {}
488*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextId;
489*8975f5c5SAndroid Build Coastguard Worker FuncUsage usage;
490*8975f5c5SAndroid Build Coastguard Worker uint32_t frameIndex;
491*8975f5c5SAndroid Build Coastguard Worker };
492*8975f5c5SAndroid Build Coastguard Worker
operator <<(std::ostream & os,const FmtGetSerializedContextStateFunction & fmt)493*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const FmtGetSerializedContextStateFunction &fmt)
494*8975f5c5SAndroid Build Coastguard Worker {
495*8975f5c5SAndroid Build Coastguard Worker os << "GetSerializedContext" << fmt.contextId << "StateFrame" << fmt.frameIndex << "Data"
496*8975f5c5SAndroid Build Coastguard Worker << fmt.usage;
497*8975f5c5SAndroid Build Coastguard Worker return os;
498*8975f5c5SAndroid Build Coastguard Worker }
499*8975f5c5SAndroid Build Coastguard Worker
WriteGLFloatValue(std::ostream & out,GLfloat value)500*8975f5c5SAndroid Build Coastguard Worker void WriteGLFloatValue(std::ostream &out, GLfloat value)
501*8975f5c5SAndroid Build Coastguard Worker {
502*8975f5c5SAndroid Build Coastguard Worker // Check for non-representable values
503*8975f5c5SAndroid Build Coastguard Worker ASSERT(std::numeric_limits<float>::has_infinity);
504*8975f5c5SAndroid Build Coastguard Worker ASSERT(std::numeric_limits<float>::has_quiet_NaN);
505*8975f5c5SAndroid Build Coastguard Worker
506*8975f5c5SAndroid Build Coastguard Worker if (std::isinf(value))
507*8975f5c5SAndroid Build Coastguard Worker {
508*8975f5c5SAndroid Build Coastguard Worker float negativeInf = -std::numeric_limits<float>::infinity();
509*8975f5c5SAndroid Build Coastguard Worker if (value == negativeInf)
510*8975f5c5SAndroid Build Coastguard Worker {
511*8975f5c5SAndroid Build Coastguard Worker out << "-";
512*8975f5c5SAndroid Build Coastguard Worker }
513*8975f5c5SAndroid Build Coastguard Worker out << "INFINITY";
514*8975f5c5SAndroid Build Coastguard Worker }
515*8975f5c5SAndroid Build Coastguard Worker else if (std::isnan(value))
516*8975f5c5SAndroid Build Coastguard Worker {
517*8975f5c5SAndroid Build Coastguard Worker out << "NAN";
518*8975f5c5SAndroid Build Coastguard Worker }
519*8975f5c5SAndroid Build Coastguard Worker else
520*8975f5c5SAndroid Build Coastguard Worker {
521*8975f5c5SAndroid Build Coastguard Worker // Write a decimal point to preserve the zero sign on replay
522*8975f5c5SAndroid Build Coastguard Worker out << (value == 0.0 ? std::showpoint : std::noshowpoint);
523*8975f5c5SAndroid Build Coastguard Worker out << std::setprecision(16);
524*8975f5c5SAndroid Build Coastguard Worker out << value;
525*8975f5c5SAndroid Build Coastguard Worker }
526*8975f5c5SAndroid Build Coastguard Worker }
527*8975f5c5SAndroid Build Coastguard Worker
528*8975f5c5SAndroid Build Coastguard Worker template <typename T, typename CastT = T>
WriteInlineData(const std::vector<uint8_t> & vec,std::ostream & out)529*8975f5c5SAndroid Build Coastguard Worker void WriteInlineData(const std::vector<uint8_t> &vec, std::ostream &out)
530*8975f5c5SAndroid Build Coastguard Worker {
531*8975f5c5SAndroid Build Coastguard Worker const T *data = reinterpret_cast<const T *>(vec.data());
532*8975f5c5SAndroid Build Coastguard Worker size_t count = vec.size() / sizeof(T);
533*8975f5c5SAndroid Build Coastguard Worker
534*8975f5c5SAndroid Build Coastguard Worker if (data == nullptr)
535*8975f5c5SAndroid Build Coastguard Worker {
536*8975f5c5SAndroid Build Coastguard Worker return;
537*8975f5c5SAndroid Build Coastguard Worker }
538*8975f5c5SAndroid Build Coastguard Worker
539*8975f5c5SAndroid Build Coastguard Worker out << static_cast<CastT>(data[0]);
540*8975f5c5SAndroid Build Coastguard Worker
541*8975f5c5SAndroid Build Coastguard Worker for (size_t dataIndex = 1; dataIndex < count; ++dataIndex)
542*8975f5c5SAndroid Build Coastguard Worker {
543*8975f5c5SAndroid Build Coastguard Worker out << ", " << static_cast<CastT>(data[dataIndex]);
544*8975f5c5SAndroid Build Coastguard Worker }
545*8975f5c5SAndroid Build Coastguard Worker }
546*8975f5c5SAndroid Build Coastguard Worker
547*8975f5c5SAndroid Build Coastguard Worker template <>
WriteInlineData(const std::vector<uint8_t> & vec,std::ostream & out)548*8975f5c5SAndroid Build Coastguard Worker void WriteInlineData<GLchar>(const std::vector<uint8_t> &vec, std::ostream &out)
549*8975f5c5SAndroid Build Coastguard Worker {
550*8975f5c5SAndroid Build Coastguard Worker const GLchar *data = reinterpret_cast<const GLchar *>(vec.data());
551*8975f5c5SAndroid Build Coastguard Worker size_t count = vec.size() / sizeof(GLchar);
552*8975f5c5SAndroid Build Coastguard Worker
553*8975f5c5SAndroid Build Coastguard Worker if (data == nullptr || data[0] == '\0')
554*8975f5c5SAndroid Build Coastguard Worker {
555*8975f5c5SAndroid Build Coastguard Worker return;
556*8975f5c5SAndroid Build Coastguard Worker }
557*8975f5c5SAndroid Build Coastguard Worker
558*8975f5c5SAndroid Build Coastguard Worker out << "\"";
559*8975f5c5SAndroid Build Coastguard Worker
560*8975f5c5SAndroid Build Coastguard Worker for (size_t dataIndex = 0; dataIndex < count; ++dataIndex)
561*8975f5c5SAndroid Build Coastguard Worker {
562*8975f5c5SAndroid Build Coastguard Worker if (data[dataIndex] == '\0')
563*8975f5c5SAndroid Build Coastguard Worker break;
564*8975f5c5SAndroid Build Coastguard Worker
565*8975f5c5SAndroid Build Coastguard Worker out << static_cast<GLchar>(data[dataIndex]);
566*8975f5c5SAndroid Build Coastguard Worker }
567*8975f5c5SAndroid Build Coastguard Worker
568*8975f5c5SAndroid Build Coastguard Worker out << "\"";
569*8975f5c5SAndroid Build Coastguard Worker }
570*8975f5c5SAndroid Build Coastguard Worker
571*8975f5c5SAndroid Build Coastguard Worker // For compatibility with C, which does not have multi-line string literals, we break strings up
572*8975f5c5SAndroid Build Coastguard Worker // into multiple lines like:
573*8975f5c5SAndroid Build Coastguard Worker //
574*8975f5c5SAndroid Build Coastguard Worker // const char *str[] = {
575*8975f5c5SAndroid Build Coastguard Worker // "multiple\n"
576*8975f5c5SAndroid Build Coastguard Worker // "line\n"
577*8975f5c5SAndroid Build Coastguard Worker // "strings may have \"quotes\"\n"
578*8975f5c5SAndroid Build Coastguard Worker // "and \\slashes\\\n",
579*8975f5c5SAndroid Build Coastguard Worker // };
580*8975f5c5SAndroid Build Coastguard Worker //
581*8975f5c5SAndroid Build Coastguard Worker // Note we need to emit extra escapes to ensure quotes and other special characters are preserved.
582*8975f5c5SAndroid Build Coastguard Worker struct FmtMultiLineString
583*8975f5c5SAndroid Build Coastguard Worker {
FmtMultiLineStringangle::__anoncf31a3f40111::FmtMultiLineString584*8975f5c5SAndroid Build Coastguard Worker FmtMultiLineString(const std::string &str) : strings()
585*8975f5c5SAndroid Build Coastguard Worker {
586*8975f5c5SAndroid Build Coastguard Worker std::string str2;
587*8975f5c5SAndroid Build Coastguard Worker
588*8975f5c5SAndroid Build Coastguard Worker // Strip any carriage returns before splitting, for consistency
589*8975f5c5SAndroid Build Coastguard Worker if (str.find("\r") != std::string::npos)
590*8975f5c5SAndroid Build Coastguard Worker {
591*8975f5c5SAndroid Build Coastguard Worker // str is const, so have to make a copy of it first
592*8975f5c5SAndroid Build Coastguard Worker str2 = str;
593*8975f5c5SAndroid Build Coastguard Worker ReplaceAllSubstrings(&str2, "\r", "");
594*8975f5c5SAndroid Build Coastguard Worker }
595*8975f5c5SAndroid Build Coastguard Worker
596*8975f5c5SAndroid Build Coastguard Worker strings =
597*8975f5c5SAndroid Build Coastguard Worker angle::SplitString(str2.empty() ? str : str2, "\n", WhitespaceHandling::KEEP_WHITESPACE,
598*8975f5c5SAndroid Build Coastguard Worker SplitResult::SPLIT_WANT_ALL);
599*8975f5c5SAndroid Build Coastguard Worker }
600*8975f5c5SAndroid Build Coastguard Worker
601*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> strings;
602*8975f5c5SAndroid Build Coastguard Worker };
603*8975f5c5SAndroid Build Coastguard Worker
EscapeString(const std::string & string)604*8975f5c5SAndroid Build Coastguard Worker std::string EscapeString(const std::string &string)
605*8975f5c5SAndroid Build Coastguard Worker {
606*8975f5c5SAndroid Build Coastguard Worker std::stringstream strstr;
607*8975f5c5SAndroid Build Coastguard Worker
608*8975f5c5SAndroid Build Coastguard Worker for (char c : string)
609*8975f5c5SAndroid Build Coastguard Worker {
610*8975f5c5SAndroid Build Coastguard Worker if (c == '\"' || c == '\\')
611*8975f5c5SAndroid Build Coastguard Worker {
612*8975f5c5SAndroid Build Coastguard Worker strstr << "\\";
613*8975f5c5SAndroid Build Coastguard Worker }
614*8975f5c5SAndroid Build Coastguard Worker strstr << c;
615*8975f5c5SAndroid Build Coastguard Worker }
616*8975f5c5SAndroid Build Coastguard Worker
617*8975f5c5SAndroid Build Coastguard Worker return strstr.str();
618*8975f5c5SAndroid Build Coastguard Worker }
619*8975f5c5SAndroid Build Coastguard Worker
operator <<(std::ostream & ostr,const FmtMultiLineString & fmt)620*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &ostr, const FmtMultiLineString &fmt)
621*8975f5c5SAndroid Build Coastguard Worker {
622*8975f5c5SAndroid Build Coastguard Worker ASSERT(!fmt.strings.empty());
623*8975f5c5SAndroid Build Coastguard Worker bool first = true;
624*8975f5c5SAndroid Build Coastguard Worker for (const std::string &string : fmt.strings)
625*8975f5c5SAndroid Build Coastguard Worker {
626*8975f5c5SAndroid Build Coastguard Worker if (first)
627*8975f5c5SAndroid Build Coastguard Worker {
628*8975f5c5SAndroid Build Coastguard Worker first = false;
629*8975f5c5SAndroid Build Coastguard Worker }
630*8975f5c5SAndroid Build Coastguard Worker else
631*8975f5c5SAndroid Build Coastguard Worker {
632*8975f5c5SAndroid Build Coastguard Worker ostr << "\\n\"\n";
633*8975f5c5SAndroid Build Coastguard Worker }
634*8975f5c5SAndroid Build Coastguard Worker
635*8975f5c5SAndroid Build Coastguard Worker ostr << "\"" << EscapeString(string);
636*8975f5c5SAndroid Build Coastguard Worker }
637*8975f5c5SAndroid Build Coastguard Worker
638*8975f5c5SAndroid Build Coastguard Worker ostr << "\"";
639*8975f5c5SAndroid Build Coastguard Worker
640*8975f5c5SAndroid Build Coastguard Worker return ostr;
641*8975f5c5SAndroid Build Coastguard Worker }
642*8975f5c5SAndroid Build Coastguard Worker
WriteStringParamReplay(ReplayWriter & replayWriter,std::ostream & out,std::ostream & header,const CallCapture & call,const ParamCapture & param,std::vector<uint8_t> * binaryData)643*8975f5c5SAndroid Build Coastguard Worker void WriteStringParamReplay(ReplayWriter &replayWriter,
644*8975f5c5SAndroid Build Coastguard Worker std::ostream &out,
645*8975f5c5SAndroid Build Coastguard Worker std::ostream &header,
646*8975f5c5SAndroid Build Coastguard Worker const CallCapture &call,
647*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶m,
648*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> *binaryData)
649*8975f5c5SAndroid Build Coastguard Worker {
650*8975f5c5SAndroid Build Coastguard Worker const std::vector<uint8_t> &data = param.data[0];
651*8975f5c5SAndroid Build Coastguard Worker // null terminate C style string
652*8975f5c5SAndroid Build Coastguard Worker ASSERT(data.size() > 0 && data.back() == '\0');
653*8975f5c5SAndroid Build Coastguard Worker std::string str(data.begin(), data.end() - 1);
654*8975f5c5SAndroid Build Coastguard Worker
655*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kMaxInlineStringLength = 20000;
656*8975f5c5SAndroid Build Coastguard Worker if (str.size() > kMaxInlineStringLength)
657*8975f5c5SAndroid Build Coastguard Worker {
658*8975f5c5SAndroid Build Coastguard Worker // Store in binary file if the string is too long.
659*8975f5c5SAndroid Build Coastguard Worker // Round up to 16-byte boundary for cross ABI safety.
660*8975f5c5SAndroid Build Coastguard Worker size_t offset = rx::roundUpPow2(binaryData->size(), kBinaryAlignment);
661*8975f5c5SAndroid Build Coastguard Worker binaryData->resize(offset + str.size() + 1);
662*8975f5c5SAndroid Build Coastguard Worker memcpy(binaryData->data() + offset, str.data(), str.size() + 1);
663*8975f5c5SAndroid Build Coastguard Worker out << "(const char *)&gBinaryData[" << offset << "]";
664*8975f5c5SAndroid Build Coastguard Worker }
665*8975f5c5SAndroid Build Coastguard Worker else if (str.find('\n') != std::string::npos)
666*8975f5c5SAndroid Build Coastguard Worker {
667*8975f5c5SAndroid Build Coastguard Worker std::string varName = replayWriter.getInlineVariableName(call.entryPoint, param.name);
668*8975f5c5SAndroid Build Coastguard Worker header << "const char " << varName << "[] = \n" << FmtMultiLineString(str) << ";";
669*8975f5c5SAndroid Build Coastguard Worker out << varName;
670*8975f5c5SAndroid Build Coastguard Worker }
671*8975f5c5SAndroid Build Coastguard Worker else
672*8975f5c5SAndroid Build Coastguard Worker {
673*8975f5c5SAndroid Build Coastguard Worker out << "\"" << str << "\"";
674*8975f5c5SAndroid Build Coastguard Worker }
675*8975f5c5SAndroid Build Coastguard Worker }
676*8975f5c5SAndroid Build Coastguard Worker
WriteStringPointerParamReplay(ReplayWriter & replayWriter,std::ostream & out,std::ostream & header,const CallCapture & call,const ParamCapture & param)677*8975f5c5SAndroid Build Coastguard Worker void WriteStringPointerParamReplay(ReplayWriter &replayWriter,
678*8975f5c5SAndroid Build Coastguard Worker std::ostream &out,
679*8975f5c5SAndroid Build Coastguard Worker std::ostream &header,
680*8975f5c5SAndroid Build Coastguard Worker const CallCapture &call,
681*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶m)
682*8975f5c5SAndroid Build Coastguard Worker {
683*8975f5c5SAndroid Build Coastguard Worker // Concatenate the strings to ensure we get an accurate counter
684*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> strings;
685*8975f5c5SAndroid Build Coastguard Worker for (const std::vector<uint8_t> &data : param.data)
686*8975f5c5SAndroid Build Coastguard Worker {
687*8975f5c5SAndroid Build Coastguard Worker // null terminate C style string
688*8975f5c5SAndroid Build Coastguard Worker ASSERT(data.size() > 0 && data.back() == '\0');
689*8975f5c5SAndroid Build Coastguard Worker strings.emplace_back(data.begin(), data.end() - 1);
690*8975f5c5SAndroid Build Coastguard Worker }
691*8975f5c5SAndroid Build Coastguard Worker
692*8975f5c5SAndroid Build Coastguard Worker bool isNewEntry = false;
693*8975f5c5SAndroid Build Coastguard Worker std::string varName = replayWriter.getInlineStringSetVariableName(call.entryPoint, param.name,
694*8975f5c5SAndroid Build Coastguard Worker strings, &isNewEntry);
695*8975f5c5SAndroid Build Coastguard Worker
696*8975f5c5SAndroid Build Coastguard Worker if (isNewEntry)
697*8975f5c5SAndroid Build Coastguard Worker {
698*8975f5c5SAndroid Build Coastguard Worker header << "const char *const " << varName << "[] = { \n";
699*8975f5c5SAndroid Build Coastguard Worker
700*8975f5c5SAndroid Build Coastguard Worker for (const std::string &str : strings)
701*8975f5c5SAndroid Build Coastguard Worker {
702*8975f5c5SAndroid Build Coastguard Worker // Break up long strings for MSVC
703*8975f5c5SAndroid Build Coastguard Worker size_t copyLength = 0;
704*8975f5c5SAndroid Build Coastguard Worker std::string separator;
705*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < str.length(); i += kStringLengthLimit)
706*8975f5c5SAndroid Build Coastguard Worker {
707*8975f5c5SAndroid Build Coastguard Worker if ((str.length() - i) <= kStringLengthLimit)
708*8975f5c5SAndroid Build Coastguard Worker {
709*8975f5c5SAndroid Build Coastguard Worker copyLength = str.length() - i;
710*8975f5c5SAndroid Build Coastguard Worker separator = ",";
711*8975f5c5SAndroid Build Coastguard Worker }
712*8975f5c5SAndroid Build Coastguard Worker else
713*8975f5c5SAndroid Build Coastguard Worker {
714*8975f5c5SAndroid Build Coastguard Worker copyLength = kStringLengthLimit;
715*8975f5c5SAndroid Build Coastguard Worker separator = "";
716*8975f5c5SAndroid Build Coastguard Worker }
717*8975f5c5SAndroid Build Coastguard Worker
718*8975f5c5SAndroid Build Coastguard Worker header << FmtMultiLineString(str.substr(i, copyLength)) << separator << "\n";
719*8975f5c5SAndroid Build Coastguard Worker }
720*8975f5c5SAndroid Build Coastguard Worker }
721*8975f5c5SAndroid Build Coastguard Worker
722*8975f5c5SAndroid Build Coastguard Worker header << "};\n";
723*8975f5c5SAndroid Build Coastguard Worker }
724*8975f5c5SAndroid Build Coastguard Worker
725*8975f5c5SAndroid Build Coastguard Worker out << varName;
726*8975f5c5SAndroid Build Coastguard Worker }
727*8975f5c5SAndroid Build Coastguard Worker
728*8975f5c5SAndroid Build Coastguard Worker enum class Indent
729*8975f5c5SAndroid Build Coastguard Worker {
730*8975f5c5SAndroid Build Coastguard Worker Indent,
731*8975f5c5SAndroid Build Coastguard Worker NoIdent,
732*8975f5c5SAndroid Build Coastguard Worker };
733*8975f5c5SAndroid Build Coastguard Worker
UpdateResourceIDBuffer(std::ostream & out,Indent indent,size_t bufferIndex,ResourceIDType resourceIDType,gl::ContextID contextID,GLuint resourceID)734*8975f5c5SAndroid Build Coastguard Worker void UpdateResourceIDBuffer(std::ostream &out,
735*8975f5c5SAndroid Build Coastguard Worker Indent indent,
736*8975f5c5SAndroid Build Coastguard Worker size_t bufferIndex,
737*8975f5c5SAndroid Build Coastguard Worker ResourceIDType resourceIDType,
738*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextID,
739*8975f5c5SAndroid Build Coastguard Worker GLuint resourceID)
740*8975f5c5SAndroid Build Coastguard Worker {
741*8975f5c5SAndroid Build Coastguard Worker if (indent == Indent::Indent)
742*8975f5c5SAndroid Build Coastguard Worker {
743*8975f5c5SAndroid Build Coastguard Worker out << " ";
744*8975f5c5SAndroid Build Coastguard Worker }
745*8975f5c5SAndroid Build Coastguard Worker out << "UpdateResourceIDBuffer(" << bufferIndex << ", g"
746*8975f5c5SAndroid Build Coastguard Worker << GetResourceIDTypeName(resourceIDType) << "Map";
747*8975f5c5SAndroid Build Coastguard Worker if (IsTrackedPerContext(resourceIDType))
748*8975f5c5SAndroid Build Coastguard Worker {
749*8975f5c5SAndroid Build Coastguard Worker out << "PerContext[" << contextID.value << "]";
750*8975f5c5SAndroid Build Coastguard Worker }
751*8975f5c5SAndroid Build Coastguard Worker out << "[" << resourceID << "]);\n";
752*8975f5c5SAndroid Build Coastguard Worker }
753*8975f5c5SAndroid Build Coastguard Worker
754*8975f5c5SAndroid Build Coastguard Worker template <typename ParamT>
WriteResourceIDPointerParamReplay(ReplayWriter & replayWriter,std::ostream & out,std::ostream & header,const CallCapture & call,const ParamCapture & param,size_t * maxResourceIDBufferSize)755*8975f5c5SAndroid Build Coastguard Worker void WriteResourceIDPointerParamReplay(ReplayWriter &replayWriter,
756*8975f5c5SAndroid Build Coastguard Worker std::ostream &out,
757*8975f5c5SAndroid Build Coastguard Worker std::ostream &header,
758*8975f5c5SAndroid Build Coastguard Worker const CallCapture &call,
759*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶m,
760*8975f5c5SAndroid Build Coastguard Worker size_t *maxResourceIDBufferSize)
761*8975f5c5SAndroid Build Coastguard Worker {
762*8975f5c5SAndroid Build Coastguard Worker const ResourceIDType resourceIDType = GetResourceIDTypeFromParamType(param.type);
763*8975f5c5SAndroid Build Coastguard Worker ASSERT(resourceIDType != ResourceIDType::InvalidEnum);
764*8975f5c5SAndroid Build Coastguard Worker
765*8975f5c5SAndroid Build Coastguard Worker if (param.dataNElements > 0)
766*8975f5c5SAndroid Build Coastguard Worker {
767*8975f5c5SAndroid Build Coastguard Worker ASSERT(param.data.size() == 1);
768*8975f5c5SAndroid Build Coastguard Worker
769*8975f5c5SAndroid Build Coastguard Worker const ParamT *returnedIDs = reinterpret_cast<const ParamT *>(param.data[0].data());
770*8975f5c5SAndroid Build Coastguard Worker for (GLsizei resIndex = 0; resIndex < param.dataNElements; ++resIndex)
771*8975f5c5SAndroid Build Coastguard Worker {
772*8975f5c5SAndroid Build Coastguard Worker ParamT id = returnedIDs[resIndex];
773*8975f5c5SAndroid Build Coastguard Worker UpdateResourceIDBuffer(header, Indent::NoIdent, resIndex, resourceIDType,
774*8975f5c5SAndroid Build Coastguard Worker call.contextID, id.value);
775*8975f5c5SAndroid Build Coastguard Worker }
776*8975f5c5SAndroid Build Coastguard Worker
777*8975f5c5SAndroid Build Coastguard Worker *maxResourceIDBufferSize = std::max<size_t>(*maxResourceIDBufferSize, param.dataNElements);
778*8975f5c5SAndroid Build Coastguard Worker }
779*8975f5c5SAndroid Build Coastguard Worker
780*8975f5c5SAndroid Build Coastguard Worker out << "gResourceIDBuffer";
781*8975f5c5SAndroid Build Coastguard Worker }
782*8975f5c5SAndroid Build Coastguard Worker
WriteBinaryParamReplay(ReplayWriter & replayWriter,std::ostream & out,std::ostream & header,const CallCapture & call,const ParamCapture & param,std::vector<uint8_t> * binaryData)783*8975f5c5SAndroid Build Coastguard Worker void WriteBinaryParamReplay(ReplayWriter &replayWriter,
784*8975f5c5SAndroid Build Coastguard Worker std::ostream &out,
785*8975f5c5SAndroid Build Coastguard Worker std::ostream &header,
786*8975f5c5SAndroid Build Coastguard Worker const CallCapture &call,
787*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶m,
788*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> *binaryData)
789*8975f5c5SAndroid Build Coastguard Worker {
790*8975f5c5SAndroid Build Coastguard Worker std::string varName = replayWriter.getInlineVariableName(call.entryPoint, param.name);
791*8975f5c5SAndroid Build Coastguard Worker
792*8975f5c5SAndroid Build Coastguard Worker ASSERT(param.data.size() == 1);
793*8975f5c5SAndroid Build Coastguard Worker const std::vector<uint8_t> &data = param.data[0];
794*8975f5c5SAndroid Build Coastguard Worker
795*8975f5c5SAndroid Build Coastguard Worker // Only inline strings (shaders) to simplify the C code.
796*8975f5c5SAndroid Build Coastguard Worker ParamType overrideType = param.type;
797*8975f5c5SAndroid Build Coastguard Worker if (param.type == ParamType::TvoidConstPointer)
798*8975f5c5SAndroid Build Coastguard Worker {
799*8975f5c5SAndroid Build Coastguard Worker overrideType = ParamType::TGLubyteConstPointer;
800*8975f5c5SAndroid Build Coastguard Worker }
801*8975f5c5SAndroid Build Coastguard Worker if (overrideType == ParamType::TGLcharPointer)
802*8975f5c5SAndroid Build Coastguard Worker {
803*8975f5c5SAndroid Build Coastguard Worker // Inline if data is of type string
804*8975f5c5SAndroid Build Coastguard Worker std::string paramTypeString = ParamTypeToString(param.type);
805*8975f5c5SAndroid Build Coastguard Worker header << paramTypeString.substr(0, paramTypeString.length() - 1) << varName << "[] = { ";
806*8975f5c5SAndroid Build Coastguard Worker WriteInlineData<GLchar>(data, header);
807*8975f5c5SAndroid Build Coastguard Worker header << " };\n";
808*8975f5c5SAndroid Build Coastguard Worker out << varName;
809*8975f5c5SAndroid Build Coastguard Worker }
810*8975f5c5SAndroid Build Coastguard Worker else
811*8975f5c5SAndroid Build Coastguard Worker {
812*8975f5c5SAndroid Build Coastguard Worker // Store in binary file if data are not of type string
813*8975f5c5SAndroid Build Coastguard Worker // Round up to 16-byte boundary for cross ABI safety
814*8975f5c5SAndroid Build Coastguard Worker size_t offset = rx::roundUpPow2(binaryData->size(), kBinaryAlignment);
815*8975f5c5SAndroid Build Coastguard Worker binaryData->resize(offset + data.size());
816*8975f5c5SAndroid Build Coastguard Worker memcpy(binaryData->data() + offset, data.data(), data.size());
817*8975f5c5SAndroid Build Coastguard Worker out << "(" << ParamTypeToString(overrideType) << ")&gBinaryData[" << offset << "]";
818*8975f5c5SAndroid Build Coastguard Worker }
819*8975f5c5SAndroid Build Coastguard Worker }
820*8975f5c5SAndroid Build Coastguard Worker
WriteComment(std::ostream & out,const CallCapture & call)821*8975f5c5SAndroid Build Coastguard Worker void WriteComment(std::ostream &out, const CallCapture &call)
822*8975f5c5SAndroid Build Coastguard Worker {
823*8975f5c5SAndroid Build Coastguard Worker // Read the string parameter
824*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &stringParam =
825*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("comment", ParamType::TGLcharConstPointer, 0);
826*8975f5c5SAndroid Build Coastguard Worker const std::vector<uint8_t> &data = stringParam.data[0];
827*8975f5c5SAndroid Build Coastguard Worker ASSERT(data.size() > 0 && data.back() == '\0');
828*8975f5c5SAndroid Build Coastguard Worker std::string str(data.begin(), data.end() - 1);
829*8975f5c5SAndroid Build Coastguard Worker
830*8975f5c5SAndroid Build Coastguard Worker // Write the string prefixed with single line comment
831*8975f5c5SAndroid Build Coastguard Worker out << "// " << str;
832*8975f5c5SAndroid Build Coastguard Worker }
833*8975f5c5SAndroid Build Coastguard Worker
WriteCppReplayForCall(const CallCapture & call,ReplayWriter & replayWriter,std::ostream & out,std::ostream & header,std::vector<uint8_t> * binaryData,size_t * maxResourceIDBufferSize)834*8975f5c5SAndroid Build Coastguard Worker void WriteCppReplayForCall(const CallCapture &call,
835*8975f5c5SAndroid Build Coastguard Worker ReplayWriter &replayWriter,
836*8975f5c5SAndroid Build Coastguard Worker std::ostream &out,
837*8975f5c5SAndroid Build Coastguard Worker std::ostream &header,
838*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> *binaryData,
839*8975f5c5SAndroid Build Coastguard Worker size_t *maxResourceIDBufferSize)
840*8975f5c5SAndroid Build Coastguard Worker {
841*8975f5c5SAndroid Build Coastguard Worker if (call.customFunctionName == "Comment")
842*8975f5c5SAndroid Build Coastguard Worker {
843*8975f5c5SAndroid Build Coastguard Worker // Just write it directly to the file and move on
844*8975f5c5SAndroid Build Coastguard Worker WriteComment(out, call);
845*8975f5c5SAndroid Build Coastguard Worker return;
846*8975f5c5SAndroid Build Coastguard Worker }
847*8975f5c5SAndroid Build Coastguard Worker
848*8975f5c5SAndroid Build Coastguard Worker std::ostringstream callOut;
849*8975f5c5SAndroid Build Coastguard Worker
850*8975f5c5SAndroid Build Coastguard Worker callOut << call.name() << "(";
851*8975f5c5SAndroid Build Coastguard Worker
852*8975f5c5SAndroid Build Coastguard Worker bool first = true;
853*8975f5c5SAndroid Build Coastguard Worker for (const ParamCapture ¶m : call.params.getParamCaptures())
854*8975f5c5SAndroid Build Coastguard Worker {
855*8975f5c5SAndroid Build Coastguard Worker if (!first)
856*8975f5c5SAndroid Build Coastguard Worker {
857*8975f5c5SAndroid Build Coastguard Worker callOut << ", ";
858*8975f5c5SAndroid Build Coastguard Worker }
859*8975f5c5SAndroid Build Coastguard Worker
860*8975f5c5SAndroid Build Coastguard Worker if (param.arrayClientPointerIndex != -1 && param.value.voidConstPointerVal != nullptr)
861*8975f5c5SAndroid Build Coastguard Worker {
862*8975f5c5SAndroid Build Coastguard Worker callOut << "gClientArrays[" << param.arrayClientPointerIndex << "]";
863*8975f5c5SAndroid Build Coastguard Worker }
864*8975f5c5SAndroid Build Coastguard Worker else if (param.readBufferSizeBytes > 0)
865*8975f5c5SAndroid Build Coastguard Worker {
866*8975f5c5SAndroid Build Coastguard Worker callOut << "(" << ParamTypeToString(param.type) << ")gReadBuffer";
867*8975f5c5SAndroid Build Coastguard Worker }
868*8975f5c5SAndroid Build Coastguard Worker else if (param.data.empty())
869*8975f5c5SAndroid Build Coastguard Worker {
870*8975f5c5SAndroid Build Coastguard Worker if (param.type == ParamType::TGLenum)
871*8975f5c5SAndroid Build Coastguard Worker {
872*8975f5c5SAndroid Build Coastguard Worker OutputGLenumString(callOut, param.enumGroup, param.value.GLenumVal);
873*8975f5c5SAndroid Build Coastguard Worker }
874*8975f5c5SAndroid Build Coastguard Worker else if (param.type == ParamType::TGLbitfield)
875*8975f5c5SAndroid Build Coastguard Worker {
876*8975f5c5SAndroid Build Coastguard Worker OutputGLbitfieldString(callOut, param.enumGroup, param.value.GLbitfieldVal);
877*8975f5c5SAndroid Build Coastguard Worker }
878*8975f5c5SAndroid Build Coastguard Worker else if (param.type == ParamType::TGLfloat)
879*8975f5c5SAndroid Build Coastguard Worker {
880*8975f5c5SAndroid Build Coastguard Worker WriteGLFloatValue(callOut, param.value.GLfloatVal);
881*8975f5c5SAndroid Build Coastguard Worker }
882*8975f5c5SAndroid Build Coastguard Worker else if (param.type == ParamType::TGLsync)
883*8975f5c5SAndroid Build Coastguard Worker {
884*8975f5c5SAndroid Build Coastguard Worker callOut << "gSyncMap[" << FmtPointerIndex(param.value.GLsyncVal) << "]";
885*8975f5c5SAndroid Build Coastguard Worker }
886*8975f5c5SAndroid Build Coastguard Worker else if (param.type == ParamType::TGLuint64 && param.name == "timeout")
887*8975f5c5SAndroid Build Coastguard Worker {
888*8975f5c5SAndroid Build Coastguard Worker if (param.value.GLuint64Val == GL_TIMEOUT_IGNORED)
889*8975f5c5SAndroid Build Coastguard Worker {
890*8975f5c5SAndroid Build Coastguard Worker callOut << "GL_TIMEOUT_IGNORED";
891*8975f5c5SAndroid Build Coastguard Worker }
892*8975f5c5SAndroid Build Coastguard Worker else
893*8975f5c5SAndroid Build Coastguard Worker {
894*8975f5c5SAndroid Build Coastguard Worker WriteParamCaptureReplay(callOut, call, param);
895*8975f5c5SAndroid Build Coastguard Worker }
896*8975f5c5SAndroid Build Coastguard Worker }
897*8975f5c5SAndroid Build Coastguard Worker else
898*8975f5c5SAndroid Build Coastguard Worker {
899*8975f5c5SAndroid Build Coastguard Worker WriteParamCaptureReplay(callOut, call, param);
900*8975f5c5SAndroid Build Coastguard Worker }
901*8975f5c5SAndroid Build Coastguard Worker }
902*8975f5c5SAndroid Build Coastguard Worker else
903*8975f5c5SAndroid Build Coastguard Worker {
904*8975f5c5SAndroid Build Coastguard Worker switch (param.type)
905*8975f5c5SAndroid Build Coastguard Worker {
906*8975f5c5SAndroid Build Coastguard Worker case ParamType::TGLcharConstPointer:
907*8975f5c5SAndroid Build Coastguard Worker WriteStringParamReplay(replayWriter, callOut, header, call, param, binaryData);
908*8975f5c5SAndroid Build Coastguard Worker break;
909*8975f5c5SAndroid Build Coastguard Worker case ParamType::TGLcharConstPointerPointer:
910*8975f5c5SAndroid Build Coastguard Worker WriteStringPointerParamReplay(replayWriter, callOut, header, call, param);
911*8975f5c5SAndroid Build Coastguard Worker break;
912*8975f5c5SAndroid Build Coastguard Worker case ParamType::TBufferIDConstPointer:
913*8975f5c5SAndroid Build Coastguard Worker WriteResourceIDPointerParamReplay<gl::BufferID>(
914*8975f5c5SAndroid Build Coastguard Worker replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
915*8975f5c5SAndroid Build Coastguard Worker break;
916*8975f5c5SAndroid Build Coastguard Worker case ParamType::TFenceNVIDConstPointer:
917*8975f5c5SAndroid Build Coastguard Worker WriteResourceIDPointerParamReplay<gl::FenceNVID>(
918*8975f5c5SAndroid Build Coastguard Worker replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
919*8975f5c5SAndroid Build Coastguard Worker break;
920*8975f5c5SAndroid Build Coastguard Worker case ParamType::TFramebufferIDConstPointer:
921*8975f5c5SAndroid Build Coastguard Worker WriteResourceIDPointerParamReplay<gl::FramebufferID>(
922*8975f5c5SAndroid Build Coastguard Worker replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
923*8975f5c5SAndroid Build Coastguard Worker break;
924*8975f5c5SAndroid Build Coastguard Worker case ParamType::TMemoryObjectIDConstPointer:
925*8975f5c5SAndroid Build Coastguard Worker WriteResourceIDPointerParamReplay<gl::MemoryObjectID>(
926*8975f5c5SAndroid Build Coastguard Worker replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
927*8975f5c5SAndroid Build Coastguard Worker break;
928*8975f5c5SAndroid Build Coastguard Worker case ParamType::TProgramPipelineIDConstPointer:
929*8975f5c5SAndroid Build Coastguard Worker WriteResourceIDPointerParamReplay<gl::ProgramPipelineID>(
930*8975f5c5SAndroid Build Coastguard Worker replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
931*8975f5c5SAndroid Build Coastguard Worker break;
932*8975f5c5SAndroid Build Coastguard Worker case ParamType::TQueryIDConstPointer:
933*8975f5c5SAndroid Build Coastguard Worker WriteResourceIDPointerParamReplay<gl::QueryID>(replayWriter, callOut, out, call,
934*8975f5c5SAndroid Build Coastguard Worker param, maxResourceIDBufferSize);
935*8975f5c5SAndroid Build Coastguard Worker break;
936*8975f5c5SAndroid Build Coastguard Worker case ParamType::TRenderbufferIDConstPointer:
937*8975f5c5SAndroid Build Coastguard Worker WriteResourceIDPointerParamReplay<gl::RenderbufferID>(
938*8975f5c5SAndroid Build Coastguard Worker replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
939*8975f5c5SAndroid Build Coastguard Worker break;
940*8975f5c5SAndroid Build Coastguard Worker case ParamType::TSamplerIDConstPointer:
941*8975f5c5SAndroid Build Coastguard Worker WriteResourceIDPointerParamReplay<gl::SamplerID>(
942*8975f5c5SAndroid Build Coastguard Worker replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
943*8975f5c5SAndroid Build Coastguard Worker break;
944*8975f5c5SAndroid Build Coastguard Worker case ParamType::TSemaphoreIDConstPointer:
945*8975f5c5SAndroid Build Coastguard Worker WriteResourceIDPointerParamReplay<gl::SemaphoreID>(
946*8975f5c5SAndroid Build Coastguard Worker replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
947*8975f5c5SAndroid Build Coastguard Worker break;
948*8975f5c5SAndroid Build Coastguard Worker case ParamType::TTextureIDConstPointer:
949*8975f5c5SAndroid Build Coastguard Worker WriteResourceIDPointerParamReplay<gl::TextureID>(
950*8975f5c5SAndroid Build Coastguard Worker replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
951*8975f5c5SAndroid Build Coastguard Worker break;
952*8975f5c5SAndroid Build Coastguard Worker case ParamType::TTransformFeedbackIDConstPointer:
953*8975f5c5SAndroid Build Coastguard Worker WriteResourceIDPointerParamReplay<gl::TransformFeedbackID>(
954*8975f5c5SAndroid Build Coastguard Worker replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
955*8975f5c5SAndroid Build Coastguard Worker break;
956*8975f5c5SAndroid Build Coastguard Worker case ParamType::TVertexArrayIDConstPointer:
957*8975f5c5SAndroid Build Coastguard Worker WriteResourceIDPointerParamReplay<gl::VertexArrayID>(
958*8975f5c5SAndroid Build Coastguard Worker replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
959*8975f5c5SAndroid Build Coastguard Worker break;
960*8975f5c5SAndroid Build Coastguard Worker default:
961*8975f5c5SAndroid Build Coastguard Worker WriteBinaryParamReplay(replayWriter, callOut, header, call, param, binaryData);
962*8975f5c5SAndroid Build Coastguard Worker break;
963*8975f5c5SAndroid Build Coastguard Worker }
964*8975f5c5SAndroid Build Coastguard Worker }
965*8975f5c5SAndroid Build Coastguard Worker
966*8975f5c5SAndroid Build Coastguard Worker first = false;
967*8975f5c5SAndroid Build Coastguard Worker }
968*8975f5c5SAndroid Build Coastguard Worker
969*8975f5c5SAndroid Build Coastguard Worker callOut << ")";
970*8975f5c5SAndroid Build Coastguard Worker
971*8975f5c5SAndroid Build Coastguard Worker out << callOut.str();
972*8975f5c5SAndroid Build Coastguard Worker }
973*8975f5c5SAndroid Build Coastguard Worker
AddComment(std::vector<CallCapture> * outCalls,const std::string & comment)974*8975f5c5SAndroid Build Coastguard Worker void AddComment(std::vector<CallCapture> *outCalls, const std::string &comment)
975*8975f5c5SAndroid Build Coastguard Worker {
976*8975f5c5SAndroid Build Coastguard Worker
977*8975f5c5SAndroid Build Coastguard Worker ParamBuffer commentParamBuffer;
978*8975f5c5SAndroid Build Coastguard Worker ParamCapture commentParam("comment", ParamType::TGLcharConstPointer);
979*8975f5c5SAndroid Build Coastguard Worker CaptureString(comment.c_str(), &commentParam);
980*8975f5c5SAndroid Build Coastguard Worker commentParamBuffer.addParam(std::move(commentParam));
981*8975f5c5SAndroid Build Coastguard Worker outCalls->emplace_back("Comment", std::move(commentParamBuffer));
982*8975f5c5SAndroid Build Coastguard Worker }
983*8975f5c5SAndroid Build Coastguard Worker
MaxClientArraySize(const gl::AttribArray<size_t> & clientArraySizes)984*8975f5c5SAndroid Build Coastguard Worker size_t MaxClientArraySize(const gl::AttribArray<size_t> &clientArraySizes)
985*8975f5c5SAndroid Build Coastguard Worker {
986*8975f5c5SAndroid Build Coastguard Worker size_t found = 0;
987*8975f5c5SAndroid Build Coastguard Worker for (size_t size : clientArraySizes)
988*8975f5c5SAndroid Build Coastguard Worker {
989*8975f5c5SAndroid Build Coastguard Worker if (size > found)
990*8975f5c5SAndroid Build Coastguard Worker {
991*8975f5c5SAndroid Build Coastguard Worker found = size;
992*8975f5c5SAndroid Build Coastguard Worker }
993*8975f5c5SAndroid Build Coastguard Worker }
994*8975f5c5SAndroid Build Coastguard Worker
995*8975f5c5SAndroid Build Coastguard Worker return found;
996*8975f5c5SAndroid Build Coastguard Worker }
997*8975f5c5SAndroid Build Coastguard Worker
GetBinaryDataFilePath(bool compression,const std::string & captureLabel)998*8975f5c5SAndroid Build Coastguard Worker std::string GetBinaryDataFilePath(bool compression, const std::string &captureLabel)
999*8975f5c5SAndroid Build Coastguard Worker {
1000*8975f5c5SAndroid Build Coastguard Worker std::stringstream fnameStream;
1001*8975f5c5SAndroid Build Coastguard Worker fnameStream << FmtCapturePrefix(kNoContextId, captureLabel) << ".angledata";
1002*8975f5c5SAndroid Build Coastguard Worker if (compression)
1003*8975f5c5SAndroid Build Coastguard Worker {
1004*8975f5c5SAndroid Build Coastguard Worker fnameStream << ".gz";
1005*8975f5c5SAndroid Build Coastguard Worker }
1006*8975f5c5SAndroid Build Coastguard Worker return fnameStream.str();
1007*8975f5c5SAndroid Build Coastguard Worker }
1008*8975f5c5SAndroid Build Coastguard Worker
1009*8975f5c5SAndroid Build Coastguard Worker struct SaveFileHelper
1010*8975f5c5SAndroid Build Coastguard Worker {
1011*8975f5c5SAndroid Build Coastguard Worker public:
1012*8975f5c5SAndroid Build Coastguard Worker // We always use ios::binary to avoid inconsistent line endings when captured on Linux vs Win.
SaveFileHelperangle::__anoncf31a3f40111::SaveFileHelper1013*8975f5c5SAndroid Build Coastguard Worker SaveFileHelper(const std::string &filePathIn)
1014*8975f5c5SAndroid Build Coastguard Worker : mOfs(filePathIn, std::ios::binary | std::ios::out), mFilePath(filePathIn)
1015*8975f5c5SAndroid Build Coastguard Worker {
1016*8975f5c5SAndroid Build Coastguard Worker if (!mOfs.is_open())
1017*8975f5c5SAndroid Build Coastguard Worker {
1018*8975f5c5SAndroid Build Coastguard Worker FATAL() << "Could not open " << filePathIn;
1019*8975f5c5SAndroid Build Coastguard Worker }
1020*8975f5c5SAndroid Build Coastguard Worker }
~SaveFileHelperangle::__anoncf31a3f40111::SaveFileHelper1021*8975f5c5SAndroid Build Coastguard Worker ~SaveFileHelper() { printf("Saved '%s'.\n", mFilePath.c_str()); }
1022*8975f5c5SAndroid Build Coastguard Worker
1023*8975f5c5SAndroid Build Coastguard Worker template <typename T>
operator <<angle::__anoncf31a3f40111::SaveFileHelper1024*8975f5c5SAndroid Build Coastguard Worker SaveFileHelper &operator<<(const T &value)
1025*8975f5c5SAndroid Build Coastguard Worker {
1026*8975f5c5SAndroid Build Coastguard Worker mOfs << value;
1027*8975f5c5SAndroid Build Coastguard Worker if (mOfs.bad())
1028*8975f5c5SAndroid Build Coastguard Worker {
1029*8975f5c5SAndroid Build Coastguard Worker FATAL() << "Error writing to " << mFilePath;
1030*8975f5c5SAndroid Build Coastguard Worker }
1031*8975f5c5SAndroid Build Coastguard Worker return *this;
1032*8975f5c5SAndroid Build Coastguard Worker }
1033*8975f5c5SAndroid Build Coastguard Worker
writeangle::__anoncf31a3f40111::SaveFileHelper1034*8975f5c5SAndroid Build Coastguard Worker void write(const uint8_t *data, size_t size)
1035*8975f5c5SAndroid Build Coastguard Worker {
1036*8975f5c5SAndroid Build Coastguard Worker mOfs.write(reinterpret_cast<const char *>(data), size);
1037*8975f5c5SAndroid Build Coastguard Worker }
1038*8975f5c5SAndroid Build Coastguard Worker
1039*8975f5c5SAndroid Build Coastguard Worker private:
1040*8975f5c5SAndroid Build Coastguard Worker void checkError();
1041*8975f5c5SAndroid Build Coastguard Worker
1042*8975f5c5SAndroid Build Coastguard Worker std::ofstream mOfs;
1043*8975f5c5SAndroid Build Coastguard Worker std::string mFilePath;
1044*8975f5c5SAndroid Build Coastguard Worker };
1045*8975f5c5SAndroid Build Coastguard Worker
SaveBinaryData(bool compression,const std::string & outDir,gl::ContextID contextId,const std::string & captureLabel,const std::vector<uint8_t> & binaryData)1046*8975f5c5SAndroid Build Coastguard Worker void SaveBinaryData(bool compression,
1047*8975f5c5SAndroid Build Coastguard Worker const std::string &outDir,
1048*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextId,
1049*8975f5c5SAndroid Build Coastguard Worker const std::string &captureLabel,
1050*8975f5c5SAndroid Build Coastguard Worker const std::vector<uint8_t> &binaryData)
1051*8975f5c5SAndroid Build Coastguard Worker {
1052*8975f5c5SAndroid Build Coastguard Worker std::string binaryDataFileName = GetBinaryDataFilePath(compression, captureLabel);
1053*8975f5c5SAndroid Build Coastguard Worker std::string dataFilepath = outDir + binaryDataFileName;
1054*8975f5c5SAndroid Build Coastguard Worker
1055*8975f5c5SAndroid Build Coastguard Worker SaveFileHelper saveData(dataFilepath);
1056*8975f5c5SAndroid Build Coastguard Worker
1057*8975f5c5SAndroid Build Coastguard Worker if (compression)
1058*8975f5c5SAndroid Build Coastguard Worker {
1059*8975f5c5SAndroid Build Coastguard Worker // Save compressed data.
1060*8975f5c5SAndroid Build Coastguard Worker uLong uncompressedSize = static_cast<uLong>(binaryData.size());
1061*8975f5c5SAndroid Build Coastguard Worker uLong expectedCompressedSize = zlib_internal::GzipExpectedCompressedSize(uncompressedSize);
1062*8975f5c5SAndroid Build Coastguard Worker
1063*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> compressedData(expectedCompressedSize, 0);
1064*8975f5c5SAndroid Build Coastguard Worker
1065*8975f5c5SAndroid Build Coastguard Worker uLong compressedSize = expectedCompressedSize;
1066*8975f5c5SAndroid Build Coastguard Worker int zResult = zlib_internal::GzipCompressHelper(compressedData.data(), &compressedSize,
1067*8975f5c5SAndroid Build Coastguard Worker binaryData.data(), uncompressedSize,
1068*8975f5c5SAndroid Build Coastguard Worker nullptr, nullptr);
1069*8975f5c5SAndroid Build Coastguard Worker
1070*8975f5c5SAndroid Build Coastguard Worker if (zResult != Z_OK)
1071*8975f5c5SAndroid Build Coastguard Worker {
1072*8975f5c5SAndroid Build Coastguard Worker FATAL() << "Error compressing binary data: " << zResult;
1073*8975f5c5SAndroid Build Coastguard Worker }
1074*8975f5c5SAndroid Build Coastguard Worker
1075*8975f5c5SAndroid Build Coastguard Worker saveData.write(compressedData.data(), compressedSize);
1076*8975f5c5SAndroid Build Coastguard Worker }
1077*8975f5c5SAndroid Build Coastguard Worker else
1078*8975f5c5SAndroid Build Coastguard Worker {
1079*8975f5c5SAndroid Build Coastguard Worker saveData.write(binaryData.data(), binaryData.size());
1080*8975f5c5SAndroid Build Coastguard Worker }
1081*8975f5c5SAndroid Build Coastguard Worker }
1082*8975f5c5SAndroid Build Coastguard Worker
WriteInitReplayCall(bool compression,std::ostream & out,gl::ContextID contextID,const std::string & captureLabel,size_t maxClientArraySize,size_t readBufferSize,size_t resourceIDBufferSize,const PackedEnumMap<ResourceIDType,uint32_t> & maxIDs)1083*8975f5c5SAndroid Build Coastguard Worker void WriteInitReplayCall(bool compression,
1084*8975f5c5SAndroid Build Coastguard Worker std::ostream &out,
1085*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextID,
1086*8975f5c5SAndroid Build Coastguard Worker const std::string &captureLabel,
1087*8975f5c5SAndroid Build Coastguard Worker size_t maxClientArraySize,
1088*8975f5c5SAndroid Build Coastguard Worker size_t readBufferSize,
1089*8975f5c5SAndroid Build Coastguard Worker size_t resourceIDBufferSize,
1090*8975f5c5SAndroid Build Coastguard Worker const PackedEnumMap<ResourceIDType, uint32_t> &maxIDs)
1091*8975f5c5SAndroid Build Coastguard Worker {
1092*8975f5c5SAndroid Build Coastguard Worker std::string binaryDataFileName = GetBinaryDataFilePath(compression, captureLabel);
1093*8975f5c5SAndroid Build Coastguard Worker
1094*8975f5c5SAndroid Build Coastguard Worker out << " // binaryDataFileName = " << binaryDataFileName << "\n";
1095*8975f5c5SAndroid Build Coastguard Worker out << " // maxClientArraySize = " << maxClientArraySize << "\n";
1096*8975f5c5SAndroid Build Coastguard Worker out << " // maxClientArraySize = " << maxClientArraySize << "\n";
1097*8975f5c5SAndroid Build Coastguard Worker out << " // readBufferSize = " << readBufferSize << "\n";
1098*8975f5c5SAndroid Build Coastguard Worker out << " // resourceIDBufferSize = " << resourceIDBufferSize << "\n";
1099*8975f5c5SAndroid Build Coastguard Worker out << " // contextID = " << contextID << "\n";
1100*8975f5c5SAndroid Build Coastguard Worker
1101*8975f5c5SAndroid Build Coastguard Worker for (ResourceIDType resourceID : AllEnums<ResourceIDType>())
1102*8975f5c5SAndroid Build Coastguard Worker {
1103*8975f5c5SAndroid Build Coastguard Worker const char *name = GetResourceIDTypeName(resourceID);
1104*8975f5c5SAndroid Build Coastguard Worker out << " // max" << name << " = " << maxIDs[resourceID] << "\n";
1105*8975f5c5SAndroid Build Coastguard Worker }
1106*8975f5c5SAndroid Build Coastguard Worker
1107*8975f5c5SAndroid Build Coastguard Worker out << " InitializeReplay4(\"" << binaryDataFileName << "\", " << maxClientArraySize << ", "
1108*8975f5c5SAndroid Build Coastguard Worker << readBufferSize << ", " << resourceIDBufferSize << ", " << contextID;
1109*8975f5c5SAndroid Build Coastguard Worker
1110*8975f5c5SAndroid Build Coastguard Worker for (ResourceIDType resourceID : AllEnums<ResourceIDType>())
1111*8975f5c5SAndroid Build Coastguard Worker {
1112*8975f5c5SAndroid Build Coastguard Worker // Sanity check for catching e.g. uninitialized memory reads like b/380296979
1113*8975f5c5SAndroid Build Coastguard Worker ASSERT(maxIDs[resourceID] < 1000000);
1114*8975f5c5SAndroid Build Coastguard Worker out << ", " << maxIDs[resourceID];
1115*8975f5c5SAndroid Build Coastguard Worker }
1116*8975f5c5SAndroid Build Coastguard Worker
1117*8975f5c5SAndroid Build Coastguard Worker out << ");\n";
1118*8975f5c5SAndroid Build Coastguard Worker }
1119*8975f5c5SAndroid Build Coastguard Worker
DeleteResourcesInReset(std::stringstream & out,const gl::ContextID contextID,const ResourceSet & newResources,const ResourceSet & resourcesToDelete,const ResourceIDType resourceIDType,size_t * maxResourceIDBufferSize)1120*8975f5c5SAndroid Build Coastguard Worker void DeleteResourcesInReset(std::stringstream &out,
1121*8975f5c5SAndroid Build Coastguard Worker const gl::ContextID contextID,
1122*8975f5c5SAndroid Build Coastguard Worker const ResourceSet &newResources,
1123*8975f5c5SAndroid Build Coastguard Worker const ResourceSet &resourcesToDelete,
1124*8975f5c5SAndroid Build Coastguard Worker const ResourceIDType resourceIDType,
1125*8975f5c5SAndroid Build Coastguard Worker size_t *maxResourceIDBufferSize)
1126*8975f5c5SAndroid Build Coastguard Worker {
1127*8975f5c5SAndroid Build Coastguard Worker if (!newResources.empty() || !resourcesToDelete.empty())
1128*8975f5c5SAndroid Build Coastguard Worker {
1129*8975f5c5SAndroid Build Coastguard Worker size_t count = 0;
1130*8975f5c5SAndroid Build Coastguard Worker
1131*8975f5c5SAndroid Build Coastguard Worker for (GLuint oldResource : resourcesToDelete)
1132*8975f5c5SAndroid Build Coastguard Worker {
1133*8975f5c5SAndroid Build Coastguard Worker UpdateResourceIDBuffer(out, Indent::Indent, count++, resourceIDType, contextID,
1134*8975f5c5SAndroid Build Coastguard Worker oldResource);
1135*8975f5c5SAndroid Build Coastguard Worker }
1136*8975f5c5SAndroid Build Coastguard Worker
1137*8975f5c5SAndroid Build Coastguard Worker for (GLuint newResource : newResources)
1138*8975f5c5SAndroid Build Coastguard Worker {
1139*8975f5c5SAndroid Build Coastguard Worker UpdateResourceIDBuffer(out, Indent::Indent, count++, resourceIDType, contextID,
1140*8975f5c5SAndroid Build Coastguard Worker newResource);
1141*8975f5c5SAndroid Build Coastguard Worker }
1142*8975f5c5SAndroid Build Coastguard Worker
1143*8975f5c5SAndroid Build Coastguard Worker // Delete all the new and old buffers at once
1144*8975f5c5SAndroid Build Coastguard Worker out << " glDelete" << GetResourceIDTypeName(resourceIDType) << "s(" << count
1145*8975f5c5SAndroid Build Coastguard Worker << ", gResourceIDBuffer);\n";
1146*8975f5c5SAndroid Build Coastguard Worker
1147*8975f5c5SAndroid Build Coastguard Worker *maxResourceIDBufferSize = std::max(*maxResourceIDBufferSize, count);
1148*8975f5c5SAndroid Build Coastguard Worker }
1149*8975f5c5SAndroid Build Coastguard Worker }
1150*8975f5c5SAndroid Build Coastguard Worker
1151*8975f5c5SAndroid Build Coastguard Worker // TODO (http://anglebug.com/42263204): Reset more state on frame loop
MaybeResetResources(egl::Display * display,gl::ContextID contextID,ResourceIDType resourceIDType,ReplayWriter & replayWriter,std::stringstream & out,std::stringstream & header,ResourceTracker * resourceTracker,std::vector<uint8_t> * binaryData,bool & anyResourceReset,size_t * maxResourceIDBufferSize)1152*8975f5c5SAndroid Build Coastguard Worker void MaybeResetResources(egl::Display *display,
1153*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextID,
1154*8975f5c5SAndroid Build Coastguard Worker ResourceIDType resourceIDType,
1155*8975f5c5SAndroid Build Coastguard Worker ReplayWriter &replayWriter,
1156*8975f5c5SAndroid Build Coastguard Worker std::stringstream &out,
1157*8975f5c5SAndroid Build Coastguard Worker std::stringstream &header,
1158*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
1159*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> *binaryData,
1160*8975f5c5SAndroid Build Coastguard Worker bool &anyResourceReset,
1161*8975f5c5SAndroid Build Coastguard Worker size_t *maxResourceIDBufferSize)
1162*8975f5c5SAndroid Build Coastguard Worker {
1163*8975f5c5SAndroid Build Coastguard Worker // Track the initial output position so we can detect if it has moved
1164*8975f5c5SAndroid Build Coastguard Worker std::streampos initialOutPos = out.tellp();
1165*8975f5c5SAndroid Build Coastguard Worker
1166*8975f5c5SAndroid Build Coastguard Worker switch (resourceIDType)
1167*8975f5c5SAndroid Build Coastguard Worker {
1168*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Buffer:
1169*8975f5c5SAndroid Build Coastguard Worker {
1170*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedBuffers =
1171*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(contextID, ResourceIDType::Buffer);
1172*8975f5c5SAndroid Build Coastguard Worker ResourceSet &newBuffers = trackedBuffers.getNewResources();
1173*8975f5c5SAndroid Build Coastguard Worker ResourceSet &buffersToDelete = trackedBuffers.getResourcesToDelete();
1174*8975f5c5SAndroid Build Coastguard Worker ResourceSet &buffersToRegen = trackedBuffers.getResourcesToRegen();
1175*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &bufferRegenCalls = trackedBuffers.getResourceRegenCalls();
1176*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &bufferRestoreCalls = trackedBuffers.getResourceRestoreCalls();
1177*8975f5c5SAndroid Build Coastguard Worker
1178*8975f5c5SAndroid Build Coastguard Worker BufferCalls &bufferMapCalls = resourceTracker->getBufferMapCalls();
1179*8975f5c5SAndroid Build Coastguard Worker BufferCalls &bufferUnmapCalls = resourceTracker->getBufferUnmapCalls();
1180*8975f5c5SAndroid Build Coastguard Worker
1181*8975f5c5SAndroid Build Coastguard Worker DeleteResourcesInReset(out, contextID, newBuffers, buffersToDelete, resourceIDType,
1182*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1183*8975f5c5SAndroid Build Coastguard Worker
1184*8975f5c5SAndroid Build Coastguard Worker // If any of our starting buffers were deleted during the run, recreate them
1185*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : buffersToRegen)
1186*8975f5c5SAndroid Build Coastguard Worker {
1187*8975f5c5SAndroid Build Coastguard Worker // Emit their regen calls
1188*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : bufferRegenCalls[id])
1189*8975f5c5SAndroid Build Coastguard Worker {
1190*8975f5c5SAndroid Build Coastguard Worker out << " ";
1191*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1192*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1193*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1194*8975f5c5SAndroid Build Coastguard Worker }
1195*8975f5c5SAndroid Build Coastguard Worker }
1196*8975f5c5SAndroid Build Coastguard Worker
1197*8975f5c5SAndroid Build Coastguard Worker // If any of our starting buffers were modified during the run, restore their contents
1198*8975f5c5SAndroid Build Coastguard Worker ResourceSet &buffersToRestore = trackedBuffers.getResourcesToRestore();
1199*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : buffersToRestore)
1200*8975f5c5SAndroid Build Coastguard Worker {
1201*8975f5c5SAndroid Build Coastguard Worker if (resourceTracker->getStartingBuffersMappedCurrent(id))
1202*8975f5c5SAndroid Build Coastguard Worker {
1203*8975f5c5SAndroid Build Coastguard Worker // Some drivers require the buffer to be unmapped before you can update data,
1204*8975f5c5SAndroid Build Coastguard Worker // which violates the spec. See gl::Buffer::bufferDataImpl().
1205*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : bufferUnmapCalls[id])
1206*8975f5c5SAndroid Build Coastguard Worker {
1207*8975f5c5SAndroid Build Coastguard Worker out << " ";
1208*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1209*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1210*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1211*8975f5c5SAndroid Build Coastguard Worker }
1212*8975f5c5SAndroid Build Coastguard Worker }
1213*8975f5c5SAndroid Build Coastguard Worker
1214*8975f5c5SAndroid Build Coastguard Worker // Emit their restore calls
1215*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : bufferRestoreCalls[id])
1216*8975f5c5SAndroid Build Coastguard Worker {
1217*8975f5c5SAndroid Build Coastguard Worker out << " ";
1218*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1219*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1220*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1221*8975f5c5SAndroid Build Coastguard Worker
1222*8975f5c5SAndroid Build Coastguard Worker // Also note that this buffer has been implicitly unmapped by this call
1223*8975f5c5SAndroid Build Coastguard Worker resourceTracker->setBufferUnmapped(contextID, id);
1224*8975f5c5SAndroid Build Coastguard Worker }
1225*8975f5c5SAndroid Build Coastguard Worker }
1226*8975f5c5SAndroid Build Coastguard Worker
1227*8975f5c5SAndroid Build Coastguard Worker // Update the map/unmap of buffers to match the starting state
1228*8975f5c5SAndroid Build Coastguard Worker ResourceSet startingBuffers = trackedBuffers.getStartingResources();
1229*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : startingBuffers)
1230*8975f5c5SAndroid Build Coastguard Worker {
1231*8975f5c5SAndroid Build Coastguard Worker // If the buffer was mapped at the start, but is not mapped now, we need to map
1232*8975f5c5SAndroid Build Coastguard Worker if (resourceTracker->getStartingBuffersMappedInitial(id) &&
1233*8975f5c5SAndroid Build Coastguard Worker !resourceTracker->getStartingBuffersMappedCurrent(id))
1234*8975f5c5SAndroid Build Coastguard Worker {
1235*8975f5c5SAndroid Build Coastguard Worker // Emit their map calls
1236*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : bufferMapCalls[id])
1237*8975f5c5SAndroid Build Coastguard Worker {
1238*8975f5c5SAndroid Build Coastguard Worker out << " ";
1239*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1240*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1241*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1242*8975f5c5SAndroid Build Coastguard Worker }
1243*8975f5c5SAndroid Build Coastguard Worker }
1244*8975f5c5SAndroid Build Coastguard Worker // If the buffer was unmapped at the start, but is mapped now, we need to unmap
1245*8975f5c5SAndroid Build Coastguard Worker if (!resourceTracker->getStartingBuffersMappedInitial(id) &&
1246*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getStartingBuffersMappedCurrent(id))
1247*8975f5c5SAndroid Build Coastguard Worker {
1248*8975f5c5SAndroid Build Coastguard Worker // Emit their unmap calls
1249*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : bufferUnmapCalls[id])
1250*8975f5c5SAndroid Build Coastguard Worker {
1251*8975f5c5SAndroid Build Coastguard Worker out << " ";
1252*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1253*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1254*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1255*8975f5c5SAndroid Build Coastguard Worker }
1256*8975f5c5SAndroid Build Coastguard Worker }
1257*8975f5c5SAndroid Build Coastguard Worker }
1258*8975f5c5SAndroid Build Coastguard Worker break;
1259*8975f5c5SAndroid Build Coastguard Worker }
1260*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Framebuffer:
1261*8975f5c5SAndroid Build Coastguard Worker {
1262*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedFramebuffers =
1263*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(contextID, ResourceIDType::Framebuffer);
1264*8975f5c5SAndroid Build Coastguard Worker ResourceSet &newFramebuffers = trackedFramebuffers.getNewResources();
1265*8975f5c5SAndroid Build Coastguard Worker ResourceSet &framebuffersToDelete = trackedFramebuffers.getResourcesToDelete();
1266*8975f5c5SAndroid Build Coastguard Worker ResourceSet &framebuffersToRegen = trackedFramebuffers.getResourcesToRegen();
1267*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &framebufferRegenCalls = trackedFramebuffers.getResourceRegenCalls();
1268*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &framebufferRestoreCalls = trackedFramebuffers.getResourceRestoreCalls();
1269*8975f5c5SAndroid Build Coastguard Worker
1270*8975f5c5SAndroid Build Coastguard Worker DeleteResourcesInReset(out, contextID, newFramebuffers, framebuffersToDelete,
1271*8975f5c5SAndroid Build Coastguard Worker resourceIDType, maxResourceIDBufferSize);
1272*8975f5c5SAndroid Build Coastguard Worker
1273*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : framebuffersToRegen)
1274*8975f5c5SAndroid Build Coastguard Worker {
1275*8975f5c5SAndroid Build Coastguard Worker // Emit their regen calls
1276*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : framebufferRegenCalls[id])
1277*8975f5c5SAndroid Build Coastguard Worker {
1278*8975f5c5SAndroid Build Coastguard Worker out << " ";
1279*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1280*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1281*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1282*8975f5c5SAndroid Build Coastguard Worker }
1283*8975f5c5SAndroid Build Coastguard Worker }
1284*8975f5c5SAndroid Build Coastguard Worker
1285*8975f5c5SAndroid Build Coastguard Worker // If any of our starting framebuffers were modified during the run, restore their
1286*8975f5c5SAndroid Build Coastguard Worker // contents
1287*8975f5c5SAndroid Build Coastguard Worker ResourceSet &framebuffersToRestore = trackedFramebuffers.getResourcesToRestore();
1288*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : framebuffersToRestore)
1289*8975f5c5SAndroid Build Coastguard Worker {
1290*8975f5c5SAndroid Build Coastguard Worker // Emit their restore calls
1291*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : framebufferRestoreCalls[id])
1292*8975f5c5SAndroid Build Coastguard Worker {
1293*8975f5c5SAndroid Build Coastguard Worker out << " ";
1294*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1295*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1296*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1297*8975f5c5SAndroid Build Coastguard Worker }
1298*8975f5c5SAndroid Build Coastguard Worker }
1299*8975f5c5SAndroid Build Coastguard Worker break;
1300*8975f5c5SAndroid Build Coastguard Worker }
1301*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Renderbuffer:
1302*8975f5c5SAndroid Build Coastguard Worker {
1303*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedRenderbuffers =
1304*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(contextID, ResourceIDType::Renderbuffer);
1305*8975f5c5SAndroid Build Coastguard Worker ResourceSet &newRenderbuffers = trackedRenderbuffers.getNewResources();
1306*8975f5c5SAndroid Build Coastguard Worker ResourceSet &renderbuffersToDelete = trackedRenderbuffers.getResourcesToDelete();
1307*8975f5c5SAndroid Build Coastguard Worker ResourceSet &renderbuffersToRegen = trackedRenderbuffers.getResourcesToRegen();
1308*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &renderbufferRegenCalls = trackedRenderbuffers.getResourceRegenCalls();
1309*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &renderbufferRestoreCalls =
1310*8975f5c5SAndroid Build Coastguard Worker trackedRenderbuffers.getResourceRestoreCalls();
1311*8975f5c5SAndroid Build Coastguard Worker
1312*8975f5c5SAndroid Build Coastguard Worker DeleteResourcesInReset(out, contextID, newRenderbuffers, renderbuffersToDelete,
1313*8975f5c5SAndroid Build Coastguard Worker resourceIDType, maxResourceIDBufferSize);
1314*8975f5c5SAndroid Build Coastguard Worker
1315*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : renderbuffersToRegen)
1316*8975f5c5SAndroid Build Coastguard Worker {
1317*8975f5c5SAndroid Build Coastguard Worker // Emit their regen calls
1318*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : renderbufferRegenCalls[id])
1319*8975f5c5SAndroid Build Coastguard Worker {
1320*8975f5c5SAndroid Build Coastguard Worker out << " ";
1321*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1322*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1323*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1324*8975f5c5SAndroid Build Coastguard Worker }
1325*8975f5c5SAndroid Build Coastguard Worker }
1326*8975f5c5SAndroid Build Coastguard Worker
1327*8975f5c5SAndroid Build Coastguard Worker // If any of our starting renderbuffers were modified during the run, restore their
1328*8975f5c5SAndroid Build Coastguard Worker // contents
1329*8975f5c5SAndroid Build Coastguard Worker ResourceSet &renderbuffersToRestore = trackedRenderbuffers.getResourcesToRestore();
1330*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : renderbuffersToRestore)
1331*8975f5c5SAndroid Build Coastguard Worker {
1332*8975f5c5SAndroid Build Coastguard Worker // Emit their restore calls
1333*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : renderbufferRestoreCalls[id])
1334*8975f5c5SAndroid Build Coastguard Worker {
1335*8975f5c5SAndroid Build Coastguard Worker out << " ";
1336*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1337*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1338*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1339*8975f5c5SAndroid Build Coastguard Worker }
1340*8975f5c5SAndroid Build Coastguard Worker }
1341*8975f5c5SAndroid Build Coastguard Worker break;
1342*8975f5c5SAndroid Build Coastguard Worker }
1343*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::ShaderProgram:
1344*8975f5c5SAndroid Build Coastguard Worker {
1345*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedShaderPrograms =
1346*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(contextID, ResourceIDType::ShaderProgram);
1347*8975f5c5SAndroid Build Coastguard Worker ResourceSet &newShaderPrograms = trackedShaderPrograms.getNewResources();
1348*8975f5c5SAndroid Build Coastguard Worker ResourceSet &shaderProgramsToDelete = trackedShaderPrograms.getResourcesToDelete();
1349*8975f5c5SAndroid Build Coastguard Worker ResourceSet &shaderProgramsToRegen = trackedShaderPrograms.getResourcesToRegen();
1350*8975f5c5SAndroid Build Coastguard Worker ResourceSet &shaderProgramsToRestore = trackedShaderPrograms.getResourcesToRestore();
1351*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &shaderProgramRegenCalls = trackedShaderPrograms.getResourceRegenCalls();
1352*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &shaderProgramRestoreCalls =
1353*8975f5c5SAndroid Build Coastguard Worker trackedShaderPrograms.getResourceRestoreCalls();
1354*8975f5c5SAndroid Build Coastguard Worker
1355*8975f5c5SAndroid Build Coastguard Worker // If we have any new shaders or programs created and not deleted during the run, delete
1356*8975f5c5SAndroid Build Coastguard Worker // them now
1357*8975f5c5SAndroid Build Coastguard Worker for (const GLuint &newShaderProgram : newShaderPrograms)
1358*8975f5c5SAndroid Build Coastguard Worker {
1359*8975f5c5SAndroid Build Coastguard Worker if (resourceTracker->getShaderProgramType({newShaderProgram}) ==
1360*8975f5c5SAndroid Build Coastguard Worker ShaderProgramType::ShaderType)
1361*8975f5c5SAndroid Build Coastguard Worker {
1362*8975f5c5SAndroid Build Coastguard Worker out << " glDeleteShader(gShaderProgramMap[" << newShaderProgram << "]);\n";
1363*8975f5c5SAndroid Build Coastguard Worker }
1364*8975f5c5SAndroid Build Coastguard Worker else
1365*8975f5c5SAndroid Build Coastguard Worker {
1366*8975f5c5SAndroid Build Coastguard Worker ASSERT(resourceTracker->getShaderProgramType({newShaderProgram}) ==
1367*8975f5c5SAndroid Build Coastguard Worker ShaderProgramType::ProgramType);
1368*8975f5c5SAndroid Build Coastguard Worker out << " glDeleteProgram(gShaderProgramMap[" << newShaderProgram << "]);\n";
1369*8975f5c5SAndroid Build Coastguard Worker }
1370*8975f5c5SAndroid Build Coastguard Worker }
1371*8975f5c5SAndroid Build Coastguard Worker
1372*8975f5c5SAndroid Build Coastguard Worker // Do the same for shaders/programs to be deleted
1373*8975f5c5SAndroid Build Coastguard Worker for (const GLuint &shaderProgramToDelete : shaderProgramsToDelete)
1374*8975f5c5SAndroid Build Coastguard Worker {
1375*8975f5c5SAndroid Build Coastguard Worker if (resourceTracker->getShaderProgramType({shaderProgramToDelete}) ==
1376*8975f5c5SAndroid Build Coastguard Worker ShaderProgramType::ShaderType)
1377*8975f5c5SAndroid Build Coastguard Worker {
1378*8975f5c5SAndroid Build Coastguard Worker out << " glDeleteShader(gShaderProgramMap[" << shaderProgramToDelete
1379*8975f5c5SAndroid Build Coastguard Worker << "]);\n";
1380*8975f5c5SAndroid Build Coastguard Worker }
1381*8975f5c5SAndroid Build Coastguard Worker else
1382*8975f5c5SAndroid Build Coastguard Worker {
1383*8975f5c5SAndroid Build Coastguard Worker ASSERT(resourceTracker->getShaderProgramType({shaderProgramToDelete}) ==
1384*8975f5c5SAndroid Build Coastguard Worker ShaderProgramType::ProgramType);
1385*8975f5c5SAndroid Build Coastguard Worker out << " glDeleteProgram(gShaderProgramMap[" << shaderProgramToDelete
1386*8975f5c5SAndroid Build Coastguard Worker << "]);\n";
1387*8975f5c5SAndroid Build Coastguard Worker }
1388*8975f5c5SAndroid Build Coastguard Worker }
1389*8975f5c5SAndroid Build Coastguard Worker
1390*8975f5c5SAndroid Build Coastguard Worker for (const GLuint id : shaderProgramsToRegen)
1391*8975f5c5SAndroid Build Coastguard Worker {
1392*8975f5c5SAndroid Build Coastguard Worker // Emit their regen calls
1393*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : shaderProgramRegenCalls[id])
1394*8975f5c5SAndroid Build Coastguard Worker {
1395*8975f5c5SAndroid Build Coastguard Worker out << " ";
1396*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1397*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1398*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1399*8975f5c5SAndroid Build Coastguard Worker }
1400*8975f5c5SAndroid Build Coastguard Worker }
1401*8975f5c5SAndroid Build Coastguard Worker
1402*8975f5c5SAndroid Build Coastguard Worker for (const GLuint id : shaderProgramsToRestore)
1403*8975f5c5SAndroid Build Coastguard Worker {
1404*8975f5c5SAndroid Build Coastguard Worker // Emit their restore calls
1405*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : shaderProgramRestoreCalls[id])
1406*8975f5c5SAndroid Build Coastguard Worker {
1407*8975f5c5SAndroid Build Coastguard Worker out << " ";
1408*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1409*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1410*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1411*8975f5c5SAndroid Build Coastguard Worker }
1412*8975f5c5SAndroid Build Coastguard Worker }
1413*8975f5c5SAndroid Build Coastguard Worker
1414*8975f5c5SAndroid Build Coastguard Worker break;
1415*8975f5c5SAndroid Build Coastguard Worker }
1416*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Texture:
1417*8975f5c5SAndroid Build Coastguard Worker {
1418*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedTextures =
1419*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(contextID, ResourceIDType::Texture);
1420*8975f5c5SAndroid Build Coastguard Worker ResourceSet &newTextures = trackedTextures.getNewResources();
1421*8975f5c5SAndroid Build Coastguard Worker ResourceSet &texturesToDelete = trackedTextures.getResourcesToDelete();
1422*8975f5c5SAndroid Build Coastguard Worker ResourceSet &texturesToRegen = trackedTextures.getResourcesToRegen();
1423*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &textureRegenCalls = trackedTextures.getResourceRegenCalls();
1424*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &textureRestoreCalls = trackedTextures.getResourceRestoreCalls();
1425*8975f5c5SAndroid Build Coastguard Worker
1426*8975f5c5SAndroid Build Coastguard Worker DeleteResourcesInReset(out, contextID, newTextures, texturesToDelete, resourceIDType,
1427*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1428*8975f5c5SAndroid Build Coastguard Worker
1429*8975f5c5SAndroid Build Coastguard Worker // If any of our starting textures were deleted, regen them
1430*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : texturesToRegen)
1431*8975f5c5SAndroid Build Coastguard Worker {
1432*8975f5c5SAndroid Build Coastguard Worker // Emit their regen calls
1433*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : textureRegenCalls[id])
1434*8975f5c5SAndroid Build Coastguard Worker {
1435*8975f5c5SAndroid Build Coastguard Worker out << " ";
1436*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1437*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1438*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1439*8975f5c5SAndroid Build Coastguard Worker }
1440*8975f5c5SAndroid Build Coastguard Worker }
1441*8975f5c5SAndroid Build Coastguard Worker
1442*8975f5c5SAndroid Build Coastguard Worker // If any of our starting textures were modified during the run, restore their contents
1443*8975f5c5SAndroid Build Coastguard Worker ResourceSet &texturesToRestore = trackedTextures.getResourcesToRestore();
1444*8975f5c5SAndroid Build Coastguard Worker
1445*8975f5c5SAndroid Build Coastguard Worker // Do some setup if we have any textures to restore
1446*8975f5c5SAndroid Build Coastguard Worker if (texturesToRestore.size() != 0)
1447*8975f5c5SAndroid Build Coastguard Worker {
1448*8975f5c5SAndroid Build Coastguard Worker // We need to unbind PIXEL_UNPACK_BUFFER before restoring textures
1449*8975f5c5SAndroid Build Coastguard Worker // The correct binding will be restored in context state reset
1450*8975f5c5SAndroid Build Coastguard Worker gl::Context *context = display->getContext(contextID);
1451*8975f5c5SAndroid Build Coastguard Worker if (context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack))
1452*8975f5c5SAndroid Build Coastguard Worker {
1453*8975f5c5SAndroid Build Coastguard Worker out << " // Clearing PIXEL_UNPACK_BUFFER binding for texture restore\n";
1454*8975f5c5SAndroid Build Coastguard Worker out << " ";
1455*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(CaptureBindBuffer(context->getState(), true,
1456*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding::PixelUnpack, {0}),
1457*8975f5c5SAndroid Build Coastguard Worker replayWriter, out, header, binaryData,
1458*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1459*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1460*8975f5c5SAndroid Build Coastguard Worker }
1461*8975f5c5SAndroid Build Coastguard Worker }
1462*8975f5c5SAndroid Build Coastguard Worker
1463*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : texturesToRestore)
1464*8975f5c5SAndroid Build Coastguard Worker {
1465*8975f5c5SAndroid Build Coastguard Worker // Emit their restore calls
1466*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : textureRestoreCalls[id])
1467*8975f5c5SAndroid Build Coastguard Worker {
1468*8975f5c5SAndroid Build Coastguard Worker out << " ";
1469*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1470*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1471*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1472*8975f5c5SAndroid Build Coastguard Worker }
1473*8975f5c5SAndroid Build Coastguard Worker }
1474*8975f5c5SAndroid Build Coastguard Worker break;
1475*8975f5c5SAndroid Build Coastguard Worker }
1476*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::VertexArray:
1477*8975f5c5SAndroid Build Coastguard Worker {
1478*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedVertexArrays =
1479*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(contextID, ResourceIDType::VertexArray);
1480*8975f5c5SAndroid Build Coastguard Worker ResourceSet &newVertexArrays = trackedVertexArrays.getNewResources();
1481*8975f5c5SAndroid Build Coastguard Worker ResourceSet &vertexArraysToDelete = trackedVertexArrays.getResourcesToDelete();
1482*8975f5c5SAndroid Build Coastguard Worker ResourceSet &vertexArraysToRegen = trackedVertexArrays.getResourcesToRegen();
1483*8975f5c5SAndroid Build Coastguard Worker ResourceSet &vertexArraysToRestore = trackedVertexArrays.getResourcesToRestore();
1484*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &vertexArrayRegenCalls = trackedVertexArrays.getResourceRegenCalls();
1485*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &vertexArrayRestoreCalls = trackedVertexArrays.getResourceRestoreCalls();
1486*8975f5c5SAndroid Build Coastguard Worker
1487*8975f5c5SAndroid Build Coastguard Worker DeleteResourcesInReset(out, contextID, newVertexArrays, vertexArraysToDelete,
1488*8975f5c5SAndroid Build Coastguard Worker resourceIDType, maxResourceIDBufferSize);
1489*8975f5c5SAndroid Build Coastguard Worker
1490*8975f5c5SAndroid Build Coastguard Worker // If any of our starting vertex arrays were deleted during the run, recreate them
1491*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : vertexArraysToRegen)
1492*8975f5c5SAndroid Build Coastguard Worker {
1493*8975f5c5SAndroid Build Coastguard Worker // Emit their regen calls
1494*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : vertexArrayRegenCalls[id])
1495*8975f5c5SAndroid Build Coastguard Worker {
1496*8975f5c5SAndroid Build Coastguard Worker out << " ";
1497*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1498*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1499*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1500*8975f5c5SAndroid Build Coastguard Worker }
1501*8975f5c5SAndroid Build Coastguard Worker }
1502*8975f5c5SAndroid Build Coastguard Worker
1503*8975f5c5SAndroid Build Coastguard Worker // If any of our starting vertex arrays were modified during the run, restore their
1504*8975f5c5SAndroid Build Coastguard Worker // contents
1505*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : vertexArraysToRestore)
1506*8975f5c5SAndroid Build Coastguard Worker {
1507*8975f5c5SAndroid Build Coastguard Worker // Emit their restore calls
1508*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : vertexArrayRestoreCalls[id])
1509*8975f5c5SAndroid Build Coastguard Worker {
1510*8975f5c5SAndroid Build Coastguard Worker out << " ";
1511*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1512*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1513*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1514*8975f5c5SAndroid Build Coastguard Worker }
1515*8975f5c5SAndroid Build Coastguard Worker }
1516*8975f5c5SAndroid Build Coastguard Worker break;
1517*8975f5c5SAndroid Build Coastguard Worker }
1518*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::egl_Sync:
1519*8975f5c5SAndroid Build Coastguard Worker {
1520*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedEGLSyncs =
1521*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(contextID, ResourceIDType::egl_Sync);
1522*8975f5c5SAndroid Build Coastguard Worker ResourceSet &newEGLSyncs = trackedEGLSyncs.getNewResources();
1523*8975f5c5SAndroid Build Coastguard Worker ResourceSet &eglSyncsToDelete = trackedEGLSyncs.getResourcesToDelete();
1524*8975f5c5SAndroid Build Coastguard Worker ResourceSet &eglSyncsToRegen = trackedEGLSyncs.getResourcesToRegen();
1525*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &eglSyncRegenCalls = trackedEGLSyncs.getResourceRegenCalls();
1526*8975f5c5SAndroid Build Coastguard Worker
1527*8975f5c5SAndroid Build Coastguard Worker if (!newEGLSyncs.empty() || !eglSyncsToDelete.empty())
1528*8975f5c5SAndroid Build Coastguard Worker {
1529*8975f5c5SAndroid Build Coastguard Worker for (GLuint oldResource : eglSyncsToDelete)
1530*8975f5c5SAndroid Build Coastguard Worker {
1531*8975f5c5SAndroid Build Coastguard Worker out << " eglDestroySyncKHR(gEGLDisplay, gEGLSyncMap[" << oldResource
1532*8975f5c5SAndroid Build Coastguard Worker << "]);\n";
1533*8975f5c5SAndroid Build Coastguard Worker }
1534*8975f5c5SAndroid Build Coastguard Worker
1535*8975f5c5SAndroid Build Coastguard Worker for (GLuint newResource : newEGLSyncs)
1536*8975f5c5SAndroid Build Coastguard Worker {
1537*8975f5c5SAndroid Build Coastguard Worker out << " eglDestroySyncKHR(gEGLDisplay, gEGLSyncMap[" << newResource
1538*8975f5c5SAndroid Build Coastguard Worker << "]);\n";
1539*8975f5c5SAndroid Build Coastguard Worker }
1540*8975f5c5SAndroid Build Coastguard Worker }
1541*8975f5c5SAndroid Build Coastguard Worker
1542*8975f5c5SAndroid Build Coastguard Worker // If any of our starting EGLsyncs were deleted during the run, recreate them
1543*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : eglSyncsToRegen)
1544*8975f5c5SAndroid Build Coastguard Worker {
1545*8975f5c5SAndroid Build Coastguard Worker // Emit their regen calls
1546*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : eglSyncRegenCalls[id])
1547*8975f5c5SAndroid Build Coastguard Worker {
1548*8975f5c5SAndroid Build Coastguard Worker out << " ";
1549*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1550*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1551*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1552*8975f5c5SAndroid Build Coastguard Worker }
1553*8975f5c5SAndroid Build Coastguard Worker }
1554*8975f5c5SAndroid Build Coastguard Worker break;
1555*8975f5c5SAndroid Build Coastguard Worker }
1556*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Image:
1557*8975f5c5SAndroid Build Coastguard Worker {
1558*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedEGLImages =
1559*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(contextID, ResourceIDType::Image);
1560*8975f5c5SAndroid Build Coastguard Worker ResourceSet &newEGLImages = trackedEGLImages.getNewResources();
1561*8975f5c5SAndroid Build Coastguard Worker ResourceSet &eglImagesToDelete = trackedEGLImages.getResourcesToDelete();
1562*8975f5c5SAndroid Build Coastguard Worker ResourceSet &eglImagesToRegen = trackedEGLImages.getResourcesToRegen();
1563*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &eglImageRegenCalls = trackedEGLImages.getResourceRegenCalls();
1564*8975f5c5SAndroid Build Coastguard Worker
1565*8975f5c5SAndroid Build Coastguard Worker if (!newEGLImages.empty() || !eglImagesToDelete.empty())
1566*8975f5c5SAndroid Build Coastguard Worker {
1567*8975f5c5SAndroid Build Coastguard Worker for (GLuint oldResource : eglImagesToDelete)
1568*8975f5c5SAndroid Build Coastguard Worker {
1569*8975f5c5SAndroid Build Coastguard Worker out << " DestroyEGLImageKHR(gEGLDisplay, gEGLImageMap2[" << oldResource
1570*8975f5c5SAndroid Build Coastguard Worker << "], " << oldResource << ");\n";
1571*8975f5c5SAndroid Build Coastguard Worker }
1572*8975f5c5SAndroid Build Coastguard Worker
1573*8975f5c5SAndroid Build Coastguard Worker for (GLuint newResource : newEGLImages)
1574*8975f5c5SAndroid Build Coastguard Worker {
1575*8975f5c5SAndroid Build Coastguard Worker out << " DestroyEGLImageKHR(gEGLDisplay, gEGLImageMap2[" << newResource
1576*8975f5c5SAndroid Build Coastguard Worker << "], " << newResource << ");\n";
1577*8975f5c5SAndroid Build Coastguard Worker }
1578*8975f5c5SAndroid Build Coastguard Worker }
1579*8975f5c5SAndroid Build Coastguard Worker // If any of our starting EGLImages were deleted during the run, recreate them
1580*8975f5c5SAndroid Build Coastguard Worker for (GLuint id : eglImagesToRegen)
1581*8975f5c5SAndroid Build Coastguard Worker {
1582*8975f5c5SAndroid Build Coastguard Worker // Emit their regen calls
1583*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : eglImageRegenCalls[id])
1584*8975f5c5SAndroid Build Coastguard Worker {
1585*8975f5c5SAndroid Build Coastguard Worker out << " ";
1586*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1587*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1588*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1589*8975f5c5SAndroid Build Coastguard Worker }
1590*8975f5c5SAndroid Build Coastguard Worker }
1591*8975f5c5SAndroid Build Coastguard Worker break;
1592*8975f5c5SAndroid Build Coastguard Worker }
1593*8975f5c5SAndroid Build Coastguard Worker default:
1594*8975f5c5SAndroid Build Coastguard Worker // TODO (http://anglebug.com/42263204): Reset more resource types
1595*8975f5c5SAndroid Build Coastguard Worker break;
1596*8975f5c5SAndroid Build Coastguard Worker }
1597*8975f5c5SAndroid Build Coastguard Worker
1598*8975f5c5SAndroid Build Coastguard Worker // If the output position has moved, we Reset something
1599*8975f5c5SAndroid Build Coastguard Worker anyResourceReset = (initialOutPos != out.tellp());
1600*8975f5c5SAndroid Build Coastguard Worker }
1601*8975f5c5SAndroid Build Coastguard Worker
MaybeResetFenceSyncObjects(std::stringstream & out,ReplayWriter & replayWriter,std::stringstream & header,ResourceTracker * resourceTracker,std::vector<uint8_t> * binaryData,size_t * maxResourceIDBufferSize)1602*8975f5c5SAndroid Build Coastguard Worker void MaybeResetFenceSyncObjects(std::stringstream &out,
1603*8975f5c5SAndroid Build Coastguard Worker ReplayWriter &replayWriter,
1604*8975f5c5SAndroid Build Coastguard Worker std::stringstream &header,
1605*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
1606*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> *binaryData,
1607*8975f5c5SAndroid Build Coastguard Worker size_t *maxResourceIDBufferSize)
1608*8975f5c5SAndroid Build Coastguard Worker {
1609*8975f5c5SAndroid Build Coastguard Worker FenceSyncCalls &fenceSyncRegenCalls = resourceTracker->getFenceSyncRegenCalls();
1610*8975f5c5SAndroid Build Coastguard Worker
1611*8975f5c5SAndroid Build Coastguard Worker // If any of our starting fence sync objects were deleted during the run, recreate them
1612*8975f5c5SAndroid Build Coastguard Worker FenceSyncSet &fenceSyncsToRegen = resourceTracker->getFenceSyncsToRegen();
1613*8975f5c5SAndroid Build Coastguard Worker for (const gl::SyncID syncID : fenceSyncsToRegen)
1614*8975f5c5SAndroid Build Coastguard Worker {
1615*8975f5c5SAndroid Build Coastguard Worker // Emit their regen calls
1616*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : fenceSyncRegenCalls[syncID])
1617*8975f5c5SAndroid Build Coastguard Worker {
1618*8975f5c5SAndroid Build Coastguard Worker out << " ";
1619*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1620*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1621*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1622*8975f5c5SAndroid Build Coastguard Worker }
1623*8975f5c5SAndroid Build Coastguard Worker }
1624*8975f5c5SAndroid Build Coastguard Worker }
1625*8975f5c5SAndroid Build Coastguard Worker
Capture(std::vector<CallCapture> * setupCalls,CallCapture && call)1626*8975f5c5SAndroid Build Coastguard Worker void Capture(std::vector<CallCapture> *setupCalls, CallCapture &&call)
1627*8975f5c5SAndroid Build Coastguard Worker {
1628*8975f5c5SAndroid Build Coastguard Worker setupCalls->emplace_back(std::move(call));
1629*8975f5c5SAndroid Build Coastguard Worker }
1630*8975f5c5SAndroid Build Coastguard Worker
CaptureUpdateCurrentProgram(const CallCapture & call,int programParamPos,std::vector<CallCapture> * callsOut)1631*8975f5c5SAndroid Build Coastguard Worker void CaptureUpdateCurrentProgram(const CallCapture &call,
1632*8975f5c5SAndroid Build Coastguard Worker int programParamPos,
1633*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *callsOut)
1634*8975f5c5SAndroid Build Coastguard Worker {
1635*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶m =
1636*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("programPacked", ParamType::TShaderProgramID, programParamPos);
1637*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID programID = param.value.ShaderProgramIDVal;
1638*8975f5c5SAndroid Build Coastguard Worker
1639*8975f5c5SAndroid Build Coastguard Worker ParamBuffer paramBuffer;
1640*8975f5c5SAndroid Build Coastguard Worker paramBuffer.addValueParam("program", ParamType::TGLuint, programID.value);
1641*8975f5c5SAndroid Build Coastguard Worker
1642*8975f5c5SAndroid Build Coastguard Worker callsOut->emplace_back("UpdateCurrentProgram", std::move(paramBuffer));
1643*8975f5c5SAndroid Build Coastguard Worker }
1644*8975f5c5SAndroid Build Coastguard Worker
ProgramNeedsReset(const gl::Context * context,ResourceTracker * resourceTracker,gl::ShaderProgramID programID)1645*8975f5c5SAndroid Build Coastguard Worker bool ProgramNeedsReset(const gl::Context *context,
1646*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
1647*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID programID)
1648*8975f5c5SAndroid Build Coastguard Worker {
1649*8975f5c5SAndroid Build Coastguard Worker // Check whether the program is listed in programs to regen or restore
1650*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedShaderPrograms =
1651*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::ShaderProgram);
1652*8975f5c5SAndroid Build Coastguard Worker
1653*8975f5c5SAndroid Build Coastguard Worker ResourceSet &shaderProgramsToRegen = trackedShaderPrograms.getResourcesToRegen();
1654*8975f5c5SAndroid Build Coastguard Worker if (shaderProgramsToRegen.count(programID.value) != 0)
1655*8975f5c5SAndroid Build Coastguard Worker {
1656*8975f5c5SAndroid Build Coastguard Worker return true;
1657*8975f5c5SAndroid Build Coastguard Worker }
1658*8975f5c5SAndroid Build Coastguard Worker
1659*8975f5c5SAndroid Build Coastguard Worker ResourceSet &shaderProgramsToRestore = trackedShaderPrograms.getResourcesToRestore();
1660*8975f5c5SAndroid Build Coastguard Worker if (shaderProgramsToRestore.count(programID.value) != 0)
1661*8975f5c5SAndroid Build Coastguard Worker {
1662*8975f5c5SAndroid Build Coastguard Worker return true;
1663*8975f5c5SAndroid Build Coastguard Worker }
1664*8975f5c5SAndroid Build Coastguard Worker
1665*8975f5c5SAndroid Build Coastguard Worker // Deferred linked programs will also update their own uniforms
1666*8975f5c5SAndroid Build Coastguard Worker FrameCaptureShared *frameCaptureShared = context->getShareGroup()->getFrameCaptureShared();
1667*8975f5c5SAndroid Build Coastguard Worker if (frameCaptureShared->isDeferredLinkProgram(programID))
1668*8975f5c5SAndroid Build Coastguard Worker {
1669*8975f5c5SAndroid Build Coastguard Worker return true;
1670*8975f5c5SAndroid Build Coastguard Worker }
1671*8975f5c5SAndroid Build Coastguard Worker
1672*8975f5c5SAndroid Build Coastguard Worker return false;
1673*8975f5c5SAndroid Build Coastguard Worker }
1674*8975f5c5SAndroid Build Coastguard Worker
MaybeResetDefaultUniforms(std::stringstream & out,ReplayWriter & replayWriter,std::stringstream & header,const gl::Context * context,ResourceTracker * resourceTracker,std::vector<uint8_t> * binaryData,size_t * maxResourceIDBufferSize)1675*8975f5c5SAndroid Build Coastguard Worker void MaybeResetDefaultUniforms(std::stringstream &out,
1676*8975f5c5SAndroid Build Coastguard Worker ReplayWriter &replayWriter,
1677*8975f5c5SAndroid Build Coastguard Worker std::stringstream &header,
1678*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context,
1679*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
1680*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> *binaryData,
1681*8975f5c5SAndroid Build Coastguard Worker size_t *maxResourceIDBufferSize)
1682*8975f5c5SAndroid Build Coastguard Worker {
1683*8975f5c5SAndroid Build Coastguard Worker DefaultUniformLocationsPerProgramMap &defaultUniformsToReset =
1684*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getDefaultUniformsToReset();
1685*8975f5c5SAndroid Build Coastguard Worker
1686*8975f5c5SAndroid Build Coastguard Worker for (const auto &uniformIter : defaultUniformsToReset)
1687*8975f5c5SAndroid Build Coastguard Worker {
1688*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID programID = uniformIter.first;
1689*8975f5c5SAndroid Build Coastguard Worker const DefaultUniformLocationsSet &locations = uniformIter.second;
1690*8975f5c5SAndroid Build Coastguard Worker
1691*8975f5c5SAndroid Build Coastguard Worker if (ProgramNeedsReset(context, resourceTracker, programID))
1692*8975f5c5SAndroid Build Coastguard Worker {
1693*8975f5c5SAndroid Build Coastguard Worker // Skip programs marked for reset as they will update their own uniforms
1694*8975f5c5SAndroid Build Coastguard Worker return;
1695*8975f5c5SAndroid Build Coastguard Worker }
1696*8975f5c5SAndroid Build Coastguard Worker
1697*8975f5c5SAndroid Build Coastguard Worker // Bind the program to update its uniforms
1698*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> bindCalls;
1699*8975f5c5SAndroid Build Coastguard Worker Capture(&bindCalls, CaptureUseProgram(context->getState(), true, programID));
1700*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateCurrentProgram((&bindCalls)->back(), 0, &bindCalls);
1701*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : bindCalls)
1702*8975f5c5SAndroid Build Coastguard Worker {
1703*8975f5c5SAndroid Build Coastguard Worker out << " ";
1704*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1705*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1706*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1707*8975f5c5SAndroid Build Coastguard Worker }
1708*8975f5c5SAndroid Build Coastguard Worker
1709*8975f5c5SAndroid Build Coastguard Worker DefaultUniformCallsPerLocationMap &defaultUniformResetCalls =
1710*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getDefaultUniformResetCalls(programID);
1711*8975f5c5SAndroid Build Coastguard Worker
1712*8975f5c5SAndroid Build Coastguard Worker // Uniform arrays might have been modified in the middle (i.e. location 5 out of 10)
1713*8975f5c5SAndroid Build Coastguard Worker // We only have Reset calls for the entire array, so emit them once for the entire array
1714*8975f5c5SAndroid Build Coastguard Worker std::set<gl::UniformLocation> alreadyReset;
1715*8975f5c5SAndroid Build Coastguard Worker
1716*8975f5c5SAndroid Build Coastguard Worker // Emit the reset calls per modified location
1717*8975f5c5SAndroid Build Coastguard Worker for (const gl::UniformLocation &location : locations)
1718*8975f5c5SAndroid Build Coastguard Worker {
1719*8975f5c5SAndroid Build Coastguard Worker gl::UniformLocation baseLocation =
1720*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getDefaultUniformBaseLocation(programID, location);
1721*8975f5c5SAndroid Build Coastguard Worker if (alreadyReset.find(baseLocation) != alreadyReset.end())
1722*8975f5c5SAndroid Build Coastguard Worker {
1723*8975f5c5SAndroid Build Coastguard Worker // We've already Reset this array
1724*8975f5c5SAndroid Build Coastguard Worker continue;
1725*8975f5c5SAndroid Build Coastguard Worker }
1726*8975f5c5SAndroid Build Coastguard Worker alreadyReset.insert(baseLocation);
1727*8975f5c5SAndroid Build Coastguard Worker
1728*8975f5c5SAndroid Build Coastguard Worker ASSERT(defaultUniformResetCalls.find(baseLocation) != defaultUniformResetCalls.end());
1729*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> &callsPerLocation = defaultUniformResetCalls[baseLocation];
1730*8975f5c5SAndroid Build Coastguard Worker
1731*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : callsPerLocation)
1732*8975f5c5SAndroid Build Coastguard Worker {
1733*8975f5c5SAndroid Build Coastguard Worker out << " ";
1734*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1735*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1736*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1737*8975f5c5SAndroid Build Coastguard Worker }
1738*8975f5c5SAndroid Build Coastguard Worker }
1739*8975f5c5SAndroid Build Coastguard Worker }
1740*8975f5c5SAndroid Build Coastguard Worker }
1741*8975f5c5SAndroid Build Coastguard Worker
MaybeResetOpaqueTypeObjects(ReplayWriter & replayWriter,std::stringstream & out,std::stringstream & header,const gl::Context * context,ResourceTracker * resourceTracker,std::vector<uint8_t> * binaryData,size_t * maxResourceIDBufferSize)1742*8975f5c5SAndroid Build Coastguard Worker void MaybeResetOpaqueTypeObjects(ReplayWriter &replayWriter,
1743*8975f5c5SAndroid Build Coastguard Worker std::stringstream &out,
1744*8975f5c5SAndroid Build Coastguard Worker std::stringstream &header,
1745*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context,
1746*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
1747*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> *binaryData,
1748*8975f5c5SAndroid Build Coastguard Worker size_t *maxResourceIDBufferSize)
1749*8975f5c5SAndroid Build Coastguard Worker {
1750*8975f5c5SAndroid Build Coastguard Worker MaybeResetFenceSyncObjects(out, replayWriter, header, resourceTracker, binaryData,
1751*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1752*8975f5c5SAndroid Build Coastguard Worker
1753*8975f5c5SAndroid Build Coastguard Worker MaybeResetDefaultUniforms(out, replayWriter, header, context, resourceTracker, binaryData,
1754*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1755*8975f5c5SAndroid Build Coastguard Worker }
1756*8975f5c5SAndroid Build Coastguard Worker
MaybeResetContextState(ReplayWriter & replayWriter,std::stringstream & out,std::stringstream & header,ResourceTracker * resourceTracker,const gl::Context * context,std::vector<uint8_t> * binaryData,StateResetHelper & stateResetHelper,size_t * maxResourceIDBufferSize)1757*8975f5c5SAndroid Build Coastguard Worker void MaybeResetContextState(ReplayWriter &replayWriter,
1758*8975f5c5SAndroid Build Coastguard Worker std::stringstream &out,
1759*8975f5c5SAndroid Build Coastguard Worker std::stringstream &header,
1760*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
1761*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context,
1762*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> *binaryData,
1763*8975f5c5SAndroid Build Coastguard Worker StateResetHelper &stateResetHelper,
1764*8975f5c5SAndroid Build Coastguard Worker size_t *maxResourceIDBufferSize)
1765*8975f5c5SAndroid Build Coastguard Worker {
1766*8975f5c5SAndroid Build Coastguard Worker // Check dirty states per entrypoint
1767*8975f5c5SAndroid Build Coastguard Worker for (const EntryPoint &entryPoint : stateResetHelper.getDirtyEntryPoints())
1768*8975f5c5SAndroid Build Coastguard Worker {
1769*8975f5c5SAndroid Build Coastguard Worker const CallResetMap *resetCalls = &stateResetHelper.getResetCalls();
1770*8975f5c5SAndroid Build Coastguard Worker
1771*8975f5c5SAndroid Build Coastguard Worker // Create the default reset call for this entrypoint
1772*8975f5c5SAndroid Build Coastguard Worker if (resetCalls->find(entryPoint) == resetCalls->end())
1773*8975f5c5SAndroid Build Coastguard Worker {
1774*8975f5c5SAndroid Build Coastguard Worker // If we don't have any reset calls for these entrypoints, that means we started capture
1775*8975f5c5SAndroid Build Coastguard Worker // from the beginning, amd mid-execution capture was not invoked.
1776*8975f5c5SAndroid Build Coastguard Worker stateResetHelper.setDefaultResetCalls(context, entryPoint);
1777*8975f5c5SAndroid Build Coastguard Worker }
1778*8975f5c5SAndroid Build Coastguard Worker
1779*8975f5c5SAndroid Build Coastguard Worker // Emit the calls, if we added any
1780*8975f5c5SAndroid Build Coastguard Worker if (resetCalls->find(entryPoint) != resetCalls->end())
1781*8975f5c5SAndroid Build Coastguard Worker {
1782*8975f5c5SAndroid Build Coastguard Worker for (const auto &call : resetCalls->at(entryPoint))
1783*8975f5c5SAndroid Build Coastguard Worker {
1784*8975f5c5SAndroid Build Coastguard Worker out << " ";
1785*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1786*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1787*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1788*8975f5c5SAndroid Build Coastguard Worker }
1789*8975f5c5SAndroid Build Coastguard Worker }
1790*8975f5c5SAndroid Build Coastguard Worker }
1791*8975f5c5SAndroid Build Coastguard Worker
1792*8975f5c5SAndroid Build Coastguard Worker // Reset buffer bindings that weren't bound at the beginning
1793*8975f5c5SAndroid Build Coastguard Worker for (const gl::BufferBinding &dirtyBufferBinding : stateResetHelper.getDirtyBufferBindings())
1794*8975f5c5SAndroid Build Coastguard Worker {
1795*8975f5c5SAndroid Build Coastguard Worker // Check to see if dirty binding was part of starting set
1796*8975f5c5SAndroid Build Coastguard Worker bool dirtyStartingBinding = false;
1797*8975f5c5SAndroid Build Coastguard Worker for (const BufferBindingPair &startingBufferBinding :
1798*8975f5c5SAndroid Build Coastguard Worker stateResetHelper.getStartingBufferBindings())
1799*8975f5c5SAndroid Build Coastguard Worker {
1800*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding startingBinding = startingBufferBinding.first;
1801*8975f5c5SAndroid Build Coastguard Worker if (startingBinding == dirtyBufferBinding)
1802*8975f5c5SAndroid Build Coastguard Worker {
1803*8975f5c5SAndroid Build Coastguard Worker dirtyStartingBinding = true;
1804*8975f5c5SAndroid Build Coastguard Worker }
1805*8975f5c5SAndroid Build Coastguard Worker }
1806*8975f5c5SAndroid Build Coastguard Worker
1807*8975f5c5SAndroid Build Coastguard Worker // If the dirty binding was not part of starting bindings, clear it
1808*8975f5c5SAndroid Build Coastguard Worker if (!dirtyStartingBinding)
1809*8975f5c5SAndroid Build Coastguard Worker {
1810*8975f5c5SAndroid Build Coastguard Worker out << " ";
1811*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(
1812*8975f5c5SAndroid Build Coastguard Worker CaptureBindBuffer(context->getState(), true, dirtyBufferBinding, {0}), replayWriter,
1813*8975f5c5SAndroid Build Coastguard Worker out, header, binaryData, maxResourceIDBufferSize);
1814*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1815*8975f5c5SAndroid Build Coastguard Worker }
1816*8975f5c5SAndroid Build Coastguard Worker }
1817*8975f5c5SAndroid Build Coastguard Worker
1818*8975f5c5SAndroid Build Coastguard Worker // Restore starting buffer bindings to initial state
1819*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> &bufferBindingCalls = resourceTracker->getBufferBindingCalls();
1820*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : bufferBindingCalls)
1821*8975f5c5SAndroid Build Coastguard Worker {
1822*8975f5c5SAndroid Build Coastguard Worker out << " ";
1823*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData, maxResourceIDBufferSize);
1824*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1825*8975f5c5SAndroid Build Coastguard Worker }
1826*8975f5c5SAndroid Build Coastguard Worker
1827*8975f5c5SAndroid Build Coastguard Worker // Restore texture bindings to initial state
1828*8975f5c5SAndroid Build Coastguard Worker size_t activeTexture = context->getState().getActiveSampler();
1829*8975f5c5SAndroid Build Coastguard Worker const TextureResetMap &resetBindings = stateResetHelper.getResetTextureBindings();
1830*8975f5c5SAndroid Build Coastguard Worker for (const auto &textureBinding : stateResetHelper.getDirtyTextureBindings())
1831*8975f5c5SAndroid Build Coastguard Worker {
1832*8975f5c5SAndroid Build Coastguard Worker TextureResetMap::const_iterator id = resetBindings.find(textureBinding);
1833*8975f5c5SAndroid Build Coastguard Worker if (id != resetBindings.end())
1834*8975f5c5SAndroid Build Coastguard Worker {
1835*8975f5c5SAndroid Build Coastguard Worker const auto &[unit, target] = textureBinding;
1836*8975f5c5SAndroid Build Coastguard Worker
1837*8975f5c5SAndroid Build Coastguard Worker // Set active texture unit if necessary
1838*8975f5c5SAndroid Build Coastguard Worker if (unit != activeTexture)
1839*8975f5c5SAndroid Build Coastguard Worker {
1840*8975f5c5SAndroid Build Coastguard Worker out << " ";
1841*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(CaptureActiveTexture(context->getState(), true,
1842*8975f5c5SAndroid Build Coastguard Worker GL_TEXTURE0 + static_cast<GLenum>(unit)),
1843*8975f5c5SAndroid Build Coastguard Worker replayWriter, out, header, binaryData,
1844*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1845*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1846*8975f5c5SAndroid Build Coastguard Worker activeTexture = unit;
1847*8975f5c5SAndroid Build Coastguard Worker }
1848*8975f5c5SAndroid Build Coastguard Worker
1849*8975f5c5SAndroid Build Coastguard Worker // Bind texture for this target
1850*8975f5c5SAndroid Build Coastguard Worker out << " ";
1851*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(CaptureBindTexture(context->getState(), true, target, id->second),
1852*8975f5c5SAndroid Build Coastguard Worker replayWriter, out, header, binaryData, maxResourceIDBufferSize);
1853*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1854*8975f5c5SAndroid Build Coastguard Worker }
1855*8975f5c5SAndroid Build Coastguard Worker }
1856*8975f5c5SAndroid Build Coastguard Worker
1857*8975f5c5SAndroid Build Coastguard Worker // Restore active texture unit to initial state if necessary
1858*8975f5c5SAndroid Build Coastguard Worker if (activeTexture != stateResetHelper.getResetActiveTexture())
1859*8975f5c5SAndroid Build Coastguard Worker {
1860*8975f5c5SAndroid Build Coastguard Worker out << " ";
1861*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(
1862*8975f5c5SAndroid Build Coastguard Worker CaptureActiveTexture(
1863*8975f5c5SAndroid Build Coastguard Worker context->getState(), true,
1864*8975f5c5SAndroid Build Coastguard Worker GL_TEXTURE0 + static_cast<GLenum>(stateResetHelper.getResetActiveTexture())),
1865*8975f5c5SAndroid Build Coastguard Worker replayWriter, out, header, binaryData, maxResourceIDBufferSize);
1866*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1867*8975f5c5SAndroid Build Coastguard Worker }
1868*8975f5c5SAndroid Build Coastguard Worker }
1869*8975f5c5SAndroid Build Coastguard Worker
MarkResourceIDActive(ResourceIDType resourceType,GLuint id,std::vector<CallCapture> * setupCalls,const ResourceIDToSetupCallsMap * resourceIDToSetupCallsMap)1870*8975f5c5SAndroid Build Coastguard Worker void MarkResourceIDActive(ResourceIDType resourceType,
1871*8975f5c5SAndroid Build Coastguard Worker GLuint id,
1872*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *setupCalls,
1873*8975f5c5SAndroid Build Coastguard Worker const ResourceIDToSetupCallsMap *resourceIDToSetupCallsMap)
1874*8975f5c5SAndroid Build Coastguard Worker {
1875*8975f5c5SAndroid Build Coastguard Worker const std::map<GLuint, gl::Range<size_t>> &resourceSetupCalls =
1876*8975f5c5SAndroid Build Coastguard Worker (*resourceIDToSetupCallsMap)[resourceType];
1877*8975f5c5SAndroid Build Coastguard Worker const auto iter = resourceSetupCalls.find(id);
1878*8975f5c5SAndroid Build Coastguard Worker if (iter == resourceSetupCalls.end())
1879*8975f5c5SAndroid Build Coastguard Worker {
1880*8975f5c5SAndroid Build Coastguard Worker return;
1881*8975f5c5SAndroid Build Coastguard Worker }
1882*8975f5c5SAndroid Build Coastguard Worker
1883*8975f5c5SAndroid Build Coastguard Worker // Mark all of the calls that were used to initialize this resource as ACTIVE
1884*8975f5c5SAndroid Build Coastguard Worker const gl::Range<size_t> &calls = iter->second;
1885*8975f5c5SAndroid Build Coastguard Worker for (size_t index : calls)
1886*8975f5c5SAndroid Build Coastguard Worker {
1887*8975f5c5SAndroid Build Coastguard Worker (*setupCalls)[index].isActive = true;
1888*8975f5c5SAndroid Build Coastguard Worker }
1889*8975f5c5SAndroid Build Coastguard Worker }
1890*8975f5c5SAndroid Build Coastguard Worker
1891*8975f5c5SAndroid Build Coastguard Worker // Some replay functions can get quite large. If over a certain size, this method breaks up the
1892*8975f5c5SAndroid Build Coastguard Worker // function into parts to avoid overflowing the stack and causing slow compilation.
WriteCppReplayFunctionWithParts(const gl::ContextID contextID,ReplayFunc replayFunc,ReplayWriter & replayWriter,uint32_t frameIndex,std::vector<uint8_t> * binaryData,const std::vector<CallCapture> & calls,std::stringstream & header,std::stringstream & out,size_t * maxResourceIDBufferSize)1893*8975f5c5SAndroid Build Coastguard Worker void WriteCppReplayFunctionWithParts(const gl::ContextID contextID,
1894*8975f5c5SAndroid Build Coastguard Worker ReplayFunc replayFunc,
1895*8975f5c5SAndroid Build Coastguard Worker ReplayWriter &replayWriter,
1896*8975f5c5SAndroid Build Coastguard Worker uint32_t frameIndex,
1897*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> *binaryData,
1898*8975f5c5SAndroid Build Coastguard Worker const std::vector<CallCapture> &calls,
1899*8975f5c5SAndroid Build Coastguard Worker std::stringstream &header,
1900*8975f5c5SAndroid Build Coastguard Worker std::stringstream &out,
1901*8975f5c5SAndroid Build Coastguard Worker size_t *maxResourceIDBufferSize)
1902*8975f5c5SAndroid Build Coastguard Worker {
1903*8975f5c5SAndroid Build Coastguard Worker int callCount = 0;
1904*8975f5c5SAndroid Build Coastguard Worker int partCount = 0;
1905*8975f5c5SAndroid Build Coastguard Worker
1906*8975f5c5SAndroid Build Coastguard Worker if (calls.size() > kFunctionSizeLimit)
1907*8975f5c5SAndroid Build Coastguard Worker {
1908*8975f5c5SAndroid Build Coastguard Worker out << "void "
1909*8975f5c5SAndroid Build Coastguard Worker << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex, ++partCount)
1910*8975f5c5SAndroid Build Coastguard Worker << "\n";
1911*8975f5c5SAndroid Build Coastguard Worker }
1912*8975f5c5SAndroid Build Coastguard Worker else
1913*8975f5c5SAndroid Build Coastguard Worker {
1914*8975f5c5SAndroid Build Coastguard Worker out << "void "
1915*8975f5c5SAndroid Build Coastguard Worker << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex, kNoPartId)
1916*8975f5c5SAndroid Build Coastguard Worker << "\n";
1917*8975f5c5SAndroid Build Coastguard Worker }
1918*8975f5c5SAndroid Build Coastguard Worker
1919*8975f5c5SAndroid Build Coastguard Worker out << "{\n";
1920*8975f5c5SAndroid Build Coastguard Worker
1921*8975f5c5SAndroid Build Coastguard Worker for (const CallCapture &call : calls)
1922*8975f5c5SAndroid Build Coastguard Worker {
1923*8975f5c5SAndroid Build Coastguard Worker // Process active calls for Setup and inactive calls for SetupInactive
1924*8975f5c5SAndroid Build Coastguard Worker if ((call.isActive && replayFunc != ReplayFunc::SetupInactive) ||
1925*8975f5c5SAndroid Build Coastguard Worker (!call.isActive && replayFunc == ReplayFunc::SetupInactive))
1926*8975f5c5SAndroid Build Coastguard Worker {
1927*8975f5c5SAndroid Build Coastguard Worker out << " ";
1928*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
1929*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
1930*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
1931*8975f5c5SAndroid Build Coastguard Worker
1932*8975f5c5SAndroid Build Coastguard Worker if (partCount > 0 && ++callCount % kFunctionSizeLimit == 0)
1933*8975f5c5SAndroid Build Coastguard Worker {
1934*8975f5c5SAndroid Build Coastguard Worker out << "}\n";
1935*8975f5c5SAndroid Build Coastguard Worker out << "\n";
1936*8975f5c5SAndroid Build Coastguard Worker out << "void "
1937*8975f5c5SAndroid Build Coastguard Worker << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex,
1938*8975f5c5SAndroid Build Coastguard Worker ++partCount)
1939*8975f5c5SAndroid Build Coastguard Worker << "\n";
1940*8975f5c5SAndroid Build Coastguard Worker out << "{\n";
1941*8975f5c5SAndroid Build Coastguard Worker }
1942*8975f5c5SAndroid Build Coastguard Worker }
1943*8975f5c5SAndroid Build Coastguard Worker }
1944*8975f5c5SAndroid Build Coastguard Worker out << "}\n";
1945*8975f5c5SAndroid Build Coastguard Worker
1946*8975f5c5SAndroid Build Coastguard Worker if (partCount > 0)
1947*8975f5c5SAndroid Build Coastguard Worker {
1948*8975f5c5SAndroid Build Coastguard Worker out << "\n";
1949*8975f5c5SAndroid Build Coastguard Worker out << "void "
1950*8975f5c5SAndroid Build Coastguard Worker << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex, kNoPartId)
1951*8975f5c5SAndroid Build Coastguard Worker << "\n";
1952*8975f5c5SAndroid Build Coastguard Worker out << "{\n";
1953*8975f5c5SAndroid Build Coastguard Worker
1954*8975f5c5SAndroid Build Coastguard Worker // Write out the main call which calls all the parts.
1955*8975f5c5SAndroid Build Coastguard Worker for (int i = 1; i <= partCount; i++)
1956*8975f5c5SAndroid Build Coastguard Worker {
1957*8975f5c5SAndroid Build Coastguard Worker out << " " << FmtFunction(replayFunc, contextID, FuncUsage::Call, frameIndex, i)
1958*8975f5c5SAndroid Build Coastguard Worker << ";\n";
1959*8975f5c5SAndroid Build Coastguard Worker }
1960*8975f5c5SAndroid Build Coastguard Worker
1961*8975f5c5SAndroid Build Coastguard Worker out << "}\n";
1962*8975f5c5SAndroid Build Coastguard Worker }
1963*8975f5c5SAndroid Build Coastguard Worker }
1964*8975f5c5SAndroid Build Coastguard Worker
1965*8975f5c5SAndroid Build Coastguard Worker // Performance can be gained by reordering traced calls and grouping them by context.
1966*8975f5c5SAndroid Build Coastguard Worker // Side context calls (as opposed to main context) can be grouped together paying attention
1967*8975f5c5SAndroid Build Coastguard Worker // to synchronization points in the original call stream.
WriteCppReplayFunctionWithPartsMultiContext(const gl::ContextID contextID,ReplayFunc replayFunc,ReplayWriter & replayWriter,uint32_t frameIndex,std::vector<uint8_t> * binaryData,std::vector<CallCapture> & calls,std::stringstream & header,std::stringstream & out,size_t * maxResourceIDBufferSize)1968*8975f5c5SAndroid Build Coastguard Worker void WriteCppReplayFunctionWithPartsMultiContext(const gl::ContextID contextID,
1969*8975f5c5SAndroid Build Coastguard Worker ReplayFunc replayFunc,
1970*8975f5c5SAndroid Build Coastguard Worker ReplayWriter &replayWriter,
1971*8975f5c5SAndroid Build Coastguard Worker uint32_t frameIndex,
1972*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> *binaryData,
1973*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> &calls,
1974*8975f5c5SAndroid Build Coastguard Worker std::stringstream &header,
1975*8975f5c5SAndroid Build Coastguard Worker std::stringstream &out,
1976*8975f5c5SAndroid Build Coastguard Worker size_t *maxResourceIDBufferSize)
1977*8975f5c5SAndroid Build Coastguard Worker {
1978*8975f5c5SAndroid Build Coastguard Worker int callCount = 0;
1979*8975f5c5SAndroid Build Coastguard Worker int partCount = 0;
1980*8975f5c5SAndroid Build Coastguard Worker
1981*8975f5c5SAndroid Build Coastguard Worker if (calls.size() > kFunctionSizeLimit)
1982*8975f5c5SAndroid Build Coastguard Worker {
1983*8975f5c5SAndroid Build Coastguard Worker out << "void "
1984*8975f5c5SAndroid Build Coastguard Worker << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex, ++partCount)
1985*8975f5c5SAndroid Build Coastguard Worker << "\n";
1986*8975f5c5SAndroid Build Coastguard Worker }
1987*8975f5c5SAndroid Build Coastguard Worker else
1988*8975f5c5SAndroid Build Coastguard Worker {
1989*8975f5c5SAndroid Build Coastguard Worker out << "void "
1990*8975f5c5SAndroid Build Coastguard Worker << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex, kNoPartId)
1991*8975f5c5SAndroid Build Coastguard Worker << "\n";
1992*8975f5c5SAndroid Build Coastguard Worker }
1993*8975f5c5SAndroid Build Coastguard Worker
1994*8975f5c5SAndroid Build Coastguard Worker out << "{\n";
1995*8975f5c5SAndroid Build Coastguard Worker
1996*8975f5c5SAndroid Build Coastguard Worker std::map<gl::ContextID, std::queue<int>> sideContextCallIndices;
1997*8975f5c5SAndroid Build Coastguard Worker
1998*8975f5c5SAndroid Build Coastguard Worker // Helper lambda to write a context change command to the call stream
1999*8975f5c5SAndroid Build Coastguard Worker auto writeMakeCurrentCall = [&](gl::ContextID cID) {
2000*8975f5c5SAndroid Build Coastguard Worker CallCapture makeCurrentCall =
2001*8975f5c5SAndroid Build Coastguard Worker egl::CaptureMakeCurrent(nullptr, true, nullptr, {0}, {0}, cID, EGL_TRUE);
2002*8975f5c5SAndroid Build Coastguard Worker out << " ";
2003*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(makeCurrentCall, replayWriter, out, header, binaryData,
2004*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
2005*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
2006*8975f5c5SAndroid Build Coastguard Worker callCount++;
2007*8975f5c5SAndroid Build Coastguard Worker };
2008*8975f5c5SAndroid Build Coastguard Worker
2009*8975f5c5SAndroid Build Coastguard Worker // Helper lambda to write a call to the call stream
2010*8975f5c5SAndroid Build Coastguard Worker auto writeCall = [&](CallCapture &outCall, gl::ContextID cID) {
2011*8975f5c5SAndroid Build Coastguard Worker out << " ";
2012*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayForCall(outCall, replayWriter, out, header, binaryData,
2013*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
2014*8975f5c5SAndroid Build Coastguard Worker out << ";\n";
2015*8975f5c5SAndroid Build Coastguard Worker if (cID != contextID)
2016*8975f5c5SAndroid Build Coastguard Worker {
2017*8975f5c5SAndroid Build Coastguard Worker sideContextCallIndices[cID].pop();
2018*8975f5c5SAndroid Build Coastguard Worker }
2019*8975f5c5SAndroid Build Coastguard Worker callCount++;
2020*8975f5c5SAndroid Build Coastguard Worker };
2021*8975f5c5SAndroid Build Coastguard Worker
2022*8975f5c5SAndroid Build Coastguard Worker int callIndex = 0;
2023*8975f5c5SAndroid Build Coastguard Worker // Iterate through calls saving side context call indices in a per-side-context queue
2024*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : calls)
2025*8975f5c5SAndroid Build Coastguard Worker {
2026*8975f5c5SAndroid Build Coastguard Worker if (call.contextID != contextID)
2027*8975f5c5SAndroid Build Coastguard Worker {
2028*8975f5c5SAndroid Build Coastguard Worker sideContextCallIndices[call.contextID].push(callIndex);
2029*8975f5c5SAndroid Build Coastguard Worker }
2030*8975f5c5SAndroid Build Coastguard Worker callIndex++;
2031*8975f5c5SAndroid Build Coastguard Worker }
2032*8975f5c5SAndroid Build Coastguard Worker
2033*8975f5c5SAndroid Build Coastguard Worker // At the beginning of the frame, output all side context calls occuring before a sync point.
2034*8975f5c5SAndroid Build Coastguard Worker // If no sync points are present, all calls in that side context are written at this time
2035*8975f5c5SAndroid Build Coastguard Worker for (auto const &sideContext : sideContextCallIndices)
2036*8975f5c5SAndroid Build Coastguard Worker {
2037*8975f5c5SAndroid Build Coastguard Worker gl::ContextID sideContextID = sideContext.first;
2038*8975f5c5SAndroid Build Coastguard Worker
2039*8975f5c5SAndroid Build Coastguard Worker // Make sidecontext current if there are commands before the first syncpoint
2040*8975f5c5SAndroid Build Coastguard Worker if (!calls[sideContextCallIndices[sideContextID].front()].isSyncPoint)
2041*8975f5c5SAndroid Build Coastguard Worker {
2042*8975f5c5SAndroid Build Coastguard Worker writeMakeCurrentCall(sideContextID);
2043*8975f5c5SAndroid Build Coastguard Worker }
2044*8975f5c5SAndroid Build Coastguard Worker // Output all commands in sidecontext until a syncpoint is reached
2045*8975f5c5SAndroid Build Coastguard Worker while (!sideContextCallIndices[sideContextID].empty() &&
2046*8975f5c5SAndroid Build Coastguard Worker !calls[sideContextCallIndices[sideContextID].front()].isSyncPoint)
2047*8975f5c5SAndroid Build Coastguard Worker {
2048*8975f5c5SAndroid Build Coastguard Worker writeCall(calls[sideContextCallIndices[sideContextID].front()], sideContextID);
2049*8975f5c5SAndroid Build Coastguard Worker }
2050*8975f5c5SAndroid Build Coastguard Worker }
2051*8975f5c5SAndroid Build Coastguard Worker
2052*8975f5c5SAndroid Build Coastguard Worker // Make mainContext current
2053*8975f5c5SAndroid Build Coastguard Worker writeMakeCurrentCall(contextID);
2054*8975f5c5SAndroid Build Coastguard Worker
2055*8975f5c5SAndroid Build Coastguard Worker // Iterate through calls writing out main context calls. When a sync point is reached, write the
2056*8975f5c5SAndroid Build Coastguard Worker // next queued sequence of side context calls until another sync point is reached.
2057*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : calls)
2058*8975f5c5SAndroid Build Coastguard Worker {
2059*8975f5c5SAndroid Build Coastguard Worker if (call.contextID == contextID)
2060*8975f5c5SAndroid Build Coastguard Worker {
2061*8975f5c5SAndroid Build Coastguard Worker writeCall(call, call.contextID);
2062*8975f5c5SAndroid Build Coastguard Worker }
2063*8975f5c5SAndroid Build Coastguard Worker else
2064*8975f5c5SAndroid Build Coastguard Worker {
2065*8975f5c5SAndroid Build Coastguard Worker if (call.isSyncPoint)
2066*8975f5c5SAndroid Build Coastguard Worker {
2067*8975f5c5SAndroid Build Coastguard Worker // Make sideContext current
2068*8975f5c5SAndroid Build Coastguard Worker writeMakeCurrentCall(call.contextID);
2069*8975f5c5SAndroid Build Coastguard Worker
2070*8975f5c5SAndroid Build Coastguard Worker do
2071*8975f5c5SAndroid Build Coastguard Worker {
2072*8975f5c5SAndroid Build Coastguard Worker writeCall(calls[sideContextCallIndices[call.contextID].front()],
2073*8975f5c5SAndroid Build Coastguard Worker call.contextID);
2074*8975f5c5SAndroid Build Coastguard Worker } while (!sideContextCallIndices[call.contextID].empty() &&
2075*8975f5c5SAndroid Build Coastguard Worker !calls[sideContextCallIndices[call.contextID].front()].isSyncPoint);
2076*8975f5c5SAndroid Build Coastguard Worker
2077*8975f5c5SAndroid Build Coastguard Worker // Make mainContext current
2078*8975f5c5SAndroid Build Coastguard Worker writeMakeCurrentCall(contextID);
2079*8975f5c5SAndroid Build Coastguard Worker
2080*8975f5c5SAndroid Build Coastguard Worker if (partCount > 0 && ++callCount % kFunctionSizeLimit == 0)
2081*8975f5c5SAndroid Build Coastguard Worker {
2082*8975f5c5SAndroid Build Coastguard Worker out << "}\n";
2083*8975f5c5SAndroid Build Coastguard Worker out << "\n";
2084*8975f5c5SAndroid Build Coastguard Worker out << "void "
2085*8975f5c5SAndroid Build Coastguard Worker << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex,
2086*8975f5c5SAndroid Build Coastguard Worker ++partCount)
2087*8975f5c5SAndroid Build Coastguard Worker << "\n";
2088*8975f5c5SAndroid Build Coastguard Worker out << "{\n";
2089*8975f5c5SAndroid Build Coastguard Worker }
2090*8975f5c5SAndroid Build Coastguard Worker }
2091*8975f5c5SAndroid Build Coastguard Worker }
2092*8975f5c5SAndroid Build Coastguard Worker }
2093*8975f5c5SAndroid Build Coastguard Worker out << "}\n";
2094*8975f5c5SAndroid Build Coastguard Worker
2095*8975f5c5SAndroid Build Coastguard Worker if (partCount > 0)
2096*8975f5c5SAndroid Build Coastguard Worker {
2097*8975f5c5SAndroid Build Coastguard Worker out << "\n";
2098*8975f5c5SAndroid Build Coastguard Worker out << "void "
2099*8975f5c5SAndroid Build Coastguard Worker << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex, kNoPartId)
2100*8975f5c5SAndroid Build Coastguard Worker << "\n";
2101*8975f5c5SAndroid Build Coastguard Worker out << "{\n";
2102*8975f5c5SAndroid Build Coastguard Worker
2103*8975f5c5SAndroid Build Coastguard Worker // Write out the main call which calls all the parts.
2104*8975f5c5SAndroid Build Coastguard Worker for (int i = 1; i <= partCount; i++)
2105*8975f5c5SAndroid Build Coastguard Worker {
2106*8975f5c5SAndroid Build Coastguard Worker out << " " << FmtFunction(replayFunc, contextID, FuncUsage::Call, frameIndex, i)
2107*8975f5c5SAndroid Build Coastguard Worker << ";\n";
2108*8975f5c5SAndroid Build Coastguard Worker }
2109*8975f5c5SAndroid Build Coastguard Worker
2110*8975f5c5SAndroid Build Coastguard Worker out << "}\n";
2111*8975f5c5SAndroid Build Coastguard Worker }
2112*8975f5c5SAndroid Build Coastguard Worker }
2113*8975f5c5SAndroid Build Coastguard Worker
2114*8975f5c5SAndroid Build Coastguard Worker // Auxiliary contexts are other contexts in the share group that aren't the context calling
2115*8975f5c5SAndroid Build Coastguard Worker // eglSwapBuffers().
WriteAuxiliaryContextCppSetupReplay(ReplayWriter & replayWriter,bool compression,const std::string & outDir,const gl::Context * context,const std::string & captureLabel,uint32_t frameIndex,const std::vector<CallCapture> & setupCalls,std::vector<uint8_t> * binaryData,bool serializeStateEnabled,const FrameCaptureShared & frameCaptureShared,size_t * maxResourceIDBufferSize)2116*8975f5c5SAndroid Build Coastguard Worker void WriteAuxiliaryContextCppSetupReplay(ReplayWriter &replayWriter,
2117*8975f5c5SAndroid Build Coastguard Worker bool compression,
2118*8975f5c5SAndroid Build Coastguard Worker const std::string &outDir,
2119*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context,
2120*8975f5c5SAndroid Build Coastguard Worker const std::string &captureLabel,
2121*8975f5c5SAndroid Build Coastguard Worker uint32_t frameIndex,
2122*8975f5c5SAndroid Build Coastguard Worker const std::vector<CallCapture> &setupCalls,
2123*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> *binaryData,
2124*8975f5c5SAndroid Build Coastguard Worker bool serializeStateEnabled,
2125*8975f5c5SAndroid Build Coastguard Worker const FrameCaptureShared &frameCaptureShared,
2126*8975f5c5SAndroid Build Coastguard Worker size_t *maxResourceIDBufferSize)
2127*8975f5c5SAndroid Build Coastguard Worker {
2128*8975f5c5SAndroid Build Coastguard Worker ASSERT(frameCaptureShared.getWindowSurfaceContextID() != context->id());
2129*8975f5c5SAndroid Build Coastguard Worker
2130*8975f5c5SAndroid Build Coastguard Worker {
2131*8975f5c5SAndroid Build Coastguard Worker std::stringstream filenameStream;
2132*8975f5c5SAndroid Build Coastguard Worker filenameStream << outDir << FmtCapturePrefix(context->id(), captureLabel);
2133*8975f5c5SAndroid Build Coastguard Worker std::string filenamePattern = filenameStream.str();
2134*8975f5c5SAndroid Build Coastguard Worker replayWriter.setFilenamePattern(filenamePattern);
2135*8975f5c5SAndroid Build Coastguard Worker }
2136*8975f5c5SAndroid Build Coastguard Worker
2137*8975f5c5SAndroid Build Coastguard Worker {
2138*8975f5c5SAndroid Build Coastguard Worker std::stringstream include;
2139*8975f5c5SAndroid Build Coastguard Worker include << "#include \""
2140*8975f5c5SAndroid Build Coastguard Worker << FmtCapturePrefix(frameCaptureShared.getWindowSurfaceContextID(), captureLabel)
2141*8975f5c5SAndroid Build Coastguard Worker << ".h\"\n";
2142*8975f5c5SAndroid Build Coastguard Worker include << "#include \"angle_trace_gl.h\"\n";
2143*8975f5c5SAndroid Build Coastguard Worker
2144*8975f5c5SAndroid Build Coastguard Worker std::string frameIncludes = include.str();
2145*8975f5c5SAndroid Build Coastguard Worker replayWriter.setSourcePrologue(frameIncludes);
2146*8975f5c5SAndroid Build Coastguard Worker replayWriter.setHeaderPrologue(frameIncludes);
2147*8975f5c5SAndroid Build Coastguard Worker }
2148*8975f5c5SAndroid Build Coastguard Worker
2149*8975f5c5SAndroid Build Coastguard Worker {
2150*8975f5c5SAndroid Build Coastguard Worker std::stringstream protoStream;
2151*8975f5c5SAndroid Build Coastguard Worker std::stringstream headerStream;
2152*8975f5c5SAndroid Build Coastguard Worker std::stringstream bodyStream;
2153*8975f5c5SAndroid Build Coastguard Worker
2154*8975f5c5SAndroid Build Coastguard Worker protoStream << "void " << FmtSetupFunction(kNoPartId, context->id(), FuncUsage::Prototype);
2155*8975f5c5SAndroid Build Coastguard Worker std::string proto = protoStream.str();
2156*8975f5c5SAndroid Build Coastguard Worker
2157*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayFunctionWithParts(context->id(), ReplayFunc::Setup, replayWriter, frameIndex,
2158*8975f5c5SAndroid Build Coastguard Worker binaryData, setupCalls, headerStream, bodyStream,
2159*8975f5c5SAndroid Build Coastguard Worker maxResourceIDBufferSize);
2160*8975f5c5SAndroid Build Coastguard Worker
2161*8975f5c5SAndroid Build Coastguard Worker replayWriter.addPrivateFunction(proto, headerStream, bodyStream);
2162*8975f5c5SAndroid Build Coastguard Worker }
2163*8975f5c5SAndroid Build Coastguard Worker
2164*8975f5c5SAndroid Build Coastguard Worker replayWriter.saveFrame();
2165*8975f5c5SAndroid Build Coastguard Worker }
2166*8975f5c5SAndroid Build Coastguard Worker
WriteShareGroupCppSetupReplay(ReplayWriter & replayWriter,bool compression,const std::string & outDir,const std::string & captureLabel,uint32_t frameIndex,uint32_t frameCount,const std::vector<CallCapture> & setupCalls,ResourceTracker * resourceTracker,std::vector<uint8_t> * binaryData,bool serializeStateEnabled,gl::ContextID windowSurfaceContextID,size_t * maxResourceIDBufferSize)2167*8975f5c5SAndroid Build Coastguard Worker void WriteShareGroupCppSetupReplay(ReplayWriter &replayWriter,
2168*8975f5c5SAndroid Build Coastguard Worker bool compression,
2169*8975f5c5SAndroid Build Coastguard Worker const std::string &outDir,
2170*8975f5c5SAndroid Build Coastguard Worker const std::string &captureLabel,
2171*8975f5c5SAndroid Build Coastguard Worker uint32_t frameIndex,
2172*8975f5c5SAndroid Build Coastguard Worker uint32_t frameCount,
2173*8975f5c5SAndroid Build Coastguard Worker const std::vector<CallCapture> &setupCalls,
2174*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
2175*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> *binaryData,
2176*8975f5c5SAndroid Build Coastguard Worker bool serializeStateEnabled,
2177*8975f5c5SAndroid Build Coastguard Worker gl::ContextID windowSurfaceContextID,
2178*8975f5c5SAndroid Build Coastguard Worker size_t *maxResourceIDBufferSize)
2179*8975f5c5SAndroid Build Coastguard Worker {
2180*8975f5c5SAndroid Build Coastguard Worker {
2181*8975f5c5SAndroid Build Coastguard Worker
2182*8975f5c5SAndroid Build Coastguard Worker std::stringstream include;
2183*8975f5c5SAndroid Build Coastguard Worker
2184*8975f5c5SAndroid Build Coastguard Worker include << "#include \"angle_trace_gl.h\"\n";
2185*8975f5c5SAndroid Build Coastguard Worker include << "#include \"" << FmtCapturePrefix(windowSurfaceContextID, captureLabel)
2186*8975f5c5SAndroid Build Coastguard Worker << ".h\"\n";
2187*8975f5c5SAndroid Build Coastguard Worker
2188*8975f5c5SAndroid Build Coastguard Worker std::string includeString = include.str();
2189*8975f5c5SAndroid Build Coastguard Worker
2190*8975f5c5SAndroid Build Coastguard Worker replayWriter.setSourcePrologue(includeString);
2191*8975f5c5SAndroid Build Coastguard Worker }
2192*8975f5c5SAndroid Build Coastguard Worker
2193*8975f5c5SAndroid Build Coastguard Worker {
2194*8975f5c5SAndroid Build Coastguard Worker std::stringstream protoStream;
2195*8975f5c5SAndroid Build Coastguard Worker std::stringstream headerStream;
2196*8975f5c5SAndroid Build Coastguard Worker std::stringstream bodyStream;
2197*8975f5c5SAndroid Build Coastguard Worker
2198*8975f5c5SAndroid Build Coastguard Worker protoStream << "void "
2199*8975f5c5SAndroid Build Coastguard Worker << FmtSetupFunction(kNoPartId, kSharedContextId, FuncUsage::Prototype);
2200*8975f5c5SAndroid Build Coastguard Worker std::string proto = protoStream.str();
2201*8975f5c5SAndroid Build Coastguard Worker
2202*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayFunctionWithParts(kSharedContextId, ReplayFunc::Setup, replayWriter,
2203*8975f5c5SAndroid Build Coastguard Worker frameIndex, binaryData, setupCalls, headerStream,
2204*8975f5c5SAndroid Build Coastguard Worker bodyStream, maxResourceIDBufferSize);
2205*8975f5c5SAndroid Build Coastguard Worker
2206*8975f5c5SAndroid Build Coastguard Worker replayWriter.addPrivateFunction(proto, headerStream, bodyStream);
2207*8975f5c5SAndroid Build Coastguard Worker
2208*8975f5c5SAndroid Build Coastguard Worker protoStream.str("");
2209*8975f5c5SAndroid Build Coastguard Worker headerStream.str("");
2210*8975f5c5SAndroid Build Coastguard Worker bodyStream.str("");
2211*8975f5c5SAndroid Build Coastguard Worker protoStream << "void "
2212*8975f5c5SAndroid Build Coastguard Worker << FmtSetupInactiveFunction(kNoPartId, kSharedContextId, FuncUsage::Prototype);
2213*8975f5c5SAndroid Build Coastguard Worker proto = protoStream.str();
2214*8975f5c5SAndroid Build Coastguard Worker
2215*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayFunctionWithParts(kSharedContextId, ReplayFunc::SetupInactive, replayWriter,
2216*8975f5c5SAndroid Build Coastguard Worker frameIndex, binaryData, setupCalls, headerStream,
2217*8975f5c5SAndroid Build Coastguard Worker bodyStream, maxResourceIDBufferSize);
2218*8975f5c5SAndroid Build Coastguard Worker replayWriter.addPrivateFunction(proto, headerStream, bodyStream);
2219*8975f5c5SAndroid Build Coastguard Worker }
2220*8975f5c5SAndroid Build Coastguard Worker
2221*8975f5c5SAndroid Build Coastguard Worker {
2222*8975f5c5SAndroid Build Coastguard Worker std::stringstream filenameStream;
2223*8975f5c5SAndroid Build Coastguard Worker filenameStream << outDir << FmtCapturePrefix(kSharedContextId, captureLabel);
2224*8975f5c5SAndroid Build Coastguard Worker
2225*8975f5c5SAndroid Build Coastguard Worker std::string filenamePattern = filenameStream.str();
2226*8975f5c5SAndroid Build Coastguard Worker
2227*8975f5c5SAndroid Build Coastguard Worker replayWriter.setFilenamePattern(filenamePattern);
2228*8975f5c5SAndroid Build Coastguard Worker }
2229*8975f5c5SAndroid Build Coastguard Worker
2230*8975f5c5SAndroid Build Coastguard Worker replayWriter.saveSetupFile();
2231*8975f5c5SAndroid Build Coastguard Worker }
2232*8975f5c5SAndroid Build Coastguard Worker
GetAttachedProgramSources(const gl::Context * context,const gl::Program * program)2233*8975f5c5SAndroid Build Coastguard Worker ProgramSources GetAttachedProgramSources(const gl::Context *context, const gl::Program *program)
2234*8975f5c5SAndroid Build Coastguard Worker {
2235*8975f5c5SAndroid Build Coastguard Worker ProgramSources sources;
2236*8975f5c5SAndroid Build Coastguard Worker for (gl::ShaderType shaderType : gl::AllShaderTypes())
2237*8975f5c5SAndroid Build Coastguard Worker {
2238*8975f5c5SAndroid Build Coastguard Worker const gl::Shader *shader = program->getAttachedShader(shaderType);
2239*8975f5c5SAndroid Build Coastguard Worker if (shader)
2240*8975f5c5SAndroid Build Coastguard Worker {
2241*8975f5c5SAndroid Build Coastguard Worker sources[shaderType] = shader->getSourceString();
2242*8975f5c5SAndroid Build Coastguard Worker }
2243*8975f5c5SAndroid Build Coastguard Worker }
2244*8975f5c5SAndroid Build Coastguard Worker return sources;
2245*8975f5c5SAndroid Build Coastguard Worker }
2246*8975f5c5SAndroid Build Coastguard Worker
2247*8975f5c5SAndroid Build Coastguard Worker template <typename IDType>
CaptureUpdateResourceIDs(const gl::Context * context,const CallCapture & call,const ParamCapture & param,ResourceTracker * resourceTracker,std::vector<CallCapture> * callsOut)2248*8975f5c5SAndroid Build Coastguard Worker void CaptureUpdateResourceIDs(const gl::Context *context,
2249*8975f5c5SAndroid Build Coastguard Worker const CallCapture &call,
2250*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶m,
2251*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
2252*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *callsOut)
2253*8975f5c5SAndroid Build Coastguard Worker {
2254*8975f5c5SAndroid Build Coastguard Worker GLsizei n = call.params.getParamFlexName("n", "count", ParamType::TGLsizei, 0).value.GLsizeiVal;
2255*8975f5c5SAndroid Build Coastguard Worker ASSERT(param.data.size() == 1);
2256*8975f5c5SAndroid Build Coastguard Worker ResourceIDType resourceIDType = GetResourceIDTypeFromParamType(param.type);
2257*8975f5c5SAndroid Build Coastguard Worker ASSERT(resourceIDType != ResourceIDType::InvalidEnum &&
2258*8975f5c5SAndroid Build Coastguard Worker resourceIDType != ResourceIDType::ShaderProgram);
2259*8975f5c5SAndroid Build Coastguard Worker const char *resourceName = GetResourceIDTypeName(resourceIDType);
2260*8975f5c5SAndroid Build Coastguard Worker
2261*8975f5c5SAndroid Build Coastguard Worker std::stringstream updateFuncNameStr;
2262*8975f5c5SAndroid Build Coastguard Worker updateFuncNameStr << "Update" << resourceName << "ID";
2263*8975f5c5SAndroid Build Coastguard Worker bool trackedPerContext = IsTrackedPerContext(resourceIDType);
2264*8975f5c5SAndroid Build Coastguard Worker if (trackedPerContext)
2265*8975f5c5SAndroid Build Coastguard Worker {
2266*8975f5c5SAndroid Build Coastguard Worker // TODO (https://issuetracker.google.com/169868803) The '2' version can be removed after all
2267*8975f5c5SAndroid Build Coastguard Worker // context-local objects are tracked per-context
2268*8975f5c5SAndroid Build Coastguard Worker updateFuncNameStr << "2";
2269*8975f5c5SAndroid Build Coastguard Worker }
2270*8975f5c5SAndroid Build Coastguard Worker std::string updateFuncName = updateFuncNameStr.str();
2271*8975f5c5SAndroid Build Coastguard Worker
2272*8975f5c5SAndroid Build Coastguard Worker const IDType *returnedIDs = reinterpret_cast<const IDType *>(param.data[0].data());
2273*8975f5c5SAndroid Build Coastguard Worker
2274*8975f5c5SAndroid Build Coastguard Worker ResourceSet &startingSet =
2275*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), resourceIDType).getStartingResources();
2276*8975f5c5SAndroid Build Coastguard Worker
2277*8975f5c5SAndroid Build Coastguard Worker for (GLsizei idIndex = 0; idIndex < n; ++idIndex)
2278*8975f5c5SAndroid Build Coastguard Worker {
2279*8975f5c5SAndroid Build Coastguard Worker IDType id = returnedIDs[idIndex];
2280*8975f5c5SAndroid Build Coastguard Worker GLsizei readBufferOffset = idIndex * sizeof(gl::RenderbufferID);
2281*8975f5c5SAndroid Build Coastguard Worker ParamBuffer params;
2282*8975f5c5SAndroid Build Coastguard Worker if (trackedPerContext)
2283*8975f5c5SAndroid Build Coastguard Worker {
2284*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("contextId", ParamType::TGLuint, context->id().value);
2285*8975f5c5SAndroid Build Coastguard Worker }
2286*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("id", ParamType::TGLuint, id.value);
2287*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("readBufferOffset", ParamType::TGLsizei, readBufferOffset);
2288*8975f5c5SAndroid Build Coastguard Worker callsOut->emplace_back(updateFuncName, std::move(params));
2289*8975f5c5SAndroid Build Coastguard Worker
2290*8975f5c5SAndroid Build Coastguard Worker // Add only if not in starting resources.
2291*8975f5c5SAndroid Build Coastguard Worker if (startingSet.find(id.value) == startingSet.end())
2292*8975f5c5SAndroid Build Coastguard Worker {
2293*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), resourceIDType)
2294*8975f5c5SAndroid Build Coastguard Worker .getNewResources()
2295*8975f5c5SAndroid Build Coastguard Worker .insert(id.value);
2296*8975f5c5SAndroid Build Coastguard Worker }
2297*8975f5c5SAndroid Build Coastguard Worker }
2298*8975f5c5SAndroid Build Coastguard Worker }
2299*8975f5c5SAndroid Build Coastguard Worker
CaptureUpdateUniformLocations(const gl::Program * program,std::vector<CallCapture> * callsOut)2300*8975f5c5SAndroid Build Coastguard Worker void CaptureUpdateUniformLocations(const gl::Program *program, std::vector<CallCapture> *callsOut)
2301*8975f5c5SAndroid Build Coastguard Worker {
2302*8975f5c5SAndroid Build Coastguard Worker const gl::ProgramExecutable &executable = program->getExecutable();
2303*8975f5c5SAndroid Build Coastguard Worker const std::vector<gl::LinkedUniform> &uniforms = executable.getUniforms();
2304*8975f5c5SAndroid Build Coastguard Worker const std::vector<gl::VariableLocation> &locations = executable.getUniformLocations();
2305*8975f5c5SAndroid Build Coastguard Worker
2306*8975f5c5SAndroid Build Coastguard Worker for (GLint location = 0; location < static_cast<GLint>(locations.size()); ++location)
2307*8975f5c5SAndroid Build Coastguard Worker {
2308*8975f5c5SAndroid Build Coastguard Worker const gl::VariableLocation &locationVar = locations[location];
2309*8975f5c5SAndroid Build Coastguard Worker
2310*8975f5c5SAndroid Build Coastguard Worker // This handles the case where the application calls glBindUniformLocationCHROMIUM
2311*8975f5c5SAndroid Build Coastguard Worker // on an unused uniform. We must still store a -1 into gUniformLocations in case the
2312*8975f5c5SAndroid Build Coastguard Worker // application attempts to call a glUniform* call. To do this we'll pass in a blank name to
2313*8975f5c5SAndroid Build Coastguard Worker // force glGetUniformLocation to return -1.
2314*8975f5c5SAndroid Build Coastguard Worker std::string name;
2315*8975f5c5SAndroid Build Coastguard Worker int count = 1;
2316*8975f5c5SAndroid Build Coastguard Worker ParamBuffer params;
2317*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("program", ParamType::TGLuint, program->id().value);
2318*8975f5c5SAndroid Build Coastguard Worker
2319*8975f5c5SAndroid Build Coastguard Worker if (locationVar.index >= uniforms.size())
2320*8975f5c5SAndroid Build Coastguard Worker {
2321*8975f5c5SAndroid Build Coastguard Worker name = "";
2322*8975f5c5SAndroid Build Coastguard Worker }
2323*8975f5c5SAndroid Build Coastguard Worker else
2324*8975f5c5SAndroid Build Coastguard Worker {
2325*8975f5c5SAndroid Build Coastguard Worker const gl::LinkedUniform &uniform = uniforms[locationVar.index];
2326*8975f5c5SAndroid Build Coastguard Worker
2327*8975f5c5SAndroid Build Coastguard Worker name = executable.getUniformNameByIndex(locationVar.index);
2328*8975f5c5SAndroid Build Coastguard Worker
2329*8975f5c5SAndroid Build Coastguard Worker if (uniform.isArray())
2330*8975f5c5SAndroid Build Coastguard Worker {
2331*8975f5c5SAndroid Build Coastguard Worker if (locationVar.arrayIndex > 0)
2332*8975f5c5SAndroid Build Coastguard Worker {
2333*8975f5c5SAndroid Build Coastguard Worker // Non-sequential array uniform locations are not currently handled.
2334*8975f5c5SAndroid Build Coastguard Worker // In practice array locations shouldn't ever be non-sequential.
2335*8975f5c5SAndroid Build Coastguard Worker ASSERT(uniform.getLocation() == -1 ||
2336*8975f5c5SAndroid Build Coastguard Worker location ==
2337*8975f5c5SAndroid Build Coastguard Worker uniform.getLocation() + static_cast<int>(locationVar.arrayIndex));
2338*8975f5c5SAndroid Build Coastguard Worker continue;
2339*8975f5c5SAndroid Build Coastguard Worker }
2340*8975f5c5SAndroid Build Coastguard Worker
2341*8975f5c5SAndroid Build Coastguard Worker name = gl::StripLastArrayIndex(name);
2342*8975f5c5SAndroid Build Coastguard Worker count = uniform.getBasicTypeElementCount();
2343*8975f5c5SAndroid Build Coastguard Worker }
2344*8975f5c5SAndroid Build Coastguard Worker }
2345*8975f5c5SAndroid Build Coastguard Worker
2346*8975f5c5SAndroid Build Coastguard Worker ParamCapture nameParam("name", ParamType::TGLcharConstPointer);
2347*8975f5c5SAndroid Build Coastguard Worker CaptureString(name.c_str(), &nameParam);
2348*8975f5c5SAndroid Build Coastguard Worker params.addParam(std::move(nameParam));
2349*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("location", ParamType::TGLint, location);
2350*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("count", ParamType::TGLint, static_cast<GLint>(count));
2351*8975f5c5SAndroid Build Coastguard Worker callsOut->emplace_back("UpdateUniformLocation", std::move(params));
2352*8975f5c5SAndroid Build Coastguard Worker }
2353*8975f5c5SAndroid Build Coastguard Worker }
2354*8975f5c5SAndroid Build Coastguard Worker
CaptureValidateSerializedState(const gl::Context * context,std::vector<CallCapture> * callsOut)2355*8975f5c5SAndroid Build Coastguard Worker void CaptureValidateSerializedState(const gl::Context *context, std::vector<CallCapture> *callsOut)
2356*8975f5c5SAndroid Build Coastguard Worker {
2357*8975f5c5SAndroid Build Coastguard Worker INFO() << "Capturing validation checkpoint at position " << callsOut->size();
2358*8975f5c5SAndroid Build Coastguard Worker
2359*8975f5c5SAndroid Build Coastguard Worker context->finishImmutable();
2360*8975f5c5SAndroid Build Coastguard Worker
2361*8975f5c5SAndroid Build Coastguard Worker std::string serializedState;
2362*8975f5c5SAndroid Build Coastguard Worker angle::Result result = angle::SerializeContextToString(context, &serializedState);
2363*8975f5c5SAndroid Build Coastguard Worker if (result != angle::Result::Continue)
2364*8975f5c5SAndroid Build Coastguard Worker {
2365*8975f5c5SAndroid Build Coastguard Worker ERR() << "Internal error serializing context state.";
2366*8975f5c5SAndroid Build Coastguard Worker return;
2367*8975f5c5SAndroid Build Coastguard Worker }
2368*8975f5c5SAndroid Build Coastguard Worker ParamCapture serializedStateParam("serializedState", ParamType::TGLcharConstPointer);
2369*8975f5c5SAndroid Build Coastguard Worker CaptureString(serializedState.c_str(), &serializedStateParam);
2370*8975f5c5SAndroid Build Coastguard Worker
2371*8975f5c5SAndroid Build Coastguard Worker ParamBuffer params;
2372*8975f5c5SAndroid Build Coastguard Worker params.addParam(std::move(serializedStateParam));
2373*8975f5c5SAndroid Build Coastguard Worker
2374*8975f5c5SAndroid Build Coastguard Worker callsOut->emplace_back("VALIDATE_CHECKPOINT", std::move(params));
2375*8975f5c5SAndroid Build Coastguard Worker }
2376*8975f5c5SAndroid Build Coastguard Worker
CaptureUpdateUniformBlockIndexes(const gl::Program * program,std::vector<CallCapture> * callsOut)2377*8975f5c5SAndroid Build Coastguard Worker void CaptureUpdateUniformBlockIndexes(const gl::Program *program,
2378*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *callsOut)
2379*8975f5c5SAndroid Build Coastguard Worker {
2380*8975f5c5SAndroid Build Coastguard Worker const std::vector<gl::InterfaceBlock> &uniformBlocks =
2381*8975f5c5SAndroid Build Coastguard Worker program->getExecutable().getUniformBlocks();
2382*8975f5c5SAndroid Build Coastguard Worker
2383*8975f5c5SAndroid Build Coastguard Worker for (GLuint index = 0; index < uniformBlocks.size(); ++index)
2384*8975f5c5SAndroid Build Coastguard Worker {
2385*8975f5c5SAndroid Build Coastguard Worker ParamBuffer params;
2386*8975f5c5SAndroid Build Coastguard Worker
2387*8975f5c5SAndroid Build Coastguard Worker std::string name;
2388*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("program", ParamType::TShaderProgramID, program->id());
2389*8975f5c5SAndroid Build Coastguard Worker
2390*8975f5c5SAndroid Build Coastguard Worker const std::string fullName = uniformBlocks[index].nameWithArrayIndex();
2391*8975f5c5SAndroid Build Coastguard Worker ParamCapture nameParam("name", ParamType::TGLcharConstPointer);
2392*8975f5c5SAndroid Build Coastguard Worker CaptureString(fullName.c_str(), &nameParam);
2393*8975f5c5SAndroid Build Coastguard Worker params.addParam(std::move(nameParam));
2394*8975f5c5SAndroid Build Coastguard Worker
2395*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("index", ParamType::TGLuint, index);
2396*8975f5c5SAndroid Build Coastguard Worker callsOut->emplace_back("UpdateUniformBlockIndex", std::move(params));
2397*8975f5c5SAndroid Build Coastguard Worker }
2398*8975f5c5SAndroid Build Coastguard Worker }
2399*8975f5c5SAndroid Build Coastguard Worker
CaptureDeleteUniformLocations(gl::ShaderProgramID program,std::vector<CallCapture> * callsOut)2400*8975f5c5SAndroid Build Coastguard Worker void CaptureDeleteUniformLocations(gl::ShaderProgramID program, std::vector<CallCapture> *callsOut)
2401*8975f5c5SAndroid Build Coastguard Worker {
2402*8975f5c5SAndroid Build Coastguard Worker ParamBuffer params;
2403*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("program", ParamType::TShaderProgramID, program);
2404*8975f5c5SAndroid Build Coastguard Worker callsOut->emplace_back("DeleteUniformLocations", std::move(params));
2405*8975f5c5SAndroid Build Coastguard Worker }
2406*8975f5c5SAndroid Build Coastguard Worker
MaybeCaptureUpdateResourceIDs(const gl::Context * context,ResourceTracker * resourceTracker,std::vector<CallCapture> * callsOut)2407*8975f5c5SAndroid Build Coastguard Worker void MaybeCaptureUpdateResourceIDs(const gl::Context *context,
2408*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
2409*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *callsOut)
2410*8975f5c5SAndroid Build Coastguard Worker {
2411*8975f5c5SAndroid Build Coastguard Worker const CallCapture &call = callsOut->back();
2412*8975f5c5SAndroid Build Coastguard Worker
2413*8975f5c5SAndroid Build Coastguard Worker switch (call.entryPoint)
2414*8975f5c5SAndroid Build Coastguard Worker {
2415*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenBuffers:
2416*8975f5c5SAndroid Build Coastguard Worker {
2417*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &buffers =
2418*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("buffersPacked", ParamType::TBufferIDPointer, 1);
2419*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateResourceIDs<gl::BufferID>(context, call, buffers, resourceTracker,
2420*8975f5c5SAndroid Build Coastguard Worker callsOut);
2421*8975f5c5SAndroid Build Coastguard Worker break;
2422*8975f5c5SAndroid Build Coastguard Worker }
2423*8975f5c5SAndroid Build Coastguard Worker
2424*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenFencesNV:
2425*8975f5c5SAndroid Build Coastguard Worker {
2426*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &fences =
2427*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("fencesPacked", ParamType::TFenceNVIDPointer, 1);
2428*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateResourceIDs<gl::FenceNVID>(context, call, fences, resourceTracker,
2429*8975f5c5SAndroid Build Coastguard Worker callsOut);
2430*8975f5c5SAndroid Build Coastguard Worker break;
2431*8975f5c5SAndroid Build Coastguard Worker }
2432*8975f5c5SAndroid Build Coastguard Worker
2433*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenFramebuffers:
2434*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenFramebuffersOES:
2435*8975f5c5SAndroid Build Coastguard Worker {
2436*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &framebuffers =
2437*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("framebuffersPacked", ParamType::TFramebufferIDPointer, 1);
2438*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateResourceIDs<gl::FramebufferID>(context, call, framebuffers,
2439*8975f5c5SAndroid Build Coastguard Worker resourceTracker, callsOut);
2440*8975f5c5SAndroid Build Coastguard Worker break;
2441*8975f5c5SAndroid Build Coastguard Worker }
2442*8975f5c5SAndroid Build Coastguard Worker
2443*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenProgramPipelines:
2444*8975f5c5SAndroid Build Coastguard Worker {
2445*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &pipelines =
2446*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("pipelinesPacked", ParamType::TProgramPipelineIDPointer, 1);
2447*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateResourceIDs<gl::ProgramPipelineID>(context, call, pipelines,
2448*8975f5c5SAndroid Build Coastguard Worker resourceTracker, callsOut);
2449*8975f5c5SAndroid Build Coastguard Worker break;
2450*8975f5c5SAndroid Build Coastguard Worker }
2451*8975f5c5SAndroid Build Coastguard Worker
2452*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenQueries:
2453*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenQueriesEXT:
2454*8975f5c5SAndroid Build Coastguard Worker {
2455*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &queries =
2456*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("idsPacked", ParamType::TQueryIDPointer, 1);
2457*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateResourceIDs<gl::QueryID>(context, call, queries, resourceTracker,
2458*8975f5c5SAndroid Build Coastguard Worker callsOut);
2459*8975f5c5SAndroid Build Coastguard Worker break;
2460*8975f5c5SAndroid Build Coastguard Worker }
2461*8975f5c5SAndroid Build Coastguard Worker
2462*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenRenderbuffers:
2463*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenRenderbuffersOES:
2464*8975f5c5SAndroid Build Coastguard Worker {
2465*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &renderbuffers =
2466*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("renderbuffersPacked", ParamType::TRenderbufferIDPointer, 1);
2467*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateResourceIDs<gl::RenderbufferID>(context, call, renderbuffers,
2468*8975f5c5SAndroid Build Coastguard Worker resourceTracker, callsOut);
2469*8975f5c5SAndroid Build Coastguard Worker break;
2470*8975f5c5SAndroid Build Coastguard Worker }
2471*8975f5c5SAndroid Build Coastguard Worker
2472*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenSamplers:
2473*8975f5c5SAndroid Build Coastguard Worker {
2474*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &samplers =
2475*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("samplersPacked", ParamType::TSamplerIDPointer, 1);
2476*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateResourceIDs<gl::SamplerID>(context, call, samplers, resourceTracker,
2477*8975f5c5SAndroid Build Coastguard Worker callsOut);
2478*8975f5c5SAndroid Build Coastguard Worker break;
2479*8975f5c5SAndroid Build Coastguard Worker }
2480*8975f5c5SAndroid Build Coastguard Worker
2481*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenSemaphoresEXT:
2482*8975f5c5SAndroid Build Coastguard Worker {
2483*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &semaphores =
2484*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("semaphoresPacked", ParamType::TSemaphoreIDPointer, 1);
2485*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateResourceIDs<gl::SemaphoreID>(context, call, semaphores, resourceTracker,
2486*8975f5c5SAndroid Build Coastguard Worker callsOut);
2487*8975f5c5SAndroid Build Coastguard Worker break;
2488*8975f5c5SAndroid Build Coastguard Worker }
2489*8975f5c5SAndroid Build Coastguard Worker
2490*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenTextures:
2491*8975f5c5SAndroid Build Coastguard Worker {
2492*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &textures =
2493*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("texturesPacked", ParamType::TTextureIDPointer, 1);
2494*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateResourceIDs<gl::TextureID>(context, call, textures, resourceTracker,
2495*8975f5c5SAndroid Build Coastguard Worker callsOut);
2496*8975f5c5SAndroid Build Coastguard Worker break;
2497*8975f5c5SAndroid Build Coastguard Worker }
2498*8975f5c5SAndroid Build Coastguard Worker
2499*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenTransformFeedbacks:
2500*8975f5c5SAndroid Build Coastguard Worker {
2501*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &xfbs =
2502*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("idsPacked", ParamType::TTransformFeedbackIDPointer, 1);
2503*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateResourceIDs<gl::TransformFeedbackID>(context, call, xfbs, resourceTracker,
2504*8975f5c5SAndroid Build Coastguard Worker callsOut);
2505*8975f5c5SAndroid Build Coastguard Worker break;
2506*8975f5c5SAndroid Build Coastguard Worker }
2507*8975f5c5SAndroid Build Coastguard Worker
2508*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenVertexArrays:
2509*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenVertexArraysOES:
2510*8975f5c5SAndroid Build Coastguard Worker {
2511*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &vertexArrays =
2512*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("arraysPacked", ParamType::TVertexArrayIDPointer, 1);
2513*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateResourceIDs<gl::VertexArrayID>(context, call, vertexArrays,
2514*8975f5c5SAndroid Build Coastguard Worker resourceTracker, callsOut);
2515*8975f5c5SAndroid Build Coastguard Worker break;
2516*8975f5c5SAndroid Build Coastguard Worker }
2517*8975f5c5SAndroid Build Coastguard Worker
2518*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCreateMemoryObjectsEXT:
2519*8975f5c5SAndroid Build Coastguard Worker {
2520*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &memoryObjects =
2521*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("memoryObjectsPacked", ParamType::TMemoryObjectIDPointer, 1);
2522*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateResourceIDs<gl::MemoryObjectID>(context, call, memoryObjects,
2523*8975f5c5SAndroid Build Coastguard Worker resourceTracker, callsOut);
2524*8975f5c5SAndroid Build Coastguard Worker break;
2525*8975f5c5SAndroid Build Coastguard Worker }
2526*8975f5c5SAndroid Build Coastguard Worker
2527*8975f5c5SAndroid Build Coastguard Worker default:
2528*8975f5c5SAndroid Build Coastguard Worker break;
2529*8975f5c5SAndroid Build Coastguard Worker }
2530*8975f5c5SAndroid Build Coastguard Worker }
2531*8975f5c5SAndroid Build Coastguard Worker
IsDefaultCurrentValue(const gl::VertexAttribCurrentValueData & currentValue)2532*8975f5c5SAndroid Build Coastguard Worker bool IsDefaultCurrentValue(const gl::VertexAttribCurrentValueData ¤tValue)
2533*8975f5c5SAndroid Build Coastguard Worker {
2534*8975f5c5SAndroid Build Coastguard Worker if (currentValue.Type != gl::VertexAttribType::Float)
2535*8975f5c5SAndroid Build Coastguard Worker return false;
2536*8975f5c5SAndroid Build Coastguard Worker
2537*8975f5c5SAndroid Build Coastguard Worker return currentValue.Values.FloatValues[0] == 0.0f &&
2538*8975f5c5SAndroid Build Coastguard Worker currentValue.Values.FloatValues[1] == 0.0f &&
2539*8975f5c5SAndroid Build Coastguard Worker currentValue.Values.FloatValues[2] == 0.0f && currentValue.Values.FloatValues[3] == 1.0f;
2540*8975f5c5SAndroid Build Coastguard Worker }
2541*8975f5c5SAndroid Build Coastguard Worker
IsQueryActive(const gl::State & glState,gl::QueryID & queryID)2542*8975f5c5SAndroid Build Coastguard Worker bool IsQueryActive(const gl::State &glState, gl::QueryID &queryID)
2543*8975f5c5SAndroid Build Coastguard Worker {
2544*8975f5c5SAndroid Build Coastguard Worker const gl::ActiveQueryMap &activeQueries = glState.getActiveQueriesForCapture();
2545*8975f5c5SAndroid Build Coastguard Worker for (const auto &activeQueryIter : activeQueries)
2546*8975f5c5SAndroid Build Coastguard Worker {
2547*8975f5c5SAndroid Build Coastguard Worker const gl::Query *activeQuery = activeQueryIter.get();
2548*8975f5c5SAndroid Build Coastguard Worker if (activeQuery && activeQuery->id() == queryID)
2549*8975f5c5SAndroid Build Coastguard Worker {
2550*8975f5c5SAndroid Build Coastguard Worker return true;
2551*8975f5c5SAndroid Build Coastguard Worker }
2552*8975f5c5SAndroid Build Coastguard Worker }
2553*8975f5c5SAndroid Build Coastguard Worker
2554*8975f5c5SAndroid Build Coastguard Worker return false;
2555*8975f5c5SAndroid Build Coastguard Worker }
2556*8975f5c5SAndroid Build Coastguard Worker
IsTextureUpdate(CallCapture & call)2557*8975f5c5SAndroid Build Coastguard Worker bool IsTextureUpdate(CallCapture &call)
2558*8975f5c5SAndroid Build Coastguard Worker {
2559*8975f5c5SAndroid Build Coastguard Worker switch (call.entryPoint)
2560*8975f5c5SAndroid Build Coastguard Worker {
2561*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompressedCopyTextureCHROMIUM:
2562*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompressedTexImage2D:
2563*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompressedTexImage2DRobustANGLE:
2564*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompressedTexImage3D:
2565*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompressedTexImage3DOES:
2566*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompressedTexImage3DRobustANGLE:
2567*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompressedTexSubImage2D:
2568*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompressedTexSubImage2DRobustANGLE:
2569*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompressedTexSubImage3D:
2570*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompressedTexSubImage3DOES:
2571*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompressedTexSubImage3DRobustANGLE:
2572*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyTexImage2D:
2573*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyTexSubImage2D:
2574*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyTexSubImage3D:
2575*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyTexSubImage3DOES:
2576*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyTexture3DANGLE:
2577*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyTextureCHROMIUM:
2578*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexImage2D:
2579*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexImage2DExternalANGLE:
2580*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexImage2DRobustANGLE:
2581*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexImage3D:
2582*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexImage3DOES:
2583*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexImage3DRobustANGLE:
2584*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexSubImage2D:
2585*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexSubImage2DRobustANGLE:
2586*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexSubImage3D:
2587*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexSubImage3DOES:
2588*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexSubImage3DRobustANGLE:
2589*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyImageSubData:
2590*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyImageSubDataEXT:
2591*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyImageSubDataOES:
2592*8975f5c5SAndroid Build Coastguard Worker return true;
2593*8975f5c5SAndroid Build Coastguard Worker default:
2594*8975f5c5SAndroid Build Coastguard Worker return false;
2595*8975f5c5SAndroid Build Coastguard Worker }
2596*8975f5c5SAndroid Build Coastguard Worker }
2597*8975f5c5SAndroid Build Coastguard Worker
IsImageUpdate(CallCapture & call)2598*8975f5c5SAndroid Build Coastguard Worker bool IsImageUpdate(CallCapture &call)
2599*8975f5c5SAndroid Build Coastguard Worker {
2600*8975f5c5SAndroid Build Coastguard Worker switch (call.entryPoint)
2601*8975f5c5SAndroid Build Coastguard Worker {
2602*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDispatchCompute:
2603*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDispatchComputeIndirect:
2604*8975f5c5SAndroid Build Coastguard Worker return true;
2605*8975f5c5SAndroid Build Coastguard Worker default:
2606*8975f5c5SAndroid Build Coastguard Worker return false;
2607*8975f5c5SAndroid Build Coastguard Worker }
2608*8975f5c5SAndroid Build Coastguard Worker }
2609*8975f5c5SAndroid Build Coastguard Worker
IsVertexArrayUpdate(CallCapture & call)2610*8975f5c5SAndroid Build Coastguard Worker bool IsVertexArrayUpdate(CallCapture &call)
2611*8975f5c5SAndroid Build Coastguard Worker {
2612*8975f5c5SAndroid Build Coastguard Worker switch (call.entryPoint)
2613*8975f5c5SAndroid Build Coastguard Worker {
2614*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLVertexAttribFormat:
2615*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLVertexAttribIFormat:
2616*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBindVertexBuffer:
2617*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLVertexAttribBinding:
2618*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLVertexAttribPointer:
2619*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLVertexAttribIPointer:
2620*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLEnableVertexAttribArray:
2621*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDisableVertexAttribArray:
2622*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLVertexBindingDivisor:
2623*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLVertexAttribDivisor:
2624*8975f5c5SAndroid Build Coastguard Worker return true;
2625*8975f5c5SAndroid Build Coastguard Worker default:
2626*8975f5c5SAndroid Build Coastguard Worker return false;
2627*8975f5c5SAndroid Build Coastguard Worker }
2628*8975f5c5SAndroid Build Coastguard Worker }
2629*8975f5c5SAndroid Build Coastguard Worker
IsSharedObjectResource(ResourceIDType type)2630*8975f5c5SAndroid Build Coastguard Worker bool IsSharedObjectResource(ResourceIDType type)
2631*8975f5c5SAndroid Build Coastguard Worker {
2632*8975f5c5SAndroid Build Coastguard Worker // This helper function informs us which objects are shared vs. per context
2633*8975f5c5SAndroid Build Coastguard Worker //
2634*8975f5c5SAndroid Build Coastguard Worker // OpenGL ES Version 3.2 (October 22, 2019)
2635*8975f5c5SAndroid Build Coastguard Worker // Chapter 5 Shared Objects and Multiple Contexts:
2636*8975f5c5SAndroid Build Coastguard Worker //
2637*8975f5c5SAndroid Build Coastguard Worker // - Objects that can be shared between contexts include buffer objects, program
2638*8975f5c5SAndroid Build Coastguard Worker // and shader objects, renderbuffer objects, sampler objects, sync objects, and texture
2639*8975f5c5SAndroid Build Coastguard Worker // objects (except for the texture objects named zero).
2640*8975f5c5SAndroid Build Coastguard Worker // - Objects which contain references to other objects include framebuffer, program
2641*8975f5c5SAndroid Build Coastguard Worker // pipeline, transform feedback, and vertex array objects. Such objects are called
2642*8975f5c5SAndroid Build Coastguard Worker // container objects and are not shared.
2643*8975f5c5SAndroid Build Coastguard Worker //
2644*8975f5c5SAndroid Build Coastguard Worker // Notably absent from this list are Sync objects, which are not ResourceIDType, are handled
2645*8975f5c5SAndroid Build Coastguard Worker // elsewhere, and are shared:
2646*8975f5c5SAndroid Build Coastguard Worker // - 2.6.13 Sync Objects: Sync objects may be shared.
2647*8975f5c5SAndroid Build Coastguard Worker
2648*8975f5c5SAndroid Build Coastguard Worker switch (type)
2649*8975f5c5SAndroid Build Coastguard Worker {
2650*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Buffer:
2651*8975f5c5SAndroid Build Coastguard Worker // 2.6.2 Buffer Objects: Buffer objects may be shared.
2652*8975f5c5SAndroid Build Coastguard Worker return true;
2653*8975f5c5SAndroid Build Coastguard Worker
2654*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Framebuffer:
2655*8975f5c5SAndroid Build Coastguard Worker // 2.6.9 Framebuffer Objects: Framebuffer objects are container objects including
2656*8975f5c5SAndroid Build Coastguard Worker // references to renderbuffer and / or texture objects, and are not shared.
2657*8975f5c5SAndroid Build Coastguard Worker return false;
2658*8975f5c5SAndroid Build Coastguard Worker
2659*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::ProgramPipeline:
2660*8975f5c5SAndroid Build Coastguard Worker // 2.6.5 Program Pipeline Objects: Program pipeline objects are container objects
2661*8975f5c5SAndroid Build Coastguard Worker // including references to program objects, and are not shared.
2662*8975f5c5SAndroid Build Coastguard Worker return false;
2663*8975f5c5SAndroid Build Coastguard Worker
2664*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::TransformFeedback:
2665*8975f5c5SAndroid Build Coastguard Worker // 2.6.11 Transform Feedback Objects: Transform feedback objects are container objects
2666*8975f5c5SAndroid Build Coastguard Worker // including references to buffer objects, and are not shared
2667*8975f5c5SAndroid Build Coastguard Worker return false;
2668*8975f5c5SAndroid Build Coastguard Worker
2669*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::VertexArray:
2670*8975f5c5SAndroid Build Coastguard Worker // 2.6.10 Vertex Array Objects: Vertex array objects are container objects including
2671*8975f5c5SAndroid Build Coastguard Worker // references to buffer objects, and are not shared
2672*8975f5c5SAndroid Build Coastguard Worker return false;
2673*8975f5c5SAndroid Build Coastguard Worker
2674*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::FenceNV:
2675*8975f5c5SAndroid Build Coastguard Worker // From https://registry.khronos.org/OpenGL/extensions/NV/NV_fence.txt
2676*8975f5c5SAndroid Build Coastguard Worker // Are the fences sharable between multiple contexts?
2677*8975f5c5SAndroid Build Coastguard Worker // RESOLUTION: No.
2678*8975f5c5SAndroid Build Coastguard Worker return false;
2679*8975f5c5SAndroid Build Coastguard Worker
2680*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Renderbuffer:
2681*8975f5c5SAndroid Build Coastguard Worker // 2.6.8 Renderbuffer Objects: Renderbuffer objects may be shared.
2682*8975f5c5SAndroid Build Coastguard Worker return true;
2683*8975f5c5SAndroid Build Coastguard Worker
2684*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::ShaderProgram:
2685*8975f5c5SAndroid Build Coastguard Worker // 2.6.3 Shader Objects: Shader objects may be shared.
2686*8975f5c5SAndroid Build Coastguard Worker // 2.6.4 Program Objects: Program objects may be shared.
2687*8975f5c5SAndroid Build Coastguard Worker return true;
2688*8975f5c5SAndroid Build Coastguard Worker
2689*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Sampler:
2690*8975f5c5SAndroid Build Coastguard Worker // 2.6.7 Sampler Objects: Sampler objects may be shared
2691*8975f5c5SAndroid Build Coastguard Worker return true;
2692*8975f5c5SAndroid Build Coastguard Worker
2693*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Sync:
2694*8975f5c5SAndroid Build Coastguard Worker // 2.6.13 Sync Objects: Sync objects may be shared.
2695*8975f5c5SAndroid Build Coastguard Worker return true;
2696*8975f5c5SAndroid Build Coastguard Worker
2697*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Texture:
2698*8975f5c5SAndroid Build Coastguard Worker // 2.6.6 Texture Objects: Texture objects may be shared
2699*8975f5c5SAndroid Build Coastguard Worker return true;
2700*8975f5c5SAndroid Build Coastguard Worker
2701*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Query:
2702*8975f5c5SAndroid Build Coastguard Worker // 2.6.12 Query Objects: Query objects are not shared
2703*8975f5c5SAndroid Build Coastguard Worker return false;
2704*8975f5c5SAndroid Build Coastguard Worker
2705*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Semaphore:
2706*8975f5c5SAndroid Build Coastguard Worker // From https://registry.khronos.org/OpenGL/extensions/EXT/EXT_external_objects.txt
2707*8975f5c5SAndroid Build Coastguard Worker // 2.6.14 Semaphore Objects: Semaphore objects may be shared.
2708*8975f5c5SAndroid Build Coastguard Worker return true;
2709*8975f5c5SAndroid Build Coastguard Worker
2710*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::MemoryObject:
2711*8975f5c5SAndroid Build Coastguard Worker // From https://registry.khronos.org/OpenGL/extensions/EXT/EXT_external_objects.txt
2712*8975f5c5SAndroid Build Coastguard Worker // 2.6.15 Memory Objects: Memory objects may be shared.
2713*8975f5c5SAndroid Build Coastguard Worker return true;
2714*8975f5c5SAndroid Build Coastguard Worker
2715*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Context:
2716*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Image:
2717*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Surface:
2718*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::egl_Sync:
2719*8975f5c5SAndroid Build Coastguard Worker // EGL types are associated with a display and not bound to a context
2720*8975f5c5SAndroid Build Coastguard Worker // For the way this function is used, we can treat them as shared.
2721*8975f5c5SAndroid Build Coastguard Worker return true;
2722*8975f5c5SAndroid Build Coastguard Worker
2723*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::EnumCount:
2724*8975f5c5SAndroid Build Coastguard Worker default:
2725*8975f5c5SAndroid Build Coastguard Worker ERR() << "Unhandled ResourceIDType= " << static_cast<int>(type);
2726*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
2727*8975f5c5SAndroid Build Coastguard Worker return false;
2728*8975f5c5SAndroid Build Coastguard Worker }
2729*8975f5c5SAndroid Build Coastguard Worker }
2730*8975f5c5SAndroid Build Coastguard Worker
2731*8975f5c5SAndroid Build Coastguard Worker enum class DefaultUniformType
2732*8975f5c5SAndroid Build Coastguard Worker {
2733*8975f5c5SAndroid Build Coastguard Worker None,
2734*8975f5c5SAndroid Build Coastguard Worker CurrentProgram,
2735*8975f5c5SAndroid Build Coastguard Worker SpecifiedProgram,
2736*8975f5c5SAndroid Build Coastguard Worker };
2737*8975f5c5SAndroid Build Coastguard Worker
GetDefaultUniformType(const CallCapture & call)2738*8975f5c5SAndroid Build Coastguard Worker DefaultUniformType GetDefaultUniformType(const CallCapture &call)
2739*8975f5c5SAndroid Build Coastguard Worker {
2740*8975f5c5SAndroid Build Coastguard Worker switch (call.entryPoint)
2741*8975f5c5SAndroid Build Coastguard Worker {
2742*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform1f:
2743*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform1fEXT:
2744*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform1fv:
2745*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform1fvEXT:
2746*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform1i:
2747*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform1iEXT:
2748*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform1iv:
2749*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform1ivEXT:
2750*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform1ui:
2751*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform1uiEXT:
2752*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform1uiv:
2753*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform1uivEXT:
2754*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform2f:
2755*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform2fEXT:
2756*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform2fv:
2757*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform2fvEXT:
2758*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform2i:
2759*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform2iEXT:
2760*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform2iv:
2761*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform2ivEXT:
2762*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform2ui:
2763*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform2uiEXT:
2764*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform2uiv:
2765*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform2uivEXT:
2766*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform3f:
2767*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform3fEXT:
2768*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform3fv:
2769*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform3fvEXT:
2770*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform3i:
2771*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform3iEXT:
2772*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform3iv:
2773*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform3ivEXT:
2774*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform3ui:
2775*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform3uiEXT:
2776*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform3uiv:
2777*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform3uivEXT:
2778*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform4f:
2779*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform4fEXT:
2780*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform4fv:
2781*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform4fvEXT:
2782*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform4i:
2783*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform4iEXT:
2784*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform4iv:
2785*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform4ivEXT:
2786*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform4ui:
2787*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform4uiEXT:
2788*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform4uiv:
2789*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniform4uivEXT:
2790*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix2fv:
2791*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix2fvEXT:
2792*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix2x3fv:
2793*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix2x3fvEXT:
2794*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix2x4fv:
2795*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix2x4fvEXT:
2796*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix3fv:
2797*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix3fvEXT:
2798*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix3x2fv:
2799*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix3x2fvEXT:
2800*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix3x4fv:
2801*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix3x4fvEXT:
2802*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix4fv:
2803*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix4fvEXT:
2804*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix4x2fv:
2805*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix4x2fvEXT:
2806*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix4x3fv:
2807*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramUniformMatrix4x3fvEXT:
2808*8975f5c5SAndroid Build Coastguard Worker return DefaultUniformType::SpecifiedProgram;
2809*8975f5c5SAndroid Build Coastguard Worker
2810*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform1f:
2811*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform1fv:
2812*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform1i:
2813*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform1iv:
2814*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform1ui:
2815*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform1uiv:
2816*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform2f:
2817*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform2fv:
2818*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform2i:
2819*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform2iv:
2820*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform2ui:
2821*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform2uiv:
2822*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform3f:
2823*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform3fv:
2824*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform3i:
2825*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform3iv:
2826*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform3ui:
2827*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform3uiv:
2828*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform4f:
2829*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform4fv:
2830*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform4i:
2831*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform4iv:
2832*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform4ui:
2833*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniform4uiv:
2834*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniformMatrix2fv:
2835*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniformMatrix2x3fv:
2836*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniformMatrix2x4fv:
2837*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniformMatrix3fv:
2838*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniformMatrix3x2fv:
2839*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniformMatrix3x4fv:
2840*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniformMatrix4fv:
2841*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniformMatrix4x2fv:
2842*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniformMatrix4x3fv:
2843*8975f5c5SAndroid Build Coastguard Worker return DefaultUniformType::CurrentProgram;
2844*8975f5c5SAndroid Build Coastguard Worker
2845*8975f5c5SAndroid Build Coastguard Worker default:
2846*8975f5c5SAndroid Build Coastguard Worker return DefaultUniformType::None;
2847*8975f5c5SAndroid Build Coastguard Worker }
2848*8975f5c5SAndroid Build Coastguard Worker }
2849*8975f5c5SAndroid Build Coastguard Worker
CaptureFramebufferAttachment(std::vector<CallCapture> * setupCalls,const gl::State & replayState,const FramebufferCaptureFuncs & framebufferFuncs,const gl::FramebufferAttachment & attachment,std::vector<CallCapture> * shareGroupSetupCalls,ResourceIDToSetupCallsMap * resourceIDToSetupCalls)2850*8975f5c5SAndroid Build Coastguard Worker void CaptureFramebufferAttachment(std::vector<CallCapture> *setupCalls,
2851*8975f5c5SAndroid Build Coastguard Worker const gl::State &replayState,
2852*8975f5c5SAndroid Build Coastguard Worker const FramebufferCaptureFuncs &framebufferFuncs,
2853*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferAttachment &attachment,
2854*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *shareGroupSetupCalls,
2855*8975f5c5SAndroid Build Coastguard Worker ResourceIDToSetupCallsMap *resourceIDToSetupCalls)
2856*8975f5c5SAndroid Build Coastguard Worker {
2857*8975f5c5SAndroid Build Coastguard Worker GLuint resourceID = attachment.getResource()->getId();
2858*8975f5c5SAndroid Build Coastguard Worker
2859*8975f5c5SAndroid Build Coastguard Worker if (attachment.type() == GL_TEXTURE)
2860*8975f5c5SAndroid Build Coastguard Worker {
2861*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndex index = attachment.getTextureImageIndex();
2862*8975f5c5SAndroid Build Coastguard Worker
2863*8975f5c5SAndroid Build Coastguard Worker if (index.usesTex3D())
2864*8975f5c5SAndroid Build Coastguard Worker {
2865*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureFramebufferTextureLayer(
2866*8975f5c5SAndroid Build Coastguard Worker replayState, true, GL_FRAMEBUFFER, attachment.getBinding(),
2867*8975f5c5SAndroid Build Coastguard Worker {resourceID}, index.getLevelIndex(), index.getLayerIndex()));
2868*8975f5c5SAndroid Build Coastguard Worker }
2869*8975f5c5SAndroid Build Coastguard Worker else
2870*8975f5c5SAndroid Build Coastguard Worker {
2871*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
2872*8975f5c5SAndroid Build Coastguard Worker framebufferFuncs.framebufferTexture2D(
2873*8975f5c5SAndroid Build Coastguard Worker replayState, true, GL_FRAMEBUFFER, attachment.getBinding(),
2874*8975f5c5SAndroid Build Coastguard Worker index.getTargetOrFirstCubeFace(), {resourceID}, index.getLevelIndex()));
2875*8975f5c5SAndroid Build Coastguard Worker }
2876*8975f5c5SAndroid Build Coastguard Worker
2877*8975f5c5SAndroid Build Coastguard Worker std::vector<gl::TextureID> textureIDs;
2878*8975f5c5SAndroid Build Coastguard Worker const CallCapture &call = setupCalls->back();
2879*8975f5c5SAndroid Build Coastguard Worker if (FindResourceIDsInCall<gl::TextureID>(call, textureIDs))
2880*8975f5c5SAndroid Build Coastguard Worker {
2881*8975f5c5SAndroid Build Coastguard Worker // We skip the is active check on the assumption this call is made during MEC
2882*8975f5c5SAndroid Build Coastguard Worker for (gl::TextureID textureID : textureIDs)
2883*8975f5c5SAndroid Build Coastguard Worker {
2884*8975f5c5SAndroid Build Coastguard Worker // Track that this call referenced a Texture, setting it active for Setup
2885*8975f5c5SAndroid Build Coastguard Worker MarkResourceIDActive(ResourceIDType::Texture, textureID.value, shareGroupSetupCalls,
2886*8975f5c5SAndroid Build Coastguard Worker resourceIDToSetupCalls);
2887*8975f5c5SAndroid Build Coastguard Worker }
2888*8975f5c5SAndroid Build Coastguard Worker }
2889*8975f5c5SAndroid Build Coastguard Worker }
2890*8975f5c5SAndroid Build Coastguard Worker else
2891*8975f5c5SAndroid Build Coastguard Worker {
2892*8975f5c5SAndroid Build Coastguard Worker ASSERT(attachment.type() == GL_RENDERBUFFER);
2893*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, framebufferFuncs.framebufferRenderbuffer(
2894*8975f5c5SAndroid Build Coastguard Worker replayState, true, GL_FRAMEBUFFER, attachment.getBinding(),
2895*8975f5c5SAndroid Build Coastguard Worker GL_RENDERBUFFER, {resourceID}));
2896*8975f5c5SAndroid Build Coastguard Worker }
2897*8975f5c5SAndroid Build Coastguard Worker }
2898*8975f5c5SAndroid Build Coastguard Worker
CaptureUpdateUniformValues(const gl::State & replayState,const gl::Context * context,gl::Program * program,ResourceTracker * resourceTracker,std::vector<CallCapture> * callsOut)2899*8975f5c5SAndroid Build Coastguard Worker void CaptureUpdateUniformValues(const gl::State &replayState,
2900*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context,
2901*8975f5c5SAndroid Build Coastguard Worker gl::Program *program,
2902*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
2903*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *callsOut)
2904*8975f5c5SAndroid Build Coastguard Worker {
2905*8975f5c5SAndroid Build Coastguard Worker if (!program->isLinked())
2906*8975f5c5SAndroid Build Coastguard Worker {
2907*8975f5c5SAndroid Build Coastguard Worker // We can't populate uniforms if the program hasn't been linked
2908*8975f5c5SAndroid Build Coastguard Worker return;
2909*8975f5c5SAndroid Build Coastguard Worker }
2910*8975f5c5SAndroid Build Coastguard Worker
2911*8975f5c5SAndroid Build Coastguard Worker // We need to bind the program and update its uniforms
2912*8975f5c5SAndroid Build Coastguard Worker if (!replayState.getProgram() || replayState.getProgram()->id() != program->id())
2913*8975f5c5SAndroid Build Coastguard Worker {
2914*8975f5c5SAndroid Build Coastguard Worker Capture(callsOut, CaptureUseProgram(replayState, true, program->id()));
2915*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateCurrentProgram(callsOut->back(), 0, callsOut);
2916*8975f5c5SAndroid Build Coastguard Worker }
2917*8975f5c5SAndroid Build Coastguard Worker
2918*8975f5c5SAndroid Build Coastguard Worker const gl::ProgramExecutable &executable = program->getExecutable();
2919*8975f5c5SAndroid Build Coastguard Worker
2920*8975f5c5SAndroid Build Coastguard Worker for (GLuint uniformIndex = 0;
2921*8975f5c5SAndroid Build Coastguard Worker uniformIndex < static_cast<GLuint>(executable.getUniforms().size()); uniformIndex++)
2922*8975f5c5SAndroid Build Coastguard Worker {
2923*8975f5c5SAndroid Build Coastguard Worker std::string uniformName = executable.getUniformNameByIndex(uniformIndex);
2924*8975f5c5SAndroid Build Coastguard Worker const gl::LinkedUniform &uniform = executable.getUniformByIndex(uniformIndex);
2925*8975f5c5SAndroid Build Coastguard Worker
2926*8975f5c5SAndroid Build Coastguard Worker int uniformCount = 1;
2927*8975f5c5SAndroid Build Coastguard Worker if (uniform.isArray())
2928*8975f5c5SAndroid Build Coastguard Worker {
2929*8975f5c5SAndroid Build Coastguard Worker uniformCount = uniform.getBasicTypeElementCount();
2930*8975f5c5SAndroid Build Coastguard Worker uniformName = gl::StripLastArrayIndex(uniformName);
2931*8975f5c5SAndroid Build Coastguard Worker }
2932*8975f5c5SAndroid Build Coastguard Worker
2933*8975f5c5SAndroid Build Coastguard Worker gl::UniformLocation uniformLoc = executable.getUniformLocation(uniformName);
2934*8975f5c5SAndroid Build Coastguard Worker const gl::UniformTypeInfo &typeInfo = gl::GetUniformTypeInfo(uniform.getType());
2935*8975f5c5SAndroid Build Coastguard Worker int componentCount = typeInfo.componentCount;
2936*8975f5c5SAndroid Build Coastguard Worker int uniformSize = uniformCount * componentCount;
2937*8975f5c5SAndroid Build Coastguard Worker
2938*8975f5c5SAndroid Build Coastguard Worker // For arrayed uniforms, we'll need to increment a read location
2939*8975f5c5SAndroid Build Coastguard Worker gl::UniformLocation readLoc = uniformLoc;
2940*8975f5c5SAndroid Build Coastguard Worker
2941*8975f5c5SAndroid Build Coastguard Worker // If the uniform is unused, just continue
2942*8975f5c5SAndroid Build Coastguard Worker if (readLoc.value == -1)
2943*8975f5c5SAndroid Build Coastguard Worker {
2944*8975f5c5SAndroid Build Coastguard Worker continue;
2945*8975f5c5SAndroid Build Coastguard Worker }
2946*8975f5c5SAndroid Build Coastguard Worker
2947*8975f5c5SAndroid Build Coastguard Worker // Image uniforms are special and cannot be set this way
2948*8975f5c5SAndroid Build Coastguard Worker if (typeInfo.isImageType)
2949*8975f5c5SAndroid Build Coastguard Worker {
2950*8975f5c5SAndroid Build Coastguard Worker continue;
2951*8975f5c5SAndroid Build Coastguard Worker }
2952*8975f5c5SAndroid Build Coastguard Worker
2953*8975f5c5SAndroid Build Coastguard Worker DefaultUniformCallsPerLocationMap &resetCalls =
2954*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getDefaultUniformResetCalls(program->id());
2955*8975f5c5SAndroid Build Coastguard Worker
2956*8975f5c5SAndroid Build Coastguard Worker // Create two lists of calls for uniforms, one for Setup, one for Reset
2957*8975f5c5SAndroid Build Coastguard Worker CallVector defaultUniformCalls({callsOut, &resetCalls[uniformLoc]});
2958*8975f5c5SAndroid Build Coastguard Worker
2959*8975f5c5SAndroid Build Coastguard Worker // Samplers should be populated with GL_INT, regardless of return type
2960*8975f5c5SAndroid Build Coastguard Worker if (typeInfo.isSampler)
2961*8975f5c5SAndroid Build Coastguard Worker {
2962*8975f5c5SAndroid Build Coastguard Worker std::vector<GLint> uniformBuffer(uniformSize);
2963*8975f5c5SAndroid Build Coastguard Worker for (int index = 0; index < uniformCount; index++, readLoc.value++)
2964*8975f5c5SAndroid Build Coastguard Worker {
2965*8975f5c5SAndroid Build Coastguard Worker executable.getUniformiv(context, readLoc,
2966*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data() + index * componentCount);
2967*8975f5c5SAndroid Build Coastguard Worker resourceTracker->setDefaultUniformBaseLocation(program->id(), readLoc, uniformLoc);
2968*8975f5c5SAndroid Build Coastguard Worker }
2969*8975f5c5SAndroid Build Coastguard Worker
2970*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
2971*8975f5c5SAndroid Build Coastguard Worker {
2972*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform1iv(replayState, true, uniformLoc, uniformCount,
2973*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data()));
2974*8975f5c5SAndroid Build Coastguard Worker }
2975*8975f5c5SAndroid Build Coastguard Worker
2976*8975f5c5SAndroid Build Coastguard Worker continue;
2977*8975f5c5SAndroid Build Coastguard Worker }
2978*8975f5c5SAndroid Build Coastguard Worker
2979*8975f5c5SAndroid Build Coastguard Worker switch (typeInfo.componentType)
2980*8975f5c5SAndroid Build Coastguard Worker {
2981*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT:
2982*8975f5c5SAndroid Build Coastguard Worker {
2983*8975f5c5SAndroid Build Coastguard Worker std::vector<GLfloat> uniformBuffer(uniformSize);
2984*8975f5c5SAndroid Build Coastguard Worker for (int index = 0; index < uniformCount; index++, readLoc.value++)
2985*8975f5c5SAndroid Build Coastguard Worker {
2986*8975f5c5SAndroid Build Coastguard Worker executable.getUniformfv(context, readLoc,
2987*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data() + index * componentCount);
2988*8975f5c5SAndroid Build Coastguard Worker resourceTracker->setDefaultUniformBaseLocation(program->id(), readLoc,
2989*8975f5c5SAndroid Build Coastguard Worker uniformLoc);
2990*8975f5c5SAndroid Build Coastguard Worker }
2991*8975f5c5SAndroid Build Coastguard Worker switch (typeInfo.type)
2992*8975f5c5SAndroid Build Coastguard Worker {
2993*8975f5c5SAndroid Build Coastguard Worker // Note: All matrix uniforms are populated without transpose
2994*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT_MAT4x3:
2995*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
2996*8975f5c5SAndroid Build Coastguard Worker {
2997*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniformMatrix4x3fv(replayState, true, uniformLoc,
2998*8975f5c5SAndroid Build Coastguard Worker uniformCount, false,
2999*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data()));
3000*8975f5c5SAndroid Build Coastguard Worker }
3001*8975f5c5SAndroid Build Coastguard Worker break;
3002*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT_MAT4x2:
3003*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3004*8975f5c5SAndroid Build Coastguard Worker {
3005*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniformMatrix4x2fv(replayState, true, uniformLoc,
3006*8975f5c5SAndroid Build Coastguard Worker uniformCount, false,
3007*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data()));
3008*8975f5c5SAndroid Build Coastguard Worker }
3009*8975f5c5SAndroid Build Coastguard Worker break;
3010*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT_MAT4:
3011*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3012*8975f5c5SAndroid Build Coastguard Worker {
3013*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniformMatrix4fv(replayState, true, uniformLoc,
3014*8975f5c5SAndroid Build Coastguard Worker uniformCount, false,
3015*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data()));
3016*8975f5c5SAndroid Build Coastguard Worker }
3017*8975f5c5SAndroid Build Coastguard Worker break;
3018*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT_MAT3x4:
3019*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3020*8975f5c5SAndroid Build Coastguard Worker {
3021*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniformMatrix3x4fv(replayState, true, uniformLoc,
3022*8975f5c5SAndroid Build Coastguard Worker uniformCount, false,
3023*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data()));
3024*8975f5c5SAndroid Build Coastguard Worker }
3025*8975f5c5SAndroid Build Coastguard Worker break;
3026*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT_MAT3x2:
3027*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3028*8975f5c5SAndroid Build Coastguard Worker {
3029*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniformMatrix3x2fv(replayState, true, uniformLoc,
3030*8975f5c5SAndroid Build Coastguard Worker uniformCount, false,
3031*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data()));
3032*8975f5c5SAndroid Build Coastguard Worker }
3033*8975f5c5SAndroid Build Coastguard Worker break;
3034*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT_MAT3:
3035*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3036*8975f5c5SAndroid Build Coastguard Worker {
3037*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniformMatrix3fv(replayState, true, uniformLoc,
3038*8975f5c5SAndroid Build Coastguard Worker uniformCount, false,
3039*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data()));
3040*8975f5c5SAndroid Build Coastguard Worker }
3041*8975f5c5SAndroid Build Coastguard Worker break;
3042*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT_MAT2x4:
3043*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3044*8975f5c5SAndroid Build Coastguard Worker {
3045*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniformMatrix2x4fv(replayState, true, uniformLoc,
3046*8975f5c5SAndroid Build Coastguard Worker uniformCount, false,
3047*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data()));
3048*8975f5c5SAndroid Build Coastguard Worker }
3049*8975f5c5SAndroid Build Coastguard Worker break;
3050*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT_MAT2x3:
3051*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3052*8975f5c5SAndroid Build Coastguard Worker {
3053*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniformMatrix2x3fv(replayState, true, uniformLoc,
3054*8975f5c5SAndroid Build Coastguard Worker uniformCount, false,
3055*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data()));
3056*8975f5c5SAndroid Build Coastguard Worker }
3057*8975f5c5SAndroid Build Coastguard Worker break;
3058*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT_MAT2:
3059*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3060*8975f5c5SAndroid Build Coastguard Worker {
3061*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniformMatrix2fv(replayState, true, uniformLoc,
3062*8975f5c5SAndroid Build Coastguard Worker uniformCount, false,
3063*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data()));
3064*8975f5c5SAndroid Build Coastguard Worker }
3065*8975f5c5SAndroid Build Coastguard Worker break;
3066*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT_VEC4:
3067*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3068*8975f5c5SAndroid Build Coastguard Worker {
3069*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform4fv(replayState, true, uniformLoc,
3070*8975f5c5SAndroid Build Coastguard Worker uniformCount, uniformBuffer.data()));
3071*8975f5c5SAndroid Build Coastguard Worker }
3072*8975f5c5SAndroid Build Coastguard Worker break;
3073*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT_VEC3:
3074*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3075*8975f5c5SAndroid Build Coastguard Worker {
3076*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform3fv(replayState, true, uniformLoc,
3077*8975f5c5SAndroid Build Coastguard Worker uniformCount, uniformBuffer.data()));
3078*8975f5c5SAndroid Build Coastguard Worker }
3079*8975f5c5SAndroid Build Coastguard Worker break;
3080*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT_VEC2:
3081*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3082*8975f5c5SAndroid Build Coastguard Worker {
3083*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform2fv(replayState, true, uniformLoc,
3084*8975f5c5SAndroid Build Coastguard Worker uniformCount, uniformBuffer.data()));
3085*8975f5c5SAndroid Build Coastguard Worker }
3086*8975f5c5SAndroid Build Coastguard Worker break;
3087*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT:
3088*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3089*8975f5c5SAndroid Build Coastguard Worker {
3090*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform1fv(replayState, true, uniformLoc,
3091*8975f5c5SAndroid Build Coastguard Worker uniformCount, uniformBuffer.data()));
3092*8975f5c5SAndroid Build Coastguard Worker }
3093*8975f5c5SAndroid Build Coastguard Worker break;
3094*8975f5c5SAndroid Build Coastguard Worker default:
3095*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
3096*8975f5c5SAndroid Build Coastguard Worker break;
3097*8975f5c5SAndroid Build Coastguard Worker }
3098*8975f5c5SAndroid Build Coastguard Worker break;
3099*8975f5c5SAndroid Build Coastguard Worker }
3100*8975f5c5SAndroid Build Coastguard Worker case GL_INT:
3101*8975f5c5SAndroid Build Coastguard Worker {
3102*8975f5c5SAndroid Build Coastguard Worker std::vector<GLint> uniformBuffer(uniformSize);
3103*8975f5c5SAndroid Build Coastguard Worker for (int index = 0; index < uniformCount; index++, readLoc.value++)
3104*8975f5c5SAndroid Build Coastguard Worker {
3105*8975f5c5SAndroid Build Coastguard Worker executable.getUniformiv(context, readLoc,
3106*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data() + index * componentCount);
3107*8975f5c5SAndroid Build Coastguard Worker resourceTracker->setDefaultUniformBaseLocation(program->id(), readLoc,
3108*8975f5c5SAndroid Build Coastguard Worker uniformLoc);
3109*8975f5c5SAndroid Build Coastguard Worker }
3110*8975f5c5SAndroid Build Coastguard Worker switch (componentCount)
3111*8975f5c5SAndroid Build Coastguard Worker {
3112*8975f5c5SAndroid Build Coastguard Worker case 4:
3113*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3114*8975f5c5SAndroid Build Coastguard Worker {
3115*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform4iv(replayState, true, uniformLoc,
3116*8975f5c5SAndroid Build Coastguard Worker uniformCount, uniformBuffer.data()));
3117*8975f5c5SAndroid Build Coastguard Worker }
3118*8975f5c5SAndroid Build Coastguard Worker break;
3119*8975f5c5SAndroid Build Coastguard Worker case 3:
3120*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3121*8975f5c5SAndroid Build Coastguard Worker {
3122*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform3iv(replayState, true, uniformLoc,
3123*8975f5c5SAndroid Build Coastguard Worker uniformCount, uniformBuffer.data()));
3124*8975f5c5SAndroid Build Coastguard Worker }
3125*8975f5c5SAndroid Build Coastguard Worker break;
3126*8975f5c5SAndroid Build Coastguard Worker case 2:
3127*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3128*8975f5c5SAndroid Build Coastguard Worker {
3129*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform2iv(replayState, true, uniformLoc,
3130*8975f5c5SAndroid Build Coastguard Worker uniformCount, uniformBuffer.data()));
3131*8975f5c5SAndroid Build Coastguard Worker }
3132*8975f5c5SAndroid Build Coastguard Worker break;
3133*8975f5c5SAndroid Build Coastguard Worker case 1:
3134*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3135*8975f5c5SAndroid Build Coastguard Worker {
3136*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform1iv(replayState, true, uniformLoc,
3137*8975f5c5SAndroid Build Coastguard Worker uniformCount, uniformBuffer.data()));
3138*8975f5c5SAndroid Build Coastguard Worker }
3139*8975f5c5SAndroid Build Coastguard Worker break;
3140*8975f5c5SAndroid Build Coastguard Worker default:
3141*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
3142*8975f5c5SAndroid Build Coastguard Worker break;
3143*8975f5c5SAndroid Build Coastguard Worker }
3144*8975f5c5SAndroid Build Coastguard Worker break;
3145*8975f5c5SAndroid Build Coastguard Worker }
3146*8975f5c5SAndroid Build Coastguard Worker case GL_BOOL:
3147*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_INT:
3148*8975f5c5SAndroid Build Coastguard Worker {
3149*8975f5c5SAndroid Build Coastguard Worker std::vector<GLuint> uniformBuffer(uniformSize);
3150*8975f5c5SAndroid Build Coastguard Worker for (int index = 0; index < uniformCount; index++, readLoc.value++)
3151*8975f5c5SAndroid Build Coastguard Worker {
3152*8975f5c5SAndroid Build Coastguard Worker executable.getUniformuiv(context, readLoc,
3153*8975f5c5SAndroid Build Coastguard Worker uniformBuffer.data() + index * componentCount);
3154*8975f5c5SAndroid Build Coastguard Worker resourceTracker->setDefaultUniformBaseLocation(program->id(), readLoc,
3155*8975f5c5SAndroid Build Coastguard Worker uniformLoc);
3156*8975f5c5SAndroid Build Coastguard Worker }
3157*8975f5c5SAndroid Build Coastguard Worker switch (componentCount)
3158*8975f5c5SAndroid Build Coastguard Worker {
3159*8975f5c5SAndroid Build Coastguard Worker case 4:
3160*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3161*8975f5c5SAndroid Build Coastguard Worker {
3162*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform4uiv(replayState, true, uniformLoc,
3163*8975f5c5SAndroid Build Coastguard Worker uniformCount, uniformBuffer.data()));
3164*8975f5c5SAndroid Build Coastguard Worker }
3165*8975f5c5SAndroid Build Coastguard Worker break;
3166*8975f5c5SAndroid Build Coastguard Worker case 3:
3167*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3168*8975f5c5SAndroid Build Coastguard Worker {
3169*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform3uiv(replayState, true, uniformLoc,
3170*8975f5c5SAndroid Build Coastguard Worker uniformCount, uniformBuffer.data()));
3171*8975f5c5SAndroid Build Coastguard Worker }
3172*8975f5c5SAndroid Build Coastguard Worker break;
3173*8975f5c5SAndroid Build Coastguard Worker case 2:
3174*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3175*8975f5c5SAndroid Build Coastguard Worker {
3176*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform2uiv(replayState, true, uniformLoc,
3177*8975f5c5SAndroid Build Coastguard Worker uniformCount, uniformBuffer.data()));
3178*8975f5c5SAndroid Build Coastguard Worker }
3179*8975f5c5SAndroid Build Coastguard Worker break;
3180*8975f5c5SAndroid Build Coastguard Worker case 1:
3181*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : defaultUniformCalls)
3182*8975f5c5SAndroid Build Coastguard Worker {
3183*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureUniform1uiv(replayState, true, uniformLoc,
3184*8975f5c5SAndroid Build Coastguard Worker uniformCount, uniformBuffer.data()));
3185*8975f5c5SAndroid Build Coastguard Worker }
3186*8975f5c5SAndroid Build Coastguard Worker break;
3187*8975f5c5SAndroid Build Coastguard Worker default:
3188*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
3189*8975f5c5SAndroid Build Coastguard Worker break;
3190*8975f5c5SAndroid Build Coastguard Worker }
3191*8975f5c5SAndroid Build Coastguard Worker break;
3192*8975f5c5SAndroid Build Coastguard Worker }
3193*8975f5c5SAndroid Build Coastguard Worker default:
3194*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
3195*8975f5c5SAndroid Build Coastguard Worker break;
3196*8975f5c5SAndroid Build Coastguard Worker }
3197*8975f5c5SAndroid Build Coastguard Worker }
3198*8975f5c5SAndroid Build Coastguard Worker }
3199*8975f5c5SAndroid Build Coastguard Worker
CaptureVertexPointerES1(std::vector<CallCapture> * setupCalls,gl::State * replayState,GLuint attribIndex,const gl::VertexAttribute & attrib,const gl::VertexBinding & binding)3200*8975f5c5SAndroid Build Coastguard Worker void CaptureVertexPointerES1(std::vector<CallCapture> *setupCalls,
3201*8975f5c5SAndroid Build Coastguard Worker gl::State *replayState,
3202*8975f5c5SAndroid Build Coastguard Worker GLuint attribIndex,
3203*8975f5c5SAndroid Build Coastguard Worker const gl::VertexAttribute &attrib,
3204*8975f5c5SAndroid Build Coastguard Worker const gl::VertexBinding &binding)
3205*8975f5c5SAndroid Build Coastguard Worker {
3206*8975f5c5SAndroid Build Coastguard Worker switch (gl::GLES1Renderer::VertexArrayType(attribIndex))
3207*8975f5c5SAndroid Build Coastguard Worker {
3208*8975f5c5SAndroid Build Coastguard Worker case gl::ClientVertexArrayType::Vertex:
3209*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3210*8975f5c5SAndroid Build Coastguard Worker CaptureVertexPointer(*replayState, true, attrib.format->channelCount,
3211*8975f5c5SAndroid Build Coastguard Worker attrib.format->vertexAttribType, binding.getStride(),
3212*8975f5c5SAndroid Build Coastguard Worker attrib.pointer));
3213*8975f5c5SAndroid Build Coastguard Worker break;
3214*8975f5c5SAndroid Build Coastguard Worker case gl::ClientVertexArrayType::Normal:
3215*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3216*8975f5c5SAndroid Build Coastguard Worker CaptureNormalPointer(*replayState, true, attrib.format->vertexAttribType,
3217*8975f5c5SAndroid Build Coastguard Worker binding.getStride(), attrib.pointer));
3218*8975f5c5SAndroid Build Coastguard Worker break;
3219*8975f5c5SAndroid Build Coastguard Worker case gl::ClientVertexArrayType::Color:
3220*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureColorPointer(*replayState, true, attrib.format->channelCount,
3221*8975f5c5SAndroid Build Coastguard Worker attrib.format->vertexAttribType,
3222*8975f5c5SAndroid Build Coastguard Worker binding.getStride(), attrib.pointer));
3223*8975f5c5SAndroid Build Coastguard Worker break;
3224*8975f5c5SAndroid Build Coastguard Worker case gl::ClientVertexArrayType::PointSize:
3225*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3226*8975f5c5SAndroid Build Coastguard Worker CapturePointSizePointerOES(*replayState, true, attrib.format->vertexAttribType,
3227*8975f5c5SAndroid Build Coastguard Worker binding.getStride(), attrib.pointer));
3228*8975f5c5SAndroid Build Coastguard Worker break;
3229*8975f5c5SAndroid Build Coastguard Worker case gl::ClientVertexArrayType::TextureCoord:
3230*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3231*8975f5c5SAndroid Build Coastguard Worker CaptureTexCoordPointer(*replayState, true, attrib.format->channelCount,
3232*8975f5c5SAndroid Build Coastguard Worker attrib.format->vertexAttribType, binding.getStride(),
3233*8975f5c5SAndroid Build Coastguard Worker attrib.pointer));
3234*8975f5c5SAndroid Build Coastguard Worker break;
3235*8975f5c5SAndroid Build Coastguard Worker default:
3236*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3237*8975f5c5SAndroid Build Coastguard Worker }
3238*8975f5c5SAndroid Build Coastguard Worker }
3239*8975f5c5SAndroid Build Coastguard Worker
CaptureTextureEnvironmentState(std::vector<CallCapture> * setupCalls,gl::State * replayState,const gl::State * apiState,unsigned int unit)3240*8975f5c5SAndroid Build Coastguard Worker void CaptureTextureEnvironmentState(std::vector<CallCapture> *setupCalls,
3241*8975f5c5SAndroid Build Coastguard Worker gl::State *replayState,
3242*8975f5c5SAndroid Build Coastguard Worker const gl::State *apiState,
3243*8975f5c5SAndroid Build Coastguard Worker unsigned int unit)
3244*8975f5c5SAndroid Build Coastguard Worker {
3245*8975f5c5SAndroid Build Coastguard Worker const gl::TextureEnvironmentParameters ¤tEnv = apiState->gles1().textureEnvironment(unit);
3246*8975f5c5SAndroid Build Coastguard Worker const gl::TextureEnvironmentParameters &defaultEnv =
3247*8975f5c5SAndroid Build Coastguard Worker replayState->gles1().textureEnvironment(unit);
3248*8975f5c5SAndroid Build Coastguard Worker
3249*8975f5c5SAndroid Build Coastguard Worker if (currentEnv == defaultEnv)
3250*8975f5c5SAndroid Build Coastguard Worker {
3251*8975f5c5SAndroid Build Coastguard Worker return;
3252*8975f5c5SAndroid Build Coastguard Worker }
3253*8975f5c5SAndroid Build Coastguard Worker
3254*8975f5c5SAndroid Build Coastguard Worker auto capIfNe = [setupCalls](auto currentState, auto defaultState, CallCapture &&call) {
3255*8975f5c5SAndroid Build Coastguard Worker if (currentState != defaultState)
3256*8975f5c5SAndroid Build Coastguard Worker {
3257*8975f5c5SAndroid Build Coastguard Worker setupCalls->emplace_back(std::move(call));
3258*8975f5c5SAndroid Build Coastguard Worker }
3259*8975f5c5SAndroid Build Coastguard Worker };
3260*8975f5c5SAndroid Build Coastguard Worker
3261*8975f5c5SAndroid Build Coastguard Worker // When the texture env state differs on a non-default sampler unit, emit an ActiveTexture call.
3262*8975f5c5SAndroid Build Coastguard Worker // The default sampler unit is GL_TEXTURE0.
3263*8975f5c5SAndroid Build Coastguard Worker GLenum currentUnit = GL_TEXTURE0 + static_cast<GLenum>(unit);
3264*8975f5c5SAndroid Build Coastguard Worker GLenum defaultUnit = GL_TEXTURE0 + static_cast<GLenum>(replayState->getActiveSampler());
3265*8975f5c5SAndroid Build Coastguard Worker capIfNe(currentUnit, defaultUnit, CaptureActiveTexture(*replayState, true, currentUnit));
3266*8975f5c5SAndroid Build Coastguard Worker
3267*8975f5c5SAndroid Build Coastguard Worker auto capEnum = [capIfNe, replayState](gl::TextureEnvParameter pname, auto currentState,
3268*8975f5c5SAndroid Build Coastguard Worker auto defaultState) {
3269*8975f5c5SAndroid Build Coastguard Worker capIfNe(currentState, defaultState,
3270*8975f5c5SAndroid Build Coastguard Worker CaptureTexEnvi(*replayState, true, gl::TextureEnvTarget::Env, pname,
3271*8975f5c5SAndroid Build Coastguard Worker ToGLenum(currentState)));
3272*8975f5c5SAndroid Build Coastguard Worker };
3273*8975f5c5SAndroid Build Coastguard Worker
3274*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Mode, currentEnv.mode, defaultEnv.mode);
3275*8975f5c5SAndroid Build Coastguard Worker
3276*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::CombineRgb, currentEnv.combineRgb, defaultEnv.combineRgb);
3277*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::CombineAlpha, currentEnv.combineAlpha,
3278*8975f5c5SAndroid Build Coastguard Worker defaultEnv.combineAlpha);
3279*8975f5c5SAndroid Build Coastguard Worker
3280*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Src0Rgb, currentEnv.src0Rgb, defaultEnv.src0Rgb);
3281*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Src1Rgb, currentEnv.src1Rgb, defaultEnv.src1Rgb);
3282*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Src2Rgb, currentEnv.src2Rgb, defaultEnv.src2Rgb);
3283*8975f5c5SAndroid Build Coastguard Worker
3284*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Src0Alpha, currentEnv.src0Alpha, defaultEnv.src0Alpha);
3285*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Src1Alpha, currentEnv.src1Alpha, defaultEnv.src1Alpha);
3286*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Src2Alpha, currentEnv.src2Alpha, defaultEnv.src2Alpha);
3287*8975f5c5SAndroid Build Coastguard Worker
3288*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Op0Rgb, currentEnv.op0Rgb, defaultEnv.op0Rgb);
3289*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Op1Rgb, currentEnv.op1Rgb, defaultEnv.op1Rgb);
3290*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Op2Rgb, currentEnv.op2Rgb, defaultEnv.op2Rgb);
3291*8975f5c5SAndroid Build Coastguard Worker
3292*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Op0Alpha, currentEnv.op0Alpha, defaultEnv.op0Alpha);
3293*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Op1Alpha, currentEnv.op1Alpha, defaultEnv.op1Alpha);
3294*8975f5c5SAndroid Build Coastguard Worker capEnum(gl::TextureEnvParameter::Op2Alpha, currentEnv.op2Alpha, defaultEnv.op2Alpha);
3295*8975f5c5SAndroid Build Coastguard Worker
3296*8975f5c5SAndroid Build Coastguard Worker auto capFloat = [capIfNe, replayState](gl::TextureEnvParameter pname, auto currentState,
3297*8975f5c5SAndroid Build Coastguard Worker auto defaultState) {
3298*8975f5c5SAndroid Build Coastguard Worker capIfNe(currentState, defaultState,
3299*8975f5c5SAndroid Build Coastguard Worker CaptureTexEnvf(*replayState, true, gl::TextureEnvTarget::Env, pname, currentState));
3300*8975f5c5SAndroid Build Coastguard Worker };
3301*8975f5c5SAndroid Build Coastguard Worker
3302*8975f5c5SAndroid Build Coastguard Worker capFloat(gl::TextureEnvParameter::RgbScale, currentEnv.rgbScale, defaultEnv.rgbScale);
3303*8975f5c5SAndroid Build Coastguard Worker capFloat(gl::TextureEnvParameter::AlphaScale, currentEnv.alphaScale, defaultEnv.alphaScale);
3304*8975f5c5SAndroid Build Coastguard Worker
3305*8975f5c5SAndroid Build Coastguard Worker capIfNe(currentEnv.color, defaultEnv.color,
3306*8975f5c5SAndroid Build Coastguard Worker CaptureTexEnvfv(*replayState, true, gl::TextureEnvTarget::Env,
3307*8975f5c5SAndroid Build Coastguard Worker gl::TextureEnvParameter::Color, currentEnv.color.data()));
3308*8975f5c5SAndroid Build Coastguard Worker
3309*8975f5c5SAndroid Build Coastguard Worker // PointCoordReplace is the only parameter that uses the PointSprite TextureEnvTarget.
3310*8975f5c5SAndroid Build Coastguard Worker capIfNe(currentEnv.pointSpriteCoordReplace, defaultEnv.pointSpriteCoordReplace,
3311*8975f5c5SAndroid Build Coastguard Worker CaptureTexEnvi(*replayState, true, gl::TextureEnvTarget::PointSprite,
3312*8975f5c5SAndroid Build Coastguard Worker gl::TextureEnvParameter::PointCoordReplace,
3313*8975f5c5SAndroid Build Coastguard Worker currentEnv.pointSpriteCoordReplace));
3314*8975f5c5SAndroid Build Coastguard Worker
3315*8975f5c5SAndroid Build Coastguard Worker // In case of non-default sampler units, the default unit must be set back here.
3316*8975f5c5SAndroid Build Coastguard Worker capIfNe(currentUnit, defaultUnit, CaptureActiveTexture(*replayState, true, defaultUnit));
3317*8975f5c5SAndroid Build Coastguard Worker }
3318*8975f5c5SAndroid Build Coastguard Worker
VertexBindingMatchesAttribStride(const gl::VertexAttribute & attrib,const gl::VertexBinding & binding)3319*8975f5c5SAndroid Build Coastguard Worker bool VertexBindingMatchesAttribStride(const gl::VertexAttribute &attrib,
3320*8975f5c5SAndroid Build Coastguard Worker const gl::VertexBinding &binding)
3321*8975f5c5SAndroid Build Coastguard Worker {
3322*8975f5c5SAndroid Build Coastguard Worker if (attrib.vertexAttribArrayStride == 0 &&
3323*8975f5c5SAndroid Build Coastguard Worker binding.getStride() == ComputeVertexAttributeTypeSize(attrib))
3324*8975f5c5SAndroid Build Coastguard Worker {
3325*8975f5c5SAndroid Build Coastguard Worker return true;
3326*8975f5c5SAndroid Build Coastguard Worker }
3327*8975f5c5SAndroid Build Coastguard Worker
3328*8975f5c5SAndroid Build Coastguard Worker return attrib.vertexAttribArrayStride == binding.getStride();
3329*8975f5c5SAndroid Build Coastguard Worker }
3330*8975f5c5SAndroid Build Coastguard Worker
CaptureVertexArrayState(std::vector<CallCapture> * setupCalls,const gl::Context * context,const gl::VertexArray * vertexArray,gl::State * replayState)3331*8975f5c5SAndroid Build Coastguard Worker void CaptureVertexArrayState(std::vector<CallCapture> *setupCalls,
3332*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context,
3333*8975f5c5SAndroid Build Coastguard Worker const gl::VertexArray *vertexArray,
3334*8975f5c5SAndroid Build Coastguard Worker gl::State *replayState)
3335*8975f5c5SAndroid Build Coastguard Worker {
3336*8975f5c5SAndroid Build Coastguard Worker const std::vector<gl::VertexAttribute> &vertexAttribs = vertexArray->getVertexAttributes();
3337*8975f5c5SAndroid Build Coastguard Worker const std::vector<gl::VertexBinding> &vertexBindings = vertexArray->getVertexBindings();
3338*8975f5c5SAndroid Build Coastguard Worker
3339*8975f5c5SAndroid Build Coastguard Worker gl::AttributesMask vertexPointerBindings;
3340*8975f5c5SAndroid Build Coastguard Worker
3341*8975f5c5SAndroid Build Coastguard Worker ASSERT(vertexAttribs.size() <= vertexBindings.size());
3342*8975f5c5SAndroid Build Coastguard Worker for (GLuint attribIndex = 0; attribIndex < vertexAttribs.size(); ++attribIndex)
3343*8975f5c5SAndroid Build Coastguard Worker {
3344*8975f5c5SAndroid Build Coastguard Worker const gl::VertexAttribute defaultAttrib(attribIndex);
3345*8975f5c5SAndroid Build Coastguard Worker const gl::VertexBinding defaultBinding;
3346*8975f5c5SAndroid Build Coastguard Worker
3347*8975f5c5SAndroid Build Coastguard Worker const gl::VertexAttribute &attrib = vertexAttribs[attribIndex];
3348*8975f5c5SAndroid Build Coastguard Worker const gl::VertexBinding &binding = vertexBindings[attrib.bindingIndex];
3349*8975f5c5SAndroid Build Coastguard Worker
3350*8975f5c5SAndroid Build Coastguard Worker if (attrib.enabled != defaultAttrib.enabled)
3351*8975f5c5SAndroid Build Coastguard Worker {
3352*8975f5c5SAndroid Build Coastguard Worker if (context->isGLES1())
3353*8975f5c5SAndroid Build Coastguard Worker {
3354*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3355*8975f5c5SAndroid Build Coastguard Worker CaptureEnableClientState(*replayState, false,
3356*8975f5c5SAndroid Build Coastguard Worker gl::GLES1Renderer::VertexArrayType(attribIndex)));
3357*8975f5c5SAndroid Build Coastguard Worker }
3358*8975f5c5SAndroid Build Coastguard Worker else
3359*8975f5c5SAndroid Build Coastguard Worker {
3360*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3361*8975f5c5SAndroid Build Coastguard Worker CaptureEnableVertexAttribArray(*replayState, false, attribIndex));
3362*8975f5c5SAndroid Build Coastguard Worker }
3363*8975f5c5SAndroid Build Coastguard Worker }
3364*8975f5c5SAndroid Build Coastguard Worker
3365*8975f5c5SAndroid Build Coastguard Worker // Don't capture CaptureVertexAttribPointer calls when a non-default VAO is bound, the array
3366*8975f5c5SAndroid Build Coastguard Worker // buffer is null and a non-null attrib pointer is used.
3367*8975f5c5SAndroid Build Coastguard Worker bool skipInvalidAttrib = vertexArray->id().value != 0 &&
3368*8975f5c5SAndroid Build Coastguard Worker binding.getBuffer().get() == nullptr && attrib.pointer != nullptr;
3369*8975f5c5SAndroid Build Coastguard Worker
3370*8975f5c5SAndroid Build Coastguard Worker if (!skipInvalidAttrib &&
3371*8975f5c5SAndroid Build Coastguard Worker (attrib.format != defaultAttrib.format || attrib.pointer != defaultAttrib.pointer ||
3372*8975f5c5SAndroid Build Coastguard Worker binding.getStride() != defaultBinding.getStride() ||
3373*8975f5c5SAndroid Build Coastguard Worker attrib.bindingIndex != defaultAttrib.bindingIndex ||
3374*8975f5c5SAndroid Build Coastguard Worker binding.getBuffer().get() != nullptr))
3375*8975f5c5SAndroid Build Coastguard Worker {
3376*8975f5c5SAndroid Build Coastguard Worker // Each attribute can pull from a separate buffer, so check the binding
3377*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = binding.getBuffer().get();
3378*8975f5c5SAndroid Build Coastguard Worker if (buffer != replayState->getArrayBuffer())
3379*8975f5c5SAndroid Build Coastguard Worker {
3380*8975f5c5SAndroid Build Coastguard Worker replayState->setBufferBinding(context, gl::BufferBinding::Array, buffer);
3381*8975f5c5SAndroid Build Coastguard Worker
3382*8975f5c5SAndroid Build Coastguard Worker gl::BufferID bufferID = {0};
3383*8975f5c5SAndroid Build Coastguard Worker if (buffer)
3384*8975f5c5SAndroid Build Coastguard Worker {
3385*8975f5c5SAndroid Build Coastguard Worker bufferID = buffer->id();
3386*8975f5c5SAndroid Build Coastguard Worker }
3387*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3388*8975f5c5SAndroid Build Coastguard Worker CaptureBindBuffer(*replayState, true, gl::BufferBinding::Array, bufferID));
3389*8975f5c5SAndroid Build Coastguard Worker }
3390*8975f5c5SAndroid Build Coastguard Worker
3391*8975f5c5SAndroid Build Coastguard Worker // Establish the relationship between currently bound buffer and the VAO
3392*8975f5c5SAndroid Build Coastguard Worker if (context->isGLES1())
3393*8975f5c5SAndroid Build Coastguard Worker {
3394*8975f5c5SAndroid Build Coastguard Worker // Track indexes that used ES1 calls
3395*8975f5c5SAndroid Build Coastguard Worker vertexPointerBindings.set(attribIndex);
3396*8975f5c5SAndroid Build Coastguard Worker
3397*8975f5c5SAndroid Build Coastguard Worker CaptureVertexPointerES1(setupCalls, replayState, attribIndex, attrib, binding);
3398*8975f5c5SAndroid Build Coastguard Worker }
3399*8975f5c5SAndroid Build Coastguard Worker else if (attrib.bindingIndex == attribIndex &&
3400*8975f5c5SAndroid Build Coastguard Worker VertexBindingMatchesAttribStride(attrib, binding) &&
3401*8975f5c5SAndroid Build Coastguard Worker (!buffer || binding.getOffset() == reinterpret_cast<GLintptr>(attrib.pointer)))
3402*8975f5c5SAndroid Build Coastguard Worker {
3403*8975f5c5SAndroid Build Coastguard Worker // Check if we can use strictly ES2 semantics, and track indexes that do.
3404*8975f5c5SAndroid Build Coastguard Worker vertexPointerBindings.set(attribIndex);
3405*8975f5c5SAndroid Build Coastguard Worker
3406*8975f5c5SAndroid Build Coastguard Worker if (attrib.format->isPureInt())
3407*8975f5c5SAndroid Build Coastguard Worker {
3408*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureVertexAttribIPointer(*replayState, true, attribIndex,
3409*8975f5c5SAndroid Build Coastguard Worker attrib.format->channelCount,
3410*8975f5c5SAndroid Build Coastguard Worker attrib.format->vertexAttribType,
3411*8975f5c5SAndroid Build Coastguard Worker attrib.vertexAttribArrayStride,
3412*8975f5c5SAndroid Build Coastguard Worker attrib.pointer));
3413*8975f5c5SAndroid Build Coastguard Worker }
3414*8975f5c5SAndroid Build Coastguard Worker else
3415*8975f5c5SAndroid Build Coastguard Worker {
3416*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3417*8975f5c5SAndroid Build Coastguard Worker CaptureVertexAttribPointer(
3418*8975f5c5SAndroid Build Coastguard Worker *replayState, true, attribIndex, attrib.format->channelCount,
3419*8975f5c5SAndroid Build Coastguard Worker attrib.format->vertexAttribType, attrib.format->isNorm(),
3420*8975f5c5SAndroid Build Coastguard Worker attrib.vertexAttribArrayStride, attrib.pointer));
3421*8975f5c5SAndroid Build Coastguard Worker }
3422*8975f5c5SAndroid Build Coastguard Worker
3423*8975f5c5SAndroid Build Coastguard Worker if (binding.getDivisor() != 0)
3424*8975f5c5SAndroid Build Coastguard Worker {
3425*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureVertexAttribDivisor(*replayState, true, attribIndex,
3426*8975f5c5SAndroid Build Coastguard Worker binding.getDivisor()));
3427*8975f5c5SAndroid Build Coastguard Worker }
3428*8975f5c5SAndroid Build Coastguard Worker }
3429*8975f5c5SAndroid Build Coastguard Worker else
3430*8975f5c5SAndroid Build Coastguard Worker {
3431*8975f5c5SAndroid Build Coastguard Worker ASSERT(context->getClientVersion() >= gl::ES_3_1);
3432*8975f5c5SAndroid Build Coastguard Worker
3433*8975f5c5SAndroid Build Coastguard Worker if (attrib.format->isPureInt())
3434*8975f5c5SAndroid Build Coastguard Worker {
3435*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureVertexAttribIFormat(*replayState, true, attribIndex,
3436*8975f5c5SAndroid Build Coastguard Worker attrib.format->channelCount,
3437*8975f5c5SAndroid Build Coastguard Worker attrib.format->vertexAttribType,
3438*8975f5c5SAndroid Build Coastguard Worker attrib.relativeOffset));
3439*8975f5c5SAndroid Build Coastguard Worker }
3440*8975f5c5SAndroid Build Coastguard Worker else
3441*8975f5c5SAndroid Build Coastguard Worker {
3442*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureVertexAttribFormat(*replayState, true, attribIndex,
3443*8975f5c5SAndroid Build Coastguard Worker attrib.format->channelCount,
3444*8975f5c5SAndroid Build Coastguard Worker attrib.format->vertexAttribType,
3445*8975f5c5SAndroid Build Coastguard Worker attrib.format->isNorm(),
3446*8975f5c5SAndroid Build Coastguard Worker attrib.relativeOffset));
3447*8975f5c5SAndroid Build Coastguard Worker }
3448*8975f5c5SAndroid Build Coastguard Worker
3449*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureVertexAttribBinding(*replayState, true, attribIndex,
3450*8975f5c5SAndroid Build Coastguard Worker attrib.bindingIndex));
3451*8975f5c5SAndroid Build Coastguard Worker }
3452*8975f5c5SAndroid Build Coastguard Worker }
3453*8975f5c5SAndroid Build Coastguard Worker }
3454*8975f5c5SAndroid Build Coastguard Worker
3455*8975f5c5SAndroid Build Coastguard Worker // The loop below expects attribs and bindings to have equal counts
3456*8975f5c5SAndroid Build Coastguard Worker static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
3457*8975f5c5SAndroid Build Coastguard Worker "Max vertex attribs and bindings count mismatch");
3458*8975f5c5SAndroid Build Coastguard Worker
3459*8975f5c5SAndroid Build Coastguard Worker // Loop through binding indices that weren't used by VertexAttribPointer
3460*8975f5c5SAndroid Build Coastguard Worker for (size_t bindingIndex : vertexPointerBindings.flip())
3461*8975f5c5SAndroid Build Coastguard Worker {
3462*8975f5c5SAndroid Build Coastguard Worker const gl::VertexBinding &binding = vertexBindings[bindingIndex];
3463*8975f5c5SAndroid Build Coastguard Worker
3464*8975f5c5SAndroid Build Coastguard Worker if (binding.getBuffer().id().value != 0)
3465*8975f5c5SAndroid Build Coastguard Worker {
3466*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3467*8975f5c5SAndroid Build Coastguard Worker CaptureBindVertexBuffer(*replayState, true, static_cast<GLuint>(bindingIndex),
3468*8975f5c5SAndroid Build Coastguard Worker binding.getBuffer().id(), binding.getOffset(),
3469*8975f5c5SAndroid Build Coastguard Worker binding.getStride()));
3470*8975f5c5SAndroid Build Coastguard Worker }
3471*8975f5c5SAndroid Build Coastguard Worker
3472*8975f5c5SAndroid Build Coastguard Worker if (binding.getDivisor() != 0)
3473*8975f5c5SAndroid Build Coastguard Worker {
3474*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureVertexBindingDivisor(*replayState, true,
3475*8975f5c5SAndroid Build Coastguard Worker static_cast<GLuint>(bindingIndex),
3476*8975f5c5SAndroid Build Coastguard Worker binding.getDivisor()));
3477*8975f5c5SAndroid Build Coastguard Worker }
3478*8975f5c5SAndroid Build Coastguard Worker }
3479*8975f5c5SAndroid Build Coastguard Worker
3480*8975f5c5SAndroid Build Coastguard Worker // The element array buffer is not per attribute, but per VAO
3481*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *elementArrayBuffer = vertexArray->getElementArrayBuffer();
3482*8975f5c5SAndroid Build Coastguard Worker if (elementArrayBuffer)
3483*8975f5c5SAndroid Build Coastguard Worker {
3484*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureBindBuffer(*replayState, true, gl::BufferBinding::ElementArray,
3485*8975f5c5SAndroid Build Coastguard Worker elementArrayBuffer->id()));
3486*8975f5c5SAndroid Build Coastguard Worker }
3487*8975f5c5SAndroid Build Coastguard Worker }
3488*8975f5c5SAndroid Build Coastguard Worker
CaptureTextureStorage(std::vector<CallCapture> * setupCalls,gl::State * replayState,const gl::Texture * texture)3489*8975f5c5SAndroid Build Coastguard Worker void CaptureTextureStorage(std::vector<CallCapture> *setupCalls,
3490*8975f5c5SAndroid Build Coastguard Worker gl::State *replayState,
3491*8975f5c5SAndroid Build Coastguard Worker const gl::Texture *texture)
3492*8975f5c5SAndroid Build Coastguard Worker {
3493*8975f5c5SAndroid Build Coastguard Worker // Use mip-level 0 for the base dimensions
3494*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndex imageIndex = gl::ImageIndex::MakeFromType(texture->getType(), 0);
3495*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &desc = texture->getTextureState().getImageDesc(imageIndex);
3496*8975f5c5SAndroid Build Coastguard Worker
3497*8975f5c5SAndroid Build Coastguard Worker switch (texture->getType())
3498*8975f5c5SAndroid Build Coastguard Worker {
3499*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::_2D:
3500*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::CubeMap:
3501*8975f5c5SAndroid Build Coastguard Worker {
3502*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureTexStorage2D(*replayState, true, texture->getType(),
3503*8975f5c5SAndroid Build Coastguard Worker texture->getImmutableLevels(),
3504*8975f5c5SAndroid Build Coastguard Worker desc.format.info->internalFormat,
3505*8975f5c5SAndroid Build Coastguard Worker desc.size.width, desc.size.height));
3506*8975f5c5SAndroid Build Coastguard Worker break;
3507*8975f5c5SAndroid Build Coastguard Worker }
3508*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::_3D:
3509*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::_2DArray:
3510*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::CubeMapArray:
3511*8975f5c5SAndroid Build Coastguard Worker {
3512*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureTexStorage3D(
3513*8975f5c5SAndroid Build Coastguard Worker *replayState, true, texture->getType(),
3514*8975f5c5SAndroid Build Coastguard Worker texture->getImmutableLevels(), desc.format.info->internalFormat,
3515*8975f5c5SAndroid Build Coastguard Worker desc.size.width, desc.size.height, desc.size.depth));
3516*8975f5c5SAndroid Build Coastguard Worker break;
3517*8975f5c5SAndroid Build Coastguard Worker }
3518*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::Buffer:
3519*8975f5c5SAndroid Build Coastguard Worker {
3520*8975f5c5SAndroid Build Coastguard Worker // Do nothing. This will already be captured as a buffer.
3521*8975f5c5SAndroid Build Coastguard Worker break;
3522*8975f5c5SAndroid Build Coastguard Worker }
3523*8975f5c5SAndroid Build Coastguard Worker default:
3524*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
3525*8975f5c5SAndroid Build Coastguard Worker break;
3526*8975f5c5SAndroid Build Coastguard Worker }
3527*8975f5c5SAndroid Build Coastguard Worker }
3528*8975f5c5SAndroid Build Coastguard Worker
CaptureTextureContents(std::vector<CallCapture> * setupCalls,gl::State * replayState,const gl::Texture * texture,const gl::ImageIndex & index,const gl::ImageDesc & desc,GLuint size,const void * data)3529*8975f5c5SAndroid Build Coastguard Worker void CaptureTextureContents(std::vector<CallCapture> *setupCalls,
3530*8975f5c5SAndroid Build Coastguard Worker gl::State *replayState,
3531*8975f5c5SAndroid Build Coastguard Worker const gl::Texture *texture,
3532*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
3533*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &desc,
3534*8975f5c5SAndroid Build Coastguard Worker GLuint size,
3535*8975f5c5SAndroid Build Coastguard Worker const void *data)
3536*8975f5c5SAndroid Build Coastguard Worker {
3537*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &format = *desc.format.info;
3538*8975f5c5SAndroid Build Coastguard Worker
3539*8975f5c5SAndroid Build Coastguard Worker if (index.getType() == gl::TextureType::Buffer)
3540*8975f5c5SAndroid Build Coastguard Worker {
3541*8975f5c5SAndroid Build Coastguard Worker // Zero binding size indicates full buffer bound
3542*8975f5c5SAndroid Build Coastguard Worker if (texture->getBuffer().getSize() == 0)
3543*8975f5c5SAndroid Build Coastguard Worker {
3544*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3545*8975f5c5SAndroid Build Coastguard Worker CaptureTexBufferEXT(*replayState, true, index.getType(), format.internalFormat,
3546*8975f5c5SAndroid Build Coastguard Worker texture->getBuffer().get()->id()));
3547*8975f5c5SAndroid Build Coastguard Worker }
3548*8975f5c5SAndroid Build Coastguard Worker else
3549*8975f5c5SAndroid Build Coastguard Worker {
3550*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureTexBufferRangeEXT(*replayState, true, index.getType(),
3551*8975f5c5SAndroid Build Coastguard Worker format.internalFormat,
3552*8975f5c5SAndroid Build Coastguard Worker texture->getBuffer().get()->id(),
3553*8975f5c5SAndroid Build Coastguard Worker texture->getBuffer().getOffset(),
3554*8975f5c5SAndroid Build Coastguard Worker texture->getBuffer().getSize()));
3555*8975f5c5SAndroid Build Coastguard Worker }
3556*8975f5c5SAndroid Build Coastguard Worker
3557*8975f5c5SAndroid Build Coastguard Worker // For buffers, we're done
3558*8975f5c5SAndroid Build Coastguard Worker return;
3559*8975f5c5SAndroid Build Coastguard Worker }
3560*8975f5c5SAndroid Build Coastguard Worker
3561*8975f5c5SAndroid Build Coastguard Worker bool is3D =
3562*8975f5c5SAndroid Build Coastguard Worker (index.getType() == gl::TextureType::_3D || index.getType() == gl::TextureType::_2DArray ||
3563*8975f5c5SAndroid Build Coastguard Worker index.getType() == gl::TextureType::CubeMapArray);
3564*8975f5c5SAndroid Build Coastguard Worker
3565*8975f5c5SAndroid Build Coastguard Worker if (format.compressed || format.paletted)
3566*8975f5c5SAndroid Build Coastguard Worker {
3567*8975f5c5SAndroid Build Coastguard Worker if (is3D)
3568*8975f5c5SAndroid Build Coastguard Worker {
3569*8975f5c5SAndroid Build Coastguard Worker if (texture->getImmutableFormat())
3570*8975f5c5SAndroid Build Coastguard Worker {
3571*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3572*8975f5c5SAndroid Build Coastguard Worker CaptureCompressedTexSubImage3D(
3573*8975f5c5SAndroid Build Coastguard Worker *replayState, true, index.getTarget(), index.getLevelIndex(), 0, 0, 0,
3574*8975f5c5SAndroid Build Coastguard Worker desc.size.width, desc.size.height, desc.size.depth,
3575*8975f5c5SAndroid Build Coastguard Worker format.internalFormat, size, data));
3576*8975f5c5SAndroid Build Coastguard Worker }
3577*8975f5c5SAndroid Build Coastguard Worker else
3578*8975f5c5SAndroid Build Coastguard Worker {
3579*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3580*8975f5c5SAndroid Build Coastguard Worker CaptureCompressedTexImage3D(*replayState, true, index.getTarget(),
3581*8975f5c5SAndroid Build Coastguard Worker index.getLevelIndex(), format.internalFormat,
3582*8975f5c5SAndroid Build Coastguard Worker desc.size.width, desc.size.height,
3583*8975f5c5SAndroid Build Coastguard Worker desc.size.depth, 0, size, data));
3584*8975f5c5SAndroid Build Coastguard Worker }
3585*8975f5c5SAndroid Build Coastguard Worker }
3586*8975f5c5SAndroid Build Coastguard Worker else
3587*8975f5c5SAndroid Build Coastguard Worker {
3588*8975f5c5SAndroid Build Coastguard Worker if (texture->getImmutableFormat())
3589*8975f5c5SAndroid Build Coastguard Worker {
3590*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3591*8975f5c5SAndroid Build Coastguard Worker CaptureCompressedTexSubImage2D(
3592*8975f5c5SAndroid Build Coastguard Worker *replayState, true, index.getTarget(), index.getLevelIndex(), 0, 0,
3593*8975f5c5SAndroid Build Coastguard Worker desc.size.width, desc.size.height, format.internalFormat, size, data));
3594*8975f5c5SAndroid Build Coastguard Worker }
3595*8975f5c5SAndroid Build Coastguard Worker else
3596*8975f5c5SAndroid Build Coastguard Worker {
3597*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureCompressedTexImage2D(
3598*8975f5c5SAndroid Build Coastguard Worker *replayState, true, index.getTarget(),
3599*8975f5c5SAndroid Build Coastguard Worker index.getLevelIndex(), format.internalFormat,
3600*8975f5c5SAndroid Build Coastguard Worker desc.size.width, desc.size.height, 0, size, data));
3601*8975f5c5SAndroid Build Coastguard Worker }
3602*8975f5c5SAndroid Build Coastguard Worker }
3603*8975f5c5SAndroid Build Coastguard Worker }
3604*8975f5c5SAndroid Build Coastguard Worker else
3605*8975f5c5SAndroid Build Coastguard Worker {
3606*8975f5c5SAndroid Build Coastguard Worker if (is3D)
3607*8975f5c5SAndroid Build Coastguard Worker {
3608*8975f5c5SAndroid Build Coastguard Worker if (texture->getImmutableFormat())
3609*8975f5c5SAndroid Build Coastguard Worker {
3610*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3611*8975f5c5SAndroid Build Coastguard Worker CaptureTexSubImage3D(*replayState, true, index.getTarget(),
3612*8975f5c5SAndroid Build Coastguard Worker index.getLevelIndex(), 0, 0, 0, desc.size.width,
3613*8975f5c5SAndroid Build Coastguard Worker desc.size.height, desc.size.depth, format.format,
3614*8975f5c5SAndroid Build Coastguard Worker format.type, data));
3615*8975f5c5SAndroid Build Coastguard Worker }
3616*8975f5c5SAndroid Build Coastguard Worker else
3617*8975f5c5SAndroid Build Coastguard Worker {
3618*8975f5c5SAndroid Build Coastguard Worker Capture(
3619*8975f5c5SAndroid Build Coastguard Worker setupCalls,
3620*8975f5c5SAndroid Build Coastguard Worker CaptureTexImage3D(*replayState, true, index.getTarget(), index.getLevelIndex(),
3621*8975f5c5SAndroid Build Coastguard Worker format.internalFormat, desc.size.width, desc.size.height,
3622*8975f5c5SAndroid Build Coastguard Worker desc.size.depth, 0, format.format, format.type, data));
3623*8975f5c5SAndroid Build Coastguard Worker }
3624*8975f5c5SAndroid Build Coastguard Worker }
3625*8975f5c5SAndroid Build Coastguard Worker else
3626*8975f5c5SAndroid Build Coastguard Worker {
3627*8975f5c5SAndroid Build Coastguard Worker if (texture->getImmutableFormat())
3628*8975f5c5SAndroid Build Coastguard Worker {
3629*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3630*8975f5c5SAndroid Build Coastguard Worker CaptureTexSubImage2D(*replayState, true, index.getTarget(),
3631*8975f5c5SAndroid Build Coastguard Worker index.getLevelIndex(), 0, 0, desc.size.width,
3632*8975f5c5SAndroid Build Coastguard Worker desc.size.height, format.format, format.type, data));
3633*8975f5c5SAndroid Build Coastguard Worker }
3634*8975f5c5SAndroid Build Coastguard Worker else
3635*8975f5c5SAndroid Build Coastguard Worker {
3636*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureTexImage2D(*replayState, true, index.getTarget(),
3637*8975f5c5SAndroid Build Coastguard Worker index.getLevelIndex(), format.internalFormat,
3638*8975f5c5SAndroid Build Coastguard Worker desc.size.width, desc.size.height, 0,
3639*8975f5c5SAndroid Build Coastguard Worker format.format, format.type, data));
3640*8975f5c5SAndroid Build Coastguard Worker }
3641*8975f5c5SAndroid Build Coastguard Worker }
3642*8975f5c5SAndroid Build Coastguard Worker }
3643*8975f5c5SAndroid Build Coastguard Worker }
3644*8975f5c5SAndroid Build Coastguard Worker
CaptureCustomUniformBlockBinding(const CallCapture & callIn,std::vector<CallCapture> & callsOut)3645*8975f5c5SAndroid Build Coastguard Worker void CaptureCustomUniformBlockBinding(const CallCapture &callIn, std::vector<CallCapture> &callsOut)
3646*8975f5c5SAndroid Build Coastguard Worker {
3647*8975f5c5SAndroid Build Coastguard Worker const ParamBuffer ¶msIn = callIn.params;
3648*8975f5c5SAndroid Build Coastguard Worker
3649*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &programID =
3650*8975f5c5SAndroid Build Coastguard Worker paramsIn.getParam("programPacked", ParamType::TShaderProgramID, 0);
3651*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &blockIndex =
3652*8975f5c5SAndroid Build Coastguard Worker paramsIn.getParam("uniformBlockIndexPacked", ParamType::TUniformBlockIndex, 1);
3653*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &blockBinding =
3654*8975f5c5SAndroid Build Coastguard Worker paramsIn.getParam("uniformBlockBinding", ParamType::TGLuint, 2);
3655*8975f5c5SAndroid Build Coastguard Worker
3656*8975f5c5SAndroid Build Coastguard Worker ParamBuffer params;
3657*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("program", ParamType::TGLuint, programID.value.ShaderProgramIDVal.value);
3658*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("uniformBlockIndex", ParamType::TGLuint,
3659*8975f5c5SAndroid Build Coastguard Worker blockIndex.value.UniformBlockIndexVal.value);
3660*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("uniformBlockBinding", ParamType::TGLuint, blockBinding.value.GLuintVal);
3661*8975f5c5SAndroid Build Coastguard Worker
3662*8975f5c5SAndroid Build Coastguard Worker callsOut.emplace_back("UniformBlockBinding", std::move(params));
3663*8975f5c5SAndroid Build Coastguard Worker }
3664*8975f5c5SAndroid Build Coastguard Worker
CaptureCustomMapBuffer(const char * entryPointName,CallCapture & call,std::vector<CallCapture> & callsOut,gl::BufferID mappedBufferID)3665*8975f5c5SAndroid Build Coastguard Worker void CaptureCustomMapBuffer(const char *entryPointName,
3666*8975f5c5SAndroid Build Coastguard Worker CallCapture &call,
3667*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> &callsOut,
3668*8975f5c5SAndroid Build Coastguard Worker gl::BufferID mappedBufferID)
3669*8975f5c5SAndroid Build Coastguard Worker {
3670*8975f5c5SAndroid Build Coastguard Worker call.params.addValueParam("buffer", ParamType::TGLuint, mappedBufferID.value);
3671*8975f5c5SAndroid Build Coastguard Worker callsOut.emplace_back(entryPointName, std::move(call.params));
3672*8975f5c5SAndroid Build Coastguard Worker }
3673*8975f5c5SAndroid Build Coastguard Worker
CaptureCustomShaderProgram(const char * name,CallCapture & call,std::vector<CallCapture> & callsOut)3674*8975f5c5SAndroid Build Coastguard Worker void CaptureCustomShaderProgram(const char *name,
3675*8975f5c5SAndroid Build Coastguard Worker CallCapture &call,
3676*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> &callsOut)
3677*8975f5c5SAndroid Build Coastguard Worker {
3678*8975f5c5SAndroid Build Coastguard Worker call.params.addValueParam("shaderProgram", ParamType::TGLuint,
3679*8975f5c5SAndroid Build Coastguard Worker call.params.getReturnValue().value.GLuintVal);
3680*8975f5c5SAndroid Build Coastguard Worker call.customFunctionName = name;
3681*8975f5c5SAndroid Build Coastguard Worker callsOut.emplace_back(std::move(call));
3682*8975f5c5SAndroid Build Coastguard Worker }
3683*8975f5c5SAndroid Build Coastguard Worker
CaptureCustomFenceSync(CallCapture & call,std::vector<CallCapture> & callsOut)3684*8975f5c5SAndroid Build Coastguard Worker void CaptureCustomFenceSync(CallCapture &call, std::vector<CallCapture> &callsOut)
3685*8975f5c5SAndroid Build Coastguard Worker {
3686*8975f5c5SAndroid Build Coastguard Worker ParamBuffer &¶ms = std::move(call.params);
3687*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("fenceSync", ParamType::TGLuint64,
3688*8975f5c5SAndroid Build Coastguard Worker params.getReturnValue().value.GLuint64Val);
3689*8975f5c5SAndroid Build Coastguard Worker call.customFunctionName = "FenceSync2";
3690*8975f5c5SAndroid Build Coastguard Worker call.isSyncPoint = true;
3691*8975f5c5SAndroid Build Coastguard Worker callsOut.emplace_back(std::move(call));
3692*8975f5c5SAndroid Build Coastguard Worker }
3693*8975f5c5SAndroid Build Coastguard Worker
GetImageFromParam(const gl::Context * context,const ParamCapture & param)3694*8975f5c5SAndroid Build Coastguard Worker const egl::Image *GetImageFromParam(const gl::Context *context, const ParamCapture ¶m)
3695*8975f5c5SAndroid Build Coastguard Worker {
3696*8975f5c5SAndroid Build Coastguard Worker const egl::ImageID eglImageID = egl::PackParam<egl::ImageID>(param.value.EGLImageVal);
3697*8975f5c5SAndroid Build Coastguard Worker const egl::Image *eglImage = context->getDisplay()->getImage(eglImageID);
3698*8975f5c5SAndroid Build Coastguard Worker ASSERT(eglImage != nullptr);
3699*8975f5c5SAndroid Build Coastguard Worker return eglImage;
3700*8975f5c5SAndroid Build Coastguard Worker }
3701*8975f5c5SAndroid Build Coastguard Worker
CaptureCustomCreateEGLImage(const gl::Context * context,const char * name,size_t width,size_t height,CallCapture & call,std::vector<CallCapture> & callsOut)3702*8975f5c5SAndroid Build Coastguard Worker void CaptureCustomCreateEGLImage(const gl::Context *context,
3703*8975f5c5SAndroid Build Coastguard Worker const char *name,
3704*8975f5c5SAndroid Build Coastguard Worker size_t width,
3705*8975f5c5SAndroid Build Coastguard Worker size_t height,
3706*8975f5c5SAndroid Build Coastguard Worker CallCapture &call,
3707*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> &callsOut)
3708*8975f5c5SAndroid Build Coastguard Worker {
3709*8975f5c5SAndroid Build Coastguard Worker ParamBuffer &¶ms = std::move(call.params);
3710*8975f5c5SAndroid Build Coastguard Worker EGLImage returnVal = params.getReturnValue().value.EGLImageVal;
3711*8975f5c5SAndroid Build Coastguard Worker egl::ImageID imageID = egl::PackParam<egl::ImageID>(returnVal);
3712*8975f5c5SAndroid Build Coastguard Worker call.customFunctionName = name;
3713*8975f5c5SAndroid Build Coastguard Worker
3714*8975f5c5SAndroid Build Coastguard Worker // Clear client buffer value if it is a pointer to a hardware buffer. It is
3715*8975f5c5SAndroid Build Coastguard Worker // not used by replay and will not be portable to 32-bit builds
3716*8975f5c5SAndroid Build Coastguard Worker if (params.getParam("target", ParamType::TEGLenum, 2).value.EGLenumVal ==
3717*8975f5c5SAndroid Build Coastguard Worker EGL_NATIVE_BUFFER_ANDROID)
3718*8975f5c5SAndroid Build Coastguard Worker {
3719*8975f5c5SAndroid Build Coastguard Worker params.setValueParamAtIndex("buffer", ParamType::TEGLClientBuffer,
3720*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(0)),
3721*8975f5c5SAndroid Build Coastguard Worker 3);
3722*8975f5c5SAndroid Build Coastguard Worker }
3723*8975f5c5SAndroid Build Coastguard Worker
3724*8975f5c5SAndroid Build Coastguard Worker // Record image dimensions in case a backing resource needs to be created during replay
3725*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("width", ParamType::TGLsizei, static_cast<GLsizei>(width));
3726*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("height", ParamType::TGLsizei, static_cast<GLsizei>(height));
3727*8975f5c5SAndroid Build Coastguard Worker
3728*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("image", ParamType::TGLuint, imageID.value);
3729*8975f5c5SAndroid Build Coastguard Worker callsOut.emplace_back(std::move(call));
3730*8975f5c5SAndroid Build Coastguard Worker }
3731*8975f5c5SAndroid Build Coastguard Worker
CaptureCustomDestroyEGLImage(const char * name,CallCapture & call,std::vector<CallCapture> & callsOut)3732*8975f5c5SAndroid Build Coastguard Worker void CaptureCustomDestroyEGLImage(const char *name,
3733*8975f5c5SAndroid Build Coastguard Worker CallCapture &call,
3734*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> &callsOut)
3735*8975f5c5SAndroid Build Coastguard Worker {
3736*8975f5c5SAndroid Build Coastguard Worker call.customFunctionName = name;
3737*8975f5c5SAndroid Build Coastguard Worker ParamBuffer &¶ms = std::move(call.params);
3738*8975f5c5SAndroid Build Coastguard Worker
3739*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &imageID = params.getParam("imagePacked", ParamType::TImageID, 1);
3740*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("imageID", ParamType::TGLuint, imageID.value.ImageIDVal.value);
3741*8975f5c5SAndroid Build Coastguard Worker
3742*8975f5c5SAndroid Build Coastguard Worker callsOut.emplace_back(std::move(call));
3743*8975f5c5SAndroid Build Coastguard Worker }
3744*8975f5c5SAndroid Build Coastguard Worker
CaptureCustomCreateEGLSync(const char * name,CallCapture & call,std::vector<CallCapture> & callsOut)3745*8975f5c5SAndroid Build Coastguard Worker void CaptureCustomCreateEGLSync(const char *name,
3746*8975f5c5SAndroid Build Coastguard Worker CallCapture &call,
3747*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> &callsOut)
3748*8975f5c5SAndroid Build Coastguard Worker {
3749*8975f5c5SAndroid Build Coastguard Worker ParamBuffer &¶ms = std::move(call.params);
3750*8975f5c5SAndroid Build Coastguard Worker EGLSync returnVal = params.getReturnValue().value.EGLSyncVal;
3751*8975f5c5SAndroid Build Coastguard Worker egl::SyncID syncID = egl::PackParam<egl::SyncID>(returnVal);
3752*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("sync", ParamType::TGLuint, syncID.value);
3753*8975f5c5SAndroid Build Coastguard Worker call.customFunctionName = name;
3754*8975f5c5SAndroid Build Coastguard Worker callsOut.emplace_back(std::move(call));
3755*8975f5c5SAndroid Build Coastguard Worker }
3756*8975f5c5SAndroid Build Coastguard Worker
CaptureCustomCreatePbufferSurface(CallCapture & call,std::vector<CallCapture> & callsOut)3757*8975f5c5SAndroid Build Coastguard Worker void CaptureCustomCreatePbufferSurface(CallCapture &call, std::vector<CallCapture> &callsOut)
3758*8975f5c5SAndroid Build Coastguard Worker {
3759*8975f5c5SAndroid Build Coastguard Worker ParamBuffer &¶ms = std::move(call.params);
3760*8975f5c5SAndroid Build Coastguard Worker EGLSurface returnVal = params.getReturnValue().value.EGLSurfaceVal;
3761*8975f5c5SAndroid Build Coastguard Worker egl::SurfaceID surfaceID = egl::PackParam<egl::SurfaceID>(returnVal);
3762*8975f5c5SAndroid Build Coastguard Worker
3763*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("surface", ParamType::TGLuint, surfaceID.value);
3764*8975f5c5SAndroid Build Coastguard Worker call.customFunctionName = "CreatePbufferSurface";
3765*8975f5c5SAndroid Build Coastguard Worker callsOut.emplace_back(std::move(call));
3766*8975f5c5SAndroid Build Coastguard Worker }
3767*8975f5c5SAndroid Build Coastguard Worker
CaptureCustomCreateNativeClientbuffer(CallCapture & call,std::vector<CallCapture> & callsOut)3768*8975f5c5SAndroid Build Coastguard Worker void CaptureCustomCreateNativeClientbuffer(CallCapture &call, std::vector<CallCapture> &callsOut)
3769*8975f5c5SAndroid Build Coastguard Worker {
3770*8975f5c5SAndroid Build Coastguard Worker ParamBuffer &¶ms = std::move(call.params);
3771*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("clientBuffer", ParamType::TEGLClientBuffer,
3772*8975f5c5SAndroid Build Coastguard Worker params.getReturnValue().value.EGLClientBufferVal);
3773*8975f5c5SAndroid Build Coastguard Worker call.customFunctionName = "CreateNativeClientBufferANDROID";
3774*8975f5c5SAndroid Build Coastguard Worker callsOut.emplace_back(std::move(call));
3775*8975f5c5SAndroid Build Coastguard Worker }
3776*8975f5c5SAndroid Build Coastguard Worker
GenerateLinkedProgram(const gl::Context * context,const gl::State & replayState,ResourceTracker * resourceTracker,std::vector<CallCapture> * setupCalls,gl::Program * program,gl::ShaderProgramID id,gl::ShaderProgramID tempIDStart,const ProgramSources & linkedSources)3777*8975f5c5SAndroid Build Coastguard Worker void GenerateLinkedProgram(const gl::Context *context,
3778*8975f5c5SAndroid Build Coastguard Worker const gl::State &replayState,
3779*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
3780*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *setupCalls,
3781*8975f5c5SAndroid Build Coastguard Worker gl::Program *program,
3782*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID id,
3783*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID tempIDStart,
3784*8975f5c5SAndroid Build Coastguard Worker const ProgramSources &linkedSources)
3785*8975f5c5SAndroid Build Coastguard Worker {
3786*8975f5c5SAndroid Build Coastguard Worker // A map to store the gShaderProgram map lookup index of the temp shaders we attached below. We
3787*8975f5c5SAndroid Build Coastguard Worker // need this map to retrieve the lookup index to pass to CaptureDetachShader calls at the end of
3788*8975f5c5SAndroid Build Coastguard Worker // GenerateLinkedProgram.
3789*8975f5c5SAndroid Build Coastguard Worker PackedEnumMap<gl::ShaderType, gl::ShaderProgramID> tempShaderIDTracker;
3790*8975f5c5SAndroid Build Coastguard Worker
3791*8975f5c5SAndroid Build Coastguard Worker const gl::ProgramExecutable &executable = program->getExecutable();
3792*8975f5c5SAndroid Build Coastguard Worker
3793*8975f5c5SAndroid Build Coastguard Worker // Compile with last linked sources.
3794*8975f5c5SAndroid Build Coastguard Worker for (gl::ShaderType shaderType : executable.getLinkedShaderStages())
3795*8975f5c5SAndroid Build Coastguard Worker {
3796*8975f5c5SAndroid Build Coastguard Worker // Bump the max shader program id for each new tempIDStart we use to create, compile, and
3797*8975f5c5SAndroid Build Coastguard Worker // attach the temp shader object.
3798*8975f5c5SAndroid Build Coastguard Worker resourceTracker->onShaderProgramAccess(tempIDStart);
3799*8975f5c5SAndroid Build Coastguard Worker // Store the tempIDStart in the tempShaderIDTracker to retrieve for CaptureDetachShader
3800*8975f5c5SAndroid Build Coastguard Worker // calls later.
3801*8975f5c5SAndroid Build Coastguard Worker tempShaderIDTracker[shaderType] = tempIDStart;
3802*8975f5c5SAndroid Build Coastguard Worker const std::string &sourceString = linkedSources[shaderType];
3803*8975f5c5SAndroid Build Coastguard Worker const char *sourcePointer = sourceString.c_str();
3804*8975f5c5SAndroid Build Coastguard Worker
3805*8975f5c5SAndroid Build Coastguard Worker if (sourceString.empty())
3806*8975f5c5SAndroid Build Coastguard Worker {
3807*8975f5c5SAndroid Build Coastguard Worker // If we don't have source for this shader, that means it was populated by the app
3808*8975f5c5SAndroid Build Coastguard Worker // using glProgramBinary. We need to look it up from our cached copy.
3809*8975f5c5SAndroid Build Coastguard Worker const ProgramSources &cachedLinkedSources =
3810*8975f5c5SAndroid Build Coastguard Worker context->getShareGroup()->getFrameCaptureShared()->getProgramSources(id);
3811*8975f5c5SAndroid Build Coastguard Worker
3812*8975f5c5SAndroid Build Coastguard Worker const std::string &cachedSourceString = cachedLinkedSources[shaderType];
3813*8975f5c5SAndroid Build Coastguard Worker sourcePointer = cachedSourceString.c_str();
3814*8975f5c5SAndroid Build Coastguard Worker ASSERT(!cachedSourceString.empty());
3815*8975f5c5SAndroid Build Coastguard Worker }
3816*8975f5c5SAndroid Build Coastguard Worker
3817*8975f5c5SAndroid Build Coastguard Worker // Compile and attach the temporary shader. Then free it immediately.
3818*8975f5c5SAndroid Build Coastguard Worker CallCapture createShader =
3819*8975f5c5SAndroid Build Coastguard Worker CaptureCreateShader(replayState, true, shaderType, tempIDStart.value);
3820*8975f5c5SAndroid Build Coastguard Worker CaptureCustomShaderProgram("CreateShader", createShader, *setupCalls);
3821*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3822*8975f5c5SAndroid Build Coastguard Worker CaptureShaderSource(replayState, true, tempIDStart, 1, &sourcePointer, nullptr));
3823*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureCompileShader(replayState, true, tempIDStart));
3824*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureAttachShader(replayState, true, id, tempIDStart));
3825*8975f5c5SAndroid Build Coastguard Worker // Increment tempIDStart to get a new gShaderProgram map index for the next linked stage
3826*8975f5c5SAndroid Build Coastguard Worker // shader object. We can't reuse the same tempIDStart as we need to retrieve the index of
3827*8975f5c5SAndroid Build Coastguard Worker // each attached shader object later to pass to CaptureDetachShader calls.
3828*8975f5c5SAndroid Build Coastguard Worker tempIDStart.value += 1;
3829*8975f5c5SAndroid Build Coastguard Worker }
3830*8975f5c5SAndroid Build Coastguard Worker
3831*8975f5c5SAndroid Build Coastguard Worker // Gather XFB varyings
3832*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> xfbVaryings;
3833*8975f5c5SAndroid Build Coastguard Worker for (const gl::TransformFeedbackVarying &xfbVarying :
3834*8975f5c5SAndroid Build Coastguard Worker executable.getLinkedTransformFeedbackVaryings())
3835*8975f5c5SAndroid Build Coastguard Worker {
3836*8975f5c5SAndroid Build Coastguard Worker xfbVaryings.push_back(xfbVarying.nameWithArrayIndex());
3837*8975f5c5SAndroid Build Coastguard Worker }
3838*8975f5c5SAndroid Build Coastguard Worker
3839*8975f5c5SAndroid Build Coastguard Worker if (!xfbVaryings.empty())
3840*8975f5c5SAndroid Build Coastguard Worker {
3841*8975f5c5SAndroid Build Coastguard Worker std::vector<const char *> varyingsStrings;
3842*8975f5c5SAndroid Build Coastguard Worker for (const std::string &varyingString : xfbVaryings)
3843*8975f5c5SAndroid Build Coastguard Worker {
3844*8975f5c5SAndroid Build Coastguard Worker varyingsStrings.push_back(varyingString.data());
3845*8975f5c5SAndroid Build Coastguard Worker }
3846*8975f5c5SAndroid Build Coastguard Worker
3847*8975f5c5SAndroid Build Coastguard Worker GLenum xfbMode = executable.getTransformFeedbackBufferMode();
3848*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureTransformFeedbackVaryings(replayState, true, id,
3849*8975f5c5SAndroid Build Coastguard Worker static_cast<GLint>(xfbVaryings.size()),
3850*8975f5c5SAndroid Build Coastguard Worker varyingsStrings.data(), xfbMode));
3851*8975f5c5SAndroid Build Coastguard Worker }
3852*8975f5c5SAndroid Build Coastguard Worker
3853*8975f5c5SAndroid Build Coastguard Worker // Force the attributes to be bound the same way as in the existing program.
3854*8975f5c5SAndroid Build Coastguard Worker // This can affect attributes that are optimized out in some implementations.
3855*8975f5c5SAndroid Build Coastguard Worker for (const gl::ProgramInput &attrib : executable.getProgramInputs())
3856*8975f5c5SAndroid Build Coastguard Worker {
3857*8975f5c5SAndroid Build Coastguard Worker if (gl::IsBuiltInName(attrib.name))
3858*8975f5c5SAndroid Build Coastguard Worker {
3859*8975f5c5SAndroid Build Coastguard Worker // Don't try to bind built-in attributes
3860*8975f5c5SAndroid Build Coastguard Worker continue;
3861*8975f5c5SAndroid Build Coastguard Worker }
3862*8975f5c5SAndroid Build Coastguard Worker
3863*8975f5c5SAndroid Build Coastguard Worker // Separable programs may not have a VS, meaning it may not have attributes.
3864*8975f5c5SAndroid Build Coastguard Worker if (executable.hasLinkedShaderStage(gl::ShaderType::Vertex))
3865*8975f5c5SAndroid Build Coastguard Worker {
3866*8975f5c5SAndroid Build Coastguard Worker ASSERT(attrib.getLocation() != -1);
3867*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureBindAttribLocation(replayState, true, id,
3868*8975f5c5SAndroid Build Coastguard Worker static_cast<GLuint>(attrib.getLocation()),
3869*8975f5c5SAndroid Build Coastguard Worker attrib.name.c_str()));
3870*8975f5c5SAndroid Build Coastguard Worker }
3871*8975f5c5SAndroid Build Coastguard Worker }
3872*8975f5c5SAndroid Build Coastguard Worker
3873*8975f5c5SAndroid Build Coastguard Worker if (program->isSeparable())
3874*8975f5c5SAndroid Build Coastguard Worker {
3875*8975f5c5SAndroid Build Coastguard Worker // MEC manually recreates separable programs, rather than attempting to recreate a call
3876*8975f5c5SAndroid Build Coastguard Worker // to glCreateShaderProgramv(), so insert a call to mark it separable.
3877*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3878*8975f5c5SAndroid Build Coastguard Worker CaptureProgramParameteri(replayState, true, id, GL_PROGRAM_SEPARABLE, GL_TRUE));
3879*8975f5c5SAndroid Build Coastguard Worker }
3880*8975f5c5SAndroid Build Coastguard Worker
3881*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureLinkProgram(replayState, true, id));
3882*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateUniformLocations(program, setupCalls);
3883*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateUniformValues(replayState, context, program, resourceTracker, setupCalls);
3884*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateUniformBlockIndexes(program, setupCalls);
3885*8975f5c5SAndroid Build Coastguard Worker
3886*8975f5c5SAndroid Build Coastguard Worker // Capture uniform block bindings for each program
3887*8975f5c5SAndroid Build Coastguard Worker for (uint32_t uniformBlockIndex = 0;
3888*8975f5c5SAndroid Build Coastguard Worker uniformBlockIndex < static_cast<uint32_t>(executable.getUniformBlocks().size());
3889*8975f5c5SAndroid Build Coastguard Worker uniformBlockIndex++)
3890*8975f5c5SAndroid Build Coastguard Worker {
3891*8975f5c5SAndroid Build Coastguard Worker GLuint blockBinding = executable.getUniformBlocks()[uniformBlockIndex].pod.inShaderBinding;
3892*8975f5c5SAndroid Build Coastguard Worker CallCapture updateCallCapture =
3893*8975f5c5SAndroid Build Coastguard Worker CaptureUniformBlockBinding(replayState, true, id, {uniformBlockIndex}, blockBinding);
3894*8975f5c5SAndroid Build Coastguard Worker CaptureCustomUniformBlockBinding(updateCallCapture, *setupCalls);
3895*8975f5c5SAndroid Build Coastguard Worker }
3896*8975f5c5SAndroid Build Coastguard Worker
3897*8975f5c5SAndroid Build Coastguard Worker // Add DetachShader call if that's what the app does, so that the
3898*8975f5c5SAndroid Build Coastguard Worker // ResourceManagerBase::mHandleAllocator can release the ShaderProgramID handle assigned to the
3899*8975f5c5SAndroid Build Coastguard Worker // shader object when glDeleteShader is called. This ensures the ShaderProgramID handles used in
3900*8975f5c5SAndroid Build Coastguard Worker // SetupReplayContextShared() are consistent with the ShaderProgramID handles used by the app.
3901*8975f5c5SAndroid Build Coastguard Worker for (gl::ShaderType shaderType : executable.getLinkedShaderStages())
3902*8975f5c5SAndroid Build Coastguard Worker {
3903*8975f5c5SAndroid Build Coastguard Worker gl::Shader *attachedShader = program->getAttachedShader(shaderType);
3904*8975f5c5SAndroid Build Coastguard Worker if (attachedShader == nullptr)
3905*8975f5c5SAndroid Build Coastguard Worker {
3906*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3907*8975f5c5SAndroid Build Coastguard Worker CaptureDetachShader(replayState, true, id, tempShaderIDTracker[shaderType]));
3908*8975f5c5SAndroid Build Coastguard Worker }
3909*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
3910*8975f5c5SAndroid Build Coastguard Worker CaptureDeleteShader(replayState, true, tempShaderIDTracker[shaderType]));
3911*8975f5c5SAndroid Build Coastguard Worker }
3912*8975f5c5SAndroid Build Coastguard Worker }
3913*8975f5c5SAndroid Build Coastguard Worker
3914*8975f5c5SAndroid Build Coastguard Worker // TODO(http://anglebug.com/42263204): Improve reset/restore call generation
3915*8975f5c5SAndroid Build Coastguard Worker // There are multiple ways to track reset calls for individual resources. For now, we are tracking
3916*8975f5c5SAndroid Build Coastguard Worker // separate lists of instructions that mirror the calls created during mid-execution setup. Other
3917*8975f5c5SAndroid Build Coastguard Worker // methods could involve passing the original CallCaptures to this function, or tracking the
3918*8975f5c5SAndroid Build Coastguard Worker // indices of original setup calls.
CaptureBufferResetCalls(const gl::Context * context,const gl::State & replayState,ResourceTracker * resourceTracker,gl::BufferID * id,const gl::Buffer * buffer)3919*8975f5c5SAndroid Build Coastguard Worker void CaptureBufferResetCalls(const gl::Context *context,
3920*8975f5c5SAndroid Build Coastguard Worker const gl::State &replayState,
3921*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
3922*8975f5c5SAndroid Build Coastguard Worker gl::BufferID *id,
3923*8975f5c5SAndroid Build Coastguard Worker const gl::Buffer *buffer)
3924*8975f5c5SAndroid Build Coastguard Worker {
3925*8975f5c5SAndroid Build Coastguard Worker GLuint bufferID = (*id).value;
3926*8975f5c5SAndroid Build Coastguard Worker
3927*8975f5c5SAndroid Build Coastguard Worker // Track this as a starting resource that may need to be restored.
3928*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedBuffers =
3929*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::Buffer);
3930*8975f5c5SAndroid Build Coastguard Worker
3931*8975f5c5SAndroid Build Coastguard Worker // Track calls to regenerate a given buffer
3932*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &bufferRegenCalls = trackedBuffers.getResourceRegenCalls();
3933*8975f5c5SAndroid Build Coastguard Worker Capture(&bufferRegenCalls[bufferID], CaptureGenBuffers(replayState, true, 1, id));
3934*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, resourceTracker, &bufferRegenCalls[bufferID]);
3935*8975f5c5SAndroid Build Coastguard Worker
3936*8975f5c5SAndroid Build Coastguard Worker // Call glBufferStorageEXT when regenerating immutable buffers,
3937*8975f5c5SAndroid Build Coastguard Worker // as we can't call glBufferData on restore.
3938*8975f5c5SAndroid Build Coastguard Worker if (buffer->isImmutable())
3939*8975f5c5SAndroid Build Coastguard Worker {
3940*8975f5c5SAndroid Build Coastguard Worker Capture(&bufferRegenCalls[bufferID],
3941*8975f5c5SAndroid Build Coastguard Worker CaptureBindBuffer(replayState, true, gl::BufferBinding::Array, *id));
3942*8975f5c5SAndroid Build Coastguard Worker Capture(
3943*8975f5c5SAndroid Build Coastguard Worker &bufferRegenCalls[bufferID],
3944*8975f5c5SAndroid Build Coastguard Worker CaptureBufferStorageEXT(replayState, true, gl::BufferBinding::Array,
3945*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(buffer->getSize()),
3946*8975f5c5SAndroid Build Coastguard Worker buffer->getMapPointer(), buffer->getStorageExtUsageFlags()));
3947*8975f5c5SAndroid Build Coastguard Worker }
3948*8975f5c5SAndroid Build Coastguard Worker
3949*8975f5c5SAndroid Build Coastguard Worker // Track calls to restore a given buffer's contents
3950*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &bufferRestoreCalls = trackedBuffers.getResourceRestoreCalls();
3951*8975f5c5SAndroid Build Coastguard Worker Capture(&bufferRestoreCalls[bufferID],
3952*8975f5c5SAndroid Build Coastguard Worker CaptureBindBuffer(replayState, true, gl::BufferBinding::Array, *id));
3953*8975f5c5SAndroid Build Coastguard Worker
3954*8975f5c5SAndroid Build Coastguard Worker // Mutable buffers will be restored here using glBufferData.
3955*8975f5c5SAndroid Build Coastguard Worker // Immutable buffers need to be restored below, after maping.
3956*8975f5c5SAndroid Build Coastguard Worker if (!buffer->isImmutable())
3957*8975f5c5SAndroid Build Coastguard Worker {
3958*8975f5c5SAndroid Build Coastguard Worker Capture(&bufferRestoreCalls[bufferID],
3959*8975f5c5SAndroid Build Coastguard Worker CaptureBufferData(replayState, true, gl::BufferBinding::Array,
3960*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(buffer->getSize()),
3961*8975f5c5SAndroid Build Coastguard Worker buffer->getMapPointer(), buffer->getUsage()));
3962*8975f5c5SAndroid Build Coastguard Worker }
3963*8975f5c5SAndroid Build Coastguard Worker
3964*8975f5c5SAndroid Build Coastguard Worker if (buffer->isMapped())
3965*8975f5c5SAndroid Build Coastguard Worker {
3966*8975f5c5SAndroid Build Coastguard Worker // Track calls to remap a buffer that started as mapped
3967*8975f5c5SAndroid Build Coastguard Worker BufferCalls &bufferMapCalls = resourceTracker->getBufferMapCalls();
3968*8975f5c5SAndroid Build Coastguard Worker
3969*8975f5c5SAndroid Build Coastguard Worker Capture(&bufferMapCalls[bufferID],
3970*8975f5c5SAndroid Build Coastguard Worker CaptureBindBuffer(replayState, true, gl::BufferBinding::Array, *id));
3971*8975f5c5SAndroid Build Coastguard Worker
3972*8975f5c5SAndroid Build Coastguard Worker void *dontCare = nullptr;
3973*8975f5c5SAndroid Build Coastguard Worker CallCapture mapBufferRange = CaptureMapBufferRange(
3974*8975f5c5SAndroid Build Coastguard Worker replayState, true, gl::BufferBinding::Array,
3975*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(buffer->getMapOffset()),
3976*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(buffer->getMapLength()), buffer->getAccessFlags(), dontCare);
3977*8975f5c5SAndroid Build Coastguard Worker CaptureCustomMapBuffer("MapBufferRange", mapBufferRange, bufferMapCalls[bufferID],
3978*8975f5c5SAndroid Build Coastguard Worker buffer->id());
3979*8975f5c5SAndroid Build Coastguard Worker
3980*8975f5c5SAndroid Build Coastguard Worker // Restore immutable mapped buffers. Needs to happen after mapping.
3981*8975f5c5SAndroid Build Coastguard Worker if (buffer->isImmutable())
3982*8975f5c5SAndroid Build Coastguard Worker {
3983*8975f5c5SAndroid Build Coastguard Worker ParamBuffer dataParamBuffer;
3984*8975f5c5SAndroid Build Coastguard Worker dataParamBuffer.addValueParam("dest", ParamType::TGLuint, buffer->id().value);
3985*8975f5c5SAndroid Build Coastguard Worker ParamCapture captureData("source", ParamType::TvoidConstPointer);
3986*8975f5c5SAndroid Build Coastguard Worker CaptureMemory(buffer->getMapPointer(), static_cast<GLsizeiptr>(buffer->getSize()),
3987*8975f5c5SAndroid Build Coastguard Worker &captureData);
3988*8975f5c5SAndroid Build Coastguard Worker dataParamBuffer.addParam(std::move(captureData));
3989*8975f5c5SAndroid Build Coastguard Worker dataParamBuffer.addValueParam<GLsizeiptr>("size", ParamType::TGLsizeiptr,
3990*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(buffer->getSize()));
3991*8975f5c5SAndroid Build Coastguard Worker bufferMapCalls[bufferID].emplace_back("UpdateClientBufferData",
3992*8975f5c5SAndroid Build Coastguard Worker std::move(dataParamBuffer));
3993*8975f5c5SAndroid Build Coastguard Worker }
3994*8975f5c5SAndroid Build Coastguard Worker }
3995*8975f5c5SAndroid Build Coastguard Worker
3996*8975f5c5SAndroid Build Coastguard Worker // Track calls unmap a buffer that started as unmapped
3997*8975f5c5SAndroid Build Coastguard Worker BufferCalls &bufferUnmapCalls = resourceTracker->getBufferUnmapCalls();
3998*8975f5c5SAndroid Build Coastguard Worker Capture(&bufferUnmapCalls[bufferID],
3999*8975f5c5SAndroid Build Coastguard Worker CaptureBindBuffer(replayState, true, gl::BufferBinding::Array, *id));
4000*8975f5c5SAndroid Build Coastguard Worker Capture(&bufferUnmapCalls[bufferID],
4001*8975f5c5SAndroid Build Coastguard Worker CaptureUnmapBuffer(replayState, true, gl::BufferBinding::Array, GL_TRUE));
4002*8975f5c5SAndroid Build Coastguard Worker }
4003*8975f5c5SAndroid Build Coastguard Worker
CaptureFenceSyncResetCalls(const gl::Context * context,const gl::State & replayState,ResourceTracker * resourceTracker,gl::SyncID syncID,GLsync syncObject,const gl::Sync * sync)4004*8975f5c5SAndroid Build Coastguard Worker void CaptureFenceSyncResetCalls(const gl::Context *context,
4005*8975f5c5SAndroid Build Coastguard Worker const gl::State &replayState,
4006*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
4007*8975f5c5SAndroid Build Coastguard Worker gl::SyncID syncID,
4008*8975f5c5SAndroid Build Coastguard Worker GLsync syncObject,
4009*8975f5c5SAndroid Build Coastguard Worker const gl::Sync *sync)
4010*8975f5c5SAndroid Build Coastguard Worker {
4011*8975f5c5SAndroid Build Coastguard Worker // Track calls to regenerate a given fence sync
4012*8975f5c5SAndroid Build Coastguard Worker FenceSyncCalls &fenceSyncRegenCalls = resourceTracker->getFenceSyncRegenCalls();
4013*8975f5c5SAndroid Build Coastguard Worker CallCapture fenceSync =
4014*8975f5c5SAndroid Build Coastguard Worker CaptureFenceSync(replayState, true, sync->getCondition(), sync->getFlags(), syncObject);
4015*8975f5c5SAndroid Build Coastguard Worker CaptureCustomFenceSync(fenceSync, fenceSyncRegenCalls[syncID]);
4016*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, resourceTracker, &fenceSyncRegenCalls[syncID]);
4017*8975f5c5SAndroid Build Coastguard Worker }
4018*8975f5c5SAndroid Build Coastguard Worker
CaptureEGLSyncResetCalls(const gl::Context * context,const gl::State & replayState,ResourceTracker * resourceTracker,egl::SyncID eglSyncID,EGLSync eglSyncObject,const egl::Sync * eglSync)4019*8975f5c5SAndroid Build Coastguard Worker void CaptureEGLSyncResetCalls(const gl::Context *context,
4020*8975f5c5SAndroid Build Coastguard Worker const gl::State &replayState,
4021*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
4022*8975f5c5SAndroid Build Coastguard Worker egl::SyncID eglSyncID,
4023*8975f5c5SAndroid Build Coastguard Worker EGLSync eglSyncObject,
4024*8975f5c5SAndroid Build Coastguard Worker const egl::Sync *eglSync)
4025*8975f5c5SAndroid Build Coastguard Worker {
4026*8975f5c5SAndroid Build Coastguard Worker // Track this as a starting resource that may need to be restored.
4027*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedEGLSyncs =
4028*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::egl_Sync);
4029*8975f5c5SAndroid Build Coastguard Worker
4030*8975f5c5SAndroid Build Coastguard Worker // Track calls to regenerate a given buffer
4031*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &eglSyncRegenCalls = trackedEGLSyncs.getResourceRegenCalls();
4032*8975f5c5SAndroid Build Coastguard Worker
4033*8975f5c5SAndroid Build Coastguard Worker CallCapture createEGLSync =
4034*8975f5c5SAndroid Build Coastguard Worker CaptureCreateSyncKHR(nullptr, true, context->getDisplay(), eglSync->getType(),
4035*8975f5c5SAndroid Build Coastguard Worker eglSync->getAttributeMap(), eglSyncObject);
4036*8975f5c5SAndroid Build Coastguard Worker CaptureCustomCreateEGLSync("CreateEGLSyncKHR", createEGLSync,
4037*8975f5c5SAndroid Build Coastguard Worker eglSyncRegenCalls[eglSyncID.value]);
4038*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, resourceTracker, &eglSyncRegenCalls[eglSyncID.value]);
4039*8975f5c5SAndroid Build Coastguard Worker }
4040*8975f5c5SAndroid Build Coastguard Worker
CaptureBufferBindingResetCalls(const gl::State & replayState,ResourceTracker * resourceTracker,gl::BufferBinding binding,gl::BufferID id)4041*8975f5c5SAndroid Build Coastguard Worker void CaptureBufferBindingResetCalls(const gl::State &replayState,
4042*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
4043*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding binding,
4044*8975f5c5SAndroid Build Coastguard Worker gl::BufferID id)
4045*8975f5c5SAndroid Build Coastguard Worker {
4046*8975f5c5SAndroid Build Coastguard Worker // Track the calls to reset it
4047*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> &bufferBindingCalls = resourceTracker->getBufferBindingCalls();
4048*8975f5c5SAndroid Build Coastguard Worker Capture(&bufferBindingCalls, CaptureBindBuffer(replayState, true, binding, id));
4049*8975f5c5SAndroid Build Coastguard Worker }
4050*8975f5c5SAndroid Build Coastguard Worker
CaptureIndexedBuffers(const gl::State & glState,const gl::BufferVector & indexedBuffers,gl::BufferBinding binding,std::vector<CallCapture> * setupCalls)4051*8975f5c5SAndroid Build Coastguard Worker void CaptureIndexedBuffers(const gl::State &glState,
4052*8975f5c5SAndroid Build Coastguard Worker const gl::BufferVector &indexedBuffers,
4053*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding binding,
4054*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *setupCalls)
4055*8975f5c5SAndroid Build Coastguard Worker {
4056*8975f5c5SAndroid Build Coastguard Worker for (unsigned int index = 0; index < indexedBuffers.size(); ++index)
4057*8975f5c5SAndroid Build Coastguard Worker {
4058*8975f5c5SAndroid Build Coastguard Worker const gl::OffsetBindingPointer<gl::Buffer> &buffer = indexedBuffers[index];
4059*8975f5c5SAndroid Build Coastguard Worker
4060*8975f5c5SAndroid Build Coastguard Worker if (buffer.get() == nullptr)
4061*8975f5c5SAndroid Build Coastguard Worker {
4062*8975f5c5SAndroid Build Coastguard Worker continue;
4063*8975f5c5SAndroid Build Coastguard Worker }
4064*8975f5c5SAndroid Build Coastguard Worker
4065*8975f5c5SAndroid Build Coastguard Worker GLintptr offset = buffer.getOffset();
4066*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr size = buffer.getSize();
4067*8975f5c5SAndroid Build Coastguard Worker gl::BufferID bufferID = buffer.get()->id();
4068*8975f5c5SAndroid Build Coastguard Worker
4069*8975f5c5SAndroid Build Coastguard Worker // Context::bindBufferBase() calls Context::bindBufferRange() with size and offset = 0.
4070*8975f5c5SAndroid Build Coastguard Worker if ((offset == 0) && (size == 0))
4071*8975f5c5SAndroid Build Coastguard Worker {
4072*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureBindBufferBase(glState, true, binding, index, bufferID));
4073*8975f5c5SAndroid Build Coastguard Worker }
4074*8975f5c5SAndroid Build Coastguard Worker else
4075*8975f5c5SAndroid Build Coastguard Worker {
4076*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls,
4077*8975f5c5SAndroid Build Coastguard Worker CaptureBindBufferRange(glState, true, binding, index, bufferID, offset, size));
4078*8975f5c5SAndroid Build Coastguard Worker }
4079*8975f5c5SAndroid Build Coastguard Worker }
4080*8975f5c5SAndroid Build Coastguard Worker }
4081*8975f5c5SAndroid Build Coastguard Worker
CaptureDefaultVertexAttribs(const gl::State & replayState,const gl::State & apiState,std::vector<CallCapture> * setupCalls)4082*8975f5c5SAndroid Build Coastguard Worker void CaptureDefaultVertexAttribs(const gl::State &replayState,
4083*8975f5c5SAndroid Build Coastguard Worker const gl::State &apiState,
4084*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *setupCalls)
4085*8975f5c5SAndroid Build Coastguard Worker {
4086*8975f5c5SAndroid Build Coastguard Worker const std::vector<gl::VertexAttribCurrentValueData> ¤tValues =
4087*8975f5c5SAndroid Build Coastguard Worker apiState.getVertexAttribCurrentValues();
4088*8975f5c5SAndroid Build Coastguard Worker
4089*8975f5c5SAndroid Build Coastguard Worker for (GLuint attribIndex = 0; attribIndex < currentValues.size(); ++attribIndex)
4090*8975f5c5SAndroid Build Coastguard Worker {
4091*8975f5c5SAndroid Build Coastguard Worker const gl::VertexAttribCurrentValueData &defaultValue = currentValues[attribIndex];
4092*8975f5c5SAndroid Build Coastguard Worker if (!IsDefaultCurrentValue(defaultValue))
4093*8975f5c5SAndroid Build Coastguard Worker {
4094*8975f5c5SAndroid Build Coastguard Worker Capture(setupCalls, CaptureVertexAttrib4fv(replayState, true, attribIndex,
4095*8975f5c5SAndroid Build Coastguard Worker defaultValue.Values.FloatValues));
4096*8975f5c5SAndroid Build Coastguard Worker }
4097*8975f5c5SAndroid Build Coastguard Worker }
4098*8975f5c5SAndroid Build Coastguard Worker }
4099*8975f5c5SAndroid Build Coastguard Worker
CompressPalettedTexture(angle::MemoryBuffer & data,angle::MemoryBuffer & tmp,const gl::InternalFormat & compressedFormat,const gl::Extents & extents)4100*8975f5c5SAndroid Build Coastguard Worker void CompressPalettedTexture(angle::MemoryBuffer &data,
4101*8975f5c5SAndroid Build Coastguard Worker angle::MemoryBuffer &tmp,
4102*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &compressedFormat,
4103*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &extents)
4104*8975f5c5SAndroid Build Coastguard Worker {
4105*8975f5c5SAndroid Build Coastguard Worker constexpr int uncompressedChannelCount = 4;
4106*8975f5c5SAndroid Build Coastguard Worker
4107*8975f5c5SAndroid Build Coastguard Worker uint32_t indexBits = 0, redBlueBits = 0, greenBits = 0, alphaBits = 0;
4108*8975f5c5SAndroid Build Coastguard Worker switch (compressedFormat.internalFormat)
4109*8975f5c5SAndroid Build Coastguard Worker {
4110*8975f5c5SAndroid Build Coastguard Worker case GL_PALETTE4_RGB8_OES:
4111*8975f5c5SAndroid Build Coastguard Worker indexBits = 4;
4112*8975f5c5SAndroid Build Coastguard Worker redBlueBits = 8;
4113*8975f5c5SAndroid Build Coastguard Worker greenBits = 8;
4114*8975f5c5SAndroid Build Coastguard Worker alphaBits = 0;
4115*8975f5c5SAndroid Build Coastguard Worker break;
4116*8975f5c5SAndroid Build Coastguard Worker case GL_PALETTE4_RGBA8_OES:
4117*8975f5c5SAndroid Build Coastguard Worker indexBits = 4;
4118*8975f5c5SAndroid Build Coastguard Worker redBlueBits = 8;
4119*8975f5c5SAndroid Build Coastguard Worker greenBits = 8;
4120*8975f5c5SAndroid Build Coastguard Worker alphaBits = 8;
4121*8975f5c5SAndroid Build Coastguard Worker break;
4122*8975f5c5SAndroid Build Coastguard Worker case GL_PALETTE4_R5_G6_B5_OES:
4123*8975f5c5SAndroid Build Coastguard Worker indexBits = 4;
4124*8975f5c5SAndroid Build Coastguard Worker redBlueBits = 5;
4125*8975f5c5SAndroid Build Coastguard Worker greenBits = 6;
4126*8975f5c5SAndroid Build Coastguard Worker alphaBits = 0;
4127*8975f5c5SAndroid Build Coastguard Worker break;
4128*8975f5c5SAndroid Build Coastguard Worker case GL_PALETTE4_RGBA4_OES:
4129*8975f5c5SAndroid Build Coastguard Worker indexBits = 4;
4130*8975f5c5SAndroid Build Coastguard Worker redBlueBits = 4;
4131*8975f5c5SAndroid Build Coastguard Worker greenBits = 4;
4132*8975f5c5SAndroid Build Coastguard Worker alphaBits = 4;
4133*8975f5c5SAndroid Build Coastguard Worker break;
4134*8975f5c5SAndroid Build Coastguard Worker case GL_PALETTE4_RGB5_A1_OES:
4135*8975f5c5SAndroid Build Coastguard Worker indexBits = 4;
4136*8975f5c5SAndroid Build Coastguard Worker redBlueBits = 5;
4137*8975f5c5SAndroid Build Coastguard Worker greenBits = 5;
4138*8975f5c5SAndroid Build Coastguard Worker alphaBits = 1;
4139*8975f5c5SAndroid Build Coastguard Worker break;
4140*8975f5c5SAndroid Build Coastguard Worker case GL_PALETTE8_RGB8_OES:
4141*8975f5c5SAndroid Build Coastguard Worker indexBits = 8;
4142*8975f5c5SAndroid Build Coastguard Worker redBlueBits = 8;
4143*8975f5c5SAndroid Build Coastguard Worker greenBits = 8;
4144*8975f5c5SAndroid Build Coastguard Worker alphaBits = 0;
4145*8975f5c5SAndroid Build Coastguard Worker break;
4146*8975f5c5SAndroid Build Coastguard Worker case GL_PALETTE8_RGBA8_OES:
4147*8975f5c5SAndroid Build Coastguard Worker indexBits = 8;
4148*8975f5c5SAndroid Build Coastguard Worker redBlueBits = 8;
4149*8975f5c5SAndroid Build Coastguard Worker greenBits = 8;
4150*8975f5c5SAndroid Build Coastguard Worker alphaBits = 8;
4151*8975f5c5SAndroid Build Coastguard Worker break;
4152*8975f5c5SAndroid Build Coastguard Worker case GL_PALETTE8_R5_G6_B5_OES:
4153*8975f5c5SAndroid Build Coastguard Worker indexBits = 8;
4154*8975f5c5SAndroid Build Coastguard Worker redBlueBits = 5;
4155*8975f5c5SAndroid Build Coastguard Worker greenBits = 6;
4156*8975f5c5SAndroid Build Coastguard Worker alphaBits = 0;
4157*8975f5c5SAndroid Build Coastguard Worker break;
4158*8975f5c5SAndroid Build Coastguard Worker case GL_PALETTE8_RGBA4_OES:
4159*8975f5c5SAndroid Build Coastguard Worker indexBits = 8;
4160*8975f5c5SAndroid Build Coastguard Worker redBlueBits = 4;
4161*8975f5c5SAndroid Build Coastguard Worker greenBits = 4;
4162*8975f5c5SAndroid Build Coastguard Worker alphaBits = 4;
4163*8975f5c5SAndroid Build Coastguard Worker break;
4164*8975f5c5SAndroid Build Coastguard Worker case GL_PALETTE8_RGB5_A1_OES:
4165*8975f5c5SAndroid Build Coastguard Worker indexBits = 8;
4166*8975f5c5SAndroid Build Coastguard Worker redBlueBits = 5;
4167*8975f5c5SAndroid Build Coastguard Worker greenBits = 5;
4168*8975f5c5SAndroid Build Coastguard Worker alphaBits = 1;
4169*8975f5c5SAndroid Build Coastguard Worker break;
4170*8975f5c5SAndroid Build Coastguard Worker
4171*8975f5c5SAndroid Build Coastguard Worker default:
4172*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
4173*8975f5c5SAndroid Build Coastguard Worker break;
4174*8975f5c5SAndroid Build Coastguard Worker }
4175*8975f5c5SAndroid Build Coastguard Worker
4176*8975f5c5SAndroid Build Coastguard Worker bool result = data.resize(
4177*8975f5c5SAndroid Build Coastguard Worker // Palette size
4178*8975f5c5SAndroid Build Coastguard Worker (1 << indexBits) * (2 * redBlueBits + greenBits + alphaBits) / 8 +
4179*8975f5c5SAndroid Build Coastguard Worker // Texels size
4180*8975f5c5SAndroid Build Coastguard Worker indexBits * extents.width * extents.height * extents.depth / 8);
4181*8975f5c5SAndroid Build Coastguard Worker ASSERT(result);
4182*8975f5c5SAndroid Build Coastguard Worker
4183*8975f5c5SAndroid Build Coastguard Worker angle::StoreRGBA8ToPalettedImpl(
4184*8975f5c5SAndroid Build Coastguard Worker extents.width, extents.height, extents.depth, indexBits, redBlueBits, greenBits, alphaBits,
4185*8975f5c5SAndroid Build Coastguard Worker tmp.data(),
4186*8975f5c5SAndroid Build Coastguard Worker uncompressedChannelCount * extents.width, // inputRowPitch
4187*8975f5c5SAndroid Build Coastguard Worker uncompressedChannelCount * extents.width * extents.height, // inputDepthPitch
4188*8975f5c5SAndroid Build Coastguard Worker data.data(), // output
4189*8975f5c5SAndroid Build Coastguard Worker indexBits * extents.width / 8, // outputRowPitch
4190*8975f5c5SAndroid Build Coastguard Worker indexBits * extents.width * extents.height / 8 // outputDepthPitch
4191*8975f5c5SAndroid Build Coastguard Worker );
4192*8975f5c5SAndroid Build Coastguard Worker }
4193*8975f5c5SAndroid Build Coastguard Worker
4194*8975f5c5SAndroid Build Coastguard Worker // Capture the setup of the state that's shared by all of the contexts in the share group
4195*8975f5c5SAndroid Build Coastguard Worker // See IsSharedObjectResource for the list of objects covered here.
CaptureShareGroupMidExecutionSetup(gl::Context * context,std::vector<CallCapture> * setupCalls,ResourceTracker * resourceTracker,gl::State & replayState,const PackedEnumMap<ResourceIDType,uint32_t> & maxAccessedResourceIDs)4196*8975f5c5SAndroid Build Coastguard Worker void CaptureShareGroupMidExecutionSetup(
4197*8975f5c5SAndroid Build Coastguard Worker gl::Context *context,
4198*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *setupCalls,
4199*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
4200*8975f5c5SAndroid Build Coastguard Worker gl::State &replayState,
4201*8975f5c5SAndroid Build Coastguard Worker const PackedEnumMap<ResourceIDType, uint32_t> &maxAccessedResourceIDs)
4202*8975f5c5SAndroid Build Coastguard Worker {
4203*8975f5c5SAndroid Build Coastguard Worker FrameCaptureShared *frameCaptureShared = context->getShareGroup()->getFrameCaptureShared();
4204*8975f5c5SAndroid Build Coastguard Worker const gl::State &apiState = context->getState();
4205*8975f5c5SAndroid Build Coastguard Worker
4206*8975f5c5SAndroid Build Coastguard Worker // Small helper function to make the code more readable.
4207*8975f5c5SAndroid Build Coastguard Worker auto cap = [setupCalls](CallCapture &&call) { setupCalls->emplace_back(std::move(call)); };
4208*8975f5c5SAndroid Build Coastguard Worker
4209*8975f5c5SAndroid Build Coastguard Worker // Capture Buffer data.
4210*8975f5c5SAndroid Build Coastguard Worker const gl::BufferManager &buffers = apiState.getBufferManagerForCapture();
4211*8975f5c5SAndroid Build Coastguard Worker for (const auto &bufferIter : gl::UnsafeResourceMapIter(buffers.getResourcesForCapture()))
4212*8975f5c5SAndroid Build Coastguard Worker {
4213*8975f5c5SAndroid Build Coastguard Worker gl::BufferID id = {bufferIter.first};
4214*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = bufferIter.second;
4215*8975f5c5SAndroid Build Coastguard Worker
4216*8975f5c5SAndroid Build Coastguard Worker if (id.value == 0)
4217*8975f5c5SAndroid Build Coastguard Worker {
4218*8975f5c5SAndroid Build Coastguard Worker continue;
4219*8975f5c5SAndroid Build Coastguard Worker }
4220*8975f5c5SAndroid Build Coastguard Worker
4221*8975f5c5SAndroid Build Coastguard Worker // Generate binding.
4222*8975f5c5SAndroid Build Coastguard Worker cap(CaptureGenBuffers(replayState, true, 1, &id));
4223*8975f5c5SAndroid Build Coastguard Worker
4224*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::Buffer)
4225*8975f5c5SAndroid Build Coastguard Worker .getStartingResources()
4226*8975f5c5SAndroid Build Coastguard Worker .insert(id.value);
4227*8975f5c5SAndroid Build Coastguard Worker
4228*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, resourceTracker, setupCalls);
4229*8975f5c5SAndroid Build Coastguard Worker
4230*8975f5c5SAndroid Build Coastguard Worker // glBufferData. Would possibly be better implemented using a getData impl method.
4231*8975f5c5SAndroid Build Coastguard Worker // Saving buffers that are mapped during a swap is not yet handled.
4232*8975f5c5SAndroid Build Coastguard Worker if (buffer->getSize() == 0)
4233*8975f5c5SAndroid Build Coastguard Worker {
4234*8975f5c5SAndroid Build Coastguard Worker resourceTracker->setStartingBufferMapped(buffer->id().value, false);
4235*8975f5c5SAndroid Build Coastguard Worker continue;
4236*8975f5c5SAndroid Build Coastguard Worker }
4237*8975f5c5SAndroid Build Coastguard Worker
4238*8975f5c5SAndroid Build Coastguard Worker // Remember if the buffer was already mapped
4239*8975f5c5SAndroid Build Coastguard Worker GLboolean bufferMapped = buffer->isMapped();
4240*8975f5c5SAndroid Build Coastguard Worker
4241*8975f5c5SAndroid Build Coastguard Worker // If needed, map the buffer so we can capture its contents
4242*8975f5c5SAndroid Build Coastguard Worker if (!bufferMapped)
4243*8975f5c5SAndroid Build Coastguard Worker {
4244*8975f5c5SAndroid Build Coastguard Worker (void)buffer->mapRange(context, 0, static_cast<GLsizeiptr>(buffer->getSize()),
4245*8975f5c5SAndroid Build Coastguard Worker GL_MAP_READ_BIT);
4246*8975f5c5SAndroid Build Coastguard Worker }
4247*8975f5c5SAndroid Build Coastguard Worker
4248*8975f5c5SAndroid Build Coastguard Worker // Always use the array buffer binding point to upload data to keep things simple.
4249*8975f5c5SAndroid Build Coastguard Worker if (buffer != replayState.getArrayBuffer())
4250*8975f5c5SAndroid Build Coastguard Worker {
4251*8975f5c5SAndroid Build Coastguard Worker replayState.setBufferBinding(context, gl::BufferBinding::Array, buffer);
4252*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBindBuffer(replayState, true, gl::BufferBinding::Array, id));
4253*8975f5c5SAndroid Build Coastguard Worker }
4254*8975f5c5SAndroid Build Coastguard Worker
4255*8975f5c5SAndroid Build Coastguard Worker if (buffer->isImmutable())
4256*8975f5c5SAndroid Build Coastguard Worker {
4257*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBufferStorageEXT(replayState, true, gl::BufferBinding::Array,
4258*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(buffer->getSize()),
4259*8975f5c5SAndroid Build Coastguard Worker buffer->getMapPointer(),
4260*8975f5c5SAndroid Build Coastguard Worker buffer->getStorageExtUsageFlags()));
4261*8975f5c5SAndroid Build Coastguard Worker }
4262*8975f5c5SAndroid Build Coastguard Worker else
4263*8975f5c5SAndroid Build Coastguard Worker {
4264*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBufferData(replayState, true, gl::BufferBinding::Array,
4265*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(buffer->getSize()),
4266*8975f5c5SAndroid Build Coastguard Worker buffer->getMapPointer(), buffer->getUsage()));
4267*8975f5c5SAndroid Build Coastguard Worker }
4268*8975f5c5SAndroid Build Coastguard Worker
4269*8975f5c5SAndroid Build Coastguard Worker if (bufferMapped)
4270*8975f5c5SAndroid Build Coastguard Worker {
4271*8975f5c5SAndroid Build Coastguard Worker void *dontCare = nullptr;
4272*8975f5c5SAndroid Build Coastguard Worker CallCapture mapBufferRange =
4273*8975f5c5SAndroid Build Coastguard Worker CaptureMapBufferRange(replayState, true, gl::BufferBinding::Array,
4274*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(buffer->getMapOffset()),
4275*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(buffer->getMapLength()),
4276*8975f5c5SAndroid Build Coastguard Worker buffer->getAccessFlags(), dontCare);
4277*8975f5c5SAndroid Build Coastguard Worker CaptureCustomMapBuffer("MapBufferRange", mapBufferRange, *setupCalls, buffer->id());
4278*8975f5c5SAndroid Build Coastguard Worker
4279*8975f5c5SAndroid Build Coastguard Worker resourceTracker->setStartingBufferMapped(buffer->id().value, true);
4280*8975f5c5SAndroid Build Coastguard Worker
4281*8975f5c5SAndroid Build Coastguard Worker frameCaptureShared->trackBufferMapping(
4282*8975f5c5SAndroid Build Coastguard Worker context, &setupCalls->back(), buffer->id(), buffer,
4283*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(buffer->getMapOffset()),
4284*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(buffer->getMapLength()),
4285*8975f5c5SAndroid Build Coastguard Worker (buffer->getAccessFlags() & GL_MAP_WRITE_BIT) != 0,
4286*8975f5c5SAndroid Build Coastguard Worker (buffer->getStorageExtUsageFlags() & GL_MAP_COHERENT_BIT_EXT) != 0);
4287*8975f5c5SAndroid Build Coastguard Worker }
4288*8975f5c5SAndroid Build Coastguard Worker else
4289*8975f5c5SAndroid Build Coastguard Worker {
4290*8975f5c5SAndroid Build Coastguard Worker resourceTracker->setStartingBufferMapped(buffer->id().value, false);
4291*8975f5c5SAndroid Build Coastguard Worker }
4292*8975f5c5SAndroid Build Coastguard Worker
4293*8975f5c5SAndroid Build Coastguard Worker // Generate the calls needed to restore this buffer to original state for frame looping
4294*8975f5c5SAndroid Build Coastguard Worker CaptureBufferResetCalls(context, replayState, resourceTracker, &id, buffer);
4295*8975f5c5SAndroid Build Coastguard Worker
4296*8975f5c5SAndroid Build Coastguard Worker // Unmap the buffer if it wasn't already mapped
4297*8975f5c5SAndroid Build Coastguard Worker if (!bufferMapped)
4298*8975f5c5SAndroid Build Coastguard Worker {
4299*8975f5c5SAndroid Build Coastguard Worker GLboolean dontCare;
4300*8975f5c5SAndroid Build Coastguard Worker (void)buffer->unmap(context, &dontCare);
4301*8975f5c5SAndroid Build Coastguard Worker }
4302*8975f5c5SAndroid Build Coastguard Worker }
4303*8975f5c5SAndroid Build Coastguard Worker
4304*8975f5c5SAndroid Build Coastguard Worker // Clear the array buffer binding.
4305*8975f5c5SAndroid Build Coastguard Worker if (replayState.getTargetBuffer(gl::BufferBinding::Array))
4306*8975f5c5SAndroid Build Coastguard Worker {
4307*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBindBuffer(replayState, true, gl::BufferBinding::Array, {0}));
4308*8975f5c5SAndroid Build Coastguard Worker replayState.setBufferBinding(context, gl::BufferBinding::Array, nullptr);
4309*8975f5c5SAndroid Build Coastguard Worker }
4310*8975f5c5SAndroid Build Coastguard Worker
4311*8975f5c5SAndroid Build Coastguard Worker // Set a unpack alignment of 1. Otherwise, computeRowPitch() will compute the wrong value,
4312*8975f5c5SAndroid Build Coastguard Worker // leading to a crash in memcpy() when capturing the texture contents.
4313*8975f5c5SAndroid Build Coastguard Worker gl::PixelUnpackState ¤tUnpackState = replayState.getUnpackState();
4314*8975f5c5SAndroid Build Coastguard Worker if (currentUnpackState.alignment != 1)
4315*8975f5c5SAndroid Build Coastguard Worker {
4316*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_UNPACK_ALIGNMENT, 1));
4317*8975f5c5SAndroid Build Coastguard Worker replayState.getMutablePrivateStateForCapture()->setUnpackAlignment(1);
4318*8975f5c5SAndroid Build Coastguard Worker }
4319*8975f5c5SAndroid Build Coastguard Worker
4320*8975f5c5SAndroid Build Coastguard Worker const egl::ImageMap eglImageMap = context->getDisplay()->getImagesForCapture();
4321*8975f5c5SAndroid Build Coastguard Worker for (const auto &[eglImageID, eglImage] : eglImageMap)
4322*8975f5c5SAndroid Build Coastguard Worker {
4323*8975f5c5SAndroid Build Coastguard Worker // Track this as a starting resource that may need to be restored.
4324*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedImages =
4325*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::Image);
4326*8975f5c5SAndroid Build Coastguard Worker trackedImages.getStartingResources().insert(eglImageID);
4327*8975f5c5SAndroid Build Coastguard Worker
4328*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &imageRegenCalls = trackedImages.getResourceRegenCalls();
4329*8975f5c5SAndroid Build Coastguard Worker CallVector imageGenCalls({setupCalls, &imageRegenCalls[eglImageID]});
4330*8975f5c5SAndroid Build Coastguard Worker
4331*8975f5c5SAndroid Build Coastguard Worker auto eglImageAttribIter = resourceTracker->getImageToAttribTable().find(
4332*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLImage>(static_cast<uintptr_t>(eglImageID)));
4333*8975f5c5SAndroid Build Coastguard Worker ASSERT(eglImageAttribIter != resourceTracker->getImageToAttribTable().end());
4334*8975f5c5SAndroid Build Coastguard Worker const egl::AttributeMap &attribs = eglImageAttribIter->second;
4335*8975f5c5SAndroid Build Coastguard Worker
4336*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : imageGenCalls)
4337*8975f5c5SAndroid Build Coastguard Worker {
4338*8975f5c5SAndroid Build Coastguard Worker // Create the image on demand with the same attrib retrieved above
4339*8975f5c5SAndroid Build Coastguard Worker CallCapture eglCreateImageKHRCall = egl::CaptureCreateImageKHR(
4340*8975f5c5SAndroid Build Coastguard Worker nullptr, true, nullptr, context->id(), EGL_GL_TEXTURE_2D,
4341*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(0)), attribs,
4342*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLImage>(static_cast<uintptr_t>(eglImageID)));
4343*8975f5c5SAndroid Build Coastguard Worker
4344*8975f5c5SAndroid Build Coastguard Worker // Convert the CaptureCreateImageKHR CallCapture to the customized CallCapture
4345*8975f5c5SAndroid Build Coastguard Worker CaptureCustomCreateEGLImage(context, "CreateEGLImageKHR", eglImage->getWidth(),
4346*8975f5c5SAndroid Build Coastguard Worker eglImage->getHeight(), eglCreateImageKHRCall, *calls);
4347*8975f5c5SAndroid Build Coastguard Worker }
4348*8975f5c5SAndroid Build Coastguard Worker }
4349*8975f5c5SAndroid Build Coastguard Worker
4350*8975f5c5SAndroid Build Coastguard Worker // Capture Texture setup and data.
4351*8975f5c5SAndroid Build Coastguard Worker const gl::TextureManager &textures = apiState.getTextureManagerForCapture();
4352*8975f5c5SAndroid Build Coastguard Worker
4353*8975f5c5SAndroid Build Coastguard Worker for (const auto &textureIter : gl::UnsafeResourceMapIter(textures.getResourcesForCapture()))
4354*8975f5c5SAndroid Build Coastguard Worker {
4355*8975f5c5SAndroid Build Coastguard Worker gl::TextureID id = {textureIter.first};
4356*8975f5c5SAndroid Build Coastguard Worker gl::Texture *texture = textureIter.second;
4357*8975f5c5SAndroid Build Coastguard Worker
4358*8975f5c5SAndroid Build Coastguard Worker if (id.value == 0)
4359*8975f5c5SAndroid Build Coastguard Worker {
4360*8975f5c5SAndroid Build Coastguard Worker continue;
4361*8975f5c5SAndroid Build Coastguard Worker }
4362*8975f5c5SAndroid Build Coastguard Worker
4363*8975f5c5SAndroid Build Coastguard Worker size_t textureSetupStart = setupCalls->size();
4364*8975f5c5SAndroid Build Coastguard Worker
4365*8975f5c5SAndroid Build Coastguard Worker // Track this as a starting resource that may need to be restored.
4366*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedTextures =
4367*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::Texture);
4368*8975f5c5SAndroid Build Coastguard Worker ResourceSet &startingTextures = trackedTextures.getStartingResources();
4369*8975f5c5SAndroid Build Coastguard Worker startingTextures.insert(id.value);
4370*8975f5c5SAndroid Build Coastguard Worker
4371*8975f5c5SAndroid Build Coastguard Worker // For the initial texture creation calls, track in the generate list
4372*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &textureRegenCalls = trackedTextures.getResourceRegenCalls();
4373*8975f5c5SAndroid Build Coastguard Worker CallVector texGenCalls({setupCalls, &textureRegenCalls[id.value]});
4374*8975f5c5SAndroid Build Coastguard Worker
4375*8975f5c5SAndroid Build Coastguard Worker // Gen the Texture.
4376*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : texGenCalls)
4377*8975f5c5SAndroid Build Coastguard Worker {
4378*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureGenTextures(replayState, true, 1, &id));
4379*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, resourceTracker, calls);
4380*8975f5c5SAndroid Build Coastguard Worker }
4381*8975f5c5SAndroid Build Coastguard Worker
4382*8975f5c5SAndroid Build Coastguard Worker // For the remaining texture setup calls, track in the restore list
4383*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &textureRestoreCalls = trackedTextures.getResourceRestoreCalls();
4384*8975f5c5SAndroid Build Coastguard Worker CallVector texSetupCalls({setupCalls, &textureRestoreCalls[id.value]});
4385*8975f5c5SAndroid Build Coastguard Worker
4386*8975f5c5SAndroid Build Coastguard Worker // For each texture, set the correct active texture and binding
4387*8975f5c5SAndroid Build Coastguard Worker // There is similar code in CaptureMidExecutionSetup for per-context setup
4388*8975f5c5SAndroid Build Coastguard Worker const gl::TextureBindingMap ¤tBoundTextures = apiState.getBoundTexturesForCapture();
4389*8975f5c5SAndroid Build Coastguard Worker const gl::TextureBindingVector ¤tBindings = currentBoundTextures[texture->getType()];
4390*8975f5c5SAndroid Build Coastguard Worker const gl::TextureBindingVector &replayBindings =
4391*8975f5c5SAndroid Build Coastguard Worker replayState.getBoundTexturesForCapture()[texture->getType()];
4392*8975f5c5SAndroid Build Coastguard Worker ASSERT(currentBindings.size() == replayBindings.size());
4393*8975f5c5SAndroid Build Coastguard Worker
4394*8975f5c5SAndroid Build Coastguard Worker // Look up the replay binding
4395*8975f5c5SAndroid Build Coastguard Worker size_t replayActiveTexture = replayState.getActiveSampler();
4396*8975f5c5SAndroid Build Coastguard Worker // If there ends up being no binding, just use the replay binding
4397*8975f5c5SAndroid Build Coastguard Worker // TODO: We may want to start using index 0 for everything, mark it dirty, and restore it
4398*8975f5c5SAndroid Build Coastguard Worker size_t currentActiveTexture = replayActiveTexture;
4399*8975f5c5SAndroid Build Coastguard Worker
4400*8975f5c5SAndroid Build Coastguard Worker // Iterate through current bindings and find the correct index for this texture ID
4401*8975f5c5SAndroid Build Coastguard Worker for (size_t bindingIndex = 0; bindingIndex < currentBindings.size(); ++bindingIndex)
4402*8975f5c5SAndroid Build Coastguard Worker {
4403*8975f5c5SAndroid Build Coastguard Worker gl::TextureID currentTextureID = currentBindings[bindingIndex].id();
4404*8975f5c5SAndroid Build Coastguard Worker gl::TextureID replayTextureID = replayBindings[bindingIndex].id();
4405*8975f5c5SAndroid Build Coastguard Worker
4406*8975f5c5SAndroid Build Coastguard Worker // Only check the texture we care about
4407*8975f5c5SAndroid Build Coastguard Worker if (currentTextureID == texture->id())
4408*8975f5c5SAndroid Build Coastguard Worker {
4409*8975f5c5SAndroid Build Coastguard Worker // If the binding doesn't match, track it
4410*8975f5c5SAndroid Build Coastguard Worker if (currentTextureID != replayTextureID)
4411*8975f5c5SAndroid Build Coastguard Worker {
4412*8975f5c5SAndroid Build Coastguard Worker currentActiveTexture = bindingIndex;
4413*8975f5c5SAndroid Build Coastguard Worker }
4414*8975f5c5SAndroid Build Coastguard Worker
4415*8975f5c5SAndroid Build Coastguard Worker break;
4416*8975f5c5SAndroid Build Coastguard Worker }
4417*8975f5c5SAndroid Build Coastguard Worker }
4418*8975f5c5SAndroid Build Coastguard Worker
4419*8975f5c5SAndroid Build Coastguard Worker // Set the correct active texture before performing any state changes, including binding
4420*8975f5c5SAndroid Build Coastguard Worker if (currentActiveTexture != replayActiveTexture)
4421*8975f5c5SAndroid Build Coastguard Worker {
4422*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : texSetupCalls)
4423*8975f5c5SAndroid Build Coastguard Worker {
4424*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureActiveTexture(
4425*8975f5c5SAndroid Build Coastguard Worker replayState, true,
4426*8975f5c5SAndroid Build Coastguard Worker GL_TEXTURE0 + static_cast<GLenum>(currentActiveTexture)));
4427*8975f5c5SAndroid Build Coastguard Worker }
4428*8975f5c5SAndroid Build Coastguard Worker replayState.getMutablePrivateStateForCapture()->setActiveSampler(
4429*8975f5c5SAndroid Build Coastguard Worker static_cast<unsigned int>(currentActiveTexture));
4430*8975f5c5SAndroid Build Coastguard Worker }
4431*8975f5c5SAndroid Build Coastguard Worker
4432*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : texSetupCalls)
4433*8975f5c5SAndroid Build Coastguard Worker {
4434*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureBindTexture(replayState, true, texture->getType(), id));
4435*8975f5c5SAndroid Build Coastguard Worker }
4436*8975f5c5SAndroid Build Coastguard Worker replayState.setSamplerTexture(context, texture->getType(), texture);
4437*8975f5c5SAndroid Build Coastguard Worker
4438*8975f5c5SAndroid Build Coastguard Worker // Capture sampler parameter states.
4439*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): More sampler / texture states. http://anglebug.com/42262323
4440*8975f5c5SAndroid Build Coastguard Worker gl::SamplerState defaultSamplerState =
4441*8975f5c5SAndroid Build Coastguard Worker gl::SamplerState::CreateDefaultForTarget(texture->getType());
4442*8975f5c5SAndroid Build Coastguard Worker const gl::SamplerState &textureSamplerState = texture->getSamplerState();
4443*8975f5c5SAndroid Build Coastguard Worker
4444*8975f5c5SAndroid Build Coastguard Worker auto capTexParam = [&replayState, texture, &texSetupCalls](GLenum pname, GLint param) {
4445*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : texSetupCalls)
4446*8975f5c5SAndroid Build Coastguard Worker {
4447*8975f5c5SAndroid Build Coastguard Worker Capture(calls,
4448*8975f5c5SAndroid Build Coastguard Worker CaptureTexParameteri(replayState, true, texture->getType(), pname, param));
4449*8975f5c5SAndroid Build Coastguard Worker }
4450*8975f5c5SAndroid Build Coastguard Worker };
4451*8975f5c5SAndroid Build Coastguard Worker
4452*8975f5c5SAndroid Build Coastguard Worker auto capTexParamf = [&replayState, texture, &texSetupCalls](GLenum pname, GLfloat param) {
4453*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : texSetupCalls)
4454*8975f5c5SAndroid Build Coastguard Worker {
4455*8975f5c5SAndroid Build Coastguard Worker Capture(calls,
4456*8975f5c5SAndroid Build Coastguard Worker CaptureTexParameterf(replayState, true, texture->getType(), pname, param));
4457*8975f5c5SAndroid Build Coastguard Worker }
4458*8975f5c5SAndroid Build Coastguard Worker };
4459*8975f5c5SAndroid Build Coastguard Worker
4460*8975f5c5SAndroid Build Coastguard Worker if (textureSamplerState.getMinFilter() != defaultSamplerState.getMinFilter())
4461*8975f5c5SAndroid Build Coastguard Worker {
4462*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_MIN_FILTER, textureSamplerState.getMinFilter());
4463*8975f5c5SAndroid Build Coastguard Worker }
4464*8975f5c5SAndroid Build Coastguard Worker
4465*8975f5c5SAndroid Build Coastguard Worker if (textureSamplerState.getMagFilter() != defaultSamplerState.getMagFilter())
4466*8975f5c5SAndroid Build Coastguard Worker {
4467*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_MAG_FILTER, textureSamplerState.getMagFilter());
4468*8975f5c5SAndroid Build Coastguard Worker }
4469*8975f5c5SAndroid Build Coastguard Worker
4470*8975f5c5SAndroid Build Coastguard Worker if (textureSamplerState.getWrapR() != defaultSamplerState.getWrapR())
4471*8975f5c5SAndroid Build Coastguard Worker {
4472*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_WRAP_R, textureSamplerState.getWrapR());
4473*8975f5c5SAndroid Build Coastguard Worker }
4474*8975f5c5SAndroid Build Coastguard Worker
4475*8975f5c5SAndroid Build Coastguard Worker if (textureSamplerState.getWrapS() != defaultSamplerState.getWrapS())
4476*8975f5c5SAndroid Build Coastguard Worker {
4477*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_WRAP_S, textureSamplerState.getWrapS());
4478*8975f5c5SAndroid Build Coastguard Worker }
4479*8975f5c5SAndroid Build Coastguard Worker
4480*8975f5c5SAndroid Build Coastguard Worker if (textureSamplerState.getWrapT() != defaultSamplerState.getWrapT())
4481*8975f5c5SAndroid Build Coastguard Worker {
4482*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_WRAP_T, textureSamplerState.getWrapT());
4483*8975f5c5SAndroid Build Coastguard Worker }
4484*8975f5c5SAndroid Build Coastguard Worker
4485*8975f5c5SAndroid Build Coastguard Worker if (textureSamplerState.getMinLod() != defaultSamplerState.getMinLod())
4486*8975f5c5SAndroid Build Coastguard Worker {
4487*8975f5c5SAndroid Build Coastguard Worker capTexParamf(GL_TEXTURE_MIN_LOD, textureSamplerState.getMinLod());
4488*8975f5c5SAndroid Build Coastguard Worker }
4489*8975f5c5SAndroid Build Coastguard Worker
4490*8975f5c5SAndroid Build Coastguard Worker if (textureSamplerState.getMaxLod() != defaultSamplerState.getMaxLod())
4491*8975f5c5SAndroid Build Coastguard Worker {
4492*8975f5c5SAndroid Build Coastguard Worker capTexParamf(GL_TEXTURE_MAX_LOD, textureSamplerState.getMaxLod());
4493*8975f5c5SAndroid Build Coastguard Worker }
4494*8975f5c5SAndroid Build Coastguard Worker
4495*8975f5c5SAndroid Build Coastguard Worker if (textureSamplerState.getCompareMode() != defaultSamplerState.getCompareMode())
4496*8975f5c5SAndroid Build Coastguard Worker {
4497*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_COMPARE_MODE, textureSamplerState.getCompareMode());
4498*8975f5c5SAndroid Build Coastguard Worker }
4499*8975f5c5SAndroid Build Coastguard Worker
4500*8975f5c5SAndroid Build Coastguard Worker if (textureSamplerState.getCompareFunc() != defaultSamplerState.getCompareFunc())
4501*8975f5c5SAndroid Build Coastguard Worker {
4502*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_COMPARE_FUNC, textureSamplerState.getCompareFunc());
4503*8975f5c5SAndroid Build Coastguard Worker }
4504*8975f5c5SAndroid Build Coastguard Worker
4505*8975f5c5SAndroid Build Coastguard Worker // Texture parameters
4506*8975f5c5SAndroid Build Coastguard Worker if (texture->getSwizzleRed() != GL_RED)
4507*8975f5c5SAndroid Build Coastguard Worker {
4508*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_SWIZZLE_R, texture->getSwizzleRed());
4509*8975f5c5SAndroid Build Coastguard Worker }
4510*8975f5c5SAndroid Build Coastguard Worker
4511*8975f5c5SAndroid Build Coastguard Worker if (texture->getSwizzleGreen() != GL_GREEN)
4512*8975f5c5SAndroid Build Coastguard Worker {
4513*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_SWIZZLE_G, texture->getSwizzleGreen());
4514*8975f5c5SAndroid Build Coastguard Worker }
4515*8975f5c5SAndroid Build Coastguard Worker
4516*8975f5c5SAndroid Build Coastguard Worker if (texture->getSwizzleBlue() != GL_BLUE)
4517*8975f5c5SAndroid Build Coastguard Worker {
4518*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_SWIZZLE_B, texture->getSwizzleBlue());
4519*8975f5c5SAndroid Build Coastguard Worker }
4520*8975f5c5SAndroid Build Coastguard Worker
4521*8975f5c5SAndroid Build Coastguard Worker if (texture->getSwizzleAlpha() != GL_ALPHA)
4522*8975f5c5SAndroid Build Coastguard Worker {
4523*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_SWIZZLE_A, texture->getSwizzleAlpha());
4524*8975f5c5SAndroid Build Coastguard Worker }
4525*8975f5c5SAndroid Build Coastguard Worker
4526*8975f5c5SAndroid Build Coastguard Worker if (texture->getBaseLevel() != 0)
4527*8975f5c5SAndroid Build Coastguard Worker {
4528*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_BASE_LEVEL, texture->getBaseLevel());
4529*8975f5c5SAndroid Build Coastguard Worker }
4530*8975f5c5SAndroid Build Coastguard Worker
4531*8975f5c5SAndroid Build Coastguard Worker if (texture->getMaxLevel() != 1000)
4532*8975f5c5SAndroid Build Coastguard Worker {
4533*8975f5c5SAndroid Build Coastguard Worker capTexParam(GL_TEXTURE_MAX_LEVEL, texture->getMaxLevel());
4534*8975f5c5SAndroid Build Coastguard Worker }
4535*8975f5c5SAndroid Build Coastguard Worker
4536*8975f5c5SAndroid Build Coastguard Worker // If the texture is immutable, initialize it with TexStorage
4537*8975f5c5SAndroid Build Coastguard Worker if (texture->getImmutableFormat())
4538*8975f5c5SAndroid Build Coastguard Worker {
4539*8975f5c5SAndroid Build Coastguard Worker // We can only call TexStorage *once* on an immutable texture, so it needs special
4540*8975f5c5SAndroid Build Coastguard Worker // handling. To solve this, immutable textures will have a BindTexture and TexStorage as
4541*8975f5c5SAndroid Build Coastguard Worker // part of their textureRegenCalls. The resulting regen sequence will be:
4542*8975f5c5SAndroid Build Coastguard Worker //
4543*8975f5c5SAndroid Build Coastguard Worker // const GLuint glDeleteTextures_texturesPacked_0[] = { gTextureMap[52] };
4544*8975f5c5SAndroid Build Coastguard Worker // glDeleteTextures(1, glDeleteTextures_texturesPacked_0);
4545*8975f5c5SAndroid Build Coastguard Worker // glGenTextures(1, reinterpret_cast<GLuint *>(gReadBuffer));
4546*8975f5c5SAndroid Build Coastguard Worker // UpdateTextureID(52, 0);
4547*8975f5c5SAndroid Build Coastguard Worker // glBindTexture(GL_TEXTURE_2D, gTextureMap[52]);
4548*8975f5c5SAndroid Build Coastguard Worker // glTexStorage2D(GL_TEXTURE_2D, 1, GL_R8, 256, 512);
4549*8975f5c5SAndroid Build Coastguard Worker
4550*8975f5c5SAndroid Build Coastguard Worker // Bind the texture first just for textureRegenCalls
4551*8975f5c5SAndroid Build Coastguard Worker Capture(&textureRegenCalls[id.value],
4552*8975f5c5SAndroid Build Coastguard Worker CaptureBindTexture(replayState, true, texture->getType(), id));
4553*8975f5c5SAndroid Build Coastguard Worker
4554*8975f5c5SAndroid Build Coastguard Worker // Then add TexStorage to texGenCalls instead of texSetupCalls
4555*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : texGenCalls)
4556*8975f5c5SAndroid Build Coastguard Worker {
4557*8975f5c5SAndroid Build Coastguard Worker CaptureTextureStorage(calls, &replayState, texture);
4558*8975f5c5SAndroid Build Coastguard Worker }
4559*8975f5c5SAndroid Build Coastguard Worker }
4560*8975f5c5SAndroid Build Coastguard Worker
4561*8975f5c5SAndroid Build Coastguard Worker // Iterate texture levels and layers.
4562*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndexIterator imageIter = gl::ImageIndexIterator::MakeGeneric(
4563*8975f5c5SAndroid Build Coastguard Worker texture->getType(), 0, texture->getMipmapMaxLevel() + 1, gl::ImageIndex::kEntireLevel,
4564*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndex::kEntireLevel);
4565*8975f5c5SAndroid Build Coastguard Worker while (imageIter.hasNext())
4566*8975f5c5SAndroid Build Coastguard Worker {
4567*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndex index = imageIter.next();
4568*8975f5c5SAndroid Build Coastguard Worker
4569*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &desc = texture->getTextureState().getImageDesc(index);
4570*8975f5c5SAndroid Build Coastguard Worker
4571*8975f5c5SAndroid Build Coastguard Worker if (desc.size.empty())
4572*8975f5c5SAndroid Build Coastguard Worker {
4573*8975f5c5SAndroid Build Coastguard Worker continue;
4574*8975f5c5SAndroid Build Coastguard Worker }
4575*8975f5c5SAndroid Build Coastguard Worker
4576*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &format = *desc.format.info;
4577*8975f5c5SAndroid Build Coastguard Worker
4578*8975f5c5SAndroid Build Coastguard Worker bool supportedType = (index.getType() == gl::TextureType::_2D ||
4579*8975f5c5SAndroid Build Coastguard Worker index.getType() == gl::TextureType::_3D ||
4580*8975f5c5SAndroid Build Coastguard Worker index.getType() == gl::TextureType::_2DArray ||
4581*8975f5c5SAndroid Build Coastguard Worker index.getType() == gl::TextureType::Buffer ||
4582*8975f5c5SAndroid Build Coastguard Worker index.getType() == gl::TextureType::CubeMap ||
4583*8975f5c5SAndroid Build Coastguard Worker index.getType() == gl::TextureType::CubeMapArray ||
4584*8975f5c5SAndroid Build Coastguard Worker index.getType() == gl::TextureType::External);
4585*8975f5c5SAndroid Build Coastguard Worker
4586*8975f5c5SAndroid Build Coastguard Worker // Check for supported textures
4587*8975f5c5SAndroid Build Coastguard Worker if (!supportedType)
4588*8975f5c5SAndroid Build Coastguard Worker {
4589*8975f5c5SAndroid Build Coastguard Worker ERR() << "Unsupported texture type: " << index.getType();
4590*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
4591*8975f5c5SAndroid Build Coastguard Worker }
4592*8975f5c5SAndroid Build Coastguard Worker
4593*8975f5c5SAndroid Build Coastguard Worker if (index.getType() == gl::TextureType::Buffer)
4594*8975f5c5SAndroid Build Coastguard Worker {
4595*8975f5c5SAndroid Build Coastguard Worker // The buffer contents are already backed up, but we need to emit the TexBuffer
4596*8975f5c5SAndroid Build Coastguard Worker // binding calls
4597*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : texSetupCalls)
4598*8975f5c5SAndroid Build Coastguard Worker {
4599*8975f5c5SAndroid Build Coastguard Worker CaptureTextureContents(calls, &replayState, texture, index, desc, 0, 0);
4600*8975f5c5SAndroid Build Coastguard Worker }
4601*8975f5c5SAndroid Build Coastguard Worker continue;
4602*8975f5c5SAndroid Build Coastguard Worker }
4603*8975f5c5SAndroid Build Coastguard Worker
4604*8975f5c5SAndroid Build Coastguard Worker if (index.getType() == gl::TextureType::External)
4605*8975f5c5SAndroid Build Coastguard Worker {
4606*8975f5c5SAndroid Build Coastguard Worker // Lookup the eglImage ID associated with this texture when the app issued
4607*8975f5c5SAndroid Build Coastguard Worker // glEGLImageTargetTexture2DOES()
4608*8975f5c5SAndroid Build Coastguard Worker auto eglImageIter = resourceTracker->getTextureIDToImageTable().find(id.value);
4609*8975f5c5SAndroid Build Coastguard Worker egl::ImageID eglImageID;
4610*8975f5c5SAndroid Build Coastguard Worker if (eglImageIter != resourceTracker->getTextureIDToImageTable().end())
4611*8975f5c5SAndroid Build Coastguard Worker {
4612*8975f5c5SAndroid Build Coastguard Worker eglImageID = eglImageIter->second;
4613*8975f5c5SAndroid Build Coastguard Worker }
4614*8975f5c5SAndroid Build Coastguard Worker else
4615*8975f5c5SAndroid Build Coastguard Worker {
4616*8975f5c5SAndroid Build Coastguard Worker // Original image was deleted and needs to be recreated first
4617*8975f5c5SAndroid Build Coastguard Worker eglImageID = {maxAccessedResourceIDs[ResourceIDType::Image] + 1};
4618*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : texSetupCalls)
4619*8975f5c5SAndroid Build Coastguard Worker {
4620*8975f5c5SAndroid Build Coastguard Worker egl::AttributeMap attribs = egl::AttributeMap::CreateFromIntArray(nullptr);
4621*8975f5c5SAndroid Build Coastguard Worker CallCapture eglCreateImageKHRCall = egl::CaptureCreateImageKHR(
4622*8975f5c5SAndroid Build Coastguard Worker nullptr, true, nullptr, context->id(), EGL_GL_TEXTURE_2D,
4623*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(0)), attribs,
4624*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLImage>(static_cast<uintptr_t>(eglImageID.value)));
4625*8975f5c5SAndroid Build Coastguard Worker CaptureCustomCreateEGLImage(context, "CreateEGLImageKHR", desc.size.width,
4626*8975f5c5SAndroid Build Coastguard Worker desc.size.height, eglCreateImageKHRCall,
4627*8975f5c5SAndroid Build Coastguard Worker *calls);
4628*8975f5c5SAndroid Build Coastguard Worker }
4629*8975f5c5SAndroid Build Coastguard Worker }
4630*8975f5c5SAndroid Build Coastguard Worker // Pass the eglImage to the texture that is bound to GL_TEXTURE_EXTERNAL_OES target
4631*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : texSetupCalls)
4632*8975f5c5SAndroid Build Coastguard Worker {
4633*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureEGLImageTargetTexture2DOES(
4634*8975f5c5SAndroid Build Coastguard Worker replayState, true, gl::TextureType::External, eglImageID));
4635*8975f5c5SAndroid Build Coastguard Worker }
4636*8975f5c5SAndroid Build Coastguard Worker }
4637*8975f5c5SAndroid Build Coastguard Worker else if (context->getExtensions().getImageANGLE)
4638*8975f5c5SAndroid Build Coastguard Worker {
4639*8975f5c5SAndroid Build Coastguard Worker // Use ANGLE_get_image to read back pixel data.
4640*8975f5c5SAndroid Build Coastguard Worker angle::MemoryBuffer data;
4641*8975f5c5SAndroid Build Coastguard Worker
4642*8975f5c5SAndroid Build Coastguard Worker const gl::Extents extents(desc.size.width, desc.size.height, desc.size.depth);
4643*8975f5c5SAndroid Build Coastguard Worker
4644*8975f5c5SAndroid Build Coastguard Worker gl::PixelPackState packState;
4645*8975f5c5SAndroid Build Coastguard Worker packState.alignment = 1;
4646*8975f5c5SAndroid Build Coastguard Worker
4647*8975f5c5SAndroid Build Coastguard Worker if (format.paletted)
4648*8975f5c5SAndroid Build Coastguard Worker {
4649*8975f5c5SAndroid Build Coastguard Worker // Read back the uncompressed texture, then re-compress it
4650*8975f5c5SAndroid Build Coastguard Worker // to store in the trace.
4651*8975f5c5SAndroid Build Coastguard Worker
4652*8975f5c5SAndroid Build Coastguard Worker angle::MemoryBuffer tmp;
4653*8975f5c5SAndroid Build Coastguard Worker
4654*8975f5c5SAndroid Build Coastguard Worker // The uncompressed format (R8G8B8A8) is 4 bytes per texel
4655*8975f5c5SAndroid Build Coastguard Worker bool result = tmp.resize(4 * extents.width * extents.height * extents.depth);
4656*8975f5c5SAndroid Build Coastguard Worker ASSERT(result);
4657*8975f5c5SAndroid Build Coastguard Worker
4658*8975f5c5SAndroid Build Coastguard Worker (void)texture->getTexImage(context, packState, nullptr, index.getTarget(),
4659*8975f5c5SAndroid Build Coastguard Worker index.getLevelIndex(), GL_RGBA, GL_UNSIGNED_BYTE,
4660*8975f5c5SAndroid Build Coastguard Worker tmp.data());
4661*8975f5c5SAndroid Build Coastguard Worker
4662*8975f5c5SAndroid Build Coastguard Worker CompressPalettedTexture(data, tmp, format, extents);
4663*8975f5c5SAndroid Build Coastguard Worker }
4664*8975f5c5SAndroid Build Coastguard Worker else if (format.compressed)
4665*8975f5c5SAndroid Build Coastguard Worker {
4666*8975f5c5SAndroid Build Coastguard Worker // Calculate the size needed to store the compressed level
4667*8975f5c5SAndroid Build Coastguard Worker GLuint sizeInBytes;
4668*8975f5c5SAndroid Build Coastguard Worker bool result = format.computeCompressedImageSize(extents, &sizeInBytes);
4669*8975f5c5SAndroid Build Coastguard Worker ASSERT(result);
4670*8975f5c5SAndroid Build Coastguard Worker
4671*8975f5c5SAndroid Build Coastguard Worker result = data.resize(sizeInBytes);
4672*8975f5c5SAndroid Build Coastguard Worker ASSERT(result);
4673*8975f5c5SAndroid Build Coastguard Worker
4674*8975f5c5SAndroid Build Coastguard Worker (void)texture->getCompressedTexImage(context, packState, nullptr,
4675*8975f5c5SAndroid Build Coastguard Worker index.getTarget(), index.getLevelIndex(),
4676*8975f5c5SAndroid Build Coastguard Worker data.data());
4677*8975f5c5SAndroid Build Coastguard Worker }
4678*8975f5c5SAndroid Build Coastguard Worker else
4679*8975f5c5SAndroid Build Coastguard Worker {
4680*8975f5c5SAndroid Build Coastguard Worker GLenum getFormat = format.format;
4681*8975f5c5SAndroid Build Coastguard Worker GLenum getType = format.type;
4682*8975f5c5SAndroid Build Coastguard Worker
4683*8975f5c5SAndroid Build Coastguard Worker const gl::PixelUnpackState &unpack = apiState.getUnpackState();
4684*8975f5c5SAndroid Build Coastguard Worker
4685*8975f5c5SAndroid Build Coastguard Worker GLuint endByte = 0;
4686*8975f5c5SAndroid Build Coastguard Worker bool unpackSize =
4687*8975f5c5SAndroid Build Coastguard Worker format.computePackUnpackEndByte(getType, extents, unpack, true, &endByte);
4688*8975f5c5SAndroid Build Coastguard Worker ASSERT(unpackSize);
4689*8975f5c5SAndroid Build Coastguard Worker
4690*8975f5c5SAndroid Build Coastguard Worker bool result = data.resize(endByte);
4691*8975f5c5SAndroid Build Coastguard Worker ASSERT(result);
4692*8975f5c5SAndroid Build Coastguard Worker
4693*8975f5c5SAndroid Build Coastguard Worker (void)texture->getTexImage(context, packState, nullptr, index.getTarget(),
4694*8975f5c5SAndroid Build Coastguard Worker index.getLevelIndex(), getFormat, getType,
4695*8975f5c5SAndroid Build Coastguard Worker data.data());
4696*8975f5c5SAndroid Build Coastguard Worker }
4697*8975f5c5SAndroid Build Coastguard Worker
4698*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : texSetupCalls)
4699*8975f5c5SAndroid Build Coastguard Worker {
4700*8975f5c5SAndroid Build Coastguard Worker CaptureTextureContents(calls, &replayState, texture, index, desc,
4701*8975f5c5SAndroid Build Coastguard Worker static_cast<GLuint>(data.size()), data.data());
4702*8975f5c5SAndroid Build Coastguard Worker }
4703*8975f5c5SAndroid Build Coastguard Worker }
4704*8975f5c5SAndroid Build Coastguard Worker else
4705*8975f5c5SAndroid Build Coastguard Worker {
4706*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : texSetupCalls)
4707*8975f5c5SAndroid Build Coastguard Worker {
4708*8975f5c5SAndroid Build Coastguard Worker CaptureTextureContents(calls, &replayState, texture, index, desc, 0, nullptr);
4709*8975f5c5SAndroid Build Coastguard Worker }
4710*8975f5c5SAndroid Build Coastguard Worker }
4711*8975f5c5SAndroid Build Coastguard Worker }
4712*8975f5c5SAndroid Build Coastguard Worker
4713*8975f5c5SAndroid Build Coastguard Worker size_t textureSetupEnd = setupCalls->size();
4714*8975f5c5SAndroid Build Coastguard Worker
4715*8975f5c5SAndroid Build Coastguard Worker // Mark the range of calls used to setup this texture
4716*8975f5c5SAndroid Build Coastguard Worker frameCaptureShared->markResourceSetupCallsInactive(
4717*8975f5c5SAndroid Build Coastguard Worker setupCalls, ResourceIDType::Texture, id.value,
4718*8975f5c5SAndroid Build Coastguard Worker gl::Range<size_t>(textureSetupStart, textureSetupEnd));
4719*8975f5c5SAndroid Build Coastguard Worker }
4720*8975f5c5SAndroid Build Coastguard Worker
4721*8975f5c5SAndroid Build Coastguard Worker // Capture Renderbuffers.
4722*8975f5c5SAndroid Build Coastguard Worker const gl::RenderbufferManager &renderbuffers = apiState.getRenderbufferManagerForCapture();
4723*8975f5c5SAndroid Build Coastguard Worker FramebufferCaptureFuncs framebufferFuncs(context->isGLES1());
4724*8975f5c5SAndroid Build Coastguard Worker
4725*8975f5c5SAndroid Build Coastguard Worker for (const auto &renderbufIter :
4726*8975f5c5SAndroid Build Coastguard Worker gl::UnsafeResourceMapIter(renderbuffers.getResourcesForCapture()))
4727*8975f5c5SAndroid Build Coastguard Worker {
4728*8975f5c5SAndroid Build Coastguard Worker gl::RenderbufferID id = {renderbufIter.first};
4729*8975f5c5SAndroid Build Coastguard Worker const gl::Renderbuffer *renderbuffer = renderbufIter.second;
4730*8975f5c5SAndroid Build Coastguard Worker
4731*8975f5c5SAndroid Build Coastguard Worker // Track this as a starting resource that may need to be restored.
4732*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedRenderbuffers =
4733*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::Renderbuffer);
4734*8975f5c5SAndroid Build Coastguard Worker ResourceSet &startingRenderbuffers = trackedRenderbuffers.getStartingResources();
4735*8975f5c5SAndroid Build Coastguard Worker startingRenderbuffers.insert(id.value);
4736*8975f5c5SAndroid Build Coastguard Worker
4737*8975f5c5SAndroid Build Coastguard Worker // For the initial renderbuffer creation calls, track in the generate list
4738*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &renderbufferRegenCalls = trackedRenderbuffers.getResourceRegenCalls();
4739*8975f5c5SAndroid Build Coastguard Worker CallVector rbGenCalls({setupCalls, &renderbufferRegenCalls[id.value]});
4740*8975f5c5SAndroid Build Coastguard Worker
4741*8975f5c5SAndroid Build Coastguard Worker // Generate renderbuffer id.
4742*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : rbGenCalls)
4743*8975f5c5SAndroid Build Coastguard Worker {
4744*8975f5c5SAndroid Build Coastguard Worker Capture(calls, framebufferFuncs.genRenderbuffers(replayState, true, 1, &id));
4745*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, resourceTracker, calls);
4746*8975f5c5SAndroid Build Coastguard Worker Capture(calls,
4747*8975f5c5SAndroid Build Coastguard Worker framebufferFuncs.bindRenderbuffer(replayState, true, GL_RENDERBUFFER, id));
4748*8975f5c5SAndroid Build Coastguard Worker }
4749*8975f5c5SAndroid Build Coastguard Worker
4750*8975f5c5SAndroid Build Coastguard Worker GLenum internalformat = renderbuffer->getFormat().info->internalFormat;
4751*8975f5c5SAndroid Build Coastguard Worker
4752*8975f5c5SAndroid Build Coastguard Worker if (renderbuffer->getSamples() > 0)
4753*8975f5c5SAndroid Build Coastguard Worker {
4754*8975f5c5SAndroid Build Coastguard Worker // Note: We could also use extensions if available.
4755*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : rbGenCalls)
4756*8975f5c5SAndroid Build Coastguard Worker {
4757*8975f5c5SAndroid Build Coastguard Worker Capture(calls,
4758*8975f5c5SAndroid Build Coastguard Worker CaptureRenderbufferStorageMultisample(
4759*8975f5c5SAndroid Build Coastguard Worker replayState, true, GL_RENDERBUFFER, renderbuffer->getSamples(),
4760*8975f5c5SAndroid Build Coastguard Worker internalformat, renderbuffer->getWidth(), renderbuffer->getHeight()));
4761*8975f5c5SAndroid Build Coastguard Worker }
4762*8975f5c5SAndroid Build Coastguard Worker }
4763*8975f5c5SAndroid Build Coastguard Worker else
4764*8975f5c5SAndroid Build Coastguard Worker {
4765*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : rbGenCalls)
4766*8975f5c5SAndroid Build Coastguard Worker {
4767*8975f5c5SAndroid Build Coastguard Worker Capture(calls, framebufferFuncs.renderbufferStorage(
4768*8975f5c5SAndroid Build Coastguard Worker replayState, true, GL_RENDERBUFFER, internalformat,
4769*8975f5c5SAndroid Build Coastguard Worker renderbuffer->getWidth(), renderbuffer->getHeight()));
4770*8975f5c5SAndroid Build Coastguard Worker }
4771*8975f5c5SAndroid Build Coastguard Worker }
4772*8975f5c5SAndroid Build Coastguard Worker
4773*8975f5c5SAndroid Build Coastguard Worker // TODO: Capture renderbuffer contents. http://anglebug.com/42262323
4774*8975f5c5SAndroid Build Coastguard Worker }
4775*8975f5c5SAndroid Build Coastguard Worker
4776*8975f5c5SAndroid Build Coastguard Worker // Capture Shaders and Programs.
4777*8975f5c5SAndroid Build Coastguard Worker const gl::ShaderProgramManager &shadersAndPrograms =
4778*8975f5c5SAndroid Build Coastguard Worker apiState.getShaderProgramManagerForCapture();
4779*8975f5c5SAndroid Build Coastguard Worker const gl::ResourceMap<gl::Shader, gl::ShaderProgramID> &shaders =
4780*8975f5c5SAndroid Build Coastguard Worker shadersAndPrograms.getShadersForCapture();
4781*8975f5c5SAndroid Build Coastguard Worker const gl::ResourceMap<gl::Program, gl::ShaderProgramID> &programs =
4782*8975f5c5SAndroid Build Coastguard Worker shadersAndPrograms.getProgramsForCaptureAndPerf();
4783*8975f5c5SAndroid Build Coastguard Worker
4784*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedShaderPrograms =
4785*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::ShaderProgram);
4786*8975f5c5SAndroid Build Coastguard Worker
4787*8975f5c5SAndroid Build Coastguard Worker // Capture Program binary state.
4788*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID tempShaderStartID = {resourceTracker->getMaxShaderPrograms()};
4789*8975f5c5SAndroid Build Coastguard Worker std::map<gl::ShaderProgramID, std::vector<gl::ShaderProgramID>> deferredAttachCalls;
4790*8975f5c5SAndroid Build Coastguard Worker for (const auto &programIter : gl::UnsafeResourceMapIter(programs))
4791*8975f5c5SAndroid Build Coastguard Worker {
4792*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID id = {programIter.first};
4793*8975f5c5SAndroid Build Coastguard Worker gl::Program *program = programIter.second;
4794*8975f5c5SAndroid Build Coastguard Worker
4795*8975f5c5SAndroid Build Coastguard Worker // Unlinked programs don't have an executable so track in case linking is deferred
4796*8975f5c5SAndroid Build Coastguard Worker // Programs are shared by contexts in the share group and only need to be captured once.
4797*8975f5c5SAndroid Build Coastguard Worker if (!program->isLinked())
4798*8975f5c5SAndroid Build Coastguard Worker {
4799*8975f5c5SAndroid Build Coastguard Worker frameCaptureShared->setDeferredLinkProgram(id);
4800*8975f5c5SAndroid Build Coastguard Worker
4801*8975f5c5SAndroid Build Coastguard Worker if (program->getAttachedShadersCount() > 0)
4802*8975f5c5SAndroid Build Coastguard Worker {
4803*8975f5c5SAndroid Build Coastguard Worker // AttachShader calls will be generated at shader-handling time
4804*8975f5c5SAndroid Build Coastguard Worker for (gl::ShaderType shaderType : gl::AllShaderTypes())
4805*8975f5c5SAndroid Build Coastguard Worker {
4806*8975f5c5SAndroid Build Coastguard Worker gl::Shader *shader = program->getAttachedShader(shaderType);
4807*8975f5c5SAndroid Build Coastguard Worker if (shader != nullptr)
4808*8975f5c5SAndroid Build Coastguard Worker {
4809*8975f5c5SAndroid Build Coastguard Worker deferredAttachCalls[shader->getHandle()].push_back(id);
4810*8975f5c5SAndroid Build Coastguard Worker }
4811*8975f5c5SAndroid Build Coastguard Worker }
4812*8975f5c5SAndroid Build Coastguard Worker }
4813*8975f5c5SAndroid Build Coastguard Worker else
4814*8975f5c5SAndroid Build Coastguard Worker {
4815*8975f5c5SAndroid Build Coastguard Worker WARN() << "Deferred attachment of shaders is not yet supported";
4816*8975f5c5SAndroid Build Coastguard Worker }
4817*8975f5c5SAndroid Build Coastguard Worker }
4818*8975f5c5SAndroid Build Coastguard Worker
4819*8975f5c5SAndroid Build Coastguard Worker size_t programSetupStart = setupCalls->size();
4820*8975f5c5SAndroid Build Coastguard Worker
4821*8975f5c5SAndroid Build Coastguard Worker // Create two lists for program regen calls
4822*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &shaderProgramRegenCalls = trackedShaderPrograms.getResourceRegenCalls();
4823*8975f5c5SAndroid Build Coastguard Worker CallVector programRegenCalls({setupCalls, &shaderProgramRegenCalls[id.value]});
4824*8975f5c5SAndroid Build Coastguard Worker
4825*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : programRegenCalls)
4826*8975f5c5SAndroid Build Coastguard Worker {
4827*8975f5c5SAndroid Build Coastguard Worker CallCapture createProgram = CaptureCreateProgram(replayState, true, id.value);
4828*8975f5c5SAndroid Build Coastguard Worker CaptureCustomShaderProgram("CreateProgram", createProgram, *calls);
4829*8975f5c5SAndroid Build Coastguard Worker }
4830*8975f5c5SAndroid Build Coastguard Worker
4831*8975f5c5SAndroid Build Coastguard Worker if (program->isLinked())
4832*8975f5c5SAndroid Build Coastguard Worker {
4833*8975f5c5SAndroid Build Coastguard Worker // Get last linked shader source.
4834*8975f5c5SAndroid Build Coastguard Worker const ProgramSources &linkedSources =
4835*8975f5c5SAndroid Build Coastguard Worker context->getShareGroup()->getFrameCaptureShared()->getProgramSources(id);
4836*8975f5c5SAndroid Build Coastguard Worker
4837*8975f5c5SAndroid Build Coastguard Worker // Create two lists for program restore calls
4838*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &shaderProgramRestoreCalls =
4839*8975f5c5SAndroid Build Coastguard Worker trackedShaderPrograms.getResourceRestoreCalls();
4840*8975f5c5SAndroid Build Coastguard Worker CallVector programRestoreCalls({setupCalls, &shaderProgramRestoreCalls[id.value]});
4841*8975f5c5SAndroid Build Coastguard Worker
4842*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : programRestoreCalls)
4843*8975f5c5SAndroid Build Coastguard Worker {
4844*8975f5c5SAndroid Build Coastguard Worker GenerateLinkedProgram(context, replayState, resourceTracker, calls, program, id,
4845*8975f5c5SAndroid Build Coastguard Worker tempShaderStartID, linkedSources);
4846*8975f5c5SAndroid Build Coastguard Worker }
4847*8975f5c5SAndroid Build Coastguard Worker
4848*8975f5c5SAndroid Build Coastguard Worker // Update the program in replayState
4849*8975f5c5SAndroid Build Coastguard Worker if (!replayState.getProgram() || replayState.getProgram()->id() != program->id())
4850*8975f5c5SAndroid Build Coastguard Worker {
4851*8975f5c5SAndroid Build Coastguard Worker // Note: We don't do this in GenerateLinkedProgram because it can't modify state
4852*8975f5c5SAndroid Build Coastguard Worker (void)replayState.setProgram(context, program);
4853*8975f5c5SAndroid Build Coastguard Worker }
4854*8975f5c5SAndroid Build Coastguard Worker }
4855*8975f5c5SAndroid Build Coastguard Worker
4856*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::ShaderProgram)
4857*8975f5c5SAndroid Build Coastguard Worker .getStartingResources()
4858*8975f5c5SAndroid Build Coastguard Worker .insert(id.value);
4859*8975f5c5SAndroid Build Coastguard Worker resourceTracker->setShaderProgramType(id, ShaderProgramType::ProgramType);
4860*8975f5c5SAndroid Build Coastguard Worker
4861*8975f5c5SAndroid Build Coastguard Worker // Mark linked programs/shaders as inactive, leaving deferred-linked programs/shaders marked
4862*8975f5c5SAndroid Build Coastguard Worker // as active
4863*8975f5c5SAndroid Build Coastguard Worker if (!frameCaptureShared->isDeferredLinkProgram(id))
4864*8975f5c5SAndroid Build Coastguard Worker {
4865*8975f5c5SAndroid Build Coastguard Worker size_t programSetupEnd = setupCalls->size();
4866*8975f5c5SAndroid Build Coastguard Worker
4867*8975f5c5SAndroid Build Coastguard Worker // Mark the range of calls used to setup this program
4868*8975f5c5SAndroid Build Coastguard Worker frameCaptureShared->markResourceSetupCallsInactive(
4869*8975f5c5SAndroid Build Coastguard Worker setupCalls, ResourceIDType::ShaderProgram, id.value,
4870*8975f5c5SAndroid Build Coastguard Worker gl::Range<size_t>(programSetupStart, programSetupEnd));
4871*8975f5c5SAndroid Build Coastguard Worker }
4872*8975f5c5SAndroid Build Coastguard Worker }
4873*8975f5c5SAndroid Build Coastguard Worker
4874*8975f5c5SAndroid Build Coastguard Worker // Handle shaders.
4875*8975f5c5SAndroid Build Coastguard Worker for (const auto &shaderIter : gl::UnsafeResourceMapIter(shaders))
4876*8975f5c5SAndroid Build Coastguard Worker {
4877*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID id = {shaderIter.first};
4878*8975f5c5SAndroid Build Coastguard Worker gl::Shader *shader = shaderIter.second;
4879*8975f5c5SAndroid Build Coastguard Worker
4880*8975f5c5SAndroid Build Coastguard Worker // Skip shaders scheduled for deletion.
4881*8975f5c5SAndroid Build Coastguard Worker // Shaders are shared by contexts in the share group and only need to be captured once.
4882*8975f5c5SAndroid Build Coastguard Worker if (shader->hasBeenDeleted())
4883*8975f5c5SAndroid Build Coastguard Worker {
4884*8975f5c5SAndroid Build Coastguard Worker continue;
4885*8975f5c5SAndroid Build Coastguard Worker }
4886*8975f5c5SAndroid Build Coastguard Worker
4887*8975f5c5SAndroid Build Coastguard Worker size_t shaderSetupStart = setupCalls->size();
4888*8975f5c5SAndroid Build Coastguard Worker
4889*8975f5c5SAndroid Build Coastguard Worker // Create two lists for shader regen calls
4890*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &shaderProgramRegenCalls = trackedShaderPrograms.getResourceRegenCalls();
4891*8975f5c5SAndroid Build Coastguard Worker CallVector shaderRegenCalls({setupCalls, &shaderProgramRegenCalls[id.value]});
4892*8975f5c5SAndroid Build Coastguard Worker
4893*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : shaderRegenCalls)
4894*8975f5c5SAndroid Build Coastguard Worker {
4895*8975f5c5SAndroid Build Coastguard Worker CallCapture createShader =
4896*8975f5c5SAndroid Build Coastguard Worker CaptureCreateShader(replayState, true, shader->getType(), id.value);
4897*8975f5c5SAndroid Build Coastguard Worker CaptureCustomShaderProgram("CreateShader", createShader, *calls);
4898*8975f5c5SAndroid Build Coastguard Worker
4899*8975f5c5SAndroid Build Coastguard Worker // If unlinked programs have been created which reference this shader emit corresponding
4900*8975f5c5SAndroid Build Coastguard Worker // attach calls
4901*8975f5c5SAndroid Build Coastguard Worker for (const auto deferredAttachedProgramID : deferredAttachCalls[id])
4902*8975f5c5SAndroid Build Coastguard Worker {
4903*8975f5c5SAndroid Build Coastguard Worker CallCapture attachShader =
4904*8975f5c5SAndroid Build Coastguard Worker CaptureAttachShader(replayState, true, deferredAttachedProgramID, id);
4905*8975f5c5SAndroid Build Coastguard Worker calls->emplace_back(std::move(attachShader));
4906*8975f5c5SAndroid Build Coastguard Worker }
4907*8975f5c5SAndroid Build Coastguard Worker }
4908*8975f5c5SAndroid Build Coastguard Worker
4909*8975f5c5SAndroid Build Coastguard Worker std::string shaderSource = shader->getSourceString();
4910*8975f5c5SAndroid Build Coastguard Worker const char *sourcePointer = shaderSource.empty() ? nullptr : shaderSource.c_str();
4911*8975f5c5SAndroid Build Coastguard Worker
4912*8975f5c5SAndroid Build Coastguard Worker // Create two lists for shader restore calls
4913*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &shaderProgramRestoreCalls = trackedShaderPrograms.getResourceRestoreCalls();
4914*8975f5c5SAndroid Build Coastguard Worker CallVector shaderRestoreCalls({setupCalls, &shaderProgramRestoreCalls[id.value]});
4915*8975f5c5SAndroid Build Coastguard Worker
4916*8975f5c5SAndroid Build Coastguard Worker // This does not handle some more tricky situations like attaching and then deleting a
4917*8975f5c5SAndroid Build Coastguard Worker // shader.
4918*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Handle trickier program uses. http://anglebug.com/42262323
4919*8975f5c5SAndroid Build Coastguard Worker if (shader->isCompiled(context))
4920*8975f5c5SAndroid Build Coastguard Worker {
4921*8975f5c5SAndroid Build Coastguard Worker const std::string &capturedSource =
4922*8975f5c5SAndroid Build Coastguard Worker context->getShareGroup()->getFrameCaptureShared()->getShaderSource(id);
4923*8975f5c5SAndroid Build Coastguard Worker if (capturedSource != shaderSource)
4924*8975f5c5SAndroid Build Coastguard Worker {
4925*8975f5c5SAndroid Build Coastguard Worker ASSERT(!capturedSource.empty());
4926*8975f5c5SAndroid Build Coastguard Worker sourcePointer = capturedSource.c_str();
4927*8975f5c5SAndroid Build Coastguard Worker }
4928*8975f5c5SAndroid Build Coastguard Worker
4929*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : shaderRestoreCalls)
4930*8975f5c5SAndroid Build Coastguard Worker {
4931*8975f5c5SAndroid Build Coastguard Worker Capture(calls,
4932*8975f5c5SAndroid Build Coastguard Worker CaptureShaderSource(replayState, true, id, 1, &sourcePointer, nullptr));
4933*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureCompileShader(replayState, true, id));
4934*8975f5c5SAndroid Build Coastguard Worker }
4935*8975f5c5SAndroid Build Coastguard Worker }
4936*8975f5c5SAndroid Build Coastguard Worker
4937*8975f5c5SAndroid Build Coastguard Worker if (sourcePointer &&
4938*8975f5c5SAndroid Build Coastguard Worker (!shader->isCompiled(context) || sourcePointer != shaderSource.c_str()))
4939*8975f5c5SAndroid Build Coastguard Worker {
4940*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : shaderRestoreCalls)
4941*8975f5c5SAndroid Build Coastguard Worker {
4942*8975f5c5SAndroid Build Coastguard Worker Capture(calls,
4943*8975f5c5SAndroid Build Coastguard Worker CaptureShaderSource(replayState, true, id, 1, &sourcePointer, nullptr));
4944*8975f5c5SAndroid Build Coastguard Worker }
4945*8975f5c5SAndroid Build Coastguard Worker }
4946*8975f5c5SAndroid Build Coastguard Worker
4947*8975f5c5SAndroid Build Coastguard Worker // Deferred-linked programs/shaders must be left marked as active
4948*8975f5c5SAndroid Build Coastguard Worker if (deferredAttachCalls[id].empty())
4949*8975f5c5SAndroid Build Coastguard Worker {
4950*8975f5c5SAndroid Build Coastguard Worker // Mark the range of calls used to setup this shader
4951*8975f5c5SAndroid Build Coastguard Worker frameCaptureShared->markResourceSetupCallsInactive(
4952*8975f5c5SAndroid Build Coastguard Worker setupCalls, ResourceIDType::ShaderProgram, id.value,
4953*8975f5c5SAndroid Build Coastguard Worker gl::Range<size_t>(shaderSetupStart, setupCalls->size()));
4954*8975f5c5SAndroid Build Coastguard Worker }
4955*8975f5c5SAndroid Build Coastguard Worker
4956*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::ShaderProgram)
4957*8975f5c5SAndroid Build Coastguard Worker .getStartingResources()
4958*8975f5c5SAndroid Build Coastguard Worker .insert(id.value);
4959*8975f5c5SAndroid Build Coastguard Worker resourceTracker->setShaderProgramType(id, ShaderProgramType::ShaderType);
4960*8975f5c5SAndroid Build Coastguard Worker }
4961*8975f5c5SAndroid Build Coastguard Worker
4962*8975f5c5SAndroid Build Coastguard Worker // Capture Sampler Objects
4963*8975f5c5SAndroid Build Coastguard Worker const gl::SamplerManager &samplers = apiState.getSamplerManagerForCapture();
4964*8975f5c5SAndroid Build Coastguard Worker for (const auto &samplerIter : gl::UnsafeResourceMapIter(samplers.getResourcesForCapture()))
4965*8975f5c5SAndroid Build Coastguard Worker {
4966*8975f5c5SAndroid Build Coastguard Worker gl::SamplerID samplerID = {samplerIter.first};
4967*8975f5c5SAndroid Build Coastguard Worker
4968*8975f5c5SAndroid Build Coastguard Worker // Don't gen the sampler if we've seen it before, since they are shared across the context
4969*8975f5c5SAndroid Build Coastguard Worker // share group.
4970*8975f5c5SAndroid Build Coastguard Worker cap(CaptureGenSamplers(replayState, true, 1, &samplerID));
4971*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, resourceTracker, setupCalls);
4972*8975f5c5SAndroid Build Coastguard Worker
4973*8975f5c5SAndroid Build Coastguard Worker gl::Sampler *sampler = samplerIter.second;
4974*8975f5c5SAndroid Build Coastguard Worker if (!sampler)
4975*8975f5c5SAndroid Build Coastguard Worker {
4976*8975f5c5SAndroid Build Coastguard Worker continue;
4977*8975f5c5SAndroid Build Coastguard Worker }
4978*8975f5c5SAndroid Build Coastguard Worker
4979*8975f5c5SAndroid Build Coastguard Worker gl::SamplerState defaultSamplerState;
4980*8975f5c5SAndroid Build Coastguard Worker if (sampler->getMinFilter() != defaultSamplerState.getMinFilter())
4981*8975f5c5SAndroid Build Coastguard Worker {
4982*8975f5c5SAndroid Build Coastguard Worker cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_MIN_FILTER,
4983*8975f5c5SAndroid Build Coastguard Worker sampler->getMinFilter()));
4984*8975f5c5SAndroid Build Coastguard Worker }
4985*8975f5c5SAndroid Build Coastguard Worker if (sampler->getMagFilter() != defaultSamplerState.getMagFilter())
4986*8975f5c5SAndroid Build Coastguard Worker {
4987*8975f5c5SAndroid Build Coastguard Worker cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_MAG_FILTER,
4988*8975f5c5SAndroid Build Coastguard Worker sampler->getMagFilter()));
4989*8975f5c5SAndroid Build Coastguard Worker }
4990*8975f5c5SAndroid Build Coastguard Worker if (sampler->getWrapS() != defaultSamplerState.getWrapS())
4991*8975f5c5SAndroid Build Coastguard Worker {
4992*8975f5c5SAndroid Build Coastguard Worker cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_WRAP_S,
4993*8975f5c5SAndroid Build Coastguard Worker sampler->getWrapS()));
4994*8975f5c5SAndroid Build Coastguard Worker }
4995*8975f5c5SAndroid Build Coastguard Worker if (sampler->getWrapR() != defaultSamplerState.getWrapR())
4996*8975f5c5SAndroid Build Coastguard Worker {
4997*8975f5c5SAndroid Build Coastguard Worker cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_WRAP_R,
4998*8975f5c5SAndroid Build Coastguard Worker sampler->getWrapR()));
4999*8975f5c5SAndroid Build Coastguard Worker }
5000*8975f5c5SAndroid Build Coastguard Worker if (sampler->getWrapT() != defaultSamplerState.getWrapT())
5001*8975f5c5SAndroid Build Coastguard Worker {
5002*8975f5c5SAndroid Build Coastguard Worker cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_WRAP_T,
5003*8975f5c5SAndroid Build Coastguard Worker sampler->getWrapT()));
5004*8975f5c5SAndroid Build Coastguard Worker }
5005*8975f5c5SAndroid Build Coastguard Worker if (sampler->getMinLod() != defaultSamplerState.getMinLod())
5006*8975f5c5SAndroid Build Coastguard Worker {
5007*8975f5c5SAndroid Build Coastguard Worker cap(CaptureSamplerParameterf(replayState, true, samplerID, GL_TEXTURE_MIN_LOD,
5008*8975f5c5SAndroid Build Coastguard Worker sampler->getMinLod()));
5009*8975f5c5SAndroid Build Coastguard Worker }
5010*8975f5c5SAndroid Build Coastguard Worker if (sampler->getMaxLod() != defaultSamplerState.getMaxLod())
5011*8975f5c5SAndroid Build Coastguard Worker {
5012*8975f5c5SAndroid Build Coastguard Worker cap(CaptureSamplerParameterf(replayState, true, samplerID, GL_TEXTURE_MAX_LOD,
5013*8975f5c5SAndroid Build Coastguard Worker sampler->getMaxLod()));
5014*8975f5c5SAndroid Build Coastguard Worker }
5015*8975f5c5SAndroid Build Coastguard Worker if (sampler->getCompareMode() != defaultSamplerState.getCompareMode())
5016*8975f5c5SAndroid Build Coastguard Worker {
5017*8975f5c5SAndroid Build Coastguard Worker cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_COMPARE_MODE,
5018*8975f5c5SAndroid Build Coastguard Worker sampler->getCompareMode()));
5019*8975f5c5SAndroid Build Coastguard Worker }
5020*8975f5c5SAndroid Build Coastguard Worker if (sampler->getCompareFunc() != defaultSamplerState.getCompareFunc())
5021*8975f5c5SAndroid Build Coastguard Worker {
5022*8975f5c5SAndroid Build Coastguard Worker cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_COMPARE_FUNC,
5023*8975f5c5SAndroid Build Coastguard Worker sampler->getCompareFunc()));
5024*8975f5c5SAndroid Build Coastguard Worker }
5025*8975f5c5SAndroid Build Coastguard Worker }
5026*8975f5c5SAndroid Build Coastguard Worker
5027*8975f5c5SAndroid Build Coastguard Worker // Capture Sync Objects
5028*8975f5c5SAndroid Build Coastguard Worker const gl::SyncManager &syncs = apiState.getSyncManagerForCapture();
5029*8975f5c5SAndroid Build Coastguard Worker for (const auto &syncIter : gl::UnsafeResourceMapIter(syncs.getResourcesForCapture()))
5030*8975f5c5SAndroid Build Coastguard Worker {
5031*8975f5c5SAndroid Build Coastguard Worker gl::SyncID syncID = {syncIter.first};
5032*8975f5c5SAndroid Build Coastguard Worker const gl::Sync *sync = syncIter.second;
5033*8975f5c5SAndroid Build Coastguard Worker GLsync syncObject = gl::unsafe_int_to_pointer_cast<GLsync>(syncID.value);
5034*8975f5c5SAndroid Build Coastguard Worker
5035*8975f5c5SAndroid Build Coastguard Worker if (!sync)
5036*8975f5c5SAndroid Build Coastguard Worker {
5037*8975f5c5SAndroid Build Coastguard Worker continue;
5038*8975f5c5SAndroid Build Coastguard Worker }
5039*8975f5c5SAndroid Build Coastguard Worker CallCapture fenceSync =
5040*8975f5c5SAndroid Build Coastguard Worker CaptureFenceSync(replayState, true, sync->getCondition(), sync->getFlags(), syncObject);
5041*8975f5c5SAndroid Build Coastguard Worker CaptureCustomFenceSync(fenceSync, *setupCalls);
5042*8975f5c5SAndroid Build Coastguard Worker CaptureFenceSyncResetCalls(context, replayState, resourceTracker, syncID, syncObject, sync);
5043*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getStartingFenceSyncs().insert(syncID);
5044*8975f5c5SAndroid Build Coastguard Worker }
5045*8975f5c5SAndroid Build Coastguard Worker
5046*8975f5c5SAndroid Build Coastguard Worker // Capture EGL Sync Objects
5047*8975f5c5SAndroid Build Coastguard Worker const egl::SyncMap &eglSyncMap = context->getDisplay()->getSyncsForCapture();
5048*8975f5c5SAndroid Build Coastguard Worker for (const auto &eglSyncIter : eglSyncMap)
5049*8975f5c5SAndroid Build Coastguard Worker {
5050*8975f5c5SAndroid Build Coastguard Worker egl::SyncID eglSyncID = {eglSyncIter.first};
5051*8975f5c5SAndroid Build Coastguard Worker const egl::Sync *eglSync = eglSyncIter.second.get();
5052*8975f5c5SAndroid Build Coastguard Worker EGLSync eglSyncObject = gl::unsafe_int_to_pointer_cast<EGLSync>(eglSyncID.value);
5053*8975f5c5SAndroid Build Coastguard Worker
5054*8975f5c5SAndroid Build Coastguard Worker if (!eglSync)
5055*8975f5c5SAndroid Build Coastguard Worker {
5056*8975f5c5SAndroid Build Coastguard Worker continue;
5057*8975f5c5SAndroid Build Coastguard Worker }
5058*8975f5c5SAndroid Build Coastguard Worker CallCapture createEGLSync =
5059*8975f5c5SAndroid Build Coastguard Worker CaptureCreateSync(nullptr, true, context->getDisplay(), eglSync->getType(),
5060*8975f5c5SAndroid Build Coastguard Worker eglSync->getAttributeMap(), eglSyncObject);
5061*8975f5c5SAndroid Build Coastguard Worker CaptureCustomCreateEGLSync("CreateEGLSyncKHR", createEGLSync, *setupCalls);
5062*8975f5c5SAndroid Build Coastguard Worker CaptureEGLSyncResetCalls(context, replayState, resourceTracker, eglSyncID, eglSyncObject,
5063*8975f5c5SAndroid Build Coastguard Worker eglSync);
5064*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::egl_Sync)
5065*8975f5c5SAndroid Build Coastguard Worker .getStartingResources()
5066*8975f5c5SAndroid Build Coastguard Worker .insert(eglSyncID.value);
5067*8975f5c5SAndroid Build Coastguard Worker }
5068*8975f5c5SAndroid Build Coastguard Worker
5069*8975f5c5SAndroid Build Coastguard Worker GLint contextUnpackAlignment = context->getState().getUnpackState().alignment;
5070*8975f5c5SAndroid Build Coastguard Worker if (currentUnpackState.alignment != contextUnpackAlignment)
5071*8975f5c5SAndroid Build Coastguard Worker {
5072*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_UNPACK_ALIGNMENT, contextUnpackAlignment));
5073*8975f5c5SAndroid Build Coastguard Worker replayState.getMutablePrivateStateForCapture()->setUnpackAlignment(contextUnpackAlignment);
5074*8975f5c5SAndroid Build Coastguard Worker }
5075*8975f5c5SAndroid Build Coastguard Worker }
5076*8975f5c5SAndroid Build Coastguard Worker
CaptureMidExecutionSetup(const gl::Context * context,std::vector<CallCapture> * setupCalls,StateResetHelper & resetHelper,std::vector<CallCapture> * shareGroupSetupCalls,ResourceIDToSetupCallsMap * resourceIDToSetupCalls,ResourceTracker * resourceTracker,gl::State & replayState,bool validationEnabled)5077*8975f5c5SAndroid Build Coastguard Worker void CaptureMidExecutionSetup(const gl::Context *context,
5078*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *setupCalls,
5079*8975f5c5SAndroid Build Coastguard Worker StateResetHelper &resetHelper,
5080*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *shareGroupSetupCalls,
5081*8975f5c5SAndroid Build Coastguard Worker ResourceIDToSetupCallsMap *resourceIDToSetupCalls,
5082*8975f5c5SAndroid Build Coastguard Worker ResourceTracker *resourceTracker,
5083*8975f5c5SAndroid Build Coastguard Worker gl::State &replayState,
5084*8975f5c5SAndroid Build Coastguard Worker bool validationEnabled)
5085*8975f5c5SAndroid Build Coastguard Worker {
5086*8975f5c5SAndroid Build Coastguard Worker const gl::State &apiState = context->getState();
5087*8975f5c5SAndroid Build Coastguard Worker
5088*8975f5c5SAndroid Build Coastguard Worker // Small helper function to make the code more readable.
5089*8975f5c5SAndroid Build Coastguard Worker auto cap = [setupCalls](CallCapture &&call) { setupCalls->emplace_back(std::move(call)); };
5090*8975f5c5SAndroid Build Coastguard Worker
5091*8975f5c5SAndroid Build Coastguard Worker cap(egl::CaptureMakeCurrent(nullptr, true, nullptr, {0}, {0}, context->id(), EGL_TRUE));
5092*8975f5c5SAndroid Build Coastguard Worker
5093*8975f5c5SAndroid Build Coastguard Worker // Vertex input states. Must happen after buffer data initialization. Do not capture on GLES1.
5094*8975f5c5SAndroid Build Coastguard Worker if (!context->isGLES1())
5095*8975f5c5SAndroid Build Coastguard Worker {
5096*8975f5c5SAndroid Build Coastguard Worker CaptureDefaultVertexAttribs(replayState, apiState, setupCalls);
5097*8975f5c5SAndroid Build Coastguard Worker }
5098*8975f5c5SAndroid Build Coastguard Worker
5099*8975f5c5SAndroid Build Coastguard Worker // Capture vertex array objects
5100*8975f5c5SAndroid Build Coastguard Worker VertexArrayCaptureFuncs vertexArrayFuncs(context->isGLES1());
5101*8975f5c5SAndroid Build Coastguard Worker
5102*8975f5c5SAndroid Build Coastguard Worker const gl::VertexArrayMap &vertexArrayMap = context->getVertexArraysForCapture();
5103*8975f5c5SAndroid Build Coastguard Worker gl::VertexArrayID boundVertexArrayID = {0};
5104*8975f5c5SAndroid Build Coastguard Worker for (const auto &vertexArrayIter : gl::UnsafeResourceMapIter(vertexArrayMap))
5105*8975f5c5SAndroid Build Coastguard Worker {
5106*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedVertexArrays =
5107*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::VertexArray);
5108*8975f5c5SAndroid Build Coastguard Worker
5109*8975f5c5SAndroid Build Coastguard Worker gl::VertexArrayID vertexArrayID = {vertexArrayIter.first};
5110*8975f5c5SAndroid Build Coastguard Worker
5111*8975f5c5SAndroid Build Coastguard Worker // Track this as a starting resource that may need to be restored
5112*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::VertexArray)
5113*8975f5c5SAndroid Build Coastguard Worker .getStartingResources()
5114*8975f5c5SAndroid Build Coastguard Worker .insert(vertexArrayID.value);
5115*8975f5c5SAndroid Build Coastguard Worker
5116*8975f5c5SAndroid Build Coastguard Worker // Create two lists of calls for initial setup
5117*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &vertexArrayRegenCalls = trackedVertexArrays.getResourceRegenCalls();
5118*8975f5c5SAndroid Build Coastguard Worker CallVector vertexArrayGenCalls({setupCalls, &vertexArrayRegenCalls[vertexArrayID.value]});
5119*8975f5c5SAndroid Build Coastguard Worker
5120*8975f5c5SAndroid Build Coastguard Worker if (vertexArrayID.value != 0)
5121*8975f5c5SAndroid Build Coastguard Worker {
5122*8975f5c5SAndroid Build Coastguard Worker // Gen the vertex array
5123*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : vertexArrayGenCalls)
5124*8975f5c5SAndroid Build Coastguard Worker {
5125*8975f5c5SAndroid Build Coastguard Worker Capture(calls,
5126*8975f5c5SAndroid Build Coastguard Worker vertexArrayFuncs.genVertexArrays(replayState, true, 1, &vertexArrayID));
5127*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, resourceTracker, calls);
5128*8975f5c5SAndroid Build Coastguard Worker }
5129*8975f5c5SAndroid Build Coastguard Worker }
5130*8975f5c5SAndroid Build Coastguard Worker
5131*8975f5c5SAndroid Build Coastguard Worker // Create two lists of calls for populating the vertex array
5132*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &vertexArrayRestoreCalls = trackedVertexArrays.getResourceRestoreCalls();
5133*8975f5c5SAndroid Build Coastguard Worker CallVector vertexArraySetupCalls(
5134*8975f5c5SAndroid Build Coastguard Worker {setupCalls, &vertexArrayRestoreCalls[vertexArrayID.value]});
5135*8975f5c5SAndroid Build Coastguard Worker
5136*8975f5c5SAndroid Build Coastguard Worker if (vertexArrayIter.second)
5137*8975f5c5SAndroid Build Coastguard Worker {
5138*8975f5c5SAndroid Build Coastguard Worker const gl::VertexArray *vertexArray = vertexArrayIter.second;
5139*8975f5c5SAndroid Build Coastguard Worker
5140*8975f5c5SAndroid Build Coastguard Worker // Populate the vertex array
5141*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : vertexArraySetupCalls)
5142*8975f5c5SAndroid Build Coastguard Worker {
5143*8975f5c5SAndroid Build Coastguard Worker // Bind the vertexArray (if needed) and populate it
5144*8975f5c5SAndroid Build Coastguard Worker if (vertexArrayID != boundVertexArrayID)
5145*8975f5c5SAndroid Build Coastguard Worker {
5146*8975f5c5SAndroid Build Coastguard Worker Capture(calls,
5147*8975f5c5SAndroid Build Coastguard Worker vertexArrayFuncs.bindVertexArray(replayState, true, vertexArrayID));
5148*8975f5c5SAndroid Build Coastguard Worker }
5149*8975f5c5SAndroid Build Coastguard Worker CaptureVertexArrayState(calls, context, vertexArray, &replayState);
5150*8975f5c5SAndroid Build Coastguard Worker }
5151*8975f5c5SAndroid Build Coastguard Worker boundVertexArrayID = vertexArrayID;
5152*8975f5c5SAndroid Build Coastguard Worker }
5153*8975f5c5SAndroid Build Coastguard Worker }
5154*8975f5c5SAndroid Build Coastguard Worker
5155*8975f5c5SAndroid Build Coastguard Worker // Bind the current vertex array
5156*8975f5c5SAndroid Build Coastguard Worker const gl::VertexArray *currentVertexArray = apiState.getVertexArray();
5157*8975f5c5SAndroid Build Coastguard Worker if (currentVertexArray->id() != boundVertexArrayID)
5158*8975f5c5SAndroid Build Coastguard Worker {
5159*8975f5c5SAndroid Build Coastguard Worker cap(vertexArrayFuncs.bindVertexArray(replayState, true, currentVertexArray->id()));
5160*8975f5c5SAndroid Build Coastguard Worker }
5161*8975f5c5SAndroid Build Coastguard Worker
5162*8975f5c5SAndroid Build Coastguard Worker // Track the calls necessary to bind the vertex array back to initial state
5163*8975f5c5SAndroid Build Coastguard Worker CallResetMap &resetCalls = resetHelper.getResetCalls();
5164*8975f5c5SAndroid Build Coastguard Worker Capture(&resetCalls[angle::EntryPoint::GLBindVertexArray],
5165*8975f5c5SAndroid Build Coastguard Worker vertexArrayFuncs.bindVertexArray(replayState, true, currentVertexArray->id()));
5166*8975f5c5SAndroid Build Coastguard Worker
5167*8975f5c5SAndroid Build Coastguard Worker // Capture indexed buffer bindings.
5168*8975f5c5SAndroid Build Coastguard Worker const gl::BufferVector &uniformIndexedBuffers =
5169*8975f5c5SAndroid Build Coastguard Worker apiState.getOffsetBindingPointerUniformBuffers();
5170*8975f5c5SAndroid Build Coastguard Worker const gl::BufferVector &atomicCounterIndexedBuffers =
5171*8975f5c5SAndroid Build Coastguard Worker apiState.getOffsetBindingPointerAtomicCounterBuffers();
5172*8975f5c5SAndroid Build Coastguard Worker const gl::BufferVector &shaderStorageIndexedBuffers =
5173*8975f5c5SAndroid Build Coastguard Worker apiState.getOffsetBindingPointerShaderStorageBuffers();
5174*8975f5c5SAndroid Build Coastguard Worker CaptureIndexedBuffers(replayState, uniformIndexedBuffers, gl::BufferBinding::Uniform,
5175*8975f5c5SAndroid Build Coastguard Worker setupCalls);
5176*8975f5c5SAndroid Build Coastguard Worker CaptureIndexedBuffers(replayState, atomicCounterIndexedBuffers,
5177*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding::AtomicCounter, setupCalls);
5178*8975f5c5SAndroid Build Coastguard Worker CaptureIndexedBuffers(replayState, shaderStorageIndexedBuffers,
5179*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding::ShaderStorage, setupCalls);
5180*8975f5c5SAndroid Build Coastguard Worker
5181*8975f5c5SAndroid Build Coastguard Worker // Capture Buffer bindings.
5182*8975f5c5SAndroid Build Coastguard Worker const gl::BoundBufferMap &boundBuffers = apiState.getBoundBuffersForCapture();
5183*8975f5c5SAndroid Build Coastguard Worker for (gl::BufferBinding binding : angle::AllEnums<gl::BufferBinding>())
5184*8975f5c5SAndroid Build Coastguard Worker {
5185*8975f5c5SAndroid Build Coastguard Worker gl::BufferID bufferID = boundBuffers[binding].id();
5186*8975f5c5SAndroid Build Coastguard Worker
5187*8975f5c5SAndroid Build Coastguard Worker // Filter out redundant buffer binding commands. Note that the code in the previous section
5188*8975f5c5SAndroid Build Coastguard Worker // only binds to ARRAY_BUFFER. Therefore we only check the array binding against the binding
5189*8975f5c5SAndroid Build Coastguard Worker // we set earlier.
5190*8975f5c5SAndroid Build Coastguard Worker const gl::Buffer *arrayBuffer = replayState.getArrayBuffer();
5191*8975f5c5SAndroid Build Coastguard Worker bool isArray = binding == gl::BufferBinding::Array;
5192*8975f5c5SAndroid Build Coastguard Worker bool isArrayBufferChanging = isArray && arrayBuffer && arrayBuffer->id() != bufferID;
5193*8975f5c5SAndroid Build Coastguard Worker if (isArrayBufferChanging || (!isArray && bufferID.value != 0))
5194*8975f5c5SAndroid Build Coastguard Worker {
5195*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBindBuffer(replayState, true, binding, bufferID));
5196*8975f5c5SAndroid Build Coastguard Worker replayState.setBufferBinding(context, binding, boundBuffers[binding].get());
5197*8975f5c5SAndroid Build Coastguard Worker }
5198*8975f5c5SAndroid Build Coastguard Worker
5199*8975f5c5SAndroid Build Coastguard Worker // Restore all buffer bindings for Reset
5200*8975f5c5SAndroid Build Coastguard Worker if (bufferID.value != 0 || isArrayBufferChanging)
5201*8975f5c5SAndroid Build Coastguard Worker {
5202*8975f5c5SAndroid Build Coastguard Worker CaptureBufferBindingResetCalls(replayState, resourceTracker, binding, bufferID);
5203*8975f5c5SAndroid Build Coastguard Worker
5204*8975f5c5SAndroid Build Coastguard Worker // Track this as a starting binding
5205*8975f5c5SAndroid Build Coastguard Worker resetHelper.setStartingBufferBinding(binding, bufferID);
5206*8975f5c5SAndroid Build Coastguard Worker }
5207*8975f5c5SAndroid Build Coastguard Worker }
5208*8975f5c5SAndroid Build Coastguard Worker
5209*8975f5c5SAndroid Build Coastguard Worker // Set a unpack alignment of 1. Otherwise, computeRowPitch() will compute the wrong value,
5210*8975f5c5SAndroid Build Coastguard Worker // leading to a crash in memcpy() when capturing the texture contents.
5211*8975f5c5SAndroid Build Coastguard Worker gl::PixelUnpackState ¤tUnpackState = replayState.getUnpackState();
5212*8975f5c5SAndroid Build Coastguard Worker if (currentUnpackState.alignment != 1)
5213*8975f5c5SAndroid Build Coastguard Worker {
5214*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_UNPACK_ALIGNMENT, 1));
5215*8975f5c5SAndroid Build Coastguard Worker replayState.getMutablePrivateStateForCapture()->setUnpackAlignment(1);
5216*8975f5c5SAndroid Build Coastguard Worker }
5217*8975f5c5SAndroid Build Coastguard Worker
5218*8975f5c5SAndroid Build Coastguard Worker // Capture Texture setup and data.
5219*8975f5c5SAndroid Build Coastguard Worker const gl::TextureBindingMap &apiBoundTextures = apiState.getBoundTexturesForCapture();
5220*8975f5c5SAndroid Build Coastguard Worker resetHelper.setResetActiveTexture(apiState.getActiveSampler());
5221*8975f5c5SAndroid Build Coastguard Worker
5222*8975f5c5SAndroid Build Coastguard Worker // Set Texture bindings.
5223*8975f5c5SAndroid Build Coastguard Worker for (gl::TextureType textureType : angle::AllEnums<gl::TextureType>())
5224*8975f5c5SAndroid Build Coastguard Worker {
5225*8975f5c5SAndroid Build Coastguard Worker const gl::TextureBindingVector &apiBindings = apiBoundTextures[textureType];
5226*8975f5c5SAndroid Build Coastguard Worker const gl::TextureBindingVector &replayBindings =
5227*8975f5c5SAndroid Build Coastguard Worker replayState.getBoundTexturesForCapture()[textureType];
5228*8975f5c5SAndroid Build Coastguard Worker ASSERT(apiBindings.size() == replayBindings.size());
5229*8975f5c5SAndroid Build Coastguard Worker for (size_t bindingIndex = 0; bindingIndex < apiBindings.size(); ++bindingIndex)
5230*8975f5c5SAndroid Build Coastguard Worker {
5231*8975f5c5SAndroid Build Coastguard Worker gl::TextureID apiTextureID = apiBindings[bindingIndex].id();
5232*8975f5c5SAndroid Build Coastguard Worker gl::TextureID replayTextureID = replayBindings[bindingIndex].id();
5233*8975f5c5SAndroid Build Coastguard Worker
5234*8975f5c5SAndroid Build Coastguard Worker if (apiTextureID != replayTextureID)
5235*8975f5c5SAndroid Build Coastguard Worker {
5236*8975f5c5SAndroid Build Coastguard Worker if (replayState.getActiveSampler() != bindingIndex)
5237*8975f5c5SAndroid Build Coastguard Worker {
5238*8975f5c5SAndroid Build Coastguard Worker cap(CaptureActiveTexture(replayState, true,
5239*8975f5c5SAndroid Build Coastguard Worker GL_TEXTURE0 + static_cast<GLenum>(bindingIndex)));
5240*8975f5c5SAndroid Build Coastguard Worker replayState.getMutablePrivateStateForCapture()->setActiveSampler(
5241*8975f5c5SAndroid Build Coastguard Worker static_cast<unsigned int>(bindingIndex));
5242*8975f5c5SAndroid Build Coastguard Worker }
5243*8975f5c5SAndroid Build Coastguard Worker
5244*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBindTexture(replayState, true, textureType, apiTextureID));
5245*8975f5c5SAndroid Build Coastguard Worker replayState.setSamplerTexture(context, textureType,
5246*8975f5c5SAndroid Build Coastguard Worker apiBindings[bindingIndex].get());
5247*8975f5c5SAndroid Build Coastguard Worker }
5248*8975f5c5SAndroid Build Coastguard Worker
5249*8975f5c5SAndroid Build Coastguard Worker if (apiTextureID.value)
5250*8975f5c5SAndroid Build Coastguard Worker {
5251*8975f5c5SAndroid Build Coastguard Worker // Set this texture as active so it will be generated in Setup
5252*8975f5c5SAndroid Build Coastguard Worker MarkResourceIDActive(ResourceIDType::Texture, apiTextureID.value,
5253*8975f5c5SAndroid Build Coastguard Worker shareGroupSetupCalls, resourceIDToSetupCalls);
5254*8975f5c5SAndroid Build Coastguard Worker // Save currently bound textures for reset
5255*8975f5c5SAndroid Build Coastguard Worker resetHelper.getResetTextureBindings().emplace(
5256*8975f5c5SAndroid Build Coastguard Worker std::make_pair(bindingIndex, textureType), apiTextureID);
5257*8975f5c5SAndroid Build Coastguard Worker }
5258*8975f5c5SAndroid Build Coastguard Worker }
5259*8975f5c5SAndroid Build Coastguard Worker }
5260*8975f5c5SAndroid Build Coastguard Worker
5261*8975f5c5SAndroid Build Coastguard Worker // Capture Texture Environment
5262*8975f5c5SAndroid Build Coastguard Worker if (context->isGLES1())
5263*8975f5c5SAndroid Build Coastguard Worker {
5264*8975f5c5SAndroid Build Coastguard Worker const gl::Caps &caps = context->getCaps();
5265*8975f5c5SAndroid Build Coastguard Worker for (GLuint unit = 0; unit < caps.maxMultitextureUnits; ++unit)
5266*8975f5c5SAndroid Build Coastguard Worker {
5267*8975f5c5SAndroid Build Coastguard Worker CaptureTextureEnvironmentState(setupCalls, &replayState, &apiState, unit);
5268*8975f5c5SAndroid Build Coastguard Worker }
5269*8975f5c5SAndroid Build Coastguard Worker }
5270*8975f5c5SAndroid Build Coastguard Worker
5271*8975f5c5SAndroid Build Coastguard Worker // Set active Texture.
5272*8975f5c5SAndroid Build Coastguard Worker if (replayState.getActiveSampler() != apiState.getActiveSampler())
5273*8975f5c5SAndroid Build Coastguard Worker {
5274*8975f5c5SAndroid Build Coastguard Worker cap(CaptureActiveTexture(replayState, true,
5275*8975f5c5SAndroid Build Coastguard Worker GL_TEXTURE0 + static_cast<GLenum>(apiState.getActiveSampler())));
5276*8975f5c5SAndroid Build Coastguard Worker replayState.getMutablePrivateStateForCapture()->setActiveSampler(
5277*8975f5c5SAndroid Build Coastguard Worker apiState.getActiveSampler());
5278*8975f5c5SAndroid Build Coastguard Worker }
5279*8975f5c5SAndroid Build Coastguard Worker
5280*8975f5c5SAndroid Build Coastguard Worker // Set Renderbuffer binding.
5281*8975f5c5SAndroid Build Coastguard Worker FramebufferCaptureFuncs framebufferFuncs(context->isGLES1());
5282*8975f5c5SAndroid Build Coastguard Worker
5283*8975f5c5SAndroid Build Coastguard Worker const gl::RenderbufferManager &renderbuffers = apiState.getRenderbufferManagerForCapture();
5284*8975f5c5SAndroid Build Coastguard Worker gl::RenderbufferID currentRenderbuffer = {0};
5285*8975f5c5SAndroid Build Coastguard Worker for (const auto &renderbufIter :
5286*8975f5c5SAndroid Build Coastguard Worker gl::UnsafeResourceMapIter(renderbuffers.getResourcesForCapture()))
5287*8975f5c5SAndroid Build Coastguard Worker {
5288*8975f5c5SAndroid Build Coastguard Worker currentRenderbuffer = renderbufIter.second->id();
5289*8975f5c5SAndroid Build Coastguard Worker }
5290*8975f5c5SAndroid Build Coastguard Worker
5291*8975f5c5SAndroid Build Coastguard Worker if (currentRenderbuffer != apiState.getRenderbufferId())
5292*8975f5c5SAndroid Build Coastguard Worker {
5293*8975f5c5SAndroid Build Coastguard Worker cap(framebufferFuncs.bindRenderbuffer(replayState, true, GL_RENDERBUFFER,
5294*8975f5c5SAndroid Build Coastguard Worker apiState.getRenderbufferId()));
5295*8975f5c5SAndroid Build Coastguard Worker }
5296*8975f5c5SAndroid Build Coastguard Worker
5297*8975f5c5SAndroid Build Coastguard Worker // Capture Framebuffers.
5298*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferManager &framebuffers = apiState.getFramebufferManagerForCapture();
5299*8975f5c5SAndroid Build Coastguard Worker
5300*8975f5c5SAndroid Build Coastguard Worker gl::FramebufferID currentDrawFramebuffer = {0};
5301*8975f5c5SAndroid Build Coastguard Worker gl::FramebufferID currentReadFramebuffer = {0};
5302*8975f5c5SAndroid Build Coastguard Worker
5303*8975f5c5SAndroid Build Coastguard Worker for (const auto &framebufferIter :
5304*8975f5c5SAndroid Build Coastguard Worker gl::UnsafeResourceMapIter(framebuffers.getResourcesForCapture()))
5305*8975f5c5SAndroid Build Coastguard Worker {
5306*8975f5c5SAndroid Build Coastguard Worker gl::FramebufferID id = {framebufferIter.first};
5307*8975f5c5SAndroid Build Coastguard Worker const gl::Framebuffer *framebuffer = framebufferIter.second;
5308*8975f5c5SAndroid Build Coastguard Worker
5309*8975f5c5SAndroid Build Coastguard Worker // The default Framebuffer exists (by default).
5310*8975f5c5SAndroid Build Coastguard Worker if (framebuffer->isDefault())
5311*8975f5c5SAndroid Build Coastguard Worker {
5312*8975f5c5SAndroid Build Coastguard Worker continue;
5313*8975f5c5SAndroid Build Coastguard Worker }
5314*8975f5c5SAndroid Build Coastguard Worker
5315*8975f5c5SAndroid Build Coastguard Worker // Track this as a starting resource that may need to be restored
5316*8975f5c5SAndroid Build Coastguard Worker TrackedResource &trackedFramebuffers =
5317*8975f5c5SAndroid Build Coastguard Worker resourceTracker->getTrackedResource(context->id(), ResourceIDType::Framebuffer);
5318*8975f5c5SAndroid Build Coastguard Worker ResourceSet &startingFramebuffers = trackedFramebuffers.getStartingResources();
5319*8975f5c5SAndroid Build Coastguard Worker startingFramebuffers.insert(id.value);
5320*8975f5c5SAndroid Build Coastguard Worker
5321*8975f5c5SAndroid Build Coastguard Worker // Create two lists of calls for initial setup
5322*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &framebufferRegenCalls = trackedFramebuffers.getResourceRegenCalls();
5323*8975f5c5SAndroid Build Coastguard Worker CallVector framebufferGenCalls({setupCalls, &framebufferRegenCalls[id.value]});
5324*8975f5c5SAndroid Build Coastguard Worker
5325*8975f5c5SAndroid Build Coastguard Worker // Gen the framebuffer
5326*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : framebufferGenCalls)
5327*8975f5c5SAndroid Build Coastguard Worker {
5328*8975f5c5SAndroid Build Coastguard Worker Capture(calls, framebufferFuncs.genFramebuffers(replayState, true, 1, &id));
5329*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, resourceTracker, calls);
5330*8975f5c5SAndroid Build Coastguard Worker }
5331*8975f5c5SAndroid Build Coastguard Worker
5332*8975f5c5SAndroid Build Coastguard Worker // Create two lists of calls for remaining setup calls. One for setup, and one for restore
5333*8975f5c5SAndroid Build Coastguard Worker // during reset.
5334*8975f5c5SAndroid Build Coastguard Worker ResourceCalls &framebufferRestoreCalls = trackedFramebuffers.getResourceRestoreCalls();
5335*8975f5c5SAndroid Build Coastguard Worker CallVector framebufferSetupCalls({setupCalls, &framebufferRestoreCalls[id.value]});
5336*8975f5c5SAndroid Build Coastguard Worker
5337*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : framebufferSetupCalls)
5338*8975f5c5SAndroid Build Coastguard Worker {
5339*8975f5c5SAndroid Build Coastguard Worker Capture(calls, framebufferFuncs.bindFramebuffer(replayState, true, GL_FRAMEBUFFER, id));
5340*8975f5c5SAndroid Build Coastguard Worker // Set current context for this CallCapture
5341*8975f5c5SAndroid Build Coastguard Worker calls->back().contextID = context->id();
5342*8975f5c5SAndroid Build Coastguard Worker }
5343*8975f5c5SAndroid Build Coastguard Worker currentDrawFramebuffer = currentReadFramebuffer = id;
5344*8975f5c5SAndroid Build Coastguard Worker
5345*8975f5c5SAndroid Build Coastguard Worker // Color Attachments.
5346*8975f5c5SAndroid Build Coastguard Worker for (const gl::FramebufferAttachment &colorAttachment : framebuffer->getColorAttachments())
5347*8975f5c5SAndroid Build Coastguard Worker {
5348*8975f5c5SAndroid Build Coastguard Worker if (!colorAttachment.isAttached())
5349*8975f5c5SAndroid Build Coastguard Worker {
5350*8975f5c5SAndroid Build Coastguard Worker continue;
5351*8975f5c5SAndroid Build Coastguard Worker }
5352*8975f5c5SAndroid Build Coastguard Worker
5353*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : framebufferSetupCalls)
5354*8975f5c5SAndroid Build Coastguard Worker {
5355*8975f5c5SAndroid Build Coastguard Worker CaptureFramebufferAttachment(calls, replayState, framebufferFuncs, colorAttachment,
5356*8975f5c5SAndroid Build Coastguard Worker shareGroupSetupCalls, resourceIDToSetupCalls);
5357*8975f5c5SAndroid Build Coastguard Worker }
5358*8975f5c5SAndroid Build Coastguard Worker }
5359*8975f5c5SAndroid Build Coastguard Worker
5360*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferAttachment *depthAttachment = framebuffer->getDepthAttachment();
5361*8975f5c5SAndroid Build Coastguard Worker if (depthAttachment)
5362*8975f5c5SAndroid Build Coastguard Worker {
5363*8975f5c5SAndroid Build Coastguard Worker ASSERT(depthAttachment->getBinding() == GL_DEPTH_ATTACHMENT ||
5364*8975f5c5SAndroid Build Coastguard Worker depthAttachment->getBinding() == GL_DEPTH_STENCIL_ATTACHMENT);
5365*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : framebufferSetupCalls)
5366*8975f5c5SAndroid Build Coastguard Worker {
5367*8975f5c5SAndroid Build Coastguard Worker CaptureFramebufferAttachment(calls, replayState, framebufferFuncs, *depthAttachment,
5368*8975f5c5SAndroid Build Coastguard Worker shareGroupSetupCalls, resourceIDToSetupCalls);
5369*8975f5c5SAndroid Build Coastguard Worker }
5370*8975f5c5SAndroid Build Coastguard Worker }
5371*8975f5c5SAndroid Build Coastguard Worker
5372*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferAttachment *stencilAttachment = framebuffer->getStencilAttachment();
5373*8975f5c5SAndroid Build Coastguard Worker if (stencilAttachment)
5374*8975f5c5SAndroid Build Coastguard Worker {
5375*8975f5c5SAndroid Build Coastguard Worker ASSERT(stencilAttachment->getBinding() == GL_STENCIL_ATTACHMENT ||
5376*8975f5c5SAndroid Build Coastguard Worker depthAttachment->getBinding() == GL_DEPTH_STENCIL_ATTACHMENT);
5377*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : framebufferSetupCalls)
5378*8975f5c5SAndroid Build Coastguard Worker {
5379*8975f5c5SAndroid Build Coastguard Worker CaptureFramebufferAttachment(calls, replayState, framebufferFuncs,
5380*8975f5c5SAndroid Build Coastguard Worker *stencilAttachment, shareGroupSetupCalls,
5381*8975f5c5SAndroid Build Coastguard Worker resourceIDToSetupCalls);
5382*8975f5c5SAndroid Build Coastguard Worker }
5383*8975f5c5SAndroid Build Coastguard Worker }
5384*8975f5c5SAndroid Build Coastguard Worker
5385*8975f5c5SAndroid Build Coastguard Worker gl::FramebufferState defaultFramebufferState(
5386*8975f5c5SAndroid Build Coastguard Worker context->getCaps(), framebuffer->getState().id(),
5387*8975f5c5SAndroid Build Coastguard Worker framebuffer->getState().getFramebufferSerial());
5388*8975f5c5SAndroid Build Coastguard Worker const gl::DrawBuffersVector<GLenum> &defaultDrawBufferStates =
5389*8975f5c5SAndroid Build Coastguard Worker defaultFramebufferState.getDrawBufferStates();
5390*8975f5c5SAndroid Build Coastguard Worker const gl::DrawBuffersVector<GLenum> &drawBufferStates = framebuffer->getDrawBufferStates();
5391*8975f5c5SAndroid Build Coastguard Worker
5392*8975f5c5SAndroid Build Coastguard Worker if (drawBufferStates != defaultDrawBufferStates)
5393*8975f5c5SAndroid Build Coastguard Worker {
5394*8975f5c5SAndroid Build Coastguard Worker for (std::vector<CallCapture> *calls : framebufferSetupCalls)
5395*8975f5c5SAndroid Build Coastguard Worker {
5396*8975f5c5SAndroid Build Coastguard Worker Capture(calls, CaptureDrawBuffers(replayState, true,
5397*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizei>(drawBufferStates.size()),
5398*8975f5c5SAndroid Build Coastguard Worker drawBufferStates.data()));
5399*8975f5c5SAndroid Build Coastguard Worker }
5400*8975f5c5SAndroid Build Coastguard Worker }
5401*8975f5c5SAndroid Build Coastguard Worker }
5402*8975f5c5SAndroid Build Coastguard Worker
5403*8975f5c5SAndroid Build Coastguard Worker // Capture framebuffer bindings.
5404*8975f5c5SAndroid Build Coastguard Worker if (apiState.getDrawFramebuffer())
5405*8975f5c5SAndroid Build Coastguard Worker {
5406*8975f5c5SAndroid Build Coastguard Worker ASSERT(apiState.getReadFramebuffer());
5407*8975f5c5SAndroid Build Coastguard Worker gl::FramebufferID stateReadFramebuffer = apiState.getReadFramebuffer()->id();
5408*8975f5c5SAndroid Build Coastguard Worker gl::FramebufferID stateDrawFramebuffer = apiState.getDrawFramebuffer()->id();
5409*8975f5c5SAndroid Build Coastguard Worker if (stateDrawFramebuffer == stateReadFramebuffer)
5410*8975f5c5SAndroid Build Coastguard Worker {
5411*8975f5c5SAndroid Build Coastguard Worker if (currentDrawFramebuffer != stateDrawFramebuffer ||
5412*8975f5c5SAndroid Build Coastguard Worker currentReadFramebuffer != stateReadFramebuffer)
5413*8975f5c5SAndroid Build Coastguard Worker {
5414*8975f5c5SAndroid Build Coastguard Worker cap(framebufferFuncs.bindFramebuffer(replayState, true, GL_FRAMEBUFFER,
5415*8975f5c5SAndroid Build Coastguard Worker stateDrawFramebuffer));
5416*8975f5c5SAndroid Build Coastguard Worker currentDrawFramebuffer = currentReadFramebuffer = stateDrawFramebuffer;
5417*8975f5c5SAndroid Build Coastguard Worker }
5418*8975f5c5SAndroid Build Coastguard Worker }
5419*8975f5c5SAndroid Build Coastguard Worker else
5420*8975f5c5SAndroid Build Coastguard Worker {
5421*8975f5c5SAndroid Build Coastguard Worker if (currentDrawFramebuffer != stateDrawFramebuffer)
5422*8975f5c5SAndroid Build Coastguard Worker {
5423*8975f5c5SAndroid Build Coastguard Worker cap(framebufferFuncs.bindFramebuffer(replayState, true, GL_DRAW_FRAMEBUFFER,
5424*8975f5c5SAndroid Build Coastguard Worker currentDrawFramebuffer));
5425*8975f5c5SAndroid Build Coastguard Worker currentDrawFramebuffer = stateDrawFramebuffer;
5426*8975f5c5SAndroid Build Coastguard Worker }
5427*8975f5c5SAndroid Build Coastguard Worker
5428*8975f5c5SAndroid Build Coastguard Worker if (currentReadFramebuffer != stateReadFramebuffer)
5429*8975f5c5SAndroid Build Coastguard Worker {
5430*8975f5c5SAndroid Build Coastguard Worker cap(framebufferFuncs.bindFramebuffer(replayState, true, GL_READ_FRAMEBUFFER,
5431*8975f5c5SAndroid Build Coastguard Worker replayState.getReadFramebuffer()->id()));
5432*8975f5c5SAndroid Build Coastguard Worker currentReadFramebuffer = stateReadFramebuffer;
5433*8975f5c5SAndroid Build Coastguard Worker }
5434*8975f5c5SAndroid Build Coastguard Worker }
5435*8975f5c5SAndroid Build Coastguard Worker }
5436*8975f5c5SAndroid Build Coastguard Worker
5437*8975f5c5SAndroid Build Coastguard Worker // Capture Program Pipelines
5438*8975f5c5SAndroid Build Coastguard Worker const gl::ProgramPipelineManager *programPipelineManager =
5439*8975f5c5SAndroid Build Coastguard Worker apiState.getProgramPipelineManagerForCapture();
5440*8975f5c5SAndroid Build Coastguard Worker
5441*8975f5c5SAndroid Build Coastguard Worker for (const auto &ppoIterator :
5442*8975f5c5SAndroid Build Coastguard Worker gl::UnsafeResourceMapIter(programPipelineManager->getResourcesForCapture()))
5443*8975f5c5SAndroid Build Coastguard Worker {
5444*8975f5c5SAndroid Build Coastguard Worker gl::ProgramPipeline *pipeline = ppoIterator.second;
5445*8975f5c5SAndroid Build Coastguard Worker gl::ProgramPipelineID id = {ppoIterator.first};
5446*8975f5c5SAndroid Build Coastguard Worker cap(CaptureGenProgramPipelines(replayState, true, 1, &id));
5447*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, resourceTracker, setupCalls);
5448*8975f5c5SAndroid Build Coastguard Worker
5449*8975f5c5SAndroid Build Coastguard Worker // PPOs can contain graphics and compute programs, so loop through all shader types rather
5450*8975f5c5SAndroid Build Coastguard Worker // than just the linked ones since getLinkedShaderStages() will return either only graphics
5451*8975f5c5SAndroid Build Coastguard Worker // or compute stages.
5452*8975f5c5SAndroid Build Coastguard Worker for (gl::ShaderType shaderType : gl::AllShaderTypes())
5453*8975f5c5SAndroid Build Coastguard Worker {
5454*8975f5c5SAndroid Build Coastguard Worker const gl::Program *program = pipeline->getShaderProgram(shaderType);
5455*8975f5c5SAndroid Build Coastguard Worker if (!program)
5456*8975f5c5SAndroid Build Coastguard Worker {
5457*8975f5c5SAndroid Build Coastguard Worker continue;
5458*8975f5c5SAndroid Build Coastguard Worker }
5459*8975f5c5SAndroid Build Coastguard Worker ASSERT(program->isLinked());
5460*8975f5c5SAndroid Build Coastguard Worker GLbitfield gLbitfield = GetBitfieldFromShaderType(shaderType);
5461*8975f5c5SAndroid Build Coastguard Worker cap(CaptureUseProgramStages(replayState, true, pipeline->id(), gLbitfield,
5462*8975f5c5SAndroid Build Coastguard Worker program->id()));
5463*8975f5c5SAndroid Build Coastguard Worker
5464*8975f5c5SAndroid Build Coastguard Worker // Set this program as active so it will be generated in Setup
5465*8975f5c5SAndroid Build Coastguard Worker // Note: We aren't filtering ProgramPipelines, so this could be setting programs
5466*8975f5c5SAndroid Build Coastguard Worker // active that aren't actually used.
5467*8975f5c5SAndroid Build Coastguard Worker MarkResourceIDActive(ResourceIDType::ShaderProgram, program->id().value,
5468*8975f5c5SAndroid Build Coastguard Worker shareGroupSetupCalls, resourceIDToSetupCalls);
5469*8975f5c5SAndroid Build Coastguard Worker }
5470*8975f5c5SAndroid Build Coastguard Worker
5471*8975f5c5SAndroid Build Coastguard Worker gl::Program *program = pipeline->getActiveShaderProgram();
5472*8975f5c5SAndroid Build Coastguard Worker if (program)
5473*8975f5c5SAndroid Build Coastguard Worker {
5474*8975f5c5SAndroid Build Coastguard Worker cap(CaptureActiveShaderProgram(replayState, true, id, program->id()));
5475*8975f5c5SAndroid Build Coastguard Worker }
5476*8975f5c5SAndroid Build Coastguard Worker }
5477*8975f5c5SAndroid Build Coastguard Worker
5478*8975f5c5SAndroid Build Coastguard Worker // For now we assume the installed program executable is the same as the current program.
5479*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Handle installed program executable. http://anglebug.com/42262323
5480*8975f5c5SAndroid Build Coastguard Worker if (!context->isGLES1())
5481*8975f5c5SAndroid Build Coastguard Worker {
5482*8975f5c5SAndroid Build Coastguard Worker // If we have a program bound in the API, or if there is no program bound to the API at
5483*8975f5c5SAndroid Build Coastguard Worker // time of capture and we bound a program for uniform updates during MEC, we must add
5484*8975f5c5SAndroid Build Coastguard Worker // a set program call to replay the correct states.
5485*8975f5c5SAndroid Build Coastguard Worker GLuint currentProgram = 0;
5486*8975f5c5SAndroid Build Coastguard Worker if (apiState.getProgram())
5487*8975f5c5SAndroid Build Coastguard Worker {
5488*8975f5c5SAndroid Build Coastguard Worker cap(CaptureUseProgram(replayState, true, apiState.getProgram()->id()));
5489*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateCurrentProgram(setupCalls->back(), 0, setupCalls);
5490*8975f5c5SAndroid Build Coastguard Worker (void)replayState.setProgram(context, apiState.getProgram());
5491*8975f5c5SAndroid Build Coastguard Worker
5492*8975f5c5SAndroid Build Coastguard Worker // Set this program as active so it will be generated in Setup
5493*8975f5c5SAndroid Build Coastguard Worker MarkResourceIDActive(ResourceIDType::ShaderProgram, apiState.getProgram()->id().value,
5494*8975f5c5SAndroid Build Coastguard Worker shareGroupSetupCalls, resourceIDToSetupCalls);
5495*8975f5c5SAndroid Build Coastguard Worker
5496*8975f5c5SAndroid Build Coastguard Worker currentProgram = apiState.getProgram()->id().value;
5497*8975f5c5SAndroid Build Coastguard Worker }
5498*8975f5c5SAndroid Build Coastguard Worker else if (replayState.getProgram())
5499*8975f5c5SAndroid Build Coastguard Worker {
5500*8975f5c5SAndroid Build Coastguard Worker cap(CaptureUseProgram(replayState, true, {0}));
5501*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateCurrentProgram(setupCalls->back(), 0, setupCalls);
5502*8975f5c5SAndroid Build Coastguard Worker (void)replayState.setProgram(context, nullptr);
5503*8975f5c5SAndroid Build Coastguard Worker }
5504*8975f5c5SAndroid Build Coastguard Worker
5505*8975f5c5SAndroid Build Coastguard Worker // Track the calls necessary to reset active program back to initial state
5506*8975f5c5SAndroid Build Coastguard Worker Capture(&resetCalls[angle::EntryPoint::GLUseProgram],
5507*8975f5c5SAndroid Build Coastguard Worker CaptureUseProgram(replayState, true, {currentProgram}));
5508*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateCurrentProgram((&resetCalls[angle::EntryPoint::GLUseProgram])->back(), 0,
5509*8975f5c5SAndroid Build Coastguard Worker &resetCalls[angle::EntryPoint::GLUseProgram]);
5510*8975f5c5SAndroid Build Coastguard Worker
5511*8975f5c5SAndroid Build Coastguard Worker // Same for program pipelines as for programs, see comment above.
5512*8975f5c5SAndroid Build Coastguard Worker if (apiState.getProgramPipeline())
5513*8975f5c5SAndroid Build Coastguard Worker {
5514*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBindProgramPipeline(replayState, true, apiState.getProgramPipeline()->id()));
5515*8975f5c5SAndroid Build Coastguard Worker }
5516*8975f5c5SAndroid Build Coastguard Worker else if (replayState.getProgramPipeline())
5517*8975f5c5SAndroid Build Coastguard Worker {
5518*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBindProgramPipeline(replayState, true, {0}));
5519*8975f5c5SAndroid Build Coastguard Worker }
5520*8975f5c5SAndroid Build Coastguard Worker }
5521*8975f5c5SAndroid Build Coastguard Worker
5522*8975f5c5SAndroid Build Coastguard Worker // Capture Queries
5523*8975f5c5SAndroid Build Coastguard Worker const gl::QueryMap &queryMap = context->getQueriesForCapture();
5524*8975f5c5SAndroid Build Coastguard Worker
5525*8975f5c5SAndroid Build Coastguard Worker // Create existing queries. Note that queries may be genned and not yet started. In that
5526*8975f5c5SAndroid Build Coastguard Worker // case the queries will exist in the query map as nullptr entries.
5527*8975f5c5SAndroid Build Coastguard Worker // If any queries are active between frames, we want to defer creation and do them last,
5528*8975f5c5SAndroid Build Coastguard Worker // otherwise you'll get GL errors about starting a query while one is already active.
5529*8975f5c5SAndroid Build Coastguard Worker for (gl::QueryMap::Iterator queryIter = gl::UnsafeResourceMapIter(queryMap).beginWithNull(),
5530*8975f5c5SAndroid Build Coastguard Worker endIter = gl::UnsafeResourceMapIter(queryMap).endWithNull();
5531*8975f5c5SAndroid Build Coastguard Worker queryIter != endIter; ++queryIter)
5532*8975f5c5SAndroid Build Coastguard Worker {
5533*8975f5c5SAndroid Build Coastguard Worker ASSERT(queryIter->first);
5534*8975f5c5SAndroid Build Coastguard Worker gl::QueryID queryID = {queryIter->first};
5535*8975f5c5SAndroid Build Coastguard Worker
5536*8975f5c5SAndroid Build Coastguard Worker cap(CaptureGenQueries(replayState, true, 1, &queryID));
5537*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, resourceTracker, setupCalls);
5538*8975f5c5SAndroid Build Coastguard Worker
5539*8975f5c5SAndroid Build Coastguard Worker gl::Query *query = queryIter->second;
5540*8975f5c5SAndroid Build Coastguard Worker if (query)
5541*8975f5c5SAndroid Build Coastguard Worker {
5542*8975f5c5SAndroid Build Coastguard Worker gl::QueryType queryType = query->getType();
5543*8975f5c5SAndroid Build Coastguard Worker
5544*8975f5c5SAndroid Build Coastguard Worker // Defer active queries until we've created them all
5545*8975f5c5SAndroid Build Coastguard Worker if (IsQueryActive(apiState, queryID))
5546*8975f5c5SAndroid Build Coastguard Worker {
5547*8975f5c5SAndroid Build Coastguard Worker continue;
5548*8975f5c5SAndroid Build Coastguard Worker }
5549*8975f5c5SAndroid Build Coastguard Worker
5550*8975f5c5SAndroid Build Coastguard Worker // Begin the query to generate the object
5551*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBeginQuery(replayState, true, queryType, queryID));
5552*8975f5c5SAndroid Build Coastguard Worker
5553*8975f5c5SAndroid Build Coastguard Worker // End the query if it was not active
5554*8975f5c5SAndroid Build Coastguard Worker cap(CaptureEndQuery(replayState, true, queryType));
5555*8975f5c5SAndroid Build Coastguard Worker }
5556*8975f5c5SAndroid Build Coastguard Worker }
5557*8975f5c5SAndroid Build Coastguard Worker
5558*8975f5c5SAndroid Build Coastguard Worker const gl::ActiveQueryMap &activeQueries = apiState.getActiveQueriesForCapture();
5559*8975f5c5SAndroid Build Coastguard Worker for (const auto &activeQueryIter : activeQueries)
5560*8975f5c5SAndroid Build Coastguard Worker {
5561*8975f5c5SAndroid Build Coastguard Worker const gl::Query *activeQuery = activeQueryIter.get();
5562*8975f5c5SAndroid Build Coastguard Worker if (activeQuery)
5563*8975f5c5SAndroid Build Coastguard Worker {
5564*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBeginQuery(replayState, true, activeQuery->getType(), activeQuery->id()));
5565*8975f5c5SAndroid Build Coastguard Worker }
5566*8975f5c5SAndroid Build Coastguard Worker }
5567*8975f5c5SAndroid Build Coastguard Worker
5568*8975f5c5SAndroid Build Coastguard Worker // Transform Feedback
5569*8975f5c5SAndroid Build Coastguard Worker const gl::TransformFeedbackMap &xfbMap = context->getTransformFeedbacksForCapture();
5570*8975f5c5SAndroid Build Coastguard Worker for (const auto &xfbIter : gl::UnsafeResourceMapIter(xfbMap))
5571*8975f5c5SAndroid Build Coastguard Worker {
5572*8975f5c5SAndroid Build Coastguard Worker gl::TransformFeedbackID xfbID = {xfbIter.first};
5573*8975f5c5SAndroid Build Coastguard Worker
5574*8975f5c5SAndroid Build Coastguard Worker // Do not capture the default XFB object.
5575*8975f5c5SAndroid Build Coastguard Worker if (xfbID.value == 0)
5576*8975f5c5SAndroid Build Coastguard Worker {
5577*8975f5c5SAndroid Build Coastguard Worker continue;
5578*8975f5c5SAndroid Build Coastguard Worker }
5579*8975f5c5SAndroid Build Coastguard Worker
5580*8975f5c5SAndroid Build Coastguard Worker cap(CaptureGenTransformFeedbacks(replayState, true, 1, &xfbID));
5581*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, resourceTracker, setupCalls);
5582*8975f5c5SAndroid Build Coastguard Worker
5583*8975f5c5SAndroid Build Coastguard Worker gl::TransformFeedback *xfb = xfbIter.second;
5584*8975f5c5SAndroid Build Coastguard Worker if (!xfb)
5585*8975f5c5SAndroid Build Coastguard Worker {
5586*8975f5c5SAndroid Build Coastguard Worker // The object was never created
5587*8975f5c5SAndroid Build Coastguard Worker continue;
5588*8975f5c5SAndroid Build Coastguard Worker }
5589*8975f5c5SAndroid Build Coastguard Worker
5590*8975f5c5SAndroid Build Coastguard Worker // Bind XFB to create the object
5591*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBindTransformFeedback(replayState, true, GL_TRANSFORM_FEEDBACK, xfbID));
5592*8975f5c5SAndroid Build Coastguard Worker
5593*8975f5c5SAndroid Build Coastguard Worker // Bind the buffers associated with this XFB object
5594*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < xfb->getIndexedBufferCount(); ++i)
5595*8975f5c5SAndroid Build Coastguard Worker {
5596*8975f5c5SAndroid Build Coastguard Worker const gl::OffsetBindingPointer<gl::Buffer> &xfbBuffer = xfb->getIndexedBuffer(i);
5597*8975f5c5SAndroid Build Coastguard Worker
5598*8975f5c5SAndroid Build Coastguard Worker // Note: Buffers bound with BindBufferBase can be used with BindBuffer
5599*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBindBufferRange(replayState, true, gl::BufferBinding::TransformFeedback, 0,
5600*8975f5c5SAndroid Build Coastguard Worker xfbBuffer.id(), xfbBuffer.getOffset(), xfbBuffer.getSize()));
5601*8975f5c5SAndroid Build Coastguard Worker }
5602*8975f5c5SAndroid Build Coastguard Worker
5603*8975f5c5SAndroid Build Coastguard Worker if (xfb->isActive() || xfb->isPaused())
5604*8975f5c5SAndroid Build Coastguard Worker {
5605*8975f5c5SAndroid Build Coastguard Worker // We don't support active XFB in MEC yet
5606*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
5607*8975f5c5SAndroid Build Coastguard Worker }
5608*8975f5c5SAndroid Build Coastguard Worker }
5609*8975f5c5SAndroid Build Coastguard Worker
5610*8975f5c5SAndroid Build Coastguard Worker // Bind the current XFB buffer after populating XFB objects
5611*8975f5c5SAndroid Build Coastguard Worker gl::TransformFeedback *currentXFB = apiState.getCurrentTransformFeedback();
5612*8975f5c5SAndroid Build Coastguard Worker if (currentXFB)
5613*8975f5c5SAndroid Build Coastguard Worker {
5614*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBindTransformFeedback(replayState, true, GL_TRANSFORM_FEEDBACK,
5615*8975f5c5SAndroid Build Coastguard Worker currentXFB->id()));
5616*8975f5c5SAndroid Build Coastguard Worker }
5617*8975f5c5SAndroid Build Coastguard Worker
5618*8975f5c5SAndroid Build Coastguard Worker // Bind samplers
5619*8975f5c5SAndroid Build Coastguard Worker const gl::SamplerBindingVector &samplerBindings = apiState.getSamplers();
5620*8975f5c5SAndroid Build Coastguard Worker for (GLuint bindingIndex = 0; bindingIndex < static_cast<GLuint>(samplerBindings.size());
5621*8975f5c5SAndroid Build Coastguard Worker ++bindingIndex)
5622*8975f5c5SAndroid Build Coastguard Worker {
5623*8975f5c5SAndroid Build Coastguard Worker gl::SamplerID samplerID = samplerBindings[bindingIndex].id();
5624*8975f5c5SAndroid Build Coastguard Worker if (samplerID.value != 0)
5625*8975f5c5SAndroid Build Coastguard Worker {
5626*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBindSampler(replayState, true, bindingIndex, samplerID));
5627*8975f5c5SAndroid Build Coastguard Worker }
5628*8975f5c5SAndroid Build Coastguard Worker }
5629*8975f5c5SAndroid Build Coastguard Worker
5630*8975f5c5SAndroid Build Coastguard Worker // Capture Image Texture bindings
5631*8975f5c5SAndroid Build Coastguard Worker const std::vector<gl::ImageUnit> &imageUnits = apiState.getImageUnits();
5632*8975f5c5SAndroid Build Coastguard Worker for (GLuint bindingIndex = 0; bindingIndex < static_cast<GLuint>(imageUnits.size());
5633*8975f5c5SAndroid Build Coastguard Worker ++bindingIndex)
5634*8975f5c5SAndroid Build Coastguard Worker {
5635*8975f5c5SAndroid Build Coastguard Worker const gl::ImageUnit &imageUnit = imageUnits[bindingIndex];
5636*8975f5c5SAndroid Build Coastguard Worker
5637*8975f5c5SAndroid Build Coastguard Worker if (imageUnit.texture == 0)
5638*8975f5c5SAndroid Build Coastguard Worker {
5639*8975f5c5SAndroid Build Coastguard Worker continue;
5640*8975f5c5SAndroid Build Coastguard Worker }
5641*8975f5c5SAndroid Build Coastguard Worker
5642*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBindImageTexture(replayState, true, bindingIndex, imageUnit.texture.id(),
5643*8975f5c5SAndroid Build Coastguard Worker imageUnit.level, imageUnit.layered, imageUnit.layer,
5644*8975f5c5SAndroid Build Coastguard Worker imageUnit.access, imageUnit.format));
5645*8975f5c5SAndroid Build Coastguard Worker }
5646*8975f5c5SAndroid Build Coastguard Worker
5647*8975f5c5SAndroid Build Coastguard Worker // Capture GL Context states.
5648*8975f5c5SAndroid Build Coastguard Worker auto capCap = [cap, &replayState](GLenum capEnum, bool capValue) {
5649*8975f5c5SAndroid Build Coastguard Worker if (capValue)
5650*8975f5c5SAndroid Build Coastguard Worker {
5651*8975f5c5SAndroid Build Coastguard Worker cap(CaptureEnable(replayState, true, capEnum));
5652*8975f5c5SAndroid Build Coastguard Worker }
5653*8975f5c5SAndroid Build Coastguard Worker else
5654*8975f5c5SAndroid Build Coastguard Worker {
5655*8975f5c5SAndroid Build Coastguard Worker cap(CaptureDisable(replayState, true, capEnum));
5656*8975f5c5SAndroid Build Coastguard Worker }
5657*8975f5c5SAndroid Build Coastguard Worker };
5658*8975f5c5SAndroid Build Coastguard Worker
5659*8975f5c5SAndroid Build Coastguard Worker // Capture GLES1 context states.
5660*8975f5c5SAndroid Build Coastguard Worker if (context->isGLES1())
5661*8975f5c5SAndroid Build Coastguard Worker {
5662*8975f5c5SAndroid Build Coastguard Worker const bool currentTextureState = apiState.getEnableFeature(GL_TEXTURE_2D);
5663*8975f5c5SAndroid Build Coastguard Worker const bool defaultTextureState = replayState.getEnableFeature(GL_TEXTURE_2D);
5664*8975f5c5SAndroid Build Coastguard Worker if (currentTextureState != defaultTextureState)
5665*8975f5c5SAndroid Build Coastguard Worker {
5666*8975f5c5SAndroid Build Coastguard Worker capCap(GL_TEXTURE_2D, currentTextureState);
5667*8975f5c5SAndroid Build Coastguard Worker }
5668*8975f5c5SAndroid Build Coastguard Worker
5669*8975f5c5SAndroid Build Coastguard Worker cap(CaptureMatrixMode(replayState, true, gl::MatrixType::Projection));
5670*8975f5c5SAndroid Build Coastguard Worker for (angle::Mat4 projectionMatrix :
5671*8975f5c5SAndroid Build Coastguard Worker apiState.gles1().getMatrixStack(gl::MatrixType::Projection))
5672*8975f5c5SAndroid Build Coastguard Worker {
5673*8975f5c5SAndroid Build Coastguard Worker cap(CapturePushMatrix(replayState, true));
5674*8975f5c5SAndroid Build Coastguard Worker cap(CaptureLoadMatrixf(replayState, true, projectionMatrix.elements().data()));
5675*8975f5c5SAndroid Build Coastguard Worker }
5676*8975f5c5SAndroid Build Coastguard Worker
5677*8975f5c5SAndroid Build Coastguard Worker cap(CaptureMatrixMode(replayState, true, gl::MatrixType::Modelview));
5678*8975f5c5SAndroid Build Coastguard Worker for (angle::Mat4 modelViewMatrix :
5679*8975f5c5SAndroid Build Coastguard Worker apiState.gles1().getMatrixStack(gl::MatrixType::Modelview))
5680*8975f5c5SAndroid Build Coastguard Worker {
5681*8975f5c5SAndroid Build Coastguard Worker cap(CapturePushMatrix(replayState, true));
5682*8975f5c5SAndroid Build Coastguard Worker cap(CaptureLoadMatrixf(replayState, true, modelViewMatrix.elements().data()));
5683*8975f5c5SAndroid Build Coastguard Worker }
5684*8975f5c5SAndroid Build Coastguard Worker
5685*8975f5c5SAndroid Build Coastguard Worker gl::MatrixType currentMatrixMode = apiState.gles1().getMatrixMode();
5686*8975f5c5SAndroid Build Coastguard Worker if (currentMatrixMode != gl::MatrixType::Modelview)
5687*8975f5c5SAndroid Build Coastguard Worker {
5688*8975f5c5SAndroid Build Coastguard Worker cap(CaptureMatrixMode(replayState, true, currentMatrixMode));
5689*8975f5c5SAndroid Build Coastguard Worker }
5690*8975f5c5SAndroid Build Coastguard Worker
5691*8975f5c5SAndroid Build Coastguard Worker // Alpha Test state
5692*8975f5c5SAndroid Build Coastguard Worker const bool currentAlphaTestState = apiState.getEnableFeature(GL_ALPHA_TEST);
5693*8975f5c5SAndroid Build Coastguard Worker const bool defaultAlphaTestState = replayState.getEnableFeature(GL_ALPHA_TEST);
5694*8975f5c5SAndroid Build Coastguard Worker
5695*8975f5c5SAndroid Build Coastguard Worker if (currentAlphaTestState != defaultAlphaTestState)
5696*8975f5c5SAndroid Build Coastguard Worker {
5697*8975f5c5SAndroid Build Coastguard Worker capCap(GL_ALPHA_TEST, currentAlphaTestState);
5698*8975f5c5SAndroid Build Coastguard Worker }
5699*8975f5c5SAndroid Build Coastguard Worker
5700*8975f5c5SAndroid Build Coastguard Worker const gl::AlphaTestParameters currentAlphaTestParameters =
5701*8975f5c5SAndroid Build Coastguard Worker apiState.gles1().getAlphaTestParameters();
5702*8975f5c5SAndroid Build Coastguard Worker const gl::AlphaTestParameters defaultAlphaTestParameters =
5703*8975f5c5SAndroid Build Coastguard Worker replayState.gles1().getAlphaTestParameters();
5704*8975f5c5SAndroid Build Coastguard Worker
5705*8975f5c5SAndroid Build Coastguard Worker if (currentAlphaTestParameters != defaultAlphaTestParameters)
5706*8975f5c5SAndroid Build Coastguard Worker {
5707*8975f5c5SAndroid Build Coastguard Worker cap(CaptureAlphaFunc(replayState, true, currentAlphaTestParameters.func,
5708*8975f5c5SAndroid Build Coastguard Worker currentAlphaTestParameters.ref));
5709*8975f5c5SAndroid Build Coastguard Worker }
5710*8975f5c5SAndroid Build Coastguard Worker }
5711*8975f5c5SAndroid Build Coastguard Worker
5712*8975f5c5SAndroid Build Coastguard Worker // Rasterizer state. Missing ES 3.x features.
5713*8975f5c5SAndroid Build Coastguard Worker const gl::RasterizerState &defaultRasterState = replayState.getRasterizerState();
5714*8975f5c5SAndroid Build Coastguard Worker const gl::RasterizerState ¤tRasterState = apiState.getRasterizerState();
5715*8975f5c5SAndroid Build Coastguard Worker if (currentRasterState.cullFace != defaultRasterState.cullFace)
5716*8975f5c5SAndroid Build Coastguard Worker {
5717*8975f5c5SAndroid Build Coastguard Worker capCap(GL_CULL_FACE, currentRasterState.cullFace);
5718*8975f5c5SAndroid Build Coastguard Worker }
5719*8975f5c5SAndroid Build Coastguard Worker
5720*8975f5c5SAndroid Build Coastguard Worker if (currentRasterState.cullMode != defaultRasterState.cullMode)
5721*8975f5c5SAndroid Build Coastguard Worker {
5722*8975f5c5SAndroid Build Coastguard Worker cap(CaptureCullFace(replayState, true, currentRasterState.cullMode));
5723*8975f5c5SAndroid Build Coastguard Worker }
5724*8975f5c5SAndroid Build Coastguard Worker
5725*8975f5c5SAndroid Build Coastguard Worker if (currentRasterState.frontFace != defaultRasterState.frontFace)
5726*8975f5c5SAndroid Build Coastguard Worker {
5727*8975f5c5SAndroid Build Coastguard Worker cap(CaptureFrontFace(replayState, true, currentRasterState.frontFace));
5728*8975f5c5SAndroid Build Coastguard Worker }
5729*8975f5c5SAndroid Build Coastguard Worker
5730*8975f5c5SAndroid Build Coastguard Worker if (currentRasterState.polygonMode != defaultRasterState.polygonMode)
5731*8975f5c5SAndroid Build Coastguard Worker {
5732*8975f5c5SAndroid Build Coastguard Worker if (context->getExtensions().polygonModeNV)
5733*8975f5c5SAndroid Build Coastguard Worker {
5734*8975f5c5SAndroid Build Coastguard Worker cap(CapturePolygonModeNV(replayState, true, GL_FRONT_AND_BACK,
5735*8975f5c5SAndroid Build Coastguard Worker currentRasterState.polygonMode));
5736*8975f5c5SAndroid Build Coastguard Worker }
5737*8975f5c5SAndroid Build Coastguard Worker else if (context->getExtensions().polygonModeANGLE)
5738*8975f5c5SAndroid Build Coastguard Worker {
5739*8975f5c5SAndroid Build Coastguard Worker cap(CapturePolygonModeANGLE(replayState, true, GL_FRONT_AND_BACK,
5740*8975f5c5SAndroid Build Coastguard Worker currentRasterState.polygonMode));
5741*8975f5c5SAndroid Build Coastguard Worker }
5742*8975f5c5SAndroid Build Coastguard Worker else
5743*8975f5c5SAndroid Build Coastguard Worker {
5744*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
5745*8975f5c5SAndroid Build Coastguard Worker }
5746*8975f5c5SAndroid Build Coastguard Worker }
5747*8975f5c5SAndroid Build Coastguard Worker
5748*8975f5c5SAndroid Build Coastguard Worker if (currentRasterState.polygonOffsetPoint != defaultRasterState.polygonOffsetPoint)
5749*8975f5c5SAndroid Build Coastguard Worker {
5750*8975f5c5SAndroid Build Coastguard Worker capCap(GL_POLYGON_OFFSET_POINT_NV, currentRasterState.polygonOffsetPoint);
5751*8975f5c5SAndroid Build Coastguard Worker }
5752*8975f5c5SAndroid Build Coastguard Worker
5753*8975f5c5SAndroid Build Coastguard Worker if (currentRasterState.polygonOffsetLine != defaultRasterState.polygonOffsetLine)
5754*8975f5c5SAndroid Build Coastguard Worker {
5755*8975f5c5SAndroid Build Coastguard Worker capCap(GL_POLYGON_OFFSET_LINE_NV, currentRasterState.polygonOffsetLine);
5756*8975f5c5SAndroid Build Coastguard Worker }
5757*8975f5c5SAndroid Build Coastguard Worker
5758*8975f5c5SAndroid Build Coastguard Worker if (currentRasterState.polygonOffsetFill != defaultRasterState.polygonOffsetFill)
5759*8975f5c5SAndroid Build Coastguard Worker {
5760*8975f5c5SAndroid Build Coastguard Worker capCap(GL_POLYGON_OFFSET_FILL, currentRasterState.polygonOffsetFill);
5761*8975f5c5SAndroid Build Coastguard Worker }
5762*8975f5c5SAndroid Build Coastguard Worker
5763*8975f5c5SAndroid Build Coastguard Worker if (currentRasterState.polygonOffsetFactor != defaultRasterState.polygonOffsetFactor ||
5764*8975f5c5SAndroid Build Coastguard Worker currentRasterState.polygonOffsetUnits != defaultRasterState.polygonOffsetUnits ||
5765*8975f5c5SAndroid Build Coastguard Worker currentRasterState.polygonOffsetClamp != defaultRasterState.polygonOffsetClamp)
5766*8975f5c5SAndroid Build Coastguard Worker {
5767*8975f5c5SAndroid Build Coastguard Worker if (currentRasterState.polygonOffsetClamp == 0.0f)
5768*8975f5c5SAndroid Build Coastguard Worker {
5769*8975f5c5SAndroid Build Coastguard Worker cap(CapturePolygonOffset(replayState, true, currentRasterState.polygonOffsetFactor,
5770*8975f5c5SAndroid Build Coastguard Worker currentRasterState.polygonOffsetUnits));
5771*8975f5c5SAndroid Build Coastguard Worker }
5772*8975f5c5SAndroid Build Coastguard Worker else
5773*8975f5c5SAndroid Build Coastguard Worker {
5774*8975f5c5SAndroid Build Coastguard Worker cap(CapturePolygonOffsetClampEXT(
5775*8975f5c5SAndroid Build Coastguard Worker replayState, true, currentRasterState.polygonOffsetFactor,
5776*8975f5c5SAndroid Build Coastguard Worker currentRasterState.polygonOffsetUnits, currentRasterState.polygonOffsetClamp));
5777*8975f5c5SAndroid Build Coastguard Worker }
5778*8975f5c5SAndroid Build Coastguard Worker }
5779*8975f5c5SAndroid Build Coastguard Worker
5780*8975f5c5SAndroid Build Coastguard Worker if (currentRasterState.depthClamp != defaultRasterState.depthClamp)
5781*8975f5c5SAndroid Build Coastguard Worker {
5782*8975f5c5SAndroid Build Coastguard Worker capCap(GL_DEPTH_CLAMP_EXT, currentRasterState.depthClamp);
5783*8975f5c5SAndroid Build Coastguard Worker }
5784*8975f5c5SAndroid Build Coastguard Worker
5785*8975f5c5SAndroid Build Coastguard Worker // pointDrawMode/multiSample are only used in the D3D back-end right now.
5786*8975f5c5SAndroid Build Coastguard Worker
5787*8975f5c5SAndroid Build Coastguard Worker if (currentRasterState.rasterizerDiscard != defaultRasterState.rasterizerDiscard)
5788*8975f5c5SAndroid Build Coastguard Worker {
5789*8975f5c5SAndroid Build Coastguard Worker capCap(GL_RASTERIZER_DISCARD, currentRasterState.rasterizerDiscard);
5790*8975f5c5SAndroid Build Coastguard Worker }
5791*8975f5c5SAndroid Build Coastguard Worker
5792*8975f5c5SAndroid Build Coastguard Worker if (currentRasterState.dither != defaultRasterState.dither)
5793*8975f5c5SAndroid Build Coastguard Worker {
5794*8975f5c5SAndroid Build Coastguard Worker capCap(GL_DITHER, currentRasterState.dither);
5795*8975f5c5SAndroid Build Coastguard Worker }
5796*8975f5c5SAndroid Build Coastguard Worker
5797*8975f5c5SAndroid Build Coastguard Worker // Depth/stencil state.
5798*8975f5c5SAndroid Build Coastguard Worker const gl::DepthStencilState &defaultDSState = replayState.getDepthStencilState();
5799*8975f5c5SAndroid Build Coastguard Worker const gl::DepthStencilState ¤tDSState = apiState.getDepthStencilState();
5800*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.depthFunc != currentDSState.depthFunc)
5801*8975f5c5SAndroid Build Coastguard Worker {
5802*8975f5c5SAndroid Build Coastguard Worker cap(CaptureDepthFunc(replayState, true, currentDSState.depthFunc));
5803*8975f5c5SAndroid Build Coastguard Worker }
5804*8975f5c5SAndroid Build Coastguard Worker
5805*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.depthMask != currentDSState.depthMask)
5806*8975f5c5SAndroid Build Coastguard Worker {
5807*8975f5c5SAndroid Build Coastguard Worker cap(CaptureDepthMask(replayState, true, gl::ConvertToGLBoolean(currentDSState.depthMask)));
5808*8975f5c5SAndroid Build Coastguard Worker }
5809*8975f5c5SAndroid Build Coastguard Worker
5810*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.depthTest != currentDSState.depthTest)
5811*8975f5c5SAndroid Build Coastguard Worker {
5812*8975f5c5SAndroid Build Coastguard Worker capCap(GL_DEPTH_TEST, currentDSState.depthTest);
5813*8975f5c5SAndroid Build Coastguard Worker }
5814*8975f5c5SAndroid Build Coastguard Worker
5815*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.stencilTest != currentDSState.stencilTest)
5816*8975f5c5SAndroid Build Coastguard Worker {
5817*8975f5c5SAndroid Build Coastguard Worker capCap(GL_STENCIL_TEST, currentDSState.stencilTest);
5818*8975f5c5SAndroid Build Coastguard Worker }
5819*8975f5c5SAndroid Build Coastguard Worker
5820*8975f5c5SAndroid Build Coastguard Worker if (currentDSState.stencilFunc == currentDSState.stencilBackFunc &&
5821*8975f5c5SAndroid Build Coastguard Worker currentDSState.stencilMask == currentDSState.stencilBackMask)
5822*8975f5c5SAndroid Build Coastguard Worker {
5823*8975f5c5SAndroid Build Coastguard Worker // Front and back are equal
5824*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.stencilFunc != currentDSState.stencilFunc ||
5825*8975f5c5SAndroid Build Coastguard Worker defaultDSState.stencilMask != currentDSState.stencilMask ||
5826*8975f5c5SAndroid Build Coastguard Worker apiState.getStencilRef() != 0)
5827*8975f5c5SAndroid Build Coastguard Worker {
5828*8975f5c5SAndroid Build Coastguard Worker cap(CaptureStencilFunc(replayState, true, currentDSState.stencilFunc,
5829*8975f5c5SAndroid Build Coastguard Worker apiState.getStencilRef(), currentDSState.stencilMask));
5830*8975f5c5SAndroid Build Coastguard Worker }
5831*8975f5c5SAndroid Build Coastguard Worker }
5832*8975f5c5SAndroid Build Coastguard Worker else
5833*8975f5c5SAndroid Build Coastguard Worker {
5834*8975f5c5SAndroid Build Coastguard Worker // Front and back are separate
5835*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.stencilFunc != currentDSState.stencilFunc ||
5836*8975f5c5SAndroid Build Coastguard Worker defaultDSState.stencilMask != currentDSState.stencilMask ||
5837*8975f5c5SAndroid Build Coastguard Worker apiState.getStencilRef() != 0)
5838*8975f5c5SAndroid Build Coastguard Worker {
5839*8975f5c5SAndroid Build Coastguard Worker cap(CaptureStencilFuncSeparate(replayState, true, GL_FRONT, currentDSState.stencilFunc,
5840*8975f5c5SAndroid Build Coastguard Worker apiState.getStencilRef(), currentDSState.stencilMask));
5841*8975f5c5SAndroid Build Coastguard Worker }
5842*8975f5c5SAndroid Build Coastguard Worker
5843*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.stencilBackFunc != currentDSState.stencilBackFunc ||
5844*8975f5c5SAndroid Build Coastguard Worker defaultDSState.stencilBackMask != currentDSState.stencilBackMask ||
5845*8975f5c5SAndroid Build Coastguard Worker apiState.getStencilBackRef() != 0)
5846*8975f5c5SAndroid Build Coastguard Worker {
5847*8975f5c5SAndroid Build Coastguard Worker cap(CaptureStencilFuncSeparate(
5848*8975f5c5SAndroid Build Coastguard Worker replayState, true, GL_BACK, currentDSState.stencilBackFunc,
5849*8975f5c5SAndroid Build Coastguard Worker apiState.getStencilBackRef(), currentDSState.stencilBackMask));
5850*8975f5c5SAndroid Build Coastguard Worker }
5851*8975f5c5SAndroid Build Coastguard Worker }
5852*8975f5c5SAndroid Build Coastguard Worker
5853*8975f5c5SAndroid Build Coastguard Worker if (currentDSState.stencilFail == currentDSState.stencilBackFail &&
5854*8975f5c5SAndroid Build Coastguard Worker currentDSState.stencilPassDepthFail == currentDSState.stencilBackPassDepthFail &&
5855*8975f5c5SAndroid Build Coastguard Worker currentDSState.stencilPassDepthPass == currentDSState.stencilBackPassDepthPass)
5856*8975f5c5SAndroid Build Coastguard Worker {
5857*8975f5c5SAndroid Build Coastguard Worker // Front and back are equal
5858*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.stencilFail != currentDSState.stencilFail ||
5859*8975f5c5SAndroid Build Coastguard Worker defaultDSState.stencilPassDepthFail != currentDSState.stencilPassDepthFail ||
5860*8975f5c5SAndroid Build Coastguard Worker defaultDSState.stencilPassDepthPass != currentDSState.stencilPassDepthPass)
5861*8975f5c5SAndroid Build Coastguard Worker {
5862*8975f5c5SAndroid Build Coastguard Worker cap(CaptureStencilOp(replayState, true, currentDSState.stencilFail,
5863*8975f5c5SAndroid Build Coastguard Worker currentDSState.stencilPassDepthFail,
5864*8975f5c5SAndroid Build Coastguard Worker currentDSState.stencilPassDepthPass));
5865*8975f5c5SAndroid Build Coastguard Worker }
5866*8975f5c5SAndroid Build Coastguard Worker }
5867*8975f5c5SAndroid Build Coastguard Worker else
5868*8975f5c5SAndroid Build Coastguard Worker {
5869*8975f5c5SAndroid Build Coastguard Worker // Front and back are separate
5870*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.stencilFail != currentDSState.stencilFail ||
5871*8975f5c5SAndroid Build Coastguard Worker defaultDSState.stencilPassDepthFail != currentDSState.stencilPassDepthFail ||
5872*8975f5c5SAndroid Build Coastguard Worker defaultDSState.stencilPassDepthPass != currentDSState.stencilPassDepthPass)
5873*8975f5c5SAndroid Build Coastguard Worker {
5874*8975f5c5SAndroid Build Coastguard Worker cap(CaptureStencilOpSeparate(replayState, true, GL_FRONT, currentDSState.stencilFail,
5875*8975f5c5SAndroid Build Coastguard Worker currentDSState.stencilPassDepthFail,
5876*8975f5c5SAndroid Build Coastguard Worker currentDSState.stencilPassDepthPass));
5877*8975f5c5SAndroid Build Coastguard Worker }
5878*8975f5c5SAndroid Build Coastguard Worker
5879*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.stencilBackFail != currentDSState.stencilBackFail ||
5880*8975f5c5SAndroid Build Coastguard Worker defaultDSState.stencilBackPassDepthFail != currentDSState.stencilBackPassDepthFail ||
5881*8975f5c5SAndroid Build Coastguard Worker defaultDSState.stencilBackPassDepthPass != currentDSState.stencilBackPassDepthPass)
5882*8975f5c5SAndroid Build Coastguard Worker {
5883*8975f5c5SAndroid Build Coastguard Worker cap(CaptureStencilOpSeparate(replayState, true, GL_BACK, currentDSState.stencilBackFail,
5884*8975f5c5SAndroid Build Coastguard Worker currentDSState.stencilBackPassDepthFail,
5885*8975f5c5SAndroid Build Coastguard Worker currentDSState.stencilBackPassDepthPass));
5886*8975f5c5SAndroid Build Coastguard Worker }
5887*8975f5c5SAndroid Build Coastguard Worker }
5888*8975f5c5SAndroid Build Coastguard Worker
5889*8975f5c5SAndroid Build Coastguard Worker if (currentDSState.stencilWritemask == currentDSState.stencilBackWritemask)
5890*8975f5c5SAndroid Build Coastguard Worker {
5891*8975f5c5SAndroid Build Coastguard Worker // Front and back are equal
5892*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.stencilWritemask != currentDSState.stencilWritemask)
5893*8975f5c5SAndroid Build Coastguard Worker {
5894*8975f5c5SAndroid Build Coastguard Worker cap(CaptureStencilMask(replayState, true, currentDSState.stencilWritemask));
5895*8975f5c5SAndroid Build Coastguard Worker }
5896*8975f5c5SAndroid Build Coastguard Worker }
5897*8975f5c5SAndroid Build Coastguard Worker else
5898*8975f5c5SAndroid Build Coastguard Worker {
5899*8975f5c5SAndroid Build Coastguard Worker // Front and back are separate
5900*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.stencilWritemask != currentDSState.stencilWritemask)
5901*8975f5c5SAndroid Build Coastguard Worker {
5902*8975f5c5SAndroid Build Coastguard Worker cap(CaptureStencilMaskSeparate(replayState, true, GL_FRONT,
5903*8975f5c5SAndroid Build Coastguard Worker currentDSState.stencilWritemask));
5904*8975f5c5SAndroid Build Coastguard Worker }
5905*8975f5c5SAndroid Build Coastguard Worker
5906*8975f5c5SAndroid Build Coastguard Worker if (defaultDSState.stencilBackWritemask != currentDSState.stencilBackWritemask)
5907*8975f5c5SAndroid Build Coastguard Worker {
5908*8975f5c5SAndroid Build Coastguard Worker cap(CaptureStencilMaskSeparate(replayState, true, GL_BACK,
5909*8975f5c5SAndroid Build Coastguard Worker currentDSState.stencilBackWritemask));
5910*8975f5c5SAndroid Build Coastguard Worker }
5911*8975f5c5SAndroid Build Coastguard Worker }
5912*8975f5c5SAndroid Build Coastguard Worker
5913*8975f5c5SAndroid Build Coastguard Worker // Blend state.
5914*8975f5c5SAndroid Build Coastguard Worker const gl::BlendState &defaultBlendState = replayState.getBlendState();
5915*8975f5c5SAndroid Build Coastguard Worker const gl::BlendState ¤tBlendState = apiState.getBlendState();
5916*8975f5c5SAndroid Build Coastguard Worker
5917*8975f5c5SAndroid Build Coastguard Worker if (currentBlendState.blend != defaultBlendState.blend)
5918*8975f5c5SAndroid Build Coastguard Worker {
5919*8975f5c5SAndroid Build Coastguard Worker capCap(GL_BLEND, currentBlendState.blend);
5920*8975f5c5SAndroid Build Coastguard Worker }
5921*8975f5c5SAndroid Build Coastguard Worker
5922*8975f5c5SAndroid Build Coastguard Worker if (currentBlendState.sourceBlendRGB != defaultBlendState.sourceBlendRGB ||
5923*8975f5c5SAndroid Build Coastguard Worker currentBlendState.destBlendRGB != defaultBlendState.destBlendRGB ||
5924*8975f5c5SAndroid Build Coastguard Worker currentBlendState.sourceBlendAlpha != defaultBlendState.sourceBlendAlpha ||
5925*8975f5c5SAndroid Build Coastguard Worker currentBlendState.destBlendAlpha != defaultBlendState.destBlendAlpha)
5926*8975f5c5SAndroid Build Coastguard Worker {
5927*8975f5c5SAndroid Build Coastguard Worker if (context->isGLES1())
5928*8975f5c5SAndroid Build Coastguard Worker {
5929*8975f5c5SAndroid Build Coastguard Worker // Even though their states are tracked independently, in GLES1 blendAlpha
5930*8975f5c5SAndroid Build Coastguard Worker // and blendRGB cannot be set separately and are always equal
5931*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBlendFunc(replayState, true, currentBlendState.sourceBlendRGB,
5932*8975f5c5SAndroid Build Coastguard Worker currentBlendState.destBlendRGB));
5933*8975f5c5SAndroid Build Coastguard Worker Capture(&resetCalls[angle::EntryPoint::GLBlendFunc],
5934*8975f5c5SAndroid Build Coastguard Worker CaptureBlendFunc(replayState, true, currentBlendState.sourceBlendRGB,
5935*8975f5c5SAndroid Build Coastguard Worker currentBlendState.destBlendRGB));
5936*8975f5c5SAndroid Build Coastguard Worker }
5937*8975f5c5SAndroid Build Coastguard Worker else
5938*8975f5c5SAndroid Build Coastguard Worker {
5939*8975f5c5SAndroid Build Coastguard Worker // Always use BlendFuncSeparate for non-GLES1 as it covers all cases
5940*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBlendFuncSeparate(
5941*8975f5c5SAndroid Build Coastguard Worker replayState, true, currentBlendState.sourceBlendRGB, currentBlendState.destBlendRGB,
5942*8975f5c5SAndroid Build Coastguard Worker currentBlendState.sourceBlendAlpha, currentBlendState.destBlendAlpha));
5943*8975f5c5SAndroid Build Coastguard Worker Capture(&resetCalls[angle::EntryPoint::GLBlendFuncSeparate],
5944*8975f5c5SAndroid Build Coastguard Worker CaptureBlendFuncSeparate(replayState, true, currentBlendState.sourceBlendRGB,
5945*8975f5c5SAndroid Build Coastguard Worker currentBlendState.destBlendRGB,
5946*8975f5c5SAndroid Build Coastguard Worker currentBlendState.sourceBlendAlpha,
5947*8975f5c5SAndroid Build Coastguard Worker currentBlendState.destBlendAlpha));
5948*8975f5c5SAndroid Build Coastguard Worker }
5949*8975f5c5SAndroid Build Coastguard Worker }
5950*8975f5c5SAndroid Build Coastguard Worker
5951*8975f5c5SAndroid Build Coastguard Worker if (currentBlendState.blendEquationRGB != defaultBlendState.blendEquationRGB ||
5952*8975f5c5SAndroid Build Coastguard Worker currentBlendState.blendEquationAlpha != defaultBlendState.blendEquationAlpha)
5953*8975f5c5SAndroid Build Coastguard Worker {
5954*8975f5c5SAndroid Build Coastguard Worker // Similarly to BlendFunc, using BlendEquation in some cases complicates Reset.
5955*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBlendEquationSeparate(replayState, true, currentBlendState.blendEquationRGB,
5956*8975f5c5SAndroid Build Coastguard Worker currentBlendState.blendEquationAlpha));
5957*8975f5c5SAndroid Build Coastguard Worker Capture(&resetCalls[angle::EntryPoint::GLBlendEquationSeparate],
5958*8975f5c5SAndroid Build Coastguard Worker CaptureBlendEquationSeparate(replayState, true, currentBlendState.blendEquationRGB,
5959*8975f5c5SAndroid Build Coastguard Worker currentBlendState.blendEquationAlpha));
5960*8975f5c5SAndroid Build Coastguard Worker }
5961*8975f5c5SAndroid Build Coastguard Worker
5962*8975f5c5SAndroid Build Coastguard Worker if (currentBlendState.colorMaskRed != defaultBlendState.colorMaskRed ||
5963*8975f5c5SAndroid Build Coastguard Worker currentBlendState.colorMaskGreen != defaultBlendState.colorMaskGreen ||
5964*8975f5c5SAndroid Build Coastguard Worker currentBlendState.colorMaskBlue != defaultBlendState.colorMaskBlue ||
5965*8975f5c5SAndroid Build Coastguard Worker currentBlendState.colorMaskAlpha != defaultBlendState.colorMaskAlpha)
5966*8975f5c5SAndroid Build Coastguard Worker {
5967*8975f5c5SAndroid Build Coastguard Worker cap(CaptureColorMask(replayState, true,
5968*8975f5c5SAndroid Build Coastguard Worker gl::ConvertToGLBoolean(currentBlendState.colorMaskRed),
5969*8975f5c5SAndroid Build Coastguard Worker gl::ConvertToGLBoolean(currentBlendState.colorMaskGreen),
5970*8975f5c5SAndroid Build Coastguard Worker gl::ConvertToGLBoolean(currentBlendState.colorMaskBlue),
5971*8975f5c5SAndroid Build Coastguard Worker gl::ConvertToGLBoolean(currentBlendState.colorMaskAlpha)));
5972*8975f5c5SAndroid Build Coastguard Worker Capture(&resetCalls[angle::EntryPoint::GLColorMask],
5973*8975f5c5SAndroid Build Coastguard Worker CaptureColorMask(replayState, true,
5974*8975f5c5SAndroid Build Coastguard Worker gl::ConvertToGLBoolean(currentBlendState.colorMaskRed),
5975*8975f5c5SAndroid Build Coastguard Worker gl::ConvertToGLBoolean(currentBlendState.colorMaskGreen),
5976*8975f5c5SAndroid Build Coastguard Worker gl::ConvertToGLBoolean(currentBlendState.colorMaskBlue),
5977*8975f5c5SAndroid Build Coastguard Worker gl::ConvertToGLBoolean(currentBlendState.colorMaskAlpha)));
5978*8975f5c5SAndroid Build Coastguard Worker }
5979*8975f5c5SAndroid Build Coastguard Worker
5980*8975f5c5SAndroid Build Coastguard Worker const gl::ColorF ¤tBlendColor = apiState.getBlendColor();
5981*8975f5c5SAndroid Build Coastguard Worker if (currentBlendColor != gl::ColorF())
5982*8975f5c5SAndroid Build Coastguard Worker {
5983*8975f5c5SAndroid Build Coastguard Worker cap(CaptureBlendColor(replayState, true, currentBlendColor.red, currentBlendColor.green,
5984*8975f5c5SAndroid Build Coastguard Worker currentBlendColor.blue, currentBlendColor.alpha));
5985*8975f5c5SAndroid Build Coastguard Worker Capture(&resetCalls[angle::EntryPoint::GLBlendColor],
5986*8975f5c5SAndroid Build Coastguard Worker CaptureBlendColor(replayState, true, currentBlendColor.red, currentBlendColor.green,
5987*8975f5c5SAndroid Build Coastguard Worker currentBlendColor.blue, currentBlendColor.alpha));
5988*8975f5c5SAndroid Build Coastguard Worker }
5989*8975f5c5SAndroid Build Coastguard Worker
5990*8975f5c5SAndroid Build Coastguard Worker // Pixel storage states.
5991*8975f5c5SAndroid Build Coastguard Worker gl::PixelPackState ¤tPackState = replayState.getPackState();
5992*8975f5c5SAndroid Build Coastguard Worker if (currentPackState.alignment != apiState.getPackAlignment())
5993*8975f5c5SAndroid Build Coastguard Worker {
5994*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_PACK_ALIGNMENT, apiState.getPackAlignment()));
5995*8975f5c5SAndroid Build Coastguard Worker currentPackState.alignment = apiState.getPackAlignment();
5996*8975f5c5SAndroid Build Coastguard Worker }
5997*8975f5c5SAndroid Build Coastguard Worker
5998*8975f5c5SAndroid Build Coastguard Worker if (currentPackState.rowLength != apiState.getPackRowLength())
5999*8975f5c5SAndroid Build Coastguard Worker {
6000*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_PACK_ROW_LENGTH, apiState.getPackRowLength()));
6001*8975f5c5SAndroid Build Coastguard Worker currentPackState.rowLength = apiState.getPackRowLength();
6002*8975f5c5SAndroid Build Coastguard Worker }
6003*8975f5c5SAndroid Build Coastguard Worker
6004*8975f5c5SAndroid Build Coastguard Worker if (currentPackState.skipRows != apiState.getPackSkipRows())
6005*8975f5c5SAndroid Build Coastguard Worker {
6006*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_PACK_SKIP_ROWS, apiState.getPackSkipRows()));
6007*8975f5c5SAndroid Build Coastguard Worker currentPackState.skipRows = apiState.getPackSkipRows();
6008*8975f5c5SAndroid Build Coastguard Worker }
6009*8975f5c5SAndroid Build Coastguard Worker
6010*8975f5c5SAndroid Build Coastguard Worker if (currentPackState.skipPixels != apiState.getPackSkipPixels())
6011*8975f5c5SAndroid Build Coastguard Worker {
6012*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_PACK_SKIP_PIXELS,
6013*8975f5c5SAndroid Build Coastguard Worker apiState.getPackSkipPixels()));
6014*8975f5c5SAndroid Build Coastguard Worker currentPackState.skipPixels = apiState.getPackSkipPixels();
6015*8975f5c5SAndroid Build Coastguard Worker }
6016*8975f5c5SAndroid Build Coastguard Worker
6017*8975f5c5SAndroid Build Coastguard Worker // We set unpack alignment above, no need to change it here
6018*8975f5c5SAndroid Build Coastguard Worker ASSERT(currentUnpackState.alignment == 1);
6019*8975f5c5SAndroid Build Coastguard Worker if (currentUnpackState.rowLength != apiState.getUnpackRowLength())
6020*8975f5c5SAndroid Build Coastguard Worker {
6021*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_UNPACK_ROW_LENGTH,
6022*8975f5c5SAndroid Build Coastguard Worker apiState.getUnpackRowLength()));
6023*8975f5c5SAndroid Build Coastguard Worker currentUnpackState.rowLength = apiState.getUnpackRowLength();
6024*8975f5c5SAndroid Build Coastguard Worker }
6025*8975f5c5SAndroid Build Coastguard Worker
6026*8975f5c5SAndroid Build Coastguard Worker if (currentUnpackState.skipRows != apiState.getUnpackSkipRows())
6027*8975f5c5SAndroid Build Coastguard Worker {
6028*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_UNPACK_SKIP_ROWS,
6029*8975f5c5SAndroid Build Coastguard Worker apiState.getUnpackSkipRows()));
6030*8975f5c5SAndroid Build Coastguard Worker currentUnpackState.skipRows = apiState.getUnpackSkipRows();
6031*8975f5c5SAndroid Build Coastguard Worker }
6032*8975f5c5SAndroid Build Coastguard Worker
6033*8975f5c5SAndroid Build Coastguard Worker if (currentUnpackState.skipPixels != apiState.getUnpackSkipPixels())
6034*8975f5c5SAndroid Build Coastguard Worker {
6035*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_UNPACK_SKIP_PIXELS,
6036*8975f5c5SAndroid Build Coastguard Worker apiState.getUnpackSkipPixels()));
6037*8975f5c5SAndroid Build Coastguard Worker currentUnpackState.skipPixels = apiState.getUnpackSkipPixels();
6038*8975f5c5SAndroid Build Coastguard Worker }
6039*8975f5c5SAndroid Build Coastguard Worker
6040*8975f5c5SAndroid Build Coastguard Worker if (currentUnpackState.imageHeight != apiState.getUnpackImageHeight())
6041*8975f5c5SAndroid Build Coastguard Worker {
6042*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_UNPACK_IMAGE_HEIGHT,
6043*8975f5c5SAndroid Build Coastguard Worker apiState.getUnpackImageHeight()));
6044*8975f5c5SAndroid Build Coastguard Worker currentUnpackState.imageHeight = apiState.getUnpackImageHeight();
6045*8975f5c5SAndroid Build Coastguard Worker }
6046*8975f5c5SAndroid Build Coastguard Worker
6047*8975f5c5SAndroid Build Coastguard Worker if (currentUnpackState.skipImages != apiState.getUnpackSkipImages())
6048*8975f5c5SAndroid Build Coastguard Worker {
6049*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_UNPACK_SKIP_IMAGES,
6050*8975f5c5SAndroid Build Coastguard Worker apiState.getUnpackSkipImages()));
6051*8975f5c5SAndroid Build Coastguard Worker currentUnpackState.skipImages = apiState.getUnpackSkipImages();
6052*8975f5c5SAndroid Build Coastguard Worker }
6053*8975f5c5SAndroid Build Coastguard Worker
6054*8975f5c5SAndroid Build Coastguard Worker // Clear state. Missing ES 3.x features.
6055*8975f5c5SAndroid Build Coastguard Worker // TODO(http://anglebug.com/42262323): Complete state capture.
6056*8975f5c5SAndroid Build Coastguard Worker const gl::ColorF ¤tClearColor = apiState.getColorClearValue();
6057*8975f5c5SAndroid Build Coastguard Worker if (currentClearColor != gl::ColorF())
6058*8975f5c5SAndroid Build Coastguard Worker {
6059*8975f5c5SAndroid Build Coastguard Worker cap(CaptureClearColor(replayState, true, currentClearColor.red, currentClearColor.green,
6060*8975f5c5SAndroid Build Coastguard Worker currentClearColor.blue, currentClearColor.alpha));
6061*8975f5c5SAndroid Build Coastguard Worker }
6062*8975f5c5SAndroid Build Coastguard Worker
6063*8975f5c5SAndroid Build Coastguard Worker if (apiState.getDepthClearValue() != 1.0f)
6064*8975f5c5SAndroid Build Coastguard Worker {
6065*8975f5c5SAndroid Build Coastguard Worker cap(CaptureClearDepthf(replayState, true, apiState.getDepthClearValue()));
6066*8975f5c5SAndroid Build Coastguard Worker }
6067*8975f5c5SAndroid Build Coastguard Worker
6068*8975f5c5SAndroid Build Coastguard Worker if (apiState.getStencilClearValue() != 0)
6069*8975f5c5SAndroid Build Coastguard Worker {
6070*8975f5c5SAndroid Build Coastguard Worker cap(CaptureClearStencil(replayState, true, apiState.getStencilClearValue()));
6071*8975f5c5SAndroid Build Coastguard Worker }
6072*8975f5c5SAndroid Build Coastguard Worker
6073*8975f5c5SAndroid Build Coastguard Worker // Viewport / scissor / clipping planes.
6074*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle ¤tViewport = apiState.getViewport();
6075*8975f5c5SAndroid Build Coastguard Worker if (currentViewport != gl::Rectangle())
6076*8975f5c5SAndroid Build Coastguard Worker {
6077*8975f5c5SAndroid Build Coastguard Worker cap(CaptureViewport(replayState, true, currentViewport.x, currentViewport.y,
6078*8975f5c5SAndroid Build Coastguard Worker currentViewport.width, currentViewport.height));
6079*8975f5c5SAndroid Build Coastguard Worker }
6080*8975f5c5SAndroid Build Coastguard Worker
6081*8975f5c5SAndroid Build Coastguard Worker if (apiState.getNearPlane() != 0.0f || apiState.getFarPlane() != 1.0f)
6082*8975f5c5SAndroid Build Coastguard Worker {
6083*8975f5c5SAndroid Build Coastguard Worker cap(CaptureDepthRangef(replayState, true, apiState.getNearPlane(), apiState.getFarPlane()));
6084*8975f5c5SAndroid Build Coastguard Worker }
6085*8975f5c5SAndroid Build Coastguard Worker
6086*8975f5c5SAndroid Build Coastguard Worker if (apiState.getClipOrigin() != gl::ClipOrigin::LowerLeft ||
6087*8975f5c5SAndroid Build Coastguard Worker apiState.getClipDepthMode() != gl::ClipDepthMode::NegativeOneToOne)
6088*8975f5c5SAndroid Build Coastguard Worker {
6089*8975f5c5SAndroid Build Coastguard Worker cap(CaptureClipControlEXT(replayState, true, apiState.getClipOrigin(),
6090*8975f5c5SAndroid Build Coastguard Worker apiState.getClipDepthMode()));
6091*8975f5c5SAndroid Build Coastguard Worker }
6092*8975f5c5SAndroid Build Coastguard Worker
6093*8975f5c5SAndroid Build Coastguard Worker if (apiState.isScissorTestEnabled())
6094*8975f5c5SAndroid Build Coastguard Worker {
6095*8975f5c5SAndroid Build Coastguard Worker capCap(GL_SCISSOR_TEST, apiState.isScissorTestEnabled());
6096*8975f5c5SAndroid Build Coastguard Worker }
6097*8975f5c5SAndroid Build Coastguard Worker
6098*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle ¤tScissor = apiState.getScissor();
6099*8975f5c5SAndroid Build Coastguard Worker if (currentScissor != gl::Rectangle())
6100*8975f5c5SAndroid Build Coastguard Worker {
6101*8975f5c5SAndroid Build Coastguard Worker cap(CaptureScissor(replayState, true, currentScissor.x, currentScissor.y,
6102*8975f5c5SAndroid Build Coastguard Worker currentScissor.width, currentScissor.height));
6103*8975f5c5SAndroid Build Coastguard Worker }
6104*8975f5c5SAndroid Build Coastguard Worker
6105*8975f5c5SAndroid Build Coastguard Worker // Allow the replayState object to be destroyed conveniently.
6106*8975f5c5SAndroid Build Coastguard Worker replayState.setBufferBinding(context, gl::BufferBinding::Array, nullptr);
6107*8975f5c5SAndroid Build Coastguard Worker
6108*8975f5c5SAndroid Build Coastguard Worker // Clean up the replay state.
6109*8975f5c5SAndroid Build Coastguard Worker replayState.reset(context);
6110*8975f5c5SAndroid Build Coastguard Worker
6111*8975f5c5SAndroid Build Coastguard Worker GLint contextUnpackAlignment = context->getState().getUnpackState().alignment;
6112*8975f5c5SAndroid Build Coastguard Worker if (currentUnpackState.alignment != contextUnpackAlignment)
6113*8975f5c5SAndroid Build Coastguard Worker {
6114*8975f5c5SAndroid Build Coastguard Worker cap(CapturePixelStorei(replayState, true, GL_UNPACK_ALIGNMENT, contextUnpackAlignment));
6115*8975f5c5SAndroid Build Coastguard Worker replayState.getMutablePrivateStateForCapture()->setUnpackAlignment(contextUnpackAlignment);
6116*8975f5c5SAndroid Build Coastguard Worker }
6117*8975f5c5SAndroid Build Coastguard Worker
6118*8975f5c5SAndroid Build Coastguard Worker if (validationEnabled)
6119*8975f5c5SAndroid Build Coastguard Worker {
6120*8975f5c5SAndroid Build Coastguard Worker CaptureValidateSerializedState(context, setupCalls);
6121*8975f5c5SAndroid Build Coastguard Worker }
6122*8975f5c5SAndroid Build Coastguard Worker }
6123*8975f5c5SAndroid Build Coastguard Worker
SkipCall(EntryPoint entryPoint)6124*8975f5c5SAndroid Build Coastguard Worker bool SkipCall(EntryPoint entryPoint)
6125*8975f5c5SAndroid Build Coastguard Worker {
6126*8975f5c5SAndroid Build Coastguard Worker switch (entryPoint)
6127*8975f5c5SAndroid Build Coastguard Worker {
6128*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDebugMessageCallback:
6129*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDebugMessageCallbackKHR:
6130*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDebugMessageControl:
6131*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDebugMessageControlKHR:
6132*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDebugMessageInsert:
6133*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDebugMessageInsertKHR:
6134*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGetDebugMessageLog:
6135*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGetDebugMessageLogKHR:
6136*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGetObjectLabel:
6137*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGetObjectLabelEXT:
6138*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGetObjectLabelKHR:
6139*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGetObjectPtrLabelKHR:
6140*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGetPointervKHR:
6141*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLInsertEventMarkerEXT:
6142*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLLabelObjectEXT:
6143*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLObjectLabel:
6144*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLObjectLabelKHR:
6145*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLObjectPtrLabelKHR:
6146*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLPopDebugGroupKHR:
6147*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLPopGroupMarkerEXT:
6148*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLPushDebugGroupKHR:
6149*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLPushGroupMarkerEXT:
6150*8975f5c5SAndroid Build Coastguard Worker // Purposefully skip entry points from:
6151*8975f5c5SAndroid Build Coastguard Worker // - KHR_debug
6152*8975f5c5SAndroid Build Coastguard Worker // - EXT_debug_label
6153*8975f5c5SAndroid Build Coastguard Worker // - EXT_debug_marker
6154*8975f5c5SAndroid Build Coastguard Worker // There is no need to capture these for replaying a trace in our harness
6155*8975f5c5SAndroid Build Coastguard Worker return true;
6156*8975f5c5SAndroid Build Coastguard Worker
6157*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGetActiveUniform:
6158*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGetActiveUniformsiv:
6159*8975f5c5SAndroid Build Coastguard Worker // Skip these calls because:
6160*8975f5c5SAndroid Build Coastguard Worker // - We don't use the return values.
6161*8975f5c5SAndroid Build Coastguard Worker // - Active uniform counts can vary between platforms due to cross stage optimizations
6162*8975f5c5SAndroid Build Coastguard Worker // and asking about uniforms above GL_ACTIVE_UNIFORMS triggers errors.
6163*8975f5c5SAndroid Build Coastguard Worker return true;
6164*8975f5c5SAndroid Build Coastguard Worker
6165*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGetActiveAttrib:
6166*8975f5c5SAndroid Build Coastguard Worker // Skip these calls because:
6167*8975f5c5SAndroid Build Coastguard Worker // - We don't use the return values.
6168*8975f5c5SAndroid Build Coastguard Worker // - Same as uniforms, the value can vary, asking above GL_ACTIVE_ATTRIBUTES is an error
6169*8975f5c5SAndroid Build Coastguard Worker return true;
6170*8975f5c5SAndroid Build Coastguard Worker
6171*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGetActiveUniformBlockiv:
6172*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGetActiveUniformBlockName:
6173*8975f5c5SAndroid Build Coastguard Worker // Skip these calls because:
6174*8975f5c5SAndroid Build Coastguard Worker // - We don't use the return values.
6175*8975f5c5SAndroid Build Coastguard Worker // - It reduces the number of references to the uniform block index map.
6176*8975f5c5SAndroid Build Coastguard Worker return true;
6177*8975f5c5SAndroid Build Coastguard Worker
6178*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLChooseConfig:
6179*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLGetProcAddress:
6180*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLGetConfigAttrib:
6181*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLGetConfigs:
6182*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLGetSyncAttrib:
6183*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLGetSyncAttribKHR:
6184*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLQueryContext:
6185*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLQuerySurface:
6186*8975f5c5SAndroid Build Coastguard Worker // Skip these calls because:
6187*8975f5c5SAndroid Build Coastguard Worker // - We don't use the return values.
6188*8975f5c5SAndroid Build Coastguard Worker // - Some EGL types and pointer parameters aren't yet implemented in EGL capture.
6189*8975f5c5SAndroid Build Coastguard Worker return true;
6190*8975f5c5SAndroid Build Coastguard Worker
6191*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLPrepareSwapBuffersANGLE:
6192*8975f5c5SAndroid Build Coastguard Worker // Skip this call because:
6193*8975f5c5SAndroid Build Coastguard Worker // - eglPrepareSwapBuffersANGLE is automatically called by eglSwapBuffers
6194*8975f5c5SAndroid Build Coastguard Worker return true;
6195*8975f5c5SAndroid Build Coastguard Worker
6196*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLSwapBuffers:
6197*8975f5c5SAndroid Build Coastguard Worker // Skip these calls because:
6198*8975f5c5SAndroid Build Coastguard Worker // - Swap is handled specially by the trace harness.
6199*8975f5c5SAndroid Build Coastguard Worker return true;
6200*8975f5c5SAndroid Build Coastguard Worker
6201*8975f5c5SAndroid Build Coastguard Worker default:
6202*8975f5c5SAndroid Build Coastguard Worker break;
6203*8975f5c5SAndroid Build Coastguard Worker }
6204*8975f5c5SAndroid Build Coastguard Worker
6205*8975f5c5SAndroid Build Coastguard Worker return false;
6206*8975f5c5SAndroid Build Coastguard Worker }
6207*8975f5c5SAndroid Build Coastguard Worker
GetBaseName(const std::string & nameWithPath)6208*8975f5c5SAndroid Build Coastguard Worker std::string GetBaseName(const std::string &nameWithPath)
6209*8975f5c5SAndroid Build Coastguard Worker {
6210*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> result = angle::SplitString(
6211*8975f5c5SAndroid Build Coastguard Worker nameWithPath, "/\\", WhitespaceHandling::TRIM_WHITESPACE, SplitResult::SPLIT_WANT_NONEMPTY);
6212*8975f5c5SAndroid Build Coastguard Worker ASSERT(!result.empty());
6213*8975f5c5SAndroid Build Coastguard Worker return result.back();
6214*8975f5c5SAndroid Build Coastguard Worker }
6215*8975f5c5SAndroid Build Coastguard Worker } // namespace
6216*8975f5c5SAndroid Build Coastguard Worker
6217*8975f5c5SAndroid Build Coastguard Worker FrameCapture::FrameCapture() = default;
6218*8975f5c5SAndroid Build Coastguard Worker FrameCapture::~FrameCapture() = default;
6219*8975f5c5SAndroid Build Coastguard Worker
reset()6220*8975f5c5SAndroid Build Coastguard Worker void FrameCapture::reset()
6221*8975f5c5SAndroid Build Coastguard Worker {
6222*8975f5c5SAndroid Build Coastguard Worker mSetupCalls.clear();
6223*8975f5c5SAndroid Build Coastguard Worker }
6224*8975f5c5SAndroid Build Coastguard Worker
FrameCaptureShared()6225*8975f5c5SAndroid Build Coastguard Worker FrameCaptureShared::FrameCaptureShared()
6226*8975f5c5SAndroid Build Coastguard Worker : mEnabled(true),
6227*8975f5c5SAndroid Build Coastguard Worker mSerializeStateEnabled(false),
6228*8975f5c5SAndroid Build Coastguard Worker mCompression(true),
6229*8975f5c5SAndroid Build Coastguard Worker mClientVertexArrayMap{},
6230*8975f5c5SAndroid Build Coastguard Worker mFrameIndex(1),
6231*8975f5c5SAndroid Build Coastguard Worker mCaptureStartFrame(1),
6232*8975f5c5SAndroid Build Coastguard Worker mCaptureEndFrame(0),
6233*8975f5c5SAndroid Build Coastguard Worker mClientArraySizes{},
6234*8975f5c5SAndroid Build Coastguard Worker mReadBufferSize(0),
6235*8975f5c5SAndroid Build Coastguard Worker mResourceIDBufferSize(0),
6236*8975f5c5SAndroid Build Coastguard Worker mHasResourceType{},
6237*8975f5c5SAndroid Build Coastguard Worker mResourceIDToSetupCalls{},
6238*8975f5c5SAndroid Build Coastguard Worker mMaxAccessedResourceIDs{},
6239*8975f5c5SAndroid Build Coastguard Worker mCaptureTrigger(0),
6240*8975f5c5SAndroid Build Coastguard Worker mCaptureActive(false),
6241*8975f5c5SAndroid Build Coastguard Worker mWindowSurfaceContextID({0})
6242*8975f5c5SAndroid Build Coastguard Worker {
6243*8975f5c5SAndroid Build Coastguard Worker reset();
6244*8975f5c5SAndroid Build Coastguard Worker
6245*8975f5c5SAndroid Build Coastguard Worker std::string enabledFromEnv =
6246*8975f5c5SAndroid Build Coastguard Worker GetEnvironmentVarOrUnCachedAndroidProperty(kEnabledVarName, kAndroidEnabled);
6247*8975f5c5SAndroid Build Coastguard Worker if (enabledFromEnv == "0")
6248*8975f5c5SAndroid Build Coastguard Worker {
6249*8975f5c5SAndroid Build Coastguard Worker mEnabled = false;
6250*8975f5c5SAndroid Build Coastguard Worker }
6251*8975f5c5SAndroid Build Coastguard Worker
6252*8975f5c5SAndroid Build Coastguard Worker std::string startFromEnv =
6253*8975f5c5SAndroid Build Coastguard Worker GetEnvironmentVarOrUnCachedAndroidProperty(kFrameStartVarName, kAndroidFrameStart);
6254*8975f5c5SAndroid Build Coastguard Worker if (!startFromEnv.empty())
6255*8975f5c5SAndroid Build Coastguard Worker {
6256*8975f5c5SAndroid Build Coastguard Worker mCaptureStartFrame = atoi(startFromEnv.c_str());
6257*8975f5c5SAndroid Build Coastguard Worker }
6258*8975f5c5SAndroid Build Coastguard Worker if (mCaptureStartFrame < 1)
6259*8975f5c5SAndroid Build Coastguard Worker {
6260*8975f5c5SAndroid Build Coastguard Worker WARN() << "Cannot use a capture start frame less than 1.";
6261*8975f5c5SAndroid Build Coastguard Worker mCaptureStartFrame = 1;
6262*8975f5c5SAndroid Build Coastguard Worker }
6263*8975f5c5SAndroid Build Coastguard Worker
6264*8975f5c5SAndroid Build Coastguard Worker std::string endFromEnv =
6265*8975f5c5SAndroid Build Coastguard Worker GetEnvironmentVarOrUnCachedAndroidProperty(kFrameEndVarName, kAndroidFrameEnd);
6266*8975f5c5SAndroid Build Coastguard Worker if (!endFromEnv.empty())
6267*8975f5c5SAndroid Build Coastguard Worker {
6268*8975f5c5SAndroid Build Coastguard Worker mCaptureEndFrame = atoi(endFromEnv.c_str());
6269*8975f5c5SAndroid Build Coastguard Worker }
6270*8975f5c5SAndroid Build Coastguard Worker
6271*8975f5c5SAndroid Build Coastguard Worker std::string captureTriggerFromEnv =
6272*8975f5c5SAndroid Build Coastguard Worker GetEnvironmentVarOrUnCachedAndroidProperty(kTriggerVarName, kAndroidTrigger);
6273*8975f5c5SAndroid Build Coastguard Worker if (!captureTriggerFromEnv.empty())
6274*8975f5c5SAndroid Build Coastguard Worker {
6275*8975f5c5SAndroid Build Coastguard Worker mCaptureTrigger = atoi(captureTriggerFromEnv.c_str());
6276*8975f5c5SAndroid Build Coastguard Worker
6277*8975f5c5SAndroid Build Coastguard Worker // If the trigger has been populated, ignore the other frame range variables by setting them
6278*8975f5c5SAndroid Build Coastguard Worker // to unreasonable values. This isn't perfect, but it is effective.
6279*8975f5c5SAndroid Build Coastguard Worker mCaptureStartFrame = mCaptureEndFrame = std::numeric_limits<uint32_t>::max();
6280*8975f5c5SAndroid Build Coastguard Worker INFO() << "Capture trigger detected, disabling capture start/end frame.";
6281*8975f5c5SAndroid Build Coastguard Worker }
6282*8975f5c5SAndroid Build Coastguard Worker
6283*8975f5c5SAndroid Build Coastguard Worker std::string labelFromEnv =
6284*8975f5c5SAndroid Build Coastguard Worker GetEnvironmentVarOrUnCachedAndroidProperty(kCaptureLabelVarName, kAndroidCaptureLabel);
6285*8975f5c5SAndroid Build Coastguard Worker // --angle-per-test-capture-label sets the env var, not properties
6286*8975f5c5SAndroid Build Coastguard Worker if (labelFromEnv.empty())
6287*8975f5c5SAndroid Build Coastguard Worker {
6288*8975f5c5SAndroid Build Coastguard Worker labelFromEnv = GetEnvironmentVar(kCaptureLabelVarName);
6289*8975f5c5SAndroid Build Coastguard Worker }
6290*8975f5c5SAndroid Build Coastguard Worker if (!labelFromEnv.empty())
6291*8975f5c5SAndroid Build Coastguard Worker {
6292*8975f5c5SAndroid Build Coastguard Worker // Optional label to provide unique file names and namespaces
6293*8975f5c5SAndroid Build Coastguard Worker mCaptureLabel = labelFromEnv;
6294*8975f5c5SAndroid Build Coastguard Worker }
6295*8975f5c5SAndroid Build Coastguard Worker
6296*8975f5c5SAndroid Build Coastguard Worker std::string compressionFromEnv =
6297*8975f5c5SAndroid Build Coastguard Worker GetEnvironmentVarOrUnCachedAndroidProperty(kCompressionVarName, kAndroidCompression);
6298*8975f5c5SAndroid Build Coastguard Worker if (compressionFromEnv == "0")
6299*8975f5c5SAndroid Build Coastguard Worker {
6300*8975f5c5SAndroid Build Coastguard Worker mCompression = false;
6301*8975f5c5SAndroid Build Coastguard Worker }
6302*8975f5c5SAndroid Build Coastguard Worker std::string serializeStateFromEnv = angle::GetEnvironmentVar(kSerializeStateVarName);
6303*8975f5c5SAndroid Build Coastguard Worker if (serializeStateFromEnv == "1")
6304*8975f5c5SAndroid Build Coastguard Worker {
6305*8975f5c5SAndroid Build Coastguard Worker mSerializeStateEnabled = true;
6306*8975f5c5SAndroid Build Coastguard Worker }
6307*8975f5c5SAndroid Build Coastguard Worker
6308*8975f5c5SAndroid Build Coastguard Worker std::string validateSerialiedStateFromEnv =
6309*8975f5c5SAndroid Build Coastguard Worker GetEnvironmentVarOrUnCachedAndroidProperty(kValidationVarName, kAndroidValidation);
6310*8975f5c5SAndroid Build Coastguard Worker if (validateSerialiedStateFromEnv == "1")
6311*8975f5c5SAndroid Build Coastguard Worker {
6312*8975f5c5SAndroid Build Coastguard Worker mValidateSerializedState = true;
6313*8975f5c5SAndroid Build Coastguard Worker }
6314*8975f5c5SAndroid Build Coastguard Worker
6315*8975f5c5SAndroid Build Coastguard Worker mValidationExpression =
6316*8975f5c5SAndroid Build Coastguard Worker GetEnvironmentVarOrUnCachedAndroidProperty(kValidationExprVarName, kAndroidValidationExpr);
6317*8975f5c5SAndroid Build Coastguard Worker
6318*8975f5c5SAndroid Build Coastguard Worker if (!mValidationExpression.empty())
6319*8975f5c5SAndroid Build Coastguard Worker {
6320*8975f5c5SAndroid Build Coastguard Worker INFO() << "Validation expression is " << kValidationExprVarName;
6321*8975f5c5SAndroid Build Coastguard Worker }
6322*8975f5c5SAndroid Build Coastguard Worker
6323*8975f5c5SAndroid Build Coastguard Worker // TODO: Remove. http://anglebug.com/42266223
6324*8975f5c5SAndroid Build Coastguard Worker std::string sourceExtFromEnv =
6325*8975f5c5SAndroid Build Coastguard Worker GetEnvironmentVarOrUnCachedAndroidProperty(kSourceExtVarName, kAndroidSourceExt);
6326*8975f5c5SAndroid Build Coastguard Worker if (!sourceExtFromEnv.empty())
6327*8975f5c5SAndroid Build Coastguard Worker {
6328*8975f5c5SAndroid Build Coastguard Worker if (sourceExtFromEnv == "c" || sourceExtFromEnv == "cpp")
6329*8975f5c5SAndroid Build Coastguard Worker {
6330*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.setSourceFileExtension(sourceExtFromEnv.c_str());
6331*8975f5c5SAndroid Build Coastguard Worker }
6332*8975f5c5SAndroid Build Coastguard Worker else
6333*8975f5c5SAndroid Build Coastguard Worker {
6334*8975f5c5SAndroid Build Coastguard Worker WARN() << "Invalid capture source extension: " << sourceExtFromEnv;
6335*8975f5c5SAndroid Build Coastguard Worker }
6336*8975f5c5SAndroid Build Coastguard Worker }
6337*8975f5c5SAndroid Build Coastguard Worker
6338*8975f5c5SAndroid Build Coastguard Worker std::string sourceSizeFromEnv =
6339*8975f5c5SAndroid Build Coastguard Worker GetEnvironmentVarOrUnCachedAndroidProperty(kSourceSizeVarName, kAndroidSourceSize);
6340*8975f5c5SAndroid Build Coastguard Worker if (!sourceSizeFromEnv.empty())
6341*8975f5c5SAndroid Build Coastguard Worker {
6342*8975f5c5SAndroid Build Coastguard Worker int sourceSize = atoi(sourceSizeFromEnv.c_str());
6343*8975f5c5SAndroid Build Coastguard Worker if (sourceSize < 0)
6344*8975f5c5SAndroid Build Coastguard Worker {
6345*8975f5c5SAndroid Build Coastguard Worker WARN() << "Invalid capture source size: " << sourceSize;
6346*8975f5c5SAndroid Build Coastguard Worker }
6347*8975f5c5SAndroid Build Coastguard Worker else
6348*8975f5c5SAndroid Build Coastguard Worker {
6349*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.setSourceFileSizeThreshold(sourceSize);
6350*8975f5c5SAndroid Build Coastguard Worker }
6351*8975f5c5SAndroid Build Coastguard Worker }
6352*8975f5c5SAndroid Build Coastguard Worker
6353*8975f5c5SAndroid Build Coastguard Worker std::string forceShadowFromEnv =
6354*8975f5c5SAndroid Build Coastguard Worker GetEnvironmentVarOrUnCachedAndroidProperty(kForceShadowVarName, kAndroidForceShadow);
6355*8975f5c5SAndroid Build Coastguard Worker if (forceShadowFromEnv == "1")
6356*8975f5c5SAndroid Build Coastguard Worker {
6357*8975f5c5SAndroid Build Coastguard Worker INFO() << "Force enabling shadow memory for coherent buffer tracking.";
6358*8975f5c5SAndroid Build Coastguard Worker mCoherentBufferTracker.enableShadowMemory();
6359*8975f5c5SAndroid Build Coastguard Worker }
6360*8975f5c5SAndroid Build Coastguard Worker
6361*8975f5c5SAndroid Build Coastguard Worker if (mFrameIndex == mCaptureStartFrame)
6362*8975f5c5SAndroid Build Coastguard Worker {
6363*8975f5c5SAndroid Build Coastguard Worker // Capture is starting from the first frame, so set the capture active to ensure all GLES
6364*8975f5c5SAndroid Build Coastguard Worker // commands issued are handled correctly by maybeCapturePreCallUpdates() and
6365*8975f5c5SAndroid Build Coastguard Worker // maybeCapturePostCallUpdates().
6366*8975f5c5SAndroid Build Coastguard Worker setCaptureActive();
6367*8975f5c5SAndroid Build Coastguard Worker }
6368*8975f5c5SAndroid Build Coastguard Worker
6369*8975f5c5SAndroid Build Coastguard Worker if (mCaptureEndFrame < mCaptureStartFrame)
6370*8975f5c5SAndroid Build Coastguard Worker {
6371*8975f5c5SAndroid Build Coastguard Worker // If we're still in a situation where start frame is after end frame,
6372*8975f5c5SAndroid Build Coastguard Worker // capture cannot happen. Consider this a disabled state.
6373*8975f5c5SAndroid Build Coastguard Worker // Note: We won't get here if trigger is in use, as it sets them equal but huge.
6374*8975f5c5SAndroid Build Coastguard Worker mEnabled = false;
6375*8975f5c5SAndroid Build Coastguard Worker }
6376*8975f5c5SAndroid Build Coastguard Worker
6377*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.setCaptureLabel(mCaptureLabel);
6378*8975f5c5SAndroid Build Coastguard Worker
6379*8975f5c5SAndroid Build Coastguard Worker // Special case the output directory
6380*8975f5c5SAndroid Build Coastguard Worker if (mEnabled)
6381*8975f5c5SAndroid Build Coastguard Worker {
6382*8975f5c5SAndroid Build Coastguard Worker // Only perform output directory checks if enabled
6383*8975f5c5SAndroid Build Coastguard Worker // - This can avoid some expensive process name and filesystem checks
6384*8975f5c5SAndroid Build Coastguard Worker // - We want to emit errors if the directory doesn't exist
6385*8975f5c5SAndroid Build Coastguard Worker std::string pathFromEnv =
6386*8975f5c5SAndroid Build Coastguard Worker GetEnvironmentVarOrUnCachedAndroidProperty(kOutDirectoryVarName, kAndroidOutDir);
6387*8975f5c5SAndroid Build Coastguard Worker if (pathFromEnv.empty())
6388*8975f5c5SAndroid Build Coastguard Worker {
6389*8975f5c5SAndroid Build Coastguard Worker mOutDirectory = GetDefaultOutDirectory();
6390*8975f5c5SAndroid Build Coastguard Worker }
6391*8975f5c5SAndroid Build Coastguard Worker else
6392*8975f5c5SAndroid Build Coastguard Worker {
6393*8975f5c5SAndroid Build Coastguard Worker mOutDirectory = pathFromEnv;
6394*8975f5c5SAndroid Build Coastguard Worker }
6395*8975f5c5SAndroid Build Coastguard Worker
6396*8975f5c5SAndroid Build Coastguard Worker // Ensure the capture path ends with a slash.
6397*8975f5c5SAndroid Build Coastguard Worker if (mOutDirectory.back() != '\\' && mOutDirectory.back() != '/')
6398*8975f5c5SAndroid Build Coastguard Worker {
6399*8975f5c5SAndroid Build Coastguard Worker mOutDirectory += '/';
6400*8975f5c5SAndroid Build Coastguard Worker }
6401*8975f5c5SAndroid Build Coastguard Worker }
6402*8975f5c5SAndroid Build Coastguard Worker }
6403*8975f5c5SAndroid Build Coastguard Worker
6404*8975f5c5SAndroid Build Coastguard Worker FrameCaptureShared::~FrameCaptureShared() = default;
6405*8975f5c5SAndroid Build Coastguard Worker
PageRange(size_t start,size_t end)6406*8975f5c5SAndroid Build Coastguard Worker PageRange::PageRange(size_t start, size_t end) : start(start), end(end) {}
6407*8975f5c5SAndroid Build Coastguard Worker PageRange::~PageRange() = default;
6408*8975f5c5SAndroid Build Coastguard Worker
AddressRange()6409*8975f5c5SAndroid Build Coastguard Worker AddressRange::AddressRange() {}
AddressRange(uintptr_t start,size_t size)6410*8975f5c5SAndroid Build Coastguard Worker AddressRange::AddressRange(uintptr_t start, size_t size) : start(start), size(size) {}
6411*8975f5c5SAndroid Build Coastguard Worker AddressRange::~AddressRange() = default;
6412*8975f5c5SAndroid Build Coastguard Worker
end()6413*8975f5c5SAndroid Build Coastguard Worker uintptr_t AddressRange::end()
6414*8975f5c5SAndroid Build Coastguard Worker {
6415*8975f5c5SAndroid Build Coastguard Worker return start + size;
6416*8975f5c5SAndroid Build Coastguard Worker }
6417*8975f5c5SAndroid Build Coastguard Worker
IsTrackedPerContext(ResourceIDType type)6418*8975f5c5SAndroid Build Coastguard Worker bool IsTrackedPerContext(ResourceIDType type)
6419*8975f5c5SAndroid Build Coastguard Worker {
6420*8975f5c5SAndroid Build Coastguard Worker // This helper function informs us which context-local (not shared) objects are tracked
6421*8975f5c5SAndroid Build Coastguard Worker // with per-context object maps.
6422*8975f5c5SAndroid Build Coastguard Worker if (IsSharedObjectResource(type))
6423*8975f5c5SAndroid Build Coastguard Worker {
6424*8975f5c5SAndroid Build Coastguard Worker return false;
6425*8975f5c5SAndroid Build Coastguard Worker }
6426*8975f5c5SAndroid Build Coastguard Worker
6427*8975f5c5SAndroid Build Coastguard Worker // TODO (https://issuetracker.google.com/169868803): Remaining context-local resources (VAOs,
6428*8975f5c5SAndroid Build Coastguard Worker // PPOs, Transform Feedback Objects, and Query Objects) must also tracked per-context. Once all
6429*8975f5c5SAndroid Build Coastguard Worker // per-context resource handling is correctly updated then this function can be replaced with
6430*8975f5c5SAndroid Build Coastguard Worker // !IsSharedObjectResource().
6431*8975f5c5SAndroid Build Coastguard Worker switch (type)
6432*8975f5c5SAndroid Build Coastguard Worker {
6433*8975f5c5SAndroid Build Coastguard Worker case ResourceIDType::Framebuffer:
6434*8975f5c5SAndroid Build Coastguard Worker return true;
6435*8975f5c5SAndroid Build Coastguard Worker
6436*8975f5c5SAndroid Build Coastguard Worker default:
6437*8975f5c5SAndroid Build Coastguard Worker return false;
6438*8975f5c5SAndroid Build Coastguard Worker }
6439*8975f5c5SAndroid Build Coastguard Worker }
6440*8975f5c5SAndroid Build Coastguard Worker
CoherentBuffer(uintptr_t start,size_t size,size_t pageSize,bool isShadowMemoryEnabled)6441*8975f5c5SAndroid Build Coastguard Worker CoherentBuffer::CoherentBuffer(uintptr_t start,
6442*8975f5c5SAndroid Build Coastguard Worker size_t size,
6443*8975f5c5SAndroid Build Coastguard Worker size_t pageSize,
6444*8975f5c5SAndroid Build Coastguard Worker bool isShadowMemoryEnabled)
6445*8975f5c5SAndroid Build Coastguard Worker : mPageSize(pageSize),
6446*8975f5c5SAndroid Build Coastguard Worker mShadowMemoryEnabled(isShadowMemoryEnabled),
6447*8975f5c5SAndroid Build Coastguard Worker mBufferStart(start),
6448*8975f5c5SAndroid Build Coastguard Worker mShadowMemory(nullptr),
6449*8975f5c5SAndroid Build Coastguard Worker mShadowDirty(false)
6450*8975f5c5SAndroid Build Coastguard Worker {
6451*8975f5c5SAndroid Build Coastguard Worker if (mShadowMemoryEnabled)
6452*8975f5c5SAndroid Build Coastguard Worker {
6453*8975f5c5SAndroid Build Coastguard Worker // Shadow memory needs to have at least the size of one page, to not protect outside.
6454*8975f5c5SAndroid Build Coastguard Worker size_t numShadowPages = (size / pageSize) + 1;
6455*8975f5c5SAndroid Build Coastguard Worker mShadowMemory = AlignedAlloc(numShadowPages * pageSize, pageSize);
6456*8975f5c5SAndroid Build Coastguard Worker ASSERT(mShadowMemory != nullptr);
6457*8975f5c5SAndroid Build Coastguard Worker start = reinterpret_cast<uintptr_t>(mShadowMemory);
6458*8975f5c5SAndroid Build Coastguard Worker }
6459*8975f5c5SAndroid Build Coastguard Worker
6460*8975f5c5SAndroid Build Coastguard Worker mRange.start = start;
6461*8975f5c5SAndroid Build Coastguard Worker mRange.size = size;
6462*8975f5c5SAndroid Build Coastguard Worker mProtectionRange.start = rx::roundDownPow2(start, pageSize);
6463*8975f5c5SAndroid Build Coastguard Worker
6464*8975f5c5SAndroid Build Coastguard Worker uintptr_t protectionEnd = rx::roundUpPow2(start + size, pageSize);
6465*8975f5c5SAndroid Build Coastguard Worker
6466*8975f5c5SAndroid Build Coastguard Worker mProtectionRange.size = protectionEnd - mProtectionRange.start;
6467*8975f5c5SAndroid Build Coastguard Worker mPageCount = mProtectionRange.size / pageSize;
6468*8975f5c5SAndroid Build Coastguard Worker
6469*8975f5c5SAndroid Build Coastguard Worker mProtectionStartPage = mProtectionRange.start / mPageSize;
6470*8975f5c5SAndroid Build Coastguard Worker mProtectionEndPage = mProtectionStartPage + mPageCount;
6471*8975f5c5SAndroid Build Coastguard Worker
6472*8975f5c5SAndroid Build Coastguard Worker mDirtyPages = std::vector<bool>(mPageCount);
6473*8975f5c5SAndroid Build Coastguard Worker mDirtyPages.assign(mPageCount, true);
6474*8975f5c5SAndroid Build Coastguard Worker }
6475*8975f5c5SAndroid Build Coastguard Worker
getDirtyPageRanges()6476*8975f5c5SAndroid Build Coastguard Worker std::vector<PageRange> CoherentBuffer::getDirtyPageRanges()
6477*8975f5c5SAndroid Build Coastguard Worker {
6478*8975f5c5SAndroid Build Coastguard Worker std::vector<PageRange> dirtyPageRanges;
6479*8975f5c5SAndroid Build Coastguard Worker
6480*8975f5c5SAndroid Build Coastguard Worker bool inDirty = false;
6481*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < mPageCount; i++)
6482*8975f5c5SAndroid Build Coastguard Worker {
6483*8975f5c5SAndroid Build Coastguard Worker if (!inDirty && mDirtyPages[i])
6484*8975f5c5SAndroid Build Coastguard Worker {
6485*8975f5c5SAndroid Build Coastguard Worker // Found start of a dirty range
6486*8975f5c5SAndroid Build Coastguard Worker inDirty = true;
6487*8975f5c5SAndroid Build Coastguard Worker // Set end page as last page initially
6488*8975f5c5SAndroid Build Coastguard Worker dirtyPageRanges.push_back(PageRange(i, mPageCount));
6489*8975f5c5SAndroid Build Coastguard Worker }
6490*8975f5c5SAndroid Build Coastguard Worker else if (inDirty && !mDirtyPages[i])
6491*8975f5c5SAndroid Build Coastguard Worker {
6492*8975f5c5SAndroid Build Coastguard Worker // Found end of a dirty range
6493*8975f5c5SAndroid Build Coastguard Worker inDirty = false;
6494*8975f5c5SAndroid Build Coastguard Worker dirtyPageRanges.back().end = i;
6495*8975f5c5SAndroid Build Coastguard Worker }
6496*8975f5c5SAndroid Build Coastguard Worker }
6497*8975f5c5SAndroid Build Coastguard Worker
6498*8975f5c5SAndroid Build Coastguard Worker return dirtyPageRanges;
6499*8975f5c5SAndroid Build Coastguard Worker }
6500*8975f5c5SAndroid Build Coastguard Worker
getRange()6501*8975f5c5SAndroid Build Coastguard Worker AddressRange CoherentBuffer::getRange()
6502*8975f5c5SAndroid Build Coastguard Worker {
6503*8975f5c5SAndroid Build Coastguard Worker return mRange;
6504*8975f5c5SAndroid Build Coastguard Worker }
6505*8975f5c5SAndroid Build Coastguard Worker
getDirtyAddressRange(const PageRange & dirtyPageRange)6506*8975f5c5SAndroid Build Coastguard Worker AddressRange CoherentBuffer::getDirtyAddressRange(const PageRange &dirtyPageRange)
6507*8975f5c5SAndroid Build Coastguard Worker {
6508*8975f5c5SAndroid Build Coastguard Worker AddressRange range;
6509*8975f5c5SAndroid Build Coastguard Worker
6510*8975f5c5SAndroid Build Coastguard Worker if (dirtyPageRange.start == 0)
6511*8975f5c5SAndroid Build Coastguard Worker {
6512*8975f5c5SAndroid Build Coastguard Worker // First page, use non page aligned buffer start.
6513*8975f5c5SAndroid Build Coastguard Worker range.start = mRange.start;
6514*8975f5c5SAndroid Build Coastguard Worker }
6515*8975f5c5SAndroid Build Coastguard Worker else
6516*8975f5c5SAndroid Build Coastguard Worker {
6517*8975f5c5SAndroid Build Coastguard Worker range.start = mProtectionRange.start + dirtyPageRange.start * mPageSize;
6518*8975f5c5SAndroid Build Coastguard Worker }
6519*8975f5c5SAndroid Build Coastguard Worker
6520*8975f5c5SAndroid Build Coastguard Worker if (dirtyPageRange.end == mPageCount)
6521*8975f5c5SAndroid Build Coastguard Worker {
6522*8975f5c5SAndroid Build Coastguard Worker // Last page, use non page aligned buffer end.
6523*8975f5c5SAndroid Build Coastguard Worker range.size = mRange.end() - range.start;
6524*8975f5c5SAndroid Build Coastguard Worker }
6525*8975f5c5SAndroid Build Coastguard Worker else
6526*8975f5c5SAndroid Build Coastguard Worker {
6527*8975f5c5SAndroid Build Coastguard Worker range.size = (dirtyPageRange.end - dirtyPageRange.start) * mPageSize;
6528*8975f5c5SAndroid Build Coastguard Worker // This occurs when a buffer occupies 2 pages, but is smaller than a page.
6529*8975f5c5SAndroid Build Coastguard Worker if (mRange.end() < range.end())
6530*8975f5c5SAndroid Build Coastguard Worker {
6531*8975f5c5SAndroid Build Coastguard Worker range.size = mRange.end() - range.start;
6532*8975f5c5SAndroid Build Coastguard Worker }
6533*8975f5c5SAndroid Build Coastguard Worker }
6534*8975f5c5SAndroid Build Coastguard Worker
6535*8975f5c5SAndroid Build Coastguard Worker // Dirty range must be in buffer
6536*8975f5c5SAndroid Build Coastguard Worker ASSERT(range.start >= mRange.start && mRange.end() >= range.end());
6537*8975f5c5SAndroid Build Coastguard Worker
6538*8975f5c5SAndroid Build Coastguard Worker return range;
6539*8975f5c5SAndroid Build Coastguard Worker }
6540*8975f5c5SAndroid Build Coastguard Worker
~CoherentBuffer()6541*8975f5c5SAndroid Build Coastguard Worker CoherentBuffer::~CoherentBuffer()
6542*8975f5c5SAndroid Build Coastguard Worker {
6543*8975f5c5SAndroid Build Coastguard Worker if (mShadowMemory != nullptr)
6544*8975f5c5SAndroid Build Coastguard Worker {
6545*8975f5c5SAndroid Build Coastguard Worker AlignedFree(mShadowMemory);
6546*8975f5c5SAndroid Build Coastguard Worker }
6547*8975f5c5SAndroid Build Coastguard Worker }
6548*8975f5c5SAndroid Build Coastguard Worker
isDirty()6549*8975f5c5SAndroid Build Coastguard Worker bool CoherentBuffer::isDirty()
6550*8975f5c5SAndroid Build Coastguard Worker {
6551*8975f5c5SAndroid Build Coastguard Worker return std::find(mDirtyPages.begin(), mDirtyPages.end(), true) != mDirtyPages.end();
6552*8975f5c5SAndroid Build Coastguard Worker }
6553*8975f5c5SAndroid Build Coastguard Worker
contains(size_t page,size_t * relativePage)6554*8975f5c5SAndroid Build Coastguard Worker bool CoherentBuffer::contains(size_t page, size_t *relativePage)
6555*8975f5c5SAndroid Build Coastguard Worker {
6556*8975f5c5SAndroid Build Coastguard Worker bool isInProtectionRange = page >= mProtectionStartPage && page < mProtectionEndPage;
6557*8975f5c5SAndroid Build Coastguard Worker if (!isInProtectionRange)
6558*8975f5c5SAndroid Build Coastguard Worker {
6559*8975f5c5SAndroid Build Coastguard Worker return false;
6560*8975f5c5SAndroid Build Coastguard Worker }
6561*8975f5c5SAndroid Build Coastguard Worker
6562*8975f5c5SAndroid Build Coastguard Worker *relativePage = page - mProtectionStartPage;
6563*8975f5c5SAndroid Build Coastguard Worker
6564*8975f5c5SAndroid Build Coastguard Worker ASSERT(page >= mProtectionStartPage);
6565*8975f5c5SAndroid Build Coastguard Worker
6566*8975f5c5SAndroid Build Coastguard Worker return true;
6567*8975f5c5SAndroid Build Coastguard Worker }
6568*8975f5c5SAndroid Build Coastguard Worker
protectPageRange(const PageRange & pageRange)6569*8975f5c5SAndroid Build Coastguard Worker void CoherentBuffer::protectPageRange(const PageRange &pageRange)
6570*8975f5c5SAndroid Build Coastguard Worker {
6571*8975f5c5SAndroid Build Coastguard Worker for (size_t i = pageRange.start; i < pageRange.end; i++)
6572*8975f5c5SAndroid Build Coastguard Worker {
6573*8975f5c5SAndroid Build Coastguard Worker setDirty(i, false);
6574*8975f5c5SAndroid Build Coastguard Worker }
6575*8975f5c5SAndroid Build Coastguard Worker }
6576*8975f5c5SAndroid Build Coastguard Worker
protectAll()6577*8975f5c5SAndroid Build Coastguard Worker void CoherentBuffer::protectAll()
6578*8975f5c5SAndroid Build Coastguard Worker {
6579*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < mPageCount; i++)
6580*8975f5c5SAndroid Build Coastguard Worker {
6581*8975f5c5SAndroid Build Coastguard Worker setDirty(i, false);
6582*8975f5c5SAndroid Build Coastguard Worker }
6583*8975f5c5SAndroid Build Coastguard Worker }
6584*8975f5c5SAndroid Build Coastguard Worker
updateBufferMemory()6585*8975f5c5SAndroid Build Coastguard Worker void CoherentBuffer::updateBufferMemory()
6586*8975f5c5SAndroid Build Coastguard Worker {
6587*8975f5c5SAndroid Build Coastguard Worker memcpy(reinterpret_cast<void *>(mBufferStart), reinterpret_cast<void *>(mRange.start),
6588*8975f5c5SAndroid Build Coastguard Worker mRange.size);
6589*8975f5c5SAndroid Build Coastguard Worker }
6590*8975f5c5SAndroid Build Coastguard Worker
updateShadowMemory()6591*8975f5c5SAndroid Build Coastguard Worker void CoherentBuffer::updateShadowMemory()
6592*8975f5c5SAndroid Build Coastguard Worker {
6593*8975f5c5SAndroid Build Coastguard Worker memcpy(reinterpret_cast<void *>(mRange.start), reinterpret_cast<void *>(mBufferStart),
6594*8975f5c5SAndroid Build Coastguard Worker mRange.size);
6595*8975f5c5SAndroid Build Coastguard Worker mShadowDirty = false;
6596*8975f5c5SAndroid Build Coastguard Worker }
6597*8975f5c5SAndroid Build Coastguard Worker
setDirty(size_t relativePage,bool dirty)6598*8975f5c5SAndroid Build Coastguard Worker void CoherentBuffer::setDirty(size_t relativePage, bool dirty)
6599*8975f5c5SAndroid Build Coastguard Worker {
6600*8975f5c5SAndroid Build Coastguard Worker if (mDirtyPages[relativePage] == dirty)
6601*8975f5c5SAndroid Build Coastguard Worker {
6602*8975f5c5SAndroid Build Coastguard Worker // The page is already set.
6603*8975f5c5SAndroid Build Coastguard Worker // This can happen when tracked buffers overlap in a page.
6604*8975f5c5SAndroid Build Coastguard Worker return;
6605*8975f5c5SAndroid Build Coastguard Worker }
6606*8975f5c5SAndroid Build Coastguard Worker
6607*8975f5c5SAndroid Build Coastguard Worker uintptr_t pageStart = mProtectionRange.start + relativePage * mPageSize;
6608*8975f5c5SAndroid Build Coastguard Worker
6609*8975f5c5SAndroid Build Coastguard Worker // Last page end must be the same as protection end
6610*8975f5c5SAndroid Build Coastguard Worker if (relativePage + 1 == mPageCount)
6611*8975f5c5SAndroid Build Coastguard Worker {
6612*8975f5c5SAndroid Build Coastguard Worker ASSERT(mProtectionRange.end() == pageStart + mPageSize);
6613*8975f5c5SAndroid Build Coastguard Worker }
6614*8975f5c5SAndroid Build Coastguard Worker
6615*8975f5c5SAndroid Build Coastguard Worker bool ret;
6616*8975f5c5SAndroid Build Coastguard Worker if (dirty)
6617*8975f5c5SAndroid Build Coastguard Worker {
6618*8975f5c5SAndroid Build Coastguard Worker ret = UnprotectMemory(pageStart, mPageSize);
6619*8975f5c5SAndroid Build Coastguard Worker }
6620*8975f5c5SAndroid Build Coastguard Worker else
6621*8975f5c5SAndroid Build Coastguard Worker {
6622*8975f5c5SAndroid Build Coastguard Worker ret = ProtectMemory(pageStart, mPageSize);
6623*8975f5c5SAndroid Build Coastguard Worker }
6624*8975f5c5SAndroid Build Coastguard Worker
6625*8975f5c5SAndroid Build Coastguard Worker if (!ret)
6626*8975f5c5SAndroid Build Coastguard Worker {
6627*8975f5c5SAndroid Build Coastguard Worker ERR() << "Could not set protection for buffer page " << relativePage << " at "
6628*8975f5c5SAndroid Build Coastguard Worker << reinterpret_cast<void *>(pageStart) << " with size " << mPageSize;
6629*8975f5c5SAndroid Build Coastguard Worker }
6630*8975f5c5SAndroid Build Coastguard Worker mDirtyPages[relativePage] = dirty;
6631*8975f5c5SAndroid Build Coastguard Worker }
6632*8975f5c5SAndroid Build Coastguard Worker
removeProtection(PageSharingType sharingType)6633*8975f5c5SAndroid Build Coastguard Worker void CoherentBuffer::removeProtection(PageSharingType sharingType)
6634*8975f5c5SAndroid Build Coastguard Worker {
6635*8975f5c5SAndroid Build Coastguard Worker uintptr_t start = mProtectionRange.start;
6636*8975f5c5SAndroid Build Coastguard Worker size_t size = mProtectionRange.size;
6637*8975f5c5SAndroid Build Coastguard Worker
6638*8975f5c5SAndroid Build Coastguard Worker switch (sharingType)
6639*8975f5c5SAndroid Build Coastguard Worker {
6640*8975f5c5SAndroid Build Coastguard Worker case PageSharingType::FirstShared:
6641*8975f5c5SAndroid Build Coastguard Worker case PageSharingType::FirstAndLastShared:
6642*8975f5c5SAndroid Build Coastguard Worker start += mPageSize;
6643*8975f5c5SAndroid Build Coastguard Worker break;
6644*8975f5c5SAndroid Build Coastguard Worker default:
6645*8975f5c5SAndroid Build Coastguard Worker break;
6646*8975f5c5SAndroid Build Coastguard Worker }
6647*8975f5c5SAndroid Build Coastguard Worker
6648*8975f5c5SAndroid Build Coastguard Worker switch (sharingType)
6649*8975f5c5SAndroid Build Coastguard Worker {
6650*8975f5c5SAndroid Build Coastguard Worker case PageSharingType::FirstShared:
6651*8975f5c5SAndroid Build Coastguard Worker case PageSharingType::LastShared:
6652*8975f5c5SAndroid Build Coastguard Worker size -= mPageSize;
6653*8975f5c5SAndroid Build Coastguard Worker break;
6654*8975f5c5SAndroid Build Coastguard Worker case PageSharingType::FirstAndLastShared:
6655*8975f5c5SAndroid Build Coastguard Worker size -= (2 * mPageSize);
6656*8975f5c5SAndroid Build Coastguard Worker break;
6657*8975f5c5SAndroid Build Coastguard Worker default:
6658*8975f5c5SAndroid Build Coastguard Worker break;
6659*8975f5c5SAndroid Build Coastguard Worker }
6660*8975f5c5SAndroid Build Coastguard Worker
6661*8975f5c5SAndroid Build Coastguard Worker if (size == 0)
6662*8975f5c5SAndroid Build Coastguard Worker {
6663*8975f5c5SAndroid Build Coastguard Worker return;
6664*8975f5c5SAndroid Build Coastguard Worker }
6665*8975f5c5SAndroid Build Coastguard Worker
6666*8975f5c5SAndroid Build Coastguard Worker if (!UnprotectMemory(start, size))
6667*8975f5c5SAndroid Build Coastguard Worker {
6668*8975f5c5SAndroid Build Coastguard Worker ERR() << "Could not remove protection for buffer at " << start << " with size " << size;
6669*8975f5c5SAndroid Build Coastguard Worker }
6670*8975f5c5SAndroid Build Coastguard Worker }
6671*8975f5c5SAndroid Build Coastguard Worker
canProtectDirectly(gl::Context * context)6672*8975f5c5SAndroid Build Coastguard Worker bool CoherentBufferTracker::canProtectDirectly(gl::Context *context)
6673*8975f5c5SAndroid Build Coastguard Worker {
6674*8975f5c5SAndroid Build Coastguard Worker gl::BufferID bufferId = context->createBuffer();
6675*8975f5c5SAndroid Build Coastguard Worker
6676*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding targetPacked = gl::BufferBinding::Array;
6677*8975f5c5SAndroid Build Coastguard Worker context->bindBuffer(targetPacked, bufferId);
6678*8975f5c5SAndroid Build Coastguard Worker
6679*8975f5c5SAndroid Build Coastguard Worker // Allocate 2 pages so we will always have a full aligned page to protect
6680*8975f5c5SAndroid Build Coastguard Worker GLsizei size = static_cast<GLsizei>(mPageSize * 2);
6681*8975f5c5SAndroid Build Coastguard Worker
6682*8975f5c5SAndroid Build Coastguard Worker context->bufferStorage(targetPacked, size, nullptr,
6683*8975f5c5SAndroid Build Coastguard Worker GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT |
6684*8975f5c5SAndroid Build Coastguard Worker GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
6685*8975f5c5SAndroid Build Coastguard Worker
6686*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = context->getBuffer(bufferId);
6687*8975f5c5SAndroid Build Coastguard Worker
6688*8975f5c5SAndroid Build Coastguard Worker angle::Result result = buffer->mapRange(
6689*8975f5c5SAndroid Build Coastguard Worker context, 0, size, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
6690*8975f5c5SAndroid Build Coastguard Worker if (result != angle::Result::Continue)
6691*8975f5c5SAndroid Build Coastguard Worker {
6692*8975f5c5SAndroid Build Coastguard Worker ERR() << "Failed to mapRange of buffer.";
6693*8975f5c5SAndroid Build Coastguard Worker }
6694*8975f5c5SAndroid Build Coastguard Worker
6695*8975f5c5SAndroid Build Coastguard Worker void *map = buffer->getMapPointer();
6696*8975f5c5SAndroid Build Coastguard Worker if (map == nullptr)
6697*8975f5c5SAndroid Build Coastguard Worker {
6698*8975f5c5SAndroid Build Coastguard Worker ERR() << "Failed to getMapPointer of buffer.";
6699*8975f5c5SAndroid Build Coastguard Worker }
6700*8975f5c5SAndroid Build Coastguard Worker
6701*8975f5c5SAndroid Build Coastguard Worker // Test mprotect
6702*8975f5c5SAndroid Build Coastguard Worker auto start = reinterpret_cast<uintptr_t>(map);
6703*8975f5c5SAndroid Build Coastguard Worker
6704*8975f5c5SAndroid Build Coastguard Worker // Only protect a whole page inside the allocated memory
6705*8975f5c5SAndroid Build Coastguard Worker uintptr_t protectionStart = rx::roundUpPow2(start, mPageSize);
6706*8975f5c5SAndroid Build Coastguard Worker uintptr_t protectionEnd = protectionStart + mPageSize;
6707*8975f5c5SAndroid Build Coastguard Worker
6708*8975f5c5SAndroid Build Coastguard Worker ASSERT(protectionStart < protectionEnd);
6709*8975f5c5SAndroid Build Coastguard Worker
6710*8975f5c5SAndroid Build Coastguard Worker angle::PageFaultCallback callback = [](uintptr_t address) {
6711*8975f5c5SAndroid Build Coastguard Worker return angle::PageFaultHandlerRangeType::InRange;
6712*8975f5c5SAndroid Build Coastguard Worker };
6713*8975f5c5SAndroid Build Coastguard Worker
6714*8975f5c5SAndroid Build Coastguard Worker std::unique_ptr<angle::PageFaultHandler> handler(CreatePageFaultHandler(callback));
6715*8975f5c5SAndroid Build Coastguard Worker
6716*8975f5c5SAndroid Build Coastguard Worker if (!handler->enable())
6717*8975f5c5SAndroid Build Coastguard Worker {
6718*8975f5c5SAndroid Build Coastguard Worker GLboolean unmapResult;
6719*8975f5c5SAndroid Build Coastguard Worker if (buffer->unmap(context, &unmapResult) != angle::Result::Continue)
6720*8975f5c5SAndroid Build Coastguard Worker {
6721*8975f5c5SAndroid Build Coastguard Worker ERR() << "Could not unmap buffer.";
6722*8975f5c5SAndroid Build Coastguard Worker }
6723*8975f5c5SAndroid Build Coastguard Worker context->bindBuffer(targetPacked, {0});
6724*8975f5c5SAndroid Build Coastguard Worker
6725*8975f5c5SAndroid Build Coastguard Worker // Page fault handler could not be enabled, memory can't be protected directly.
6726*8975f5c5SAndroid Build Coastguard Worker return false;
6727*8975f5c5SAndroid Build Coastguard Worker }
6728*8975f5c5SAndroid Build Coastguard Worker
6729*8975f5c5SAndroid Build Coastguard Worker size_t protectionSize = protectionEnd - protectionStart;
6730*8975f5c5SAndroid Build Coastguard Worker
6731*8975f5c5SAndroid Build Coastguard Worker ASSERT(protectionSize == mPageSize);
6732*8975f5c5SAndroid Build Coastguard Worker
6733*8975f5c5SAndroid Build Coastguard Worker bool canProtect = angle::ProtectMemory(protectionStart, protectionSize);
6734*8975f5c5SAndroid Build Coastguard Worker if (canProtect)
6735*8975f5c5SAndroid Build Coastguard Worker {
6736*8975f5c5SAndroid Build Coastguard Worker angle::UnprotectMemory(protectionStart, protectionSize);
6737*8975f5c5SAndroid Build Coastguard Worker }
6738*8975f5c5SAndroid Build Coastguard Worker
6739*8975f5c5SAndroid Build Coastguard Worker // Clean up
6740*8975f5c5SAndroid Build Coastguard Worker handler->disable();
6741*8975f5c5SAndroid Build Coastguard Worker
6742*8975f5c5SAndroid Build Coastguard Worker GLboolean unmapResult;
6743*8975f5c5SAndroid Build Coastguard Worker if (buffer->unmap(context, &unmapResult) != angle::Result::Continue)
6744*8975f5c5SAndroid Build Coastguard Worker {
6745*8975f5c5SAndroid Build Coastguard Worker ERR() << "Could not unmap buffer.";
6746*8975f5c5SAndroid Build Coastguard Worker }
6747*8975f5c5SAndroid Build Coastguard Worker context->bindBuffer(targetPacked, {0});
6748*8975f5c5SAndroid Build Coastguard Worker context->deleteBuffer(buffer->id());
6749*8975f5c5SAndroid Build Coastguard Worker
6750*8975f5c5SAndroid Build Coastguard Worker return canProtect;
6751*8975f5c5SAndroid Build Coastguard Worker }
6752*8975f5c5SAndroid Build Coastguard Worker
CoherentBufferTracker()6753*8975f5c5SAndroid Build Coastguard Worker CoherentBufferTracker::CoherentBufferTracker() : mEnabled(false), mShadowMemoryEnabled(false)
6754*8975f5c5SAndroid Build Coastguard Worker {
6755*8975f5c5SAndroid Build Coastguard Worker mPageSize = GetPageSize();
6756*8975f5c5SAndroid Build Coastguard Worker }
6757*8975f5c5SAndroid Build Coastguard Worker
~CoherentBufferTracker()6758*8975f5c5SAndroid Build Coastguard Worker CoherentBufferTracker::~CoherentBufferTracker()
6759*8975f5c5SAndroid Build Coastguard Worker {
6760*8975f5c5SAndroid Build Coastguard Worker disable();
6761*8975f5c5SAndroid Build Coastguard Worker }
6762*8975f5c5SAndroid Build Coastguard Worker
handleWrite(uintptr_t address)6763*8975f5c5SAndroid Build Coastguard Worker PageFaultHandlerRangeType CoherentBufferTracker::handleWrite(uintptr_t address)
6764*8975f5c5SAndroid Build Coastguard Worker {
6765*8975f5c5SAndroid Build Coastguard Worker std::lock_guard<angle::SimpleMutex> lock(mMutex);
6766*8975f5c5SAndroid Build Coastguard Worker auto pagesInBuffers = getBufferPagesForAddress(address);
6767*8975f5c5SAndroid Build Coastguard Worker
6768*8975f5c5SAndroid Build Coastguard Worker if (pagesInBuffers.empty())
6769*8975f5c5SAndroid Build Coastguard Worker {
6770*8975f5c5SAndroid Build Coastguard Worker ERR() << "Didn't find a tracked buffer containing " << reinterpret_cast<void *>(address);
6771*8975f5c5SAndroid Build Coastguard Worker }
6772*8975f5c5SAndroid Build Coastguard Worker
6773*8975f5c5SAndroid Build Coastguard Worker for (const auto &page : pagesInBuffers)
6774*8975f5c5SAndroid Build Coastguard Worker {
6775*8975f5c5SAndroid Build Coastguard Worker std::shared_ptr<CoherentBuffer> buffer = page.first;
6776*8975f5c5SAndroid Build Coastguard Worker size_t relativePage = page.second;
6777*8975f5c5SAndroid Build Coastguard Worker buffer->setDirty(relativePage, true);
6778*8975f5c5SAndroid Build Coastguard Worker }
6779*8975f5c5SAndroid Build Coastguard Worker
6780*8975f5c5SAndroid Build Coastguard Worker return pagesInBuffers.empty() ? PageFaultHandlerRangeType::OutOfRange
6781*8975f5c5SAndroid Build Coastguard Worker : PageFaultHandlerRangeType::InRange;
6782*8975f5c5SAndroid Build Coastguard Worker }
6783*8975f5c5SAndroid Build Coastguard Worker
getBufferPagesForAddress(uintptr_t address)6784*8975f5c5SAndroid Build Coastguard Worker HashMap<std::shared_ptr<CoherentBuffer>, size_t> CoherentBufferTracker::getBufferPagesForAddress(
6785*8975f5c5SAndroid Build Coastguard Worker uintptr_t address)
6786*8975f5c5SAndroid Build Coastguard Worker {
6787*8975f5c5SAndroid Build Coastguard Worker HashMap<std::shared_ptr<CoherentBuffer>, size_t> foundPages;
6788*8975f5c5SAndroid Build Coastguard Worker
6789*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_ANDROID)
6790*8975f5c5SAndroid Build Coastguard Worker size_t page;
6791*8975f5c5SAndroid Build Coastguard Worker if (mShadowMemoryEnabled)
6792*8975f5c5SAndroid Build Coastguard Worker {
6793*8975f5c5SAndroid Build Coastguard Worker // Starting with Android 11 heap pointers get a tag which is stripped by the POSIX mprotect
6794*8975f5c5SAndroid Build Coastguard Worker // callback. We need to add this tag manually to the untagged pointer in order to determine
6795*8975f5c5SAndroid Build Coastguard Worker // the corresponding page.
6796*8975f5c5SAndroid Build Coastguard Worker // See: https://source.android.com/docs/security/test/tagged-pointers
6797*8975f5c5SAndroid Build Coastguard Worker // TODO(http://anglebug.com/42265874): Determine when heap pointer tagging is not enabled.
6798*8975f5c5SAndroid Build Coastguard Worker constexpr unsigned long long POINTER_TAG = 0xb400000000000000;
6799*8975f5c5SAndroid Build Coastguard Worker unsigned long long taggedAddress = address | POINTER_TAG;
6800*8975f5c5SAndroid Build Coastguard Worker page = static_cast<size_t>(taggedAddress / mPageSize);
6801*8975f5c5SAndroid Build Coastguard Worker }
6802*8975f5c5SAndroid Build Coastguard Worker else
6803*8975f5c5SAndroid Build Coastguard Worker {
6804*8975f5c5SAndroid Build Coastguard Worker // VMA allocated memory pointers are not tagged.
6805*8975f5c5SAndroid Build Coastguard Worker page = address / mPageSize;
6806*8975f5c5SAndroid Build Coastguard Worker }
6807*8975f5c5SAndroid Build Coastguard Worker #else
6808*8975f5c5SAndroid Build Coastguard Worker size_t page = address / mPageSize;
6809*8975f5c5SAndroid Build Coastguard Worker #endif
6810*8975f5c5SAndroid Build Coastguard Worker
6811*8975f5c5SAndroid Build Coastguard Worker for (const auto &pair : mBuffers)
6812*8975f5c5SAndroid Build Coastguard Worker {
6813*8975f5c5SAndroid Build Coastguard Worker std::shared_ptr<CoherentBuffer> buffer = pair.second;
6814*8975f5c5SAndroid Build Coastguard Worker size_t relativePage;
6815*8975f5c5SAndroid Build Coastguard Worker if (buffer->contains(page, &relativePage))
6816*8975f5c5SAndroid Build Coastguard Worker {
6817*8975f5c5SAndroid Build Coastguard Worker foundPages.insert(std::make_pair(buffer, relativePage));
6818*8975f5c5SAndroid Build Coastguard Worker }
6819*8975f5c5SAndroid Build Coastguard Worker }
6820*8975f5c5SAndroid Build Coastguard Worker
6821*8975f5c5SAndroid Build Coastguard Worker return foundPages;
6822*8975f5c5SAndroid Build Coastguard Worker }
6823*8975f5c5SAndroid Build Coastguard Worker
isDirty(gl::BufferID id)6824*8975f5c5SAndroid Build Coastguard Worker bool CoherentBufferTracker::isDirty(gl::BufferID id)
6825*8975f5c5SAndroid Build Coastguard Worker {
6826*8975f5c5SAndroid Build Coastguard Worker return mBuffers[id.value]->isDirty();
6827*8975f5c5SAndroid Build Coastguard Worker }
6828*8975f5c5SAndroid Build Coastguard Worker
enable()6829*8975f5c5SAndroid Build Coastguard Worker void CoherentBufferTracker::enable()
6830*8975f5c5SAndroid Build Coastguard Worker {
6831*8975f5c5SAndroid Build Coastguard Worker if (mEnabled)
6832*8975f5c5SAndroid Build Coastguard Worker {
6833*8975f5c5SAndroid Build Coastguard Worker return;
6834*8975f5c5SAndroid Build Coastguard Worker }
6835*8975f5c5SAndroid Build Coastguard Worker
6836*8975f5c5SAndroid Build Coastguard Worker PageFaultCallback callback = [this](uintptr_t address) { return handleWrite(address); };
6837*8975f5c5SAndroid Build Coastguard Worker
6838*8975f5c5SAndroid Build Coastguard Worker // This needs to be initialized after canProtectDirectly ran and can only be initialized once.
6839*8975f5c5SAndroid Build Coastguard Worker if (!mPageFaultHandler)
6840*8975f5c5SAndroid Build Coastguard Worker {
6841*8975f5c5SAndroid Build Coastguard Worker mPageFaultHandler = std::unique_ptr<PageFaultHandler>(CreatePageFaultHandler(callback));
6842*8975f5c5SAndroid Build Coastguard Worker }
6843*8975f5c5SAndroid Build Coastguard Worker
6844*8975f5c5SAndroid Build Coastguard Worker bool ret = mPageFaultHandler->enable();
6845*8975f5c5SAndroid Build Coastguard Worker if (ret)
6846*8975f5c5SAndroid Build Coastguard Worker {
6847*8975f5c5SAndroid Build Coastguard Worker mEnabled = true;
6848*8975f5c5SAndroid Build Coastguard Worker }
6849*8975f5c5SAndroid Build Coastguard Worker else
6850*8975f5c5SAndroid Build Coastguard Worker {
6851*8975f5c5SAndroid Build Coastguard Worker ERR() << "Could not enable page fault handler.";
6852*8975f5c5SAndroid Build Coastguard Worker }
6853*8975f5c5SAndroid Build Coastguard Worker }
6854*8975f5c5SAndroid Build Coastguard Worker
haveBuffer(gl::BufferID id)6855*8975f5c5SAndroid Build Coastguard Worker bool CoherentBufferTracker::haveBuffer(gl::BufferID id)
6856*8975f5c5SAndroid Build Coastguard Worker {
6857*8975f5c5SAndroid Build Coastguard Worker return mBuffers.find(id.value) != mBuffers.end();
6858*8975f5c5SAndroid Build Coastguard Worker }
6859*8975f5c5SAndroid Build Coastguard Worker
onEndFrame()6860*8975f5c5SAndroid Build Coastguard Worker void CoherentBufferTracker::onEndFrame()
6861*8975f5c5SAndroid Build Coastguard Worker {
6862*8975f5c5SAndroid Build Coastguard Worker std::lock_guard<angle::SimpleMutex> lock(mMutex);
6863*8975f5c5SAndroid Build Coastguard Worker
6864*8975f5c5SAndroid Build Coastguard Worker if (!mEnabled)
6865*8975f5c5SAndroid Build Coastguard Worker {
6866*8975f5c5SAndroid Build Coastguard Worker return;
6867*8975f5c5SAndroid Build Coastguard Worker }
6868*8975f5c5SAndroid Build Coastguard Worker
6869*8975f5c5SAndroid Build Coastguard Worker // Remove protection from all buffers
6870*8975f5c5SAndroid Build Coastguard Worker for (const auto &pair : mBuffers)
6871*8975f5c5SAndroid Build Coastguard Worker {
6872*8975f5c5SAndroid Build Coastguard Worker std::shared_ptr<CoherentBuffer> buffer = pair.second;
6873*8975f5c5SAndroid Build Coastguard Worker buffer->removeProtection(PageSharingType::NoneShared);
6874*8975f5c5SAndroid Build Coastguard Worker }
6875*8975f5c5SAndroid Build Coastguard Worker
6876*8975f5c5SAndroid Build Coastguard Worker disable();
6877*8975f5c5SAndroid Build Coastguard Worker }
6878*8975f5c5SAndroid Build Coastguard Worker
disable()6879*8975f5c5SAndroid Build Coastguard Worker void CoherentBufferTracker::disable()
6880*8975f5c5SAndroid Build Coastguard Worker {
6881*8975f5c5SAndroid Build Coastguard Worker if (!mEnabled)
6882*8975f5c5SAndroid Build Coastguard Worker {
6883*8975f5c5SAndroid Build Coastguard Worker return;
6884*8975f5c5SAndroid Build Coastguard Worker }
6885*8975f5c5SAndroid Build Coastguard Worker
6886*8975f5c5SAndroid Build Coastguard Worker if (mPageFaultHandler->disable())
6887*8975f5c5SAndroid Build Coastguard Worker {
6888*8975f5c5SAndroid Build Coastguard Worker mEnabled = false;
6889*8975f5c5SAndroid Build Coastguard Worker }
6890*8975f5c5SAndroid Build Coastguard Worker else
6891*8975f5c5SAndroid Build Coastguard Worker {
6892*8975f5c5SAndroid Build Coastguard Worker ERR() << "Could not disable page fault handler.";
6893*8975f5c5SAndroid Build Coastguard Worker }
6894*8975f5c5SAndroid Build Coastguard Worker
6895*8975f5c5SAndroid Build Coastguard Worker if (mShadowMemoryEnabled && mBuffers.size() > 0)
6896*8975f5c5SAndroid Build Coastguard Worker {
6897*8975f5c5SAndroid Build Coastguard Worker WARN() << "Disabling coherent buffer tracking while leaving shadow memory without "
6898*8975f5c5SAndroid Build Coastguard Worker "synchronization. Expect rendering artifacts after capture ends.";
6899*8975f5c5SAndroid Build Coastguard Worker }
6900*8975f5c5SAndroid Build Coastguard Worker }
6901*8975f5c5SAndroid Build Coastguard Worker
addBuffer(gl::BufferID id,uintptr_t start,size_t size)6902*8975f5c5SAndroid Build Coastguard Worker uintptr_t CoherentBufferTracker::addBuffer(gl::BufferID id, uintptr_t start, size_t size)
6903*8975f5c5SAndroid Build Coastguard Worker {
6904*8975f5c5SAndroid Build Coastguard Worker std::lock_guard<angle::SimpleMutex> lock(mMutex);
6905*8975f5c5SAndroid Build Coastguard Worker
6906*8975f5c5SAndroid Build Coastguard Worker if (haveBuffer(id))
6907*8975f5c5SAndroid Build Coastguard Worker {
6908*8975f5c5SAndroid Build Coastguard Worker auto buffer = mBuffers[id.value];
6909*8975f5c5SAndroid Build Coastguard Worker return buffer->getRange().start;
6910*8975f5c5SAndroid Build Coastguard Worker }
6911*8975f5c5SAndroid Build Coastguard Worker
6912*8975f5c5SAndroid Build Coastguard Worker auto buffer = std::make_shared<CoherentBuffer>(start, size, mPageSize, mShadowMemoryEnabled);
6913*8975f5c5SAndroid Build Coastguard Worker uintptr_t realOrShadowStart = buffer->getRange().start;
6914*8975f5c5SAndroid Build Coastguard Worker
6915*8975f5c5SAndroid Build Coastguard Worker mBuffers.insert(std::make_pair(id.value, std::move(buffer)));
6916*8975f5c5SAndroid Build Coastguard Worker
6917*8975f5c5SAndroid Build Coastguard Worker return realOrShadowStart;
6918*8975f5c5SAndroid Build Coastguard Worker }
6919*8975f5c5SAndroid Build Coastguard Worker
maybeUpdateShadowMemory()6920*8975f5c5SAndroid Build Coastguard Worker void CoherentBufferTracker::maybeUpdateShadowMemory()
6921*8975f5c5SAndroid Build Coastguard Worker {
6922*8975f5c5SAndroid Build Coastguard Worker for (const auto &pair : mBuffers)
6923*8975f5c5SAndroid Build Coastguard Worker {
6924*8975f5c5SAndroid Build Coastguard Worker std::shared_ptr<CoherentBuffer> cb = pair.second;
6925*8975f5c5SAndroid Build Coastguard Worker if (cb->isShadowDirty())
6926*8975f5c5SAndroid Build Coastguard Worker {
6927*8975f5c5SAndroid Build Coastguard Worker cb->removeProtection(PageSharingType::NoneShared);
6928*8975f5c5SAndroid Build Coastguard Worker cb->updateShadowMemory();
6929*8975f5c5SAndroid Build Coastguard Worker cb->protectAll();
6930*8975f5c5SAndroid Build Coastguard Worker }
6931*8975f5c5SAndroid Build Coastguard Worker }
6932*8975f5c5SAndroid Build Coastguard Worker }
6933*8975f5c5SAndroid Build Coastguard Worker
markAllShadowDirty()6934*8975f5c5SAndroid Build Coastguard Worker void CoherentBufferTracker::markAllShadowDirty()
6935*8975f5c5SAndroid Build Coastguard Worker {
6936*8975f5c5SAndroid Build Coastguard Worker for (const auto &pair : mBuffers)
6937*8975f5c5SAndroid Build Coastguard Worker {
6938*8975f5c5SAndroid Build Coastguard Worker std::shared_ptr<CoherentBuffer> cb = pair.second;
6939*8975f5c5SAndroid Build Coastguard Worker cb->markShadowDirty();
6940*8975f5c5SAndroid Build Coastguard Worker }
6941*8975f5c5SAndroid Build Coastguard Worker }
6942*8975f5c5SAndroid Build Coastguard Worker
doesBufferSharePage(gl::BufferID id)6943*8975f5c5SAndroid Build Coastguard Worker PageSharingType CoherentBufferTracker::doesBufferSharePage(gl::BufferID id)
6944*8975f5c5SAndroid Build Coastguard Worker {
6945*8975f5c5SAndroid Build Coastguard Worker bool firstPageShared = false;
6946*8975f5c5SAndroid Build Coastguard Worker bool lastPageShared = false;
6947*8975f5c5SAndroid Build Coastguard Worker
6948*8975f5c5SAndroid Build Coastguard Worker std::shared_ptr<CoherentBuffer> buffer = mBuffers[id.value];
6949*8975f5c5SAndroid Build Coastguard Worker
6950*8975f5c5SAndroid Build Coastguard Worker AddressRange range = buffer->getRange();
6951*8975f5c5SAndroid Build Coastguard Worker
6952*8975f5c5SAndroid Build Coastguard Worker size_t firstPage = range.start / mPageSize;
6953*8975f5c5SAndroid Build Coastguard Worker size_t lastPage = range.end() / mPageSize;
6954*8975f5c5SAndroid Build Coastguard Worker
6955*8975f5c5SAndroid Build Coastguard Worker for (const auto &pair : mBuffers)
6956*8975f5c5SAndroid Build Coastguard Worker {
6957*8975f5c5SAndroid Build Coastguard Worker gl::BufferID otherId = {pair.first};
6958*8975f5c5SAndroid Build Coastguard Worker if (otherId != id)
6959*8975f5c5SAndroid Build Coastguard Worker {
6960*8975f5c5SAndroid Build Coastguard Worker std::shared_ptr<CoherentBuffer> otherBuffer = pair.second;
6961*8975f5c5SAndroid Build Coastguard Worker size_t relativePage;
6962*8975f5c5SAndroid Build Coastguard Worker if (otherBuffer->contains(firstPage, &relativePage))
6963*8975f5c5SAndroid Build Coastguard Worker {
6964*8975f5c5SAndroid Build Coastguard Worker firstPageShared = true;
6965*8975f5c5SAndroid Build Coastguard Worker }
6966*8975f5c5SAndroid Build Coastguard Worker else if (otherBuffer->contains(lastPage, &relativePage))
6967*8975f5c5SAndroid Build Coastguard Worker {
6968*8975f5c5SAndroid Build Coastguard Worker lastPageShared = true;
6969*8975f5c5SAndroid Build Coastguard Worker }
6970*8975f5c5SAndroid Build Coastguard Worker }
6971*8975f5c5SAndroid Build Coastguard Worker }
6972*8975f5c5SAndroid Build Coastguard Worker
6973*8975f5c5SAndroid Build Coastguard Worker if (firstPageShared && !lastPageShared)
6974*8975f5c5SAndroid Build Coastguard Worker {
6975*8975f5c5SAndroid Build Coastguard Worker return PageSharingType::FirstShared;
6976*8975f5c5SAndroid Build Coastguard Worker }
6977*8975f5c5SAndroid Build Coastguard Worker else if (!firstPageShared && lastPageShared)
6978*8975f5c5SAndroid Build Coastguard Worker {
6979*8975f5c5SAndroid Build Coastguard Worker return PageSharingType::LastShared;
6980*8975f5c5SAndroid Build Coastguard Worker }
6981*8975f5c5SAndroid Build Coastguard Worker else if (firstPageShared && lastPageShared)
6982*8975f5c5SAndroid Build Coastguard Worker {
6983*8975f5c5SAndroid Build Coastguard Worker return PageSharingType::FirstAndLastShared;
6984*8975f5c5SAndroid Build Coastguard Worker }
6985*8975f5c5SAndroid Build Coastguard Worker else
6986*8975f5c5SAndroid Build Coastguard Worker {
6987*8975f5c5SAndroid Build Coastguard Worker return PageSharingType::NoneShared;
6988*8975f5c5SAndroid Build Coastguard Worker }
6989*8975f5c5SAndroid Build Coastguard Worker }
6990*8975f5c5SAndroid Build Coastguard Worker
removeBuffer(gl::BufferID id)6991*8975f5c5SAndroid Build Coastguard Worker void CoherentBufferTracker::removeBuffer(gl::BufferID id)
6992*8975f5c5SAndroid Build Coastguard Worker {
6993*8975f5c5SAndroid Build Coastguard Worker std::lock_guard<angle::SimpleMutex> lock(mMutex);
6994*8975f5c5SAndroid Build Coastguard Worker
6995*8975f5c5SAndroid Build Coastguard Worker if (!haveBuffer(id))
6996*8975f5c5SAndroid Build Coastguard Worker {
6997*8975f5c5SAndroid Build Coastguard Worker return;
6998*8975f5c5SAndroid Build Coastguard Worker }
6999*8975f5c5SAndroid Build Coastguard Worker
7000*8975f5c5SAndroid Build Coastguard Worker // Synchronize graphics buffer memory before the buffer is removed from the tracker.
7001*8975f5c5SAndroid Build Coastguard Worker if (mShadowMemoryEnabled)
7002*8975f5c5SAndroid Build Coastguard Worker {
7003*8975f5c5SAndroid Build Coastguard Worker mBuffers[id.value]->updateBufferMemory();
7004*8975f5c5SAndroid Build Coastguard Worker }
7005*8975f5c5SAndroid Build Coastguard Worker
7006*8975f5c5SAndroid Build Coastguard Worker // If the buffer shares pages with other tracked buffers,
7007*8975f5c5SAndroid Build Coastguard Worker // don't unprotect the overlapping pages.
7008*8975f5c5SAndroid Build Coastguard Worker PageSharingType sharingType = doesBufferSharePage(id);
7009*8975f5c5SAndroid Build Coastguard Worker mBuffers[id.value]->removeProtection(sharingType);
7010*8975f5c5SAndroid Build Coastguard Worker mBuffers.erase(id.value);
7011*8975f5c5SAndroid Build Coastguard Worker }
7012*8975f5c5SAndroid Build Coastguard Worker
maybeGetShadowMemoryPointer(gl::Buffer * buffer,GLsizeiptr length,GLbitfield access)7013*8975f5c5SAndroid Build Coastguard Worker void *FrameCaptureShared::maybeGetShadowMemoryPointer(gl::Buffer *buffer,
7014*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr length,
7015*8975f5c5SAndroid Build Coastguard Worker GLbitfield access)
7016*8975f5c5SAndroid Build Coastguard Worker {
7017*8975f5c5SAndroid Build Coastguard Worker if (!(access & GL_MAP_COHERENT_BIT_EXT) || !mCoherentBufferTracker.isShadowMemoryEnabled())
7018*8975f5c5SAndroid Build Coastguard Worker {
7019*8975f5c5SAndroid Build Coastguard Worker return buffer->getMapPointer();
7020*8975f5c5SAndroid Build Coastguard Worker }
7021*8975f5c5SAndroid Build Coastguard Worker
7022*8975f5c5SAndroid Build Coastguard Worker mCoherentBufferTracker.enable();
7023*8975f5c5SAndroid Build Coastguard Worker uintptr_t realMapPointer = reinterpret_cast<uintptr_t>(buffer->getMapPointer());
7024*8975f5c5SAndroid Build Coastguard Worker return (void *)mCoherentBufferTracker.addBuffer(buffer->id(), realMapPointer, length);
7025*8975f5c5SAndroid Build Coastguard Worker }
7026*8975f5c5SAndroid Build Coastguard Worker
determineMemoryProtectionSupport(gl::Context * context)7027*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::determineMemoryProtectionSupport(gl::Context *context)
7028*8975f5c5SAndroid Build Coastguard Worker {
7029*8975f5c5SAndroid Build Coastguard Worker // Skip this test if shadow memory was force enabled or shadow memory requirement was detected
7030*8975f5c5SAndroid Build Coastguard Worker // previously
7031*8975f5c5SAndroid Build Coastguard Worker if (mCoherentBufferTracker.isShadowMemoryEnabled())
7032*8975f5c5SAndroid Build Coastguard Worker {
7033*8975f5c5SAndroid Build Coastguard Worker return;
7034*8975f5c5SAndroid Build Coastguard Worker }
7035*8975f5c5SAndroid Build Coastguard Worker
7036*8975f5c5SAndroid Build Coastguard Worker // These known devices must use shadow memory
7037*8975f5c5SAndroid Build Coastguard Worker HashMap<std::string, std::vector<std::string>> denyList = {
7038*8975f5c5SAndroid Build Coastguard Worker {"Google", {"Pixel 6", "Pixel 6 Pro", "Pixel 6a", "Pixel 7", "Pixel 7 Pro"}},
7039*8975f5c5SAndroid Build Coastguard Worker };
7040*8975f5c5SAndroid Build Coastguard Worker
7041*8975f5c5SAndroid Build Coastguard Worker angle::SystemInfo info;
7042*8975f5c5SAndroid Build Coastguard Worker angle::GetSystemInfo(&info);
7043*8975f5c5SAndroid Build Coastguard Worker bool isDeviceDenyListed = false;
7044*8975f5c5SAndroid Build Coastguard Worker
7045*8975f5c5SAndroid Build Coastguard Worker if (rx::GetAndroidSDKVersion() < 34)
7046*8975f5c5SAndroid Build Coastguard Worker {
7047*8975f5c5SAndroid Build Coastguard Worker // Before Android 14, there was a bug in Mali based Pixel preventing mprotect
7048*8975f5c5SAndroid Build Coastguard Worker // on Vulkan surfaces. (https://b.corp.google.com/issues/269535398)
7049*8975f5c5SAndroid Build Coastguard Worker // Check the denylist in this case.
7050*8975f5c5SAndroid Build Coastguard Worker if (denyList.find(info.machineManufacturer) != denyList.end())
7051*8975f5c5SAndroid Build Coastguard Worker {
7052*8975f5c5SAndroid Build Coastguard Worker const std::vector<std::string> &models = denyList[info.machineManufacturer];
7053*8975f5c5SAndroid Build Coastguard Worker isDeviceDenyListed =
7054*8975f5c5SAndroid Build Coastguard Worker std::find(models.begin(), models.end(), info.machineModelName) != models.end();
7055*8975f5c5SAndroid Build Coastguard Worker }
7056*8975f5c5SAndroid Build Coastguard Worker }
7057*8975f5c5SAndroid Build Coastguard Worker
7058*8975f5c5SAndroid Build Coastguard Worker if (isDeviceDenyListed)
7059*8975f5c5SAndroid Build Coastguard Worker {
7060*8975f5c5SAndroid Build Coastguard Worker WARN() << "Direct memory protection not possible on deny listed device '"
7061*8975f5c5SAndroid Build Coastguard Worker << info.machineModelName
7062*8975f5c5SAndroid Build Coastguard Worker << "', enabling shadow memory for coherent buffer tracking.";
7063*8975f5c5SAndroid Build Coastguard Worker mCoherentBufferTracker.enableShadowMemory();
7064*8975f5c5SAndroid Build Coastguard Worker }
7065*8975f5c5SAndroid Build Coastguard Worker else
7066*8975f5c5SAndroid Build Coastguard Worker {
7067*8975f5c5SAndroid Build Coastguard Worker // Device is not on deny listed. Run a test if we actually can protect directly. Do this
7068*8975f5c5SAndroid Build Coastguard Worker // only on assertion enabled builds.
7069*8975f5c5SAndroid Build Coastguard Worker ASSERT(mCoherentBufferTracker.canProtectDirectly(context));
7070*8975f5c5SAndroid Build Coastguard Worker }
7071*8975f5c5SAndroid Build Coastguard Worker }
7072*8975f5c5SAndroid Build Coastguard Worker
trackBufferMapping(const gl::Context * context,CallCapture * call,gl::BufferID id,gl::Buffer * buffer,GLintptr offset,GLsizeiptr length,bool writable,bool coherent)7073*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::trackBufferMapping(const gl::Context *context,
7074*8975f5c5SAndroid Build Coastguard Worker CallCapture *call,
7075*8975f5c5SAndroid Build Coastguard Worker gl::BufferID id,
7076*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer,
7077*8975f5c5SAndroid Build Coastguard Worker GLintptr offset,
7078*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr length,
7079*8975f5c5SAndroid Build Coastguard Worker bool writable,
7080*8975f5c5SAndroid Build Coastguard Worker bool coherent)
7081*8975f5c5SAndroid Build Coastguard Worker {
7082*8975f5c5SAndroid Build Coastguard Worker // Track that the buffer was mapped
7083*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.setBufferMapped(context->id(), id.value);
7084*8975f5c5SAndroid Build Coastguard Worker
7085*8975f5c5SAndroid Build Coastguard Worker if (writable)
7086*8975f5c5SAndroid Build Coastguard Worker {
7087*8975f5c5SAndroid Build Coastguard Worker // If this buffer was mapped writable, we don't have any visibility into what
7088*8975f5c5SAndroid Build Coastguard Worker // happens to it. Therefore, remember the details about it, and we'll read it back
7089*8975f5c5SAndroid Build Coastguard Worker // on Unmap to repopulate it during replay.
7090*8975f5c5SAndroid Build Coastguard Worker mBufferDataMap[id] = std::make_pair(offset, length);
7091*8975f5c5SAndroid Build Coastguard Worker
7092*8975f5c5SAndroid Build Coastguard Worker // Track that this buffer was potentially modified
7093*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.getTrackedResource(context->id(), ResourceIDType::Buffer)
7094*8975f5c5SAndroid Build Coastguard Worker .setModifiedResource(id.value);
7095*8975f5c5SAndroid Build Coastguard Worker
7096*8975f5c5SAndroid Build Coastguard Worker // Track coherent buffer
7097*8975f5c5SAndroid Build Coastguard Worker // Check if capture is active to not initialize the coherent buffer tracker on the
7098*8975f5c5SAndroid Build Coastguard Worker // first coherent glMapBufferRange call.
7099*8975f5c5SAndroid Build Coastguard Worker if (coherent && isCaptureActive())
7100*8975f5c5SAndroid Build Coastguard Worker {
7101*8975f5c5SAndroid Build Coastguard Worker mCoherentBufferTracker.enable();
7102*8975f5c5SAndroid Build Coastguard Worker // When not using shadow memory, adding buffers to the tracking happens here instead of
7103*8975f5c5SAndroid Build Coastguard Worker // during mapping
7104*8975f5c5SAndroid Build Coastguard Worker if (!mCoherentBufferTracker.isShadowMemoryEnabled())
7105*8975f5c5SAndroid Build Coastguard Worker {
7106*8975f5c5SAndroid Build Coastguard Worker uintptr_t data = reinterpret_cast<uintptr_t>(buffer->getMapPointer());
7107*8975f5c5SAndroid Build Coastguard Worker mCoherentBufferTracker.addBuffer(id, data, length);
7108*8975f5c5SAndroid Build Coastguard Worker }
7109*8975f5c5SAndroid Build Coastguard Worker }
7110*8975f5c5SAndroid Build Coastguard Worker }
7111*8975f5c5SAndroid Build Coastguard Worker }
7112*8975f5c5SAndroid Build Coastguard Worker
trackTextureUpdate(const gl::Context * context,const CallCapture & call)7113*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::trackTextureUpdate(const gl::Context *context, const CallCapture &call)
7114*8975f5c5SAndroid Build Coastguard Worker {
7115*8975f5c5SAndroid Build Coastguard Worker int index = 0;
7116*8975f5c5SAndroid Build Coastguard Worker std::string paramName = "targetPacked";
7117*8975f5c5SAndroid Build Coastguard Worker ParamType paramType = ParamType::TTextureTarget;
7118*8975f5c5SAndroid Build Coastguard Worker
7119*8975f5c5SAndroid Build Coastguard Worker // Some calls provide the textureID directly
7120*8975f5c5SAndroid Build Coastguard Worker // For the rest, look it up based on the currently bound texture
7121*8975f5c5SAndroid Build Coastguard Worker switch (call.entryPoint)
7122*8975f5c5SAndroid Build Coastguard Worker {
7123*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompressedCopyTextureCHROMIUM:
7124*8975f5c5SAndroid Build Coastguard Worker index = 1;
7125*8975f5c5SAndroid Build Coastguard Worker paramName = "destIdPacked";
7126*8975f5c5SAndroid Build Coastguard Worker paramType = ParamType::TTextureID;
7127*8975f5c5SAndroid Build Coastguard Worker break;
7128*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyTextureCHROMIUM:
7129*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopySubTextureCHROMIUM:
7130*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyTexture3DANGLE:
7131*8975f5c5SAndroid Build Coastguard Worker index = 3;
7132*8975f5c5SAndroid Build Coastguard Worker paramName = "destIdPacked";
7133*8975f5c5SAndroid Build Coastguard Worker paramType = ParamType::TTextureID;
7134*8975f5c5SAndroid Build Coastguard Worker break;
7135*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyImageSubData:
7136*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyImageSubDataEXT:
7137*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyImageSubDataOES:
7138*8975f5c5SAndroid Build Coastguard Worker index = 7;
7139*8975f5c5SAndroid Build Coastguard Worker paramName = "dstTarget";
7140*8975f5c5SAndroid Build Coastguard Worker paramType = ParamType::TGLenum;
7141*8975f5c5SAndroid Build Coastguard Worker break;
7142*8975f5c5SAndroid Build Coastguard Worker default:
7143*8975f5c5SAndroid Build Coastguard Worker break;
7144*8975f5c5SAndroid Build Coastguard Worker }
7145*8975f5c5SAndroid Build Coastguard Worker
7146*8975f5c5SAndroid Build Coastguard Worker GLuint id = 0;
7147*8975f5c5SAndroid Build Coastguard Worker switch (paramType)
7148*8975f5c5SAndroid Build Coastguard Worker {
7149*8975f5c5SAndroid Build Coastguard Worker case ParamType::TTextureTarget:
7150*8975f5c5SAndroid Build Coastguard Worker {
7151*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget targetPacked =
7152*8975f5c5SAndroid Build Coastguard Worker call.params.getParam(paramName.c_str(), ParamType::TTextureTarget, index)
7153*8975f5c5SAndroid Build Coastguard Worker .value.TextureTargetVal;
7154*8975f5c5SAndroid Build Coastguard Worker gl::TextureType textureType = gl::TextureTargetToType(targetPacked);
7155*8975f5c5SAndroid Build Coastguard Worker gl::Texture *texture = context->getState().getTargetTexture(textureType);
7156*8975f5c5SAndroid Build Coastguard Worker id = texture->id().value;
7157*8975f5c5SAndroid Build Coastguard Worker break;
7158*8975f5c5SAndroid Build Coastguard Worker }
7159*8975f5c5SAndroid Build Coastguard Worker case ParamType::TTextureID:
7160*8975f5c5SAndroid Build Coastguard Worker {
7161*8975f5c5SAndroid Build Coastguard Worker gl::TextureID destIDPacked =
7162*8975f5c5SAndroid Build Coastguard Worker call.params.getParam(paramName.c_str(), ParamType::TTextureID, index)
7163*8975f5c5SAndroid Build Coastguard Worker .value.TextureIDVal;
7164*8975f5c5SAndroid Build Coastguard Worker id = destIDPacked.value;
7165*8975f5c5SAndroid Build Coastguard Worker break;
7166*8975f5c5SAndroid Build Coastguard Worker }
7167*8975f5c5SAndroid Build Coastguard Worker case ParamType::TGLenum:
7168*8975f5c5SAndroid Build Coastguard Worker {
7169*8975f5c5SAndroid Build Coastguard Worker GLenum target =
7170*8975f5c5SAndroid Build Coastguard Worker call.params.getParam(paramName.c_str(), ParamType::TGLenum, index).value.GLenumVal;
7171*8975f5c5SAndroid Build Coastguard Worker
7172*8975f5c5SAndroid Build Coastguard Worker if (target == GL_TEXTURE_CUBE_MAP)
7173*8975f5c5SAndroid Build Coastguard Worker {
7174*8975f5c5SAndroid Build Coastguard Worker // CopyImageSubData doesn't support cube faces, but PackedParams requires one
7175*8975f5c5SAndroid Build Coastguard Worker target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
7176*8975f5c5SAndroid Build Coastguard Worker }
7177*8975f5c5SAndroid Build Coastguard Worker
7178*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget targetPacked = gl::PackParam<gl::TextureTarget>(target);
7179*8975f5c5SAndroid Build Coastguard Worker gl::TextureType textureType = gl::TextureTargetToType(targetPacked);
7180*8975f5c5SAndroid Build Coastguard Worker gl::Texture *texture = context->getState().getTargetTexture(textureType);
7181*8975f5c5SAndroid Build Coastguard Worker id = texture->id().value;
7182*8975f5c5SAndroid Build Coastguard Worker break;
7183*8975f5c5SAndroid Build Coastguard Worker }
7184*8975f5c5SAndroid Build Coastguard Worker default:
7185*8975f5c5SAndroid Build Coastguard Worker ERR() << "Unhandled paramType= " << static_cast<int>(paramType);
7186*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
7187*8975f5c5SAndroid Build Coastguard Worker break;
7188*8975f5c5SAndroid Build Coastguard Worker }
7189*8975f5c5SAndroid Build Coastguard Worker
7190*8975f5c5SAndroid Build Coastguard Worker // Mark it as modified
7191*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.getTrackedResource(context->id(), ResourceIDType::Texture)
7192*8975f5c5SAndroid Build Coastguard Worker .setModifiedResource(id);
7193*8975f5c5SAndroid Build Coastguard Worker }
7194*8975f5c5SAndroid Build Coastguard Worker
7195*8975f5c5SAndroid Build Coastguard Worker // Identify and mark writeable shader image textures as modified
trackImageUpdate(const gl::Context * context,const CallCapture & call)7196*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::trackImageUpdate(const gl::Context *context, const CallCapture &call)
7197*8975f5c5SAndroid Build Coastguard Worker {
7198*8975f5c5SAndroid Build Coastguard Worker const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
7199*8975f5c5SAndroid Build Coastguard Worker for (const gl::ImageBinding &imageBinding : executable->getImageBindings())
7200*8975f5c5SAndroid Build Coastguard Worker {
7201*8975f5c5SAndroid Build Coastguard Worker for (GLuint binding : imageBinding.boundImageUnits)
7202*8975f5c5SAndroid Build Coastguard Worker {
7203*8975f5c5SAndroid Build Coastguard Worker const gl::ImageUnit &imageUnit = context->getState().getImageUnit(binding);
7204*8975f5c5SAndroid Build Coastguard Worker if (imageUnit.access != GL_READ_ONLY)
7205*8975f5c5SAndroid Build Coastguard Worker {
7206*8975f5c5SAndroid Build Coastguard Worker // Get image binding texture id and mark it as modified
7207*8975f5c5SAndroid Build Coastguard Worker GLuint id = imageUnit.texture.id().value;
7208*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.getTrackedResource(context->id(), ResourceIDType::Texture)
7209*8975f5c5SAndroid Build Coastguard Worker .setModifiedResource(id);
7210*8975f5c5SAndroid Build Coastguard Worker }
7211*8975f5c5SAndroid Build Coastguard Worker }
7212*8975f5c5SAndroid Build Coastguard Worker }
7213*8975f5c5SAndroid Build Coastguard Worker }
7214*8975f5c5SAndroid Build Coastguard Worker
trackDefaultUniformUpdate(const gl::Context * context,const CallCapture & call)7215*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::trackDefaultUniformUpdate(const gl::Context *context,
7216*8975f5c5SAndroid Build Coastguard Worker const CallCapture &call)
7217*8975f5c5SAndroid Build Coastguard Worker {
7218*8975f5c5SAndroid Build Coastguard Worker DefaultUniformType defaultUniformType = GetDefaultUniformType(call);
7219*8975f5c5SAndroid Build Coastguard Worker
7220*8975f5c5SAndroid Build Coastguard Worker GLuint programID = 0;
7221*8975f5c5SAndroid Build Coastguard Worker int location = 0;
7222*8975f5c5SAndroid Build Coastguard Worker
7223*8975f5c5SAndroid Build Coastguard Worker // We track default uniform updates by program and location, so look them up in parameters
7224*8975f5c5SAndroid Build Coastguard Worker if (defaultUniformType == DefaultUniformType::CurrentProgram)
7225*8975f5c5SAndroid Build Coastguard Worker {
7226*8975f5c5SAndroid Build Coastguard Worker programID = context->getActiveLinkedProgram()->id().value;
7227*8975f5c5SAndroid Build Coastguard Worker
7228*8975f5c5SAndroid Build Coastguard Worker location = call.params.getParam("locationPacked", ParamType::TUniformLocation, 0)
7229*8975f5c5SAndroid Build Coastguard Worker .value.UniformLocationVal.value;
7230*8975f5c5SAndroid Build Coastguard Worker }
7231*8975f5c5SAndroid Build Coastguard Worker else
7232*8975f5c5SAndroid Build Coastguard Worker {
7233*8975f5c5SAndroid Build Coastguard Worker ASSERT(defaultUniformType == DefaultUniformType::SpecifiedProgram);
7234*8975f5c5SAndroid Build Coastguard Worker
7235*8975f5c5SAndroid Build Coastguard Worker programID = call.params.getParam("programPacked", ParamType::TShaderProgramID, 0)
7236*8975f5c5SAndroid Build Coastguard Worker .value.ShaderProgramIDVal.value;
7237*8975f5c5SAndroid Build Coastguard Worker
7238*8975f5c5SAndroid Build Coastguard Worker location = call.params.getParam("locationPacked", ParamType::TUniformLocation, 1)
7239*8975f5c5SAndroid Build Coastguard Worker .value.UniformLocationVal.value;
7240*8975f5c5SAndroid Build Coastguard Worker }
7241*8975f5c5SAndroid Build Coastguard Worker
7242*8975f5c5SAndroid Build Coastguard Worker const TrackedResource &trackedShaderProgram =
7243*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.getTrackedResource(context->id(), ResourceIDType::ShaderProgram);
7244*8975f5c5SAndroid Build Coastguard Worker const ResourceSet &startingPrograms = trackedShaderProgram.getStartingResources();
7245*8975f5c5SAndroid Build Coastguard Worker const ResourceSet &programsToRegen = trackedShaderProgram.getResourcesToRegen();
7246*8975f5c5SAndroid Build Coastguard Worker
7247*8975f5c5SAndroid Build Coastguard Worker // If this program was in our starting set, track its uniform updates. Unless it was deleted,
7248*8975f5c5SAndroid Build Coastguard Worker // then its uniforms will all be regenned along wih with the program.
7249*8975f5c5SAndroid Build Coastguard Worker if (startingPrograms.find(programID) != startingPrograms.end() &&
7250*8975f5c5SAndroid Build Coastguard Worker programsToRegen.find(programID) == programsToRegen.end())
7251*8975f5c5SAndroid Build Coastguard Worker {
7252*8975f5c5SAndroid Build Coastguard Worker // Track that we need to set this default uniform value again
7253*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.setModifiedDefaultUniform({programID}, {location});
7254*8975f5c5SAndroid Build Coastguard Worker }
7255*8975f5c5SAndroid Build Coastguard Worker }
7256*8975f5c5SAndroid Build Coastguard Worker
trackVertexArrayUpdate(const gl::Context * context,const CallCapture & call)7257*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::trackVertexArrayUpdate(const gl::Context *context, const CallCapture &call)
7258*8975f5c5SAndroid Build Coastguard Worker {
7259*8975f5c5SAndroid Build Coastguard Worker // Look up the currently bound vertex array
7260*8975f5c5SAndroid Build Coastguard Worker gl::VertexArrayID id = context->getState().getVertexArray()->id();
7261*8975f5c5SAndroid Build Coastguard Worker
7262*8975f5c5SAndroid Build Coastguard Worker // Mark it as modified
7263*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.getTrackedResource(context->id(), ResourceIDType::VertexArray)
7264*8975f5c5SAndroid Build Coastguard Worker .setModifiedResource(id.value);
7265*8975f5c5SAndroid Build Coastguard Worker }
7266*8975f5c5SAndroid Build Coastguard Worker
updateCopyImageSubData(CallCapture & call)7267*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::updateCopyImageSubData(CallCapture &call)
7268*8975f5c5SAndroid Build Coastguard Worker {
7269*8975f5c5SAndroid Build Coastguard Worker // This call modifies srcName and dstName to no longer be object IDs (GLuint), but actual
7270*8975f5c5SAndroid Build Coastguard Worker // packed types that can remapped using gTextureMap and gRenderbufferMap
7271*8975f5c5SAndroid Build Coastguard Worker
7272*8975f5c5SAndroid Build Coastguard Worker GLint srcName = call.params.getParam("srcName", ParamType::TGLuint, 0).value.GLuintVal;
7273*8975f5c5SAndroid Build Coastguard Worker GLenum srcTarget = call.params.getParam("srcTarget", ParamType::TGLenum, 1).value.GLenumVal;
7274*8975f5c5SAndroid Build Coastguard Worker switch (srcTarget)
7275*8975f5c5SAndroid Build Coastguard Worker {
7276*8975f5c5SAndroid Build Coastguard Worker case GL_RENDERBUFFER:
7277*8975f5c5SAndroid Build Coastguard Worker {
7278*8975f5c5SAndroid Build Coastguard Worker // Convert the GLuint to RenderbufferID
7279*8975f5c5SAndroid Build Coastguard Worker gl::RenderbufferID srcRenderbufferID = {static_cast<GLuint>(srcName)};
7280*8975f5c5SAndroid Build Coastguard Worker call.params.setValueParamAtIndex("srcName", ParamType::TRenderbufferID,
7281*8975f5c5SAndroid Build Coastguard Worker srcRenderbufferID, 0);
7282*8975f5c5SAndroid Build Coastguard Worker break;
7283*8975f5c5SAndroid Build Coastguard Worker }
7284*8975f5c5SAndroid Build Coastguard Worker case GL_TEXTURE_2D:
7285*8975f5c5SAndroid Build Coastguard Worker case GL_TEXTURE_2D_ARRAY:
7286*8975f5c5SAndroid Build Coastguard Worker case GL_TEXTURE_3D:
7287*8975f5c5SAndroid Build Coastguard Worker case GL_TEXTURE_CUBE_MAP:
7288*8975f5c5SAndroid Build Coastguard Worker case GL_TEXTURE_EXTERNAL_OES:
7289*8975f5c5SAndroid Build Coastguard Worker {
7290*8975f5c5SAndroid Build Coastguard Worker // Convert the GLuint to TextureID
7291*8975f5c5SAndroid Build Coastguard Worker gl::TextureID srcTextureID = {static_cast<GLuint>(srcName)};
7292*8975f5c5SAndroid Build Coastguard Worker call.params.setValueParamAtIndex("srcName", ParamType::TTextureID, srcTextureID, 0);
7293*8975f5c5SAndroid Build Coastguard Worker break;
7294*8975f5c5SAndroid Build Coastguard Worker }
7295*8975f5c5SAndroid Build Coastguard Worker default:
7296*8975f5c5SAndroid Build Coastguard Worker ERR() << "Unhandled srcTarget = " << srcTarget;
7297*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
7298*8975f5c5SAndroid Build Coastguard Worker break;
7299*8975f5c5SAndroid Build Coastguard Worker }
7300*8975f5c5SAndroid Build Coastguard Worker
7301*8975f5c5SAndroid Build Coastguard Worker // Change dstName to the appropriate type based on dstTarget
7302*8975f5c5SAndroid Build Coastguard Worker GLint dstName = call.params.getParam("dstName", ParamType::TGLuint, 6).value.GLuintVal;
7303*8975f5c5SAndroid Build Coastguard Worker GLenum dstTarget = call.params.getParam("dstTarget", ParamType::TGLenum, 7).value.GLenumVal;
7304*8975f5c5SAndroid Build Coastguard Worker switch (dstTarget)
7305*8975f5c5SAndroid Build Coastguard Worker {
7306*8975f5c5SAndroid Build Coastguard Worker case GL_RENDERBUFFER:
7307*8975f5c5SAndroid Build Coastguard Worker {
7308*8975f5c5SAndroid Build Coastguard Worker // Convert the GLuint to RenderbufferID
7309*8975f5c5SAndroid Build Coastguard Worker gl::RenderbufferID dstRenderbufferID = {static_cast<GLuint>(dstName)};
7310*8975f5c5SAndroid Build Coastguard Worker call.params.setValueParamAtIndex("dstName", ParamType::TRenderbufferID,
7311*8975f5c5SAndroid Build Coastguard Worker dstRenderbufferID, 6);
7312*8975f5c5SAndroid Build Coastguard Worker break;
7313*8975f5c5SAndroid Build Coastguard Worker }
7314*8975f5c5SAndroid Build Coastguard Worker case GL_TEXTURE_2D:
7315*8975f5c5SAndroid Build Coastguard Worker case GL_TEXTURE_2D_ARRAY:
7316*8975f5c5SAndroid Build Coastguard Worker case GL_TEXTURE_3D:
7317*8975f5c5SAndroid Build Coastguard Worker case GL_TEXTURE_CUBE_MAP:
7318*8975f5c5SAndroid Build Coastguard Worker case GL_TEXTURE_EXTERNAL_OES:
7319*8975f5c5SAndroid Build Coastguard Worker {
7320*8975f5c5SAndroid Build Coastguard Worker // Convert the GLuint to TextureID
7321*8975f5c5SAndroid Build Coastguard Worker gl::TextureID dstTextureID = {static_cast<GLuint>(dstName)};
7322*8975f5c5SAndroid Build Coastguard Worker call.params.setValueParamAtIndex("dstName", ParamType::TTextureID, dstTextureID, 6);
7323*8975f5c5SAndroid Build Coastguard Worker break;
7324*8975f5c5SAndroid Build Coastguard Worker }
7325*8975f5c5SAndroid Build Coastguard Worker default:
7326*8975f5c5SAndroid Build Coastguard Worker ERR() << "Unhandled dstTarget = " << dstTarget;
7327*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
7328*8975f5c5SAndroid Build Coastguard Worker break;
7329*8975f5c5SAndroid Build Coastguard Worker }
7330*8975f5c5SAndroid Build Coastguard Worker }
7331*8975f5c5SAndroid Build Coastguard Worker
overrideProgramBinary(const gl::Context * context,CallCapture & inCall,std::vector<CallCapture> & outCalls)7332*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::overrideProgramBinary(const gl::Context *context,
7333*8975f5c5SAndroid Build Coastguard Worker CallCapture &inCall,
7334*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> &outCalls)
7335*8975f5c5SAndroid Build Coastguard Worker {
7336*8975f5c5SAndroid Build Coastguard Worker // Program binaries are inherently non-portable, even between two ANGLE builds.
7337*8975f5c5SAndroid Build Coastguard Worker // If an application is using glProgramBinary in the middle of a trace, we need to replace
7338*8975f5c5SAndroid Build Coastguard Worker // those calls with an equivalent sequence of portable calls.
7339*8975f5c5SAndroid Build Coastguard Worker //
7340*8975f5c5SAndroid Build Coastguard Worker // For example, here is a sequence an app could use for glProgramBinary:
7341*8975f5c5SAndroid Build Coastguard Worker //
7342*8975f5c5SAndroid Build Coastguard Worker // gShaderProgramMap[42] = glCreateProgram();
7343*8975f5c5SAndroid Build Coastguard Worker // glProgramBinary(gShaderProgramMap[42], GL_PROGRAM_BINARY_ANGLE, gBinaryData[x], 1000);
7344*8975f5c5SAndroid Build Coastguard Worker // glGetProgramiv(gShaderProgramMap[42], GL_LINK_STATUS, gReadBuffer);
7345*8975f5c5SAndroid Build Coastguard Worker // glGetProgramiv(gShaderProgramMap[42], GL_PROGRAM_BINARY_LENGTH, gReadBuffer);
7346*8975f5c5SAndroid Build Coastguard Worker //
7347*8975f5c5SAndroid Build Coastguard Worker // With this override, the glProgramBinary call will be replaced like so:
7348*8975f5c5SAndroid Build Coastguard Worker //
7349*8975f5c5SAndroid Build Coastguard Worker // gShaderProgramMap[42] = glCreateProgram();
7350*8975f5c5SAndroid Build Coastguard Worker // === Begin override ===
7351*8975f5c5SAndroid Build Coastguard Worker // gShaderProgramMap[43] = glCreateShader(GL_VERTEX_SHADER);
7352*8975f5c5SAndroid Build Coastguard Worker // glShaderSource(gShaderProgramMap[43], 1, string_0, &gBinaryData[100]);
7353*8975f5c5SAndroid Build Coastguard Worker // glCompileShader(gShaderProgramMap[43]);
7354*8975f5c5SAndroid Build Coastguard Worker // glAttachShader(gShaderProgramMap[42], gShaderProgramMap[43]);
7355*8975f5c5SAndroid Build Coastguard Worker // glDeleteShader(gShaderProgramMap[43]);
7356*8975f5c5SAndroid Build Coastguard Worker // gShaderProgramMap[43] = glCreateShader(GL_FRAGMENT_SHADER);
7357*8975f5c5SAndroid Build Coastguard Worker // glShaderSource(gShaderProgramMap[43], 1, string_1, &gBinaryData[200]);
7358*8975f5c5SAndroid Build Coastguard Worker // glCompileShader(gShaderProgramMap[43]);
7359*8975f5c5SAndroid Build Coastguard Worker // glAttachShader(gShaderProgramMap[42], gShaderProgramMap[43]);
7360*8975f5c5SAndroid Build Coastguard Worker // glDeleteShader(gShaderProgramMap[43]);
7361*8975f5c5SAndroid Build Coastguard Worker // glBindAttribLocation(gShaderProgramMap[42], 0, "attrib1");
7362*8975f5c5SAndroid Build Coastguard Worker // glBindAttribLocation(gShaderProgramMap[42], 1, "attrib2");
7363*8975f5c5SAndroid Build Coastguard Worker // glLinkProgram(gShaderProgramMap[42]);
7364*8975f5c5SAndroid Build Coastguard Worker // UpdateUniformLocation(gShaderProgramMap[42], "foo", 0, 20);
7365*8975f5c5SAndroid Build Coastguard Worker // UpdateUniformLocation(gShaderProgramMap[42], "bar", 72, 1);
7366*8975f5c5SAndroid Build Coastguard Worker // glUseProgram(gShaderProgramMap[42]);
7367*8975f5c5SAndroid Build Coastguard Worker // UpdateCurrentProgram(gShaderProgramMap[42]);
7368*8975f5c5SAndroid Build Coastguard Worker // glUniform4fv(gUniformLocations[gCurrentProgram][0], 20, &gBinaryData[300]);
7369*8975f5c5SAndroid Build Coastguard Worker // glUniform1iv(gUniformLocations[gCurrentProgram][72], 1, &gBinaryData[400]);
7370*8975f5c5SAndroid Build Coastguard Worker // === End override ===
7371*8975f5c5SAndroid Build Coastguard Worker // glGetProgramiv(gShaderProgramMap[42], GL_LINK_STATUS, gReadBuffer);
7372*8975f5c5SAndroid Build Coastguard Worker // glGetProgramiv(gShaderProgramMap[42], GL_PROGRAM_BINARY_LENGTH, gReadBuffer);
7373*8975f5c5SAndroid Build Coastguard Worker //
7374*8975f5c5SAndroid Build Coastguard Worker // To facilitate this override, we are serializing each shader stage source into the binary
7375*8975f5c5SAndroid Build Coastguard Worker // itself. See Program::serialize and Program::deserialize. Once extracted from the binary,
7376*8975f5c5SAndroid Build Coastguard Worker // they will be available via getProgramSources.
7377*8975f5c5SAndroid Build Coastguard Worker
7378*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID id = inCall.params.getParam("programPacked", ParamType::TShaderProgramID, 0)
7379*8975f5c5SAndroid Build Coastguard Worker .value.ShaderProgramIDVal;
7380*8975f5c5SAndroid Build Coastguard Worker
7381*8975f5c5SAndroid Build Coastguard Worker gl::Program *program = context->getProgramResolveLink(id);
7382*8975f5c5SAndroid Build Coastguard Worker ASSERT(program);
7383*8975f5c5SAndroid Build Coastguard Worker
7384*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.onShaderProgramAccess(id);
7385*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID tempShaderStartID = {mResourceTracker.getMaxShaderPrograms()};
7386*8975f5c5SAndroid Build Coastguard Worker GenerateLinkedProgram(context, context->getState(), &mResourceTracker, &outCalls, program, id,
7387*8975f5c5SAndroid Build Coastguard Worker tempShaderStartID, getProgramSources(id));
7388*8975f5c5SAndroid Build Coastguard Worker }
7389*8975f5c5SAndroid Build Coastguard Worker
captureCustomMapBufferFromContext(const gl::Context * context,const char * entryPointName,CallCapture & call,std::vector<CallCapture> & callsOut)7390*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::captureCustomMapBufferFromContext(const gl::Context *context,
7391*8975f5c5SAndroid Build Coastguard Worker const char *entryPointName,
7392*8975f5c5SAndroid Build Coastguard Worker CallCapture &call,
7393*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> &callsOut)
7394*8975f5c5SAndroid Build Coastguard Worker {
7395*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding binding =
7396*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("targetPacked", ParamType::TBufferBinding, 0).value.BufferBindingVal;
7397*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = context->getState().getTargetBuffer(binding);
7398*8975f5c5SAndroid Build Coastguard Worker
7399*8975f5c5SAndroid Build Coastguard Worker if (call.entryPoint == EntryPoint::GLMapBufferRange ||
7400*8975f5c5SAndroid Build Coastguard Worker call.entryPoint == EntryPoint::GLMapBufferRangeEXT)
7401*8975f5c5SAndroid Build Coastguard Worker {
7402*8975f5c5SAndroid Build Coastguard Worker GLintptr offset = call.params.getParam("offset", ParamType::TGLintptr, 1).value.GLintptrVal;
7403*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr length =
7404*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("length", ParamType::TGLsizeiptr, 2).value.GLsizeiptrVal;
7405*8975f5c5SAndroid Build Coastguard Worker GLbitfield access =
7406*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("access", ParamType::TGLbitfield, 3).value.GLbitfieldVal;
7407*8975f5c5SAndroid Build Coastguard Worker
7408*8975f5c5SAndroid Build Coastguard Worker trackBufferMapping(context, &call, buffer->id(), buffer, offset, length,
7409*8975f5c5SAndroid Build Coastguard Worker access & GL_MAP_WRITE_BIT, access & GL_MAP_COHERENT_BIT_EXT);
7410*8975f5c5SAndroid Build Coastguard Worker }
7411*8975f5c5SAndroid Build Coastguard Worker else
7412*8975f5c5SAndroid Build Coastguard Worker {
7413*8975f5c5SAndroid Build Coastguard Worker ASSERT(call.entryPoint == EntryPoint::GLMapBufferOES);
7414*8975f5c5SAndroid Build Coastguard Worker GLenum access = call.params.getParam("access", ParamType::TGLenum, 1).value.GLenumVal;
7415*8975f5c5SAndroid Build Coastguard Worker bool writeAccess =
7416*8975f5c5SAndroid Build Coastguard Worker (access == GL_WRITE_ONLY_OES || access == GL_WRITE_ONLY || access == GL_READ_WRITE);
7417*8975f5c5SAndroid Build Coastguard Worker trackBufferMapping(context, &call, buffer->id(), buffer, 0,
7418*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(buffer->getSize()), writeAccess, false);
7419*8975f5c5SAndroid Build Coastguard Worker }
7420*8975f5c5SAndroid Build Coastguard Worker
7421*8975f5c5SAndroid Build Coastguard Worker CaptureCustomMapBuffer(entryPointName, call, callsOut, buffer->id());
7422*8975f5c5SAndroid Build Coastguard Worker }
7423*8975f5c5SAndroid Build Coastguard Worker
maybeOverrideEntryPoint(const gl::Context * context,CallCapture & inCall,std::vector<CallCapture> & outCalls)7424*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::maybeOverrideEntryPoint(const gl::Context *context,
7425*8975f5c5SAndroid Build Coastguard Worker CallCapture &inCall,
7426*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> &outCalls)
7427*8975f5c5SAndroid Build Coastguard Worker {
7428*8975f5c5SAndroid Build Coastguard Worker switch (inCall.entryPoint)
7429*8975f5c5SAndroid Build Coastguard Worker {
7430*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyImageSubData:
7431*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyImageSubDataEXT:
7432*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyImageSubDataOES:
7433*8975f5c5SAndroid Build Coastguard Worker {
7434*8975f5c5SAndroid Build Coastguard Worker // We must look at the src and dst target types to determine which remap table to use
7435*8975f5c5SAndroid Build Coastguard Worker updateCopyImageSubData(inCall);
7436*8975f5c5SAndroid Build Coastguard Worker outCalls.emplace_back(std::move(inCall));
7437*8975f5c5SAndroid Build Coastguard Worker break;
7438*8975f5c5SAndroid Build Coastguard Worker }
7439*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramBinary:
7440*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLProgramBinaryOES:
7441*8975f5c5SAndroid Build Coastguard Worker {
7442*8975f5c5SAndroid Build Coastguard Worker // Binary formats are not portable at all, so replace the calls with full linking
7443*8975f5c5SAndroid Build Coastguard Worker // sequence
7444*8975f5c5SAndroid Build Coastguard Worker overrideProgramBinary(context, inCall, outCalls);
7445*8975f5c5SAndroid Build Coastguard Worker break;
7446*8975f5c5SAndroid Build Coastguard Worker }
7447*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUniformBlockBinding:
7448*8975f5c5SAndroid Build Coastguard Worker {
7449*8975f5c5SAndroid Build Coastguard Worker CaptureCustomUniformBlockBinding(inCall, outCalls);
7450*8975f5c5SAndroid Build Coastguard Worker break;
7451*8975f5c5SAndroid Build Coastguard Worker }
7452*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLMapBufferRange:
7453*8975f5c5SAndroid Build Coastguard Worker {
7454*8975f5c5SAndroid Build Coastguard Worker captureCustomMapBufferFromContext(context, "MapBufferRange", inCall, outCalls);
7455*8975f5c5SAndroid Build Coastguard Worker break;
7456*8975f5c5SAndroid Build Coastguard Worker }
7457*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLMapBufferRangeEXT:
7458*8975f5c5SAndroid Build Coastguard Worker {
7459*8975f5c5SAndroid Build Coastguard Worker captureCustomMapBufferFromContext(context, "MapBufferRangeEXT", inCall, outCalls);
7460*8975f5c5SAndroid Build Coastguard Worker break;
7461*8975f5c5SAndroid Build Coastguard Worker }
7462*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLMapBufferOES:
7463*8975f5c5SAndroid Build Coastguard Worker {
7464*8975f5c5SAndroid Build Coastguard Worker captureCustomMapBufferFromContext(context, "MapBufferOES", inCall, outCalls);
7465*8975f5c5SAndroid Build Coastguard Worker break;
7466*8975f5c5SAndroid Build Coastguard Worker }
7467*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCreateShader:
7468*8975f5c5SAndroid Build Coastguard Worker {
7469*8975f5c5SAndroid Build Coastguard Worker CaptureCustomShaderProgram("CreateShader", inCall, outCalls);
7470*8975f5c5SAndroid Build Coastguard Worker break;
7471*8975f5c5SAndroid Build Coastguard Worker }
7472*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCreateProgram:
7473*8975f5c5SAndroid Build Coastguard Worker {
7474*8975f5c5SAndroid Build Coastguard Worker CaptureCustomShaderProgram("CreateProgram", inCall, outCalls);
7475*8975f5c5SAndroid Build Coastguard Worker break;
7476*8975f5c5SAndroid Build Coastguard Worker }
7477*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCreateShaderProgramv:
7478*8975f5c5SAndroid Build Coastguard Worker {
7479*8975f5c5SAndroid Build Coastguard Worker CaptureCustomShaderProgram("CreateShaderProgramv", inCall, outCalls);
7480*8975f5c5SAndroid Build Coastguard Worker break;
7481*8975f5c5SAndroid Build Coastguard Worker }
7482*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLFenceSync:
7483*8975f5c5SAndroid Build Coastguard Worker {
7484*8975f5c5SAndroid Build Coastguard Worker CaptureCustomFenceSync(inCall, outCalls);
7485*8975f5c5SAndroid Build Coastguard Worker break;
7486*8975f5c5SAndroid Build Coastguard Worker }
7487*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLCreateImage:
7488*8975f5c5SAndroid Build Coastguard Worker {
7489*8975f5c5SAndroid Build Coastguard Worker const egl::Image *eglImage = GetImageFromParam(context, inCall.params.getReturnValue());
7490*8975f5c5SAndroid Build Coastguard Worker CaptureCustomCreateEGLImage(context, "CreateEGLImage", eglImage->getWidth(),
7491*8975f5c5SAndroid Build Coastguard Worker eglImage->getHeight(), inCall, outCalls);
7492*8975f5c5SAndroid Build Coastguard Worker break;
7493*8975f5c5SAndroid Build Coastguard Worker }
7494*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLCreateImageKHR:
7495*8975f5c5SAndroid Build Coastguard Worker {
7496*8975f5c5SAndroid Build Coastguard Worker const egl::Image *eglImage = GetImageFromParam(context, inCall.params.getReturnValue());
7497*8975f5c5SAndroid Build Coastguard Worker CaptureCustomCreateEGLImage(context, "CreateEGLImageKHR", eglImage->getWidth(),
7498*8975f5c5SAndroid Build Coastguard Worker eglImage->getHeight(), inCall, outCalls);
7499*8975f5c5SAndroid Build Coastguard Worker break;
7500*8975f5c5SAndroid Build Coastguard Worker }
7501*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLDestroyImage:
7502*8975f5c5SAndroid Build Coastguard Worker {
7503*8975f5c5SAndroid Build Coastguard Worker CaptureCustomDestroyEGLImage("DestroyEGLImage", inCall, outCalls);
7504*8975f5c5SAndroid Build Coastguard Worker break;
7505*8975f5c5SAndroid Build Coastguard Worker }
7506*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLDestroyImageKHR:
7507*8975f5c5SAndroid Build Coastguard Worker {
7508*8975f5c5SAndroid Build Coastguard Worker CaptureCustomDestroyEGLImage("DestroyEGLImageKHR", inCall, outCalls);
7509*8975f5c5SAndroid Build Coastguard Worker break;
7510*8975f5c5SAndroid Build Coastguard Worker }
7511*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLCreateSync:
7512*8975f5c5SAndroid Build Coastguard Worker {
7513*8975f5c5SAndroid Build Coastguard Worker CaptureCustomCreateEGLSync("CreateEGLSync", inCall, outCalls);
7514*8975f5c5SAndroid Build Coastguard Worker break;
7515*8975f5c5SAndroid Build Coastguard Worker }
7516*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLCreateSyncKHR:
7517*8975f5c5SAndroid Build Coastguard Worker {
7518*8975f5c5SAndroid Build Coastguard Worker CaptureCustomCreateEGLSync("CreateEGLSyncKHR", inCall, outCalls);
7519*8975f5c5SAndroid Build Coastguard Worker break;
7520*8975f5c5SAndroid Build Coastguard Worker }
7521*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLCreatePbufferSurface:
7522*8975f5c5SAndroid Build Coastguard Worker {
7523*8975f5c5SAndroid Build Coastguard Worker CaptureCustomCreatePbufferSurface(inCall, outCalls);
7524*8975f5c5SAndroid Build Coastguard Worker break;
7525*8975f5c5SAndroid Build Coastguard Worker }
7526*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLCreateNativeClientBufferANDROID:
7527*8975f5c5SAndroid Build Coastguard Worker {
7528*8975f5c5SAndroid Build Coastguard Worker CaptureCustomCreateNativeClientbuffer(inCall, outCalls);
7529*8975f5c5SAndroid Build Coastguard Worker break;
7530*8975f5c5SAndroid Build Coastguard Worker }
7531*8975f5c5SAndroid Build Coastguard Worker
7532*8975f5c5SAndroid Build Coastguard Worker default:
7533*8975f5c5SAndroid Build Coastguard Worker {
7534*8975f5c5SAndroid Build Coastguard Worker // Pass the single call through
7535*8975f5c5SAndroid Build Coastguard Worker outCalls.emplace_back(std::move(inCall));
7536*8975f5c5SAndroid Build Coastguard Worker break;
7537*8975f5c5SAndroid Build Coastguard Worker }
7538*8975f5c5SAndroid Build Coastguard Worker }
7539*8975f5c5SAndroid Build Coastguard Worker }
7540*8975f5c5SAndroid Build Coastguard Worker
maybeCaptureCoherentBuffers(const gl::Context * context)7541*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::maybeCaptureCoherentBuffers(const gl::Context *context)
7542*8975f5c5SAndroid Build Coastguard Worker {
7543*8975f5c5SAndroid Build Coastguard Worker if (!isCaptureActive())
7544*8975f5c5SAndroid Build Coastguard Worker {
7545*8975f5c5SAndroid Build Coastguard Worker return;
7546*8975f5c5SAndroid Build Coastguard Worker }
7547*8975f5c5SAndroid Build Coastguard Worker
7548*8975f5c5SAndroid Build Coastguard Worker std::lock_guard<angle::SimpleMutex> lock(mCoherentBufferTracker.mMutex);
7549*8975f5c5SAndroid Build Coastguard Worker
7550*8975f5c5SAndroid Build Coastguard Worker for (const auto &pair : mCoherentBufferTracker.mBuffers)
7551*8975f5c5SAndroid Build Coastguard Worker {
7552*8975f5c5SAndroid Build Coastguard Worker gl::BufferID id = {pair.first};
7553*8975f5c5SAndroid Build Coastguard Worker if (mCoherentBufferTracker.isDirty(id))
7554*8975f5c5SAndroid Build Coastguard Worker {
7555*8975f5c5SAndroid Build Coastguard Worker captureCoherentBufferSnapshot(context, id);
7556*8975f5c5SAndroid Build Coastguard Worker }
7557*8975f5c5SAndroid Build Coastguard Worker }
7558*8975f5c5SAndroid Build Coastguard Worker }
7559*8975f5c5SAndroid Build Coastguard Worker
maybeCaptureDrawArraysClientData(const gl::Context * context,CallCapture & call,size_t instanceCount)7560*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::maybeCaptureDrawArraysClientData(const gl::Context *context,
7561*8975f5c5SAndroid Build Coastguard Worker CallCapture &call,
7562*8975f5c5SAndroid Build Coastguard Worker size_t instanceCount)
7563*8975f5c5SAndroid Build Coastguard Worker {
7564*8975f5c5SAndroid Build Coastguard Worker if (!context->getStateCache().hasAnyActiveClientAttrib())
7565*8975f5c5SAndroid Build Coastguard Worker {
7566*8975f5c5SAndroid Build Coastguard Worker return;
7567*8975f5c5SAndroid Build Coastguard Worker }
7568*8975f5c5SAndroid Build Coastguard Worker
7569*8975f5c5SAndroid Build Coastguard Worker // Get counts from paramBuffer.
7570*8975f5c5SAndroid Build Coastguard Worker GLint firstVertex =
7571*8975f5c5SAndroid Build Coastguard Worker call.params.getParamFlexName("first", "start", ParamType::TGLint, 1).value.GLintVal;
7572*8975f5c5SAndroid Build Coastguard Worker GLsizei drawCount = call.params.getParam("count", ParamType::TGLsizei, 2).value.GLsizeiVal;
7573*8975f5c5SAndroid Build Coastguard Worker captureClientArraySnapshot(context, firstVertex + drawCount, instanceCount);
7574*8975f5c5SAndroid Build Coastguard Worker }
7575*8975f5c5SAndroid Build Coastguard Worker
maybeCaptureDrawElementsClientData(const gl::Context * context,CallCapture & call,size_t instanceCount)7576*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::maybeCaptureDrawElementsClientData(const gl::Context *context,
7577*8975f5c5SAndroid Build Coastguard Worker CallCapture &call,
7578*8975f5c5SAndroid Build Coastguard Worker size_t instanceCount)
7579*8975f5c5SAndroid Build Coastguard Worker {
7580*8975f5c5SAndroid Build Coastguard Worker if (!context->getStateCache().hasAnyActiveClientAttrib())
7581*8975f5c5SAndroid Build Coastguard Worker {
7582*8975f5c5SAndroid Build Coastguard Worker return;
7583*8975f5c5SAndroid Build Coastguard Worker }
7584*8975f5c5SAndroid Build Coastguard Worker
7585*8975f5c5SAndroid Build Coastguard Worker // if the count is zero then the index evaluation is not valid and we wouldn't be drawing
7586*8975f5c5SAndroid Build Coastguard Worker // anything anyway, so skip capturing
7587*8975f5c5SAndroid Build Coastguard Worker GLsizei count = call.params.getParam("count", ParamType::TGLsizei, 1).value.GLsizeiVal;
7588*8975f5c5SAndroid Build Coastguard Worker if (count == 0)
7589*8975f5c5SAndroid Build Coastguard Worker {
7590*8975f5c5SAndroid Build Coastguard Worker return;
7591*8975f5c5SAndroid Build Coastguard Worker }
7592*8975f5c5SAndroid Build Coastguard Worker
7593*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType drawElementsType =
7594*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("typePacked", ParamType::TDrawElementsType, 2)
7595*8975f5c5SAndroid Build Coastguard Worker .value.DrawElementsTypeVal;
7596*8975f5c5SAndroid Build Coastguard Worker const void *indices =
7597*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("indices", ParamType::TvoidConstPointer, 3).value.voidConstPointerVal;
7598*8975f5c5SAndroid Build Coastguard Worker
7599*8975f5c5SAndroid Build Coastguard Worker gl::IndexRange indexRange;
7600*8975f5c5SAndroid Build Coastguard Worker
7601*8975f5c5SAndroid Build Coastguard Worker bool restart = context->getState().isPrimitiveRestartEnabled();
7602*8975f5c5SAndroid Build Coastguard Worker
7603*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *elementArrayBuffer = context->getState().getVertexArray()->getElementArrayBuffer();
7604*8975f5c5SAndroid Build Coastguard Worker if (elementArrayBuffer)
7605*8975f5c5SAndroid Build Coastguard Worker {
7606*8975f5c5SAndroid Build Coastguard Worker size_t offset = reinterpret_cast<size_t>(indices);
7607*8975f5c5SAndroid Build Coastguard Worker (void)elementArrayBuffer->getIndexRange(context, drawElementsType, offset, count, restart,
7608*8975f5c5SAndroid Build Coastguard Worker &indexRange);
7609*8975f5c5SAndroid Build Coastguard Worker }
7610*8975f5c5SAndroid Build Coastguard Worker else
7611*8975f5c5SAndroid Build Coastguard Worker {
7612*8975f5c5SAndroid Build Coastguard Worker ASSERT(indices);
7613*8975f5c5SAndroid Build Coastguard Worker indexRange = gl::ComputeIndexRange(drawElementsType, indices, count, restart);
7614*8975f5c5SAndroid Build Coastguard Worker }
7615*8975f5c5SAndroid Build Coastguard Worker
7616*8975f5c5SAndroid Build Coastguard Worker // index starts from 0
7617*8975f5c5SAndroid Build Coastguard Worker captureClientArraySnapshot(context, indexRange.end + 1, instanceCount);
7618*8975f5c5SAndroid Build Coastguard Worker }
7619*8975f5c5SAndroid Build Coastguard Worker
7620*8975f5c5SAndroid Build Coastguard Worker template <typename AttribT, typename FactoryT>
CreateEGLImagePreCallUpdate(const CallCapture & call,ResourceTracker & resourceTracker,ParamType paramType,FactoryT factory)7621*8975f5c5SAndroid Build Coastguard Worker void CreateEGLImagePreCallUpdate(const CallCapture &call,
7622*8975f5c5SAndroid Build Coastguard Worker ResourceTracker &resourceTracker,
7623*8975f5c5SAndroid Build Coastguard Worker ParamType paramType,
7624*8975f5c5SAndroid Build Coastguard Worker FactoryT factory)
7625*8975f5c5SAndroid Build Coastguard Worker {
7626*8975f5c5SAndroid Build Coastguard Worker EGLImage image = call.params.getReturnValue().value.EGLImageVal;
7627*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶m = call.params.getParam("attrib_list", paramType, 4);
7628*8975f5c5SAndroid Build Coastguard Worker const AttribT *attribs =
7629*8975f5c5SAndroid Build Coastguard Worker param.data.empty() ? nullptr : reinterpret_cast<const AttribT *>(param.data[0].data());
7630*8975f5c5SAndroid Build Coastguard Worker egl::AttributeMap attributeMap = factory(attribs);
7631*8975f5c5SAndroid Build Coastguard Worker attributeMap.initializeWithoutValidation();
7632*8975f5c5SAndroid Build Coastguard Worker resourceTracker.getImageToAttribTable().insert(
7633*8975f5c5SAndroid Build Coastguard Worker std::pair<EGLImage, egl::AttributeMap>(image, attributeMap));
7634*8975f5c5SAndroid Build Coastguard Worker }
7635*8975f5c5SAndroid Build Coastguard Worker
maybeCapturePreCallUpdates(const gl::Context * context,CallCapture & call,std::vector<CallCapture> * shareGroupSetupCalls,ResourceIDToSetupCallsMap * resourceIDToSetupCalls)7636*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::maybeCapturePreCallUpdates(
7637*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context,
7638*8975f5c5SAndroid Build Coastguard Worker CallCapture &call,
7639*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> *shareGroupSetupCalls,
7640*8975f5c5SAndroid Build Coastguard Worker ResourceIDToSetupCallsMap *resourceIDToSetupCalls)
7641*8975f5c5SAndroid Build Coastguard Worker {
7642*8975f5c5SAndroid Build Coastguard Worker switch (call.entryPoint)
7643*8975f5c5SAndroid Build Coastguard Worker {
7644*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLVertexAttribPointer:
7645*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLVertexPointer:
7646*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLColorPointer:
7647*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexCoordPointer:
7648*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLNormalPointer:
7649*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLPointSizePointerOES:
7650*8975f5c5SAndroid Build Coastguard Worker {
7651*8975f5c5SAndroid Build Coastguard Worker // Get array location
7652*8975f5c5SAndroid Build Coastguard Worker GLuint index = 0;
7653*8975f5c5SAndroid Build Coastguard Worker if (call.entryPoint == EntryPoint::GLVertexAttribPointer)
7654*8975f5c5SAndroid Build Coastguard Worker {
7655*8975f5c5SAndroid Build Coastguard Worker index = call.params.getParam("index", ParamType::TGLuint, 0).value.GLuintVal;
7656*8975f5c5SAndroid Build Coastguard Worker }
7657*8975f5c5SAndroid Build Coastguard Worker else
7658*8975f5c5SAndroid Build Coastguard Worker {
7659*8975f5c5SAndroid Build Coastguard Worker gl::ClientVertexArrayType type;
7660*8975f5c5SAndroid Build Coastguard Worker switch (call.entryPoint)
7661*8975f5c5SAndroid Build Coastguard Worker {
7662*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLVertexPointer:
7663*8975f5c5SAndroid Build Coastguard Worker type = gl::ClientVertexArrayType::Vertex;
7664*8975f5c5SAndroid Build Coastguard Worker break;
7665*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLColorPointer:
7666*8975f5c5SAndroid Build Coastguard Worker type = gl::ClientVertexArrayType::Color;
7667*8975f5c5SAndroid Build Coastguard Worker break;
7668*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLTexCoordPointer:
7669*8975f5c5SAndroid Build Coastguard Worker type = gl::ClientVertexArrayType::TextureCoord;
7670*8975f5c5SAndroid Build Coastguard Worker break;
7671*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLNormalPointer:
7672*8975f5c5SAndroid Build Coastguard Worker type = gl::ClientVertexArrayType::Normal;
7673*8975f5c5SAndroid Build Coastguard Worker break;
7674*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLPointSizePointerOES:
7675*8975f5c5SAndroid Build Coastguard Worker type = gl::ClientVertexArrayType::PointSize;
7676*8975f5c5SAndroid Build Coastguard Worker break;
7677*8975f5c5SAndroid Build Coastguard Worker default:
7678*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
7679*8975f5c5SAndroid Build Coastguard Worker type = gl::ClientVertexArrayType::InvalidEnum;
7680*8975f5c5SAndroid Build Coastguard Worker }
7681*8975f5c5SAndroid Build Coastguard Worker index = gl::GLES1Renderer::VertexArrayIndex(type, context->getState().gles1());
7682*8975f5c5SAndroid Build Coastguard Worker }
7683*8975f5c5SAndroid Build Coastguard Worker
7684*8975f5c5SAndroid Build Coastguard Worker if (call.params.hasClientArrayData())
7685*8975f5c5SAndroid Build Coastguard Worker {
7686*8975f5c5SAndroid Build Coastguard Worker mClientVertexArrayMap[index] = static_cast<int>(mFrameCalls.size());
7687*8975f5c5SAndroid Build Coastguard Worker }
7688*8975f5c5SAndroid Build Coastguard Worker else
7689*8975f5c5SAndroid Build Coastguard Worker {
7690*8975f5c5SAndroid Build Coastguard Worker mClientVertexArrayMap[index] = -1;
7691*8975f5c5SAndroid Build Coastguard Worker }
7692*8975f5c5SAndroid Build Coastguard Worker break;
7693*8975f5c5SAndroid Build Coastguard Worker }
7694*8975f5c5SAndroid Build Coastguard Worker
7695*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenFramebuffers:
7696*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenFramebuffersOES:
7697*8975f5c5SAndroid Build Coastguard Worker {
7698*8975f5c5SAndroid Build Coastguard Worker GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
7699*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferID *framebufferIDs =
7700*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("framebuffersPacked", ParamType::TFramebufferIDPointer, 1)
7701*8975f5c5SAndroid Build Coastguard Worker .value.FramebufferIDPointerVal;
7702*8975f5c5SAndroid Build Coastguard Worker for (GLsizei i = 0; i < count; i++)
7703*8975f5c5SAndroid Build Coastguard Worker {
7704*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, framebufferIDs[i]);
7705*8975f5c5SAndroid Build Coastguard Worker }
7706*8975f5c5SAndroid Build Coastguard Worker break;
7707*8975f5c5SAndroid Build Coastguard Worker }
7708*8975f5c5SAndroid Build Coastguard Worker
7709*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBindFramebuffer:
7710*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBindFramebufferOES:
7711*8975f5c5SAndroid Build Coastguard Worker maybeGenResourceOnBind<gl::FramebufferID>(context, call);
7712*8975f5c5SAndroid Build Coastguard Worker break;
7713*8975f5c5SAndroid Build Coastguard Worker
7714*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenRenderbuffers:
7715*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenRenderbuffersOES:
7716*8975f5c5SAndroid Build Coastguard Worker {
7717*8975f5c5SAndroid Build Coastguard Worker GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
7718*8975f5c5SAndroid Build Coastguard Worker const gl::RenderbufferID *renderbufferIDs =
7719*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("renderbuffersPacked", ParamType::TRenderbufferIDPointer, 1)
7720*8975f5c5SAndroid Build Coastguard Worker .value.RenderbufferIDPointerVal;
7721*8975f5c5SAndroid Build Coastguard Worker for (GLsizei i = 0; i < count; i++)
7722*8975f5c5SAndroid Build Coastguard Worker {
7723*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, renderbufferIDs[i]);
7724*8975f5c5SAndroid Build Coastguard Worker }
7725*8975f5c5SAndroid Build Coastguard Worker break;
7726*8975f5c5SAndroid Build Coastguard Worker }
7727*8975f5c5SAndroid Build Coastguard Worker
7728*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBindRenderbuffer:
7729*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBindRenderbufferOES:
7730*8975f5c5SAndroid Build Coastguard Worker maybeGenResourceOnBind<gl::RenderbufferID>(context, call);
7731*8975f5c5SAndroid Build Coastguard Worker break;
7732*8975f5c5SAndroid Build Coastguard Worker
7733*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteRenderbuffers:
7734*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteRenderbuffersOES:
7735*8975f5c5SAndroid Build Coastguard Worker {
7736*8975f5c5SAndroid Build Coastguard Worker // Look up how many renderbuffers are being deleted
7737*8975f5c5SAndroid Build Coastguard Worker GLsizei n = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
7738*8975f5c5SAndroid Build Coastguard Worker
7739*8975f5c5SAndroid Build Coastguard Worker // Look up the pointer to list of renderbuffers
7740*8975f5c5SAndroid Build Coastguard Worker const gl::RenderbufferID *renderbufferIDs =
7741*8975f5c5SAndroid Build Coastguard Worker call.params
7742*8975f5c5SAndroid Build Coastguard Worker .getParam("renderbuffersPacked", ParamType::TRenderbufferIDConstPointer, 1)
7743*8975f5c5SAndroid Build Coastguard Worker .value.RenderbufferIDConstPointerVal;
7744*8975f5c5SAndroid Build Coastguard Worker
7745*8975f5c5SAndroid Build Coastguard Worker // For each renderbuffer listed for deletion
7746*8975f5c5SAndroid Build Coastguard Worker for (int32_t i = 0; i < n; ++i)
7747*8975f5c5SAndroid Build Coastguard Worker {
7748*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track what renderbuffers have been deleted
7749*8975f5c5SAndroid Build Coastguard Worker handleDeletedResource(context, renderbufferIDs[i]);
7750*8975f5c5SAndroid Build Coastguard Worker }
7751*8975f5c5SAndroid Build Coastguard Worker break;
7752*8975f5c5SAndroid Build Coastguard Worker }
7753*8975f5c5SAndroid Build Coastguard Worker
7754*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenTextures:
7755*8975f5c5SAndroid Build Coastguard Worker {
7756*8975f5c5SAndroid Build Coastguard Worker GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
7757*8975f5c5SAndroid Build Coastguard Worker const gl::TextureID *textureIDs =
7758*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("texturesPacked", ParamType::TTextureIDPointer, 1)
7759*8975f5c5SAndroid Build Coastguard Worker .value.TextureIDPointerVal;
7760*8975f5c5SAndroid Build Coastguard Worker for (GLsizei i = 0; i < count; i++)
7761*8975f5c5SAndroid Build Coastguard Worker {
7762*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track what new textures have been genned
7763*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, textureIDs[i]);
7764*8975f5c5SAndroid Build Coastguard Worker }
7765*8975f5c5SAndroid Build Coastguard Worker break;
7766*8975f5c5SAndroid Build Coastguard Worker }
7767*8975f5c5SAndroid Build Coastguard Worker
7768*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBindTexture:
7769*8975f5c5SAndroid Build Coastguard Worker maybeGenResourceOnBind<gl::TextureID>(context, call);
7770*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
7771*8975f5c5SAndroid Build Coastguard Worker {
7772*8975f5c5SAndroid Build Coastguard Worker gl::TextureType target =
7773*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("targetPacked", ParamType::TTextureType, 0)
7774*8975f5c5SAndroid Build Coastguard Worker .value.TextureTypeVal;
7775*8975f5c5SAndroid Build Coastguard Worker context->getFrameCapture()->getStateResetHelper().setTextureBindingDirty(
7776*8975f5c5SAndroid Build Coastguard Worker context->getState().getActiveSampler(), target);
7777*8975f5c5SAndroid Build Coastguard Worker }
7778*8975f5c5SAndroid Build Coastguard Worker break;
7779*8975f5c5SAndroid Build Coastguard Worker
7780*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteBuffers:
7781*8975f5c5SAndroid Build Coastguard Worker {
7782*8975f5c5SAndroid Build Coastguard Worker GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
7783*8975f5c5SAndroid Build Coastguard Worker const gl::BufferID *bufferIDs =
7784*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("buffersPacked", ParamType::TBufferIDConstPointer, 1)
7785*8975f5c5SAndroid Build Coastguard Worker .value.BufferIDConstPointerVal;
7786*8975f5c5SAndroid Build Coastguard Worker for (GLsizei i = 0; i < count; i++)
7787*8975f5c5SAndroid Build Coastguard Worker {
7788*8975f5c5SAndroid Build Coastguard Worker // For each buffer being deleted, check our backup of data and remove it
7789*8975f5c5SAndroid Build Coastguard Worker const auto &bufferDataInfo = mBufferDataMap.find(bufferIDs[i]);
7790*8975f5c5SAndroid Build Coastguard Worker if (bufferDataInfo != mBufferDataMap.end())
7791*8975f5c5SAndroid Build Coastguard Worker {
7792*8975f5c5SAndroid Build Coastguard Worker mBufferDataMap.erase(bufferDataInfo);
7793*8975f5c5SAndroid Build Coastguard Worker }
7794*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track what buffers have been deleted
7795*8975f5c5SAndroid Build Coastguard Worker handleDeletedResource(context, bufferIDs[i]);
7796*8975f5c5SAndroid Build Coastguard Worker }
7797*8975f5c5SAndroid Build Coastguard Worker break;
7798*8975f5c5SAndroid Build Coastguard Worker }
7799*8975f5c5SAndroid Build Coastguard Worker
7800*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenBuffers:
7801*8975f5c5SAndroid Build Coastguard Worker {
7802*8975f5c5SAndroid Build Coastguard Worker GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
7803*8975f5c5SAndroid Build Coastguard Worker const gl::BufferID *bufferIDs =
7804*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("buffersPacked", ParamType::TBufferIDPointer, 1)
7805*8975f5c5SAndroid Build Coastguard Worker .value.BufferIDPointerVal;
7806*8975f5c5SAndroid Build Coastguard Worker for (GLsizei i = 0; i < count; i++)
7807*8975f5c5SAndroid Build Coastguard Worker {
7808*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, bufferIDs[i]);
7809*8975f5c5SAndroid Build Coastguard Worker }
7810*8975f5c5SAndroid Build Coastguard Worker break;
7811*8975f5c5SAndroid Build Coastguard Worker }
7812*8975f5c5SAndroid Build Coastguard Worker
7813*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBindBuffer:
7814*8975f5c5SAndroid Build Coastguard Worker maybeGenResourceOnBind<gl::BufferID>(context, call);
7815*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
7816*8975f5c5SAndroid Build Coastguard Worker {
7817*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding binding =
7818*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("targetPacked", ParamType::TBufferBinding, 0)
7819*8975f5c5SAndroid Build Coastguard Worker .value.BufferBindingVal;
7820*8975f5c5SAndroid Build Coastguard Worker
7821*8975f5c5SAndroid Build Coastguard Worker context->getFrameCapture()->getStateResetHelper().setBufferBindingDirty(binding);
7822*8975f5c5SAndroid Build Coastguard Worker }
7823*8975f5c5SAndroid Build Coastguard Worker break;
7824*8975f5c5SAndroid Build Coastguard Worker
7825*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBindBufferBase:
7826*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBindBufferRange:
7827*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
7828*8975f5c5SAndroid Build Coastguard Worker {
7829*8975f5c5SAndroid Build Coastguard Worker WARN() << "Indexed buffer binding changed during capture, Reset doesn't handle it "
7830*8975f5c5SAndroid Build Coastguard Worker "yet.";
7831*8975f5c5SAndroid Build Coastguard Worker }
7832*8975f5c5SAndroid Build Coastguard Worker break;
7833*8975f5c5SAndroid Build Coastguard Worker
7834*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteProgramPipelines:
7835*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteProgramPipelinesEXT:
7836*8975f5c5SAndroid Build Coastguard Worker {
7837*8975f5c5SAndroid Build Coastguard Worker GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
7838*8975f5c5SAndroid Build Coastguard Worker const gl::ProgramPipelineID *pipelineIDs =
7839*8975f5c5SAndroid Build Coastguard Worker call.params
7840*8975f5c5SAndroid Build Coastguard Worker .getParam("pipelinesPacked", ParamType::TProgramPipelineIDConstPointer, 1)
7841*8975f5c5SAndroid Build Coastguard Worker .value.ProgramPipelineIDPointerVal;
7842*8975f5c5SAndroid Build Coastguard Worker for (GLsizei i = 0; i < count; i++)
7843*8975f5c5SAndroid Build Coastguard Worker {
7844*8975f5c5SAndroid Build Coastguard Worker handleDeletedResource(context, pipelineIDs[i]);
7845*8975f5c5SAndroid Build Coastguard Worker }
7846*8975f5c5SAndroid Build Coastguard Worker break;
7847*8975f5c5SAndroid Build Coastguard Worker }
7848*8975f5c5SAndroid Build Coastguard Worker
7849*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenProgramPipelines:
7850*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenProgramPipelinesEXT:
7851*8975f5c5SAndroid Build Coastguard Worker {
7852*8975f5c5SAndroid Build Coastguard Worker GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
7853*8975f5c5SAndroid Build Coastguard Worker const gl::ProgramPipelineID *pipelineIDs =
7854*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("pipelinesPacked", ParamType::TProgramPipelineIDPointer, 1)
7855*8975f5c5SAndroid Build Coastguard Worker .value.ProgramPipelineIDPointerVal;
7856*8975f5c5SAndroid Build Coastguard Worker for (GLsizei i = 0; i < count; i++)
7857*8975f5c5SAndroid Build Coastguard Worker {
7858*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, pipelineIDs[i]);
7859*8975f5c5SAndroid Build Coastguard Worker }
7860*8975f5c5SAndroid Build Coastguard Worker break;
7861*8975f5c5SAndroid Build Coastguard Worker }
7862*8975f5c5SAndroid Build Coastguard Worker
7863*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteSync:
7864*8975f5c5SAndroid Build Coastguard Worker {
7865*8975f5c5SAndroid Build Coastguard Worker gl::SyncID sync =
7866*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("syncPacked", ParamType::TSyncID, 0).value.SyncIDVal;
7867*8975f5c5SAndroid Build Coastguard Worker FrameCaptureShared *frameCaptureShared =
7868*8975f5c5SAndroid Build Coastguard Worker context->getShareGroup()->getFrameCaptureShared();
7869*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track which fence sync has been deleted
7870*8975f5c5SAndroid Build Coastguard Worker if (frameCaptureShared->isCaptureActive())
7871*8975f5c5SAndroid Build Coastguard Worker {
7872*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.setDeletedFenceSync(sync);
7873*8975f5c5SAndroid Build Coastguard Worker }
7874*8975f5c5SAndroid Build Coastguard Worker break;
7875*8975f5c5SAndroid Build Coastguard Worker }
7876*8975f5c5SAndroid Build Coastguard Worker
7877*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDrawArrays:
7878*8975f5c5SAndroid Build Coastguard Worker {
7879*8975f5c5SAndroid Build Coastguard Worker maybeCaptureDrawArraysClientData(context, call, 1);
7880*8975f5c5SAndroid Build Coastguard Worker maybeCaptureCoherentBuffers(context);
7881*8975f5c5SAndroid Build Coastguard Worker break;
7882*8975f5c5SAndroid Build Coastguard Worker }
7883*8975f5c5SAndroid Build Coastguard Worker
7884*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDrawArraysInstanced:
7885*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDrawArraysInstancedANGLE:
7886*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDrawArraysInstancedEXT:
7887*8975f5c5SAndroid Build Coastguard Worker {
7888*8975f5c5SAndroid Build Coastguard Worker GLsizei instancecount =
7889*8975f5c5SAndroid Build Coastguard Worker call.params.getParamFlexName("instancecount", "primcount", ParamType::TGLsizei, 3)
7890*8975f5c5SAndroid Build Coastguard Worker .value.GLsizeiVal;
7891*8975f5c5SAndroid Build Coastguard Worker
7892*8975f5c5SAndroid Build Coastguard Worker maybeCaptureDrawArraysClientData(context, call, instancecount);
7893*8975f5c5SAndroid Build Coastguard Worker maybeCaptureCoherentBuffers(context);
7894*8975f5c5SAndroid Build Coastguard Worker break;
7895*8975f5c5SAndroid Build Coastguard Worker }
7896*8975f5c5SAndroid Build Coastguard Worker
7897*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDrawElements:
7898*8975f5c5SAndroid Build Coastguard Worker {
7899*8975f5c5SAndroid Build Coastguard Worker maybeCaptureDrawElementsClientData(context, call, 1);
7900*8975f5c5SAndroid Build Coastguard Worker maybeCaptureCoherentBuffers(context);
7901*8975f5c5SAndroid Build Coastguard Worker break;
7902*8975f5c5SAndroid Build Coastguard Worker }
7903*8975f5c5SAndroid Build Coastguard Worker
7904*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDrawElementsInstanced:
7905*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDrawElementsInstancedANGLE:
7906*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDrawElementsInstancedEXT:
7907*8975f5c5SAndroid Build Coastguard Worker {
7908*8975f5c5SAndroid Build Coastguard Worker GLsizei instancecount =
7909*8975f5c5SAndroid Build Coastguard Worker call.params.getParamFlexName("instancecount", "primcount", ParamType::TGLsizei, 4)
7910*8975f5c5SAndroid Build Coastguard Worker .value.GLsizeiVal;
7911*8975f5c5SAndroid Build Coastguard Worker
7912*8975f5c5SAndroid Build Coastguard Worker maybeCaptureDrawElementsClientData(context, call, instancecount);
7913*8975f5c5SAndroid Build Coastguard Worker maybeCaptureCoherentBuffers(context);
7914*8975f5c5SAndroid Build Coastguard Worker break;
7915*8975f5c5SAndroid Build Coastguard Worker }
7916*8975f5c5SAndroid Build Coastguard Worker
7917*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCreateShaderProgramv:
7918*8975f5c5SAndroid Build Coastguard Worker {
7919*8975f5c5SAndroid Build Coastguard Worker // Refresh the cached shader sources.
7920*8975f5c5SAndroid Build Coastguard Worker // The command CreateShaderProgramv() creates a stand-alone program from an array of
7921*8975f5c5SAndroid Build Coastguard Worker // null-terminated source code strings for a single shader type, so we need update the
7922*8975f5c5SAndroid Build Coastguard Worker // Shader and Program sources, similar to GLCompileShader + GLLinkProgram handling.
7923*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID programID = {call.params.getReturnValue().value.GLuintVal};
7924*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶mCapture =
7925*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("typePacked", ParamType::TShaderType, 0);
7926*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &lineCount = call.params.getParam("count", ParamType::TGLsizei, 1);
7927*8975f5c5SAndroid Build Coastguard Worker const ParamCapture &strings =
7928*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("strings", ParamType::TGLcharConstPointerPointer, 2);
7929*8975f5c5SAndroid Build Coastguard Worker
7930*8975f5c5SAndroid Build Coastguard Worker std::ostringstream sourceString;
7931*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < lineCount.value.GLsizeiVal; ++i)
7932*8975f5c5SAndroid Build Coastguard Worker {
7933*8975f5c5SAndroid Build Coastguard Worker sourceString << strings.value.GLcharConstPointerPointerVal[i];
7934*8975f5c5SAndroid Build Coastguard Worker }
7935*8975f5c5SAndroid Build Coastguard Worker
7936*8975f5c5SAndroid Build Coastguard Worker gl::ShaderType shaderType = paramCapture.value.ShaderTypeVal;
7937*8975f5c5SAndroid Build Coastguard Worker ProgramSources source;
7938*8975f5c5SAndroid Build Coastguard Worker source[shaderType] = sourceString.str();
7939*8975f5c5SAndroid Build Coastguard Worker setProgramSources(programID, source);
7940*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, programID);
7941*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.setShaderProgramType(programID, ShaderProgramType::ProgramType);
7942*8975f5c5SAndroid Build Coastguard Worker break;
7943*8975f5c5SAndroid Build Coastguard Worker }
7944*8975f5c5SAndroid Build Coastguard Worker
7945*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCreateProgram:
7946*8975f5c5SAndroid Build Coastguard Worker {
7947*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track which programs have been created
7948*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID programID = {call.params.getReturnValue().value.GLuintVal};
7949*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, programID);
7950*8975f5c5SAndroid Build Coastguard Worker
7951*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.setShaderProgramType(programID, ShaderProgramType::ProgramType);
7952*8975f5c5SAndroid Build Coastguard Worker break;
7953*8975f5c5SAndroid Build Coastguard Worker }
7954*8975f5c5SAndroid Build Coastguard Worker
7955*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteProgram:
7956*8975f5c5SAndroid Build Coastguard Worker {
7957*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track which programs have been deleted
7958*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶m =
7959*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("programPacked", ParamType::TShaderProgramID, 0);
7960*8975f5c5SAndroid Build Coastguard Worker handleDeletedResource(context, param.value.ShaderProgramIDVal);
7961*8975f5c5SAndroid Build Coastguard Worker
7962*8975f5c5SAndroid Build Coastguard Worker // If this assert fires, it means a ShaderProgramID has changed from program to shader
7963*8975f5c5SAndroid Build Coastguard Worker // which is unsupported
7964*8975f5c5SAndroid Build Coastguard Worker ASSERT(mResourceTracker.getShaderProgramType(param.value.ShaderProgramIDVal) ==
7965*8975f5c5SAndroid Build Coastguard Worker ShaderProgramType::ProgramType);
7966*8975f5c5SAndroid Build Coastguard Worker
7967*8975f5c5SAndroid Build Coastguard Worker break;
7968*8975f5c5SAndroid Build Coastguard Worker }
7969*8975f5c5SAndroid Build Coastguard Worker
7970*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCreateShader:
7971*8975f5c5SAndroid Build Coastguard Worker {
7972*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track which shaders have been created
7973*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID shaderID = {call.params.getReturnValue().value.GLuintVal};
7974*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, shaderID);
7975*8975f5c5SAndroid Build Coastguard Worker
7976*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.setShaderProgramType(shaderID, ShaderProgramType::ShaderType);
7977*8975f5c5SAndroid Build Coastguard Worker break;
7978*8975f5c5SAndroid Build Coastguard Worker }
7979*8975f5c5SAndroid Build Coastguard Worker
7980*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteShader:
7981*8975f5c5SAndroid Build Coastguard Worker {
7982*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track which shaders have been deleted
7983*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶m =
7984*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("shaderPacked", ParamType::TShaderProgramID, 0);
7985*8975f5c5SAndroid Build Coastguard Worker handleDeletedResource(context, param.value.ShaderProgramIDVal);
7986*8975f5c5SAndroid Build Coastguard Worker
7987*8975f5c5SAndroid Build Coastguard Worker // If this assert fires, it means a ShaderProgramID has changed from shader to program
7988*8975f5c5SAndroid Build Coastguard Worker // which is unsupported
7989*8975f5c5SAndroid Build Coastguard Worker ASSERT(mResourceTracker.getShaderProgramType(param.value.ShaderProgramIDVal) ==
7990*8975f5c5SAndroid Build Coastguard Worker ShaderProgramType::ShaderType);
7991*8975f5c5SAndroid Build Coastguard Worker break;
7992*8975f5c5SAndroid Build Coastguard Worker }
7993*8975f5c5SAndroid Build Coastguard Worker
7994*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCompileShader:
7995*8975f5c5SAndroid Build Coastguard Worker {
7996*8975f5c5SAndroid Build Coastguard Worker // Refresh the cached shader sources.
7997*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID shaderID =
7998*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("shaderPacked", ParamType::TShaderProgramID, 0)
7999*8975f5c5SAndroid Build Coastguard Worker .value.ShaderProgramIDVal;
8000*8975f5c5SAndroid Build Coastguard Worker const gl::Shader *shader = context->getShaderNoResolveCompile(shaderID);
8001*8975f5c5SAndroid Build Coastguard Worker // Shaders compiled for ProgramBinary will not have a shader created
8002*8975f5c5SAndroid Build Coastguard Worker if (shader)
8003*8975f5c5SAndroid Build Coastguard Worker {
8004*8975f5c5SAndroid Build Coastguard Worker setShaderSource(shaderID, shader->getSourceString());
8005*8975f5c5SAndroid Build Coastguard Worker }
8006*8975f5c5SAndroid Build Coastguard Worker break;
8007*8975f5c5SAndroid Build Coastguard Worker }
8008*8975f5c5SAndroid Build Coastguard Worker
8009*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLLinkProgram:
8010*8975f5c5SAndroid Build Coastguard Worker {
8011*8975f5c5SAndroid Build Coastguard Worker // Refresh the cached program sources.
8012*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID programID =
8013*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("programPacked", ParamType::TShaderProgramID, 0)
8014*8975f5c5SAndroid Build Coastguard Worker .value.ShaderProgramIDVal;
8015*8975f5c5SAndroid Build Coastguard Worker const gl::Program *program = context->getProgramResolveLink(programID);
8016*8975f5c5SAndroid Build Coastguard Worker // Programs linked in support of ProgramBinary will not have attached shaders
8017*8975f5c5SAndroid Build Coastguard Worker if (program->getState().hasAnyAttachedShader())
8018*8975f5c5SAndroid Build Coastguard Worker {
8019*8975f5c5SAndroid Build Coastguard Worker setProgramSources(programID, GetAttachedProgramSources(context, program));
8020*8975f5c5SAndroid Build Coastguard Worker }
8021*8975f5c5SAndroid Build Coastguard Worker break;
8022*8975f5c5SAndroid Build Coastguard Worker }
8023*8975f5c5SAndroid Build Coastguard Worker
8024*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteTextures:
8025*8975f5c5SAndroid Build Coastguard Worker {
8026*8975f5c5SAndroid Build Coastguard Worker // Free any TextureLevelDataMap entries being tracked for this texture
8027*8975f5c5SAndroid Build Coastguard Worker // This is to cover the scenario where a texture has been created, its
8028*8975f5c5SAndroid Build Coastguard Worker // levels cached, then texture deleted and recreated, receiving the same ID
8029*8975f5c5SAndroid Build Coastguard Worker
8030*8975f5c5SAndroid Build Coastguard Worker // Look up how many textures are being deleted
8031*8975f5c5SAndroid Build Coastguard Worker GLsizei n = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
8032*8975f5c5SAndroid Build Coastguard Worker
8033*8975f5c5SAndroid Build Coastguard Worker // Look up the pointer to list of textures
8034*8975f5c5SAndroid Build Coastguard Worker const gl::TextureID *textureIDs =
8035*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("texturesPacked", ParamType::TTextureIDConstPointer, 1)
8036*8975f5c5SAndroid Build Coastguard Worker .value.TextureIDConstPointerVal;
8037*8975f5c5SAndroid Build Coastguard Worker
8038*8975f5c5SAndroid Build Coastguard Worker // For each texture listed for deletion
8039*8975f5c5SAndroid Build Coastguard Worker for (int32_t i = 0; i < n; ++i)
8040*8975f5c5SAndroid Build Coastguard Worker {
8041*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track what textures have been deleted
8042*8975f5c5SAndroid Build Coastguard Worker handleDeletedResource(context, textureIDs[i]);
8043*8975f5c5SAndroid Build Coastguard Worker }
8044*8975f5c5SAndroid Build Coastguard Worker break;
8045*8975f5c5SAndroid Build Coastguard Worker }
8046*8975f5c5SAndroid Build Coastguard Worker
8047*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLMapBufferOES:
8048*8975f5c5SAndroid Build Coastguard Worker {
8049*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding target =
8050*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("targetPacked", ParamType::TBufferBinding, 0)
8051*8975f5c5SAndroid Build Coastguard Worker .value.BufferBindingVal;
8052*8975f5c5SAndroid Build Coastguard Worker
8053*8975f5c5SAndroid Build Coastguard Worker GLbitfield access =
8054*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("access", ParamType::TGLenum, 1).value.GLenumVal;
8055*8975f5c5SAndroid Build Coastguard Worker
8056*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = context->getState().getTargetBuffer(target);
8057*8975f5c5SAndroid Build Coastguard Worker
8058*8975f5c5SAndroid Build Coastguard Worker GLintptr offset = 0;
8059*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr length = static_cast<GLsizeiptr>(buffer->getSize());
8060*8975f5c5SAndroid Build Coastguard Worker
8061*8975f5c5SAndroid Build Coastguard Worker bool writable =
8062*8975f5c5SAndroid Build Coastguard Worker access == GL_WRITE_ONLY_OES || access == GL_WRITE_ONLY || access == GL_READ_WRITE;
8063*8975f5c5SAndroid Build Coastguard Worker
8064*8975f5c5SAndroid Build Coastguard Worker FrameCaptureShared *frameCaptureShared =
8065*8975f5c5SAndroid Build Coastguard Worker context->getShareGroup()->getFrameCaptureShared();
8066*8975f5c5SAndroid Build Coastguard Worker frameCaptureShared->trackBufferMapping(context, &call, buffer->id(), buffer, offset,
8067*8975f5c5SAndroid Build Coastguard Worker length, writable, false);
8068*8975f5c5SAndroid Build Coastguard Worker break;
8069*8975f5c5SAndroid Build Coastguard Worker }
8070*8975f5c5SAndroid Build Coastguard Worker
8071*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUnmapBuffer:
8072*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUnmapBufferOES:
8073*8975f5c5SAndroid Build Coastguard Worker {
8074*8975f5c5SAndroid Build Coastguard Worker // See if we need to capture the buffer contents
8075*8975f5c5SAndroid Build Coastguard Worker captureMappedBufferSnapshot(context, call);
8076*8975f5c5SAndroid Build Coastguard Worker
8077*8975f5c5SAndroid Build Coastguard Worker // Track that the buffer was unmapped, for use during state reset
8078*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding target =
8079*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("targetPacked", ParamType::TBufferBinding, 0)
8080*8975f5c5SAndroid Build Coastguard Worker .value.BufferBindingVal;
8081*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = context->getState().getTargetBuffer(target);
8082*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.setBufferUnmapped(context->id(), buffer->id().value);
8083*8975f5c5SAndroid Build Coastguard Worker
8084*8975f5c5SAndroid Build Coastguard Worker // Remove from CoherentBufferTracker
8085*8975f5c5SAndroid Build Coastguard Worker mCoherentBufferTracker.removeBuffer(buffer->id());
8086*8975f5c5SAndroid Build Coastguard Worker break;
8087*8975f5c5SAndroid Build Coastguard Worker }
8088*8975f5c5SAndroid Build Coastguard Worker
8089*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBufferData:
8090*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBufferSubData:
8091*8975f5c5SAndroid Build Coastguard Worker {
8092*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding target =
8093*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("targetPacked", ParamType::TBufferBinding, 0)
8094*8975f5c5SAndroid Build Coastguard Worker .value.BufferBindingVal;
8095*8975f5c5SAndroid Build Coastguard Worker
8096*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = context->getState().getTargetBuffer(target);
8097*8975f5c5SAndroid Build Coastguard Worker
8098*8975f5c5SAndroid Build Coastguard Worker // Track that this buffer's contents have been modified
8099*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.getTrackedResource(context->id(), ResourceIDType::Buffer)
8100*8975f5c5SAndroid Build Coastguard Worker .setModifiedResource(buffer->id().value);
8101*8975f5c5SAndroid Build Coastguard Worker
8102*8975f5c5SAndroid Build Coastguard Worker // BufferData is equivalent to UnmapBuffer, for what we're tracking.
8103*8975f5c5SAndroid Build Coastguard Worker // From the ES 3.1 spec in BufferData section:
8104*8975f5c5SAndroid Build Coastguard Worker // If any portion of the buffer object is mapped in the current context or any
8105*8975f5c5SAndroid Build Coastguard Worker // context current to another thread, it is as though UnmapBuffer (see section
8106*8975f5c5SAndroid Build Coastguard Worker // 6.3.1) is executed in each such context prior to deleting the existing data
8107*8975f5c5SAndroid Build Coastguard Worker // store.
8108*8975f5c5SAndroid Build Coastguard Worker // Track that the buffer was unmapped, for use during state reset
8109*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.setBufferUnmapped(context->id(), buffer->id().value);
8110*8975f5c5SAndroid Build Coastguard Worker
8111*8975f5c5SAndroid Build Coastguard Worker break;
8112*8975f5c5SAndroid Build Coastguard Worker }
8113*8975f5c5SAndroid Build Coastguard Worker
8114*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyBufferSubData:
8115*8975f5c5SAndroid Build Coastguard Worker {
8116*8975f5c5SAndroid Build Coastguard Worker maybeCaptureCoherentBuffers(context);
8117*8975f5c5SAndroid Build Coastguard Worker break;
8118*8975f5c5SAndroid Build Coastguard Worker }
8119*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLFinish:
8120*8975f5c5SAndroid Build Coastguard Worker {
8121*8975f5c5SAndroid Build Coastguard Worker // When using shadow memory we might need to synchronize it here.
8122*8975f5c5SAndroid Build Coastguard Worker if (mCoherentBufferTracker.isShadowMemoryEnabled())
8123*8975f5c5SAndroid Build Coastguard Worker {
8124*8975f5c5SAndroid Build Coastguard Worker mCoherentBufferTracker.maybeUpdateShadowMemory();
8125*8975f5c5SAndroid Build Coastguard Worker }
8126*8975f5c5SAndroid Build Coastguard Worker break;
8127*8975f5c5SAndroid Build Coastguard Worker }
8128*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteFramebuffers:
8129*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteFramebuffersOES:
8130*8975f5c5SAndroid Build Coastguard Worker {
8131*8975f5c5SAndroid Build Coastguard Worker // Look up how many framebuffers are being deleted
8132*8975f5c5SAndroid Build Coastguard Worker GLsizei n = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
8133*8975f5c5SAndroid Build Coastguard Worker
8134*8975f5c5SAndroid Build Coastguard Worker // Look up the pointer to list of framebuffers
8135*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferID *framebufferIDs =
8136*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("framebuffersPacked", ParamType::TFramebufferIDConstPointer, 1)
8137*8975f5c5SAndroid Build Coastguard Worker .value.FramebufferIDConstPointerVal;
8138*8975f5c5SAndroid Build Coastguard Worker
8139*8975f5c5SAndroid Build Coastguard Worker // For each framebuffer listed for deletion
8140*8975f5c5SAndroid Build Coastguard Worker for (int32_t i = 0; i < n; ++i)
8141*8975f5c5SAndroid Build Coastguard Worker {
8142*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track what framebuffers have been deleted
8143*8975f5c5SAndroid Build Coastguard Worker handleDeletedResource(context, framebufferIDs[i]);
8144*8975f5c5SAndroid Build Coastguard Worker }
8145*8975f5c5SAndroid Build Coastguard Worker break;
8146*8975f5c5SAndroid Build Coastguard Worker }
8147*8975f5c5SAndroid Build Coastguard Worker
8148*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUseProgram:
8149*8975f5c5SAndroid Build Coastguard Worker {
8150*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8151*8975f5c5SAndroid Build Coastguard Worker {
8152*8975f5c5SAndroid Build Coastguard Worker context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
8153*8975f5c5SAndroid Build Coastguard Worker EntryPoint::GLUseProgram);
8154*8975f5c5SAndroid Build Coastguard Worker }
8155*8975f5c5SAndroid Build Coastguard Worker break;
8156*8975f5c5SAndroid Build Coastguard Worker }
8157*8975f5c5SAndroid Build Coastguard Worker
8158*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenVertexArrays:
8159*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLGenVertexArraysOES:
8160*8975f5c5SAndroid Build Coastguard Worker {
8161*8975f5c5SAndroid Build Coastguard Worker GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
8162*8975f5c5SAndroid Build Coastguard Worker const gl::VertexArrayID *arrayIDs =
8163*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("arraysPacked", ParamType::TVertexArrayIDPointer, 1)
8164*8975f5c5SAndroid Build Coastguard Worker .value.VertexArrayIDPointerVal;
8165*8975f5c5SAndroid Build Coastguard Worker for (GLsizei i = 0; i < count; i++)
8166*8975f5c5SAndroid Build Coastguard Worker {
8167*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, arrayIDs[i]);
8168*8975f5c5SAndroid Build Coastguard Worker }
8169*8975f5c5SAndroid Build Coastguard Worker break;
8170*8975f5c5SAndroid Build Coastguard Worker }
8171*8975f5c5SAndroid Build Coastguard Worker
8172*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteVertexArrays:
8173*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteVertexArraysOES:
8174*8975f5c5SAndroid Build Coastguard Worker {
8175*8975f5c5SAndroid Build Coastguard Worker GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
8176*8975f5c5SAndroid Build Coastguard Worker const gl::VertexArrayID *arrayIDs =
8177*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("arraysPacked", ParamType::TVertexArrayIDConstPointer, 1)
8178*8975f5c5SAndroid Build Coastguard Worker .value.VertexArrayIDConstPointerVal;
8179*8975f5c5SAndroid Build Coastguard Worker for (GLsizei i = 0; i < count; i++)
8180*8975f5c5SAndroid Build Coastguard Worker {
8181*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track which vertex arrays have been deleted
8182*8975f5c5SAndroid Build Coastguard Worker handleDeletedResource(context, arrayIDs[i]);
8183*8975f5c5SAndroid Build Coastguard Worker }
8184*8975f5c5SAndroid Build Coastguard Worker break;
8185*8975f5c5SAndroid Build Coastguard Worker }
8186*8975f5c5SAndroid Build Coastguard Worker
8187*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBindVertexArray:
8188*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBindVertexArrayOES:
8189*8975f5c5SAndroid Build Coastguard Worker {
8190*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8191*8975f5c5SAndroid Build Coastguard Worker {
8192*8975f5c5SAndroid Build Coastguard Worker context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
8193*8975f5c5SAndroid Build Coastguard Worker EntryPoint::GLBindVertexArray);
8194*8975f5c5SAndroid Build Coastguard Worker }
8195*8975f5c5SAndroid Build Coastguard Worker break;
8196*8975f5c5SAndroid Build Coastguard Worker }
8197*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBlendFunc:
8198*8975f5c5SAndroid Build Coastguard Worker {
8199*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8200*8975f5c5SAndroid Build Coastguard Worker {
8201*8975f5c5SAndroid Build Coastguard Worker context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
8202*8975f5c5SAndroid Build Coastguard Worker EntryPoint::GLBlendFunc);
8203*8975f5c5SAndroid Build Coastguard Worker }
8204*8975f5c5SAndroid Build Coastguard Worker break;
8205*8975f5c5SAndroid Build Coastguard Worker }
8206*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBlendFuncSeparate:
8207*8975f5c5SAndroid Build Coastguard Worker {
8208*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8209*8975f5c5SAndroid Build Coastguard Worker {
8210*8975f5c5SAndroid Build Coastguard Worker context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
8211*8975f5c5SAndroid Build Coastguard Worker EntryPoint::GLBlendFuncSeparate);
8212*8975f5c5SAndroid Build Coastguard Worker }
8213*8975f5c5SAndroid Build Coastguard Worker break;
8214*8975f5c5SAndroid Build Coastguard Worker }
8215*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBlendEquation:
8216*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBlendEquationSeparate:
8217*8975f5c5SAndroid Build Coastguard Worker {
8218*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8219*8975f5c5SAndroid Build Coastguard Worker {
8220*8975f5c5SAndroid Build Coastguard Worker context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
8221*8975f5c5SAndroid Build Coastguard Worker EntryPoint::GLBlendEquationSeparate);
8222*8975f5c5SAndroid Build Coastguard Worker }
8223*8975f5c5SAndroid Build Coastguard Worker break;
8224*8975f5c5SAndroid Build Coastguard Worker }
8225*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLColorMask:
8226*8975f5c5SAndroid Build Coastguard Worker {
8227*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8228*8975f5c5SAndroid Build Coastguard Worker {
8229*8975f5c5SAndroid Build Coastguard Worker context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
8230*8975f5c5SAndroid Build Coastguard Worker EntryPoint::GLColorMask);
8231*8975f5c5SAndroid Build Coastguard Worker }
8232*8975f5c5SAndroid Build Coastguard Worker break;
8233*8975f5c5SAndroid Build Coastguard Worker }
8234*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBlendColor:
8235*8975f5c5SAndroid Build Coastguard Worker {
8236*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8237*8975f5c5SAndroid Build Coastguard Worker {
8238*8975f5c5SAndroid Build Coastguard Worker context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
8239*8975f5c5SAndroid Build Coastguard Worker EntryPoint::GLBlendColor);
8240*8975f5c5SAndroid Build Coastguard Worker }
8241*8975f5c5SAndroid Build Coastguard Worker break;
8242*8975f5c5SAndroid Build Coastguard Worker }
8243*8975f5c5SAndroid Build Coastguard Worker
8244*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLEGLImageTargetTexture2DOES:
8245*8975f5c5SAndroid Build Coastguard Worker {
8246*8975f5c5SAndroid Build Coastguard Worker gl::TextureType target =
8247*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("targetPacked", ParamType::TTextureType, 0)
8248*8975f5c5SAndroid Build Coastguard Worker .value.TextureTypeVal;
8249*8975f5c5SAndroid Build Coastguard Worker egl::ImageID imageID =
8250*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("imagePacked", ParamType::TImageID, 1).value.ImageIDVal;
8251*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.getTextureIDToImageTable().insert(std::pair<GLuint, egl::ImageID>(
8252*8975f5c5SAndroid Build Coastguard Worker context->getState().getTargetTexture(target)->getId(), imageID));
8253*8975f5c5SAndroid Build Coastguard Worker break;
8254*8975f5c5SAndroid Build Coastguard Worker }
8255*8975f5c5SAndroid Build Coastguard Worker
8256*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLCreateImage:
8257*8975f5c5SAndroid Build Coastguard Worker {
8258*8975f5c5SAndroid Build Coastguard Worker CreateEGLImagePreCallUpdate<EGLAttrib>(call, mResourceTracker,
8259*8975f5c5SAndroid Build Coastguard Worker ParamType::TEGLAttribPointer,
8260*8975f5c5SAndroid Build Coastguard Worker egl::AttributeMap::CreateFromAttribArray);
8261*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8262*8975f5c5SAndroid Build Coastguard Worker {
8263*8975f5c5SAndroid Build Coastguard Worker EGLImage eglImage = call.params.getReturnValue().value.EGLImageVal;
8264*8975f5c5SAndroid Build Coastguard Worker egl::ImageID imageID = egl::PackParam<egl::ImageID>(eglImage);
8265*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, imageID);
8266*8975f5c5SAndroid Build Coastguard Worker }
8267*8975f5c5SAndroid Build Coastguard Worker break;
8268*8975f5c5SAndroid Build Coastguard Worker }
8269*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLCreateImageKHR:
8270*8975f5c5SAndroid Build Coastguard Worker {
8271*8975f5c5SAndroid Build Coastguard Worker CreateEGLImagePreCallUpdate<EGLint>(call, mResourceTracker, ParamType::TEGLintPointer,
8272*8975f5c5SAndroid Build Coastguard Worker egl::AttributeMap::CreateFromIntArray);
8273*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8274*8975f5c5SAndroid Build Coastguard Worker {
8275*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR eglImage = call.params.getReturnValue().value.EGLImageKHRVal;
8276*8975f5c5SAndroid Build Coastguard Worker egl::ImageID imageID = egl::PackParam<egl::ImageID>(eglImage);
8277*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, imageID);
8278*8975f5c5SAndroid Build Coastguard Worker }
8279*8975f5c5SAndroid Build Coastguard Worker break;
8280*8975f5c5SAndroid Build Coastguard Worker }
8281*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLDestroyImage:
8282*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLDestroyImageKHR:
8283*8975f5c5SAndroid Build Coastguard Worker {
8284*8975f5c5SAndroid Build Coastguard Worker egl::ImageID eglImageID =
8285*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("imagePacked", ParamType::TImageID, 1).value.ImageIDVal;
8286*8975f5c5SAndroid Build Coastguard Worker
8287*8975f5c5SAndroid Build Coastguard Worker // Clear any texture->image mappings that involve this image
8288*8975f5c5SAndroid Build Coastguard Worker for (auto texImageIter = mResourceTracker.getTextureIDToImageTable().begin();
8289*8975f5c5SAndroid Build Coastguard Worker texImageIter != mResourceTracker.getTextureIDToImageTable().end();)
8290*8975f5c5SAndroid Build Coastguard Worker {
8291*8975f5c5SAndroid Build Coastguard Worker if (texImageIter->second == eglImageID)
8292*8975f5c5SAndroid Build Coastguard Worker {
8293*8975f5c5SAndroid Build Coastguard Worker texImageIter = mResourceTracker.getTextureIDToImageTable().erase(texImageIter);
8294*8975f5c5SAndroid Build Coastguard Worker }
8295*8975f5c5SAndroid Build Coastguard Worker else
8296*8975f5c5SAndroid Build Coastguard Worker {
8297*8975f5c5SAndroid Build Coastguard Worker ++texImageIter;
8298*8975f5c5SAndroid Build Coastguard Worker }
8299*8975f5c5SAndroid Build Coastguard Worker }
8300*8975f5c5SAndroid Build Coastguard Worker
8301*8975f5c5SAndroid Build Coastguard Worker FrameCaptureShared *frameCaptureShared =
8302*8975f5c5SAndroid Build Coastguard Worker context->getShareGroup()->getFrameCaptureShared();
8303*8975f5c5SAndroid Build Coastguard Worker if (frameCaptureShared->isCaptureActive())
8304*8975f5c5SAndroid Build Coastguard Worker {
8305*8975f5c5SAndroid Build Coastguard Worker handleDeletedResource(context, eglImageID);
8306*8975f5c5SAndroid Build Coastguard Worker }
8307*8975f5c5SAndroid Build Coastguard Worker break;
8308*8975f5c5SAndroid Build Coastguard Worker }
8309*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLCreateSync:
8310*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLCreateSyncKHR:
8311*8975f5c5SAndroid Build Coastguard Worker {
8312*8975f5c5SAndroid Build Coastguard Worker egl::SyncID eglSyncID = call.params.getReturnValue().value.egl_SyncIDVal;
8313*8975f5c5SAndroid Build Coastguard Worker FrameCaptureShared *frameCaptureShared =
8314*8975f5c5SAndroid Build Coastguard Worker context->getShareGroup()->getFrameCaptureShared();
8315*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track which egl sync has been created
8316*8975f5c5SAndroid Build Coastguard Worker if (frameCaptureShared->isCaptureActive())
8317*8975f5c5SAndroid Build Coastguard Worker {
8318*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, eglSyncID);
8319*8975f5c5SAndroid Build Coastguard Worker }
8320*8975f5c5SAndroid Build Coastguard Worker break;
8321*8975f5c5SAndroid Build Coastguard Worker }
8322*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLDestroySync:
8323*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLDestroySyncKHR:
8324*8975f5c5SAndroid Build Coastguard Worker {
8325*8975f5c5SAndroid Build Coastguard Worker egl::SyncID eglSyncID =
8326*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("syncPacked", ParamType::Tegl_SyncID, 1).value.egl_SyncIDVal;
8327*8975f5c5SAndroid Build Coastguard Worker FrameCaptureShared *frameCaptureShared =
8328*8975f5c5SAndroid Build Coastguard Worker context->getShareGroup()->getFrameCaptureShared();
8329*8975f5c5SAndroid Build Coastguard Worker // If we're capturing, track which EGL sync has been deleted
8330*8975f5c5SAndroid Build Coastguard Worker if (frameCaptureShared->isCaptureActive())
8331*8975f5c5SAndroid Build Coastguard Worker {
8332*8975f5c5SAndroid Build Coastguard Worker handleDeletedResource(context, eglSyncID);
8333*8975f5c5SAndroid Build Coastguard Worker }
8334*8975f5c5SAndroid Build Coastguard Worker break;
8335*8975f5c5SAndroid Build Coastguard Worker }
8336*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDispatchCompute:
8337*8975f5c5SAndroid Build Coastguard Worker {
8338*8975f5c5SAndroid Build Coastguard Worker // When using shadow memory we need to update the real memory here
8339*8975f5c5SAndroid Build Coastguard Worker if (mCoherentBufferTracker.isShadowMemoryEnabled())
8340*8975f5c5SAndroid Build Coastguard Worker {
8341*8975f5c5SAndroid Build Coastguard Worker maybeCaptureCoherentBuffers(context);
8342*8975f5c5SAndroid Build Coastguard Worker }
8343*8975f5c5SAndroid Build Coastguard Worker break;
8344*8975f5c5SAndroid Build Coastguard Worker }
8345*8975f5c5SAndroid Build Coastguard Worker default:
8346*8975f5c5SAndroid Build Coastguard Worker break;
8347*8975f5c5SAndroid Build Coastguard Worker }
8348*8975f5c5SAndroid Build Coastguard Worker
8349*8975f5c5SAndroid Build Coastguard Worker if (IsTextureUpdate(call))
8350*8975f5c5SAndroid Build Coastguard Worker {
8351*8975f5c5SAndroid Build Coastguard Worker // If this call modified texture contents, track it for possible reset
8352*8975f5c5SAndroid Build Coastguard Worker trackTextureUpdate(context, call);
8353*8975f5c5SAndroid Build Coastguard Worker }
8354*8975f5c5SAndroid Build Coastguard Worker
8355*8975f5c5SAndroid Build Coastguard Worker if (IsImageUpdate(call))
8356*8975f5c5SAndroid Build Coastguard Worker {
8357*8975f5c5SAndroid Build Coastguard Worker // If this call modified shader image contents, track it for possible reset
8358*8975f5c5SAndroid Build Coastguard Worker trackImageUpdate(context, call);
8359*8975f5c5SAndroid Build Coastguard Worker }
8360*8975f5c5SAndroid Build Coastguard Worker
8361*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive() && GetDefaultUniformType(call) != DefaultUniformType::None)
8362*8975f5c5SAndroid Build Coastguard Worker {
8363*8975f5c5SAndroid Build Coastguard Worker trackDefaultUniformUpdate(context, call);
8364*8975f5c5SAndroid Build Coastguard Worker }
8365*8975f5c5SAndroid Build Coastguard Worker
8366*8975f5c5SAndroid Build Coastguard Worker if (IsVertexArrayUpdate(call))
8367*8975f5c5SAndroid Build Coastguard Worker {
8368*8975f5c5SAndroid Build Coastguard Worker trackVertexArrayUpdate(context, call);
8369*8975f5c5SAndroid Build Coastguard Worker }
8370*8975f5c5SAndroid Build Coastguard Worker
8371*8975f5c5SAndroid Build Coastguard Worker updateReadBufferSize(call.params.getReadBufferSize());
8372*8975f5c5SAndroid Build Coastguard Worker
8373*8975f5c5SAndroid Build Coastguard Worker std::vector<gl::ShaderProgramID> shaderProgramIDs;
8374*8975f5c5SAndroid Build Coastguard Worker if (FindResourceIDsInCall<gl::ShaderProgramID>(call, shaderProgramIDs))
8375*8975f5c5SAndroid Build Coastguard Worker {
8376*8975f5c5SAndroid Build Coastguard Worker for (gl::ShaderProgramID shaderProgramID : shaderProgramIDs)
8377*8975f5c5SAndroid Build Coastguard Worker {
8378*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.onShaderProgramAccess(shaderProgramID);
8379*8975f5c5SAndroid Build Coastguard Worker
8380*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8381*8975f5c5SAndroid Build Coastguard Worker {
8382*8975f5c5SAndroid Build Coastguard Worker // Track that this call referenced a ShaderProgram, setting it active for Setup
8383*8975f5c5SAndroid Build Coastguard Worker MarkResourceIDActive(ResourceIDType::ShaderProgram, shaderProgramID.value,
8384*8975f5c5SAndroid Build Coastguard Worker shareGroupSetupCalls, resourceIDToSetupCalls);
8385*8975f5c5SAndroid Build Coastguard Worker }
8386*8975f5c5SAndroid Build Coastguard Worker }
8387*8975f5c5SAndroid Build Coastguard Worker }
8388*8975f5c5SAndroid Build Coastguard Worker
8389*8975f5c5SAndroid Build Coastguard Worker std::vector<gl::TextureID> textureIDs;
8390*8975f5c5SAndroid Build Coastguard Worker if (FindResourceIDsInCall<gl::TextureID>(call, textureIDs))
8391*8975f5c5SAndroid Build Coastguard Worker {
8392*8975f5c5SAndroid Build Coastguard Worker for (gl::TextureID textureID : textureIDs)
8393*8975f5c5SAndroid Build Coastguard Worker {
8394*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8395*8975f5c5SAndroid Build Coastguard Worker {
8396*8975f5c5SAndroid Build Coastguard Worker // Track that this call referenced a Texture, setting it active for Setup
8397*8975f5c5SAndroid Build Coastguard Worker MarkResourceIDActive(ResourceIDType::Texture, textureID.value, shareGroupSetupCalls,
8398*8975f5c5SAndroid Build Coastguard Worker resourceIDToSetupCalls);
8399*8975f5c5SAndroid Build Coastguard Worker }
8400*8975f5c5SAndroid Build Coastguard Worker }
8401*8975f5c5SAndroid Build Coastguard Worker }
8402*8975f5c5SAndroid Build Coastguard Worker }
8403*8975f5c5SAndroid Build Coastguard Worker
8404*8975f5c5SAndroid Build Coastguard Worker template <typename ParamValueType>
maybeGenResourceOnBind(const gl::Context * context,CallCapture & call)8405*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::maybeGenResourceOnBind(const gl::Context *context, CallCapture &call)
8406*8975f5c5SAndroid Build Coastguard Worker {
8407*8975f5c5SAndroid Build Coastguard Worker const char *paramName = ParamValueTrait<ParamValueType>::name;
8408*8975f5c5SAndroid Build Coastguard Worker const ParamType paramType = ParamValueTrait<ParamValueType>::typeID;
8409*8975f5c5SAndroid Build Coastguard Worker
8410*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶m = call.params.getParam(paramName, paramType, 1);
8411*8975f5c5SAndroid Build Coastguard Worker const ParamValueType id = AccessParamValue<ParamValueType>(paramType, param.value);
8412*8975f5c5SAndroid Build Coastguard Worker
8413*8975f5c5SAndroid Build Coastguard Worker // Don't inject the default resource or resources that are already generated
8414*8975f5c5SAndroid Build Coastguard Worker if (id.value != 0 && !resourceIsGenerated(context, id))
8415*8975f5c5SAndroid Build Coastguard Worker {
8416*8975f5c5SAndroid Build Coastguard Worker handleGennedResource(context, id);
8417*8975f5c5SAndroid Build Coastguard Worker
8418*8975f5c5SAndroid Build Coastguard Worker ResourceIDType resourceIDType = GetResourceIDTypeFromParamType(param.type);
8419*8975f5c5SAndroid Build Coastguard Worker const char *resourceName = GetResourceIDTypeName(resourceIDType);
8420*8975f5c5SAndroid Build Coastguard Worker
8421*8975f5c5SAndroid Build Coastguard Worker std::stringstream updateFuncNameStr;
8422*8975f5c5SAndroid Build Coastguard Worker updateFuncNameStr << "Set" << resourceName << "ID";
8423*8975f5c5SAndroid Build Coastguard Worker ParamBuffer params;
8424*8975f5c5SAndroid Build Coastguard Worker if (IsTrackedPerContext(resourceIDType))
8425*8975f5c5SAndroid Build Coastguard Worker {
8426*8975f5c5SAndroid Build Coastguard Worker // TODO (https://issuetracker.google.com/169868803) The '2' version can be removed after
8427*8975f5c5SAndroid Build Coastguard Worker // all context-local objects are tracked per-context
8428*8975f5c5SAndroid Build Coastguard Worker updateFuncNameStr << "2";
8429*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("contextID", ParamType::TGLuint, context->id().value);
8430*8975f5c5SAndroid Build Coastguard Worker }
8431*8975f5c5SAndroid Build Coastguard Worker std::string updateFuncName = updateFuncNameStr.str();
8432*8975f5c5SAndroid Build Coastguard Worker params.addValueParam("id", ParamType::TGLuint, id.value);
8433*8975f5c5SAndroid Build Coastguard Worker mFrameCalls.emplace_back(updateFuncName, std::move(params));
8434*8975f5c5SAndroid Build Coastguard Worker }
8435*8975f5c5SAndroid Build Coastguard Worker }
8436*8975f5c5SAndroid Build Coastguard Worker
updateResourceCountsFromParamCapture(const ParamCapture & param,ResourceIDType idType)8437*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::updateResourceCountsFromParamCapture(const ParamCapture ¶m,
8438*8975f5c5SAndroid Build Coastguard Worker ResourceIDType idType)
8439*8975f5c5SAndroid Build Coastguard Worker {
8440*8975f5c5SAndroid Build Coastguard Worker if (idType != ResourceIDType::InvalidEnum)
8441*8975f5c5SAndroid Build Coastguard Worker {
8442*8975f5c5SAndroid Build Coastguard Worker mHasResourceType.set(idType);
8443*8975f5c5SAndroid Build Coastguard Worker
8444*8975f5c5SAndroid Build Coastguard Worker // Capture resource IDs for non-pointer types.
8445*8975f5c5SAndroid Build Coastguard Worker if (strcmp(ParamTypeToString(param.type), "GLuint") == 0)
8446*8975f5c5SAndroid Build Coastguard Worker {
8447*8975f5c5SAndroid Build Coastguard Worker mMaxAccessedResourceIDs[idType] =
8448*8975f5c5SAndroid Build Coastguard Worker std::max(mMaxAccessedResourceIDs[idType], param.value.GLuintVal);
8449*8975f5c5SAndroid Build Coastguard Worker }
8450*8975f5c5SAndroid Build Coastguard Worker // Capture resource IDs for pointer types.
8451*8975f5c5SAndroid Build Coastguard Worker if (strstr(ParamTypeToString(param.type), "GLuint *") != nullptr)
8452*8975f5c5SAndroid Build Coastguard Worker {
8453*8975f5c5SAndroid Build Coastguard Worker if (param.data.size() == 1u)
8454*8975f5c5SAndroid Build Coastguard Worker {
8455*8975f5c5SAndroid Build Coastguard Worker const GLuint *dataPtr = reinterpret_cast<const GLuint *>(param.data[0].data());
8456*8975f5c5SAndroid Build Coastguard Worker size_t numHandles = param.data[0].size() / sizeof(GLuint);
8457*8975f5c5SAndroid Build Coastguard Worker for (size_t handleIndex = 0; handleIndex < numHandles; ++handleIndex)
8458*8975f5c5SAndroid Build Coastguard Worker {
8459*8975f5c5SAndroid Build Coastguard Worker mMaxAccessedResourceIDs[idType] =
8460*8975f5c5SAndroid Build Coastguard Worker std::max(mMaxAccessedResourceIDs[idType], dataPtr[handleIndex]);
8461*8975f5c5SAndroid Build Coastguard Worker }
8462*8975f5c5SAndroid Build Coastguard Worker }
8463*8975f5c5SAndroid Build Coastguard Worker }
8464*8975f5c5SAndroid Build Coastguard Worker if (idType == ResourceIDType::Sync)
8465*8975f5c5SAndroid Build Coastguard Worker {
8466*8975f5c5SAndroid Build Coastguard Worker mMaxAccessedResourceIDs[idType] =
8467*8975f5c5SAndroid Build Coastguard Worker std::max(mMaxAccessedResourceIDs[idType], param.value.GLuintVal);
8468*8975f5c5SAndroid Build Coastguard Worker }
8469*8975f5c5SAndroid Build Coastguard Worker }
8470*8975f5c5SAndroid Build Coastguard Worker }
8471*8975f5c5SAndroid Build Coastguard Worker
updateResourceCountsFromCallCapture(const CallCapture & call)8472*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::updateResourceCountsFromCallCapture(const CallCapture &call)
8473*8975f5c5SAndroid Build Coastguard Worker {
8474*8975f5c5SAndroid Build Coastguard Worker for (const ParamCapture ¶m : call.params.getParamCaptures())
8475*8975f5c5SAndroid Build Coastguard Worker {
8476*8975f5c5SAndroid Build Coastguard Worker ResourceIDType idType = GetResourceIDTypeFromParamType(param.type);
8477*8975f5c5SAndroid Build Coastguard Worker updateResourceCountsFromParamCapture(param, idType);
8478*8975f5c5SAndroid Build Coastguard Worker }
8479*8975f5c5SAndroid Build Coastguard Worker
8480*8975f5c5SAndroid Build Coastguard Worker // Update resource IDs in the return value. Return values types are not stored as resource IDs,
8481*8975f5c5SAndroid Build Coastguard Worker // but instead are stored as GLuints. Therefore we need to explicitly label the resource ID type
8482*8975f5c5SAndroid Build Coastguard Worker // when we call update. Currently only shader and program creation are explicitly tracked.
8483*8975f5c5SAndroid Build Coastguard Worker switch (call.entryPoint)
8484*8975f5c5SAndroid Build Coastguard Worker {
8485*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCreateShader:
8486*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCreateProgram:
8487*8975f5c5SAndroid Build Coastguard Worker updateResourceCountsFromParamCapture(call.params.getReturnValue(),
8488*8975f5c5SAndroid Build Coastguard Worker ResourceIDType::ShaderProgram);
8489*8975f5c5SAndroid Build Coastguard Worker break;
8490*8975f5c5SAndroid Build Coastguard Worker
8491*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLFenceSync:
8492*8975f5c5SAndroid Build Coastguard Worker updateResourceCountsFromParamCapture(call.params.getReturnValue(),
8493*8975f5c5SAndroid Build Coastguard Worker ResourceIDType::Sync);
8494*8975f5c5SAndroid Build Coastguard Worker break;
8495*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLCreateSync:
8496*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::EGLCreateSyncKHR:
8497*8975f5c5SAndroid Build Coastguard Worker updateResourceCountsFromParamCapture(call.params.getReturnValue(),
8498*8975f5c5SAndroid Build Coastguard Worker ResourceIDType::egl_Sync);
8499*8975f5c5SAndroid Build Coastguard Worker break;
8500*8975f5c5SAndroid Build Coastguard Worker default:
8501*8975f5c5SAndroid Build Coastguard Worker break;
8502*8975f5c5SAndroid Build Coastguard Worker }
8503*8975f5c5SAndroid Build Coastguard Worker }
8504*8975f5c5SAndroid Build Coastguard Worker
captureCall(gl::Context * context,CallCapture && inCall,bool isCallValid)8505*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::captureCall(gl::Context *context, CallCapture &&inCall, bool isCallValid)
8506*8975f5c5SAndroid Build Coastguard Worker {
8507*8975f5c5SAndroid Build Coastguard Worker if (SkipCall(inCall.entryPoint))
8508*8975f5c5SAndroid Build Coastguard Worker {
8509*8975f5c5SAndroid Build Coastguard Worker return;
8510*8975f5c5SAndroid Build Coastguard Worker }
8511*8975f5c5SAndroid Build Coastguard Worker
8512*8975f5c5SAndroid Build Coastguard Worker if (isCallValid)
8513*8975f5c5SAndroid Build Coastguard Worker {
8514*8975f5c5SAndroid Build Coastguard Worker // Save the call's contextID
8515*8975f5c5SAndroid Build Coastguard Worker inCall.contextID = context->id();
8516*8975f5c5SAndroid Build Coastguard Worker
8517*8975f5c5SAndroid Build Coastguard Worker // Update resource counts before we override entry points with custom calls.
8518*8975f5c5SAndroid Build Coastguard Worker updateResourceCountsFromCallCapture(inCall);
8519*8975f5c5SAndroid Build Coastguard Worker
8520*8975f5c5SAndroid Build Coastguard Worker size_t j = mFrameCalls.size();
8521*8975f5c5SAndroid Build Coastguard Worker
8522*8975f5c5SAndroid Build Coastguard Worker std::vector<CallCapture> outCalls;
8523*8975f5c5SAndroid Build Coastguard Worker maybeOverrideEntryPoint(context, inCall, outCalls);
8524*8975f5c5SAndroid Build Coastguard Worker
8525*8975f5c5SAndroid Build Coastguard Worker // Need to loop on any new calls we added during override
8526*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : outCalls)
8527*8975f5c5SAndroid Build Coastguard Worker {
8528*8975f5c5SAndroid Build Coastguard Worker // During capture, consider all frame calls active
8529*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8530*8975f5c5SAndroid Build Coastguard Worker {
8531*8975f5c5SAndroid Build Coastguard Worker call.isActive = true;
8532*8975f5c5SAndroid Build Coastguard Worker }
8533*8975f5c5SAndroid Build Coastguard Worker
8534*8975f5c5SAndroid Build Coastguard Worker maybeCapturePreCallUpdates(context, call, &mShareGroupSetupCalls,
8535*8975f5c5SAndroid Build Coastguard Worker &mResourceIDToSetupCalls);
8536*8975f5c5SAndroid Build Coastguard Worker mFrameCalls.emplace_back(std::move(call));
8537*8975f5c5SAndroid Build Coastguard Worker maybeCapturePostCallUpdates(context);
8538*8975f5c5SAndroid Build Coastguard Worker }
8539*8975f5c5SAndroid Build Coastguard Worker
8540*8975f5c5SAndroid Build Coastguard Worker // Tag all 'added' commands with this context
8541*8975f5c5SAndroid Build Coastguard Worker for (size_t k = j; k < mFrameCalls.size(); k++)
8542*8975f5c5SAndroid Build Coastguard Worker {
8543*8975f5c5SAndroid Build Coastguard Worker mFrameCalls[k].contextID = context->id();
8544*8975f5c5SAndroid Build Coastguard Worker }
8545*8975f5c5SAndroid Build Coastguard Worker
8546*8975f5c5SAndroid Build Coastguard Worker // Evaluate the validation expression to determine if we insert a validation checkpoint.
8547*8975f5c5SAndroid Build Coastguard Worker // This lets the user pick a subset of calls to check instead of checking every call.
8548*8975f5c5SAndroid Build Coastguard Worker if (mValidateSerializedState && !mValidationExpression.empty())
8549*8975f5c5SAndroid Build Coastguard Worker {
8550*8975f5c5SAndroid Build Coastguard Worker // Example substitution for frame #2, call #110:
8551*8975f5c5SAndroid Build Coastguard Worker // Before: (call == 2) && (frame >= 100) && (frame <= 120) && ((frame % 10) == 0)
8552*8975f5c5SAndroid Build Coastguard Worker // After: (2 == 2) && (110 >= 100) && (110 <= 120) && ((110 % 10) == 0)
8553*8975f5c5SAndroid Build Coastguard Worker // Evaluates to 1.0.
8554*8975f5c5SAndroid Build Coastguard Worker std::string expression = mValidationExpression;
8555*8975f5c5SAndroid Build Coastguard Worker
8556*8975f5c5SAndroid Build Coastguard Worker angle::ReplaceAllSubstrings(&expression, "frame", std::to_string(mFrameIndex));
8557*8975f5c5SAndroid Build Coastguard Worker angle::ReplaceAllSubstrings(&expression, "call", std::to_string(mFrameCalls.size()));
8558*8975f5c5SAndroid Build Coastguard Worker
8559*8975f5c5SAndroid Build Coastguard Worker double result = ceval_result(expression);
8560*8975f5c5SAndroid Build Coastguard Worker if (result > 0)
8561*8975f5c5SAndroid Build Coastguard Worker {
8562*8975f5c5SAndroid Build Coastguard Worker CaptureValidateSerializedState(context, &mFrameCalls);
8563*8975f5c5SAndroid Build Coastguard Worker }
8564*8975f5c5SAndroid Build Coastguard Worker }
8565*8975f5c5SAndroid Build Coastguard Worker }
8566*8975f5c5SAndroid Build Coastguard Worker else
8567*8975f5c5SAndroid Build Coastguard Worker {
8568*8975f5c5SAndroid Build Coastguard Worker const int maxInvalidCallLogs = 3;
8569*8975f5c5SAndroid Build Coastguard Worker size_t &callCount = isCaptureActive() ? mInvalidCallCountsActive[inCall.entryPoint]
8570*8975f5c5SAndroid Build Coastguard Worker : mInvalidCallCountsInactive[inCall.entryPoint];
8571*8975f5c5SAndroid Build Coastguard Worker callCount++;
8572*8975f5c5SAndroid Build Coastguard Worker if (callCount <= maxInvalidCallLogs)
8573*8975f5c5SAndroid Build Coastguard Worker {
8574*8975f5c5SAndroid Build Coastguard Worker std::ostringstream msg;
8575*8975f5c5SAndroid Build Coastguard Worker msg << "FrameCapture (capture " << (isCaptureActive() ? "active" : "inactive")
8576*8975f5c5SAndroid Build Coastguard Worker << "): Not capturing invalid call to " << GetEntryPointName(inCall.entryPoint);
8577*8975f5c5SAndroid Build Coastguard Worker if (callCount == maxInvalidCallLogs)
8578*8975f5c5SAndroid Build Coastguard Worker {
8579*8975f5c5SAndroid Build Coastguard Worker msg << " (will no longer repeat for this entry point)";
8580*8975f5c5SAndroid Build Coastguard Worker }
8581*8975f5c5SAndroid Build Coastguard Worker INFO() << msg.str();
8582*8975f5c5SAndroid Build Coastguard Worker }
8583*8975f5c5SAndroid Build Coastguard Worker
8584*8975f5c5SAndroid Build Coastguard Worker std::stringstream skipCall;
8585*8975f5c5SAndroid Build Coastguard Worker skipCall << "Skipping invalid call to " << GetEntryPointName(inCall.entryPoint)
8586*8975f5c5SAndroid Build Coastguard Worker << " with error: "
8587*8975f5c5SAndroid Build Coastguard Worker << gl::GLenumToString(gl::GLESEnum::ErrorCode, context->getErrorForCapture());
8588*8975f5c5SAndroid Build Coastguard Worker AddComment(&mFrameCalls, skipCall.str());
8589*8975f5c5SAndroid Build Coastguard Worker }
8590*8975f5c5SAndroid Build Coastguard Worker }
8591*8975f5c5SAndroid Build Coastguard Worker
maybeCapturePostCallUpdates(const gl::Context * context)8592*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::maybeCapturePostCallUpdates(const gl::Context *context)
8593*8975f5c5SAndroid Build Coastguard Worker {
8594*8975f5c5SAndroid Build Coastguard Worker // Process resource ID updates.
8595*8975f5c5SAndroid Build Coastguard Worker if (isCaptureActive())
8596*8975f5c5SAndroid Build Coastguard Worker {
8597*8975f5c5SAndroid Build Coastguard Worker MaybeCaptureUpdateResourceIDs(context, &mResourceTracker, &mFrameCalls);
8598*8975f5c5SAndroid Build Coastguard Worker }
8599*8975f5c5SAndroid Build Coastguard Worker
8600*8975f5c5SAndroid Build Coastguard Worker CallCapture &lastCall = mFrameCalls.back();
8601*8975f5c5SAndroid Build Coastguard Worker switch (lastCall.entryPoint)
8602*8975f5c5SAndroid Build Coastguard Worker {
8603*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCreateShaderProgramv:
8604*8975f5c5SAndroid Build Coastguard Worker {
8605*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID programId;
8606*8975f5c5SAndroid Build Coastguard Worker programId.value = lastCall.params.getReturnValue().value.GLuintVal;
8607*8975f5c5SAndroid Build Coastguard Worker const gl::Program *program = context->getProgramResolveLink(programId);
8608*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateUniformLocations(program, &mFrameCalls);
8609*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateUniformBlockIndexes(program, &mFrameCalls);
8610*8975f5c5SAndroid Build Coastguard Worker break;
8611*8975f5c5SAndroid Build Coastguard Worker }
8612*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLLinkProgram:
8613*8975f5c5SAndroid Build Coastguard Worker {
8614*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶m =
8615*8975f5c5SAndroid Build Coastguard Worker lastCall.params.getParam("programPacked", ParamType::TShaderProgramID, 0);
8616*8975f5c5SAndroid Build Coastguard Worker const gl::Program *program =
8617*8975f5c5SAndroid Build Coastguard Worker context->getProgramResolveLink(param.value.ShaderProgramIDVal);
8618*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateUniformLocations(program, &mFrameCalls);
8619*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateUniformBlockIndexes(program, &mFrameCalls);
8620*8975f5c5SAndroid Build Coastguard Worker break;
8621*8975f5c5SAndroid Build Coastguard Worker }
8622*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLUseProgram:
8623*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateCurrentProgram(lastCall, 0, &mFrameCalls);
8624*8975f5c5SAndroid Build Coastguard Worker break;
8625*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLActiveShaderProgram:
8626*8975f5c5SAndroid Build Coastguard Worker CaptureUpdateCurrentProgram(lastCall, 1, &mFrameCalls);
8627*8975f5c5SAndroid Build Coastguard Worker break;
8628*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDeleteProgram:
8629*8975f5c5SAndroid Build Coastguard Worker {
8630*8975f5c5SAndroid Build Coastguard Worker const ParamCapture ¶m =
8631*8975f5c5SAndroid Build Coastguard Worker lastCall.params.getParam("programPacked", ParamType::TShaderProgramID, 0);
8632*8975f5c5SAndroid Build Coastguard Worker CaptureDeleteUniformLocations(param.value.ShaderProgramIDVal, &mFrameCalls);
8633*8975f5c5SAndroid Build Coastguard Worker break;
8634*8975f5c5SAndroid Build Coastguard Worker }
8635*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLShaderSource:
8636*8975f5c5SAndroid Build Coastguard Worker {
8637*8975f5c5SAndroid Build Coastguard Worker lastCall.params.setValueParamAtIndex("count", ParamType::TGLsizei, 1, 1);
8638*8975f5c5SAndroid Build Coastguard Worker
8639*8975f5c5SAndroid Build Coastguard Worker ParamCapture ¶mLength =
8640*8975f5c5SAndroid Build Coastguard Worker lastCall.params.getParam("length", ParamType::TGLintConstPointer, 3);
8641*8975f5c5SAndroid Build Coastguard Worker paramLength.data.resize(1);
8642*8975f5c5SAndroid Build Coastguard Worker // Set the length parameter to {-1} to signal that the actual string length
8643*8975f5c5SAndroid Build Coastguard Worker // is to be used. Since we store the parameter blob as an array of four uint8_t
8644*8975f5c5SAndroid Build Coastguard Worker // values, we have to pass the binary equivalent of -1.
8645*8975f5c5SAndroid Build Coastguard Worker paramLength.data[0] = {0xff, 0xff, 0xff, 0xff};
8646*8975f5c5SAndroid Build Coastguard Worker break;
8647*8975f5c5SAndroid Build Coastguard Worker }
8648*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBufferData:
8649*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLBufferSubData:
8650*8975f5c5SAndroid Build Coastguard Worker {
8651*8975f5c5SAndroid Build Coastguard Worker // When using shadow memory we need to update it from real memory here
8652*8975f5c5SAndroid Build Coastguard Worker if (mCoherentBufferTracker.isShadowMemoryEnabled())
8653*8975f5c5SAndroid Build Coastguard Worker {
8654*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding target =
8655*8975f5c5SAndroid Build Coastguard Worker lastCall.params.getParam("targetPacked", ParamType::TBufferBinding, 0)
8656*8975f5c5SAndroid Build Coastguard Worker .value.BufferBindingVal;
8657*8975f5c5SAndroid Build Coastguard Worker
8658*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = context->getState().getTargetBuffer(target);
8659*8975f5c5SAndroid Build Coastguard Worker if (mCoherentBufferTracker.haveBuffer(buffer->id()))
8660*8975f5c5SAndroid Build Coastguard Worker {
8661*8975f5c5SAndroid Build Coastguard Worker std::shared_ptr<CoherentBuffer> cb =
8662*8975f5c5SAndroid Build Coastguard Worker mCoherentBufferTracker.mBuffers[buffer->id().value];
8663*8975f5c5SAndroid Build Coastguard Worker cb->removeProtection(PageSharingType::NoneShared);
8664*8975f5c5SAndroid Build Coastguard Worker cb->updateShadowMemory();
8665*8975f5c5SAndroid Build Coastguard Worker cb->protectAll();
8666*8975f5c5SAndroid Build Coastguard Worker }
8667*8975f5c5SAndroid Build Coastguard Worker }
8668*8975f5c5SAndroid Build Coastguard Worker break;
8669*8975f5c5SAndroid Build Coastguard Worker }
8670*8975f5c5SAndroid Build Coastguard Worker
8671*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLCopyBufferSubData:
8672*8975f5c5SAndroid Build Coastguard Worker {
8673*8975f5c5SAndroid Build Coastguard Worker // When using shadow memory, we need to mark the buffer shadowDirty bit to true
8674*8975f5c5SAndroid Build Coastguard Worker // so it will be synchronized with real memory on the next glFinish call.
8675*8975f5c5SAndroid Build Coastguard Worker if (mCoherentBufferTracker.isShadowMemoryEnabled())
8676*8975f5c5SAndroid Build Coastguard Worker {
8677*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding target =
8678*8975f5c5SAndroid Build Coastguard Worker lastCall.params.getParam("writeTargetPacked", ParamType::TBufferBinding, 1)
8679*8975f5c5SAndroid Build Coastguard Worker .value.BufferBindingVal;
8680*8975f5c5SAndroid Build Coastguard Worker
8681*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = context->getState().getTargetBuffer(target);
8682*8975f5c5SAndroid Build Coastguard Worker if (mCoherentBufferTracker.haveBuffer(buffer->id()))
8683*8975f5c5SAndroid Build Coastguard Worker {
8684*8975f5c5SAndroid Build Coastguard Worker std::shared_ptr<CoherentBuffer> cb =
8685*8975f5c5SAndroid Build Coastguard Worker mCoherentBufferTracker.mBuffers[buffer->id().value];
8686*8975f5c5SAndroid Build Coastguard Worker // This needs to be synced on glFinish
8687*8975f5c5SAndroid Build Coastguard Worker cb->markShadowDirty();
8688*8975f5c5SAndroid Build Coastguard Worker }
8689*8975f5c5SAndroid Build Coastguard Worker }
8690*8975f5c5SAndroid Build Coastguard Worker break;
8691*8975f5c5SAndroid Build Coastguard Worker }
8692*8975f5c5SAndroid Build Coastguard Worker case EntryPoint::GLDispatchCompute:
8693*8975f5c5SAndroid Build Coastguard Worker {
8694*8975f5c5SAndroid Build Coastguard Worker // When using shadow memory, we need to mark all buffer's shadowDirty bit to true
8695*8975f5c5SAndroid Build Coastguard Worker // so they will be synchronized with real memory on the next glFinish call.
8696*8975f5c5SAndroid Build Coastguard Worker if (mCoherentBufferTracker.isShadowMemoryEnabled())
8697*8975f5c5SAndroid Build Coastguard Worker {
8698*8975f5c5SAndroid Build Coastguard Worker mCoherentBufferTracker.markAllShadowDirty();
8699*8975f5c5SAndroid Build Coastguard Worker }
8700*8975f5c5SAndroid Build Coastguard Worker break;
8701*8975f5c5SAndroid Build Coastguard Worker }
8702*8975f5c5SAndroid Build Coastguard Worker default:
8703*8975f5c5SAndroid Build Coastguard Worker break;
8704*8975f5c5SAndroid Build Coastguard Worker }
8705*8975f5c5SAndroid Build Coastguard Worker }
8706*8975f5c5SAndroid Build Coastguard Worker
captureClientArraySnapshot(const gl::Context * context,size_t vertexCount,size_t instanceCount)8707*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::captureClientArraySnapshot(const gl::Context *context,
8708*8975f5c5SAndroid Build Coastguard Worker size_t vertexCount,
8709*8975f5c5SAndroid Build Coastguard Worker size_t instanceCount)
8710*8975f5c5SAndroid Build Coastguard Worker {
8711*8975f5c5SAndroid Build Coastguard Worker if (vertexCount == 0)
8712*8975f5c5SAndroid Build Coastguard Worker {
8713*8975f5c5SAndroid Build Coastguard Worker // Nothing to capture
8714*8975f5c5SAndroid Build Coastguard Worker return;
8715*8975f5c5SAndroid Build Coastguard Worker }
8716*8975f5c5SAndroid Build Coastguard Worker
8717*8975f5c5SAndroid Build Coastguard Worker const gl::VertexArray *vao = context->getState().getVertexArray();
8718*8975f5c5SAndroid Build Coastguard Worker
8719*8975f5c5SAndroid Build Coastguard Worker // Capture client array data.
8720*8975f5c5SAndroid Build Coastguard Worker for (size_t attribIndex : context->getStateCache().getActiveClientAttribsMask())
8721*8975f5c5SAndroid Build Coastguard Worker {
8722*8975f5c5SAndroid Build Coastguard Worker const gl::VertexAttribute &attrib = vao->getVertexAttribute(attribIndex);
8723*8975f5c5SAndroid Build Coastguard Worker const gl::VertexBinding &binding = vao->getVertexBinding(attrib.bindingIndex);
8724*8975f5c5SAndroid Build Coastguard Worker
8725*8975f5c5SAndroid Build Coastguard Worker int callIndex = mClientVertexArrayMap[attribIndex];
8726*8975f5c5SAndroid Build Coastguard Worker
8727*8975f5c5SAndroid Build Coastguard Worker if (callIndex != -1)
8728*8975f5c5SAndroid Build Coastguard Worker {
8729*8975f5c5SAndroid Build Coastguard Worker size_t count = vertexCount;
8730*8975f5c5SAndroid Build Coastguard Worker
8731*8975f5c5SAndroid Build Coastguard Worker if (binding.getDivisor() > 0)
8732*8975f5c5SAndroid Build Coastguard Worker {
8733*8975f5c5SAndroid Build Coastguard Worker count = rx::UnsignedCeilDivide(static_cast<uint32_t>(instanceCount),
8734*8975f5c5SAndroid Build Coastguard Worker binding.getDivisor());
8735*8975f5c5SAndroid Build Coastguard Worker }
8736*8975f5c5SAndroid Build Coastguard Worker
8737*8975f5c5SAndroid Build Coastguard Worker // The last capture element doesn't take up the full stride.
8738*8975f5c5SAndroid Build Coastguard Worker size_t bytesToCapture = (count - 1) * binding.getStride() + attrib.format->pixelBytes;
8739*8975f5c5SAndroid Build Coastguard Worker
8740*8975f5c5SAndroid Build Coastguard Worker CallCapture &call = mFrameCalls[callIndex];
8741*8975f5c5SAndroid Build Coastguard Worker ParamCapture ¶m = call.params.getClientArrayPointerParameter();
8742*8975f5c5SAndroid Build Coastguard Worker ASSERT(param.type == ParamType::TvoidConstPointer);
8743*8975f5c5SAndroid Build Coastguard Worker
8744*8975f5c5SAndroid Build Coastguard Worker ParamBuffer updateParamBuffer;
8745*8975f5c5SAndroid Build Coastguard Worker updateParamBuffer.addValueParam<GLint>("arrayIndex", ParamType::TGLint,
8746*8975f5c5SAndroid Build Coastguard Worker static_cast<uint32_t>(attribIndex));
8747*8975f5c5SAndroid Build Coastguard Worker
8748*8975f5c5SAndroid Build Coastguard Worker ParamCapture updateMemory("pointer", ParamType::TvoidConstPointer);
8749*8975f5c5SAndroid Build Coastguard Worker CaptureMemory(param.value.voidConstPointerVal, bytesToCapture, &updateMemory);
8750*8975f5c5SAndroid Build Coastguard Worker updateParamBuffer.addParam(std::move(updateMemory));
8751*8975f5c5SAndroid Build Coastguard Worker
8752*8975f5c5SAndroid Build Coastguard Worker updateParamBuffer.addValueParam<GLuint64>("size", ParamType::TGLuint64, bytesToCapture);
8753*8975f5c5SAndroid Build Coastguard Worker
8754*8975f5c5SAndroid Build Coastguard Worker mFrameCalls.emplace_back("UpdateClientArrayPointer", std::move(updateParamBuffer));
8755*8975f5c5SAndroid Build Coastguard Worker
8756*8975f5c5SAndroid Build Coastguard Worker mClientArraySizes[attribIndex] =
8757*8975f5c5SAndroid Build Coastguard Worker std::max(mClientArraySizes[attribIndex], bytesToCapture);
8758*8975f5c5SAndroid Build Coastguard Worker }
8759*8975f5c5SAndroid Build Coastguard Worker }
8760*8975f5c5SAndroid Build Coastguard Worker }
8761*8975f5c5SAndroid Build Coastguard Worker
captureCoherentBufferSnapshot(const gl::Context * context,gl::BufferID id)8762*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::captureCoherentBufferSnapshot(const gl::Context *context, gl::BufferID id)
8763*8975f5c5SAndroid Build Coastguard Worker {
8764*8975f5c5SAndroid Build Coastguard Worker if (!hasBufferData(id))
8765*8975f5c5SAndroid Build Coastguard Worker {
8766*8975f5c5SAndroid Build Coastguard Worker // This buffer was not marked writable
8767*8975f5c5SAndroid Build Coastguard Worker return;
8768*8975f5c5SAndroid Build Coastguard Worker }
8769*8975f5c5SAndroid Build Coastguard Worker
8770*8975f5c5SAndroid Build Coastguard Worker const gl::State &apiState = context->getState();
8771*8975f5c5SAndroid Build Coastguard Worker const gl::BufferManager &buffers = apiState.getBufferManagerForCapture();
8772*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = buffers.getBuffer(id);
8773*8975f5c5SAndroid Build Coastguard Worker if (!buffer)
8774*8975f5c5SAndroid Build Coastguard Worker {
8775*8975f5c5SAndroid Build Coastguard Worker // Could not find buffer binding
8776*8975f5c5SAndroid Build Coastguard Worker return;
8777*8975f5c5SAndroid Build Coastguard Worker }
8778*8975f5c5SAndroid Build Coastguard Worker
8779*8975f5c5SAndroid Build Coastguard Worker ASSERT(buffer->isMapped());
8780*8975f5c5SAndroid Build Coastguard Worker
8781*8975f5c5SAndroid Build Coastguard Worker std::shared_ptr<angle::CoherentBuffer> coherentBuffer =
8782*8975f5c5SAndroid Build Coastguard Worker mCoherentBufferTracker.mBuffers[id.value];
8783*8975f5c5SAndroid Build Coastguard Worker
8784*8975f5c5SAndroid Build Coastguard Worker std::vector<PageRange> dirtyPageRanges = coherentBuffer->getDirtyPageRanges();
8785*8975f5c5SAndroid Build Coastguard Worker
8786*8975f5c5SAndroid Build Coastguard Worker if (mCoherentBufferTracker.isShadowMemoryEnabled() && !dirtyPageRanges.empty())
8787*8975f5c5SAndroid Build Coastguard Worker {
8788*8975f5c5SAndroid Build Coastguard Worker coherentBuffer->updateBufferMemory();
8789*8975f5c5SAndroid Build Coastguard Worker }
8790*8975f5c5SAndroid Build Coastguard Worker
8791*8975f5c5SAndroid Build Coastguard Worker AddressRange wholeRange = coherentBuffer->getRange();
8792*8975f5c5SAndroid Build Coastguard Worker
8793*8975f5c5SAndroid Build Coastguard Worker for (PageRange &pageRange : dirtyPageRanges)
8794*8975f5c5SAndroid Build Coastguard Worker {
8795*8975f5c5SAndroid Build Coastguard Worker // Write protect the memory already, so the app is blocked on writing during our capture
8796*8975f5c5SAndroid Build Coastguard Worker coherentBuffer->protectPageRange(pageRange);
8797*8975f5c5SAndroid Build Coastguard Worker
8798*8975f5c5SAndroid Build Coastguard Worker // Create the parameters to our helper for use during replay
8799*8975f5c5SAndroid Build Coastguard Worker ParamBuffer dataParamBuffer;
8800*8975f5c5SAndroid Build Coastguard Worker
8801*8975f5c5SAndroid Build Coastguard Worker // Pass in the target buffer ID
8802*8975f5c5SAndroid Build Coastguard Worker dataParamBuffer.addValueParam("dest", ParamType::TGLuint, buffer->id().value);
8803*8975f5c5SAndroid Build Coastguard Worker
8804*8975f5c5SAndroid Build Coastguard Worker // Capture the current buffer data with a binary param
8805*8975f5c5SAndroid Build Coastguard Worker ParamCapture captureData("source", ParamType::TvoidConstPointer);
8806*8975f5c5SAndroid Build Coastguard Worker
8807*8975f5c5SAndroid Build Coastguard Worker AddressRange dirtyRange = coherentBuffer->getDirtyAddressRange(pageRange);
8808*8975f5c5SAndroid Build Coastguard Worker CaptureMemory(reinterpret_cast<void *>(dirtyRange.start), dirtyRange.size, &captureData);
8809*8975f5c5SAndroid Build Coastguard Worker dataParamBuffer.addParam(std::move(captureData));
8810*8975f5c5SAndroid Build Coastguard Worker
8811*8975f5c5SAndroid Build Coastguard Worker // Also track its size for use with memcpy
8812*8975f5c5SAndroid Build Coastguard Worker dataParamBuffer.addValueParam<GLsizeiptr>("size", ParamType::TGLsizeiptr,
8813*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(dirtyRange.size));
8814*8975f5c5SAndroid Build Coastguard Worker
8815*8975f5c5SAndroid Build Coastguard Worker if (wholeRange.start != dirtyRange.start)
8816*8975f5c5SAndroid Build Coastguard Worker {
8817*8975f5c5SAndroid Build Coastguard Worker // Capture with offset
8818*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr offset = dirtyRange.start - wholeRange.start;
8819*8975f5c5SAndroid Build Coastguard Worker
8820*8975f5c5SAndroid Build Coastguard Worker ASSERT(offset > 0);
8821*8975f5c5SAndroid Build Coastguard Worker
8822*8975f5c5SAndroid Build Coastguard Worker // The dirty page range is not at the start of the buffer, track the offset.
8823*8975f5c5SAndroid Build Coastguard Worker dataParamBuffer.addValueParam<GLsizeiptr>("offset", ParamType::TGLsizeiptr, offset);
8824*8975f5c5SAndroid Build Coastguard Worker
8825*8975f5c5SAndroid Build Coastguard Worker // Call the helper that populates the buffer with captured data
8826*8975f5c5SAndroid Build Coastguard Worker mFrameCalls.emplace_back("UpdateClientBufferDataWithOffset",
8827*8975f5c5SAndroid Build Coastguard Worker std::move(dataParamBuffer));
8828*8975f5c5SAndroid Build Coastguard Worker }
8829*8975f5c5SAndroid Build Coastguard Worker else
8830*8975f5c5SAndroid Build Coastguard Worker {
8831*8975f5c5SAndroid Build Coastguard Worker // Call the helper that populates the buffer with captured data
8832*8975f5c5SAndroid Build Coastguard Worker mFrameCalls.emplace_back("UpdateClientBufferData", std::move(dataParamBuffer));
8833*8975f5c5SAndroid Build Coastguard Worker }
8834*8975f5c5SAndroid Build Coastguard Worker }
8835*8975f5c5SAndroid Build Coastguard Worker }
8836*8975f5c5SAndroid Build Coastguard Worker
captureMappedBufferSnapshot(const gl::Context * context,const CallCapture & call)8837*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::captureMappedBufferSnapshot(const gl::Context *context,
8838*8975f5c5SAndroid Build Coastguard Worker const CallCapture &call)
8839*8975f5c5SAndroid Build Coastguard Worker {
8840*8975f5c5SAndroid Build Coastguard Worker // If the buffer was mapped writable, we need to restore its data, since we have no
8841*8975f5c5SAndroid Build Coastguard Worker // visibility into what the client did to the buffer while mapped.
8842*8975f5c5SAndroid Build Coastguard Worker // This sequence will result in replay calls like this:
8843*8975f5c5SAndroid Build Coastguard Worker // ...
8844*8975f5c5SAndroid Build Coastguard Worker // gMappedBufferData[gBufferMap[42]] = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 65536,
8845*8975f5c5SAndroid Build Coastguard Worker // GL_MAP_WRITE_BIT);
8846*8975f5c5SAndroid Build Coastguard Worker // ...
8847*8975f5c5SAndroid Build Coastguard Worker // UpdateClientBufferData(42, &gBinaryData[164631024], 65536);
8848*8975f5c5SAndroid Build Coastguard Worker // glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
8849*8975f5c5SAndroid Build Coastguard Worker // ...
8850*8975f5c5SAndroid Build Coastguard Worker
8851*8975f5c5SAndroid Build Coastguard Worker // Re-map the buffer, using the info we tracked about the buffer
8852*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding target =
8853*8975f5c5SAndroid Build Coastguard Worker call.params.getParam("targetPacked", ParamType::TBufferBinding, 0).value.BufferBindingVal;
8854*8975f5c5SAndroid Build Coastguard Worker
8855*8975f5c5SAndroid Build Coastguard Worker FrameCaptureShared *frameCaptureShared = context->getShareGroup()->getFrameCaptureShared();
8856*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = context->getState().getTargetBuffer(target);
8857*8975f5c5SAndroid Build Coastguard Worker if (!frameCaptureShared->hasBufferData(buffer->id()))
8858*8975f5c5SAndroid Build Coastguard Worker {
8859*8975f5c5SAndroid Build Coastguard Worker // This buffer was not marked writable, so we did not back it up
8860*8975f5c5SAndroid Build Coastguard Worker return;
8861*8975f5c5SAndroid Build Coastguard Worker }
8862*8975f5c5SAndroid Build Coastguard Worker
8863*8975f5c5SAndroid Build Coastguard Worker std::pair<GLintptr, GLsizeiptr> bufferDataOffsetAndLength =
8864*8975f5c5SAndroid Build Coastguard Worker frameCaptureShared->getBufferDataOffsetAndLength(buffer->id());
8865*8975f5c5SAndroid Build Coastguard Worker GLintptr offset = bufferDataOffsetAndLength.first;
8866*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr length = bufferDataOffsetAndLength.second;
8867*8975f5c5SAndroid Build Coastguard Worker
8868*8975f5c5SAndroid Build Coastguard Worker // Map the buffer so we can copy its contents out
8869*8975f5c5SAndroid Build Coastguard Worker ASSERT(!buffer->isMapped());
8870*8975f5c5SAndroid Build Coastguard Worker angle::Result result = buffer->mapRange(context, offset, length, GL_MAP_READ_BIT);
8871*8975f5c5SAndroid Build Coastguard Worker if (result != angle::Result::Continue)
8872*8975f5c5SAndroid Build Coastguard Worker {
8873*8975f5c5SAndroid Build Coastguard Worker ERR() << "Failed to mapRange of buffer" << std::endl;
8874*8975f5c5SAndroid Build Coastguard Worker }
8875*8975f5c5SAndroid Build Coastguard Worker const uint8_t *data = reinterpret_cast<const uint8_t *>(buffer->getMapPointer());
8876*8975f5c5SAndroid Build Coastguard Worker
8877*8975f5c5SAndroid Build Coastguard Worker // Create the parameters to our helper for use during replay
8878*8975f5c5SAndroid Build Coastguard Worker ParamBuffer dataParamBuffer;
8879*8975f5c5SAndroid Build Coastguard Worker
8880*8975f5c5SAndroid Build Coastguard Worker // Pass in the target buffer ID
8881*8975f5c5SAndroid Build Coastguard Worker dataParamBuffer.addValueParam("dest", ParamType::TGLuint, buffer->id().value);
8882*8975f5c5SAndroid Build Coastguard Worker
8883*8975f5c5SAndroid Build Coastguard Worker // Capture the current buffer data with a binary param
8884*8975f5c5SAndroid Build Coastguard Worker ParamCapture captureData("source", ParamType::TvoidConstPointer);
8885*8975f5c5SAndroid Build Coastguard Worker CaptureMemory(data, length, &captureData);
8886*8975f5c5SAndroid Build Coastguard Worker dataParamBuffer.addParam(std::move(captureData));
8887*8975f5c5SAndroid Build Coastguard Worker
8888*8975f5c5SAndroid Build Coastguard Worker // Also track its size for use with memcpy
8889*8975f5c5SAndroid Build Coastguard Worker dataParamBuffer.addValueParam<GLsizeiptr>("size", ParamType::TGLsizeiptr, length);
8890*8975f5c5SAndroid Build Coastguard Worker
8891*8975f5c5SAndroid Build Coastguard Worker // Call the helper that populates the buffer with captured data
8892*8975f5c5SAndroid Build Coastguard Worker mFrameCalls.emplace_back("UpdateClientBufferData", std::move(dataParamBuffer));
8893*8975f5c5SAndroid Build Coastguard Worker
8894*8975f5c5SAndroid Build Coastguard Worker // Unmap the buffer and move on
8895*8975f5c5SAndroid Build Coastguard Worker GLboolean dontCare;
8896*8975f5c5SAndroid Build Coastguard Worker (void)buffer->unmap(context, &dontCare);
8897*8975f5c5SAndroid Build Coastguard Worker }
8898*8975f5c5SAndroid Build Coastguard Worker
checkForCaptureTrigger()8899*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::checkForCaptureTrigger()
8900*8975f5c5SAndroid Build Coastguard Worker {
8901*8975f5c5SAndroid Build Coastguard Worker // If the capture trigger has not been set, move on
8902*8975f5c5SAndroid Build Coastguard Worker if (mCaptureTrigger == 0)
8903*8975f5c5SAndroid Build Coastguard Worker {
8904*8975f5c5SAndroid Build Coastguard Worker return;
8905*8975f5c5SAndroid Build Coastguard Worker }
8906*8975f5c5SAndroid Build Coastguard Worker
8907*8975f5c5SAndroid Build Coastguard Worker // Otherwise, poll the value for a change
8908*8975f5c5SAndroid Build Coastguard Worker std::string captureTriggerStr = GetCaptureTrigger();
8909*8975f5c5SAndroid Build Coastguard Worker if (captureTriggerStr.empty())
8910*8975f5c5SAndroid Build Coastguard Worker {
8911*8975f5c5SAndroid Build Coastguard Worker return;
8912*8975f5c5SAndroid Build Coastguard Worker }
8913*8975f5c5SAndroid Build Coastguard Worker
8914*8975f5c5SAndroid Build Coastguard Worker // If the value has changed, use the original value as the frame count
8915*8975f5c5SAndroid Build Coastguard Worker // TODO (anglebug.com/42263521): Improve capture at unknown frame time. It is good to
8916*8975f5c5SAndroid Build Coastguard Worker // avoid polling if the feature is not enabled, but not entirely intuitive to set
8917*8975f5c5SAndroid Build Coastguard Worker // a value to zero when you want to trigger it.
8918*8975f5c5SAndroid Build Coastguard Worker uint32_t captureTrigger = atoi(captureTriggerStr.c_str());
8919*8975f5c5SAndroid Build Coastguard Worker if (captureTrigger != mCaptureTrigger)
8920*8975f5c5SAndroid Build Coastguard Worker {
8921*8975f5c5SAndroid Build Coastguard Worker // Start mid-execution capture for the current frame
8922*8975f5c5SAndroid Build Coastguard Worker mCaptureStartFrame = mFrameIndex + 1;
8923*8975f5c5SAndroid Build Coastguard Worker
8924*8975f5c5SAndroid Build Coastguard Worker // Use the original trigger value as the frame count
8925*8975f5c5SAndroid Build Coastguard Worker mCaptureEndFrame = mCaptureStartFrame + mCaptureTrigger - 1;
8926*8975f5c5SAndroid Build Coastguard Worker
8927*8975f5c5SAndroid Build Coastguard Worker INFO() << "Capture triggered after frame " << mFrameIndex << " for " << mCaptureTrigger
8928*8975f5c5SAndroid Build Coastguard Worker << " frames";
8929*8975f5c5SAndroid Build Coastguard Worker
8930*8975f5c5SAndroid Build Coastguard Worker // Stop polling
8931*8975f5c5SAndroid Build Coastguard Worker mCaptureTrigger = 0;
8932*8975f5c5SAndroid Build Coastguard Worker }
8933*8975f5c5SAndroid Build Coastguard Worker }
8934*8975f5c5SAndroid Build Coastguard Worker
scanSetupCalls(std::vector<CallCapture> & setupCalls)8935*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::scanSetupCalls(std::vector<CallCapture> &setupCalls)
8936*8975f5c5SAndroid Build Coastguard Worker {
8937*8975f5c5SAndroid Build Coastguard Worker // Scan all the instructions in the list for tracking
8938*8975f5c5SAndroid Build Coastguard Worker for (CallCapture &call : setupCalls)
8939*8975f5c5SAndroid Build Coastguard Worker {
8940*8975f5c5SAndroid Build Coastguard Worker updateReadBufferSize(call.params.getReadBufferSize());
8941*8975f5c5SAndroid Build Coastguard Worker updateResourceCountsFromCallCapture(call);
8942*8975f5c5SAndroid Build Coastguard Worker }
8943*8975f5c5SAndroid Build Coastguard Worker }
8944*8975f5c5SAndroid Build Coastguard Worker
runMidExecutionCapture(gl::Context * mainContext)8945*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::runMidExecutionCapture(gl::Context *mainContext)
8946*8975f5c5SAndroid Build Coastguard Worker {
8947*8975f5c5SAndroid Build Coastguard Worker // Set the capture active to ensure all GLES commands issued by the next frame are
8948*8975f5c5SAndroid Build Coastguard Worker // handled correctly by maybeCapturePreCallUpdates() and maybeCapturePostCallUpdates().
8949*8975f5c5SAndroid Build Coastguard Worker setCaptureActive();
8950*8975f5c5SAndroid Build Coastguard Worker
8951*8975f5c5SAndroid Build Coastguard Worker // Make sure all pending work for every Context in the share group has completed so all data
8952*8975f5c5SAndroid Build Coastguard Worker // (buffers, textures, etc.) has been updated and no resources are in use.
8953*8975f5c5SAndroid Build Coastguard Worker egl::ShareGroup *shareGroup = mainContext->getShareGroup();
8954*8975f5c5SAndroid Build Coastguard Worker shareGroup->finishAllContexts();
8955*8975f5c5SAndroid Build Coastguard Worker
8956*8975f5c5SAndroid Build Coastguard Worker const gl::State &contextState = mainContext->getState();
8957*8975f5c5SAndroid Build Coastguard Worker gl::State mainContextReplayState(
8958*8975f5c5SAndroid Build Coastguard Worker nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, contextState.getClientVersion(),
8959*8975f5c5SAndroid Build Coastguard Worker false, true, true, true, false, EGL_CONTEXT_PRIORITY_MEDIUM_IMG,
8960*8975f5c5SAndroid Build Coastguard Worker contextState.hasRobustAccess(), contextState.hasProtectedContent(), false);
8961*8975f5c5SAndroid Build Coastguard Worker mainContextReplayState.initializeForCapture(mainContext);
8962*8975f5c5SAndroid Build Coastguard Worker
8963*8975f5c5SAndroid Build Coastguard Worker CaptureShareGroupMidExecutionSetup(mainContext, &mShareGroupSetupCalls, &mResourceTracker,
8964*8975f5c5SAndroid Build Coastguard Worker mainContextReplayState, mMaxAccessedResourceIDs);
8965*8975f5c5SAndroid Build Coastguard Worker
8966*8975f5c5SAndroid Build Coastguard Worker scanSetupCalls(mShareGroupSetupCalls);
8967*8975f5c5SAndroid Build Coastguard Worker
8968*8975f5c5SAndroid Build Coastguard Worker egl::Display *display = mainContext->getDisplay();
8969*8975f5c5SAndroid Build Coastguard Worker egl::Surface *draw = mainContext->getCurrentDrawSurface();
8970*8975f5c5SAndroid Build Coastguard Worker egl::Surface *read = mainContext->getCurrentReadSurface();
8971*8975f5c5SAndroid Build Coastguard Worker
8972*8975f5c5SAndroid Build Coastguard Worker for (auto shareContext : shareGroup->getContexts())
8973*8975f5c5SAndroid Build Coastguard Worker {
8974*8975f5c5SAndroid Build Coastguard Worker FrameCapture *frameCapture = shareContext.second->getFrameCapture();
8975*8975f5c5SAndroid Build Coastguard Worker ASSERT(frameCapture->getSetupCalls().empty());
8976*8975f5c5SAndroid Build Coastguard Worker
8977*8975f5c5SAndroid Build Coastguard Worker if (shareContext.second->id() == mainContext->id())
8978*8975f5c5SAndroid Build Coastguard Worker {
8979*8975f5c5SAndroid Build Coastguard Worker CaptureMidExecutionSetup(shareContext.second, &frameCapture->getSetupCalls(),
8980*8975f5c5SAndroid Build Coastguard Worker frameCapture->getStateResetHelper(), &mShareGroupSetupCalls,
8981*8975f5c5SAndroid Build Coastguard Worker &mResourceIDToSetupCalls, &mResourceTracker,
8982*8975f5c5SAndroid Build Coastguard Worker mainContextReplayState, mValidateSerializedState);
8983*8975f5c5SAndroid Build Coastguard Worker scanSetupCalls(frameCapture->getSetupCalls());
8984*8975f5c5SAndroid Build Coastguard Worker
8985*8975f5c5SAndroid Build Coastguard Worker std::stringstream protoStream;
8986*8975f5c5SAndroid Build Coastguard Worker std::stringstream headerStream;
8987*8975f5c5SAndroid Build Coastguard Worker std::stringstream bodyStream;
8988*8975f5c5SAndroid Build Coastguard Worker
8989*8975f5c5SAndroid Build Coastguard Worker protoStream << "void "
8990*8975f5c5SAndroid Build Coastguard Worker << FmtSetupFunction(kNoPartId, mainContext->id(), FuncUsage::Prototype);
8991*8975f5c5SAndroid Build Coastguard Worker std::string proto = protoStream.str();
8992*8975f5c5SAndroid Build Coastguard Worker
8993*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayFunctionWithParts(mainContext->id(), ReplayFunc::Setup, mReplayWriter, 1,
8994*8975f5c5SAndroid Build Coastguard Worker &mBinaryData, frameCapture->getSetupCalls(),
8995*8975f5c5SAndroid Build Coastguard Worker headerStream, bodyStream, &mResourceIDBufferSize);
8996*8975f5c5SAndroid Build Coastguard Worker
8997*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.addPrivateFunction(proto, headerStream, bodyStream);
8998*8975f5c5SAndroid Build Coastguard Worker }
8999*8975f5c5SAndroid Build Coastguard Worker else
9000*8975f5c5SAndroid Build Coastguard Worker {
9001*8975f5c5SAndroid Build Coastguard Worker const gl::State &shareContextState = shareContext.second->getState();
9002*8975f5c5SAndroid Build Coastguard Worker gl::State auxContextReplayState(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
9003*8975f5c5SAndroid Build Coastguard Worker shareContextState.getClientVersion(), false, true, true,
9004*8975f5c5SAndroid Build Coastguard Worker true, false, EGL_CONTEXT_PRIORITY_MEDIUM_IMG,
9005*8975f5c5SAndroid Build Coastguard Worker shareContextState.hasRobustAccess(),
9006*8975f5c5SAndroid Build Coastguard Worker shareContextState.hasProtectedContent(), false);
9007*8975f5c5SAndroid Build Coastguard Worker auxContextReplayState.initializeForCapture(shareContext.second);
9008*8975f5c5SAndroid Build Coastguard Worker
9009*8975f5c5SAndroid Build Coastguard Worker egl::Error error = shareContext.second->makeCurrent(display, draw, read);
9010*8975f5c5SAndroid Build Coastguard Worker if (error.isError())
9011*8975f5c5SAndroid Build Coastguard Worker {
9012*8975f5c5SAndroid Build Coastguard Worker INFO() << "MEC unable to make secondary context current";
9013*8975f5c5SAndroid Build Coastguard Worker }
9014*8975f5c5SAndroid Build Coastguard Worker
9015*8975f5c5SAndroid Build Coastguard Worker CaptureMidExecutionSetup(shareContext.second, &frameCapture->getSetupCalls(),
9016*8975f5c5SAndroid Build Coastguard Worker frameCapture->getStateResetHelper(), &mShareGroupSetupCalls,
9017*8975f5c5SAndroid Build Coastguard Worker &mResourceIDToSetupCalls, &mResourceTracker,
9018*8975f5c5SAndroid Build Coastguard Worker auxContextReplayState, mValidateSerializedState);
9019*8975f5c5SAndroid Build Coastguard Worker
9020*8975f5c5SAndroid Build Coastguard Worker scanSetupCalls(frameCapture->getSetupCalls());
9021*8975f5c5SAndroid Build Coastguard Worker
9022*8975f5c5SAndroid Build Coastguard Worker WriteAuxiliaryContextCppSetupReplay(
9023*8975f5c5SAndroid Build Coastguard Worker mReplayWriter, mCompression, mOutDirectory, shareContext.second, mCaptureLabel, 1,
9024*8975f5c5SAndroid Build Coastguard Worker frameCapture->getSetupCalls(), &mBinaryData, mSerializeStateEnabled, *this,
9025*8975f5c5SAndroid Build Coastguard Worker &mResourceIDBufferSize);
9026*8975f5c5SAndroid Build Coastguard Worker }
9027*8975f5c5SAndroid Build Coastguard Worker // Track that this context was created before MEC started
9028*8975f5c5SAndroid Build Coastguard Worker mActiveContexts.insert(shareContext.first);
9029*8975f5c5SAndroid Build Coastguard Worker }
9030*8975f5c5SAndroid Build Coastguard Worker
9031*8975f5c5SAndroid Build Coastguard Worker egl::Error error = mainContext->makeCurrent(display, draw, read);
9032*8975f5c5SAndroid Build Coastguard Worker if (error.isError())
9033*8975f5c5SAndroid Build Coastguard Worker {
9034*8975f5c5SAndroid Build Coastguard Worker INFO() << "MEC unable to make main context current again";
9035*8975f5c5SAndroid Build Coastguard Worker }
9036*8975f5c5SAndroid Build Coastguard Worker }
9037*8975f5c5SAndroid Build Coastguard Worker
onEndFrame(gl::Context * context)9038*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::onEndFrame(gl::Context *context)
9039*8975f5c5SAndroid Build Coastguard Worker {
9040*8975f5c5SAndroid Build Coastguard Worker if (!enabled() || mFrameIndex > mCaptureEndFrame)
9041*8975f5c5SAndroid Build Coastguard Worker {
9042*8975f5c5SAndroid Build Coastguard Worker setCaptureInactive();
9043*8975f5c5SAndroid Build Coastguard Worker mCoherentBufferTracker.onEndFrame();
9044*8975f5c5SAndroid Build Coastguard Worker return;
9045*8975f5c5SAndroid Build Coastguard Worker }
9046*8975f5c5SAndroid Build Coastguard Worker
9047*8975f5c5SAndroid Build Coastguard Worker FrameCapture *frameCapture = context->getFrameCapture();
9048*8975f5c5SAndroid Build Coastguard Worker
9049*8975f5c5SAndroid Build Coastguard Worker // Count resource IDs. This is also done on every frame. It could probably be done by
9050*8975f5c5SAndroid Build Coastguard Worker // checking the GL state instead of the calls.
9051*8975f5c5SAndroid Build Coastguard Worker for (const CallCapture &call : mFrameCalls)
9052*8975f5c5SAndroid Build Coastguard Worker {
9053*8975f5c5SAndroid Build Coastguard Worker for (const ParamCapture ¶m : call.params.getParamCaptures())
9054*8975f5c5SAndroid Build Coastguard Worker {
9055*8975f5c5SAndroid Build Coastguard Worker ResourceIDType idType = GetResourceIDTypeFromParamType(param.type);
9056*8975f5c5SAndroid Build Coastguard Worker if (idType != ResourceIDType::InvalidEnum)
9057*8975f5c5SAndroid Build Coastguard Worker {
9058*8975f5c5SAndroid Build Coastguard Worker mHasResourceType.set(idType);
9059*8975f5c5SAndroid Build Coastguard Worker }
9060*8975f5c5SAndroid Build Coastguard Worker }
9061*8975f5c5SAndroid Build Coastguard Worker }
9062*8975f5c5SAndroid Build Coastguard Worker
9063*8975f5c5SAndroid Build Coastguard Worker mWindowSurfaceContextID = context->id();
9064*8975f5c5SAndroid Build Coastguard Worker
9065*8975f5c5SAndroid Build Coastguard Worker // On Android, we can trigger a capture during the run
9066*8975f5c5SAndroid Build Coastguard Worker checkForCaptureTrigger();
9067*8975f5c5SAndroid Build Coastguard Worker
9068*8975f5c5SAndroid Build Coastguard Worker // Check for MEC. Done after checkForCaptureTrigger(), since that can modify mCaptureStartFrame.
9069*8975f5c5SAndroid Build Coastguard Worker if (mFrameIndex < mCaptureStartFrame)
9070*8975f5c5SAndroid Build Coastguard Worker {
9071*8975f5c5SAndroid Build Coastguard Worker if (mFrameIndex == mCaptureStartFrame - 1)
9072*8975f5c5SAndroid Build Coastguard Worker {
9073*8975f5c5SAndroid Build Coastguard Worker // Trigger MEC.
9074*8975f5c5SAndroid Build Coastguard Worker runMidExecutionCapture(context);
9075*8975f5c5SAndroid Build Coastguard Worker }
9076*8975f5c5SAndroid Build Coastguard Worker mFrameIndex++;
9077*8975f5c5SAndroid Build Coastguard Worker reset();
9078*8975f5c5SAndroid Build Coastguard Worker return;
9079*8975f5c5SAndroid Build Coastguard Worker }
9080*8975f5c5SAndroid Build Coastguard Worker
9081*8975f5c5SAndroid Build Coastguard Worker ASSERT(isCaptureActive());
9082*8975f5c5SAndroid Build Coastguard Worker
9083*8975f5c5SAndroid Build Coastguard Worker if (!mFrameCalls.empty())
9084*8975f5c5SAndroid Build Coastguard Worker {
9085*8975f5c5SAndroid Build Coastguard Worker mActiveFrameIndices.push_back(getReplayFrameIndex());
9086*8975f5c5SAndroid Build Coastguard Worker }
9087*8975f5c5SAndroid Build Coastguard Worker
9088*8975f5c5SAndroid Build Coastguard Worker // Make sure all pending work for every Context in the share group has completed so all data
9089*8975f5c5SAndroid Build Coastguard Worker // (buffers, textures, etc.) has been updated and no resources are in use.
9090*8975f5c5SAndroid Build Coastguard Worker egl::ShareGroup *shareGroup = context->getShareGroup();
9091*8975f5c5SAndroid Build Coastguard Worker shareGroup->finishAllContexts();
9092*8975f5c5SAndroid Build Coastguard Worker
9093*8975f5c5SAndroid Build Coastguard Worker // Only validate the first frame for now to save on retracing time.
9094*8975f5c5SAndroid Build Coastguard Worker if (mValidateSerializedState && mFrameIndex == mCaptureStartFrame)
9095*8975f5c5SAndroid Build Coastguard Worker {
9096*8975f5c5SAndroid Build Coastguard Worker CaptureValidateSerializedState(context, &mFrameCalls);
9097*8975f5c5SAndroid Build Coastguard Worker }
9098*8975f5c5SAndroid Build Coastguard Worker
9099*8975f5c5SAndroid Build Coastguard Worker writeMainContextCppReplay(context, frameCapture->getSetupCalls(),
9100*8975f5c5SAndroid Build Coastguard Worker frameCapture->getStateResetHelper());
9101*8975f5c5SAndroid Build Coastguard Worker
9102*8975f5c5SAndroid Build Coastguard Worker if (mFrameIndex == mCaptureEndFrame)
9103*8975f5c5SAndroid Build Coastguard Worker {
9104*8975f5c5SAndroid Build Coastguard Worker // Write shared MEC after frame sequence so we can eliminate unused assets like programs
9105*8975f5c5SAndroid Build Coastguard Worker WriteShareGroupCppSetupReplay(mReplayWriter, mCompression, mOutDirectory, mCaptureLabel, 1,
9106*8975f5c5SAndroid Build Coastguard Worker 1, mShareGroupSetupCalls, &mResourceTracker, &mBinaryData,
9107*8975f5c5SAndroid Build Coastguard Worker mSerializeStateEnabled, mWindowSurfaceContextID,
9108*8975f5c5SAndroid Build Coastguard Worker &mResourceIDBufferSize);
9109*8975f5c5SAndroid Build Coastguard Worker
9110*8975f5c5SAndroid Build Coastguard Worker // Save the index files after the last frame.
9111*8975f5c5SAndroid Build Coastguard Worker writeCppReplayIndexFiles(context, false);
9112*8975f5c5SAndroid Build Coastguard Worker SaveBinaryData(mCompression, mOutDirectory, kSharedContextId, mCaptureLabel, mBinaryData);
9113*8975f5c5SAndroid Build Coastguard Worker mBinaryData.clear();
9114*8975f5c5SAndroid Build Coastguard Worker mWroteIndexFile = true;
9115*8975f5c5SAndroid Build Coastguard Worker INFO() << "Finished recording graphics API capture";
9116*8975f5c5SAndroid Build Coastguard Worker }
9117*8975f5c5SAndroid Build Coastguard Worker
9118*8975f5c5SAndroid Build Coastguard Worker reset();
9119*8975f5c5SAndroid Build Coastguard Worker mFrameIndex++;
9120*8975f5c5SAndroid Build Coastguard Worker }
9121*8975f5c5SAndroid Build Coastguard Worker
onDestroyContext(const gl::Context * context)9122*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::onDestroyContext(const gl::Context *context)
9123*8975f5c5SAndroid Build Coastguard Worker {
9124*8975f5c5SAndroid Build Coastguard Worker if (!mEnabled)
9125*8975f5c5SAndroid Build Coastguard Worker {
9126*8975f5c5SAndroid Build Coastguard Worker return;
9127*8975f5c5SAndroid Build Coastguard Worker }
9128*8975f5c5SAndroid Build Coastguard Worker if (!mWroteIndexFile && mFrameIndex > mCaptureStartFrame)
9129*8975f5c5SAndroid Build Coastguard Worker {
9130*8975f5c5SAndroid Build Coastguard Worker // If context is destroyed before end frame is reached and at least
9131*8975f5c5SAndroid Build Coastguard Worker // 1 frame has been recorded, then write the index files.
9132*8975f5c5SAndroid Build Coastguard Worker // It doesn't make sense to write the index files when no frame has been recorded
9133*8975f5c5SAndroid Build Coastguard Worker mFrameIndex -= 1;
9134*8975f5c5SAndroid Build Coastguard Worker mCaptureEndFrame = mFrameIndex;
9135*8975f5c5SAndroid Build Coastguard Worker writeCppReplayIndexFiles(context, true);
9136*8975f5c5SAndroid Build Coastguard Worker SaveBinaryData(mCompression, mOutDirectory, kSharedContextId, mCaptureLabel, mBinaryData);
9137*8975f5c5SAndroid Build Coastguard Worker mBinaryData.clear();
9138*8975f5c5SAndroid Build Coastguard Worker mWroteIndexFile = true;
9139*8975f5c5SAndroid Build Coastguard Worker }
9140*8975f5c5SAndroid Build Coastguard Worker }
9141*8975f5c5SAndroid Build Coastguard Worker
onMakeCurrent(const gl::Context * context,const egl::Surface * drawSurface)9142*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::onMakeCurrent(const gl::Context *context, const egl::Surface *drawSurface)
9143*8975f5c5SAndroid Build Coastguard Worker {
9144*8975f5c5SAndroid Build Coastguard Worker if (!drawSurface)
9145*8975f5c5SAndroid Build Coastguard Worker {
9146*8975f5c5SAndroid Build Coastguard Worker return;
9147*8975f5c5SAndroid Build Coastguard Worker }
9148*8975f5c5SAndroid Build Coastguard Worker
9149*8975f5c5SAndroid Build Coastguard Worker // Track the width, height and color space of the draw surface as provided to makeCurrent
9150*8975f5c5SAndroid Build Coastguard Worker SurfaceParams ¶ms = mDrawSurfaceParams[context->id()];
9151*8975f5c5SAndroid Build Coastguard Worker params.extents = gl::Extents(drawSurface->getWidth(), drawSurface->getHeight(), 1);
9152*8975f5c5SAndroid Build Coastguard Worker params.colorSpace = egl::FromEGLenum<egl::ColorSpace>(drawSurface->getGLColorspace());
9153*8975f5c5SAndroid Build Coastguard Worker }
9154*8975f5c5SAndroid Build Coastguard Worker
9155*8975f5c5SAndroid Build Coastguard Worker DataCounters::DataCounters() = default;
9156*8975f5c5SAndroid Build Coastguard Worker
9157*8975f5c5SAndroid Build Coastguard Worker DataCounters::~DataCounters() = default;
9158*8975f5c5SAndroid Build Coastguard Worker
getAndIncrement(EntryPoint entryPoint,const std::string & paramName)9159*8975f5c5SAndroid Build Coastguard Worker int DataCounters::getAndIncrement(EntryPoint entryPoint, const std::string ¶mName)
9160*8975f5c5SAndroid Build Coastguard Worker {
9161*8975f5c5SAndroid Build Coastguard Worker Counter counterKey = {entryPoint, paramName};
9162*8975f5c5SAndroid Build Coastguard Worker return mData[counterKey]++;
9163*8975f5c5SAndroid Build Coastguard Worker }
9164*8975f5c5SAndroid Build Coastguard Worker
9165*8975f5c5SAndroid Build Coastguard Worker DataTracker::DataTracker() = default;
9166*8975f5c5SAndroid Build Coastguard Worker
9167*8975f5c5SAndroid Build Coastguard Worker DataTracker::~DataTracker() = default;
9168*8975f5c5SAndroid Build Coastguard Worker
9169*8975f5c5SAndroid Build Coastguard Worker StringCounters::StringCounters() = default;
9170*8975f5c5SAndroid Build Coastguard Worker
9171*8975f5c5SAndroid Build Coastguard Worker StringCounters::~StringCounters() = default;
9172*8975f5c5SAndroid Build Coastguard Worker
getStringCounter(const std::vector<std::string> & strings)9173*8975f5c5SAndroid Build Coastguard Worker int StringCounters::getStringCounter(const std::vector<std::string> &strings)
9174*8975f5c5SAndroid Build Coastguard Worker {
9175*8975f5c5SAndroid Build Coastguard Worker const auto &id = mStringCounterMap.find(strings);
9176*8975f5c5SAndroid Build Coastguard Worker if (id == mStringCounterMap.end())
9177*8975f5c5SAndroid Build Coastguard Worker {
9178*8975f5c5SAndroid Build Coastguard Worker return kStringsNotFound;
9179*8975f5c5SAndroid Build Coastguard Worker }
9180*8975f5c5SAndroid Build Coastguard Worker else
9181*8975f5c5SAndroid Build Coastguard Worker {
9182*8975f5c5SAndroid Build Coastguard Worker return mStringCounterMap[strings];
9183*8975f5c5SAndroid Build Coastguard Worker }
9184*8975f5c5SAndroid Build Coastguard Worker }
9185*8975f5c5SAndroid Build Coastguard Worker
setStringCounter(const std::vector<std::string> & strings,int & counter)9186*8975f5c5SAndroid Build Coastguard Worker void StringCounters::setStringCounter(const std::vector<std::string> &strings, int &counter)
9187*8975f5c5SAndroid Build Coastguard Worker {
9188*8975f5c5SAndroid Build Coastguard Worker ASSERT(counter >= 0);
9189*8975f5c5SAndroid Build Coastguard Worker mStringCounterMap[strings] = counter;
9190*8975f5c5SAndroid Build Coastguard Worker }
9191*8975f5c5SAndroid Build Coastguard Worker
9192*8975f5c5SAndroid Build Coastguard Worker TrackedResource::TrackedResource() = default;
9193*8975f5c5SAndroid Build Coastguard Worker
9194*8975f5c5SAndroid Build Coastguard Worker TrackedResource::~TrackedResource() = default;
9195*8975f5c5SAndroid Build Coastguard Worker
9196*8975f5c5SAndroid Build Coastguard Worker ResourceTracker::ResourceTracker() = default;
9197*8975f5c5SAndroid Build Coastguard Worker
9198*8975f5c5SAndroid Build Coastguard Worker ResourceTracker::~ResourceTracker() = default;
9199*8975f5c5SAndroid Build Coastguard Worker
9200*8975f5c5SAndroid Build Coastguard Worker StateResetHelper::StateResetHelper() = default;
9201*8975f5c5SAndroid Build Coastguard Worker
9202*8975f5c5SAndroid Build Coastguard Worker StateResetHelper::~StateResetHelper() = default;
9203*8975f5c5SAndroid Build Coastguard Worker
setDefaultResetCalls(const gl::Context * context,angle::EntryPoint entryPoint)9204*8975f5c5SAndroid Build Coastguard Worker void StateResetHelper::setDefaultResetCalls(const gl::Context *context,
9205*8975f5c5SAndroid Build Coastguard Worker angle::EntryPoint entryPoint)
9206*8975f5c5SAndroid Build Coastguard Worker {
9207*8975f5c5SAndroid Build Coastguard Worker static const gl::BlendState kDefaultBlendState;
9208*8975f5c5SAndroid Build Coastguard Worker
9209*8975f5c5SAndroid Build Coastguard Worker // Populate default reset calls for entrypoints to support looping to beginning
9210*8975f5c5SAndroid Build Coastguard Worker switch (entryPoint)
9211*8975f5c5SAndroid Build Coastguard Worker {
9212*8975f5c5SAndroid Build Coastguard Worker case angle::EntryPoint::GLUseProgram:
9213*8975f5c5SAndroid Build Coastguard Worker {
9214*8975f5c5SAndroid Build Coastguard Worker if (context->getActiveLinkedProgram() &&
9215*8975f5c5SAndroid Build Coastguard Worker context->getActiveLinkedProgram()->id().value != 0)
9216*8975f5c5SAndroid Build Coastguard Worker {
9217*8975f5c5SAndroid Build Coastguard Worker Capture(&mResetCalls[angle::EntryPoint::GLUseProgram],
9218*8975f5c5SAndroid Build Coastguard Worker gl::CaptureUseProgram(context->getState(), true, {0}));
9219*8975f5c5SAndroid Build Coastguard Worker }
9220*8975f5c5SAndroid Build Coastguard Worker break;
9221*8975f5c5SAndroid Build Coastguard Worker }
9222*8975f5c5SAndroid Build Coastguard Worker case angle::EntryPoint::GLBindVertexArray:
9223*8975f5c5SAndroid Build Coastguard Worker {
9224*8975f5c5SAndroid Build Coastguard Worker if (context->getState().getVertexArray()->id().value != 0)
9225*8975f5c5SAndroid Build Coastguard Worker {
9226*8975f5c5SAndroid Build Coastguard Worker VertexArrayCaptureFuncs vertexArrayFuncs(context->isGLES1());
9227*8975f5c5SAndroid Build Coastguard Worker Capture(&mResetCalls[angle::EntryPoint::GLBindVertexArray],
9228*8975f5c5SAndroid Build Coastguard Worker vertexArrayFuncs.bindVertexArray(context->getState(), true, {0}));
9229*8975f5c5SAndroid Build Coastguard Worker }
9230*8975f5c5SAndroid Build Coastguard Worker break;
9231*8975f5c5SAndroid Build Coastguard Worker }
9232*8975f5c5SAndroid Build Coastguard Worker case angle::EntryPoint::GLBlendFunc:
9233*8975f5c5SAndroid Build Coastguard Worker {
9234*8975f5c5SAndroid Build Coastguard Worker Capture(&mResetCalls[angle::EntryPoint::GLBlendFunc],
9235*8975f5c5SAndroid Build Coastguard Worker CaptureBlendFunc(context->getState(), true, kDefaultBlendState.sourceBlendRGB,
9236*8975f5c5SAndroid Build Coastguard Worker kDefaultBlendState.destBlendRGB));
9237*8975f5c5SAndroid Build Coastguard Worker break;
9238*8975f5c5SAndroid Build Coastguard Worker }
9239*8975f5c5SAndroid Build Coastguard Worker case angle::EntryPoint::GLBlendFuncSeparate:
9240*8975f5c5SAndroid Build Coastguard Worker {
9241*8975f5c5SAndroid Build Coastguard Worker Capture(&mResetCalls[angle::EntryPoint::GLBlendFuncSeparate],
9242*8975f5c5SAndroid Build Coastguard Worker CaptureBlendFuncSeparate(
9243*8975f5c5SAndroid Build Coastguard Worker context->getState(), true, kDefaultBlendState.sourceBlendRGB,
9244*8975f5c5SAndroid Build Coastguard Worker kDefaultBlendState.destBlendRGB, kDefaultBlendState.sourceBlendAlpha,
9245*8975f5c5SAndroid Build Coastguard Worker kDefaultBlendState.destBlendAlpha));
9246*8975f5c5SAndroid Build Coastguard Worker break;
9247*8975f5c5SAndroid Build Coastguard Worker }
9248*8975f5c5SAndroid Build Coastguard Worker case angle::EntryPoint::GLBlendEquation:
9249*8975f5c5SAndroid Build Coastguard Worker {
9250*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE(); // GLBlendEquationSeparate is always used instead
9251*8975f5c5SAndroid Build Coastguard Worker break;
9252*8975f5c5SAndroid Build Coastguard Worker }
9253*8975f5c5SAndroid Build Coastguard Worker case angle::EntryPoint::GLBlendEquationSeparate:
9254*8975f5c5SAndroid Build Coastguard Worker {
9255*8975f5c5SAndroid Build Coastguard Worker Capture(&mResetCalls[angle::EntryPoint::GLBlendEquationSeparate],
9256*8975f5c5SAndroid Build Coastguard Worker CaptureBlendEquationSeparate(context->getState(), true,
9257*8975f5c5SAndroid Build Coastguard Worker kDefaultBlendState.blendEquationRGB,
9258*8975f5c5SAndroid Build Coastguard Worker kDefaultBlendState.blendEquationAlpha));
9259*8975f5c5SAndroid Build Coastguard Worker break;
9260*8975f5c5SAndroid Build Coastguard Worker }
9261*8975f5c5SAndroid Build Coastguard Worker case angle::EntryPoint::GLColorMask:
9262*8975f5c5SAndroid Build Coastguard Worker {
9263*8975f5c5SAndroid Build Coastguard Worker Capture(&mResetCalls[angle::EntryPoint::GLColorMask],
9264*8975f5c5SAndroid Build Coastguard Worker CaptureColorMask(context->getState(), true,
9265*8975f5c5SAndroid Build Coastguard Worker gl::ConvertToGLBoolean(kDefaultBlendState.colorMaskRed),
9266*8975f5c5SAndroid Build Coastguard Worker gl::ConvertToGLBoolean(kDefaultBlendState.colorMaskGreen),
9267*8975f5c5SAndroid Build Coastguard Worker gl::ConvertToGLBoolean(kDefaultBlendState.colorMaskBlue),
9268*8975f5c5SAndroid Build Coastguard Worker gl::ConvertToGLBoolean(kDefaultBlendState.colorMaskAlpha)));
9269*8975f5c5SAndroid Build Coastguard Worker break;
9270*8975f5c5SAndroid Build Coastguard Worker }
9271*8975f5c5SAndroid Build Coastguard Worker case angle::EntryPoint::GLBlendColor:
9272*8975f5c5SAndroid Build Coastguard Worker {
9273*8975f5c5SAndroid Build Coastguard Worker Capture(&mResetCalls[angle::EntryPoint::GLBlendColor],
9274*8975f5c5SAndroid Build Coastguard Worker CaptureBlendColor(context->getState(), true, 0, 0, 0, 0));
9275*8975f5c5SAndroid Build Coastguard Worker break;
9276*8975f5c5SAndroid Build Coastguard Worker }
9277*8975f5c5SAndroid Build Coastguard Worker default:
9278*8975f5c5SAndroid Build Coastguard Worker ERR() << "Unhandled entry point in setDefaultResetCalls: "
9279*8975f5c5SAndroid Build Coastguard Worker << GetEntryPointName(entryPoint);
9280*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
9281*8975f5c5SAndroid Build Coastguard Worker break;
9282*8975f5c5SAndroid Build Coastguard Worker }
9283*8975f5c5SAndroid Build Coastguard Worker }
9284*8975f5c5SAndroid Build Coastguard Worker
setDeletedFenceSync(gl::SyncID sync)9285*8975f5c5SAndroid Build Coastguard Worker void ResourceTracker::setDeletedFenceSync(gl::SyncID sync)
9286*8975f5c5SAndroid Build Coastguard Worker {
9287*8975f5c5SAndroid Build Coastguard Worker ASSERT(sync.value != 0);
9288*8975f5c5SAndroid Build Coastguard Worker if (mStartingFenceSyncs.find(sync) == mStartingFenceSyncs.end())
9289*8975f5c5SAndroid Build Coastguard Worker {
9290*8975f5c5SAndroid Build Coastguard Worker // This is a fence sync created after MEC was initialized. Ignore it.
9291*8975f5c5SAndroid Build Coastguard Worker return;
9292*8975f5c5SAndroid Build Coastguard Worker }
9293*8975f5c5SAndroid Build Coastguard Worker
9294*8975f5c5SAndroid Build Coastguard Worker // In this case, the app is deleting a fence sync we started with, we need to regen on loop.
9295*8975f5c5SAndroid Build Coastguard Worker mFenceSyncsToRegen.insert(sync);
9296*8975f5c5SAndroid Build Coastguard Worker }
9297*8975f5c5SAndroid Build Coastguard Worker
setModifiedDefaultUniform(gl::ShaderProgramID programID,gl::UniformLocation location)9298*8975f5c5SAndroid Build Coastguard Worker void ResourceTracker::setModifiedDefaultUniform(gl::ShaderProgramID programID,
9299*8975f5c5SAndroid Build Coastguard Worker gl::UniformLocation location)
9300*8975f5c5SAndroid Build Coastguard Worker {
9301*8975f5c5SAndroid Build Coastguard Worker // Pull up or create the list of uniform locations for this program and mark one dirty
9302*8975f5c5SAndroid Build Coastguard Worker mDefaultUniformsToReset[programID].insert(location);
9303*8975f5c5SAndroid Build Coastguard Worker }
9304*8975f5c5SAndroid Build Coastguard Worker
setDefaultUniformBaseLocation(gl::ShaderProgramID programID,gl::UniformLocation location,gl::UniformLocation baseLocation)9305*8975f5c5SAndroid Build Coastguard Worker void ResourceTracker::setDefaultUniformBaseLocation(gl::ShaderProgramID programID,
9306*8975f5c5SAndroid Build Coastguard Worker gl::UniformLocation location,
9307*8975f5c5SAndroid Build Coastguard Worker gl::UniformLocation baseLocation)
9308*8975f5c5SAndroid Build Coastguard Worker {
9309*8975f5c5SAndroid Build Coastguard Worker // Track the base location used to populate arrayed uniforms in Setup
9310*8975f5c5SAndroid Build Coastguard Worker mDefaultUniformBaseLocations[{programID, location}] = baseLocation;
9311*8975f5c5SAndroid Build Coastguard Worker }
9312*8975f5c5SAndroid Build Coastguard Worker
getTrackedResource(gl::ContextID contextID,ResourceIDType type)9313*8975f5c5SAndroid Build Coastguard Worker TrackedResource &ResourceTracker::getTrackedResource(gl::ContextID contextID, ResourceIDType type)
9314*8975f5c5SAndroid Build Coastguard Worker {
9315*8975f5c5SAndroid Build Coastguard Worker if (IsSharedObjectResource(type))
9316*8975f5c5SAndroid Build Coastguard Worker {
9317*8975f5c5SAndroid Build Coastguard Worker // No need to index with context if shared
9318*8975f5c5SAndroid Build Coastguard Worker return mTrackedResourcesShared[static_cast<uint32_t>(type)];
9319*8975f5c5SAndroid Build Coastguard Worker }
9320*8975f5c5SAndroid Build Coastguard Worker else
9321*8975f5c5SAndroid Build Coastguard Worker {
9322*8975f5c5SAndroid Build Coastguard Worker // For per-context objects, track the resource per-context
9323*8975f5c5SAndroid Build Coastguard Worker return mTrackedResourcesPerContext[contextID][static_cast<uint32_t>(type)];
9324*8975f5c5SAndroid Build Coastguard Worker }
9325*8975f5c5SAndroid Build Coastguard Worker }
9326*8975f5c5SAndroid Build Coastguard Worker
getContextIDs(std::set<gl::ContextID> & idsOut)9327*8975f5c5SAndroid Build Coastguard Worker void ResourceTracker::getContextIDs(std::set<gl::ContextID> &idsOut)
9328*8975f5c5SAndroid Build Coastguard Worker {
9329*8975f5c5SAndroid Build Coastguard Worker for (const auto &trackedResourceIterator : mTrackedResourcesPerContext)
9330*8975f5c5SAndroid Build Coastguard Worker {
9331*8975f5c5SAndroid Build Coastguard Worker gl::ContextID contextID = trackedResourceIterator.first;
9332*8975f5c5SAndroid Build Coastguard Worker idsOut.insert(contextID);
9333*8975f5c5SAndroid Build Coastguard Worker }
9334*8975f5c5SAndroid Build Coastguard Worker }
9335*8975f5c5SAndroid Build Coastguard Worker
setGennedResource(GLuint id)9336*8975f5c5SAndroid Build Coastguard Worker void TrackedResource::setGennedResource(GLuint id)
9337*8975f5c5SAndroid Build Coastguard Worker {
9338*8975f5c5SAndroid Build Coastguard Worker if (mStartingResources.find(id) == mStartingResources.end())
9339*8975f5c5SAndroid Build Coastguard Worker {
9340*8975f5c5SAndroid Build Coastguard Worker // This is a resource created after MEC was initialized, track it
9341*8975f5c5SAndroid Build Coastguard Worker mNewResources.insert(id);
9342*8975f5c5SAndroid Build Coastguard Worker }
9343*8975f5c5SAndroid Build Coastguard Worker else
9344*8975f5c5SAndroid Build Coastguard Worker {
9345*8975f5c5SAndroid Build Coastguard Worker // In this case, the app is genning a resource with starting ID after previously deleting it
9346*8975f5c5SAndroid Build Coastguard Worker ASSERT(mResourcesToRegen.find(id) != mResourcesToRegen.end());
9347*8975f5c5SAndroid Build Coastguard Worker
9348*8975f5c5SAndroid Build Coastguard Worker // For this, we need to delete it again to recreate it.
9349*8975f5c5SAndroid Build Coastguard Worker mResourcesToDelete.insert(id);
9350*8975f5c5SAndroid Build Coastguard Worker }
9351*8975f5c5SAndroid Build Coastguard Worker }
9352*8975f5c5SAndroid Build Coastguard Worker
resourceIsGenerated(GLuint id)9353*8975f5c5SAndroid Build Coastguard Worker bool TrackedResource::resourceIsGenerated(GLuint id)
9354*8975f5c5SAndroid Build Coastguard Worker {
9355*8975f5c5SAndroid Build Coastguard Worker return mStartingResources.find(id) != mStartingResources.end() ||
9356*8975f5c5SAndroid Build Coastguard Worker mNewResources.find(id) != mNewResources.end();
9357*8975f5c5SAndroid Build Coastguard Worker }
9358*8975f5c5SAndroid Build Coastguard Worker
setDeletedResource(GLuint id)9359*8975f5c5SAndroid Build Coastguard Worker void TrackedResource::setDeletedResource(GLuint id)
9360*8975f5c5SAndroid Build Coastguard Worker {
9361*8975f5c5SAndroid Build Coastguard Worker if (id == 0)
9362*8975f5c5SAndroid Build Coastguard Worker {
9363*8975f5c5SAndroid Build Coastguard Worker // Ignore ID 0
9364*8975f5c5SAndroid Build Coastguard Worker return;
9365*8975f5c5SAndroid Build Coastguard Worker }
9366*8975f5c5SAndroid Build Coastguard Worker
9367*8975f5c5SAndroid Build Coastguard Worker if (mNewResources.find(id) != mNewResources.end())
9368*8975f5c5SAndroid Build Coastguard Worker {
9369*8975f5c5SAndroid Build Coastguard Worker // This is a resource created after MEC was initialized, just clear it, since there will be
9370*8975f5c5SAndroid Build Coastguard Worker // no actions required for it to return to starting state.
9371*8975f5c5SAndroid Build Coastguard Worker mNewResources.erase(id);
9372*8975f5c5SAndroid Build Coastguard Worker return;
9373*8975f5c5SAndroid Build Coastguard Worker }
9374*8975f5c5SAndroid Build Coastguard Worker
9375*8975f5c5SAndroid Build Coastguard Worker if (mStartingResources.find(id) != mStartingResources.end())
9376*8975f5c5SAndroid Build Coastguard Worker {
9377*8975f5c5SAndroid Build Coastguard Worker // In this case, the app is deleting a resource we started with, we need to regen on loop
9378*8975f5c5SAndroid Build Coastguard Worker
9379*8975f5c5SAndroid Build Coastguard Worker // Mark that we don't need to delete this
9380*8975f5c5SAndroid Build Coastguard Worker mResourcesToDelete.erase(id);
9381*8975f5c5SAndroid Build Coastguard Worker
9382*8975f5c5SAndroid Build Coastguard Worker // Generate the resource again
9383*8975f5c5SAndroid Build Coastguard Worker mResourcesToRegen.insert(id);
9384*8975f5c5SAndroid Build Coastguard Worker
9385*8975f5c5SAndroid Build Coastguard Worker // Also restore its contents
9386*8975f5c5SAndroid Build Coastguard Worker mResourcesToRestore.insert(id);
9387*8975f5c5SAndroid Build Coastguard Worker }
9388*8975f5c5SAndroid Build Coastguard Worker
9389*8975f5c5SAndroid Build Coastguard Worker // If none of the above is true, the app is deleting a resource that was never genned.
9390*8975f5c5SAndroid Build Coastguard Worker }
9391*8975f5c5SAndroid Build Coastguard Worker
setModifiedResource(GLuint id)9392*8975f5c5SAndroid Build Coastguard Worker void TrackedResource::setModifiedResource(GLuint id)
9393*8975f5c5SAndroid Build Coastguard Worker {
9394*8975f5c5SAndroid Build Coastguard Worker // If this was a starting resource, we need to track it for restore
9395*8975f5c5SAndroid Build Coastguard Worker if (mStartingResources.find(id) != mStartingResources.end())
9396*8975f5c5SAndroid Build Coastguard Worker {
9397*8975f5c5SAndroid Build Coastguard Worker mResourcesToRestore.insert(id);
9398*8975f5c5SAndroid Build Coastguard Worker }
9399*8975f5c5SAndroid Build Coastguard Worker }
9400*8975f5c5SAndroid Build Coastguard Worker
setBufferMapped(gl::ContextID contextID,GLuint id)9401*8975f5c5SAndroid Build Coastguard Worker void ResourceTracker::setBufferMapped(gl::ContextID contextID, GLuint id)
9402*8975f5c5SAndroid Build Coastguard Worker {
9403*8975f5c5SAndroid Build Coastguard Worker // If this was a starting buffer, we may need to restore it to original state during Reset.
9404*8975f5c5SAndroid Build Coastguard Worker // Skip buffers that were deleted after the starting point.
9405*8975f5c5SAndroid Build Coastguard Worker const TrackedResource &trackedBuffers = getTrackedResource(contextID, ResourceIDType::Buffer);
9406*8975f5c5SAndroid Build Coastguard Worker const ResourceSet &startingBuffers = trackedBuffers.getStartingResources();
9407*8975f5c5SAndroid Build Coastguard Worker const ResourceSet &buffersToRegen = trackedBuffers.getResourcesToRegen();
9408*8975f5c5SAndroid Build Coastguard Worker if (startingBuffers.find(id) != startingBuffers.end() &&
9409*8975f5c5SAndroid Build Coastguard Worker buffersToRegen.find(id) == buffersToRegen.end())
9410*8975f5c5SAndroid Build Coastguard Worker {
9411*8975f5c5SAndroid Build Coastguard Worker // Track that its current state is mapped (true)
9412*8975f5c5SAndroid Build Coastguard Worker mStartingBuffersMappedCurrent[id] = true;
9413*8975f5c5SAndroid Build Coastguard Worker }
9414*8975f5c5SAndroid Build Coastguard Worker }
9415*8975f5c5SAndroid Build Coastguard Worker
setBufferUnmapped(gl::ContextID contextID,GLuint id)9416*8975f5c5SAndroid Build Coastguard Worker void ResourceTracker::setBufferUnmapped(gl::ContextID contextID, GLuint id)
9417*8975f5c5SAndroid Build Coastguard Worker {
9418*8975f5c5SAndroid Build Coastguard Worker // If this was a starting buffer, we may need to restore it to original state during Reset.
9419*8975f5c5SAndroid Build Coastguard Worker // Skip buffers that were deleted after the starting point.
9420*8975f5c5SAndroid Build Coastguard Worker const TrackedResource &trackedBuffers = getTrackedResource(contextID, ResourceIDType::Buffer);
9421*8975f5c5SAndroid Build Coastguard Worker const ResourceSet &startingBuffers = trackedBuffers.getStartingResources();
9422*8975f5c5SAndroid Build Coastguard Worker const ResourceSet &buffersToRegen = trackedBuffers.getResourcesToRegen();
9423*8975f5c5SAndroid Build Coastguard Worker if (startingBuffers.find(id) != startingBuffers.end() &&
9424*8975f5c5SAndroid Build Coastguard Worker buffersToRegen.find(id) == buffersToRegen.end())
9425*8975f5c5SAndroid Build Coastguard Worker {
9426*8975f5c5SAndroid Build Coastguard Worker // Track that its current state is unmapped (false)
9427*8975f5c5SAndroid Build Coastguard Worker mStartingBuffersMappedCurrent[id] = false;
9428*8975f5c5SAndroid Build Coastguard Worker }
9429*8975f5c5SAndroid Build Coastguard Worker }
9430*8975f5c5SAndroid Build Coastguard Worker
getStartingBuffersMappedCurrent(GLuint id) const9431*8975f5c5SAndroid Build Coastguard Worker bool ResourceTracker::getStartingBuffersMappedCurrent(GLuint id) const
9432*8975f5c5SAndroid Build Coastguard Worker {
9433*8975f5c5SAndroid Build Coastguard Worker const auto &foundBool = mStartingBuffersMappedCurrent.find(id);
9434*8975f5c5SAndroid Build Coastguard Worker ASSERT(foundBool != mStartingBuffersMappedCurrent.end());
9435*8975f5c5SAndroid Build Coastguard Worker return foundBool->second;
9436*8975f5c5SAndroid Build Coastguard Worker }
9437*8975f5c5SAndroid Build Coastguard Worker
getStartingBuffersMappedInitial(GLuint id) const9438*8975f5c5SAndroid Build Coastguard Worker bool ResourceTracker::getStartingBuffersMappedInitial(GLuint id) const
9439*8975f5c5SAndroid Build Coastguard Worker {
9440*8975f5c5SAndroid Build Coastguard Worker const auto &foundBool = mStartingBuffersMappedInitial.find(id);
9441*8975f5c5SAndroid Build Coastguard Worker ASSERT(foundBool != mStartingBuffersMappedInitial.end());
9442*8975f5c5SAndroid Build Coastguard Worker return foundBool->second;
9443*8975f5c5SAndroid Build Coastguard Worker }
9444*8975f5c5SAndroid Build Coastguard Worker
onShaderProgramAccess(gl::ShaderProgramID shaderProgramID)9445*8975f5c5SAndroid Build Coastguard Worker void ResourceTracker::onShaderProgramAccess(gl::ShaderProgramID shaderProgramID)
9446*8975f5c5SAndroid Build Coastguard Worker {
9447*8975f5c5SAndroid Build Coastguard Worker mMaxShaderPrograms = std::max(mMaxShaderPrograms, shaderProgramID.value + 1);
9448*8975f5c5SAndroid Build Coastguard Worker }
9449*8975f5c5SAndroid Build Coastguard Worker
isCapturing() const9450*8975f5c5SAndroid Build Coastguard Worker bool FrameCaptureShared::isCapturing() const
9451*8975f5c5SAndroid Build Coastguard Worker {
9452*8975f5c5SAndroid Build Coastguard Worker // Currently we will always do a capture up until the last frame. In the future we could improve
9453*8975f5c5SAndroid Build Coastguard Worker // mid execution capture by only capturing between the start and end frames. The only necessary
9454*8975f5c5SAndroid Build Coastguard Worker // reason we need to capture before the start is for attached program and shader sources.
9455*8975f5c5SAndroid Build Coastguard Worker return mEnabled && mFrameIndex <= mCaptureEndFrame;
9456*8975f5c5SAndroid Build Coastguard Worker }
9457*8975f5c5SAndroid Build Coastguard Worker
getFrameCount() const9458*8975f5c5SAndroid Build Coastguard Worker uint32_t FrameCaptureShared::getFrameCount() const
9459*8975f5c5SAndroid Build Coastguard Worker {
9460*8975f5c5SAndroid Build Coastguard Worker return mCaptureEndFrame - mCaptureStartFrame + 1;
9461*8975f5c5SAndroid Build Coastguard Worker }
9462*8975f5c5SAndroid Build Coastguard Worker
getReplayFrameIndex() const9463*8975f5c5SAndroid Build Coastguard Worker uint32_t FrameCaptureShared::getReplayFrameIndex() const
9464*8975f5c5SAndroid Build Coastguard Worker {
9465*8975f5c5SAndroid Build Coastguard Worker return mFrameIndex - mCaptureStartFrame + 1;
9466*8975f5c5SAndroid Build Coastguard Worker }
9467*8975f5c5SAndroid Build Coastguard Worker
9468*8975f5c5SAndroid Build Coastguard Worker // Serialize trace metadata into a JSON file. The JSON file will be named "trace_prefix.json".
9469*8975f5c5SAndroid Build Coastguard Worker //
9470*8975f5c5SAndroid Build Coastguard Worker // As of writing, it will have the format like so:
9471*8975f5c5SAndroid Build Coastguard Worker // {
9472*8975f5c5SAndroid Build Coastguard Worker // "TraceMetadata":
9473*8975f5c5SAndroid Build Coastguard Worker // {
9474*8975f5c5SAndroid Build Coastguard Worker // "AreClientArraysEnabled" : 1, "CaptureRevision" : 16631, "ConfigAlphaBits" : 8,
9475*8975f5c5SAndroid Build Coastguard Worker // "ConfigBlueBits" : 8, "ConfigDepthBits" : 24, "ConfigGreenBits" : 8,
9476*8975f5c5SAndroid Build Coastguard Worker // ... etc ...
writeJSON(const gl::Context * context)9477*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::writeJSON(const gl::Context *context)
9478*8975f5c5SAndroid Build Coastguard Worker {
9479*8975f5c5SAndroid Build Coastguard Worker const gl::ContextID contextId = context->id();
9480*8975f5c5SAndroid Build Coastguard Worker const SurfaceParams &surfaceParams = mDrawSurfaceParams.at(contextId);
9481*8975f5c5SAndroid Build Coastguard Worker const gl::State &glState = context->getState();
9482*8975f5c5SAndroid Build Coastguard Worker const egl::Config *config = context->getConfig();
9483*8975f5c5SAndroid Build Coastguard Worker const egl::AttributeMap &displayAttribs = context->getDisplay()->getAttributeMap();
9484*8975f5c5SAndroid Build Coastguard Worker
9485*8975f5c5SAndroid Build Coastguard Worker unsigned int frameCount = getFrameCount();
9486*8975f5c5SAndroid Build Coastguard Worker
9487*8975f5c5SAndroid Build Coastguard Worker JsonSerializer json;
9488*8975f5c5SAndroid Build Coastguard Worker json.startGroup("TraceMetadata");
9489*8975f5c5SAndroid Build Coastguard Worker json.addScalar("CaptureRevision", GetANGLERevision());
9490*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ContextClientMajorVersion", context->getClientMajorVersion());
9491*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ContextClientMinorVersion", context->getClientMinorVersion());
9492*8975f5c5SAndroid Build Coastguard Worker json.addHexValue("DisplayPlatformType", displayAttribs.getAsInt(EGL_PLATFORM_ANGLE_TYPE_ANGLE));
9493*8975f5c5SAndroid Build Coastguard Worker json.addHexValue("DisplayDeviceType",
9494*8975f5c5SAndroid Build Coastguard Worker displayAttribs.getAsInt(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE));
9495*8975f5c5SAndroid Build Coastguard Worker json.addScalar("FrameStart", 1);
9496*8975f5c5SAndroid Build Coastguard Worker json.addScalar("FrameEnd", frameCount);
9497*8975f5c5SAndroid Build Coastguard Worker json.addScalar("DrawSurfaceWidth", surfaceParams.extents.width);
9498*8975f5c5SAndroid Build Coastguard Worker json.addScalar("DrawSurfaceHeight", surfaceParams.extents.height);
9499*8975f5c5SAndroid Build Coastguard Worker json.addHexValue("DrawSurfaceColorSpace", ToEGLenum(surfaceParams.colorSpace));
9500*8975f5c5SAndroid Build Coastguard Worker if (config)
9501*8975f5c5SAndroid Build Coastguard Worker {
9502*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ConfigRedBits", config->redSize);
9503*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ConfigGreenBits", config->greenSize);
9504*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ConfigBlueBits", config->blueSize);
9505*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ConfigAlphaBits", config->alphaSize);
9506*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ConfigDepthBits", config->depthSize);
9507*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ConfigStencilBits", config->stencilSize);
9508*8975f5c5SAndroid Build Coastguard Worker }
9509*8975f5c5SAndroid Build Coastguard Worker else
9510*8975f5c5SAndroid Build Coastguard Worker {
9511*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ConfigRedBits", EGL_DONT_CARE);
9512*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ConfigGreenBits", EGL_DONT_CARE);
9513*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ConfigBlueBits", EGL_DONT_CARE);
9514*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ConfigAlphaBits", EGL_DONT_CARE);
9515*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ConfigDepthBits", EGL_DONT_CARE);
9516*8975f5c5SAndroid Build Coastguard Worker json.addScalar("ConfigStencilBits", EGL_DONT_CARE);
9517*8975f5c5SAndroid Build Coastguard Worker }
9518*8975f5c5SAndroid Build Coastguard Worker json.addBool("IsBinaryDataCompressed", mCompression);
9519*8975f5c5SAndroid Build Coastguard Worker json.addBool("AreClientArraysEnabled", glState.areClientArraysEnabled());
9520*8975f5c5SAndroid Build Coastguard Worker json.addBool("IsBindGeneratesResourcesEnabled", glState.isBindGeneratesResourceEnabled());
9521*8975f5c5SAndroid Build Coastguard Worker json.addBool("IsWebGLCompatibilityEnabled", glState.isWebGL());
9522*8975f5c5SAndroid Build Coastguard Worker json.addBool("IsRobustResourceInitEnabled", glState.isRobustResourceInitEnabled());
9523*8975f5c5SAndroid Build Coastguard Worker json.endGroup();
9524*8975f5c5SAndroid Build Coastguard Worker
9525*8975f5c5SAndroid Build Coastguard Worker {
9526*8975f5c5SAndroid Build Coastguard Worker const std::vector<std::string> &traceFiles = mReplayWriter.getAndResetWrittenFiles();
9527*8975f5c5SAndroid Build Coastguard Worker json.addVectorOfStrings("TraceFiles", traceFiles);
9528*8975f5c5SAndroid Build Coastguard Worker }
9529*8975f5c5SAndroid Build Coastguard Worker
9530*8975f5c5SAndroid Build Coastguard Worker json.addScalar("WindowSurfaceContextID", contextId.value);
9531*8975f5c5SAndroid Build Coastguard Worker
9532*8975f5c5SAndroid Build Coastguard Worker {
9533*8975f5c5SAndroid Build Coastguard Worker std::stringstream jsonFileNameStream;
9534*8975f5c5SAndroid Build Coastguard Worker jsonFileNameStream << mOutDirectory << FmtCapturePrefix(kNoContextId, mCaptureLabel)
9535*8975f5c5SAndroid Build Coastguard Worker << ".json";
9536*8975f5c5SAndroid Build Coastguard Worker std::string jsonFileName = jsonFileNameStream.str();
9537*8975f5c5SAndroid Build Coastguard Worker
9538*8975f5c5SAndroid Build Coastguard Worker SaveFileHelper saveData(jsonFileName);
9539*8975f5c5SAndroid Build Coastguard Worker saveData.write(reinterpret_cast<const uint8_t *>(json.data()), json.length());
9540*8975f5c5SAndroid Build Coastguard Worker }
9541*8975f5c5SAndroid Build Coastguard Worker }
9542*8975f5c5SAndroid Build Coastguard Worker
writeCppReplayIndexFiles(const gl::Context * context,bool writeResetContextCall)9543*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::writeCppReplayIndexFiles(const gl::Context *context,
9544*8975f5c5SAndroid Build Coastguard Worker bool writeResetContextCall)
9545*8975f5c5SAndroid Build Coastguard Worker {
9546*8975f5c5SAndroid Build Coastguard Worker // Ensure the last frame is written. This will no-op if the frame is already written.
9547*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.saveFrame();
9548*8975f5c5SAndroid Build Coastguard Worker
9549*8975f5c5SAndroid Build Coastguard Worker const gl::ContextID contextId = context->id();
9550*8975f5c5SAndroid Build Coastguard Worker
9551*8975f5c5SAndroid Build Coastguard Worker {
9552*8975f5c5SAndroid Build Coastguard Worker std::stringstream header;
9553*8975f5c5SAndroid Build Coastguard Worker
9554*8975f5c5SAndroid Build Coastguard Worker header << "#pragma once\n";
9555*8975f5c5SAndroid Build Coastguard Worker header << "\n";
9556*8975f5c5SAndroid Build Coastguard Worker header << "#include <EGL/egl.h>\n";
9557*8975f5c5SAndroid Build Coastguard Worker header << "#include <stdint.h>\n";
9558*8975f5c5SAndroid Build Coastguard Worker
9559*8975f5c5SAndroid Build Coastguard Worker std::string includes = header.str();
9560*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.setHeaderPrologue(includes);
9561*8975f5c5SAndroid Build Coastguard Worker }
9562*8975f5c5SAndroid Build Coastguard Worker
9563*8975f5c5SAndroid Build Coastguard Worker {
9564*8975f5c5SAndroid Build Coastguard Worker std::stringstream source;
9565*8975f5c5SAndroid Build Coastguard Worker
9566*8975f5c5SAndroid Build Coastguard Worker source << "#include \"" << FmtCapturePrefix(contextId, mCaptureLabel) << ".h\"\n";
9567*8975f5c5SAndroid Build Coastguard Worker source << "#include \"trace_fixture.h\"\n";
9568*8975f5c5SAndroid Build Coastguard Worker source << "#include \"angle_trace_gl.h\"\n";
9569*8975f5c5SAndroid Build Coastguard Worker
9570*8975f5c5SAndroid Build Coastguard Worker std::string sourcePrologue = source.str();
9571*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.setSourcePrologue(sourcePrologue);
9572*8975f5c5SAndroid Build Coastguard Worker }
9573*8975f5c5SAndroid Build Coastguard Worker
9574*8975f5c5SAndroid Build Coastguard Worker {
9575*8975f5c5SAndroid Build Coastguard Worker std::string proto = "void InitReplay(void)";
9576*8975f5c5SAndroid Build Coastguard Worker
9577*8975f5c5SAndroid Build Coastguard Worker std::stringstream source;
9578*8975f5c5SAndroid Build Coastguard Worker source << proto << "\n";
9579*8975f5c5SAndroid Build Coastguard Worker source << "{\n";
9580*8975f5c5SAndroid Build Coastguard Worker WriteInitReplayCall(mCompression, source, context->id(), mCaptureLabel,
9581*8975f5c5SAndroid Build Coastguard Worker MaxClientArraySize(mClientArraySizes), mReadBufferSize,
9582*8975f5c5SAndroid Build Coastguard Worker mResourceIDBufferSize, mMaxAccessedResourceIDs);
9583*8975f5c5SAndroid Build Coastguard Worker source << "}\n";
9584*8975f5c5SAndroid Build Coastguard Worker
9585*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.addPrivateFunction(proto, std::stringstream(), source);
9586*8975f5c5SAndroid Build Coastguard Worker }
9587*8975f5c5SAndroid Build Coastguard Worker
9588*8975f5c5SAndroid Build Coastguard Worker {
9589*8975f5c5SAndroid Build Coastguard Worker std::string proto = "void ReplayFrame(uint32_t frameIndex)";
9590*8975f5c5SAndroid Build Coastguard Worker
9591*8975f5c5SAndroid Build Coastguard Worker std::stringstream source;
9592*8975f5c5SAndroid Build Coastguard Worker
9593*8975f5c5SAndroid Build Coastguard Worker source << proto << "\n";
9594*8975f5c5SAndroid Build Coastguard Worker source << "{\n";
9595*8975f5c5SAndroid Build Coastguard Worker source << " switch (frameIndex)\n";
9596*8975f5c5SAndroid Build Coastguard Worker source << " {\n";
9597*8975f5c5SAndroid Build Coastguard Worker for (uint32_t frameIndex : mActiveFrameIndices)
9598*8975f5c5SAndroid Build Coastguard Worker {
9599*8975f5c5SAndroid Build Coastguard Worker source << " case " << frameIndex << ":\n";
9600*8975f5c5SAndroid Build Coastguard Worker source << " " << FmtReplayFunction(contextId, FuncUsage::Call, frameIndex)
9601*8975f5c5SAndroid Build Coastguard Worker << ";\n";
9602*8975f5c5SAndroid Build Coastguard Worker source << " break;\n";
9603*8975f5c5SAndroid Build Coastguard Worker }
9604*8975f5c5SAndroid Build Coastguard Worker source << " default:\n";
9605*8975f5c5SAndroid Build Coastguard Worker source << " break;\n";
9606*8975f5c5SAndroid Build Coastguard Worker source << " }\n";
9607*8975f5c5SAndroid Build Coastguard Worker source << "}\n";
9608*8975f5c5SAndroid Build Coastguard Worker
9609*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.addPublicFunction(proto, std::stringstream(), source);
9610*8975f5c5SAndroid Build Coastguard Worker }
9611*8975f5c5SAndroid Build Coastguard Worker
9612*8975f5c5SAndroid Build Coastguard Worker if (writeResetContextCall)
9613*8975f5c5SAndroid Build Coastguard Worker {
9614*8975f5c5SAndroid Build Coastguard Worker std::string proto = "void ResetReplay(void)";
9615*8975f5c5SAndroid Build Coastguard Worker
9616*8975f5c5SAndroid Build Coastguard Worker std::stringstream source;
9617*8975f5c5SAndroid Build Coastguard Worker
9618*8975f5c5SAndroid Build Coastguard Worker source << proto << "\n";
9619*8975f5c5SAndroid Build Coastguard Worker source << "{\n";
9620*8975f5c5SAndroid Build Coastguard Worker source << " // Reset context is empty because context is destroyed before end "
9621*8975f5c5SAndroid Build Coastguard Worker "frame is reached\n";
9622*8975f5c5SAndroid Build Coastguard Worker source << "}\n";
9623*8975f5c5SAndroid Build Coastguard Worker
9624*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.addPublicFunction(proto, std::stringstream(), source);
9625*8975f5c5SAndroid Build Coastguard Worker }
9626*8975f5c5SAndroid Build Coastguard Worker
9627*8975f5c5SAndroid Build Coastguard Worker if (mSerializeStateEnabled)
9628*8975f5c5SAndroid Build Coastguard Worker {
9629*8975f5c5SAndroid Build Coastguard Worker std::string proto = "const char *GetSerializedContextState(uint32_t frameIndex)";
9630*8975f5c5SAndroid Build Coastguard Worker
9631*8975f5c5SAndroid Build Coastguard Worker std::stringstream source;
9632*8975f5c5SAndroid Build Coastguard Worker
9633*8975f5c5SAndroid Build Coastguard Worker source << proto << "\n";
9634*8975f5c5SAndroid Build Coastguard Worker source << "{\n";
9635*8975f5c5SAndroid Build Coastguard Worker source << " switch (frameIndex)\n";
9636*8975f5c5SAndroid Build Coastguard Worker source << " {\n";
9637*8975f5c5SAndroid Build Coastguard Worker for (uint32_t frameIndex = 1; frameIndex <= getFrameCount(); ++frameIndex)
9638*8975f5c5SAndroid Build Coastguard Worker {
9639*8975f5c5SAndroid Build Coastguard Worker source << " case " << frameIndex << ":\n";
9640*8975f5c5SAndroid Build Coastguard Worker source << " return "
9641*8975f5c5SAndroid Build Coastguard Worker << FmtGetSerializedContextStateFunction(contextId, FuncUsage::Call, frameIndex)
9642*8975f5c5SAndroid Build Coastguard Worker << ";\n";
9643*8975f5c5SAndroid Build Coastguard Worker }
9644*8975f5c5SAndroid Build Coastguard Worker source << " default:\n";
9645*8975f5c5SAndroid Build Coastguard Worker source << " return NULL;\n";
9646*8975f5c5SAndroid Build Coastguard Worker source << " }\n";
9647*8975f5c5SAndroid Build Coastguard Worker source << "}\n";
9648*8975f5c5SAndroid Build Coastguard Worker
9649*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.addPublicFunction(proto, std::stringstream(), source);
9650*8975f5c5SAndroid Build Coastguard Worker }
9651*8975f5c5SAndroid Build Coastguard Worker
9652*8975f5c5SAndroid Build Coastguard Worker {
9653*8975f5c5SAndroid Build Coastguard Worker std::stringstream fnameStream;
9654*8975f5c5SAndroid Build Coastguard Worker fnameStream << mOutDirectory << FmtCapturePrefix(contextId, mCaptureLabel);
9655*8975f5c5SAndroid Build Coastguard Worker std::string fnamePattern = fnameStream.str();
9656*8975f5c5SAndroid Build Coastguard Worker
9657*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.setFilenamePattern(fnamePattern);
9658*8975f5c5SAndroid Build Coastguard Worker }
9659*8975f5c5SAndroid Build Coastguard Worker
9660*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.saveIndexFilesAndHeader();
9661*8975f5c5SAndroid Build Coastguard Worker
9662*8975f5c5SAndroid Build Coastguard Worker writeJSON(context);
9663*8975f5c5SAndroid Build Coastguard Worker }
9664*8975f5c5SAndroid Build Coastguard Worker
writeMainContextCppReplay(const gl::Context * context,const std::vector<CallCapture> & setupCalls,StateResetHelper & stateResetHelper)9665*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::writeMainContextCppReplay(const gl::Context *context,
9666*8975f5c5SAndroid Build Coastguard Worker const std::vector<CallCapture> &setupCalls,
9667*8975f5c5SAndroid Build Coastguard Worker StateResetHelper &stateResetHelper)
9668*8975f5c5SAndroid Build Coastguard Worker {
9669*8975f5c5SAndroid Build Coastguard Worker ASSERT(mWindowSurfaceContextID == context->id());
9670*8975f5c5SAndroid Build Coastguard Worker
9671*8975f5c5SAndroid Build Coastguard Worker {
9672*8975f5c5SAndroid Build Coastguard Worker std::stringstream header;
9673*8975f5c5SAndroid Build Coastguard Worker
9674*8975f5c5SAndroid Build Coastguard Worker header << "#include \"" << FmtCapturePrefix(context->id(), mCaptureLabel) << ".h\"\n";
9675*8975f5c5SAndroid Build Coastguard Worker header << "#include \"angle_trace_gl.h\"\n";
9676*8975f5c5SAndroid Build Coastguard Worker
9677*8975f5c5SAndroid Build Coastguard Worker std::string headerString = header.str();
9678*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.setSourcePrologue(headerString);
9679*8975f5c5SAndroid Build Coastguard Worker }
9680*8975f5c5SAndroid Build Coastguard Worker
9681*8975f5c5SAndroid Build Coastguard Worker uint32_t frameCount = getFrameCount();
9682*8975f5c5SAndroid Build Coastguard Worker uint32_t frameIndex = getReplayFrameIndex();
9683*8975f5c5SAndroid Build Coastguard Worker
9684*8975f5c5SAndroid Build Coastguard Worker if (frameIndex == 1)
9685*8975f5c5SAndroid Build Coastguard Worker {
9686*8975f5c5SAndroid Build Coastguard Worker {
9687*8975f5c5SAndroid Build Coastguard Worker std::string proto = "void SetupReplay(void)";
9688*8975f5c5SAndroid Build Coastguard Worker
9689*8975f5c5SAndroid Build Coastguard Worker std::stringstream out;
9690*8975f5c5SAndroid Build Coastguard Worker
9691*8975f5c5SAndroid Build Coastguard Worker out << proto << "\n";
9692*8975f5c5SAndroid Build Coastguard Worker out << "{\n";
9693*8975f5c5SAndroid Build Coastguard Worker
9694*8975f5c5SAndroid Build Coastguard Worker // Setup all of the shared objects.
9695*8975f5c5SAndroid Build Coastguard Worker out << " InitReplay();\n";
9696*8975f5c5SAndroid Build Coastguard Worker if (usesMidExecutionCapture())
9697*8975f5c5SAndroid Build Coastguard Worker {
9698*8975f5c5SAndroid Build Coastguard Worker out << " " << FmtSetupFunction(kNoPartId, kSharedContextId, FuncUsage::Call)
9699*8975f5c5SAndroid Build Coastguard Worker << ";\n";
9700*8975f5c5SAndroid Build Coastguard Worker out << " "
9701*8975f5c5SAndroid Build Coastguard Worker << FmtSetupInactiveFunction(kNoPartId, kSharedContextId, FuncUsage::Call)
9702*8975f5c5SAndroid Build Coastguard Worker << "\n";
9703*8975f5c5SAndroid Build Coastguard Worker // Make sure that the current context is mapped correctly
9704*8975f5c5SAndroid Build Coastguard Worker out << " SetCurrentContextID(" << context->id() << ");\n";
9705*8975f5c5SAndroid Build Coastguard Worker }
9706*8975f5c5SAndroid Build Coastguard Worker
9707*8975f5c5SAndroid Build Coastguard Worker // Setup each of the auxiliary contexts.
9708*8975f5c5SAndroid Build Coastguard Worker egl::ShareGroup *shareGroup = context->getShareGroup();
9709*8975f5c5SAndroid Build Coastguard Worker const egl::ContextMap &shareContextMap = shareGroup->getContexts();
9710*8975f5c5SAndroid Build Coastguard Worker for (auto shareContext : shareContextMap)
9711*8975f5c5SAndroid Build Coastguard Worker {
9712*8975f5c5SAndroid Build Coastguard Worker if (shareContext.first == context->id().value)
9713*8975f5c5SAndroid Build Coastguard Worker {
9714*8975f5c5SAndroid Build Coastguard Worker if (usesMidExecutionCapture())
9715*8975f5c5SAndroid Build Coastguard Worker {
9716*8975f5c5SAndroid Build Coastguard Worker // Setup the presentation (this) context first.
9717*8975f5c5SAndroid Build Coastguard Worker out << " " << FmtSetupFunction(kNoPartId, context->id(), FuncUsage::Call)
9718*8975f5c5SAndroid Build Coastguard Worker << ";\n";
9719*8975f5c5SAndroid Build Coastguard Worker out << "\n";
9720*8975f5c5SAndroid Build Coastguard Worker }
9721*8975f5c5SAndroid Build Coastguard Worker
9722*8975f5c5SAndroid Build Coastguard Worker continue;
9723*8975f5c5SAndroid Build Coastguard Worker }
9724*8975f5c5SAndroid Build Coastguard Worker
9725*8975f5c5SAndroid Build Coastguard Worker // The SetupReplayContextXX() calls only exist if this is a mid-execution capture
9726*8975f5c5SAndroid Build Coastguard Worker // and we can only call them if they exist, so only output the calls if this is a
9727*8975f5c5SAndroid Build Coastguard Worker // MEC.
9728*8975f5c5SAndroid Build Coastguard Worker if (usesMidExecutionCapture())
9729*8975f5c5SAndroid Build Coastguard Worker {
9730*8975f5c5SAndroid Build Coastguard Worker // Only call SetupReplayContext for secondary contexts that were current before
9731*8975f5c5SAndroid Build Coastguard Worker // MEC started
9732*8975f5c5SAndroid Build Coastguard Worker if (mActiveContexts.find(shareContext.first) != mActiveContexts.end())
9733*8975f5c5SAndroid Build Coastguard Worker {
9734*8975f5c5SAndroid Build Coastguard Worker // TODO(http://anglebug.com/42264418): Support capture/replay of
9735*8975f5c5SAndroid Build Coastguard Worker // eglCreateContext() so this block can be moved into SetupReplayContextXX()
9736*8975f5c5SAndroid Build Coastguard Worker // by injecting them into the beginning of the setup call stream.
9737*8975f5c5SAndroid Build Coastguard Worker out << " CreateContext(" << shareContext.first << ");\n";
9738*8975f5c5SAndroid Build Coastguard Worker
9739*8975f5c5SAndroid Build Coastguard Worker out << " "
9740*8975f5c5SAndroid Build Coastguard Worker << FmtSetupFunction(kNoPartId, shareContext.second->id(),
9741*8975f5c5SAndroid Build Coastguard Worker FuncUsage::Call)
9742*8975f5c5SAndroid Build Coastguard Worker << ";\n";
9743*8975f5c5SAndroid Build Coastguard Worker }
9744*8975f5c5SAndroid Build Coastguard Worker }
9745*8975f5c5SAndroid Build Coastguard Worker }
9746*8975f5c5SAndroid Build Coastguard Worker
9747*8975f5c5SAndroid Build Coastguard Worker // If there are other contexts that were initialized, we need to make the main context
9748*8975f5c5SAndroid Build Coastguard Worker // current again.
9749*8975f5c5SAndroid Build Coastguard Worker if (shareContextMap.size() > 1)
9750*8975f5c5SAndroid Build Coastguard Worker {
9751*8975f5c5SAndroid Build Coastguard Worker out << "\n";
9752*8975f5c5SAndroid Build Coastguard Worker out << " eglMakeCurrent(NULL, NULL, NULL, gContextMap2[" << context->id()
9753*8975f5c5SAndroid Build Coastguard Worker << "]);\n";
9754*8975f5c5SAndroid Build Coastguard Worker }
9755*8975f5c5SAndroid Build Coastguard Worker
9756*8975f5c5SAndroid Build Coastguard Worker out << "}\n";
9757*8975f5c5SAndroid Build Coastguard Worker
9758*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.addPublicFunction(proto, std::stringstream(), out);
9759*8975f5c5SAndroid Build Coastguard Worker }
9760*8975f5c5SAndroid Build Coastguard Worker }
9761*8975f5c5SAndroid Build Coastguard Worker
9762*8975f5c5SAndroid Build Coastguard Worker // Emit code to reset back to starting state
9763*8975f5c5SAndroid Build Coastguard Worker if (frameIndex == frameCount)
9764*8975f5c5SAndroid Build Coastguard Worker {
9765*8975f5c5SAndroid Build Coastguard Worker std::stringstream resetProtoStream;
9766*8975f5c5SAndroid Build Coastguard Worker std::stringstream resetHeaderStream;
9767*8975f5c5SAndroid Build Coastguard Worker std::stringstream resetBodyStream;
9768*8975f5c5SAndroid Build Coastguard Worker
9769*8975f5c5SAndroid Build Coastguard Worker resetProtoStream << "void ResetReplay(void)";
9770*8975f5c5SAndroid Build Coastguard Worker
9771*8975f5c5SAndroid Build Coastguard Worker resetBodyStream << resetProtoStream.str() << "\n";
9772*8975f5c5SAndroid Build Coastguard Worker resetBodyStream << "{\n";
9773*8975f5c5SAndroid Build Coastguard Worker
9774*8975f5c5SAndroid Build Coastguard Worker // Grab the list of contexts to be reset
9775*8975f5c5SAndroid Build Coastguard Worker std::set<gl::ContextID> contextIDs;
9776*8975f5c5SAndroid Build Coastguard Worker mResourceTracker.getContextIDs(contextIDs);
9777*8975f5c5SAndroid Build Coastguard Worker
9778*8975f5c5SAndroid Build Coastguard Worker // TODO(http://anglebug.com/42264418): Look at moving this into the shared context file
9779*8975f5c5SAndroid Build Coastguard Worker // since it's resetting shared objects.
9780*8975f5c5SAndroid Build Coastguard Worker
9781*8975f5c5SAndroid Build Coastguard Worker // TODO(http://anglebug.com/42263204): Support function parts when writing Reset functions
9782*8975f5c5SAndroid Build Coastguard Worker
9783*8975f5c5SAndroid Build Coastguard Worker // Track whether anything was written during Reset
9784*8975f5c5SAndroid Build Coastguard Worker bool anyResourceReset = false;
9785*8975f5c5SAndroid Build Coastguard Worker
9786*8975f5c5SAndroid Build Coastguard Worker // Track whether we changed contexts during Reset
9787*8975f5c5SAndroid Build Coastguard Worker bool contextChanged = false;
9788*8975f5c5SAndroid Build Coastguard Worker
9789*8975f5c5SAndroid Build Coastguard Worker // First emit shared object reset, including opaque and context state
9790*8975f5c5SAndroid Build Coastguard Worker {
9791*8975f5c5SAndroid Build Coastguard Worker std::stringstream protoStream;
9792*8975f5c5SAndroid Build Coastguard Worker std::stringstream headerStream;
9793*8975f5c5SAndroid Build Coastguard Worker std::stringstream bodyStream;
9794*8975f5c5SAndroid Build Coastguard Worker
9795*8975f5c5SAndroid Build Coastguard Worker protoStream << "void "
9796*8975f5c5SAndroid Build Coastguard Worker << FmtResetFunction(kNoPartId, kSharedContextId, FuncUsage::Prototype);
9797*8975f5c5SAndroid Build Coastguard Worker bodyStream << protoStream.str() << "\n";
9798*8975f5c5SAndroid Build Coastguard Worker bodyStream << "{\n";
9799*8975f5c5SAndroid Build Coastguard Worker
9800*8975f5c5SAndroid Build Coastguard Worker for (ResourceIDType resourceType : AllEnums<ResourceIDType>())
9801*8975f5c5SAndroid Build Coastguard Worker {
9802*8975f5c5SAndroid Build Coastguard Worker if (!IsSharedObjectResource(resourceType))
9803*8975f5c5SAndroid Build Coastguard Worker {
9804*8975f5c5SAndroid Build Coastguard Worker continue;
9805*8975f5c5SAndroid Build Coastguard Worker }
9806*8975f5c5SAndroid Build Coastguard Worker // Use current context for shared reset
9807*8975f5c5SAndroid Build Coastguard Worker MaybeResetResources(context->getDisplay(), context->id(), resourceType,
9808*8975f5c5SAndroid Build Coastguard Worker mReplayWriter, bodyStream, headerStream, &mResourceTracker,
9809*8975f5c5SAndroid Build Coastguard Worker &mBinaryData, anyResourceReset, &mResourceIDBufferSize);
9810*8975f5c5SAndroid Build Coastguard Worker }
9811*8975f5c5SAndroid Build Coastguard Worker
9812*8975f5c5SAndroid Build Coastguard Worker // Reset opaque type objects that don't have IDs, so are not ResourceIDTypes.
9813*8975f5c5SAndroid Build Coastguard Worker MaybeResetOpaqueTypeObjects(mReplayWriter, bodyStream, headerStream, context,
9814*8975f5c5SAndroid Build Coastguard Worker &mResourceTracker, &mBinaryData, &mResourceIDBufferSize);
9815*8975f5c5SAndroid Build Coastguard Worker
9816*8975f5c5SAndroid Build Coastguard Worker bodyStream << "}\n";
9817*8975f5c5SAndroid Build Coastguard Worker
9818*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.addPrivateFunction(protoStream.str(), headerStream, bodyStream);
9819*8975f5c5SAndroid Build Coastguard Worker }
9820*8975f5c5SAndroid Build Coastguard Worker
9821*8975f5c5SAndroid Build Coastguard Worker // Emit the call to shared object reset
9822*8975f5c5SAndroid Build Coastguard Worker resetBodyStream << " " << FmtResetFunction(kNoPartId, kSharedContextId, FuncUsage::Call)
9823*8975f5c5SAndroid Build Coastguard Worker << ";\n";
9824*8975f5c5SAndroid Build Coastguard Worker
9825*8975f5c5SAndroid Build Coastguard Worker // Reset our output tracker (Note: This was unused during shared reset)
9826*8975f5c5SAndroid Build Coastguard Worker anyResourceReset = false;
9827*8975f5c5SAndroid Build Coastguard Worker
9828*8975f5c5SAndroid Build Coastguard Worker // Walk through all contexts that need Reset
9829*8975f5c5SAndroid Build Coastguard Worker for (const gl::ContextID &contextID : contextIDs)
9830*8975f5c5SAndroid Build Coastguard Worker {
9831*8975f5c5SAndroid Build Coastguard Worker // Create a function to reset each context's non-shared objects
9832*8975f5c5SAndroid Build Coastguard Worker {
9833*8975f5c5SAndroid Build Coastguard Worker std::stringstream protoStream;
9834*8975f5c5SAndroid Build Coastguard Worker std::stringstream headerStream;
9835*8975f5c5SAndroid Build Coastguard Worker std::stringstream bodyStream;
9836*8975f5c5SAndroid Build Coastguard Worker
9837*8975f5c5SAndroid Build Coastguard Worker protoStream << "void "
9838*8975f5c5SAndroid Build Coastguard Worker << FmtResetFunction(kNoPartId, contextID, FuncUsage::Prototype);
9839*8975f5c5SAndroid Build Coastguard Worker bodyStream << protoStream.str() << "\n";
9840*8975f5c5SAndroid Build Coastguard Worker bodyStream << "{\n";
9841*8975f5c5SAndroid Build Coastguard Worker
9842*8975f5c5SAndroid Build Coastguard Worker // Build the Reset calls in a separate stream so we can insert before them
9843*8975f5c5SAndroid Build Coastguard Worker std::stringstream resetStream;
9844*8975f5c5SAndroid Build Coastguard Worker
9845*8975f5c5SAndroid Build Coastguard Worker for (ResourceIDType resourceType : AllEnums<ResourceIDType>())
9846*8975f5c5SAndroid Build Coastguard Worker {
9847*8975f5c5SAndroid Build Coastguard Worker if (IsSharedObjectResource(resourceType))
9848*8975f5c5SAndroid Build Coastguard Worker {
9849*8975f5c5SAndroid Build Coastguard Worker continue;
9850*8975f5c5SAndroid Build Coastguard Worker }
9851*8975f5c5SAndroid Build Coastguard Worker MaybeResetResources(context->getDisplay(), contextID, resourceType,
9852*8975f5c5SAndroid Build Coastguard Worker mReplayWriter, resetStream, headerStream, &mResourceTracker,
9853*8975f5c5SAndroid Build Coastguard Worker &mBinaryData, anyResourceReset, &mResourceIDBufferSize);
9854*8975f5c5SAndroid Build Coastguard Worker }
9855*8975f5c5SAndroid Build Coastguard Worker
9856*8975f5c5SAndroid Build Coastguard Worker // Only call eglMakeCurrent if anything was actually reset in the function and the
9857*8975f5c5SAndroid Build Coastguard Worker // context differs from current
9858*8975f5c5SAndroid Build Coastguard Worker if (anyResourceReset && contextID != context->id())
9859*8975f5c5SAndroid Build Coastguard Worker {
9860*8975f5c5SAndroid Build Coastguard Worker contextChanged = true;
9861*8975f5c5SAndroid Build Coastguard Worker bodyStream << " eglMakeCurrent(NULL, NULL, NULL, gContextMap2["
9862*8975f5c5SAndroid Build Coastguard Worker << contextID.value << "]);\n\n";
9863*8975f5c5SAndroid Build Coastguard Worker }
9864*8975f5c5SAndroid Build Coastguard Worker
9865*8975f5c5SAndroid Build Coastguard Worker // Then append the Reset calls
9866*8975f5c5SAndroid Build Coastguard Worker bodyStream << resetStream.str();
9867*8975f5c5SAndroid Build Coastguard Worker
9868*8975f5c5SAndroid Build Coastguard Worker bodyStream << "}\n";
9869*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.addPrivateFunction(protoStream.str(), headerStream, bodyStream);
9870*8975f5c5SAndroid Build Coastguard Worker }
9871*8975f5c5SAndroid Build Coastguard Worker
9872*8975f5c5SAndroid Build Coastguard Worker // Emit a call to reset each context's non-shared objects
9873*8975f5c5SAndroid Build Coastguard Worker resetBodyStream << " " << FmtResetFunction(kNoPartId, contextID, FuncUsage::Call)
9874*8975f5c5SAndroid Build Coastguard Worker << ";\n";
9875*8975f5c5SAndroid Build Coastguard Worker }
9876*8975f5c5SAndroid Build Coastguard Worker
9877*8975f5c5SAndroid Build Coastguard Worker // Bind the main context again if we bound any additional contexts
9878*8975f5c5SAndroid Build Coastguard Worker if (contextChanged)
9879*8975f5c5SAndroid Build Coastguard Worker {
9880*8975f5c5SAndroid Build Coastguard Worker resetBodyStream << " eglMakeCurrent(NULL, NULL, NULL, gContextMap2["
9881*8975f5c5SAndroid Build Coastguard Worker << context->id().value << "]);\n";
9882*8975f5c5SAndroid Build Coastguard Worker }
9883*8975f5c5SAndroid Build Coastguard Worker
9884*8975f5c5SAndroid Build Coastguard Worker // Now that we're back on the main context, reset any additional state
9885*8975f5c5SAndroid Build Coastguard Worker resetBodyStream << "\n // Reset main context state\n";
9886*8975f5c5SAndroid Build Coastguard Worker MaybeResetContextState(mReplayWriter, resetBodyStream, resetHeaderStream, &mResourceTracker,
9887*8975f5c5SAndroid Build Coastguard Worker context, &mBinaryData, stateResetHelper, &mResourceIDBufferSize);
9888*8975f5c5SAndroid Build Coastguard Worker
9889*8975f5c5SAndroid Build Coastguard Worker resetBodyStream << "}\n";
9890*8975f5c5SAndroid Build Coastguard Worker
9891*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.addPublicFunction(resetProtoStream.str(), resetHeaderStream, resetBodyStream);
9892*8975f5c5SAndroid Build Coastguard Worker }
9893*8975f5c5SAndroid Build Coastguard Worker
9894*8975f5c5SAndroid Build Coastguard Worker if (!mFrameCalls.empty())
9895*8975f5c5SAndroid Build Coastguard Worker {
9896*8975f5c5SAndroid Build Coastguard Worker std::stringstream protoStream;
9897*8975f5c5SAndroid Build Coastguard Worker protoStream << "void "
9898*8975f5c5SAndroid Build Coastguard Worker << FmtReplayFunction(context->id(), FuncUsage::Prototype, frameIndex);
9899*8975f5c5SAndroid Build Coastguard Worker std::string proto = protoStream.str();
9900*8975f5c5SAndroid Build Coastguard Worker std::stringstream headerStream;
9901*8975f5c5SAndroid Build Coastguard Worker std::stringstream bodyStream;
9902*8975f5c5SAndroid Build Coastguard Worker
9903*8975f5c5SAndroid Build Coastguard Worker if (context->getShareGroup()->getContexts().size() > 1)
9904*8975f5c5SAndroid Build Coastguard Worker {
9905*8975f5c5SAndroid Build Coastguard Worker // Only ReplayFunc::Replay trace file output functions are affected by multi-context
9906*8975f5c5SAndroid Build Coastguard Worker // call grouping so they can safely be special-cased here.
9907*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayFunctionWithPartsMultiContext(
9908*8975f5c5SAndroid Build Coastguard Worker context->id(), ReplayFunc::Replay, mReplayWriter, frameIndex, &mBinaryData,
9909*8975f5c5SAndroid Build Coastguard Worker mFrameCalls, headerStream, bodyStream, &mResourceIDBufferSize);
9910*8975f5c5SAndroid Build Coastguard Worker }
9911*8975f5c5SAndroid Build Coastguard Worker else
9912*8975f5c5SAndroid Build Coastguard Worker {
9913*8975f5c5SAndroid Build Coastguard Worker WriteCppReplayFunctionWithParts(context->id(), ReplayFunc::Replay, mReplayWriter,
9914*8975f5c5SAndroid Build Coastguard Worker frameIndex, &mBinaryData, mFrameCalls, headerStream,
9915*8975f5c5SAndroid Build Coastguard Worker bodyStream, &mResourceIDBufferSize);
9916*8975f5c5SAndroid Build Coastguard Worker }
9917*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.addPrivateFunction(proto, headerStream, bodyStream);
9918*8975f5c5SAndroid Build Coastguard Worker }
9919*8975f5c5SAndroid Build Coastguard Worker
9920*8975f5c5SAndroid Build Coastguard Worker if (mSerializeStateEnabled)
9921*8975f5c5SAndroid Build Coastguard Worker {
9922*8975f5c5SAndroid Build Coastguard Worker std::string serializedContextString;
9923*8975f5c5SAndroid Build Coastguard Worker if (SerializeContextToString(const_cast<gl::Context *>(context),
9924*8975f5c5SAndroid Build Coastguard Worker &serializedContextString) == Result::Continue)
9925*8975f5c5SAndroid Build Coastguard Worker {
9926*8975f5c5SAndroid Build Coastguard Worker std::stringstream protoStream;
9927*8975f5c5SAndroid Build Coastguard Worker protoStream << "const char *"
9928*8975f5c5SAndroid Build Coastguard Worker << FmtGetSerializedContextStateFunction(context->id(), FuncUsage::Prototype,
9929*8975f5c5SAndroid Build Coastguard Worker frameIndex);
9930*8975f5c5SAndroid Build Coastguard Worker std::string proto = protoStream.str();
9931*8975f5c5SAndroid Build Coastguard Worker
9932*8975f5c5SAndroid Build Coastguard Worker std::stringstream bodyStream;
9933*8975f5c5SAndroid Build Coastguard Worker bodyStream << proto << "\n";
9934*8975f5c5SAndroid Build Coastguard Worker bodyStream << "{\n";
9935*8975f5c5SAndroid Build Coastguard Worker bodyStream << " return " << FmtMultiLineString(serializedContextString) << ";\n";
9936*8975f5c5SAndroid Build Coastguard Worker bodyStream << "}\n";
9937*8975f5c5SAndroid Build Coastguard Worker
9938*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.addPrivateFunction(proto, std::stringstream(), bodyStream);
9939*8975f5c5SAndroid Build Coastguard Worker }
9940*8975f5c5SAndroid Build Coastguard Worker }
9941*8975f5c5SAndroid Build Coastguard Worker
9942*8975f5c5SAndroid Build Coastguard Worker {
9943*8975f5c5SAndroid Build Coastguard Worker std::stringstream fnamePatternStream;
9944*8975f5c5SAndroid Build Coastguard Worker fnamePatternStream << mOutDirectory << FmtCapturePrefix(context->id(), mCaptureLabel);
9945*8975f5c5SAndroid Build Coastguard Worker std::string fnamePattern = fnamePatternStream.str();
9946*8975f5c5SAndroid Build Coastguard Worker
9947*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.setFilenamePattern(fnamePattern);
9948*8975f5c5SAndroid Build Coastguard Worker }
9949*8975f5c5SAndroid Build Coastguard Worker
9950*8975f5c5SAndroid Build Coastguard Worker if (mFrameIndex == mCaptureEndFrame)
9951*8975f5c5SAndroid Build Coastguard Worker {
9952*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.saveFrame();
9953*8975f5c5SAndroid Build Coastguard Worker }
9954*8975f5c5SAndroid Build Coastguard Worker else
9955*8975f5c5SAndroid Build Coastguard Worker {
9956*8975f5c5SAndroid Build Coastguard Worker mReplayWriter.saveFrameIfFull();
9957*8975f5c5SAndroid Build Coastguard Worker }
9958*8975f5c5SAndroid Build Coastguard Worker }
9959*8975f5c5SAndroid Build Coastguard Worker
reset()9960*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::reset()
9961*8975f5c5SAndroid Build Coastguard Worker {
9962*8975f5c5SAndroid Build Coastguard Worker mFrameCalls.clear();
9963*8975f5c5SAndroid Build Coastguard Worker mClientVertexArrayMap.fill(-1);
9964*8975f5c5SAndroid Build Coastguard Worker
9965*8975f5c5SAndroid Build Coastguard Worker // Do not reset replay-specific settings like the maximum read buffer size, client array sizes,
9966*8975f5c5SAndroid Build Coastguard Worker // or the 'has seen' type map. We could refine this into per-frame and per-capture maximums if
9967*8975f5c5SAndroid Build Coastguard Worker // necessary.
9968*8975f5c5SAndroid Build Coastguard Worker }
9969*8975f5c5SAndroid Build Coastguard Worker
getShaderSource(gl::ShaderProgramID id) const9970*8975f5c5SAndroid Build Coastguard Worker const std::string &FrameCaptureShared::getShaderSource(gl::ShaderProgramID id) const
9971*8975f5c5SAndroid Build Coastguard Worker {
9972*8975f5c5SAndroid Build Coastguard Worker const auto &foundSources = mCachedShaderSource.find(id);
9973*8975f5c5SAndroid Build Coastguard Worker ASSERT(foundSources != mCachedShaderSource.end());
9974*8975f5c5SAndroid Build Coastguard Worker return foundSources->second;
9975*8975f5c5SAndroid Build Coastguard Worker }
9976*8975f5c5SAndroid Build Coastguard Worker
setShaderSource(gl::ShaderProgramID id,std::string source)9977*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::setShaderSource(gl::ShaderProgramID id, std::string source)
9978*8975f5c5SAndroid Build Coastguard Worker {
9979*8975f5c5SAndroid Build Coastguard Worker mCachedShaderSource[id] = source;
9980*8975f5c5SAndroid Build Coastguard Worker }
9981*8975f5c5SAndroid Build Coastguard Worker
getProgramSources(gl::ShaderProgramID id) const9982*8975f5c5SAndroid Build Coastguard Worker const ProgramSources &FrameCaptureShared::getProgramSources(gl::ShaderProgramID id) const
9983*8975f5c5SAndroid Build Coastguard Worker {
9984*8975f5c5SAndroid Build Coastguard Worker const auto &foundSources = mCachedProgramSources.find(id);
9985*8975f5c5SAndroid Build Coastguard Worker ASSERT(foundSources != mCachedProgramSources.end());
9986*8975f5c5SAndroid Build Coastguard Worker return foundSources->second;
9987*8975f5c5SAndroid Build Coastguard Worker }
9988*8975f5c5SAndroid Build Coastguard Worker
setProgramSources(gl::ShaderProgramID id,ProgramSources sources)9989*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::setProgramSources(gl::ShaderProgramID id, ProgramSources sources)
9990*8975f5c5SAndroid Build Coastguard Worker {
9991*8975f5c5SAndroid Build Coastguard Worker mCachedProgramSources[id] = sources;
9992*8975f5c5SAndroid Build Coastguard Worker }
9993*8975f5c5SAndroid Build Coastguard Worker
markResourceSetupCallsInactive(std::vector<CallCapture> * setupCalls,ResourceIDType type,GLuint id,gl::Range<size_t> range)9994*8975f5c5SAndroid Build Coastguard Worker void FrameCaptureShared::markResourceSetupCallsInactive(std::vector<CallCapture> *setupCalls,
9995*8975f5c5SAndroid Build Coastguard Worker ResourceIDType type,
9996*8975f5c5SAndroid Build Coastguard Worker GLuint id,
9997*8975f5c5SAndroid Build Coastguard Worker gl::Range<size_t> range)
9998*8975f5c5SAndroid Build Coastguard Worker {
9999*8975f5c5SAndroid Build Coastguard Worker ASSERT(mResourceIDToSetupCalls[type].find(id) == mResourceIDToSetupCalls[type].end());
10000*8975f5c5SAndroid Build Coastguard Worker
10001*8975f5c5SAndroid Build Coastguard Worker // Mark all of the calls that were used to initialize this resource as INACTIVE
10002*8975f5c5SAndroid Build Coastguard Worker for (size_t index : range)
10003*8975f5c5SAndroid Build Coastguard Worker {
10004*8975f5c5SAndroid Build Coastguard Worker (*setupCalls)[index].isActive = false;
10005*8975f5c5SAndroid Build Coastguard Worker }
10006*8975f5c5SAndroid Build Coastguard Worker
10007*8975f5c5SAndroid Build Coastguard Worker mResourceIDToSetupCalls[type][id] = range;
10008*8975f5c5SAndroid Build Coastguard Worker }
10009*8975f5c5SAndroid Build Coastguard Worker
CaptureMemory(const void * source,size_t size,ParamCapture * paramCapture)10010*8975f5c5SAndroid Build Coastguard Worker void CaptureMemory(const void *source, size_t size, ParamCapture *paramCapture)
10011*8975f5c5SAndroid Build Coastguard Worker {
10012*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> data(size);
10013*8975f5c5SAndroid Build Coastguard Worker memcpy(data.data(), source, size);
10014*8975f5c5SAndroid Build Coastguard Worker paramCapture->data.emplace_back(std::move(data));
10015*8975f5c5SAndroid Build Coastguard Worker }
10016*8975f5c5SAndroid Build Coastguard Worker
CaptureString(const GLchar * str,ParamCapture * paramCapture)10017*8975f5c5SAndroid Build Coastguard Worker void CaptureString(const GLchar *str, ParamCapture *paramCapture)
10018*8975f5c5SAndroid Build Coastguard Worker {
10019*8975f5c5SAndroid Build Coastguard Worker // include the '\0' suffix
10020*8975f5c5SAndroid Build Coastguard Worker CaptureMemory(str, strlen(str) + 1, paramCapture);
10021*8975f5c5SAndroid Build Coastguard Worker }
10022*8975f5c5SAndroid Build Coastguard Worker
CaptureStringLimit(const GLchar * str,uint32_t limit,ParamCapture * paramCapture)10023*8975f5c5SAndroid Build Coastguard Worker void CaptureStringLimit(const GLchar *str, uint32_t limit, ParamCapture *paramCapture)
10024*8975f5c5SAndroid Build Coastguard Worker {
10025*8975f5c5SAndroid Build Coastguard Worker // Write the incoming string up to limit, including null terminator
10026*8975f5c5SAndroid Build Coastguard Worker size_t length = strlen(str) + 1;
10027*8975f5c5SAndroid Build Coastguard Worker
10028*8975f5c5SAndroid Build Coastguard Worker if (length > limit)
10029*8975f5c5SAndroid Build Coastguard Worker {
10030*8975f5c5SAndroid Build Coastguard Worker // If too many characters, resize the string to fit in the limit
10031*8975f5c5SAndroid Build Coastguard Worker std::string newStr = str;
10032*8975f5c5SAndroid Build Coastguard Worker newStr.resize(limit - 1);
10033*8975f5c5SAndroid Build Coastguard Worker CaptureString(newStr.c_str(), paramCapture);
10034*8975f5c5SAndroid Build Coastguard Worker }
10035*8975f5c5SAndroid Build Coastguard Worker else
10036*8975f5c5SAndroid Build Coastguard Worker {
10037*8975f5c5SAndroid Build Coastguard Worker CaptureMemory(str, length, paramCapture);
10038*8975f5c5SAndroid Build Coastguard Worker }
10039*8975f5c5SAndroid Build Coastguard Worker }
10040*8975f5c5SAndroid Build Coastguard Worker
CaptureVertexPointerGLES1(const gl::State & glState,gl::ClientVertexArrayType type,const void * pointer,ParamCapture * paramCapture)10041*8975f5c5SAndroid Build Coastguard Worker void CaptureVertexPointerGLES1(const gl::State &glState,
10042*8975f5c5SAndroid Build Coastguard Worker gl::ClientVertexArrayType type,
10043*8975f5c5SAndroid Build Coastguard Worker const void *pointer,
10044*8975f5c5SAndroid Build Coastguard Worker ParamCapture *paramCapture)
10045*8975f5c5SAndroid Build Coastguard Worker {
10046*8975f5c5SAndroid Build Coastguard Worker paramCapture->value.voidConstPointerVal = pointer;
10047*8975f5c5SAndroid Build Coastguard Worker if (!glState.getTargetBuffer(gl::BufferBinding::Array))
10048*8975f5c5SAndroid Build Coastguard Worker {
10049*8975f5c5SAndroid Build Coastguard Worker paramCapture->arrayClientPointerIndex =
10050*8975f5c5SAndroid Build Coastguard Worker gl::GLES1Renderer::VertexArrayIndex(type, glState.gles1());
10051*8975f5c5SAndroid Build Coastguard Worker }
10052*8975f5c5SAndroid Build Coastguard Worker }
10053*8975f5c5SAndroid Build Coastguard Worker
GetProgramForCapture(const gl::State & glState,gl::ShaderProgramID handle)10054*8975f5c5SAndroid Build Coastguard Worker gl::Program *GetProgramForCapture(const gl::State &glState, gl::ShaderProgramID handle)
10055*8975f5c5SAndroid Build Coastguard Worker {
10056*8975f5c5SAndroid Build Coastguard Worker gl::Program *program = glState.getShaderProgramManagerForCapture().getProgram(handle);
10057*8975f5c5SAndroid Build Coastguard Worker return program;
10058*8975f5c5SAndroid Build Coastguard Worker }
10059*8975f5c5SAndroid Build Coastguard Worker
CaptureGetActiveUniformBlockivParameters(const gl::State & glState,gl::ShaderProgramID handle,gl::UniformBlockIndex uniformBlockIndex,GLenum pname,ParamCapture * paramCapture)10060*8975f5c5SAndroid Build Coastguard Worker void CaptureGetActiveUniformBlockivParameters(const gl::State &glState,
10061*8975f5c5SAndroid Build Coastguard Worker gl::ShaderProgramID handle,
10062*8975f5c5SAndroid Build Coastguard Worker gl::UniformBlockIndex uniformBlockIndex,
10063*8975f5c5SAndroid Build Coastguard Worker GLenum pname,
10064*8975f5c5SAndroid Build Coastguard Worker ParamCapture *paramCapture)
10065*8975f5c5SAndroid Build Coastguard Worker {
10066*8975f5c5SAndroid Build Coastguard Worker int numParams = 1;
10067*8975f5c5SAndroid Build Coastguard Worker
10068*8975f5c5SAndroid Build Coastguard Worker // From the OpenGL ES 3.0 spec:
10069*8975f5c5SAndroid Build Coastguard Worker // If pname is UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, then a list of the
10070*8975f5c5SAndroid Build Coastguard Worker // active uniform indices for the uniform block identified by uniformBlockIndex is
10071*8975f5c5SAndroid Build Coastguard Worker // returned. The number of elements that will be written to params is the value of
10072*8975f5c5SAndroid Build Coastguard Worker // UNIFORM_BLOCK_ACTIVE_UNIFORMS for uniformBlockIndex
10073*8975f5c5SAndroid Build Coastguard Worker if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
10074*8975f5c5SAndroid Build Coastguard Worker {
10075*8975f5c5SAndroid Build Coastguard Worker gl::Program *program = GetProgramForCapture(glState, handle);
10076*8975f5c5SAndroid Build Coastguard Worker if (program)
10077*8975f5c5SAndroid Build Coastguard Worker {
10078*8975f5c5SAndroid Build Coastguard Worker gl::QueryActiveUniformBlockiv(program, uniformBlockIndex,
10079*8975f5c5SAndroid Build Coastguard Worker GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &numParams);
10080*8975f5c5SAndroid Build Coastguard Worker }
10081*8975f5c5SAndroid Build Coastguard Worker }
10082*8975f5c5SAndroid Build Coastguard Worker
10083*8975f5c5SAndroid Build Coastguard Worker paramCapture->readBufferSizeBytes = sizeof(GLint) * numParams;
10084*8975f5c5SAndroid Build Coastguard Worker }
10085*8975f5c5SAndroid Build Coastguard Worker
CaptureGetParameter(const gl::State & glState,GLenum pname,size_t typeSize,ParamCapture * paramCapture)10086*8975f5c5SAndroid Build Coastguard Worker void CaptureGetParameter(const gl::State &glState,
10087*8975f5c5SAndroid Build Coastguard Worker GLenum pname,
10088*8975f5c5SAndroid Build Coastguard Worker size_t typeSize,
10089*8975f5c5SAndroid Build Coastguard Worker ParamCapture *paramCapture)
10090*8975f5c5SAndroid Build Coastguard Worker {
10091*8975f5c5SAndroid Build Coastguard Worker // kMaxReportedCapabilities is the biggest array we'll need to hold data from glGet calls.
10092*8975f5c5SAndroid Build Coastguard Worker // This value needs to be updated if any new extensions are introduced that would allow for
10093*8975f5c5SAndroid Build Coastguard Worker // more compressed texture formats. The current value is taken from:
10094*8975f5c5SAndroid Build Coastguard Worker // http://opengles.gpuinfo.org/displaycapability.php?name=GL_NUM_COMPRESSED_TEXTURE_FORMATS&esversion=2
10095*8975f5c5SAndroid Build Coastguard Worker constexpr unsigned int kMaxReportedCapabilities = 69;
10096*8975f5c5SAndroid Build Coastguard Worker paramCapture->readBufferSizeBytes = typeSize * kMaxReportedCapabilities;
10097*8975f5c5SAndroid Build Coastguard Worker }
10098*8975f5c5SAndroid Build Coastguard Worker
CaptureGenHandlesImpl(GLsizei n,GLuint * handles,ParamCapture * paramCapture)10099*8975f5c5SAndroid Build Coastguard Worker void CaptureGenHandlesImpl(GLsizei n, GLuint *handles, ParamCapture *paramCapture)
10100*8975f5c5SAndroid Build Coastguard Worker {
10101*8975f5c5SAndroid Build Coastguard Worker paramCapture->readBufferSizeBytes = sizeof(GLuint) * n;
10102*8975f5c5SAndroid Build Coastguard Worker CaptureMemory(handles, paramCapture->readBufferSizeBytes, paramCapture);
10103*8975f5c5SAndroid Build Coastguard Worker }
10104*8975f5c5SAndroid Build Coastguard Worker
CaptureShaderStrings(GLsizei count,const GLchar * const * strings,const GLint * length,ParamCapture * paramCapture)10105*8975f5c5SAndroid Build Coastguard Worker void CaptureShaderStrings(GLsizei count,
10106*8975f5c5SAndroid Build Coastguard Worker const GLchar *const *strings,
10107*8975f5c5SAndroid Build Coastguard Worker const GLint *length,
10108*8975f5c5SAndroid Build Coastguard Worker ParamCapture *paramCapture)
10109*8975f5c5SAndroid Build Coastguard Worker {
10110*8975f5c5SAndroid Build Coastguard Worker // Concat the array elements of the string into one data vector,
10111*8975f5c5SAndroid Build Coastguard Worker // append the terminating zero and use this as the captured shader
10112*8975f5c5SAndroid Build Coastguard Worker // string. The string count and the length array are adjusted
10113*8975f5c5SAndroid Build Coastguard Worker // accordingly in the capture post-processing
10114*8975f5c5SAndroid Build Coastguard Worker
10115*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> data;
10116*8975f5c5SAndroid Build Coastguard Worker size_t offset = 0;
10117*8975f5c5SAndroid Build Coastguard Worker for (GLsizei index = 0; index < count; ++index)
10118*8975f5c5SAndroid Build Coastguard Worker {
10119*8975f5c5SAndroid Build Coastguard Worker size_t len = ((length && length[index] >= 0) ? length[index] : strlen(strings[index]));
10120*8975f5c5SAndroid Build Coastguard Worker
10121*8975f5c5SAndroid Build Coastguard Worker // Count trailing zeros
10122*8975f5c5SAndroid Build Coastguard Worker uint32_t i = 1;
10123*8975f5c5SAndroid Build Coastguard Worker while (i < len && strings[index][len - i] == 0)
10124*8975f5c5SAndroid Build Coastguard Worker {
10125*8975f5c5SAndroid Build Coastguard Worker i++;
10126*8975f5c5SAndroid Build Coastguard Worker }
10127*8975f5c5SAndroid Build Coastguard Worker
10128*8975f5c5SAndroid Build Coastguard Worker // Don't copy trailing zeros
10129*8975f5c5SAndroid Build Coastguard Worker len -= (i - 1);
10130*8975f5c5SAndroid Build Coastguard Worker
10131*8975f5c5SAndroid Build Coastguard Worker data.resize(offset + len);
10132*8975f5c5SAndroid Build Coastguard Worker std::copy(strings[index], strings[index] + len, data.begin() + offset);
10133*8975f5c5SAndroid Build Coastguard Worker offset += len;
10134*8975f5c5SAndroid Build Coastguard Worker }
10135*8975f5c5SAndroid Build Coastguard Worker
10136*8975f5c5SAndroid Build Coastguard Worker data.push_back(0);
10137*8975f5c5SAndroid Build Coastguard Worker paramCapture->data.emplace_back(std::move(data));
10138*8975f5c5SAndroid Build Coastguard Worker }
10139*8975f5c5SAndroid Build Coastguard Worker
10140*8975f5c5SAndroid Build Coastguard Worker // ReplayWriter implementation.
ReplayWriter()10141*8975f5c5SAndroid Build Coastguard Worker ReplayWriter::ReplayWriter()
10142*8975f5c5SAndroid Build Coastguard Worker : mSourceFileExtension(kDefaultSourceFileExt),
10143*8975f5c5SAndroid Build Coastguard Worker mSourceFileSizeThreshold(kDefaultSourceFileSizeThreshold),
10144*8975f5c5SAndroid Build Coastguard Worker mFrameIndex(1)
10145*8975f5c5SAndroid Build Coastguard Worker {}
10146*8975f5c5SAndroid Build Coastguard Worker
~ReplayWriter()10147*8975f5c5SAndroid Build Coastguard Worker ReplayWriter::~ReplayWriter()
10148*8975f5c5SAndroid Build Coastguard Worker {
10149*8975f5c5SAndroid Build Coastguard Worker ASSERT(mPrivateFunctionPrototypes.empty());
10150*8975f5c5SAndroid Build Coastguard Worker ASSERT(mPublicFunctionPrototypes.empty());
10151*8975f5c5SAndroid Build Coastguard Worker ASSERT(mPrivateFunctions.empty());
10152*8975f5c5SAndroid Build Coastguard Worker ASSERT(mPublicFunctions.empty());
10153*8975f5c5SAndroid Build Coastguard Worker ASSERT(mGlobalVariableDeclarations.empty());
10154*8975f5c5SAndroid Build Coastguard Worker ASSERT(mReplayHeaders.empty());
10155*8975f5c5SAndroid Build Coastguard Worker }
10156*8975f5c5SAndroid Build Coastguard Worker
setSourceFileExtension(const char * ext)10157*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::setSourceFileExtension(const char *ext)
10158*8975f5c5SAndroid Build Coastguard Worker {
10159*8975f5c5SAndroid Build Coastguard Worker mSourceFileExtension = ext;
10160*8975f5c5SAndroid Build Coastguard Worker }
10161*8975f5c5SAndroid Build Coastguard Worker
setSourceFileSizeThreshold(size_t sourceFileSizeThreshold)10162*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::setSourceFileSizeThreshold(size_t sourceFileSizeThreshold)
10163*8975f5c5SAndroid Build Coastguard Worker {
10164*8975f5c5SAndroid Build Coastguard Worker mSourceFileSizeThreshold = sourceFileSizeThreshold;
10165*8975f5c5SAndroid Build Coastguard Worker }
10166*8975f5c5SAndroid Build Coastguard Worker
setFilenamePattern(const std::string & pattern)10167*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::setFilenamePattern(const std::string &pattern)
10168*8975f5c5SAndroid Build Coastguard Worker {
10169*8975f5c5SAndroid Build Coastguard Worker if (mFilenamePattern != pattern)
10170*8975f5c5SAndroid Build Coastguard Worker {
10171*8975f5c5SAndroid Build Coastguard Worker mFilenamePattern = pattern;
10172*8975f5c5SAndroid Build Coastguard Worker }
10173*8975f5c5SAndroid Build Coastguard Worker }
10174*8975f5c5SAndroid Build Coastguard Worker
setCaptureLabel(const std::string & label)10175*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::setCaptureLabel(const std::string &label)
10176*8975f5c5SAndroid Build Coastguard Worker {
10177*8975f5c5SAndroid Build Coastguard Worker mCaptureLabel = label;
10178*8975f5c5SAndroid Build Coastguard Worker }
10179*8975f5c5SAndroid Build Coastguard Worker
setSourcePrologue(const std::string & prologue)10180*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::setSourcePrologue(const std::string &prologue)
10181*8975f5c5SAndroid Build Coastguard Worker {
10182*8975f5c5SAndroid Build Coastguard Worker mSourcePrologue = prologue;
10183*8975f5c5SAndroid Build Coastguard Worker }
10184*8975f5c5SAndroid Build Coastguard Worker
setHeaderPrologue(const std::string & prologue)10185*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::setHeaderPrologue(const std::string &prologue)
10186*8975f5c5SAndroid Build Coastguard Worker {
10187*8975f5c5SAndroid Build Coastguard Worker mHeaderPrologue = prologue;
10188*8975f5c5SAndroid Build Coastguard Worker }
10189*8975f5c5SAndroid Build Coastguard Worker
addPublicFunction(const std::string & functionProto,const std::stringstream & headerStream,const std::stringstream & bodyStream)10190*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::addPublicFunction(const std::string &functionProto,
10191*8975f5c5SAndroid Build Coastguard Worker const std::stringstream &headerStream,
10192*8975f5c5SAndroid Build Coastguard Worker const std::stringstream &bodyStream)
10193*8975f5c5SAndroid Build Coastguard Worker {
10194*8975f5c5SAndroid Build Coastguard Worker mPublicFunctionPrototypes.push_back(functionProto);
10195*8975f5c5SAndroid Build Coastguard Worker
10196*8975f5c5SAndroid Build Coastguard Worker std::string header = headerStream.str();
10197*8975f5c5SAndroid Build Coastguard Worker std::string body = bodyStream.str();
10198*8975f5c5SAndroid Build Coastguard Worker
10199*8975f5c5SAndroid Build Coastguard Worker if (!header.empty())
10200*8975f5c5SAndroid Build Coastguard Worker {
10201*8975f5c5SAndroid Build Coastguard Worker mReplayHeaders.emplace_back(header);
10202*8975f5c5SAndroid Build Coastguard Worker }
10203*8975f5c5SAndroid Build Coastguard Worker
10204*8975f5c5SAndroid Build Coastguard Worker if (!body.empty())
10205*8975f5c5SAndroid Build Coastguard Worker {
10206*8975f5c5SAndroid Build Coastguard Worker mPublicFunctions.emplace_back(body);
10207*8975f5c5SAndroid Build Coastguard Worker }
10208*8975f5c5SAndroid Build Coastguard Worker }
10209*8975f5c5SAndroid Build Coastguard Worker
addPrivateFunction(const std::string & functionProto,const std::stringstream & headerStream,const std::stringstream & bodyStream)10210*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::addPrivateFunction(const std::string &functionProto,
10211*8975f5c5SAndroid Build Coastguard Worker const std::stringstream &headerStream,
10212*8975f5c5SAndroid Build Coastguard Worker const std::stringstream &bodyStream)
10213*8975f5c5SAndroid Build Coastguard Worker {
10214*8975f5c5SAndroid Build Coastguard Worker mPrivateFunctionPrototypes.push_back(functionProto);
10215*8975f5c5SAndroid Build Coastguard Worker
10216*8975f5c5SAndroid Build Coastguard Worker std::string header = headerStream.str();
10217*8975f5c5SAndroid Build Coastguard Worker std::string body = bodyStream.str();
10218*8975f5c5SAndroid Build Coastguard Worker
10219*8975f5c5SAndroid Build Coastguard Worker if (!header.empty())
10220*8975f5c5SAndroid Build Coastguard Worker {
10221*8975f5c5SAndroid Build Coastguard Worker mReplayHeaders.emplace_back(header);
10222*8975f5c5SAndroid Build Coastguard Worker }
10223*8975f5c5SAndroid Build Coastguard Worker
10224*8975f5c5SAndroid Build Coastguard Worker if (!body.empty())
10225*8975f5c5SAndroid Build Coastguard Worker {
10226*8975f5c5SAndroid Build Coastguard Worker mPrivateFunctions.emplace_back(body);
10227*8975f5c5SAndroid Build Coastguard Worker }
10228*8975f5c5SAndroid Build Coastguard Worker }
10229*8975f5c5SAndroid Build Coastguard Worker
getInlineVariableName(EntryPoint entryPoint,const std::string & paramName)10230*8975f5c5SAndroid Build Coastguard Worker std::string ReplayWriter::getInlineVariableName(EntryPoint entryPoint, const std::string ¶mName)
10231*8975f5c5SAndroid Build Coastguard Worker {
10232*8975f5c5SAndroid Build Coastguard Worker int counter = mDataTracker.getCounters().getAndIncrement(entryPoint, paramName);
10233*8975f5c5SAndroid Build Coastguard Worker return GetVarName(entryPoint, paramName, counter);
10234*8975f5c5SAndroid Build Coastguard Worker }
10235*8975f5c5SAndroid Build Coastguard Worker
getInlineStringSetVariableName(EntryPoint entryPoint,const std::string & paramName,const std::vector<std::string> & strings,bool * isNewEntryOut)10236*8975f5c5SAndroid Build Coastguard Worker std::string ReplayWriter::getInlineStringSetVariableName(EntryPoint entryPoint,
10237*8975f5c5SAndroid Build Coastguard Worker const std::string ¶mName,
10238*8975f5c5SAndroid Build Coastguard Worker const std::vector<std::string> &strings,
10239*8975f5c5SAndroid Build Coastguard Worker bool *isNewEntryOut)
10240*8975f5c5SAndroid Build Coastguard Worker {
10241*8975f5c5SAndroid Build Coastguard Worker int counter = mDataTracker.getStringCounters().getStringCounter(strings);
10242*8975f5c5SAndroid Build Coastguard Worker *isNewEntryOut = (counter == kStringsNotFound);
10243*8975f5c5SAndroid Build Coastguard Worker if (*isNewEntryOut)
10244*8975f5c5SAndroid Build Coastguard Worker {
10245*8975f5c5SAndroid Build Coastguard Worker // This is a unique set of strings, so set up their declaration and update the counter
10246*8975f5c5SAndroid Build Coastguard Worker counter = mDataTracker.getCounters().getAndIncrement(entryPoint, paramName);
10247*8975f5c5SAndroid Build Coastguard Worker mDataTracker.getStringCounters().setStringCounter(strings, counter);
10248*8975f5c5SAndroid Build Coastguard Worker
10249*8975f5c5SAndroid Build Coastguard Worker std::string varName = GetVarName(entryPoint, paramName, counter);
10250*8975f5c5SAndroid Build Coastguard Worker
10251*8975f5c5SAndroid Build Coastguard Worker std::stringstream declStream;
10252*8975f5c5SAndroid Build Coastguard Worker declStream << "const char *const " << varName << "[]";
10253*8975f5c5SAndroid Build Coastguard Worker std::string decl = declStream.str();
10254*8975f5c5SAndroid Build Coastguard Worker
10255*8975f5c5SAndroid Build Coastguard Worker mGlobalVariableDeclarations.push_back(decl);
10256*8975f5c5SAndroid Build Coastguard Worker
10257*8975f5c5SAndroid Build Coastguard Worker return varName;
10258*8975f5c5SAndroid Build Coastguard Worker }
10259*8975f5c5SAndroid Build Coastguard Worker else
10260*8975f5c5SAndroid Build Coastguard Worker {
10261*8975f5c5SAndroid Build Coastguard Worker return GetVarName(entryPoint, paramName, counter);
10262*8975f5c5SAndroid Build Coastguard Worker }
10263*8975f5c5SAndroid Build Coastguard Worker }
10264*8975f5c5SAndroid Build Coastguard Worker
getStoredReplaySourceSize() const10265*8975f5c5SAndroid Build Coastguard Worker size_t ReplayWriter::getStoredReplaySourceSize() const
10266*8975f5c5SAndroid Build Coastguard Worker {
10267*8975f5c5SAndroid Build Coastguard Worker size_t sum = 0;
10268*8975f5c5SAndroid Build Coastguard Worker for (const std::string &header : mReplayHeaders)
10269*8975f5c5SAndroid Build Coastguard Worker {
10270*8975f5c5SAndroid Build Coastguard Worker sum += header.size();
10271*8975f5c5SAndroid Build Coastguard Worker }
10272*8975f5c5SAndroid Build Coastguard Worker for (const std::string &publicFunc : mPublicFunctions)
10273*8975f5c5SAndroid Build Coastguard Worker {
10274*8975f5c5SAndroid Build Coastguard Worker sum += publicFunc.size();
10275*8975f5c5SAndroid Build Coastguard Worker }
10276*8975f5c5SAndroid Build Coastguard Worker for (const std::string &privateFunc : mPrivateFunctions)
10277*8975f5c5SAndroid Build Coastguard Worker {
10278*8975f5c5SAndroid Build Coastguard Worker sum += privateFunc.size();
10279*8975f5c5SAndroid Build Coastguard Worker }
10280*8975f5c5SAndroid Build Coastguard Worker return sum;
10281*8975f5c5SAndroid Build Coastguard Worker }
10282*8975f5c5SAndroid Build Coastguard Worker
10283*8975f5c5SAndroid Build Coastguard Worker // static
GetVarName(EntryPoint entryPoint,const std::string & paramName,int counter)10284*8975f5c5SAndroid Build Coastguard Worker std::string ReplayWriter::GetVarName(EntryPoint entryPoint,
10285*8975f5c5SAndroid Build Coastguard Worker const std::string ¶mName,
10286*8975f5c5SAndroid Build Coastguard Worker int counter)
10287*8975f5c5SAndroid Build Coastguard Worker {
10288*8975f5c5SAndroid Build Coastguard Worker std::stringstream strstr;
10289*8975f5c5SAndroid Build Coastguard Worker strstr << GetEntryPointName(entryPoint) << "_" << paramName << "_" << counter;
10290*8975f5c5SAndroid Build Coastguard Worker return strstr.str();
10291*8975f5c5SAndroid Build Coastguard Worker }
10292*8975f5c5SAndroid Build Coastguard Worker
saveFrame()10293*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::saveFrame()
10294*8975f5c5SAndroid Build Coastguard Worker {
10295*8975f5c5SAndroid Build Coastguard Worker if (mReplayHeaders.empty() && mPublicFunctions.empty() && mPrivateFunctions.empty())
10296*8975f5c5SAndroid Build Coastguard Worker {
10297*8975f5c5SAndroid Build Coastguard Worker return;
10298*8975f5c5SAndroid Build Coastguard Worker }
10299*8975f5c5SAndroid Build Coastguard Worker
10300*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mSourceFileExtension.empty());
10301*8975f5c5SAndroid Build Coastguard Worker
10302*8975f5c5SAndroid Build Coastguard Worker std::stringstream strstr;
10303*8975f5c5SAndroid Build Coastguard Worker strstr << mFilenamePattern << "_" << std::setfill('0') << std::setw(3) << mFrameIndex++ << "."
10304*8975f5c5SAndroid Build Coastguard Worker << mSourceFileExtension;
10305*8975f5c5SAndroid Build Coastguard Worker
10306*8975f5c5SAndroid Build Coastguard Worker std::string frameFilePath = strstr.str();
10307*8975f5c5SAndroid Build Coastguard Worker
10308*8975f5c5SAndroid Build Coastguard Worker writeReplaySource(frameFilePath);
10309*8975f5c5SAndroid Build Coastguard Worker }
10310*8975f5c5SAndroid Build Coastguard Worker
saveFrameIfFull()10311*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::saveFrameIfFull()
10312*8975f5c5SAndroid Build Coastguard Worker {
10313*8975f5c5SAndroid Build Coastguard Worker if (getStoredReplaySourceSize() < mSourceFileSizeThreshold)
10314*8975f5c5SAndroid Build Coastguard Worker {
10315*8975f5c5SAndroid Build Coastguard Worker INFO() << "Merging captured frame: " << getStoredReplaySourceSize()
10316*8975f5c5SAndroid Build Coastguard Worker << " less than threshold of " << mSourceFileSizeThreshold << " bytes";
10317*8975f5c5SAndroid Build Coastguard Worker return;
10318*8975f5c5SAndroid Build Coastguard Worker }
10319*8975f5c5SAndroid Build Coastguard Worker
10320*8975f5c5SAndroid Build Coastguard Worker saveFrame();
10321*8975f5c5SAndroid Build Coastguard Worker }
10322*8975f5c5SAndroid Build Coastguard Worker
saveHeader()10323*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::saveHeader()
10324*8975f5c5SAndroid Build Coastguard Worker {
10325*8975f5c5SAndroid Build Coastguard Worker std::stringstream headerPathStream;
10326*8975f5c5SAndroid Build Coastguard Worker headerPathStream << mFilenamePattern << ".h";
10327*8975f5c5SAndroid Build Coastguard Worker std::string headerPath = headerPathStream.str();
10328*8975f5c5SAndroid Build Coastguard Worker
10329*8975f5c5SAndroid Build Coastguard Worker SaveFileHelper saveH(headerPath);
10330*8975f5c5SAndroid Build Coastguard Worker
10331*8975f5c5SAndroid Build Coastguard Worker saveH << mHeaderPrologue << "\n";
10332*8975f5c5SAndroid Build Coastguard Worker
10333*8975f5c5SAndroid Build Coastguard Worker saveH << "// Public functions are declared in trace_fixture.h.\n";
10334*8975f5c5SAndroid Build Coastguard Worker saveH << "\n";
10335*8975f5c5SAndroid Build Coastguard Worker saveH << "// Private Functions\n";
10336*8975f5c5SAndroid Build Coastguard Worker saveH << "\n";
10337*8975f5c5SAndroid Build Coastguard Worker
10338*8975f5c5SAndroid Build Coastguard Worker for (const std::string &proto : mPrivateFunctionPrototypes)
10339*8975f5c5SAndroid Build Coastguard Worker {
10340*8975f5c5SAndroid Build Coastguard Worker saveH << proto << ";\n";
10341*8975f5c5SAndroid Build Coastguard Worker }
10342*8975f5c5SAndroid Build Coastguard Worker
10343*8975f5c5SAndroid Build Coastguard Worker saveH << "\n";
10344*8975f5c5SAndroid Build Coastguard Worker saveH << "// Global variables\n";
10345*8975f5c5SAndroid Build Coastguard Worker saveH << "\n";
10346*8975f5c5SAndroid Build Coastguard Worker
10347*8975f5c5SAndroid Build Coastguard Worker for (const std::string &globalVar : mGlobalVariableDeclarations)
10348*8975f5c5SAndroid Build Coastguard Worker {
10349*8975f5c5SAndroid Build Coastguard Worker saveH << "extern " << globalVar << ";\n";
10350*8975f5c5SAndroid Build Coastguard Worker }
10351*8975f5c5SAndroid Build Coastguard Worker
10352*8975f5c5SAndroid Build Coastguard Worker mPublicFunctionPrototypes.clear();
10353*8975f5c5SAndroid Build Coastguard Worker mPrivateFunctionPrototypes.clear();
10354*8975f5c5SAndroid Build Coastguard Worker mGlobalVariableDeclarations.clear();
10355*8975f5c5SAndroid Build Coastguard Worker
10356*8975f5c5SAndroid Build Coastguard Worker addWrittenFile(headerPath);
10357*8975f5c5SAndroid Build Coastguard Worker }
10358*8975f5c5SAndroid Build Coastguard Worker
saveIndexFilesAndHeader()10359*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::saveIndexFilesAndHeader()
10360*8975f5c5SAndroid Build Coastguard Worker {
10361*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mSourceFileExtension.empty());
10362*8975f5c5SAndroid Build Coastguard Worker
10363*8975f5c5SAndroid Build Coastguard Worker std::stringstream sourcePathStream;
10364*8975f5c5SAndroid Build Coastguard Worker sourcePathStream << mFilenamePattern << "." << mSourceFileExtension;
10365*8975f5c5SAndroid Build Coastguard Worker std::string sourcePath = sourcePathStream.str();
10366*8975f5c5SAndroid Build Coastguard Worker
10367*8975f5c5SAndroid Build Coastguard Worker writeReplaySource(sourcePath);
10368*8975f5c5SAndroid Build Coastguard Worker saveHeader();
10369*8975f5c5SAndroid Build Coastguard Worker }
10370*8975f5c5SAndroid Build Coastguard Worker
saveSetupFile()10371*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::saveSetupFile()
10372*8975f5c5SAndroid Build Coastguard Worker {
10373*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mSourceFileExtension.empty());
10374*8975f5c5SAndroid Build Coastguard Worker
10375*8975f5c5SAndroid Build Coastguard Worker std::stringstream strstr;
10376*8975f5c5SAndroid Build Coastguard Worker strstr << mFilenamePattern << "." << mSourceFileExtension;
10377*8975f5c5SAndroid Build Coastguard Worker
10378*8975f5c5SAndroid Build Coastguard Worker std::string frameFilePath = strstr.str();
10379*8975f5c5SAndroid Build Coastguard Worker
10380*8975f5c5SAndroid Build Coastguard Worker writeReplaySource(frameFilePath);
10381*8975f5c5SAndroid Build Coastguard Worker }
10382*8975f5c5SAndroid Build Coastguard Worker
writeReplaySource(const std::string & filename)10383*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::writeReplaySource(const std::string &filename)
10384*8975f5c5SAndroid Build Coastguard Worker {
10385*8975f5c5SAndroid Build Coastguard Worker SaveFileHelper saveCpp(filename);
10386*8975f5c5SAndroid Build Coastguard Worker
10387*8975f5c5SAndroid Build Coastguard Worker saveCpp << mSourcePrologue << "\n";
10388*8975f5c5SAndroid Build Coastguard Worker for (const std::string &header : mReplayHeaders)
10389*8975f5c5SAndroid Build Coastguard Worker {
10390*8975f5c5SAndroid Build Coastguard Worker saveCpp << header << "\n";
10391*8975f5c5SAndroid Build Coastguard Worker }
10392*8975f5c5SAndroid Build Coastguard Worker
10393*8975f5c5SAndroid Build Coastguard Worker saveCpp << "// Private Functions\n";
10394*8975f5c5SAndroid Build Coastguard Worker saveCpp << "\n";
10395*8975f5c5SAndroid Build Coastguard Worker
10396*8975f5c5SAndroid Build Coastguard Worker for (const std::string &func : mPrivateFunctions)
10397*8975f5c5SAndroid Build Coastguard Worker {
10398*8975f5c5SAndroid Build Coastguard Worker saveCpp << func << "\n";
10399*8975f5c5SAndroid Build Coastguard Worker }
10400*8975f5c5SAndroid Build Coastguard Worker
10401*8975f5c5SAndroid Build Coastguard Worker saveCpp << "// Public Functions\n";
10402*8975f5c5SAndroid Build Coastguard Worker saveCpp << "\n";
10403*8975f5c5SAndroid Build Coastguard Worker
10404*8975f5c5SAndroid Build Coastguard Worker if (mFilenamePattern == "cpp")
10405*8975f5c5SAndroid Build Coastguard Worker {
10406*8975f5c5SAndroid Build Coastguard Worker saveCpp << "extern \"C\"\n";
10407*8975f5c5SAndroid Build Coastguard Worker saveCpp << "{\n";
10408*8975f5c5SAndroid Build Coastguard Worker }
10409*8975f5c5SAndroid Build Coastguard Worker
10410*8975f5c5SAndroid Build Coastguard Worker for (const std::string &func : mPublicFunctions)
10411*8975f5c5SAndroid Build Coastguard Worker {
10412*8975f5c5SAndroid Build Coastguard Worker saveCpp << func << "\n";
10413*8975f5c5SAndroid Build Coastguard Worker }
10414*8975f5c5SAndroid Build Coastguard Worker
10415*8975f5c5SAndroid Build Coastguard Worker if (mFilenamePattern == "cpp")
10416*8975f5c5SAndroid Build Coastguard Worker {
10417*8975f5c5SAndroid Build Coastguard Worker saveCpp << "} // extern \"C\"\n";
10418*8975f5c5SAndroid Build Coastguard Worker }
10419*8975f5c5SAndroid Build Coastguard Worker
10420*8975f5c5SAndroid Build Coastguard Worker mReplayHeaders.clear();
10421*8975f5c5SAndroid Build Coastguard Worker mPrivateFunctions.clear();
10422*8975f5c5SAndroid Build Coastguard Worker mPublicFunctions.clear();
10423*8975f5c5SAndroid Build Coastguard Worker
10424*8975f5c5SAndroid Build Coastguard Worker addWrittenFile(filename);
10425*8975f5c5SAndroid Build Coastguard Worker }
10426*8975f5c5SAndroid Build Coastguard Worker
addWrittenFile(const std::string & filename)10427*8975f5c5SAndroid Build Coastguard Worker void ReplayWriter::addWrittenFile(const std::string &filename)
10428*8975f5c5SAndroid Build Coastguard Worker {
10429*8975f5c5SAndroid Build Coastguard Worker std::string writtenFile = GetBaseName(filename);
10430*8975f5c5SAndroid Build Coastguard Worker ASSERT(std::find(mWrittenFiles.begin(), mWrittenFiles.end(), writtenFile) ==
10431*8975f5c5SAndroid Build Coastguard Worker mWrittenFiles.end());
10432*8975f5c5SAndroid Build Coastguard Worker mWrittenFiles.push_back(writtenFile);
10433*8975f5c5SAndroid Build Coastguard Worker }
10434*8975f5c5SAndroid Build Coastguard Worker
getAndResetWrittenFiles()10435*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> ReplayWriter::getAndResetWrittenFiles()
10436*8975f5c5SAndroid Build Coastguard Worker {
10437*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> results = std::move(mWrittenFiles);
10438*8975f5c5SAndroid Build Coastguard Worker std::sort(results.begin(), results.end());
10439*8975f5c5SAndroid Build Coastguard Worker ASSERT(mWrittenFiles.empty());
10440*8975f5c5SAndroid Build Coastguard Worker return results;
10441*8975f5c5SAndroid Build Coastguard Worker }
10442*8975f5c5SAndroid Build Coastguard Worker } // namespace angle
10443*8975f5c5SAndroid Build Coastguard Worker
10444*8975f5c5SAndroid Build Coastguard Worker namespace egl
10445*8975f5c5SAndroid Build Coastguard Worker {
CaptureAttributeMap(const egl::AttributeMap & attribMap)10446*8975f5c5SAndroid Build Coastguard Worker angle::ParamCapture CaptureAttributeMap(const egl::AttributeMap &attribMap)
10447*8975f5c5SAndroid Build Coastguard Worker {
10448*8975f5c5SAndroid Build Coastguard Worker switch (attribMap.getType())
10449*8975f5c5SAndroid Build Coastguard Worker {
10450*8975f5c5SAndroid Build Coastguard Worker case AttributeMapType::Attrib:
10451*8975f5c5SAndroid Build Coastguard Worker {
10452*8975f5c5SAndroid Build Coastguard Worker angle::ParamCapture paramCapture("attrib_list", angle::ParamType::TEGLAttribPointer);
10453*8975f5c5SAndroid Build Coastguard Worker if (attribMap.isEmpty())
10454*8975f5c5SAndroid Build Coastguard Worker {
10455*8975f5c5SAndroid Build Coastguard Worker paramCapture.value.EGLAttribPointerVal = nullptr;
10456*8975f5c5SAndroid Build Coastguard Worker }
10457*8975f5c5SAndroid Build Coastguard Worker else
10458*8975f5c5SAndroid Build Coastguard Worker {
10459*8975f5c5SAndroid Build Coastguard Worker std::vector<EGLAttrib> attribs;
10460*8975f5c5SAndroid Build Coastguard Worker for (const auto &[key, value] : attribMap)
10461*8975f5c5SAndroid Build Coastguard Worker {
10462*8975f5c5SAndroid Build Coastguard Worker attribs.push_back(key);
10463*8975f5c5SAndroid Build Coastguard Worker attribs.push_back(value);
10464*8975f5c5SAndroid Build Coastguard Worker }
10465*8975f5c5SAndroid Build Coastguard Worker attribs.push_back(EGL_NONE);
10466*8975f5c5SAndroid Build Coastguard Worker
10467*8975f5c5SAndroid Build Coastguard Worker angle::CaptureMemory(attribs.data(), attribs.size() * sizeof(EGLAttrib),
10468*8975f5c5SAndroid Build Coastguard Worker ¶mCapture);
10469*8975f5c5SAndroid Build Coastguard Worker }
10470*8975f5c5SAndroid Build Coastguard Worker return paramCapture;
10471*8975f5c5SAndroid Build Coastguard Worker }
10472*8975f5c5SAndroid Build Coastguard Worker
10473*8975f5c5SAndroid Build Coastguard Worker case AttributeMapType::Int:
10474*8975f5c5SAndroid Build Coastguard Worker {
10475*8975f5c5SAndroid Build Coastguard Worker angle::ParamCapture paramCapture("attrib_list", angle::ParamType::TEGLintPointer);
10476*8975f5c5SAndroid Build Coastguard Worker if (attribMap.isEmpty())
10477*8975f5c5SAndroid Build Coastguard Worker {
10478*8975f5c5SAndroid Build Coastguard Worker paramCapture.value.EGLintPointerVal = nullptr;
10479*8975f5c5SAndroid Build Coastguard Worker }
10480*8975f5c5SAndroid Build Coastguard Worker else
10481*8975f5c5SAndroid Build Coastguard Worker {
10482*8975f5c5SAndroid Build Coastguard Worker std::vector<EGLint> attribs;
10483*8975f5c5SAndroid Build Coastguard Worker for (const auto &[key, value] : attribMap)
10484*8975f5c5SAndroid Build Coastguard Worker {
10485*8975f5c5SAndroid Build Coastguard Worker attribs.push_back(static_cast<EGLint>(key));
10486*8975f5c5SAndroid Build Coastguard Worker attribs.push_back(static_cast<EGLint>(value));
10487*8975f5c5SAndroid Build Coastguard Worker }
10488*8975f5c5SAndroid Build Coastguard Worker attribs.push_back(EGL_NONE);
10489*8975f5c5SAndroid Build Coastguard Worker
10490*8975f5c5SAndroid Build Coastguard Worker angle::CaptureMemory(attribs.data(), attribs.size() * sizeof(EGLint),
10491*8975f5c5SAndroid Build Coastguard Worker ¶mCapture);
10492*8975f5c5SAndroid Build Coastguard Worker }
10493*8975f5c5SAndroid Build Coastguard Worker return paramCapture;
10494*8975f5c5SAndroid Build Coastguard Worker }
10495*8975f5c5SAndroid Build Coastguard Worker
10496*8975f5c5SAndroid Build Coastguard Worker default:
10497*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
10498*8975f5c5SAndroid Build Coastguard Worker return angle::ParamCapture();
10499*8975f5c5SAndroid Build Coastguard Worker }
10500*8975f5c5SAndroid Build Coastguard Worker }
10501*8975f5c5SAndroid Build Coastguard Worker } // namespace egl
10502