X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=retrace%2Fretrace_main.cpp;h=5e31c020490ab86beccb3635914fa82d9e83d479;hb=386d29d3e0c3abbb4c2913b6097319071738e762;hp=7cc3fcab869bf0e5935d504838275de4909bd940;hpb=4f9982f5ec3dccae65d5a49dfd5a81b9737d90cd;p=apitrace diff --git a/retrace/retrace_main.cpp b/retrace/retrace_main.cpp index 7cc3fca..5e31c02 100644 --- a/retrace/retrace_main.cpp +++ b/retrace/retrace_main.cpp @@ -42,11 +42,18 @@ static bool waitOnFinish = false; +static bool loopOnFinish = false; static const char *comparePrefix = NULL; static const char *snapshotPrefix = NULL; +static enum { + PNM_FMT, + RAW_RGB +} snapshotFormat = PNM_FMT; + static trace::CallSet snapshotFrequency; static trace::CallSet compareFrequency; +static trace::ParseBookmark lastFrameStart; static unsigned dumpStateCallNo = ~0; @@ -76,6 +83,7 @@ bool profilingCpuTimes = false; bool profilingPixelsDrawn = false; bool profilingMemoryUsage = false; bool useCallNos = true; +bool singleThread = false; unsigned frameNo = 0; unsigned callNo = 0; @@ -116,7 +124,7 @@ takeSnapshot(unsigned call_no) { image::Image *src = dumper->getSnapshot(); if (!src) { - std::cout << "Failed to get snapshot\n"; + std::cerr << call_no << ": warning: failed to get snapshot\n"; return; } @@ -125,7 +133,10 @@ takeSnapshot(unsigned call_no) { char comment[21]; snprintf(comment, sizeof comment, "%u", useCallNos ? call_no : snapshot_no); - src->writePNM(std::cout, comment); + if (snapshotFormat == RAW_RGB) + src->writeRAW(std::cout); + else + src->writePNM(std::cout, comment); } else { os::String filename = os::String::format("%s%010u.png", snapshotPrefix, @@ -273,6 +284,12 @@ public: } } + ~RelayRunner() { + if (thread.joinable()) { + thread.join(); + } + } + /** * Thread main loop. */ @@ -308,13 +325,34 @@ public: */ void runLeg(trace::Call *call) { + /* 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); + } + retraceCall(call); delete call; call = parser.parse_call(); + + /* Restart last frame if looping is requested. */ + if (loopOnFinish) { + if (!call) { + parser.setBookmark(lastFrameStart); + call = parser.parse_call(); + } else if (callEndsFrame) { + lastFrameStart = frameStart; + } + } + } while (call && call->thread_id == leg); if (call) { @@ -422,6 +460,14 @@ RelayRace::run(void) { 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 */ @@ -483,8 +529,17 @@ mainLoop() { 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); @@ -526,10 +581,13 @@ usage(const char *argv0) { " --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" + " --snapshot-format=FMT use (PNM or RGB; default is PNM) when writing to 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" + " --loop continuously loop, replaying final frame.\n" + " --singlethread use a single thread to replay command stream\n"; } enum { @@ -542,6 +600,9 @@ enum { PPD_OPT, PMEM_OPT, SB_OPT, + SNAPSHOT_FORMAT_OPT, + LOOP_OPT, + SINGLETHREAD_OPT }; const static char * @@ -564,9 +625,12 @@ longOptions[] = { {"pmem", no_argument, 0, PMEM_OPT}, {"sb", no_argument, 0, SB_OPT}, {"snapshot-prefix", required_argument, 0, 's'}, + {"snapshot-format", required_argument, 0, SNAPSHOT_FORMAT_OPT}, {"snapshot", required_argument, 0, 'S'}, {"verbose", no_argument, 0, 'v'}, {"wait", no_argument, 0, 'w'}, + {"loop", no_argument, 0, LOOP_OPT}, + {"singlethread", no_argument, 0, SINGLETHREAD_OPT}, {0, 0, 0, 0} }; @@ -639,6 +703,9 @@ int main(int argc, char **argv) case SB_OPT: retrace::doubleBuffer = false; break; + case SINGLETHREAD_OPT: + retrace::singleThread = true; + break; case 's': snapshotPrefix = optarg; if (snapshotFrequency.empty()) { @@ -649,6 +716,12 @@ int main(int argc, char **argv) retrace::verbosity = -2; } break; + case SNAPSHOT_FORMAT_OPT: + if (strcmp(optarg, "RGB") == 0) + snapshotFormat = RAW_RGB; + else + snapshotFormat = PNM_FMT; + break; case 'S': snapshotFrequency = trace::CallSet(optarg); if (snapshotPrefix == NULL) { @@ -661,6 +734,9 @@ int main(int argc, char **argv) case 'w': waitOnFinish = true; break; + case LOOP_OPT: + loopOnFinish = true; + break; case PGPU_OPT: retrace::debug = false; retrace::profiling = true;