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