[PATCH] glretrace: Create decorator parser class to allow variety of parsers.

Jon Ashburn jon at lunarg.com
Mon Aug 11 14:35:34 PDT 2014


The parser class is abstracted so that various looping parsers  can be added
as decorators.  Add the last frame looping parser as the first looping
parser.  Fix the singlethreaded case so it functions with the looping parser
just like the multithreaded case.
---
 common/trace_parser.cpp  | 38 +++++++++++++++++++++++++++++++
 common/trace_parser.hpp  | 50 +++++++++++++++++++++++++++++++++++++++--
 retrace/glretrace.py     |  2 +-
 retrace/retrace.hpp      |  2 +-
 retrace/retrace_main.cpp | 58 +++++++++++++++---------------------------------
 5 files changed, 106 insertions(+), 44 deletions(-)

diff --git a/common/trace_parser.cpp b/common/trace_parser.cpp
index a9cdd0f..f5c6f1d 100644
--- a/common/trace_parser.cpp
+++ b/common/trace_parser.cpp
@@ -36,6 +36,9 @@
 
 #define TRACE_VERBOSE 0
 
+bool loopOnFinish = false;
+bool loopContinuous = false;
+unsigned loopIter = 1;
 
 namespace trace {
 
@@ -1011,5 +1014,40 @@ inline void Parser::skip_byte(void) {
     file->skip(1);
 }
 
+void LastFrameLoopParser::bookmarkFrameStart(trace::Call *call) {
+    if (call->flags & trace::CALL_FLAG_END_FRAME) {
+        callEndsFrame = true;
+        parser->getBookmark(frameStart);
+    } else {
+        callEndsFrame = false;
+    }
+}
+
+Call *LastFrameLoopParser::parse_call(void) {
+    trace::Call *call;
+
+    call = parser->parse_call();
+
+     /* If the user wants to loop we need to get a bookmark target. We
+     * usually get this after replaying a call that ends a frame, but
+     * for a trace that has only one frame we need to get it at the
+     * beginning. */
+    if (firstCall) {
+        firstCall = false;
+        parser->getBookmark(lastFrameStart);
+    }
+    /* Restart last frame when looping is requested. */
+    if (!call  && (loopIter > 0  || loopContinuous)) {
+        parser->setBookmark(lastFrameStart);
+        call = parser->parse_call();
+        if (!loopContinuous)
+            loopIter--;
+    } else if (callEndsFrame) {
+        lastFrameStart = frameStart;
+        callEndsFrame = false;
+    }
+
+    return call;
+}
 
 } /* namespace trace */
diff --git a/common/trace_parser.hpp b/common/trace_parser.hpp
index 7bf0a7d..a86f35d 100644
--- a/common/trace_parser.hpp
+++ b/common/trace_parser.hpp
@@ -35,6 +35,9 @@
 #include "trace_model.hpp"
 #include "trace_api.hpp"
 
+extern bool loopOnFinish;
+extern bool loopContinuous;
+extern unsigned loopIter;
 
 namespace trace {
 
@@ -46,7 +49,21 @@ struct ParseBookmark
 };
 
 
-class Parser
+// Parser interface
+ class AbstractParser
+ {
+ public:
+    virtual ~AbstractParser() {}
+    virtual  Call *parse_call(void) = 0;
+    virtual void bookmarkFrameStart(trace::Call *call) = 0;
+    virtual void getBookmark(ParseBookmark &bookmark) = 0;
+    virtual void setBookmark(const ParseBookmark &bookmark) = 0;
+    virtual bool open(const char *filename) = 0;
+    virtual void close(void) = 0;
+    virtual unsigned long long get_version(void) = 0;
+ };
+
+class Parser: public AbstractParser
 {
 protected:
     File *file;
@@ -96,8 +113,8 @@ protected:
 
     unsigned next_call_no;
 
-public:
     unsigned long long version;
+public:
     API api;
 
     Parser();
@@ -121,6 +138,10 @@ public:
 
     void setBookmark(const ParseBookmark &bookmark);
 
+    void bookmarkFrameStart(trace::Call *call) {};
+
+    unsigned long long get_version() {return version;}
+
     int percentRead()
     {
         return file->percentRead();
@@ -217,6 +238,31 @@ protected:
     inline void skip_byte(void);
 };
 
+// Decorator for parser which loops
+class LastFrameLoopParser : public AbstractParser  {
+public:
+   LastFrameLoopParser(AbstractParser *p) {
+        parser = p;
+        callEndsFrame = false;
+        firstCall = true;
+    }
+    ~LastFrameLoopParser() { delete parser; }
+
+    Call *parse_call(void);
+    void bookmarkFrameStart(trace::Call *call);
+
+    //delegate to Parser
+    void getBookmark(ParseBookmark &bookmark) {parser->getBookmark(bookmark);}
+    void setBookmark(const ParseBookmark &bookmark) {parser->setBookmark(bookmark);}
+    bool open(const char *filename) {return parser->open(filename);}
+    void close(void) {parser->close();}
+    unsigned long long get_version(void) {return parser->get_version();}
+private:
+    AbstractParser *parser;
+    bool callEndsFrame, firstCall;
+    ParseBookmark frameStart;
+    ParseBookmark lastFrameStart;
+};
 
 } /* namespace trace */
 
