xref: /aosp_15_r20/external/angle/util/capture/trace_interpreter.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 &params, 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 &params, 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 &params, 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 &params, 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 &params, 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 &params, 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 &params, 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 &params, 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 &params,
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 &params, 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 &params,
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 &params, 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 &params, 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 &params,
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 &params,
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 &params,
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 &params,
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 &params,
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 &params,
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 &params,
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 &params, 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 &params, 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 &params, 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 &params,
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 &params, 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 &params,
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 &params,
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 &params,
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 &params,
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 &params,
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 &params,
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 &params,
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 &params, 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 &params,
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 &params, 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 &params,
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 &params,
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 &params,
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 &params,
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 &params,
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 &params,
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 &params,
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 &params,
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 &params,
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 &params, 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 &params, 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 &params,
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