/**************************************************************************
*
* Copyright 2011 Jose Fonseca
+ * Copyright (C) 2013 Intel Corporation. All rights reversed.
+ * Author: Shuang He <shuang.he@intel.com>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
#include "image.hpp"
#include "trace_callset.hpp"
#include "trace_dump.hpp"
+#include "trace_option.hpp"
#include "retrace.hpp"
bool debug = true;
bool dumpingState = false;
+Driver driver = DRIVER_DEFAULT;
+const char *driverModule = NULL;
+
bool doubleBuffer = true;
bool coreProfile = false;
bool profilingGpuTimes = false;
bool profilingCpuTimes = false;
bool profilingPixelsDrawn = false;
+bool profilingMemoryUsage = false;
+bool useCallNos = true;
+bool singleThread = false;
unsigned frameNo = 0;
unsigned callNo = 0;
}
+static Dumper defaultDumper;
+
+Dumper *dumper = &defaultDumper;
+
+
/**
* Take/compare snapshots.
*/
static void
takeSnapshot(unsigned call_no) {
+ static unsigned snapshot_no = 0;
+
assert(snapshotPrefix || comparePrefix);
image::Image *ref = NULL;
}
}
- image::Image *src = getSnapshot();
+ image::Image *src = dumper->getSnapshot();
if (!src) {
+ std::cout << "Failed to get snapshot\n";
return;
}
if (snapshotPrefix) {
if (snapshotPrefix[0] == '-' && snapshotPrefix[1] == 0) {
char comment[21];
- snprintf(comment, sizeof comment, "%u", call_no);
+ snprintf(comment, sizeof comment, "%u",
+ useCallNos ? call_no : snapshot_no);
src->writePNM(std::cout, comment);
} else {
- os::String filename = os::String::format("%s%010u.png", snapshotPrefix, call_no);
+ os::String filename = os::String::format("%s%010u.png",
+ snapshotPrefix,
+ useCallNos ? call_no : snapshot_no);
if (src->writePNG(filename) && retrace::verbosity >= 0) {
std::cout << "Wrote " << filename << "\n";
}
delete src;
+ snapshot_no++;
+
return;
}
takeSnapshot(call->no);
if (call->no >= dumpStateCallNo &&
- dumpState(std::cout)) {
+ dumper->dumpState(std::cout)) {
exit(0);
}
}
startTime = os::getTime();
- RelayRace race;
- race.run();
+ if (singleThread) {
+ trace::Call *call;
+ while ((call = parser.parse_call())) {
+ retraceCall(call);
+ delete call;
+ };
+ flushRendering();
+ } else {
+ RelayRace race;
+ race.run();
+ }
long long endTime = os::getTime();
float timeInterval = (endTime - startTime) * (1.0 / os::timeFrequency);
" --pcpu cpu profiling (cpu times per call)\n"
" --pgpu gpu profiling (gpu times per draw call)\n"
" --ppd pixels drawn profiling (pixels drawn per draw call)\n"
+ " --pmem memory usage profiling (vsize rss per call)\n"
" -c, --compare=PREFIX compare against snapshots with given PREFIX\n"
" -C, --calls=CALLSET calls to compare (default is every frame)\n"
+ " --call-nos[=BOOL] use call numbers in snapshot filenames\n"
" --core use core profile\n"
" --db use a double buffer visual (default)\n"
+ " --driver=DRIVER force driver type (`hw`, `sw`, `ref`, `null`, or driver module name)\n"
" --sb use a single buffer visual\n"
" -s, --snapshot-prefix=PREFIX take snapshots; `-` for PNM stdout output\n"
" -S, --snapshot=CALLSET calls to snapshot (default is every frame)\n"
" -v, --verbose increase output verbosity\n"
" -D, --dump-state=CALL dump state at specific call no\n"
- " -w, --wait waitOnFinish on final frame\n";
+ " -w, --wait waitOnFinish on final frame\n"
+ " --singlethread use a single thread to replay command stream\n";
}
enum {
- CORE_OPT = CHAR_MAX + 1,
+ CALL_NOS_OPT = CHAR_MAX + 1,
+ CORE_OPT,
DB_OPT,
+ DRIVER_OPT,
PCPU_OPT,
PGPU_OPT,
PPD_OPT,
+ PMEM_OPT,
SB_OPT,
+ SINGLETHREAD_OPT,
};
const static char *
const static struct option
longOptions[] = {
{"benchmark", no_argument, 0, 'b'},
+ {"call-nos", optional_argument, 0, CALL_NOS_OPT },
{"calls", required_argument, 0, 'C'},
{"compare", required_argument, 0, 'c'},
{"core", no_argument, 0, CORE_OPT},
{"db", no_argument, 0, DB_OPT},
+ {"driver", required_argument, 0, DRIVER_OPT},
{"dump-state", required_argument, 0, 'D'},
{"help", no_argument, 0, 'h'},
{"pcpu", no_argument, 0, PCPU_OPT},
{"pgpu", no_argument, 0, PGPU_OPT},
{"ppd", no_argument, 0, PPD_OPT},
+ {"pmem", no_argument, 0, PMEM_OPT},
{"sb", no_argument, 0, SB_OPT},
{"snapshot-prefix", required_argument, 0, 's'},
{"snapshot", required_argument, 0, 'S'},
{"verbose", no_argument, 0, 'v'},
{"wait", no_argument, 0, 'w'},
+ {"singlethread", no_argument, 0, SINGLETHREAD_OPT},
{0, 0, 0, 0}
};
+
+static void exceptionCallback(void)
+{
+ std::cerr << retrace::callNo << ": error: caught an unhandled exception\n";
+}
+
+
extern "C"
int main(int argc, char **argv)
{
retrace::debug = false;
retrace::verbosity = -1;
break;
+ case CALL_NOS_OPT:
+ useCallNos = trace::boolOption(optarg);
+ break;
case 'c':
comparePrefix = optarg;
if (compareFrequency.empty()) {
case DB_OPT:
retrace::doubleBuffer = true;
break;
+ case DRIVER_OPT:
+ if (strcasecmp(optarg, "hw") == 0) {
+ driver = DRIVER_HARDWARE;
+ } else if (strcasecmp(optarg, "sw") == 0) {
+ driver = DRIVER_SOFTWARE;
+ } else if (strcasecmp(optarg, "ref") == 0) {
+ driver = DRIVER_REFERENCE;
+ } else if (strcasecmp(optarg, "null") == 0) {
+ driver = DRIVER_NULL;
+ } else {
+ driver = DRIVER_MODULE;
+ driverModule = optarg;
+ }
+ break;
case SB_OPT:
retrace::doubleBuffer = false;
break;
+ case SINGLETHREAD_OPT:
+ retrace::singleThread = true;
+ break;
case 's':
snapshotPrefix = optarg;
if (snapshotFrequency.empty()) {
retrace::profilingPixelsDrawn = true;
break;
+ case PMEM_OPT:
+ retrace::debug = false;
+ retrace::profiling = true;
+ retrace::verbosity = -1;
+
+ retrace::profilingMemoryUsage = true;
+ break;
default:
std::cerr << "error: unknown option " << opt << "\n";
usage(argv[0]);
retrace::setUp();
if (retrace::profiling) {
- retrace::profiler.setup(retrace::profilingCpuTimes, retrace::profilingGpuTimes, retrace::profilingPixelsDrawn);
+ retrace::profiler.setup(retrace::profilingCpuTimes, retrace::profilingGpuTimes, retrace::profilingPixelsDrawn, retrace::profilingMemoryUsage);
}
+ os::setExceptionCallback(exceptionCallback);
+
for (i = optind; i < argc; ++i) {
if (!retrace::parser.open(argv[i])) {
- std::cerr << "error: failed to open " << argv[i] << "\n";
return 1;
}
retrace::parser.close();
}
+
+ os::resetExceptionCallback();
// XXX: X often hangs on XCloseDisplay
//retrace::cleanUp();