]> git.cworth.org Git - apitrace/blobdiff - cli/trace_analyzer.cpp
Rename trim::CallSet to trace::FastCallSet
[apitrace] / cli / trace_analyzer.cpp
index afca8026f1a62e6465c847b2812ca6d4a1139cc9..f98eaa75abb16d0b7acd732563e1c7b699e4e8b2 100644 (file)
@@ -162,7 +162,7 @@ TraceAnalyzer::consume(std::string resource)
     resources.erase(resource);
 
     for (call = calls.begin(); call != calls.end(); call++) {
-        required.insert(*call);
+        required.add(*call);
     }
 }
 
@@ -263,48 +263,21 @@ TraceAnalyzer::stateTrackPostCall(trace::Call *call)
     }
 }
 
-void
-TraceAnalyzer::recordSideEffects(trace::Call *call)
+bool
+TraceAnalyzer::callHasNoSideEffects(trace::Call *call, const char *name)
 {
-
-    const char *name = call->name();
-
-    /* Handle display lists before any other processing. */
-
-    /* FIXME: If we encode the list of commands that are executed
-     * immediately (as opposed to those that are compiled into a
-     * display list) then we could generate a "display-list-X"
-     * resource just as we do for "texture-X" resources and only
-     * emit it in the trace if a glCallList(X) is emitted. For
-     * now, simply punt and include anything within glNewList and
-     * glEndList in the trim output. This guarantees that display
-     * lists will work, but does not trim out unused display
-     * lists. */
-    if (insideNewEndList != 0) {
-        provide("state", call->no);
-
-        /* Also, any texture bound inside a display list is
-         * conservatively considered required. */
-        if (strcmp(name, "glBindTexture") == 0) {
-            GLuint texture = call->arg(1).toUInt();
-
-            linkf("state", "texture-", texture);
-        }
-
-        return;
-    }
-
     /* If call is flagged as no side effects, then we are done here. */
     if (call->flags & trace::CALL_FLAG_NO_SIDE_EFFECTS) {
-        return;
+        return true;
     }
 
-    /* Similarly, swap-buffers calls don't have interesting side effects. */
-    if (call->flags & trace::CALL_FLAG_SWAP_RENDERTARGET &&
-        call->flags & trace::CALL_FLAG_END_FRAME) {
-        return;
-    }
+    /* Not known as a no-side-effect call. Return false for more analysis. */
+    return false;
+}
 
+bool
+TraceAnalyzer::recordTextureSideEffects(trace::Call *call, const char *name)
+{
     if (strcmp(name, "glGenTextures") == 0) {
         const trace::Array *textures = dynamic_cast<const trace::Array *>(&call->arg(1));
         size_t i;
@@ -316,7 +289,21 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
                 providef("texture-", texture, call->no);
             }
         }
-        return;
+        return true;
+    }
+
+    /* FIXME: When we start tracking framebuffer objects as their own
+     * resources, we will want to link the FBO to the given texture
+     * resource, (and to this call). For now, just link render state
+     * to the texture, and force this call to be required. */
+    if (strcmp(name, "glFramebufferTexture2D") == 0) {
+        GLuint texture;
+
+        texture = call->arg(3).toUInt();
+
+        linkf("render-state", "texture-", texture);
+
+        provide("state", call->no);
     }
 
     if (strcmp(name, "glBindTexture") == 0) {
@@ -351,10 +338,10 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
          * conservative and don't trim. */
         provide("state", call->no);
 
-        return;
+        return true;
     }
 
-    /* FIXME: Need to handle glMultTetImage and friends. */
+    /* FIXME: Need to handle glMultiTexImage and friends. */
     if (STRNCMP_LITERAL(name, "glTexImage") == 0 ||
         STRNCMP_LITERAL(name, "glTexSubImage") == 0 ||
         STRNCMP_LITERAL(name, "glCopyTexImage") == 0 ||
@@ -384,7 +371,7 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
             }
         }
 
-        return;
+        return true;
     }
 
     if (strcmp(name, "glEnable") == 0) {
@@ -405,7 +392,7 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
         }
 
         provide("state", call->no);
-        return;
+        return true;
     }
 
     if (strcmp(name, "glDisable") == 0) {
@@ -426,15 +413,22 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
         }
 
         provide("state", call->no);
-        return;
+        return true;
     }
 
