X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=cli%2Fcli_trim.cpp;h=3302dffc98325fcb64876db0192d16367b6e60e0;hb=6338d4c26c8ba7afad886404921bf1988ced3822;hp=4cfe18f8fb769943fb1fcdd548a96363831a3935;hpb=ab82b3b949caad0be4e0759a0bce6fa9fd76d2f5;p=apitrace diff --git a/cli/cli_trim.cpp b/cli/cli_trim.cpp index 4cfe18f..3302dff 100644 --- a/cli/cli_trim.cpp +++ b/cli/cli_trim.cpp @@ -42,6 +42,7 @@ #include "trace_parser.hpp" #include "trace_writer.hpp" +#define MAX(a, b) ((a) > (b) ? (a) : (b)) #define STRNCMP_LITERAL(var, literal) strncmp((var), (literal), sizeof (literal) -1) static const char *synopsis = "Create a new trace by trimming an existing trace."; @@ -172,7 +173,9 @@ class TraceAnalyzer { bool transformFeedbackActive; bool framebufferObjectActive; bool insideBeginEnd; + GLuint insideNewEndList; GLuint activeProgram; + GLenum activeTextureUnit; /* Rendering often has no side effects, but it can in some cases, * (such as when transform feedback is active, or when rendering @@ -302,6 +305,11 @@ class TraceAnalyzer { return; } + if (strcmp(name, "glActiveTexture") == 0) { + activeTextureUnit = static_cast(call->arg(0).toSInt()); + return; + } + if (strcmp(name, "glBindTexture") == 0) { GLenum target; GLuint texture; @@ -338,6 +346,12 @@ class TraceAnalyzer { } return; } + + if (strcmp(name, "glNewList") == 0) { + GLuint list = call->arg(0).toUInt(); + + insideNewEndList = list; + } } void stateTrackPostCall(trace::Call *call) { @@ -364,12 +378,41 @@ class TraceAnalyzer { resources.erase("framebuffer"); return; } + + if (strcmp(name, "glEndList") == 0) { + insideNewEndList = 0; + } } void recordSideEffects(trace::Call *call) { 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; @@ -404,7 +447,7 @@ class TraceAnalyzer { target = static_cast(call->arg(0).toSInt()); texture = call->arg(1).toUInt(); - ss_target << "texture-target-" << target; + ss_target << "texture-unit-" << activeTextureUnit << "-target-" << target; ss_texture << "texture-" << texture; resources.erase(ss_target.str()); @@ -432,7 +475,7 @@ class TraceAnalyzer { GLenum target = static_cast(call->arg(0).toSInt()); - ss_target << "texture-target-" << target; + ss_target << "texture-unit-" << activeTextureUnit << "-target-" << target; ss_texture << "texture-" << texture_map[target]; /* The texture resource depends on this call and any calls @@ -459,7 +502,11 @@ class TraceAnalyzer { cap == GL_TEXTURE_3D || cap == GL_TEXTURE_CUBE_MAP) { - linkf("render-state", "texture-target-", cap); + std::stringstream ss; + + ss << "texture-unit-" << activeTextureUnit << "-target-" << cap; + + link("render-state", ss.str()); } provide("state", call->no); @@ -476,7 +523,11 @@ class TraceAnalyzer { cap == GL_TEXTURE_3D || cap == GL_TEXTURE_CUBE_MAP) { - unlinkf("render-state", "texture-target-", cap); + std::stringstream ss; + + ss << "texture-unit-" << activeTextureUnit << "-target-" << cap; + + unlink("render-state", ss.str()); } provide("state", call->no); @@ -595,6 +646,41 @@ class TraceAnalyzer { strcmp(call->sig->arg_names[0], "location") == 0) { providef("program-", activeProgram, call->no); + + /* We can't easily tell if this uniform is being used to + * associate a sampler in the shader with a texture + * unit. The conservative option is to assume that it is + * and create a link from the active program to any bound + * textures for the given unit number. + * + * FIXME: We should be doing the same thing for calls to + * glUniform1iv. */ + if (strcmp(name, "glUniform1i") == 0 || + strcmp(name, "glUniform1iARB") == 0) { + + GLint max_unit = MAX(GL_MAX_TEXTURE_COORDS, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS); + + GLint unit = call->arg(1).toSInt(); + std::stringstream ss_program; + std::stringstream ss_texture; + + if (unit < max_unit) { + + ss_program << "program-" << activeProgram; + + ss_texture << "texture-unit-" << GL_TEXTURE0 + unit << "-target-"; + + /* We don't know what target(s) might get bound to + * this texture unit, so conservatively link to + * all. Only bound textures will actually get inserted + * into the output call stream. */ + linkf(ss_program.str(), ss_texture.str(), GL_TEXTURE_1D); + linkf(ss_program.str(), ss_texture.str(), GL_TEXTURE_2D); + linkf(ss_program.str(), ss_texture.str(), GL_TEXTURE_3D); + linkf(ss_program.str(), ss_texture.str(), GL_TEXTURE_CUBE_MAP); + } + } + return; } @@ -667,7 +753,9 @@ class TraceAnalyzer { public: TraceAnalyzer(): transformFeedbackActive(false), framebufferObjectActive(false), - insideBeginEnd(false) + insideBeginEnd(false), + insideNewEndList(0), + activeTextureUnit(GL_TEXTURE0) {} ~TraceAnalyzer() {}