" --calls=CALLSET Include specified calls in the trimmed output.\n"
" --frames=FRAMESET Include specified frames in the trimmed output.\n"
" --deps Include additional calls to satisfy dependencies\n"
- " --no-deps Do not include calls from dependency analysis\n"
- " --prune Omit uninteresting calls from the trace output\n"
- " --no-prune Do not prune uninteresting calls from the trace.\n"
- " -x, --exact Trim exactly to calls specified in --calls/--frames\n"
+ " --no-deps Do not include any more calls than requestd\n"
+ " --prune Omit calls without side effects from the output\n"
+ " --no-prune Do not omit any requested calls\n"
+ " -a, --auto Trim automatically to calls specified in --calls/--frames\n"
+ " Equivalent to both --deps and --prune\n"
+ " --exact Trim to exactly the calls specified in --calls/--frames\n"
" Equivalent to both --no-deps and --no-prune\n"
" --print-callset Print the final set of calls included in output\n"
+ " --trim-spec=SPEC Only performing trimming as described in SPEC\n"
" --thread=THREAD_ID Only retain calls from specified thread\n"
" -o, --output=TRACE_FILE Output trace file\n"
;
"\n"
" --calls=CALLSET Include specified calls in the trimmed output.\n"
" --frames=FRAMESET Include specified frames in the trimmed output.\n"
- " Note that due to dependency analysis and pruning\n"
- " of uninteresting calls the resulting trace may\n"
- " include more and less calls than specified.\n"
- " See --no-deps, --no-prune, and --exact to change\n"
- " this behavior.\n"
"\n"
" --deps Perform dependency analysis and include dependent\n"
" calls as needed, (even if those calls were not\n"
" explicitly requested with --calls or --frames).\n"
- " This is the default behavior. See --no-deps and\n"
- " --exact to change the behavior.\n"
- "\n"
- " --no-deps Do not perform dependency analysis. In this mode\n"
- " the trimmed trace will never include calls from\n"
- " outside what is specified in --calls or --frames.\n"
+ " (On by default. See --no-deps or --exact)\n"
+ " --no-deps Do not perform dependency analysis. Output will\n"
+ " not include any additional calls beyond those\n"
+ " explicitly requested with --calls or --frames).\n"
"\n"
" --prune Omit calls with no side effects, even if the call\n"
" is within the range specified by --calls/--frames.\n"
- " This is the default behavior. See --no-prune.\n"
+ " (On by default. See --no-prune or --exact)\n"
"\n"
- " --no-prune Do not prune uninteresting calls from the trace.\n"
- " In this mode the trimmed trace will never omit\n"
- " any calls within the user-specified range.\n"
+ " --no-prune Never omit any calls from the range specified\n"
+ " --calls/--frames.\n"
+ "\n"
+ " -a, --auto Use dependency analysis and pruning\n"
+ " of uninteresting calls the resulting trace may\n"
+ " include more and less calls than specified.\n"
+ " This option is equivalent\n"
+ " to passing both --deps and --prune and is on by\n"
+ " default (see --no-deps, --no-prune and --exact)\n"
"\n"
- " -x, --exact Trim the trace to exactly the calls specified in\n"
- " --calls and --frames. This option is equivalent\n"
+ " --exact Trim output to exact the calls or frames\n"
+ " specified with --calls or --frames.\n"
+ " This option is equivalent\n"
" to passing both --no-deps and --no-prune.\n"
"\n"
" --print-callset Print to stdout the final set of calls included\n"
" in the trim output. This can be useful for\n"
- " debugging trim operations by using a modified\n"
- " callset on the command-line along with --exact.\n"
- " Use --calls=@<file> to read callset from a file.\n"
+ " tweaking the trimmed callset from --auto on the\n"
+ " command-line.\n"
+ " Use --calls=@FILE to read callset from a file.\n"
+ " --trim-spec=SPEC Specifies which classes of calls will be trimmed.\n"
+ " This option only has an effect if dependency\n"
+ " analysis is enabled. The argument is a comma-\n"
+ " separated list of names from the following:\n"
+ "\n"
+ " no-side-effects Calls with no side effects\n"
+ " textures Calls to setup unused textures\n"
+ " shaders Calls to setup unused shaders\n"
+ " drawing Calls that draw\n"
+ "\n"
+ " The default trim specification includes all of\n"
+ " the above, (as much as possible will be trimmed).\n"
"\n"
" --thread=THREAD_ID Only retain calls from specified thread\n"
"\n"
NO_PRUNE_OPT,
THREAD_OPT,
PRINT_CALLSET_OPT,
+ TRIM_SPEC_OPT,
+ EXACT_OPT
};
const static char *
-shortOptions = "ho:x";
+shortOptions = "aho:x";
const static struct option
longOptions[] = {
{"no-deps", no_argument, 0, NO_DEPS_OPT},
{"prune", no_argument, 0, PRUNE_OPT},
{"no-prune", no_argument, 0, NO_PRUNE_OPT},
- {"exact", no_argument, 0, 'x'},
+ {"auto", no_argument, 0, 'a'},
+ {"exact", no_argument, 0, EXACT_OPT},
{"thread", required_argument, 0, THREAD_OPT},
{"output", required_argument, 0, 'o'},
{"print-callset", no_argument, 0, PRINT_CALLSET_OPT},
+ {"trim-spec", required_argument, 0, TRIM_SPEC_OPT},
{0, 0, 0, 0}
};
/* Print resulting callset */
int print_callset;
+
+ /* What kind of trimming to perform. */
+ TrimFlags trim_flags;
};
static int
{
trace::ParseBookmark beginning;
trace::Parser p;
- TraceAnalyzer analyzer;
- std::set<unsigned> *required;
+ TraceAnalyzer analyzer(options->trim_flags);
+ trace::FastCallSet *required;
unsigned frame;
int call_range_first, call_range_last;
trace::Call *call;
while ((call = p.parse_call())) {
- /* There's no use doing any work past the last call or frame
+ /* There's no use doing any work past the last call and frame
* requested by the user. */
- if (call->no > options->calls.getLast() ||
- frame > options->frames.getLast()) {
-
+ if ((options->calls.empty() || call->no > options->calls.getLast()) &&
+ (options->frames.empty() || frame > options->frames.getLast())) {
+
delete call;
break;
}
goto NEXT;
}
- /* Also, prune if uninteresting (unless the user asked for no pruning. */
- if (options->prune_uninteresting && call->flags & trace::CALL_FLAG_UNINTERESTING) {
+ /* Also, prune if no side effects (unless the user asked for no pruning. */
+ if (options->prune_uninteresting && call->flags & trace::CALL_FLAG_NO_SIDE_EFFECTS) {
goto NEXT;
}
trace::Writer writer;
if (!writer.open(options->output.c_str())) {
- std::cerr << "error: failed to create " << filename << "\n";
+ std::cerr << "error: failed to create " << options->output << "\n";
return 1;
}
call_range_last = -1;
while ((call = p.parse_call())) {
- /* There's no use doing any work past the last call or frame
+ /* There's no use doing any work past the last call and frame
* requested by the user. */
- if (call->no > options->calls.getLast() ||
- frame > options->frames.getLast()) {
+ if ((options->calls.empty() || call->no > options->calls.getLast()) &&
+ (options->frames.empty() || frame > options->frames.getLast())) {
break;
}
- if (required->find(call->no) != required->end()) {
+ if (required->contains(call->no)) {
writer.writeCall(call);
if (options->print_callset) {
return 0;
}
+static int
+parse_trim_spec(const char *trim_spec, TrimFlags *flags)
+{
+ std::string spec(trim_spec), word;
+ size_t start = 0, comma = 0;
+ *flags = 0;
+
+ while (start < spec.size()) {
+ comma = spec.find(',', start);
+
+ if (comma == std::string::npos)
+ word = std::string(spec, start);
+ else
+ word = std::string(spec, start, comma - start);
+
+ if (strcmp(word.c_str(), "no-side-effects") == 0)
+ *flags |= TRIM_FLAG_NO_SIDE_EFFECTS;
+ else if (strcmp(word.c_str(), "textures") == 0)
+ *flags |= TRIM_FLAG_TEXTURES;
+ else if (strcmp(word.c_str(), "shaders") == 0)
+ *flags |= TRIM_FLAG_SHADERS;
+ else if (strcmp(word.c_str(), "drawing") == 0)
+ *flags |= TRIM_FLAG_DRAWING;
+ else {
+ return 1;
+ }
+
+ if (comma == std::string::npos)
+ break;
+
+ start = comma + 1;
+ }
+
+ return 0;
+}
+
static int
command(int argc, char *argv[])
{
options.output = "";
options.thread = -1;
options.print_callset = 0;
+ options.trim_flags = -1;
int opt;
while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) {
case NO_PRUNE_OPT:
options.prune_uninteresting = false;
break;
- case 'x':
+ case 'a':
+ options.dependency_analysis = true;
+ options.prune_uninteresting = true;
+ break;
+ case EXACT_OPT:
options.dependency_analysis = false;
options.prune_uninteresting = false;
break;
case PRINT_CALLSET_OPT:
options.print_callset = 1;
break;
+ case TRIM_SPEC_OPT:
+ if (parse_trim_spec(optarg, &options.trim_flags)) {
+ std::cerr << "error: illegal value for trim-spec: " << optarg << "\n";
+ std::cerr << "See \"apitrace help trim\" for help.\n";
+ return 1;
+ }
+ break;
default:
std::cerr << "error: unexpected option `" << opt << "`\n";
usage();