xref: /aosp_15_r20/external/angle/src/libANGLE/capture/serialize.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // serialize.cpp:
7 //   ANGLE GL state serialization.
8 //
9 
10 #include "libANGLE/capture/serialize.h"
11 
12 #include "common/Color.h"
13 #include "common/MemoryBuffer.h"
14 #include "common/angleutils.h"
15 #include "common/gl_enum_utils.h"
16 #include "common/serializer/JsonSerializer.h"
17 #include "libANGLE/Buffer.h"
18 #include "libANGLE/Caps.h"
19 #include "libANGLE/Context.h"
20 #include "libANGLE/Framebuffer.h"
21 #include "libANGLE/Query.h"
22 #include "libANGLE/RefCountObject.h"
23 #include "libANGLE/ResourceMap.h"
24 #include "libANGLE/Sampler.h"
25 #include "libANGLE/State.h"
26 #include "libANGLE/TransformFeedback.h"
27 #include "libANGLE/VertexAttribute.h"
28 #include "libANGLE/angletypes.h"
29 #include "libANGLE/renderer/FramebufferImpl.h"
30 #include "libANGLE/renderer/RenderbufferImpl.h"
31 
32 #include <vector>
33 
34 #if !ANGLE_CAPTURE_ENABLED
35 #    error Frame capture must be enabled to build this file.
36 #endif  // !ANGLE_CAPTURE_ENABLED
37 
38 // Note: when diagnosing serialization comparison failures, you can disable the unused function
39 // compiler warning to allow bisecting the comparison function. One first check is to disable
40 // Framebuffer Attachment pixel comparison which includes the pixel contents of the default FBO.
41 // ANGLE_DISABLE_UNUSED_FUNCTION_WARNING
42 
43 namespace angle
44 {
45 namespace
46 {
47 template <typename ArgT>
ToString(const ArgT & arg)48 std::string ToString(const ArgT &arg)
49 {
50     std::ostringstream strstr;
51     strstr << arg;
52     return strstr.str();
53 }
54 
55 #define ENUM_TO_STRING(C, M) \
56     case C ::M:              \
57         return #M
58 
InitStateToString(gl::InitState state)59 const char *InitStateToString(gl::InitState state)
60 {
61     switch (state)
62     {
63         ENUM_TO_STRING(gl::InitState, Initialized);
64         ENUM_TO_STRING(gl::InitState, MayNeedInit);
65         default:
66             return "invalid";
67     }
68 }
69 
SrgbOverrideToString(gl::SrgbOverride value)70 const char *SrgbOverrideToString(gl::SrgbOverride value)
71 {
72     switch (value)
73     {
74         ENUM_TO_STRING(gl::SrgbOverride, Default);
75         ENUM_TO_STRING(gl::SrgbOverride, SRGB);
76         default:
77             return "invalid";
78     }
79 }
80 
ColorGenericTypeToString(gl::ColorGeneric::Type type)81 const char *ColorGenericTypeToString(gl::ColorGeneric::Type type)
82 {
83     switch (type)
84     {
85         ENUM_TO_STRING(gl::ColorGeneric::Type, Float);
86         ENUM_TO_STRING(gl::ColorGeneric::Type, Int);
87         ENUM_TO_STRING(gl::ColorGeneric::Type, UInt);
88         default:
89             return "invalid";
90     }
91 }
92 
CompileStatusToString(gl::CompileStatus status)93 const char *CompileStatusToString(gl::CompileStatus status)
94 {
95     switch (status)
96     {
97         ENUM_TO_STRING(gl::CompileStatus, NOT_COMPILED);
98         ENUM_TO_STRING(gl::CompileStatus, COMPILE_REQUESTED);
99         ENUM_TO_STRING(gl::CompileStatus, COMPILED);
100         default:
101             return "invalid";
102     }
103 }
104 
105 #undef ENUM_TO_STRING
106 
107 class [[nodiscard]] GroupScope
108 {
109   public:
GroupScope(JsonSerializer * json,const std::string & name)110     GroupScope(JsonSerializer *json, const std::string &name) : mJson(json)
111     {
112         mJson->startGroup(name);
113     }
114 
GroupScope(JsonSerializer * json,const std::string & name,int index)115     GroupScope(JsonSerializer *json, const std::string &name, int index) : mJson(json)
116     {
117         constexpr size_t kBufSize = 255;
118         char buf[kBufSize + 1]    = {};
119         snprintf(buf, kBufSize, "%s%s%03d", name.c_str(), name.empty() ? "" : " ", index);
120         mJson->startGroup(buf);
121     }
122 
GroupScope(JsonSerializer * json,int index)123     GroupScope(JsonSerializer *json, int index) : GroupScope(json, "", index) {}
124 
~GroupScope()125     ~GroupScope() { mJson->endGroup(); }
126 
127   private:
128     JsonSerializer *mJson;
129 };
130 
SerializeColorF(JsonSerializer * json,const ColorF & color)131 void SerializeColorF(JsonSerializer *json, const ColorF &color)
132 {
133     json->addScalar("red", color.red);
134     json->addScalar("green", color.green);
135     json->addScalar("blue", color.blue);
136     json->addScalar("alpha", color.alpha);
137 }
138 
SerializeColorFWithGroup(JsonSerializer * json,const char * groupName,const ColorF & color)139 void SerializeColorFWithGroup(JsonSerializer *json, const char *groupName, const ColorF &color)
140 {
141     GroupScope group(json, groupName);
142     SerializeColorF(json, color);
143 }
144 
SerializeColorI(JsonSerializer * json,const ColorI & color)145 void SerializeColorI(JsonSerializer *json, const ColorI &color)
146 {
147     json->addScalar("Red", color.red);
148     json->addScalar("Green", color.green);
149     json->addScalar("Blue", color.blue);
150     json->addScalar("Alpha", color.alpha);
151 }
152 
SerializeColorUI(JsonSerializer * json,const ColorUI & color)153 void SerializeColorUI(JsonSerializer *json, const ColorUI &color)
154 {
155     json->addScalar("Red", color.red);
156     json->addScalar("Green", color.green);
157     json->addScalar("Blue", color.blue);
158     json->addScalar("Alpha", color.alpha);
159 }
160 
SerializeExtents(JsonSerializer * json,const gl::Extents & extents)161 void SerializeExtents(JsonSerializer *json, const gl::Extents &extents)
162 {
163     json->addScalar("Width", extents.width);
164     json->addScalar("Height", extents.height);
165     json->addScalar("Depth", extents.depth);
166 }
167 
168 template <class ObjectType>
SerializeOffsetBindingPointerVector(JsonSerializer * json,const char * groupName,const std::vector<gl::OffsetBindingPointer<ObjectType>> & offsetBindingPointerVector)169 void SerializeOffsetBindingPointerVector(
170     JsonSerializer *json,
171     const char *groupName,
172     const std::vector<gl::OffsetBindingPointer<ObjectType>> &offsetBindingPointerVector)
173 {
174     GroupScope vectorGroup(json, groupName);
175 
176     for (size_t i = 0; i < offsetBindingPointerVector.size(); i++)
177     {
178         GroupScope itemGroup(json, static_cast<int>(i));
179         json->addScalar("Value", offsetBindingPointerVector[i].id().value);
180         json->addScalar("Offset", offsetBindingPointerVector[i].getOffset());
181         json->addScalar("Size", offsetBindingPointerVector[i].getSize());
182     }
183 }
184 
185 template <class ObjectType>
SerializeBindingPointerVector(JsonSerializer * json,const std::vector<gl::BindingPointer<ObjectType>> & bindingPointerVector)186 void SerializeBindingPointerVector(
187     JsonSerializer *json,
188     const std::vector<gl::BindingPointer<ObjectType>> &bindingPointerVector)
189 {
190     for (size_t i = 0; i < bindingPointerVector.size(); i++)
191     {
192         const gl::BindingPointer<ObjectType> &obj = bindingPointerVector[i];
193 
194         // Do not serialize zero bindings, as this will create unwanted diffs
195         if (obj.id().value != 0)
196         {
197             std::ostringstream s;
198             s << std::setfill('0') << std::setw(3) << i;
199             json->addScalar(s.str().c_str(), obj.id().value);
200         }
201     }
202 }
203 
204 template <class T>
SerializeRange(JsonSerializer * json,const gl::Range<T> & range)205 void SerializeRange(JsonSerializer *json, const gl::Range<T> &range)
206 {
207     GroupScope group(json, "Range");
208     json->addScalar("Low", range.low());
209     json->addScalar("High", range.high());
210 }
211 
IsValidColorAttachmentBinding(GLenum binding,size_t colorAttachmentsCount)212 bool IsValidColorAttachmentBinding(GLenum binding, size_t colorAttachmentsCount)
213 {
214     return binding == GL_BACK || (binding >= GL_COLOR_ATTACHMENT0 &&
215                                   (binding - GL_COLOR_ATTACHMENT0) < colorAttachmentsCount);
216 }
217 
SerializeFormat(JsonSerializer * json,GLenum glFormat)218 void SerializeFormat(JsonSerializer *json, GLenum glFormat)
219 {
220     json->addCString("InternalFormat", gl::GLenumToString(gl::GLESEnum::InternalFormat, glFormat));
221 }
222 
SerializeInternalFormat(JsonSerializer * json,const gl::InternalFormat * internalFormat)223 void SerializeInternalFormat(JsonSerializer *json, const gl::InternalFormat *internalFormat)
224 {
225     SerializeFormat(json, internalFormat->internalFormat);
226 }
227 
SerializeANGLEFormat(JsonSerializer * json,const angle::Format * format)228 void SerializeANGLEFormat(JsonSerializer *json, const angle::Format *format)
229 {
230     SerializeFormat(json, format->glInternalFormat);
231 }
232 
SerializeGLFormat(JsonSerializer * json,const gl::Format & format)233 void SerializeGLFormat(JsonSerializer *json, const gl::Format &format)
234 {
235     SerializeInternalFormat(json, format.info);
236 }
237 
ReadPixelsFromAttachment(const gl::Context * context,gl::Framebuffer * framebuffer,const gl::FramebufferAttachment & framebufferAttachment,ScratchBuffer * scratchBuffer,MemoryBuffer ** pixels)238 Result ReadPixelsFromAttachment(const gl::Context *context,
239                                 gl::Framebuffer *framebuffer,
240                                 const gl::FramebufferAttachment &framebufferAttachment,
241                                 ScratchBuffer *scratchBuffer,
242                                 MemoryBuffer **pixels)
243 {
244     gl::Extents extents       = framebufferAttachment.getSize();
245     GLenum binding            = framebufferAttachment.getBinding();
246     gl::InternalFormat format = *framebufferAttachment.getFormat().info;
247     if (IsValidColorAttachmentBinding(binding,
248                                       framebuffer->getState().getColorAttachments().size()))
249     {
250         format = framebuffer->getImplementation()->getImplementationColorReadFormat(context);
251     }
252     ANGLE_CHECK_GL_ALLOC(const_cast<gl::Context *>(context),
253                          scratchBuffer->getInitialized(
254                              format.pixelBytes * extents.width * extents.height, pixels, 0));
255     ANGLE_TRY(framebuffer->readPixels(context, gl::Rectangle{0, 0, extents.width, extents.height},
256                                       format.format, format.type, gl::PixelPackState{}, nullptr,
257                                       (*pixels)->data()));
258     return Result::Continue;
259 }
SerializeImageIndex(JsonSerializer * json,const gl::ImageIndex & imageIndex)260 void SerializeImageIndex(JsonSerializer *json, const gl::ImageIndex &imageIndex)
261 {
262     GroupScope group(json, "Image");
263     json->addString("ImageType", ToString(imageIndex.getType()));
264     json->addScalar("LevelIndex", imageIndex.getLevelIndex());
265     json->addScalar("LayerIndex", imageIndex.getLayerIndex());
266     json->addScalar("LayerCount", imageIndex.getLayerCount());
267 }
268 
SerializeFramebufferAttachment(const gl::Context * context,JsonSerializer * json,ScratchBuffer * scratchBuffer,gl::Framebuffer * framebuffer,const gl::FramebufferAttachment & framebufferAttachment,gl::GLESEnum enumGroup)269 Result SerializeFramebufferAttachment(const gl::Context *context,
270                                       JsonSerializer *json,
271                                       ScratchBuffer *scratchBuffer,
272                                       gl::Framebuffer *framebuffer,
273                                       const gl::FramebufferAttachment &framebufferAttachment,
274                                       gl::GLESEnum enumGroup)
275 {
276     if (framebufferAttachment.type() == GL_TEXTURE ||
277         framebufferAttachment.type() == GL_RENDERBUFFER)
278     {
279         json->addScalar("AttachedResourceID", framebufferAttachment.id());
280     }
281     json->addCString(
282         "Type", gl::GLenumToString(gl::GLESEnum::ObjectIdentifier, framebufferAttachment.type()));
283     // serialize target variable
284     json->addString("Binding", gl::GLenumToString(enumGroup, framebufferAttachment.getBinding()));
285     if (framebufferAttachment.type() == GL_TEXTURE)
286     {
287         SerializeImageIndex(json, framebufferAttachment.getTextureImageIndex());
288     }
289     json->addScalar("NumViews", framebufferAttachment.getNumViews());
290     json->addScalar("Multiview", framebufferAttachment.isMultiview());
291     json->addScalar("ViewIndex", framebufferAttachment.getBaseViewIndex());
292     json->addScalar("Samples", framebufferAttachment.getRenderToTextureSamples());
293 
294     {
295         GroupScope extentsGroup(json, "Extents");
296         SerializeExtents(json, framebufferAttachment.getSize());
297     }
298 
299     if (framebufferAttachment.type() != GL_TEXTURE &&
300         framebufferAttachment.type() != GL_RENDERBUFFER)
301     {
302         GLenum prevReadBufferState = framebuffer->getReadBufferState();
303         GLenum binding             = framebufferAttachment.getBinding();
304         if (IsValidColorAttachmentBinding(binding,
305                                           framebuffer->getState().getColorAttachments().size()))
306         {
307             framebuffer->setReadBuffer(framebufferAttachment.getBinding());
308             ANGLE_TRY(framebuffer->syncState(context, GL_FRAMEBUFFER, gl::Command::Other));
309         }
310 
311         if (framebufferAttachment.initState() == gl::InitState::Initialized)
312         {
313             MemoryBuffer *pixelsPtr = nullptr;
314             ANGLE_TRY(ReadPixelsFromAttachment(context, framebuffer, framebufferAttachment,
315                                                scratchBuffer, &pixelsPtr));
316             json->addBlob("Data", pixelsPtr->data(), pixelsPtr->size());
317         }
318         else
319         {
320             json->addCString("Data", "Not initialized");
321         }
322         // Reset framebuffer state
323         framebuffer->setReadBuffer(prevReadBufferState);
324     }
325     return Result::Continue;
326 }
327 
SerializeFramebufferState(const gl::Context * context,JsonSerializer * json,ScratchBuffer * scratchBuffer,gl::Framebuffer * framebuffer,const gl::FramebufferState & framebufferState)328 Result SerializeFramebufferState(const gl::Context *context,
329                                  JsonSerializer *json,
330                                  ScratchBuffer *scratchBuffer,
331                                  gl::Framebuffer *framebuffer,
332                                  const gl::FramebufferState &framebufferState)
333 {
334     GroupScope group(json, "Framebuffer", framebufferState.id().value);
335 
336     json->addString("Label", framebufferState.getLabel());
337     json->addVector("DrawStates", framebufferState.getDrawBufferStates());
338     json->addScalar("ReadBufferState", framebufferState.getReadBufferState());
339     json->addScalar("DefaultWidth", framebufferState.getDefaultWidth());
340     json->addScalar("DefaultHeight", framebufferState.getDefaultHeight());
341     json->addScalar("DefaultSamples", framebufferState.getDefaultSamples());
342     json->addScalar("DefaultFixedSampleLocation",
343                     framebufferState.getDefaultFixedSampleLocations());
344     json->addScalar("DefaultLayers", framebufferState.getDefaultLayers());
345     json->addScalar("FlipY", framebufferState.getFlipY());
346 
347     {
348         GroupScope attachmentsGroup(json, "Attachments");
349         const gl::DrawBuffersVector<gl::FramebufferAttachment> &colorAttachments =
350             framebufferState.getColorAttachments();
351         for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size();
352              ++attachmentIndex)
353         {
354             const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
355             if (colorAttachment.isAttached())
356             {
357                 GroupScope colorAttachmentgroup(json, "ColorAttachment",
358                                                 static_cast<int>(attachmentIndex));
359                 ANGLE_TRY(SerializeFramebufferAttachment(context, json, scratchBuffer, framebuffer,
360                                                          colorAttachment,
361                                                          gl::GLESEnum::ColorBuffer));
362             }
363         }
364         if (framebuffer->getDepthStencilAttachment())
365         {
366             GroupScope dsAttachmentgroup(json, "DepthStencilAttachment");
367             ANGLE_TRY(SerializeFramebufferAttachment(context, json, scratchBuffer, framebuffer,
368                                                      *framebuffer->getDepthStencilAttachment(),
369                                                      gl::GLESEnum::AllEnums));
370         }
371         else
372         {
373             if (framebuffer->getDepthAttachment())
374             {
375                 GroupScope depthAttachmentgroup(json, "DepthAttachment");
376                 ANGLE_TRY(SerializeFramebufferAttachment(context, json, scratchBuffer, framebuffer,
377                                                          *framebuffer->getDepthAttachment(),
378                                                          gl::GLESEnum::FramebufferAttachment));
379             }
380             if (framebuffer->getStencilAttachment())
381             {
382                 GroupScope stencilAttachmengroup(json, "StencilAttachment");
383                 ANGLE_TRY(SerializeFramebufferAttachment(context, json, scratchBuffer, framebuffer,
384                                                          *framebuffer->getStencilAttachment(),
385                                                          gl::GLESEnum::AllEnums));
386             }
387         }
388     }
389     return Result::Continue;
390 }
391 
SerializeFramebuffer(const gl::Context * context,JsonSerializer * json,ScratchBuffer * scratchBuffer,gl::Framebuffer * framebuffer)392 Result SerializeFramebuffer(const gl::Context *context,
393                             JsonSerializer *json,
394                             ScratchBuffer *scratchBuffer,
395                             gl::Framebuffer *framebuffer)
396 {
397     return SerializeFramebufferState(context, json, scratchBuffer, framebuffer,
398                                      framebuffer->getState());
399 }
400 
SerializeRasterizerState(JsonSerializer * json,const gl::RasterizerState & rasterizerState)401 void SerializeRasterizerState(JsonSerializer *json, const gl::RasterizerState &rasterizerState)
402 {
403     GroupScope group(json, "Rasterizer");
404     json->addScalar("CullFace", rasterizerState.cullFace);
405     json->addString("CullMode", ToString(rasterizerState.cullMode));
406     json->addScalar("FrontFace", rasterizerState.frontFace);
407     json->addString("PolygonMode", ToString(rasterizerState.polygonMode));
408     json->addScalar("PolygonOffsetPoint", rasterizerState.polygonOffsetPoint);
409     json->addScalar("PolygonOffsetLine", rasterizerState.polygonOffsetLine);
410     json->addScalar("PolygonOffsetFill", rasterizerState.polygonOffsetFill);
411     json->addScalar("PolygonOffsetFactor", rasterizerState.polygonOffsetFactor);
412     json->addScalar("PolygonOffsetUnits", rasterizerState.polygonOffsetUnits);
413     json->addScalar("PolygonOffsetClamp", rasterizerState.polygonOffsetClamp);
414     json->addScalar("DepthClamp", rasterizerState.depthClamp);
415     json->addScalar("PointDrawMode", rasterizerState.pointDrawMode);
416     json->addScalar("MultiSample", rasterizerState.multiSample);
417     json->addScalar("RasterizerDiscard", rasterizerState.rasterizerDiscard);
418     json->addScalar("Dither", rasterizerState.dither);
419 }
420 
SerializeRectangle(JsonSerializer * json,const std::string & name,const gl::Rectangle & rectangle)421 void SerializeRectangle(JsonSerializer *json,
422                         const std::string &name,
423                         const gl::Rectangle &rectangle)
424 {
425     GroupScope group(json, name);
426     json->addScalar("x", rectangle.x);
427     json->addScalar("y", rectangle.y);
428     json->addScalar("w", rectangle.width);
429     json->addScalar("h", rectangle.height);
430 }
431 
SerializeBlendStateExt(JsonSerializer * json,const gl::BlendStateExt & blendStateExt)432 void SerializeBlendStateExt(JsonSerializer *json, const gl::BlendStateExt &blendStateExt)
433 {
434     GroupScope group(json, "BlendStateExt");
435     json->addScalar("DrawBufferCount", blendStateExt.getDrawBufferCount());
436     json->addScalar("EnableMask", blendStateExt.getEnabledMask().bits());
437     json->addScalar("DstColor", blendStateExt.getDstColorBits());
438     json->addScalar("DstAlpha", blendStateExt.getDstAlphaBits());
439     json->addScalar("SrcColor", blendStateExt.getSrcColorBits());
440     json->addScalar("SrcAlpha", blendStateExt.getSrcAlphaBits());
441     json->addScalar("EquationColor", blendStateExt.getEquationColorBits());
442     json->addScalar("EquationAlpha", blendStateExt.getEquationAlphaBits());
443     json->addScalar("ColorMask", blendStateExt.getColorMaskBits());
444 }
445 
SerializeDepthStencilState(JsonSerializer * json,const gl::DepthStencilState & depthStencilState)446 void SerializeDepthStencilState(JsonSerializer *json,
447                                 const gl::DepthStencilState &depthStencilState)
448 {
449     GroupScope group(json, "DepthStencilState");
450     json->addScalar("DepthTest", depthStencilState.depthTest);
451     json->addScalar("DepthFunc", depthStencilState.depthFunc);
452     json->addScalar("DepthMask", depthStencilState.depthMask);
453     json->addScalar("StencilTest", depthStencilState.stencilTest);
454     json->addScalar("StencilFunc", depthStencilState.stencilFunc);
455     json->addScalar("StencilMask", depthStencilState.stencilMask);
456     json->addScalar("StencilFail", depthStencilState.stencilFail);
457     json->addScalar("StencilPassDepthFail", depthStencilState.stencilPassDepthFail);
458     json->addScalar("StencilPassDepthPass", depthStencilState.stencilPassDepthPass);
459     json->addScalar("StencilWritemask", depthStencilState.stencilWritemask);
460     json->addScalar("StencilBackFunc", depthStencilState.stencilBackFunc);
461     json->addScalar("StencilBackMask", depthStencilState.stencilBackMask);
462     json->addScalar("StencilBackFail", depthStencilState.stencilBackFail);
463     json->addScalar("StencilBackPassDepthFail", depthStencilState.stencilBackPassDepthFail);
464     json->addScalar("StencilBackPassDepthPass", depthStencilState.stencilBackPassDepthPass);
465     json->addScalar("StencilBackWritemask", depthStencilState.stencilBackWritemask);
466 }
467 
SerializeVertexAttribCurrentValueData(JsonSerializer * json,const gl::VertexAttribCurrentValueData & vertexAttribCurrentValueData)468 void SerializeVertexAttribCurrentValueData(
469     JsonSerializer *json,
470     const gl::VertexAttribCurrentValueData &vertexAttribCurrentValueData)
471 {
472     ASSERT(vertexAttribCurrentValueData.Type == gl::VertexAttribType::Float ||
473            vertexAttribCurrentValueData.Type == gl::VertexAttribType::Int ||
474            vertexAttribCurrentValueData.Type == gl::VertexAttribType::UnsignedInt);
475     if (vertexAttribCurrentValueData.Type == gl::VertexAttribType::Float)
476     {
477         json->addScalar("0", vertexAttribCurrentValueData.Values.FloatValues[0]);
478         json->addScalar("1", vertexAttribCurrentValueData.Values.FloatValues[1]);
479         json->addScalar("2", vertexAttribCurrentValueData.Values.FloatValues[2]);
480         json->addScalar("3", vertexAttribCurrentValueData.Values.FloatValues[3]);
481     }
482     else if (vertexAttribCurrentValueData.Type == gl::VertexAttribType::Int)
483     {
484         json->addScalar("0", vertexAttribCurrentValueData.Values.IntValues[0]);
485         json->addScalar("1", vertexAttribCurrentValueData.Values.IntValues[1]);
486         json->addScalar("2", vertexAttribCurrentValueData.Values.IntValues[2]);
487         json->addScalar("3", vertexAttribCurrentValueData.Values.IntValues[3]);
488     }
489     else
490     {
491         json->addScalar("0", vertexAttribCurrentValueData.Values.UnsignedIntValues[0]);
492         json->addScalar("1", vertexAttribCurrentValueData.Values.UnsignedIntValues[1]);
493         json->addScalar("2", vertexAttribCurrentValueData.Values.UnsignedIntValues[2]);
494         json->addScalar("3", vertexAttribCurrentValueData.Values.UnsignedIntValues[3]);
495     }
496 }
497 
SerializePixelPackState(JsonSerializer * json,const gl::PixelPackState & pixelPackState)498 void SerializePixelPackState(JsonSerializer *json, const gl::PixelPackState &pixelPackState)
499 {
500     GroupScope group(json, "PixelPackState");
501     json->addScalar("Alignment", pixelPackState.alignment);
502     json->addScalar("RowLength", pixelPackState.rowLength);
503     json->addScalar("SkipRows", pixelPackState.skipRows);
504     json->addScalar("SkipPixels", pixelPackState.skipPixels);
505     json->addScalar("ImageHeight", pixelPackState.imageHeight);
506     json->addScalar("SkipImages", pixelPackState.skipImages);
507     json->addScalar("ReverseRowOrder", pixelPackState.reverseRowOrder);
508 }
509 
SerializePixelUnpackState(JsonSerializer * json,const gl::PixelUnpackState & pixelUnpackState)510 void SerializePixelUnpackState(JsonSerializer *json, const gl::PixelUnpackState &pixelUnpackState)
511 {
512     GroupScope group(json, "PixelUnpackState");
513     json->addScalar("Alignment", pixelUnpackState.alignment);
514     json->addScalar("RowLength", pixelUnpackState.rowLength);
515     json->addScalar("SkipRows", pixelUnpackState.skipRows);
516     json->addScalar("SkipPixels", pixelUnpackState.skipPixels);
517     json->addScalar("ImageHeight", pixelUnpackState.imageHeight);
518     json->addScalar("SkipImages", pixelUnpackState.skipImages);
519 }
520 
SerializeImageUnit(JsonSerializer * json,const gl::ImageUnit & imageUnit,int imageUnitIndex)521 void SerializeImageUnit(JsonSerializer *json, const gl::ImageUnit &imageUnit, int imageUnitIndex)
522 {
523     GroupScope group(json, "ImageUnit", imageUnitIndex);
524     json->addScalar("Level", imageUnit.level);
525     json->addScalar("Layered", imageUnit.layered);
526     json->addScalar("Layer", imageUnit.layer);
527     json->addScalar("Access", imageUnit.access);
528     json->addCString("Format", gl::GLinternalFormatToString(imageUnit.format));
529     json->addScalar("TextureID", imageUnit.texture.id().value);
530 }
531 
532 template <typename ResourceType>
SerializeResourceID(JsonSerializer * json,const char * name,const ResourceType * resource)533 void SerializeResourceID(JsonSerializer *json, const char *name, const ResourceType *resource)
534 {
535     json->addScalar(name, resource ? resource->id().value : 0);
536 }
537 
SerializeContextState(JsonSerializer * json,const gl::State & state)538 void SerializeContextState(JsonSerializer *json, const gl::State &state)
539 {
540     GroupScope group(json, "ContextState");
541     json->addScalar("Priority", state.getContextPriority());
542     json->addScalar("Major", state.getClientMajorVersion());
543     json->addScalar("Minor", state.getClientMinorVersion());
544     SerializeColorFWithGroup(json, "ColorClearValue", state.getColorClearValue());
545     json->addScalar("DepthClearValue", state.getDepthClearValue());
546     json->addScalar("StencilClearValue", state.getStencilClearValue());
547     SerializeRasterizerState(json, state.getRasterizerState());
548     json->addScalar("ScissorTestEnabled", state.isScissorTestEnabled());
549     SerializeRectangle(json, "Scissors", state.getScissor());
550     SerializeBlendStateExt(json, state.getBlendStateExt());
551     SerializeColorFWithGroup(json, "BlendColor", state.getBlendColor());
552     json->addScalar("SampleAlphaToCoverageEnabled", state.isSampleAlphaToCoverageEnabled());
553     json->addScalar("SampleCoverageEnabled", state.isSampleCoverageEnabled());
554     json->addScalar("SampleCoverageValue", state.getSampleCoverageValue());
555     json->addScalar("SampleCoverageInvert", state.getSampleCoverageInvert());
556     json->addScalar("SampleMaskEnabled", state.isSampleMaskEnabled());
557     json->addScalar("MaxSampleMaskWords", state.getMaxSampleMaskWords());
558     {
559         const auto &sampleMaskValues = state.getSampleMaskValues();
560         GroupScope maskGroup(json, "SampleMaskValues");
561         for (size_t i = 0; i < sampleMaskValues.size(); i++)
562         {
563             json->addScalar(ToString(i), sampleMaskValues[i]);
564         }
565     }
566     SerializeDepthStencilState(json, state.getDepthStencilState());
567     json->addScalar("StencilRef", state.getStencilRef());
568     json->addScalar("StencilBackRef", state.getStencilBackRef());
569     json->addScalar("LineWidth", state.getLineWidth());
570     json->addScalar("GenerateMipmapHint", state.getGenerateMipmapHint());
571     json->addScalar("FragmentShaderDerivativeHint", state.getFragmentShaderDerivativeHint());
572     json->addScalar("BindGeneratesResourceEnabled", state.isBindGeneratesResourceEnabled());
573     json->addScalar("ClientArraysEnabled", state.areClientArraysEnabled());
574     SerializeRectangle(json, "Viewport", state.getViewport());
575     json->addScalar("Near", state.getNearPlane());
576     json->addScalar("Far", state.getFarPlane());
577     json->addString("ClipOrigin", ToString(state.getClipOrigin()));
578     json->addString("ClipDepthMode", ToString(state.getClipDepthMode()));
579     SerializeResourceID(json, "ReadFramebufferID", state.getReadFramebuffer());
580     SerializeResourceID(json, "DrawFramebufferID", state.getDrawFramebuffer());
581     json->addScalar("RenderbufferID", state.getRenderbufferId().value);
582     SerializeResourceID(json, "CurrentProgramID", state.getProgram());
583     SerializeResourceID(json, "CurrentProgramPipelineID", state.getProgramPipeline());
584     json->addString("ProvokingVertex", ToString(state.getProvokingVertex()));
585     const std::vector<gl::VertexAttribCurrentValueData> &vertexAttribCurrentValues =
586         state.getVertexAttribCurrentValues();
587     for (size_t i = 0; i < vertexAttribCurrentValues.size(); i++)
588     {
589         GroupScope vagroup(json, "VertexAttribCurrentValue", static_cast<int>(i));
590         SerializeVertexAttribCurrentValueData(json, vertexAttribCurrentValues[i]);
591     }
592     ASSERT(state.getVertexArray());
593     json->addScalar("VertexArrayID", state.getVertexArray()->id().value);
594     json->addScalar("CurrentValuesTypeMask", state.getCurrentValuesTypeMask().to_ulong());
595     json->addScalar("ActiveSampler", state.getActiveSampler());
596     {
597         GroupScope boundTexturesGroup(json, "BoundTextures");
598         const gl::TextureBindingMap &boundTexturesMap = state.getBoundTexturesForCapture();
599         for (gl::TextureType textureType : AllEnums<gl::TextureType>())
600         {
601             const gl::TextureBindingVector &textures = boundTexturesMap[textureType];
602             GroupScope texturesGroup(json, ToString(textureType));
603             SerializeBindingPointerVector<gl::Texture>(json, textures);
604         }
605     }
606     json->addScalar("TexturesIncompatibleWithSamplers",
607                     state.getTexturesIncompatibleWithSamplers().to_ulong());
608 
609     {
610         GroupScope texturesCacheGroup(json, "ActiveTexturesCache");
611 
612         const gl::ActiveTexturesCache &texturesCache = state.getActiveTexturesCache();
613         for (GLuint textureIndex = 0; textureIndex < texturesCache.size(); ++textureIndex)
614         {
615             const gl::Texture *tex = texturesCache[textureIndex];
616             std::stringstream strstr;
617             strstr << "Tex " << std::setfill('0') << std::setw(2) << textureIndex;
618             json->addScalar(strstr.str(), tex ? tex->id().value : 0);
619         }
620     }
621 
622     {
623         GroupScope samplersGroupScope(json, "Samplers");
624         SerializeBindingPointerVector<gl::Sampler>(json, state.getSamplers());
625     }
626 
627     {
628         GroupScope imageUnitsGroup(json, "BoundImageUnits");
629 
630         const std::vector<gl::ImageUnit> &imageUnits = state.getImageUnits();
631         for (size_t imageUnitIndex = 0; imageUnitIndex < imageUnits.size(); ++imageUnitIndex)
632         {
633             const gl::ImageUnit &imageUnit = imageUnits[imageUnitIndex];
634             SerializeImageUnit(json, imageUnit, static_cast<int>(imageUnitIndex));
635         }
636     }
637 
638     {
639         const gl::ActiveQueryMap &activeQueries = state.getActiveQueriesForCapture();
640         GroupScope activeQueriesGroup(json, "ActiveQueries");
641         for (gl::QueryType queryType : AllEnums<gl::QueryType>())
642         {
643             const gl::BindingPointer<gl::Query> &query = activeQueries[queryType];
644             std::stringstream strstr;
645             strstr << queryType;
646             json->addScalar(strstr.str(), query.id().value);
647         }
648     }
649 
650     {
651         const gl::BoundBufferMap &boundBuffers = state.getBoundBuffersForCapture();
652         GroupScope boundBuffersGroup(json, "BoundBuffers");
653         for (gl::BufferBinding bufferBinding : AllEnums<gl::BufferBinding>())
654         {
655             const gl::BindingPointer<gl::Buffer> &buffer = boundBuffers[bufferBinding];
656             std::stringstream strstr;
657             strstr << bufferBinding;
658             json->addScalar(strstr.str(), buffer.id().value);
659         }
660     }
661 
662     SerializeOffsetBindingPointerVector<gl::Buffer>(json, "UniformBufferBindings",
663                                                     state.getOffsetBindingPointerUniformBuffers());
664     SerializeOffsetBindingPointerVector<gl::Buffer>(
665         json, "AtomicCounterBufferBindings", state.getOffsetBindingPointerAtomicCounterBuffers());
666     SerializeOffsetBindingPointerVector<gl::Buffer>(
667         json, "ShaderStorageBufferBindings", state.getOffsetBindingPointerShaderStorageBuffers());
668     if (state.getCurrentTransformFeedback())
669     {
670         json->addScalar("CurrentTransformFeedback",
671                         state.getCurrentTransformFeedback()->id().value);
672     }
673     SerializePixelUnpackState(json, state.getUnpackState());
674     SerializePixelPackState(json, state.getPackState());
675     json->addScalar("PrimitiveRestartEnabled", state.isPrimitiveRestartEnabled());
676     json->addScalar("MultisamplingEnabled", state.isMultisamplingEnabled());
677     json->addScalar("SampleAlphaToOneEnabled", state.isSampleAlphaToOneEnabled());
678     json->addScalar("CoverageModulation", state.getCoverageModulation());
679     json->addScalar("FramebufferSRGB", state.getFramebufferSRGB());
680     json->addScalar("RobustResourceInitEnabled", state.isRobustResourceInitEnabled());
681     json->addScalar("ProgramBinaryCacheEnabled", state.isProgramBinaryCacheEnabled());
682     json->addScalar("TextureRectangleEnabled", state.isTextureRectangleEnabled());
683     json->addScalar("MaxShaderCompilerThreads", state.getMaxShaderCompilerThreads());
684     json->addScalar("EnabledClipDistances", state.getEnabledClipDistances().to_ulong());
685     json->addScalar("BlendFuncConstantAlphaDrawBuffers",
686                     state.getBlendFuncConstantAlphaDrawBuffers().to_ulong());
687     json->addScalar("BlendFuncConstantColorDrawBuffers",
688                     state.getBlendFuncConstantColorDrawBuffers().to_ulong());
689     json->addScalar("SimultaneousConstantColorAndAlphaBlendFunc",
690                     state.noSimultaneousConstantColorAndAlphaBlendFunc());
691 }
692 
SerializeBufferState(JsonSerializer * json,const gl::BufferState & bufferState)693 void SerializeBufferState(JsonSerializer *json, const gl::BufferState &bufferState)
694 {
695     json->addString("Label", bufferState.getLabel());
696     json->addString("Usage", ToString(bufferState.getUsage()));
697     json->addScalar("Size", bufferState.getSize());
698     json->addScalar("AccessFlags", bufferState.getAccessFlags());
699     json->addScalar("Access", bufferState.getAccess());
700     json->addScalar("Mapped", bufferState.isMapped());
701     json->addScalar("MapOffset", bufferState.getMapOffset());
702     json->addScalar("MapLength", bufferState.getMapLength());
703 }
704 
SerializeBuffer(const gl::Context * context,JsonSerializer * json,ScratchBuffer * scratchBuffer,gl::Buffer * buffer)705 Result SerializeBuffer(const gl::Context *context,
706                        JsonSerializer *json,
707                        ScratchBuffer *scratchBuffer,
708                        gl::Buffer *buffer)
709 {
710     GroupScope group(json, "Buffer", buffer->id().value);
711     SerializeBufferState(json, buffer->getState());
712     if (buffer->getSize() > 0)
713     {
714         MemoryBuffer *dataPtr = nullptr;
715         ANGLE_CHECK_GL_ALLOC(
716             const_cast<gl::Context *>(context),
717             scratchBuffer->getInitialized(static_cast<size_t>(buffer->getSize()), &dataPtr, 0));
718         ANGLE_TRY(buffer->getSubData(context, 0, dataPtr->size(), dataPtr->data()));
719         json->addBlob("data", dataPtr->data(), dataPtr->size());
720     }
721     else
722     {
723         json->addCString("data", "null");
724     }
725     return Result::Continue;
726 }
727 
SerializeColorGeneric(JsonSerializer * json,const std::string & name,const ColorGeneric & colorGeneric)728 void SerializeColorGeneric(JsonSerializer *json,
729                            const std::string &name,
730                            const ColorGeneric &colorGeneric)
731 {
732     GroupScope group(json, name);
733     ASSERT(colorGeneric.type == ColorGeneric::Type::Float ||
734            colorGeneric.type == ColorGeneric::Type::Int ||
735            colorGeneric.type == ColorGeneric::Type::UInt);
736     json->addCString("Type", ColorGenericTypeToString(colorGeneric.type));
737     if (colorGeneric.type == ColorGeneric::Type::Float)
738     {
739         SerializeColorF(json, colorGeneric.colorF);
740     }
741     else if (colorGeneric.type == ColorGeneric::Type::Int)
742     {
743         SerializeColorI(json, colorGeneric.colorI);
744     }
745     else
746     {
747         SerializeColorUI(json, colorGeneric.colorUI);
748     }
749 }
750 
SerializeSamplerState(JsonSerializer * json,const gl::SamplerState & samplerState)751 void SerializeSamplerState(JsonSerializer *json, const gl::SamplerState &samplerState)
752 {
753     json->addScalar("MinFilter", samplerState.getMinFilter());
754     json->addScalar("MagFilter", samplerState.getMagFilter());
755     json->addScalar("WrapS", samplerState.getWrapS());
756     json->addScalar("WrapT", samplerState.getWrapT());
757     json->addScalar("WrapR", samplerState.getWrapR());
758     json->addScalar("MaxAnisotropy", samplerState.getMaxAnisotropy());
759     json->addScalar("MinLod", samplerState.getMinLod());
760     json->addScalar("MaxLod", samplerState.getMaxLod());
761     json->addScalar("CompareMode", samplerState.getCompareMode());
762     json->addScalar("CompareFunc", samplerState.getCompareFunc());
763     json->addScalar("SRGBDecode", samplerState.getSRGBDecode());
764     SerializeColorGeneric(json, "BorderColor", samplerState.getBorderColor());
765 }
766 
SerializeSampler(JsonSerializer * json,gl::Sampler * sampler)767 void SerializeSampler(JsonSerializer *json, gl::Sampler *sampler)
768 {
769     GroupScope group(json, "Sampler", sampler->id().value);
770     json->addString("Label", sampler->getLabel());
771     SerializeSamplerState(json, sampler->getSamplerState());
772 }
773 
SerializeSwizzleState(JsonSerializer * json,const gl::SwizzleState & swizzleState)774 void SerializeSwizzleState(JsonSerializer *json, const gl::SwizzleState &swizzleState)
775 {
776     json->addScalar("SwizzleRed", swizzleState.swizzleRed);
777     json->addScalar("SwizzleGreen", swizzleState.swizzleGreen);
778     json->addScalar("SwizzleBlue", swizzleState.swizzleBlue);
779     json->addScalar("SwizzleAlpha", swizzleState.swizzleAlpha);
780 }
781 
SerializeRenderbufferState(JsonSerializer * json,const gl::RenderbufferState & renderbufferState)782 void SerializeRenderbufferState(JsonSerializer *json,
783                                 const gl::RenderbufferState &renderbufferState)
784 {
785     GroupScope wg(json, "State");
786     json->addScalar("Width", renderbufferState.getWidth());
787     json->addScalar("Height", renderbufferState.getHeight());
788     SerializeGLFormat(json, renderbufferState.getFormat());
789     json->addScalar("Samples", renderbufferState.getSamples());
790     json->addCString("InitState", InitStateToString(renderbufferState.getInitState()));
791 }
792 
SerializeRenderbuffer(const gl::Context * context,JsonSerializer * json,ScratchBuffer * scratchBuffer,gl::Renderbuffer * renderbuffer)793 Result SerializeRenderbuffer(const gl::Context *context,
794                              JsonSerializer *json,
795                              ScratchBuffer *scratchBuffer,
796                              gl::Renderbuffer *renderbuffer)
797 {
798     GroupScope wg(json, "Renderbuffer", renderbuffer->id().value);
799     SerializeRenderbufferState(json, renderbuffer->getState());
800     json->addString("Label", renderbuffer->getLabel());
801 
802     if (renderbuffer->initState(GL_NONE, gl::ImageIndex()) == gl::InitState::Initialized)
803     {
804         if (renderbuffer->getSamples() > 1 && renderbuffer->getFormat().info->depthBits > 0)
805         {
806             // Vulkan can't do resolve blits for multisampled depth attachemnts and
807             // we don't implement an emulation, therefore we can't read back any useful
808             // data here.
809             json->addCString("Pixels", "multisampled depth buffer");
810         }
811         else if (renderbuffer->getWidth() * renderbuffer->getHeight() <= 0)
812         {
813             json->addCString("Pixels", "no pixels");
814         }
815         else
816         {
817             const gl::InternalFormat &format = *renderbuffer->getFormat().info;
818 
819             const gl::Extents size(renderbuffer->getWidth(), renderbuffer->getHeight(), 1);
820             gl::PixelPackState packState;
821             packState.alignment = 1;
822 
823             GLenum readFormat = renderbuffer->getImplementationColorReadFormat(context);
824             GLenum readType   = renderbuffer->getImplementationColorReadType(context);
825 
826             GLuint bytes = 0;
827             bool computeOK =
828                 format.computePackUnpackEndByte(readType, size, packState, false, &bytes);
829             ASSERT(computeOK);
830 
831             MemoryBuffer *pixelsPtr = nullptr;
832             ANGLE_CHECK_GL_ALLOC(const_cast<gl::Context *>(context),
833                                  scratchBuffer->getInitialized(bytes, &pixelsPtr, 0));
834 
835             ANGLE_TRY(renderbuffer->getImplementation()->getRenderbufferImage(
836                 context, packState, nullptr, readFormat, readType, pixelsPtr->data()));
837             json->addBlob("Pixels", pixelsPtr->data(), pixelsPtr->size());
838         }
839     }
840     else
841     {
842         json->addCString("Pixels", "Not initialized");
843     }
844     return Result::Continue;
845 }
846 
SerializeWorkGroupSize(JsonSerializer * json,const sh::WorkGroupSize & workGroupSize)847 void SerializeWorkGroupSize(JsonSerializer *json, const sh::WorkGroupSize &workGroupSize)
848 {
849     GroupScope wg(json, "workGroupSize");
850     json->addScalar("x", workGroupSize[0]);
851     json->addScalar("y", workGroupSize[1]);
852     json->addScalar("z", workGroupSize[2]);
853 }
854 
SerializeUniformIndexToBufferBinding(JsonSerializer * json,const gl::ProgramUniformBlockArray<GLuint> & blockToBuffer)855 void SerializeUniformIndexToBufferBinding(JsonSerializer *json,
856                                           const gl::ProgramUniformBlockArray<GLuint> &blockToBuffer)
857 {
858     GroupScope wg(json, "uniformBlockIndexToBufferBinding");
859     for (size_t blockIndex = 0; blockIndex < blockToBuffer.size(); ++blockIndex)
860     {
861         json->addScalar(ToString(blockIndex), blockToBuffer[blockIndex]);
862     }
863 }
864 
SerializeShaderVariable(JsonSerializer * json,const sh::ShaderVariable & shaderVariable)865 void SerializeShaderVariable(JsonSerializer *json, const sh::ShaderVariable &shaderVariable)
866 {
867     GroupScope wg(json, "ShaderVariable");
868     json->addScalar("Type", shaderVariable.type);
869     json->addScalar("Precision", shaderVariable.precision);
870     json->addString("Name", shaderVariable.name);
871     json->addString("MappedName", shaderVariable.mappedName);
872     json->addVector("ArraySizes", shaderVariable.arraySizes);
873     json->addScalar("StaticUse", shaderVariable.staticUse);
874     json->addScalar("Active", shaderVariable.active);
875     for (const sh::ShaderVariable &field : shaderVariable.fields)
876     {
877         SerializeShaderVariable(json, field);
878     }
879     json->addString("StructOrBlockName", shaderVariable.structOrBlockName);
880     json->addString("MappedStructOrBlockName", shaderVariable.mappedStructOrBlockName);
881     json->addScalar("RowMajorLayout", shaderVariable.isRowMajorLayout);
882     json->addScalar("Location", shaderVariable.location);
883     json->addScalar("Binding", shaderVariable.binding);
884     json->addScalar("ImageUnitFormat", shaderVariable.imageUnitFormat);
885     json->addScalar("Offset", shaderVariable.offset);
886     json->addScalar("Readonly", shaderVariable.readonly);
887     json->addScalar("Writeonly", shaderVariable.writeonly);
888     json->addScalar("Index", shaderVariable.index);
889     json->addScalar("YUV", shaderVariable.yuv);
890     json->addCString("Interpolation", InterpolationTypeToString(shaderVariable.interpolation));
891     json->addScalar("Invariant", shaderVariable.isInvariant);
892     json->addScalar("TexelFetchStaticUse", shaderVariable.texelFetchStaticUse);
893 }
894 
SerializeShaderVariablesVector(JsonSerializer * json,const std::vector<sh::ShaderVariable> & shaderVariables)895 void SerializeShaderVariablesVector(JsonSerializer *json,
896                                     const std::vector<sh::ShaderVariable> &shaderVariables)
897 {
898     for (const sh::ShaderVariable &shaderVariable : shaderVariables)
899     {
900         SerializeShaderVariable(json, shaderVariable);
901     }
902 }
903 
SerializeInterfaceBlocksVector(JsonSerializer * json,const std::vector<sh::InterfaceBlock> & interfaceBlocks)904 void SerializeInterfaceBlocksVector(JsonSerializer *json,
905                                     const std::vector<sh::InterfaceBlock> &interfaceBlocks)
906 {
907     for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
908     {
909         GroupScope group(json, "Interface Block");
910         json->addString("Name", interfaceBlock.name);
911         json->addString("MappedName", interfaceBlock.mappedName);
912         json->addString("InstanceName", interfaceBlock.instanceName);
913         json->addScalar("ArraySize", interfaceBlock.arraySize);
914         json->addCString("Layout", BlockLayoutTypeToString(interfaceBlock.layout));
915         json->addScalar("Binding", interfaceBlock.binding);
916         json->addScalar("StaticUse", interfaceBlock.staticUse);
917         json->addScalar("Active", interfaceBlock.active);
918         json->addCString("BlockType", BlockTypeToString(interfaceBlock.blockType));
919         SerializeShaderVariablesVector(json, interfaceBlock.fields);
920     }
921 }
922 
SerializeCompiledShaderState(JsonSerializer * json,const gl::SharedCompiledShaderState & state)923 void SerializeCompiledShaderState(JsonSerializer *json, const gl::SharedCompiledShaderState &state)
924 {
925     json->addCString("Type", gl::ShaderTypeToString(state->shaderType));
926     json->addScalar("Version", state->shaderVersion);
927     json->addString("TranslatedSource", state->translatedSource);
928     json->addVectorAsHash("CompiledBinary", state->compiledBinary);
929     SerializeWorkGroupSize(json, state->localSize);
930     SerializeShaderVariablesVector(json, state->inputVaryings);
931     SerializeShaderVariablesVector(json, state->outputVaryings);
932     SerializeShaderVariablesVector(json, state->uniforms);
933     SerializeInterfaceBlocksVector(json, state->uniformBlocks);
934     SerializeInterfaceBlocksVector(json, state->shaderStorageBlocks);
935     SerializeShaderVariablesVector(json, state->allAttributes);
936     SerializeShaderVariablesVector(json, state->activeAttributes);
937     SerializeShaderVariablesVector(json, state->activeOutputVariables);
938     json->addScalar("NumViews", state->numViews);
939     json->addScalar("SpecConstUsageBits", state->specConstUsageBits.bits());
940     json->addScalar("MetadataFlags", state->metadataFlags.bits());
941     json->addScalar("AdvancedBlendEquations", state->advancedBlendEquations.bits());
942     json->addString("GeometryShaderInputPrimitiveType",
943                     ToString(state->geometryShaderInputPrimitiveType));
944     json->addString("GeometryShaderOutputPrimitiveType",
945                     ToString(state->geometryShaderOutputPrimitiveType));
946     json->addScalar("GeometryShaderMaxVertices", state->geometryShaderMaxVertices);
947     json->addScalar("GeometryShaderInvocations", state->geometryShaderInvocations);
948     json->addScalar("TessControlShaderVertices", state->tessControlShaderVertices);
949     json->addScalar("TessGenMode", state->tessGenMode);
950     json->addScalar("TessGenSpacing", state->tessGenSpacing);
951     json->addScalar("TessGenVertexOrder", state->tessGenVertexOrder);
952     json->addScalar("TessGenPointMode", state->tessGenPointMode);
953 }
954 
SerializeShaderState(JsonSerializer * json,const gl::ShaderState & shaderState)955 void SerializeShaderState(JsonSerializer *json, const gl::ShaderState &shaderState)
956 {
957     GroupScope group(json, "ShaderState");
958     json->addString("Label", shaderState.getLabel());
959     json->addString("Source", shaderState.getSource());
960     json->addCString("CompileStatus", CompileStatusToString(shaderState.getCompileStatus()));
961 }
962 
SerializeShader(const gl::Context * context,JsonSerializer * json,GLuint id,gl::Shader * shader)963 void SerializeShader(const gl::Context *context,
964                      JsonSerializer *json,
965                      GLuint id,
966                      gl::Shader *shader)
967 {
968     // Ensure deterministic compilation.
969     shader->resolveCompile(context);
970 
971     GroupScope group(json, "Shader", id);
972     SerializeShaderState(json, shader->getState());
973     SerializeCompiledShaderState(json, shader->getCompiledState());
974     json->addScalar("Handle", shader->getHandle().value);
975     // TODO: implement MEC context validation only after all contexts have been initialized
976     // http://anglebug.com/42266488
977     // json->addScalar("RefCount", shader->getRefCount());
978     json->addScalar("FlaggedForDeletion", shader->isFlaggedForDeletion());
979     // Do not serialize mType because it is already serialized in SerializeCompiledShaderState.
980     json->addString("InfoLogString", shader->getInfoLogString());
981     // Do not serialize compiler resources string because it can vary between test modes.
982 }
983 
SerializeVariableLocationsVector(JsonSerializer * json,const std::string & group_name,const std::vector<gl::VariableLocation> & variableLocations)984 void SerializeVariableLocationsVector(JsonSerializer *json,
985                                       const std::string &group_name,
986                                       const std::vector<gl::VariableLocation> &variableLocations)
987 {
988     GroupScope group(json, group_name);
989     for (size_t locIndex = 0; locIndex < variableLocations.size(); ++locIndex)
990     {
991         const gl::VariableLocation &variableLocation = variableLocations[locIndex];
992         GroupScope vargroup(json, "Location", static_cast<int>(locIndex));
993         json->addScalar("ArrayIndex", variableLocation.arrayIndex);
994         json->addScalar("Index", variableLocation.index);
995         json->addScalar("Ignored", variableLocation.ignored);
996     }
997 }
998 
SerializeBlockMemberInfo(JsonSerializer * json,const sh::BlockMemberInfo & blockMemberInfo)999 void SerializeBlockMemberInfo(JsonSerializer *json, const sh::BlockMemberInfo &blockMemberInfo)
1000 {
1001     GroupScope group(json, "BlockMemberInfo");
1002     json->addScalar("Offset", blockMemberInfo.offset);
1003     json->addScalar("Stride", blockMemberInfo.arrayStride);
1004     json->addScalar("MatrixStride", blockMemberInfo.matrixStride);
1005     json->addScalar("IsRowMajorMatrix", blockMemberInfo.isRowMajorMatrix);
1006     json->addScalar("TopLevelArrayStride", blockMemberInfo.topLevelArrayStride);
1007 }
1008 
SerializeBufferVariablesVector(JsonSerializer * json,const std::vector<gl::BufferVariable> & bufferVariables)1009 void SerializeBufferVariablesVector(JsonSerializer *json,
1010                                     const std::vector<gl::BufferVariable> &bufferVariables)
1011 {
1012     for (const gl::BufferVariable &bufferVariable : bufferVariables)
1013     {
1014         GroupScope group(json, "BufferVariable");
1015         json->addString("Name", bufferVariable.name);
1016         json->addString("MappedName", bufferVariable.mappedName);
1017 
1018         json->addScalar("Type", bufferVariable.pod.type);
1019         json->addScalar("Precision", bufferVariable.pod.precision);
1020         json->addScalar("activeUseBits", bufferVariable.activeShaders().to_ulong());
1021         for (const gl::ShaderType shaderType : gl::AllShaderTypes())
1022         {
1023             json->addScalar(
1024                 gl::ShaderTypeToString(shaderType),
1025                 bufferVariable.isActive(shaderType) ? bufferVariable.getId(shaderType) : 0);
1026         }
1027 
1028         json->addScalar("BufferIndex", bufferVariable.pod.bufferIndex);
1029         SerializeBlockMemberInfo(json, bufferVariable.pod.blockInfo);
1030 
1031         json->addScalar("TopLevelArraySize", bufferVariable.pod.topLevelArraySize);
1032         json->addScalar("basicTypeElementCount", bufferVariable.pod.basicTypeElementCount);
1033         json->addScalar("isArray", bufferVariable.pod.isArray);
1034     }
1035 }
1036 
SerializeProgramAliasedBindings(JsonSerializer * json,const gl::ProgramAliasedBindings & programAliasedBindings)1037 void SerializeProgramAliasedBindings(JsonSerializer *json,
1038                                      const gl::ProgramAliasedBindings &programAliasedBindings)
1039 {
1040     for (const auto &programAliasedBinding : programAliasedBindings)
1041     {
1042         GroupScope group(json, programAliasedBinding.first);
1043         json->addScalar("Location", programAliasedBinding.second.location);
1044         json->addScalar("Aliased", programAliasedBinding.second.aliased);
1045     }
1046 }
1047 
SerializeProgramState(JsonSerializer * json,const gl::ProgramState & programState)1048 void SerializeProgramState(JsonSerializer *json, const gl::ProgramState &programState)
1049 {
1050     json->addString("Label", programState.getLabel());
1051     json->addVectorOfStrings("TransformFeedbackVaryingNames",
1052                              programState.getTransformFeedbackVaryingNames());
1053     json->addScalar("BinaryRetrieveableHint", programState.hasBinaryRetrieveableHint());
1054     json->addScalar("Separable", programState.isSeparable());
1055     SerializeProgramAliasedBindings(json, programState.getUniformLocationBindings());
1056 
1057     const gl::ProgramExecutable &executable = programState.getExecutable();
1058 
1059     SerializeWorkGroupSize(json, executable.getComputeShaderLocalSize());
1060     SerializeUniformIndexToBufferBinding(
1061         json, executable.getUniformBlockIndexToBufferBindingForCapture());
1062     SerializeVariableLocationsVector(json, "UniformLocations", executable.getUniformLocations());
1063     SerializeBufferVariablesVector(json, executable.getBufferVariables());
1064     SerializeRange(json, executable.getAtomicCounterUniformRange());
1065     SerializeVariableLocationsVector(json, "SecondaryOutputLocations",
1066                                      executable.getSecondaryOutputLocations());
1067     json->addScalar("NumViews", executable.getNumViews());
1068     json->addScalar("DrawIDLocation", executable.getDrawIDLocation());
1069     json->addScalar("BaseVertexLocation", executable.getBaseVertexLocation());
1070     json->addScalar("BaseInstanceLocation", executable.getBaseInstanceLocation());
1071 }
1072 
SerializeProgramBindings(JsonSerializer * json,const gl::ProgramBindings & programBindings)1073 void SerializeProgramBindings(JsonSerializer *json, const gl::ProgramBindings &programBindings)
1074 {
1075     for (const auto &programBinding : programBindings)
1076     {
1077         json->addScalar(programBinding.first, programBinding.second);
1078     }
1079 }
1080 
1081 template <typename T>
SerializeUniformData(JsonSerializer * json,const gl::Context * context,const gl::ProgramExecutable & executable,gl::UniformLocation loc,GLenum type,GLint size,void (gl::ProgramExecutable::* getFunc)(const gl::Context *,gl::UniformLocation,T *)const)1082 void SerializeUniformData(JsonSerializer *json,
1083                           const gl::Context *context,
1084                           const gl::ProgramExecutable &executable,
1085                           gl::UniformLocation loc,
1086                           GLenum type,
1087                           GLint size,
1088                           void (gl::ProgramExecutable::*getFunc)(const gl::Context *,
1089                                                                  gl::UniformLocation,
1090                                                                  T *) const)
1091 {
1092     std::vector<T> uniformData(gl::VariableComponentCount(type) * size, 0);
1093     (executable.*getFunc)(context, loc, uniformData.data());
1094     json->addVector("Data", uniformData);
1095 }
1096 
SerializeProgram(JsonSerializer * json,const gl::Context * context,GLuint id,gl::Program * program)1097 void SerializeProgram(JsonSerializer *json,
1098                       const gl::Context *context,
1099                       GLuint id,
1100                       gl::Program *program)
1101 {
1102     // Ensure deterministic link.
1103     program->resolveLink(context);
1104 
1105     GroupScope group(json, "Program", id);
1106 
1107     std::vector<GLint> shaderHandles;
1108     for (gl::ShaderType shaderType : gl::AllShaderTypes())
1109     {
1110         gl::Shader *shader = program->getAttachedShader(shaderType);
1111         shaderHandles.push_back(shader ? shader->getHandle().value : 0);
1112     }
1113     json->addVector("Handle", shaderHandles);
1114 
1115     SerializeProgramState(json, program->getState());
1116     json->addScalar("IsValidated", program->isValidated());
1117     SerializeProgramBindings(json, program->getAttributeBindings());
1118     SerializeProgramAliasedBindings(json, program->getFragmentOutputLocations());
1119     SerializeProgramAliasedBindings(json, program->getFragmentOutputIndexes());
1120     json->addScalar("IsLinked", program->isLinked());
1121     json->addScalar("IsFlaggedForDeletion", program->isFlaggedForDeletion());
1122     // TODO: implement MEC context validation only after all contexts have been initialized
1123     // http://anglebug.com/42266488
1124     // json->addScalar("RefCount", program->getRefCount());
1125     json->addScalar("ID", program->id().value);
1126 
1127     const gl::ProgramExecutable &executable = program->getExecutable();
1128 
1129     // Serialize uniforms.
1130     {
1131         GroupScope uniformsGroup(json, "Uniforms");
1132         GLint uniformCount = static_cast<GLint>(executable.getUniforms().size());
1133         for (int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
1134         {
1135             GroupScope uniformGroup(json, "Uniform", uniformIndex);
1136 
1137             constexpr GLsizei kMaxUniformNameLen = 1024;
1138             char uniformName[kMaxUniformNameLen] = {};
1139             GLint size                           = 0;
1140             GLenum type                          = GL_NONE;
1141             executable.getActiveUniform(uniformIndex, kMaxUniformNameLen, nullptr, &size, &type,
1142                                         uniformName);
1143 
1144             json->addCString("Name", uniformName);
1145             json->addScalar("Size", size);
1146             json->addCString("Type", gl::GLenumToString(gl::GLESEnum::AttributeType, type));
1147 
1148             const gl::UniformLocation loc = executable.getUniformLocation(uniformName);
1149 
1150             if (loc.value == -1)
1151             {
1152                 continue;
1153             }
1154 
1155             switch (gl::VariableComponentType(type))
1156             {
1157                 case GL_FLOAT:
1158                 {
1159                     SerializeUniformData<GLfloat>(json, context, executable, loc, type, size,
1160                                                   &gl::ProgramExecutable::getUniformfv);
1161                     break;
1162                 }
1163                 case GL_BOOL:
1164                 case GL_INT:
1165                 {
1166                     SerializeUniformData<GLint>(json, context, executable, loc, type, size,
1167                                                 &gl::ProgramExecutable::getUniformiv);
1168                     break;
1169                 }
1170                 case GL_UNSIGNED_INT:
1171                 {
1172                     SerializeUniformData<GLuint>(json, context, executable, loc, type, size,
1173                                                  &gl::ProgramExecutable::getUniformuiv);
1174                     break;
1175                 }
1176                 default:
1177                     UNREACHABLE();
1178                     break;
1179             }
1180         }
1181     }
1182 }
1183 
SerializeImageDesc(JsonSerializer * json,size_t descIndex,const gl::ImageDesc & imageDesc)1184 void SerializeImageDesc(JsonSerializer *json, size_t descIndex, const gl::ImageDesc &imageDesc)
1185 {
1186     // Skip serializing unspecified image levels.
1187     if (imageDesc.size.empty())
1188     {
1189         return;
1190     }
1191 
1192     GroupScope group(json, "ImageDesc", static_cast<int>(descIndex));
1193     SerializeExtents(json, imageDesc.size);
1194     SerializeGLFormat(json, imageDesc.format);
1195     json->addScalar("Samples", imageDesc.samples);
1196     json->addScalar("FixesSampleLocations", imageDesc.fixedSampleLocations);
1197     json->addCString("InitState", InitStateToString(imageDesc.initState));
1198 }
1199 
SerializeTextureState(JsonSerializer * json,const gl::TextureState & textureState)1200 void SerializeTextureState(JsonSerializer *json, const gl::TextureState &textureState)
1201 {
1202     json->addString("Type", ToString(textureState.getType()));
1203     SerializeSwizzleState(json, textureState.getSwizzleState());
1204     {
1205         GroupScope samplerStateGroup(json, "SamplerState");
1206         SerializeSamplerState(json, textureState.getSamplerState());
1207     }
1208     json->addCString("SRGB", SrgbOverrideToString(textureState.getSRGBOverride()));
1209     json->addScalar("BaseLevel", textureState.getBaseLevel());
1210     json->addScalar("MaxLevel", textureState.getMaxLevel());
1211     json->addScalar("DepthStencilTextureMode", textureState.getDepthStencilTextureMode());
1212     json->addScalar("BeenBoundAsImage", textureState.hasBeenBoundAsImage());
1213     json->addScalar("ImmutableFormat", textureState.getImmutableFormat());
1214     json->addScalar("ImmutableLevels", textureState.getImmutableLevels());
1215     json->addScalar("Usage", textureState.getUsage());
1216     SerializeRectangle(json, "Crop", textureState.getCrop());
1217     json->addScalar("GenerateMipmapHint", textureState.getGenerateMipmapHint());
1218     json->addCString("InitState", InitStateToString(textureState.getInitState()));
1219     json->addScalar("BoundBufferID", textureState.getBuffer().id().value);
1220 
1221     {
1222         GroupScope descGroup(json, "ImageDescs");
1223         const std::vector<gl::ImageDesc> &imageDescs = textureState.getImageDescs();
1224         for (size_t descIndex = 0; descIndex < imageDescs.size(); ++descIndex)
1225         {
1226             SerializeImageDesc(json, descIndex, imageDescs[descIndex]);
1227         }
1228     }
1229 }
1230 
SerializeTextureData(JsonSerializer * json,const gl::Context * context,gl::Texture * texture,ScratchBuffer * scratchBuffer)1231 Result SerializeTextureData(JsonSerializer *json,
1232                             const gl::Context *context,
1233                             gl::Texture *texture,
1234                             ScratchBuffer *scratchBuffer)
1235 {
1236     gl::ImageIndexIterator imageIter = gl::ImageIndexIterator::MakeGeneric(
1237         texture->getType(), texture->getBaseLevel(), texture->getMipmapMaxLevel() + 1,
1238         gl::ImageIndex::kEntireLevel, gl::ImageIndex::kEntireLevel);
1239     while (imageIter.hasNext())
1240     {
1241         gl::ImageIndex index = imageIter.next();
1242 
1243         // Skip serializing level data if the level index is out of range
1244         GLuint levelIndex = index.getLevelIndex();
1245         if (levelIndex > texture->getMipmapMaxLevel() || levelIndex < texture->getBaseLevel())
1246             continue;
1247 
1248         const gl::ImageDesc &desc = texture->getTextureState().getImageDesc(index);
1249 
1250         if (desc.size.empty())
1251             continue;
1252 
1253         const gl::InternalFormat &format = *desc.format.info;
1254 
1255         // Check for supported textures
1256         ASSERT(index.getType() == gl::TextureType::_2D || index.getType() == gl::TextureType::_3D ||
1257                index.getType() == gl::TextureType::_2DArray ||
1258                index.getType() == gl::TextureType::CubeMap ||
1259                index.getType() == gl::TextureType::CubeMapArray ||
1260                index.getType() == gl::TextureType::_2DMultisampleArray ||
1261                index.getType() == gl::TextureType::_2DMultisample ||
1262                index.getType() == gl::TextureType::External);
1263 
1264         GLenum glFormat = format.format;
1265         GLenum glType   = format.type;
1266 
1267         const gl::Extents size(desc.size.width, desc.size.height, desc.size.depth);
1268         gl::PixelPackState packState;
1269         packState.alignment = 1;
1270 
1271         GLuint endByte  = 0;
1272         bool unpackSize = format.computePackUnpackEndByte(glType, size, packState, true, &endByte);
1273         ASSERT(unpackSize);
1274         MemoryBuffer *texelsPtr = nullptr;
1275         ANGLE_CHECK_GL_ALLOC(const_cast<gl::Context *>(context),
1276                              scratchBuffer->getInitialized(endByte, &texelsPtr, 0));
1277 
1278         std::stringstream label;
1279 
1280         label << "Texels-Level" << index.getLevelIndex();
1281         if (imageIter.current().hasLayer())
1282         {
1283             label << "-Layer" << imageIter.current().getLayerIndex();
1284         }
1285 
1286         if (texture->getState().getInitState() == gl::InitState::Initialized)
1287         {
1288             if (format.compressed)
1289             {
1290                 // TODO: Read back compressed data. http://anglebug.com/42264702
1291                 json->addCString(label.str(), "compressed texel data");
1292             }
1293             else
1294             {
1295                 ANGLE_TRY(texture->getTexImage(context, packState, nullptr, index.getTarget(),
1296                                                index.getLevelIndex(), glFormat, glType,
1297                                                texelsPtr->data()));
1298                 json->addBlob(label.str(), texelsPtr->data(), texelsPtr->size());
1299             }
1300         }
1301         else
1302         {
1303             json->addCString(label.str(), "not initialized");
1304         }
1305     }
1306     return Result::Continue;
1307 }
1308 
SerializeTexture(const gl::Context * context,JsonSerializer * json,ScratchBuffer * scratchBuffer,gl::Texture * texture)1309 Result SerializeTexture(const gl::Context *context,
1310                         JsonSerializer *json,
1311                         ScratchBuffer *scratchBuffer,
1312                         gl::Texture *texture)
1313 {
1314     GroupScope group(json, "Texture", texture->getId());
1315 
1316     // We serialize texture data first, to force the texture state to be initialized.
1317     if (texture->getType() != gl::TextureType::Buffer)
1318     {
1319         ANGLE_TRY(SerializeTextureData(json, context, texture, scratchBuffer));
1320     }
1321 
1322     SerializeTextureState(json, texture->getState());
1323     json->addString("Label", texture->getLabel());
1324     // FrameCapture can not serialize mBoundSurface and mBoundStream
1325     // because they are likely to change with each run
1326     return Result::Continue;
1327 }
1328 
SerializeVertexAttributeVector(JsonSerializer * json,const std::vector<gl::VertexAttribute> & vertexAttributes)1329 void SerializeVertexAttributeVector(JsonSerializer *json,
1330                                     const std::vector<gl::VertexAttribute> &vertexAttributes)
1331 {
1332     for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
1333     {
1334         GroupScope group(json, "VertexAttribute", static_cast<int>(attribIndex));
1335         const gl::VertexAttribute &vertexAttribute = vertexAttributes[attribIndex];
1336         json->addScalar("BindingIndex", vertexAttribute.bindingIndex);
1337         json->addScalar("Enabled", vertexAttribute.enabled);
1338         ASSERT(vertexAttribute.format);
1339         SerializeANGLEFormat(json, vertexAttribute.format);
1340         json->addScalar("RelativeOffset", vertexAttribute.relativeOffset);
1341         json->addScalar("VertexAttribArrayStride", vertexAttribute.vertexAttribArrayStride);
1342     }
1343 }
1344 
SerializeVertexBindingsVector(JsonSerializer * json,const std::vector<gl::VertexBinding> & vertexBindings)1345 void SerializeVertexBindingsVector(JsonSerializer *json,
1346                                    const std::vector<gl::VertexBinding> &vertexBindings)
1347 {
1348     for (size_t bindingIndex = 0; bindingIndex < vertexBindings.size(); ++bindingIndex)
1349     {
1350         GroupScope group(json, "VertexBinding", static_cast<int>(bindingIndex));
1351         const gl::VertexBinding &vertexBinding = vertexBindings[bindingIndex];
1352         json->addScalar("Stride", vertexBinding.getStride());
1353         json->addScalar("Divisor", vertexBinding.getDivisor());
1354         json->addScalar("Offset", vertexBinding.getOffset());
1355         json->addScalar("BufferID", vertexBinding.getBuffer().id().value);
1356         json->addScalar("BoundAttributesMask", vertexBinding.getBoundAttributesMask().to_ulong());
1357     }
1358 }
1359 
SerializeVertexArrayState(JsonSerializer * json,const gl::VertexArrayState & vertexArrayState)1360 void SerializeVertexArrayState(JsonSerializer *json, const gl::VertexArrayState &vertexArrayState)
1361 {
1362     json->addString("Label", vertexArrayState.getLabel());
1363     SerializeVertexAttributeVector(json, vertexArrayState.getVertexAttributes());
1364     if (vertexArrayState.getElementArrayBuffer())
1365     {
1366         json->addScalar("ElementArrayBufferID",
1367                         vertexArrayState.getElementArrayBuffer()->id().value);
1368     }
1369     else
1370     {
1371         json->addScalar("ElementArrayBufferID", 0);
1372     }
1373     SerializeVertexBindingsVector(json, vertexArrayState.getVertexBindings());
1374     json->addScalar("EnabledAttributesMask",
1375                     vertexArrayState.getEnabledAttributesMask().to_ulong());
1376     json->addScalar("VertexAttributesTypeMask",
1377                     vertexArrayState.getVertexAttributesTypeMask().to_ulong());
1378     json->addScalar("ClientMemoryAttribsMask",
1379                     vertexArrayState.getClientMemoryAttribsMask().to_ulong());
1380     json->addScalar("NullPointerClientMemoryAttribsMask",
1381                     vertexArrayState.getNullPointerClientMemoryAttribsMask().to_ulong());
1382 }
1383 
SerializeVertexArray(JsonSerializer * json,gl::VertexArray * vertexArray)1384 void SerializeVertexArray(JsonSerializer *json, gl::VertexArray *vertexArray)
1385 {
1386     GroupScope group(json, "VertexArray", vertexArray->id().value);
1387     SerializeVertexArrayState(json, vertexArray->getState());
1388     json->addScalar("BufferAccessValidationEnabled",
1389                     vertexArray->isBufferAccessValidationEnabled());
1390 }
1391 
1392 }  // namespace
1393 
SerializeContextToString(const gl::Context * context,std::string * stringOut)1394 Result SerializeContextToString(const gl::Context *context, std::string *stringOut)
1395 {
1396     JsonSerializer json;
1397     json.startGroup("Context");
1398 
1399     SerializeContextState(&json, context->getState());
1400     ScratchBuffer scratchBuffer(1);
1401     {
1402         const gl::FramebufferManager &framebufferManager =
1403             context->getState().getFramebufferManagerForCapture();
1404         GroupScope framebufferGroup(&json, "FramebufferManager");
1405         for (const auto &framebuffer :
1406              gl::UnsafeResourceMapIter(framebufferManager.getResourcesForCapture()))
1407         {
1408             gl::Framebuffer *framebufferPtr = framebuffer.second;
1409             ANGLE_TRY(SerializeFramebuffer(context, &json, &scratchBuffer, framebufferPtr));
1410         }
1411     }
1412     {
1413         const gl::BufferManager &bufferManager = context->getState().getBufferManagerForCapture();
1414         GroupScope framebufferGroup(&json, "BufferManager");
1415         for (const auto &buffer : gl::UnsafeResourceMapIter(bufferManager.getResourcesForCapture()))
1416         {
1417             gl::Buffer *bufferPtr = buffer.second;
1418             ANGLE_TRY(SerializeBuffer(context, &json, &scratchBuffer, bufferPtr));
1419         }
1420     }
1421     {
1422         const gl::SamplerManager &samplerManager =
1423             context->getState().getSamplerManagerForCapture();
1424         GroupScope samplerGroup(&json, "SamplerManager");
1425         for (const auto &sampler :
1426              gl::UnsafeResourceMapIter(samplerManager.getResourcesForCapture()))
1427         {
1428             gl::Sampler *samplerPtr = sampler.second;
1429             SerializeSampler(&json, samplerPtr);
1430         }
1431     }
1432     {
1433         const gl::RenderbufferManager &renderbufferManager =
1434             context->getState().getRenderbufferManagerForCapture();
1435         GroupScope renderbufferGroup(&json, "RenderbufferManager");
1436         for (const auto &renderbuffer :
1437              gl::UnsafeResourceMapIter(renderbufferManager.getResourcesForCapture()))
1438         {
1439             gl::Renderbuffer *renderbufferPtr = renderbuffer.second;
1440             ANGLE_TRY(SerializeRenderbuffer(context, &json, &scratchBuffer, renderbufferPtr));
1441         }
1442     }
1443     const gl::ShaderProgramManager &shaderProgramManager =
1444         context->getState().getShaderProgramManagerForCapture();
1445     {
1446         const gl::ResourceMap<gl::Shader, gl::ShaderProgramID> &shaderManager =
1447             shaderProgramManager.getShadersForCapture();
1448         GroupScope shaderGroup(&json, "ShaderManager");
1449         for (const auto &shader : gl::UnsafeResourceMapIter(shaderManager))
1450         {
1451             GLuint id             = shader.first;
1452             gl::Shader *shaderPtr = shader.second;
1453             SerializeShader(context, &json, id, shaderPtr);
1454         }
1455     }
1456     {
1457         const gl::ResourceMap<gl::Program, gl::ShaderProgramID> &programManager =
1458             shaderProgramManager.getProgramsForCaptureAndPerf();
1459         GroupScope shaderGroup(&json, "ProgramManager");
1460         for (const auto &program : gl::UnsafeResourceMapIter(programManager))
1461         {
1462             GLuint id               = program.first;
1463             gl::Program *programPtr = program.second;
1464             SerializeProgram(&json, context, id, programPtr);
1465         }
1466     }
1467     {
1468         const gl::TextureManager &textureManager =
1469             context->getState().getTextureManagerForCapture();
1470         GroupScope shaderGroup(&json, "TextureManager");
1471         for (const auto &texture :
1472              gl::UnsafeResourceMapIter(textureManager.getResourcesForCapture()))
1473         {
1474             gl::Texture *texturePtr = texture.second;
1475             ANGLE_TRY(SerializeTexture(context, &json, &scratchBuffer, texturePtr));
1476         }
1477     }
1478     {
1479         const gl::VertexArrayMap &vertexArrayMap = context->getVertexArraysForCapture();
1480         GroupScope shaderGroup(&json, "VertexArrayMap");
1481         for (const auto &vertexArray : gl::UnsafeResourceMapIter(vertexArrayMap))
1482         {
1483             gl::VertexArray *vertexArrayPtr = vertexArray.second;
1484             SerializeVertexArray(&json, vertexArrayPtr);
1485         }
1486     }
1487     json.endGroup();
1488 
1489     *stringOut = json.data();
1490 
1491     scratchBuffer.clear();
1492     return Result::Continue;
1493 }
1494 
1495 }  // namespace angle
1496