diff --git a/retrace/glretrace.py b/retrace/glretrace.py
index c0d60c6..e23bfcc 100644
--- a/retrace/glretrace.py
+++ b/retrace/glretrace.py
@@ -191,7 +191,7 @@ class GlRetracer(Retracer):
         is_misc_draw = function.name in self.misc_draw_function_names
 
         if is_array_pointer or is_draw_array or is_draw_elements:
-            print '    if (retrace::parser.version < 1) {'
+            print '    if (retrace::parser->get_version() < 1) {'
 
             if is_array_pointer or is_draw_array:
                 print '        GLint _array_buffer = 0;'
diff --git a/retrace/retrace.hpp b/retrace/retrace.hpp
index 8f92d1c..c156215 100644
--- a/retrace/retrace.hpp
+++ b/retrace/retrace.hpp
@@ -51,7 +51,7 @@ namespace image {
 namespace retrace {
 
 
-extern trace::Parser parser;
+extern trace::AbstractParser *parser;
 extern trace::Profiler profiler;
 
 
diff --git a/retrace/retrace_main.cpp b/retrace/retrace_main.cpp
index dda1c2f..0db1b16 100644
--- a/retrace/retrace_main.cpp
+++ b/retrace/retrace_main.cpp
@@ -45,9 +45,6 @@
 
 
 static bool waitOnFinish = false;
-static bool loopOnFinish = false;
-static bool loopContinuos = false;
-
 static const char *snapshotPrefix = NULL;
 static enum {
     PNM_FMT,
@@ -57,7 +54,6 @@ static enum {
 
 static trace::CallSet snapshotFrequency;
 static unsigned snapshotInterval = 0;
-static trace::ParseBookmark lastFrameStart;
 
 static unsigned dumpStateCallNo = ~0;
 
@@ -66,8 +62,7 @@ retrace::Retracer retracer;
 
 namespace retrace {
 
-
-trace::Parser parser;
+trace::AbstractParser *parser;
 trace::Profiler profiler;
 
 
@@ -91,7 +86,6 @@ bool singleThread = false;
 
 unsigned frameNo = 0;
 unsigned callNo = 0;
-unsigned loopIter = 1;
 
 void
 frameComplete(trace::Call &call) {
@@ -326,32 +320,15 @@ public:
 
         /* Consume successive calls for this thread. */
         do {
-            bool callEndsFrame = false;
-            static trace::ParseBookmark frameStart;
 
             assert(call);
             assert(call->thread_id == leg);
 
-            if (loopOnFinish && call->flags & trace::CALL_FLAG_END_FRAME) {
-                callEndsFrame = true;
-                parser.getBookmark(frameStart);
-            }
+            parser->bookmarkFrameStart(call);
 
             retraceCall(call);
             delete call;
-            call = parser.parse_call();
-
-            /* Restart last frame if looping is requested. */
-            if (loopOnFinish) {
-                if (!call  && (loopIter > 0  || loopContinuos)) {
-                    parser.setBookmark(lastFrameStart);
-                    call = parser.parse_call();
-                    if (!loopContinuos)
-                        loopIter--;
-                } else if (callEndsFrame) {
-                    lastFrameStart = frameStart;
-                }
-            }
+            call = parser->parse_call();
 
         } while (call && call->thread_id == leg);
 
@@ -454,20 +431,12 @@ RelayRace::getRunner(unsigned leg) {
 void
 RelayRace::run(void) {
     trace::Call *call;
-    call = parser.parse_call();
+    call = parser->parse_call();
     if (!call) {
         /* Nothing to do */
         return;
     }
 
-    /* If the user wants to loop we need to get a bookmark target. We
-     * usually get this after replaying a call that ends a frame, but
-     * for a trace that has only one frame we need to get it at the
-     * beginning. */
-    if (loopOnFinish) {
-        parser.getBookmark(lastFrameStart);
-    }
-
     RelayRunner *foreRunner = getForeRunner();
     if (call->thread_id == 0) {
         /* We are the forerunner thread, so no need to pass baton */
@@ -531,10 +500,13 @@ mainLoop() {
 
     if (singleThread) {
         trace::Call *call;
-        while ((call = parser.parse_call())) {
+        call = parser->parse_call();
+        do {
+            parser->bookmarkFrameStart(call);
             retraceCall(call);
             delete call;
-        };
+            call = parser->parse_call();
+        } while (call);
     } else {
         RelayRace race;
         race.run();
@@ -756,7 +728,7 @@ int main(int argc, char **argv)
         case LOOP_OPT:
             loopIter = trace::intOption(optarg);
             if (loopIter == 0)
-                loopContinuos = true;
+                loopContinuous = true;
             loopOnFinish = true;
             break;
         case PGPU_OPT:
@@ -807,16 +779,22 @@ int main(int argc, char **argv)
 
     os::setExceptionCallback(exceptionCallback);
 
+    if (loopOnFinish)
+        parser = new trace::LastFrameLoopParser(new trace::Parser);
+    else
+        parser = new trace::Parser;
+
     for (i = optind; i < argc; ++i) {
-        if (!retrace::parser.open(argv[i])) {
+        if (!parser->open(argv[i])) {
             return 1;
         }
 
         retrace::mainLoop();
 
-        retrace::parser.close();
+        parser->close();
     }
     
+    delete parser;
     os::resetExceptionCallback();
 
     // XXX: X often hangs on XCloseDisplay
-- 
1.9.1



More information about the apitrace mailing list