1 //
2 // Copyright 2022 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 // trace_interpreter.cpp:
7 // Parser and interpreter for the C-based replays.
8 //
9
10 #include "trace_interpreter.h"
11
12 #include "anglebase/no_destructor.h"
13 #include "common/gl_enum_utils.h"
14 #include "common/string_utils.h"
15 #include "trace_fixture.h"
16
17 #define USE_SYSTEM_ZLIB
18 #include "compression_utils_portable.h"
19
20 namespace angle
21 {
22 namespace
23 {
ShouldParseFile(const std::string & file)24 bool ShouldParseFile(const std::string &file)
25 {
26 return EndsWith(file, ".c") || EndsWith(file, ".cpp");
27 }
28
ReplayTraceFunction(const TraceFunction & func,const TraceFunctionMap & customFunctions)29 void ReplayTraceFunction(const TraceFunction &func, const TraceFunctionMap &customFunctions)
30 {
31 for (const CallCapture &call : func)
32 {
33 ReplayTraceFunctionCall(call, customFunctions);
34 }
35 }
36
37 class Parser : angle::NonCopyable
38 {
39 public:
Parser(const std::string & stream,TraceFunctionMap & functionsIn,TraceStringMap & stringsIn,bool verboseLogging)40 Parser(const std::string &stream,
41 TraceFunctionMap &functionsIn,
42 TraceStringMap &stringsIn,
43 bool verboseLogging)
44 : mStream(stream),
45 mFunctions(functionsIn),
46 mStrings(stringsIn),
47 mIndex(0),
48 mVerboseLogging(verboseLogging)
49 {}
50
parse()51 void parse()
52 {
53 while (mIndex < mStream.size())
54 {
55 if (peek() == '#' || peek() == '/')
56 {
57 skipLine();
58 }
59 else if (peek() == 'v')
60 {
61 ASSERT(check("void "));
62 readFunction();
63 }
64 else if (peek() == 'c')
65 {
66 ASSERT(check("const "));
67 readMultilineString();
68 }
69 else
70 {
71 printf("Unexpected character: '%c'\n", peek());
72 UNREACHABLE();
73 }
74 }
75 }
76
77 private:
peek() const78 ANGLE_INLINE char peek() const { return mStream[mIndex]; }
79
look(size_t ahead) const80 ANGLE_INLINE char look(size_t ahead) const { return mStream[mIndex + ahead]; }
81
advance()82 ANGLE_INLINE void advance() { mIndex++; }
83
advanceTo(char delim)84 ANGLE_INLINE void advanceTo(char delim)
85 {
86 while (peek() != delim)
87 {
88 advance();
89 }
90 }
91
check(const char * forString) const92 bool check(const char *forString) const
93 {
94 return mStream.substr(mIndex, strlen(forString)) == forString;
95 }
96
skipLine()97 void skipLine()
98 {
99 advanceTo('\n');
100 skipWhitespace();
101 }
102
skipWhitespace()103 void skipWhitespace()
104 {
105 while (isspace(peek()))
106 {
107 advance();
108 }
109 }
110
skipNonWhitespace()111 void skipNonWhitespace()
112 {
113 while (!isspace(peek()))
114 {
115 advance();
116 }
117 }
118
119 // In our simplified trace C, every line that begins with a } either ends a function or a
120 // string. All lines inside the function begin with whitespace. So to find the end of the
121 // function we just need to scan for a line beginning with }.
skipFunction()122 void skipFunction()
123 {
124 while (peek() != '}')
125 {
126 advanceTo('\n');
127 advance();
128 }
129 advance();
130 skipWhitespace();
131 }
132
readStringAppend(std::string * stringOut,char delim)133 void readStringAppend(std::string *stringOut, char delim)
134 {
135 while (peek() != delim)
136 {
137 if (peek() == '\\')
138 {
139 advance();
140 switch (peek())
141 {
142 case 'n':
143 *stringOut += '\n';
144 break;
145 case '\"':
146 *stringOut += '\"';
147 break;
148 case '\\':
149 *stringOut += '\\';
150 break;
151 default:
152 printf("Unrecognized escape character: \\%c\n", peek());
153 UNREACHABLE();
154 break;
155 }
156 }
157 else
158 {
159 *stringOut += peek();
160 }
161 advance();
162 }
163 }
164
readToken(Token & token,char delim)165 void readToken(Token &token, char delim)
166 {
167 size_t startIndex = mIndex;
168 advanceTo(delim);
169 size_t tokenSize = mIndex - startIndex;
170 ASSERT(tokenSize < kMaxTokenSize);
171 memcpy(token, &mStream[startIndex], tokenSize);
172 token[mIndex - startIndex] = 0;
173 }
174
skipCast()175 void skipCast()
176 {
177 if (peek() == '(')
178 {
179 advanceTo(')');
180 advance();
181 }
182 }
183
skipComments()184 void skipComments()
185 {
186 while (peek() == '/')
187 {
188 skipLine();
189 }
190 }
191
readFunction()192 void readFunction()
193 {
194 std::string funcName;
195 TraceFunction func;
196
197 // Skip past the "void" return value.
198 skipNonWhitespace();
199 advance();
200 readStringAppend(&funcName, '(');
201 if (mVerboseLogging)
202 {
203 printf("function: %s\n", funcName.c_str());
204 }
205
206 // Skip this function because of the switch statements.
207 if (funcName == "ReplayFrame")
208 {
209 skipFunction();
210 return;
211 }
212
213 skipLine();
214 ASSERT(peek() == '{');
215 skipLine();
216 while (peek() != '}')
217 {
218 skipComments();
219
220 Token nameToken;
221 readToken(nameToken, '(');
222 advance();
223 ParamBuffer params;
224 Token paramTokens[kMaxParameters];
225 size_t numParams = 0;
226 skipCast();
227 size_t tokenStart = mIndex;
228 while (peek() != ';')
229 {
230 // Skip casts.
231 if (peek() == ',' || (peek() == ')' && mIndex != tokenStart))
232 {
233 ASSERT(numParams < kMaxParameters);
234 size_t tokenSize = mIndex - tokenStart;
235 ASSERT(tokenSize < kMaxTokenSize);
236 Token &token = paramTokens[numParams++];
237
238 memcpy(token, &mStream[tokenStart], tokenSize);
239 token[tokenSize] = 0;
240 advance();
241 skipWhitespace();
242 skipCast();
243 tokenStart = mIndex;
244 }
245 else
246 {
247 advance();
248 }
249 }
250
251 // Turn on if you want more spam.
252 // if (mVerboseLogging)
253 //{
254 // printf("call: %s(", nameToken);
255 // for (size_t paramIndex = 0; paramIndex < numParams; ++paramIndex)
256 // {
257 // if (paramIndex > 0)
258 // {
259 // printf(", ");
260 // }
261 // printf("%s", paramTokens[paramIndex]);
262 // }
263 // printf(")\n");
264 //}
265
266 // We pass in the strings for specific use with C string array parameters.
267 CallCapture call = ParseCallCapture(nameToken, numParams, paramTokens, mStrings);
268 func.push_back(std::move(call));
269 skipLine();
270 }
271 skipLine();
272
273 addFunction(funcName, func);
274 }
275
readMultilineString()276 void readMultilineString()
277 {
278 std::string name;
279 TraceString traceStr;
280
281 while (peek() != 'g')
282 {
283 advance();
284 }
285 ASSERT(check("glShaderSource") || check("glTransformFeedbackVaryings"));
286
287 readStringAppend(&name, '[');
288 if (mVerboseLogging)
289 {
290 printf("string: %s\n", name.c_str());
291 }
292 skipLine();
293 std::string str;
294 while (peek() != '}')
295 {
296 advance();
297 readStringAppend(&str, '\"');
298 advance();
299 if (peek() == ',')
300 {
301 traceStr.strings.push_back(std::move(str));
302 }
303 skipLine();
304 }
305 skipLine();
306
307 for (const std::string &cppstr : traceStr.strings)
308 {
309 traceStr.pointers.push_back(cppstr.c_str());
310 }
311
312 mStrings[name] = std::move(traceStr);
313 }
314
addFunction(const std::string & funcName,TraceFunction & func)315 void addFunction(const std::string &funcName, TraceFunction &func)
316 {
317 // Run initialize immediately so we can load the binary data.
318 if (funcName == "InitReplay")
319 {
320 ReplayTraceFunction(func, {});
321 func.clear();
322 }
323 mFunctions[funcName] = std::move(func);
324 }
325
326 const std::string &mStream;
327 TraceFunctionMap &mFunctions;
328 TraceStringMap &mStrings;
329 size_t mIndex;
330 bool mVerboseLogging = false;
331 };
332
PackResourceID(ParamBuffer & params,const Token & token)333 void PackResourceID(ParamBuffer ¶ms, const Token &token)
334 {
335 ASSERT(token[0] == 'g');
336 const char *start = strrchr(token, '[');
337 ASSERT(start != nullptr && EndsWith(token, "]"));
338 uint32_t value = static_cast<uint32_t>(atoi(start + 1));
339 if (BeginsWith(token, "gShaderProgramMap"))
340 {
341 gl::ShaderProgramID id = {value};
342 params.addUnnamedParam(ParamType::TShaderProgramID, id);
343 }
344 else if (BeginsWith(token, "gBufferMap"))
345 {
346 gl::BufferID id = {value};
347 params.addUnnamedParam(ParamType::TBufferID, id);
348 }
349 else if (BeginsWith(token, "gTextureMap"))
350 {
351 gl::TextureID id = {value};
352 params.addUnnamedParam(ParamType::TTextureID, id);
353 }
354 else if (BeginsWith(token, "gRenderbufferMap"))
355 {
356 gl::RenderbufferID id = {value};
357 params.addUnnamedParam(ParamType::TRenderbufferID, id);
358 }
359 else if (BeginsWith(token, "gFramebufferMap"))
360 {
361 gl::FramebufferID id = {value};
362 params.addUnnamedParam(ParamType::TFramebufferID, id);
363 }
364 else if (BeginsWith(token, "gSyncMap"))
365 {
366 gl::SyncID id = {value};
367 params.addUnnamedParam(ParamType::TSyncID, id);
368 }
369 else if (BeginsWith(token, "gTransformFeedbackMap"))
370 {
371 gl::TransformFeedbackID id = {value};
372 params.addUnnamedParam(ParamType::TTransformFeedbackID, id);
373 }
374 else if (BeginsWith(token, "gVertexArrayMap"))
375 {
376 gl::VertexArrayID id = {value};
377 params.addUnnamedParam(ParamType::TVertexArrayID, id);
378 }
379 else if (BeginsWith(token, "gQueryMap"))
380 {
381 gl::QueryID id = {value};
382 params.addUnnamedParam(ParamType::TQueryID, id);
383 }
384 else if (BeginsWith(token, "gSamplerMap"))
385 {
386 gl::SamplerID id = {value};
387 params.addUnnamedParam(ParamType::TSamplerID, id);
388 }
389 else
390 {
391 printf("Unknown resource map: %s\n", token);
392 UNREACHABLE();
393 }
394 }
395
396 template <typename IntT>
PackIntParameter(ParamBuffer & params,ParamType paramType,const Token & token)397 void PackIntParameter(ParamBuffer ¶ms, ParamType paramType, const Token &token)
398 {
399 IntT value;
400
401 if (token[0] == 'G')
402 {
403 ASSERT(BeginsWith(token, "GL_"));
404 if (strchr(token, '|') == 0)
405 {
406 value = static_cast<IntT>(gl::StringToGLenum(token));
407 }
408 else
409 {
410 value = static_cast<IntT>(gl::StringToGLbitfield(token));
411 }
412 }
413 else
414 {
415 if (!isdigit(token[0]) && !(token[0] == '-' && isdigit(token[1])))
416 {
417 printf("Expected number, got %s\n", token);
418 UNREACHABLE();
419 }
420 if (token[0] == '0' && token[1] == 'x')
421 {
422 value = static_cast<IntT>(strtol(token, nullptr, 16));
423 }
424 else
425 {
426 value = static_cast<IntT>(atoi(token));
427 }
428 }
429
430 params.addUnnamedParam(paramType, value);
431 }
432
GetStringArrayOffset(const Token & token,const char * prefixString)433 uint32_t GetStringArrayOffset(const Token &token, const char *prefixString)
434 {
435 const char *offsetString = &token[strlen(prefixString)];
436 return atoi(offsetString);
437 }
438
439 template <typename PointerT>
PackMemPointer(ParamBuffer & params,ParamType paramType,uint32_t offset,uint8_t * mem)440 void PackMemPointer(ParamBuffer ¶ms, ParamType paramType, uint32_t offset, uint8_t *mem)
441 {
442 ASSERT(gBinaryData);
443 params.addUnnamedParam(paramType, reinterpret_cast<PointerT>(&mem[offset]));
444 }
445
446 template <typename T>
PackMutablePointerParameter(ParamBuffer & params,ParamType paramType,const Token & token)447 void PackMutablePointerParameter(ParamBuffer ¶ms, ParamType paramType, const Token &token)
448 {
449 if (token[0] == '0' && token[1] == 0)
450 {
451 params.addUnnamedParam(paramType, reinterpret_cast<T *>(0));
452 }
453 else if (token[0] == '&')
454 {
455 ASSERT(BeginsWith(token, "&gReadBuffer[") && EndsWith(token, "]"));
456 uint32_t offset = GetStringArrayOffset(token, "&gReadBuffer[");
457 PackMemPointer<T *>(params, paramType, offset, gReadBuffer);
458 }
459 else if (token[0] == 'g')
460 {
461 ASSERT(strcmp(token, "gReadBuffer") == 0);
462 params.addUnnamedParam(paramType, reinterpret_cast<T *>(gReadBuffer));
463 }
464 else
465 {
466 UNREACHABLE();
467 }
468 }
469
470 template <typename T>
PackConstPointerParameter(ParamBuffer & params,ParamType paramType,const Token & token)471 void PackConstPointerParameter(ParamBuffer ¶ms, ParamType paramType, const Token &token)
472 {
473 // Handle nullptr, the literal "0".
474 if (token[0] == '0' && token[1] == 0)
475 {
476 params.addUnnamedParam(paramType, reinterpret_cast<const T *>(0));
477 }
478 else if (token[0] == '&')
479 {
480 ASSERT(BeginsWith(token, "&gBinaryData[") && EndsWith(token, "]"));
481 uint32_t offset = GetStringArrayOffset(token, "&gReadBuffer[");
482 PackMemPointer<const T *>(params, paramType, offset, gBinaryData);
483 }
484 else if (token[0] == 'g')
485 {
486 if (strcmp(token, "gResourceIDBuffer") == 0)
487 {
488 params.addUnnamedParam(paramType, reinterpret_cast<const T *>(gResourceIDBuffer));
489 }
490 else if (BeginsWith(token, "gClientArrays"))
491 {
492 uint32_t offset = GetStringArrayOffset(token, "gClientArrays[");
493 params.addUnnamedParam(paramType, reinterpret_cast<const T *>(gClientArrays[offset]));
494 }
495 else
496 {
497 printf("Unexpected token: %s\n", token);
498 UNREACHABLE();
499 }
500 }
501 else
502 {
503 ASSERT(isdigit(token[0]));
504 uint32_t offset = atoi(token);
505 params.addUnnamedParam(paramType,
506 reinterpret_cast<const T *>(static_cast<uintptr_t>(offset)));
507 }
508 }
509
510 class TraceInterpreter : angle::NonCopyable
511 {
512 public:
513 TraceInterpreter() = default;
514 ~TraceInterpreter() = default;
515
516 void replayFrame(uint32_t frameIndex);
517 void setupReplay();
518 void resetReplay();
519 void setupFirstFrame();
520 const char *getSerializedContextState(uint32_t frameIndex);
521
522 private:
523 void runTraceFunction(const char *name) const;
524 void parseTraceUncompressed();
525 void parseTraceGz();
526
527 TraceFunctionMap mTraceFunctions;
528 TraceStringMap mTraceStrings;
529 bool mVerboseLogging = true;
530 };
531
replayFrame(uint32_t frameIndex)532 void TraceInterpreter::replayFrame(uint32_t frameIndex)
533 {
534 char funcName[kMaxTokenSize];
535 snprintf(funcName, kMaxTokenSize, "ReplayFrame%u", frameIndex);
536 runTraceFunction(funcName);
537 }
538
parseTraceUncompressed()539 void TraceInterpreter::parseTraceUncompressed()
540 {
541 for (const std::string &file : gTraceInfo.traceFiles)
542 {
543 if (!ShouldParseFile(file))
544 {
545 if (mVerboseLogging)
546 {
547 printf("Skipping function parsing for %s.\n", file.c_str());
548 }
549 continue;
550 }
551
552 if (mVerboseLogging)
553 {
554 printf("Parsing functions from %s\n", file.c_str());
555 }
556 std::stringstream pathStream;
557 pathStream << gBinaryDataDir << GetPathSeparator() << file;
558 std::string path = pathStream.str();
559
560 std::string fileData;
561 if (!ReadFileToString(path, &fileData))
562 {
563 UNREACHABLE();
564 }
565
566 Parser parser(fileData, mTraceFunctions, mTraceStrings, mVerboseLogging);
567 parser.parse();
568 }
569 }
570
parseTraceGz()571 void TraceInterpreter::parseTraceGz()
572 {
573 if (mVerboseLogging)
574 {
575 printf("Parsing functions from %s\n", gTraceGzPath.c_str());
576 }
577
578 FILE *fp = fopen(gTraceGzPath.c_str(), "rb");
579 if (fp == 0)
580 {
581 printf("Error loading trace (gz) from: %s\n", gTraceGzPath.c_str());
582 exit(1);
583 }
584
585 fseek(fp, 0, SEEK_END);
586 long size = ftell(fp);
587 fseek(fp, 0, SEEK_SET);
588
589 std::vector<uint8_t> compressedData(size);
590 (void)fread(compressedData.data(), 1, size, fp);
591
592 uint32_t uncompressedSize =
593 zlib_internal::GetGzipUncompressedSize(compressedData.data(), compressedData.size());
594
595 std::string uncompressedData(uncompressedSize, 0);
596 uLong destLen = uncompressedSize;
597 int zResult = zlib_internal::GzipUncompressHelper((uint8_t *)uncompressedData.data(), &destLen,
598 compressedData.data(),
599 static_cast<uLong>(compressedData.size()));
600
601 if (zResult != Z_OK)
602 {
603 printf("Failure to decompress gz trace: %s\n", gTraceGzPath.c_str());
604 exit(1);
605 }
606
607 Parser parser(uncompressedData, mTraceFunctions, mTraceStrings, mVerboseLogging);
608 parser.parse();
609 }
610
setupReplay()611 void TraceInterpreter::setupReplay()
612 {
613 if (!gTraceGzPath.empty())
614 {
615 parseTraceGz();
616 }
617 else
618 {
619 parseTraceUncompressed();
620 }
621
622 if (mTraceFunctions.count("SetupReplay") == 0)
623 {
624 printf("Did not find a SetupReplay function to run among %zu parsed functions.\n",
625 mTraceFunctions.size());
626 exit(1);
627 }
628
629 runTraceFunction("SetupReplay");
630 }
631
resetReplay()632 void TraceInterpreter::resetReplay()
633 {
634 runTraceFunction("ResetReplay");
635 }
636
setupFirstFrame()637 void TraceInterpreter::setupFirstFrame()
638 {
639 runTraceFunction("SetupFirstFrame");
640 }
641
getSerializedContextState(uint32_t frameIndex)642 const char *TraceInterpreter::getSerializedContextState(uint32_t frameIndex)
643 {
644 // TODO: Necessary for complete self-testing. http://anglebug.com/42266250
645 UNREACHABLE();
646 return nullptr;
647 }
648
runTraceFunction(const char * name) const649 void TraceInterpreter::runTraceFunction(const char *name) const
650 {
651 auto iter = mTraceFunctions.find(name);
652 if (iter == mTraceFunctions.end())
653 {
654 printf("Cannot find function: %s\n", name);
655 UNREACHABLE();
656 }
657 const TraceFunction &func = iter->second;
658 ReplayTraceFunction(func, mTraceFunctions);
659 }
660
GetInterpreter()661 TraceInterpreter &GetInterpreter()
662 {
663 static angle::base::NoDestructor<std::unique_ptr<TraceInterpreter>> sTraceInterpreter(
664 new TraceInterpreter());
665 return *sTraceInterpreter.get()->get();
666 }
667 } // anonymous namespace
668
669 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)670 void PackParameter<uint32_t>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
671 {
672 if (token[0] == 'g')
673 {
674 PackResourceID(params, token);
675 }
676 else
677 {
678 PackIntParameter<uint32_t>(params, ParamType::TGLuint, token);
679 }
680 }
681
682 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)683 void PackParameter<int32_t>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
684 {
685 if (BeginsWith(token, "gUniformLocations"))
686 {
687 const char *start = strrchr(token, '[');
688 ASSERT(start != nullptr && EndsWith(token, "]"));
689 int32_t value = atoi(start + 1);
690 gl::UniformLocation loc = {value};
691 params.addUnnamedParam(ParamType::TUniformLocation, loc);
692 }
693 else
694 {
695 PackIntParameter<int32_t>(params, ParamType::TGLint, token);
696 }
697 }
698
699 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)700 void PackParameter<void *>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
701 {
702 void *value = 0;
703 params.addUnnamedParam(ParamType::TvoidPointer, value);
704 }
705
706 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)707 void PackParameter<const int32_t *>(ParamBuffer ¶ms,
708 const Token &token,
709 const TraceStringMap &strings)
710 {
711 PackConstPointerParameter<int32_t>(params, ParamType::TGLintConstPointer, token);
712 }
713
714 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)715 void PackParameter<void **>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
716 {
717 UNREACHABLE();
718 }
719
720 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)721 void PackParameter<int32_t *>(ParamBuffer ¶ms,
722 const Token &token,
723 const TraceStringMap &strings)
724 {
725 PackMutablePointerParameter<int32_t>(params, ParamType::TGLintPointer, token);
726 }
727
728 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)729 void PackParameter<uint64_t>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
730 {
731 params.addUnnamedParam(ParamType::TGLuint64,
732 static_cast<GLuint64>(std::strtoull(token, nullptr, 10)));
733 }
734
735 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)736 void PackParameter<int64_t>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
737 {
738 params.addUnnamedParam(ParamType::TGLint64,
739 static_cast<GLint64>(std::strtoll(token, nullptr, 10)));
740 }
741
742 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)743 void PackParameter<const int64_t *>(ParamBuffer ¶ms,
744 const Token &token,
745 const TraceStringMap &strings)
746 {
747 UNREACHABLE();
748 }
749
750 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)751 void PackParameter<int64_t *>(ParamBuffer ¶ms,
752 const Token &token,
753 const TraceStringMap &strings)
754 {
755 UNREACHABLE();
756 }
757
758 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)759 void PackParameter<uint64_t *>(ParamBuffer ¶ms,
760 const Token &token,
761 const TraceStringMap &strings)
762 {
763 UNREACHABLE();
764 }
765
766 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)767 void PackParameter<const char *>(ParamBuffer ¶ms,
768 const Token &token,
769 const TraceStringMap &strings)
770 {
771 if (token[0] == '"')
772 {
773 ASSERT(EndsWith(token, "\""));
774
775 ParamCapture param(params.getNextParamName(), ParamType::TGLcharConstPointer);
776 std::vector<uint8_t> data(&token[1], &token[strlen(token) - 1]);
777 data.push_back(0);
778 param.data.push_back(std::move(data));
779 param.value.GLcharConstPointerVal = reinterpret_cast<const char *>(param.data[0].data());
780 params.addParam(std::move(param));
781 }
782 else
783 {
784 PackConstPointerParameter<char>(params, ParamType::TGLcharConstPointer, token);
785 }
786 }
787
788 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)789 void PackParameter<const void *>(ParamBuffer ¶ms,
790 const Token &token,
791 const TraceStringMap &strings)
792 {
793 PackConstPointerParameter<void>(params, ParamType::TvoidConstPointer, token);
794 }
795
796 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)797 void PackParameter<uint32_t *>(ParamBuffer ¶ms,
798 const Token &token,
799 const TraceStringMap &strings)
800 {
801 PackMutablePointerParameter<uint32_t>(params, ParamType::TGLuintPointer, token);
802 }
803
804 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)805 void PackParameter<const uint32_t *>(ParamBuffer ¶ms,
806 const Token &token,
807 const TraceStringMap &strings)
808 {
809 PackConstPointerParameter<uint32_t>(params, ParamType::TGLuintConstPointer, token);
810 }
811
812 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)813 void PackParameter<float>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
814 {
815 params.addUnnamedParam(ParamType::TGLfloat, std::stof(token));
816 }
817
818 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)819 void PackParameter<uint8_t>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
820 {
821 PackIntParameter<uint8_t>(params, ParamType::TGLubyte, token);
822 }
823
824 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)825 void PackParameter<float *>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
826 {
827 PackMutablePointerParameter<float>(params, ParamType::TGLfloatPointer, token);
828 }
829
830 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)831 void PackParameter<const float *>(ParamBuffer ¶ms,
832 const Token &token,
833 const TraceStringMap &strings)
834 {
835 PackConstPointerParameter<float>(params, ParamType::TGLfloatConstPointer, token);
836 }
837
838 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)839 void PackParameter<GLsync>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
840 {
841 PackResourceID(params, token);
842 }
843
844 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)845 void PackParameter<const char *const *>(ParamBuffer ¶ms,
846 const Token &token,
847 const TraceStringMap &strings)
848 {
849 // Find the string that corresponds to "token". Currently we only support string arrays.
850 auto iter = strings.find(token);
851 if (iter == strings.end())
852 {
853 printf("Could not find string: %s\n", token);
854 UNREACHABLE();
855 }
856 const TraceString &traceStr = iter->second;
857 params.addUnnamedParam(ParamType::TGLcharConstPointerPointer, traceStr.pointers.data());
858 }
859
860 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)861 void PackParameter<const char **>(ParamBuffer ¶ms,
862 const Token &token,
863 const TraceStringMap &strings)
864 {
865 UNREACHABLE();
866 }
867
868 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)869 void PackParameter<GLDEBUGPROCKHR>(ParamBuffer ¶ms,
870 const Token &token,
871 const TraceStringMap &strings)
872 {
873 UNREACHABLE();
874 }
875
876 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)877 void PackParameter<EGLDEBUGPROCKHR>(ParamBuffer ¶ms,
878 const Token &token,
879 const TraceStringMap &strings)
880 {
881 UNREACHABLE();
882 }
883
884 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)885 void PackParameter<const struct AHardwareBuffer *>(ParamBuffer ¶ms,
886 const Token &token,
887 const TraceStringMap &strings)
888 {
889 UNREACHABLE();
890 }
891
892 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)893 void PackParameter<EGLSetBlobFuncANDROID>(ParamBuffer ¶ms,
894 const Token &token,
895 const TraceStringMap &strings)
896 {
897 UNREACHABLE();
898 }
899
900 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)901 void PackParameter<EGLGetBlobFuncANDROID>(ParamBuffer ¶ms,
902 const Token &token,
903 const TraceStringMap &strings)
904 {
905 UNREACHABLE();
906 }
907
908 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)909 void PackParameter<int16_t>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
910 {
911 PackIntParameter<int16_t>(params, ParamType::TGLshort, token);
912 }
913
914 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)915 void PackParameter<const int16_t *>(ParamBuffer ¶ms,
916 const Token &token,
917 const TraceStringMap &strings)
918 {
919 PackConstPointerParameter<int16_t>(params, ParamType::TGLshortConstPointer, token);
920 }
921
922 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)923 void PackParameter<char *>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
924 {
925 UNREACHABLE();
926 }
927
928 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)929 void PackParameter<unsigned char *>(ParamBuffer ¶ms,
930 const Token &token,
931 const TraceStringMap &strings)
932 {
933 PackMutablePointerParameter<GLubyte>(params, ParamType::TGLubytePointer, token);
934 }
935
936 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)937 void PackParameter<const void *const *>(ParamBuffer ¶ms,
938 const Token &token,
939 const TraceStringMap &strings)
940 {
941 UNREACHABLE();
942 }
943
944 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)945 void PackParameter<const uint64_t *>(ParamBuffer ¶ms,
946 const Token &token,
947 const TraceStringMap &strings)
948 {
949 UNREACHABLE();
950 }
951
952 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)953 void PackParameter<GLGETBLOBPROCANGLE>(ParamBuffer ¶ms,
954 const Token &token,
955 const TraceStringMap &strings)
956 {
957 UNREACHABLE();
958 }
959
960 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)961 void PackParameter<GLSETBLOBPROCANGLE>(ParamBuffer ¶ms,
962 const Token &token,
963 const TraceStringMap &strings)
964 {
965 UNREACHABLE();
966 }
967
968 #if defined(ANGLE_PLATFORM_WINDOWS)
969 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)970 void PackParameter<EGLNativeDisplayType>(ParamBuffer ¶ms,
971 const Token &token,
972 const TraceStringMap &strings)
973 {
974 UNREACHABLE();
975 }
976 #endif // defined(ANGLE_PLATFORM_WINDOWS)
977
978 #if defined(ANGLE_PLATFORM_WINDOWS) || defined(ANGLE_PLATFORM_ANDROID)
979 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)980 void PackParameter<EGLNativeWindowType>(ParamBuffer ¶ms,
981 const Token &token,
982 const TraceStringMap &strings)
983 {
984 UNREACHABLE();
985 }
986
987 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)988 void PackParameter<EGLNativePixmapType>(ParamBuffer ¶ms,
989 const Token &token,
990 const TraceStringMap &strings)
991 {
992 UNREACHABLE();
993 }
994 #endif // defined(ANGLE_PLATFORM_WINDOWS) || defined(ANGLE_PLATFORM_ANDROID)
995
996 #if defined(ANGLE_PLATFORM_APPLE) || !defined(ANGLE_IS_64_BIT_CPU)
997 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)998 void PackParameter<const long *>(ParamBuffer ¶ms,
999 const Token &token,
1000 const TraceStringMap &strings)
1001 {
1002 PackConstPointerParameter<int64_t>(params, ParamType::TGLuint64ConstPointer, token);
1003 }
1004
1005 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)1006 void PackParameter<long *>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
1007 {
1008 PackMutablePointerParameter<int64_t>(params, ParamType::TGLint64Pointer, token);
1009 }
1010
1011 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)1012 void PackParameter<long>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
1013 {
1014 PackIntParameter<int64_t>(params, ParamType::TGLint64, token);
1015 }
1016
1017 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)1018 void PackParameter<unsigned long>(ParamBuffer ¶ms,
1019 const Token &token,
1020 const TraceStringMap &strings)
1021 {
1022 PackIntParameter<uint64_t>(params, ParamType::TGLuint64, token);
1023 }
1024 #endif // defined(ANGLE_PLATFORM_APPLE) || !defined(ANGLE_IS_64_BIT_CPU)
1025
GetResourceIDMapValue(ResourceIDType resourceIDType,GLuint key)1026 GLuint GetResourceIDMapValue(ResourceIDType resourceIDType, GLuint key)
1027 {
1028 switch (resourceIDType)
1029 {
1030 case ResourceIDType::Buffer:
1031 return gBufferMap[key];
1032 case ResourceIDType::FenceNV:
1033 return gFenceNVMap[key];
1034 case ResourceIDType::Framebuffer:
1035 return gFramebufferMap[key];
1036 case ResourceIDType::ProgramPipeline:
1037 return gProgramPipelineMap[key];
1038 case ResourceIDType::Query:
1039 return gQueryMap[key];
1040 case ResourceIDType::Renderbuffer:
1041 return gRenderbufferMap[key];
1042 case ResourceIDType::Sampler:
1043 return gSamplerMap[key];
1044 case ResourceIDType::Semaphore:
1045 return gSemaphoreMap[key];
1046 case ResourceIDType::ShaderProgram:
1047 return gShaderProgramMap[key];
1048 case ResourceIDType::Texture:
1049 return gTextureMap[key];
1050 case ResourceIDType::TransformFeedback:
1051 return gTransformFeedbackMap[key];
1052 case ResourceIDType::VertexArray:
1053 return gVertexArrayMap[key];
1054 default:
1055 printf("Incompatible resource ID type: %d\n", static_cast<int>(resourceIDType));
1056 UNREACHABLE();
1057 return 0;
1058 }
1059 }
1060
1061 } // namespace angle
1062
1063 extern "C" {
SetupReplay()1064 void SetupReplay()
1065 {
1066 angle::GetInterpreter().setupReplay();
1067 }
1068
ReplayFrame(uint32_t frameIndex)1069 void ReplayFrame(uint32_t frameIndex)
1070 {
1071 angle::GetInterpreter().replayFrame(frameIndex);
1072 }
1073
ResetReplay()1074 void ResetReplay()
1075 {
1076 angle::GetInterpreter().resetReplay();
1077 }
1078
GetSerializedContextState(uint32_t frameIndex)1079 const char *GetSerializedContextState(uint32_t frameIndex)
1080 {
1081 return angle::GetInterpreter().getSerializedContextState(frameIndex);
1082 }
1083 } // extern "C"
1084