+    /* No known texture-related side effects. Return false for more analysis. */
+    return false;
+}
+
+bool
+TraceAnalyzer::recordShaderSideEffects(trace::Call *call, const char *name)
+{
     if (strcmp(name, "glCreateShader") == 0 ||
         strcmp(name, "glCreateShaderObjectARB") == 0) {
 
         GLuint shader = call->ret->toUInt();
         providef("shader-", shader, call->no);
-        return;
+        return true;
     }
 
     if (strcmp(name, "glShaderSource") == 0 ||
@@ -446,7 +440,7 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
 
         GLuint shader = call->arg(0).toUInt();
         providef("shader-", shader, call->no);
-        return;
+        return true;
     }
 
     if (strcmp(name, "glCreateProgram") == 0 ||
@@ -454,7 +448,7 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
 
         GLuint program = call->ret->toUInt();
         providef("program-", program, call->no);
-        return;
+        return true;
     }
 
     if (strcmp(name, "glAttachShader") == 0 ||
@@ -472,7 +466,7 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
         link(ss_program.str(), ss_shader.str());
         provide(ss_program.str(), call->no);
 
-        return;
+        return true;
     }
 
     if (strcmp(name, "glDetachShader") == 0 ||
@@ -489,7 +483,7 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
 
         unlink(ss_program.str(), ss_shader.str());
 
-        return;
+        return true;
     }
 
     if (strcmp(name, "glUseProgram") == 0 ||
@@ -515,7 +509,7 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
             provide(ss.str(), call->no);
         }
 
-        return;
+        return true;
     }
 
     if (strcmp(name, "glGetUniformLocation") == 0 ||
@@ -531,7 +525,7 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
 
         providef("program-", program, call->no);
 
-        return;
+        return true;
     }
 
     /* For any call that accepts 'location' as its first argument,
@@ -576,7 +570,7 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
             }
         }
 
-        return;
+        return true;
     }
 
     /* FIXME: We cut a huge swath by assuming that any unhandled
@@ -596,9 +590,16 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
 
         GLuint program = call->arg(0).toUInt();
         providef("program-", program, call->no);
-        return;
+        return true;
     }
 
+    /* No known shader-related side effects. Return false for more analysis. */
+    return false;
+}
+
+bool
+TraceAnalyzer::recordDrawingSideEffects(trace::Call *call, const char *name)
+{
     /* Handle all rendering operations, (even though only glEnd is
      * flagged as a rendering operation we treat everything from
      * glBegin through glEnd as a rendering operation). */
@@ -625,9 +626,77 @@ TraceAnalyzer::recordSideEffects(trace::Call *call)
             }
         }
 
+        return true;
+    }
+
+    /* Though it's not flagged as a "RENDER" operation, we also want
+     * to trim swapbuffers calls when trimming drawing operations. */
+    if (call->flags & trace::CALL_FLAG_SWAP_RENDERTARGET &&
+        call->flags & trace::CALL_FLAG_END_FRAME) {
+        return true;
+    }
+
+    /* No known drawing-related side effects. Return false for more analysis. */
+    return false;
+}
+
+void
+TraceAnalyzer::recordSideEffects(trace::Call *call)
+{
+
+    const char *name = call->name();
+
+    /* FIXME: If we encode the list of commands that are executed
+     * immediately (as opposed to those that are compiled into a
+     * display list) then we could generate a "display-list-X"
+     * resource just as we do for "texture-X" resources and only
+     * emit it in the trace if a glCallList(X) is emitted. For
+     * now, simply punt and include anything within glNewList and
+     * glEndList in the trim output. This guarantees that display
+     * lists will work, but does not trim out unused display
+     * lists. */
+    if (insideNewEndList != 0) {
+        provide("state", call->no);
+
+        /* Also, any texture bound inside a display list is
+         * conservatively considered required. */
+        if (strcmp(name, "glBindTexture") == 0) {
+            GLuint texture = call->arg(1).toUInt();
+
+            linkf("state", "texture-", texture);
+        }
+
         return;
     }
 
+    if (trimFlags & TRIM_FLAG_NO_SIDE_EFFECTS) {
+
+        if (callHasNoSideEffects(call, name)) {
+            return;
+        }
+    }
+
+    if (trimFlags & TRIM_FLAG_TEXTURES) {
+        
+        if (recordTextureSideEffects(call, name)) {
+            return;
+        }
+    }
+
+    if (trimFlags & TRIM_FLAG_SHADERS) {
+
+        if (recordShaderSideEffects(call, name)) {
+            return;
+        }
+    }
+
+    if (trimFlags & TRIM_FLAG_DRAWING) {
+
+        if (recordDrawingSideEffects(call, name)) {
+            return;
+        }
+    }
+
     /* By default, assume this call affects the state somehow. */
     resources["state"].insert(call->no);
 }
@@ -646,11 +715,13 @@ TraceAnalyzer::requireDependencies(trace::Call *call)
     consume("state");
 }
 
-TraceAnalyzer::TraceAnalyzer(): transformFeedbackActive(false),
-                               framebufferObjectActive(false),
-                               insideBeginEnd(false),
-                               insideNewEndList(0),
-                               activeTextureUnit(GL_TEXTURE0)
+TraceAnalyzer::TraceAnalyzer(TrimFlags trimFlagsOpt = -1):
+    transformFeedbackActive(false),
+    framebufferObjectActive(false),
+    insideBeginEnd(false),
+    insideNewEndList(0),
+    activeTextureUnit(GL_TEXTURE0),
+    trimFlags(trimFlagsOpt)
 {
     /* Nothing needed. */
 }
@@ -683,13 +754,13 @@ TraceAnalyzer::require(trace::Call *call)
     requireDependencies(call);
 
     /* Then insert this call itself. */
-    required.insert(call->no);
+    required.add(call->no);
 }
 
 /* Return a set of all the required calls, (both those calls added
  * explicitly with require() and those implicitly depended
  * upon. */
-std::set<unsigned>  *
+trace::FastCallSet *
 TraceAnalyzer::get_required(void)
 {
     return &required;