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 const char *getSerializedContextState(uint32_t frameIndex);
520
521 private:
522 void runTraceFunction(const char *name) const;
523 void parseTraceUncompressed();
524 void parseTraceGz();
525
526 TraceFunctionMap mTraceFunctions;
527 TraceStringMap mTraceStrings;
528 bool mVerboseLogging = true;
529 };
530
replayFrame(uint32_t frameIndex)531 void TraceInterpreter::replayFrame(uint32_t frameIndex)
532 {
533 char funcName[kMaxTokenSize];
534 snprintf(funcName, kMaxTokenSize, "ReplayFrame%u", frameIndex);
535 runTraceFunction(funcName);
536 }
537
parseTraceUncompressed()538 void TraceInterpreter::parseTraceUncompressed()
539 {
540 for (const std::string &file : gTraceInfo.traceFiles)
541 {
542 if (!ShouldParseFile(file))
543 {
544 if (mVerboseLogging)
545 {
546 printf("Skipping function parsing for %s.\n", file.c_str());
547 }
548 continue;
549 }
550
551 if (mVerboseLogging)
552 {
553 printf("Parsing functions from %s\n", file.c_str());
554 }
555 std::stringstream pathStream;
556 pathStream << gBinaryDataDir << GetPathSeparator() << file;
557 std::string path = pathStream.str();
558
559 std::string fileData;
560 if (!ReadFileToString(path, &fileData))
561 {
562 UNREACHABLE();
563 }
564
565 Parser parser(fileData, mTraceFunctions, mTraceStrings, mVerboseLogging);
566 parser.parse();
567 }
568 }
569
parseTraceGz()570 void TraceInterpreter::parseTraceGz()
571 {
572 if (mVerboseLogging)
573 {
574 printf("Parsing functions from %s\n", gTraceGzPath.c_str());
575 }
576
577 FILE *fp = fopen(gTraceGzPath.c_str(), "rb");
578 if (fp == 0)
579 {
580 printf("Error loading trace (gz) from: %s\n", gTraceGzPath.c_str());
581 exit(1);
582 }
583
584 fseek(fp, 0, SEEK_END);
585 long size = ftell(fp);
586 fseek(fp, 0, SEEK_SET);
587
588 std::vector<uint8_t> compressedData(size);
589 (void)fread(compressedData.data(), 1, size, fp);
590
591 uint32_t uncompressedSize =
592 zlib_internal::GetGzipUncompressedSize(compressedData.data(), compressedData.size());
593
594 std::string uncompressedData(uncompressedSize, 0);
595 uLong destLen = uncompressedSize;
596 int zResult = zlib_internal::GzipUncompressHelper((uint8_t *)uncompressedData.data(), &destLen,
597 compressedData.data(),
598 static_cast<uLong>(compressedData.size()));
599
600 if (zResult != Z_OK)
601 {
602 printf("Failure to decompress gz trace: %s\n", gTraceGzPath.c_str());
603 exit(1);
604 }
605
606 Parser parser(uncompressedData, mTraceFunctions, mTraceStrings, mVerboseLogging);
607 parser.parse();
608 }
609
setupReplay()610 void TraceInterpreter::setupReplay()
611 {
612 if (!gTraceGzPath.empty())
613 {
614 parseTraceGz();
615 }
616 else
617 {
618 parseTraceUncompressed();
619 }
620
621 if (mTraceFunctions.count("SetupReplay") == 0)
622 {
623 printf("Did not find a SetupReplay function to run among %zu parsed functions.\n",
624 mTraceFunctions.size());
625 exit(1);
626 }
627
628 runTraceFunction("SetupReplay");
629 }
630
resetReplay()631 void TraceInterpreter::resetReplay()
632 {
633 runTraceFunction("ResetReplay");
634 }
635
getSerializedContextState(uint32_t frameIndex)636 const char *TraceInterpreter::getSerializedContextState(uint32_t frameIndex)
637 {
638 // TODO: Necessary for complete self-testing. http://anglebug.com/42266250
639 UNREACHABLE();
640 return nullptr;
641 }
642
runTraceFunction(const char * name) const643 void TraceInterpreter::runTraceFunction(const char *name) const
644 {
645 auto iter = mTraceFunctions.find(name);
646 if (iter == mTraceFunctions.end())
647 {
648 printf("Cannot find function: %s\n", name);
649 UNREACHABLE();
650 }
651 const TraceFunction &func = iter->second;
652 ReplayTraceFunction(func, mTraceFunctions);
653 }
654
GetInterpreter()655 TraceInterpreter &GetInterpreter()
656 {
657 static angle::base::NoDestructor<std::unique_ptr<TraceInterpreter>> sTraceInterpreter(
658 new TraceInterpreter());
659 return *sTraceInterpreter.get()->get();
660 }
661 } // anonymous namespace
662
663 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)664 void PackParameter<uint32_t>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
665 {
666 if (token[0] == 'g')
667 {
668 PackResourceID(params, token);
669 }
670 else
671 {
672 PackIntParameter<uint32_t>(params, ParamType::TGLuint, token);
673 }
674 }
675
676 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)677 void PackParameter<int32_t>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
678 {
679 if (BeginsWith(token, "gUniformLocations"))
680 {
681 const char *start = strrchr(token, '[');
682 ASSERT(start != nullptr && EndsWith(token, "]"));
683 int32_t value = atoi(start + 1);
684 gl::UniformLocation loc = {value};
685 params.addUnnamedParam(ParamType::TUniformLocation, loc);
686 }
687 else
688 {
689 PackIntParameter<int32_t>(params, ParamType::TGLint, token);
690 }
691 }
692
693 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)694 void PackParameter<void *>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
695 {
696 void *value = 0;
697 params.addUnnamedParam(ParamType::TvoidPointer, value);
698 }
699
700 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)701 void PackParameter<const int32_t *>(ParamBuffer ¶ms,
702 const Token &token,
703 const TraceStringMap &strings)
704 {
705 PackConstPointerParameter<int32_t>(params, ParamType::TGLintConstPointer, token);
706 }
707
708 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)709 void PackParameter<void **>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
710 {
711 UNREACHABLE();
712 }
713
714 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)715 void PackParameter<int32_t *>(ParamBuffer ¶ms,
716 const Token &token,
717 const TraceStringMap &strings)
718 {
719 PackMutablePointerParameter<int32_t>(params, ParamType::TGLintPointer, token);
720 }
721
722 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)723 void PackParameter<uint64_t>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
724 {
725 params.addUnnamedParam(ParamType::TGLuint64,
726 static_cast<GLuint64>(std::strtoull(token, nullptr, 10)));
727 }
728
729 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)730 void PackParameter<int64_t>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
731 {
732 params.addUnnamedParam(ParamType::TGLint64,
733 static_cast<GLint64>(std::strtoll(token, nullptr, 10)));
734 }
735
736 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)737 void PackParameter<const int64_t *>(ParamBuffer ¶ms,
738 const Token &token,
739 const TraceStringMap &strings)
740 {
741 UNREACHABLE();
742 }
743
744 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)745 void PackParameter<int64_t *>(ParamBuffer ¶ms,
746 const Token &token,
747 const TraceStringMap &strings)
748 {
749 UNREACHABLE();
750 }
751
752 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)753 void PackParameter<uint64_t *>(ParamBuffer ¶ms,
754 const Token &token,
755 const TraceStringMap &strings)
756 {
757 UNREACHABLE();
758 }
759
760 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)761 void PackParameter<const char *>(ParamBuffer ¶ms,
762 const Token &token,
763 const TraceStringMap &strings)
764 {
765 if (token[0] == '"')
766 {
767 ASSERT(EndsWith(token, "\""));
768
769 ParamCapture param(params.getNextParamName(), ParamType::TGLcharConstPointer);
770 std::vector<uint8_t> data(&token[1], &token[strlen(token) - 1]);
771 data.push_back(0);
772 param.data.push_back(std::move(data));
773 param.value.GLcharConstPointerVal = reinterpret_cast<const char *>(param.data[0].data());
774 params.addParam(std::move(param));
775 }
776 else
777 {
778 PackConstPointerParameter<char>(params, ParamType::TGLcharConstPointer, token);
779 }
780 }
781
782 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)783 void PackParameter<const void *>(ParamBuffer ¶ms,
784 const Token &token,
785 const TraceStringMap &strings)
786 {
787 PackConstPointerParameter<void>(params, ParamType::TvoidConstPointer, token);
788 }
789
790 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)791 void PackParameter<uint32_t *>(ParamBuffer ¶ms,
792 const Token &token,
793 const TraceStringMap &strings)
794 {
795 PackMutablePointerParameter<uint32_t>(params, ParamType::TGLuintPointer, token);
796 }
797
798 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)799 void PackParameter<const uint32_t *>(ParamBuffer ¶ms,
800 const Token &token,
801 const TraceStringMap &strings)
802 {
803 PackConstPointerParameter<uint32_t>(params, ParamType::TGLuintConstPointer, token);
804 }
805
806 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)807 void PackParameter<float>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
808 {
809 params.addUnnamedParam(ParamType::TGLfloat, std::stof(token));
810 }
811
812 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)813 void PackParameter<uint8_t>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
814 {
815 PackIntParameter<uint8_t>(params, ParamType::TGLubyte, token);
816 }
817
818 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)819 void PackParameter<float *>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
820 {
821 PackMutablePointerParameter<float>(params, ParamType::TGLfloatPointer, token);
822 }
823
824 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)825 void PackParameter<const float *>(ParamBuffer ¶ms,
826 const Token &token,
827 const TraceStringMap &strings)
828 {
829 PackConstPointerParameter<float>(params, ParamType::TGLfloatConstPointer, token);
830 }
831
832 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)833 void PackParameter<GLsync>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
834 {
835 PackResourceID(params, token);
836 }
837
838 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)839 void PackParameter<const char *const *>(ParamBuffer ¶ms,
840 const Token &token,
841 const TraceStringMap &strings)
842 {
843 // Find the string that corresponds to "token". Currently we only support string arrays.
844 auto iter = strings.find(token);
845 if (iter == strings.end())
846 {
847 printf("Could not find string: %s\n", token);
848 UNREACHABLE();
849 }
850 const TraceString &traceStr = iter->second;
851 params.addUnnamedParam(ParamType::TGLcharConstPointerPointer, traceStr.pointers.data());
852 }
853
854 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)855 void PackParameter<const char **>(ParamBuffer ¶ms,
856 const Token &token,
857 const TraceStringMap &strings)
858 {
859 UNREACHABLE();
860 }
861
862 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)863 void PackParameter<GLDEBUGPROCKHR>(ParamBuffer ¶ms,
864 const Token &token,
865 const TraceStringMap &strings)
866 {
867 UNREACHABLE();
868 }
869
870 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)871 void PackParameter<EGLDEBUGPROCKHR>(ParamBuffer ¶ms,
872 const Token &token,
873 const TraceStringMap &strings)
874 {
875 UNREACHABLE();
876 }
877
878 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)879 void PackParameter<const struct AHardwareBuffer *>(ParamBuffer ¶ms,
880 const Token &token,
881 const TraceStringMap &strings)
882 {
883 UNREACHABLE();
884 }
885
886 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)887 void PackParameter<EGLSetBlobFuncANDROID>(ParamBuffer ¶ms,
888 const Token &token,
889 const TraceStringMap &strings)
890 {
891 UNREACHABLE();
892 }
893
894 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)895 void PackParameter<EGLGetBlobFuncANDROID>(ParamBuffer ¶ms,
896 const Token &token,
897 const TraceStringMap &strings)
898 {
899 UNREACHABLE();
900 }
901
902 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)903 void PackParameter<int16_t>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
904 {
905 PackIntParameter<int16_t>(params, ParamType::TGLshort, token);
906 }
907
908 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)909 void PackParameter<const int16_t *>(ParamBuffer ¶ms,
910 const Token &token,
911 const TraceStringMap &strings)
912 {
913 PackConstPointerParameter<int16_t>(params, ParamType::TGLshortConstPointer, token);
914 }
915
916 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)917 void PackParameter<char *>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
918 {
919 UNREACHABLE();
920 }
921
922 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)923 void PackParameter<unsigned char *>(ParamBuffer ¶ms,
924 const Token &token,
925 const TraceStringMap &strings)
926 {
927 PackMutablePointerParameter<GLubyte>(params, ParamType::TGLubytePointer, token);
928 }
929
930 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)931 void PackParameter<const void *const *>(ParamBuffer ¶ms,
932 const Token &token,
933 const TraceStringMap &strings)
934 {
935 UNREACHABLE();
936 }
937
938 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)939 void PackParameter<const uint64_t *>(ParamBuffer ¶ms,
940 const Token &token,
941 const TraceStringMap &strings)
942 {
943 UNREACHABLE();
944 }
945
946 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)947 void PackParameter<GLGETBLOBPROCANGLE>(ParamBuffer ¶ms,
948 const Token &token,
949 const TraceStringMap &strings)
950 {
951 UNREACHABLE();
952 }
953
954 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)955 void PackParameter<GLSETBLOBPROCANGLE>(ParamBuffer ¶ms,
956 const Token &token,
957 const TraceStringMap &strings)
958 {
959 UNREACHABLE();
960 }
961
962 #if defined(ANGLE_PLATFORM_WINDOWS)
963 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)964 void PackParameter<EGLNativeDisplayType>(ParamBuffer ¶ms,
965 const Token &token,
966 const TraceStringMap &strings)
967 {
968 UNREACHABLE();
969 }
970 #endif // defined(ANGLE_PLATFORM_WINDOWS)
971
972 #if defined(ANGLE_PLATFORM_WINDOWS) || defined(ANGLE_PLATFORM_ANDROID)
973 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)974 void PackParameter<EGLNativeWindowType>(ParamBuffer ¶ms,
975 const Token &token,
976 const TraceStringMap &strings)
977 {
978 UNREACHABLE();
979 }
980
981 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)982 void PackParameter<EGLNativePixmapType>(ParamBuffer ¶ms,
983 const Token &token,
984 const TraceStringMap &strings)
985 {
986 UNREACHABLE();
987 }
988 #endif // defined(ANGLE_PLATFORM_WINDOWS) || defined(ANGLE_PLATFORM_ANDROID)
989
990 #if defined(ANGLE_PLATFORM_APPLE) || !defined(ANGLE_IS_64_BIT_CPU)
991 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)992 void PackParameter<const long *>(ParamBuffer ¶ms,
993 const Token &token,
994 const TraceStringMap &strings)
995 {
996 PackConstPointerParameter<int64_t>(params, ParamType::TGLuint64ConstPointer, token);
997 }
998
999 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)1000 void PackParameter<long *>(ParamBuffer ¶ms, const Token &token, const TraceStringMap &strings)
1001 {
1002 PackMutablePointerParameter<int64_t>(params, ParamType::TGLint64Pointer, 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 PackIntParameter<int64_t>(params, ParamType::TGLint64, token);
1009 }
1010
1011 template <>
PackParameter(ParamBuffer & params,const Token & token,const TraceStringMap & strings)1012 void PackParameter<unsigned long>(ParamBuffer ¶ms,
1013 const Token &token,
1014 const TraceStringMap &strings)
1015 {
1016 PackIntParameter<uint64_t>(params, ParamType::TGLuint64, token);
1017 }
1018 #endif // defined(ANGLE_PLATFORM_APPLE) || !defined(ANGLE_IS_64_BIT_CPU)
1019
GetResourceIDMapValue(ResourceIDType resourceIDType,GLuint key)1020 GLuint GetResourceIDMapValue(ResourceIDType resourceIDType, GLuint key)
1021 {
1022 switch (resourceIDType)
1023 {
1024 case ResourceIDType::Buffer:
1025 return gBufferMap[key];
1026 case ResourceIDType::FenceNV:
1027 return gFenceNVMap[key];
1028 case ResourceIDType::Framebuffer:
1029 return gFramebufferMap[key];
1030 case ResourceIDType::ProgramPipeline:
1031 return gProgramPipelineMap[key];
1032 case ResourceIDType::Query:
1033 return gQueryMap[key];
1034 case ResourceIDType::Renderbuffer:
1035 return gRenderbufferMap[key];
1036 case ResourceIDType::Sampler:
1037 return gSamplerMap[key];
1038 case ResourceIDType::Semaphore:
1039 return gSemaphoreMap[key];
1040 case ResourceIDType::ShaderProgram:
1041 return gShaderProgramMap[key];
1042 case ResourceIDType::Texture:
1043 return gTextureMap[key];
1044 case ResourceIDType::TransformFeedback:
1045 return gTransformFeedbackMap[key];
1046 case ResourceIDType::VertexArray:
1047 return gVertexArrayMap[key];
1048 default:
1049 printf("Incompatible resource ID type: %d\n", static_cast<int>(resourceIDType));
1050 UNREACHABLE();
1051 return 0;
1052 }
1053 }
1054
1055 } // namespace angle
1056
1057 extern "C" {
SetupReplay()1058 void SetupReplay()
1059 {
1060 angle::GetInterpreter().setupReplay();
1061 }
1062
ReplayFrame(uint32_t frameIndex)1063 void ReplayFrame(uint32_t frameIndex)
1064 {
1065 angle::GetInterpreter().replayFrame(frameIndex);
1066 }
1067
ResetReplay()1068 void ResetReplay()
1069 {
1070 angle::GetInterpreter().resetReplay();
1071 }
1072
GetSerializedContextState(uint32_t frameIndex)1073 const char *GetSerializedContextState(uint32_t frameIndex)
1074 {
1075 return angle::GetInterpreter().getSerializedContextState(frameIndex);
1076 }
1077 } // extern "C"
1078