X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=retrace%2Fretrace_main.cpp;fp=retrace%2Fretrace_main.cpp;h=df69d4add281233ce0ba817fdef25c576c1601d8;hb=977400f966549e14f02ecdd7eb93830beee18f7d;hp=9386a6182a989621a62a60c5e5b689fbd2fcaac6;hpb=8ecded8401d50cc3e8cc980243a016758550d950;p=apitrace diff --git a/retrace/retrace_main.cpp b/retrace/retrace_main.cpp index 9386a61..df69d4a 100644 --- a/retrace/retrace_main.cpp +++ b/retrace/retrace_main.cpp @@ -27,8 +27,10 @@ #include #include +#include "glws.hpp" #include "os_binary.hpp" #include "os_time.hpp" +#include "os_workqueue.hpp" #include "image.hpp" #include "trace_callset.hpp" #include "trace_dump.hpp" @@ -36,6 +38,7 @@ static bool waitOnFinish = false; +static bool use_threads; static const char *comparePrefix = NULL; static const char *snapshotPrefix = NULL; @@ -44,6 +47,8 @@ static trace::CallSet compareFrequency; static unsigned dumpStateCallNo = ~0; +retrace::Retracer retracer; + namespace retrace { @@ -51,6 +56,7 @@ namespace retrace { trace::Parser parser; trace::Profiler profiler; +static std::map thread_wq_map; int verbosity = 0; bool debug = true; @@ -66,7 +72,22 @@ bool profilingPixelsDrawn = false; unsigned frameNo = 0; unsigned callNo = 0; +static bool state_dumped; +class RenderWork : public os::WorkQueueWork +{ + trace::Call *call; +public: + void run(void); + RenderWork(trace::Call *_call) { call = _call; } + ~RenderWork(void) { delete call; } +}; + +class FlushGLWork : public os::WorkQueueWork +{ +public: + void run(void) { flushRendering(); } +}; void frameComplete(trace::Call &call) { @@ -119,57 +140,119 @@ takeSnapshot(unsigned call_no) { return; } +void RenderWork::run(void) +{ + bool swapRenderTarget = call->flags & + trace::CALL_FLAG_SWAP_RENDERTARGET; + bool doSnapshot = snapshotFrequency.contains(*call) || + compareFrequency.contains(*call); -static void -mainLoop() { - retrace::Retracer retracer; + if (state_dumped) + return; - addCallbacks(retracer); + // For calls which cause rendertargets to be swaped, we take the + // snapshot _before_ swapping the rendertargets. + if (doSnapshot && swapRenderTarget) { + if (call->flags & trace::CALL_FLAG_END_FRAME) { + // For swapbuffers/presents we still use this + // call number, spite not have been executed yet. + takeSnapshot(call->no); + } else { + // Whereas for ordinate fbo/rendertarget changes we + // use the previous call's number. + takeSnapshot(call->no - 1); + } + } - long long startTime = 0; - frameNo = 0; + callNo = call->no; + retracer.retrace(*call); - startTime = os::getTime(); - trace::Call *call; + if (doSnapshot && !swapRenderTarget) + takeSnapshot(call->no); - while ((call = retrace::parser.parse_call())) { - bool swapRenderTarget = call->flags & trace::CALL_FLAG_SWAP_RENDERTARGET; - bool doSnapshot = - snapshotFrequency.contains(*call) || - compareFrequency.contains(*call) - ; - - // For calls which cause rendertargets to be swaped, we take the - // snapshot _before_ swapping the rendertargets. - if (doSnapshot && swapRenderTarget) { - if (call->flags & trace::CALL_FLAG_END_FRAME) { - // For swapbuffers/presents we still use this call number, - // spite not have been executed yet. - takeSnapshot(call->no); - } else { - // Whereas for ordinate fbo/rendertarget changes we use the - // previous call's number. - takeSnapshot(call->no - 1); - } - } + if (call->no >= dumpStateCallNo && dumpState(std::cout)) + state_dumped = true; +} - callNo = call->no; - retracer.retrace(*call); +static os::WorkQueue *get_work_queue(unsigned long thread_id) +{ + os::WorkQueue *thread; + std::map::iterator it; - if (doSnapshot && !swapRenderTarget) { - takeSnapshot(call->no); - } + it = thread_wq_map.find(thread_id); + if (it == thread_wq_map.end()) { + thread = new os::WorkQueue(); + thread_wq_map[thread_id] = thread; + } else { + thread = it->second; + } + + return thread; +} - if (call->no >= dumpStateCallNo && - dumpState(std::cout)) { - exit(0); +static void exit_work_queues(void) +{ + std::map::iterator it; + + it = thread_wq_map.begin(); + while (it != thread_wq_map.end()) { + os::WorkQueue *thread_wq = it->second; + + thread_wq->queue_work(new FlushGLWork); + thread_wq->flush(); + thread_wq->destroy(); + thread_wq_map.erase(it++); + } +} + +static void do_all_calls(void) +{ + trace::Call *call; + int prev_thread_id = -1; + os::WorkQueue *thread_wq = NULL; + + while ((call = parser.parse_call())) { + RenderWork *render_work = new RenderWork(call); + + if (use_threads) { + if (prev_thread_id != call->thread_id) { + if (thread_wq) + thread_wq->flush(); + thread_wq = get_work_queue(call->thread_id); + prev_thread_id = call->thread_id; + } + + thread_wq->queue_work(render_work); + } else { + render_work->run(); + delete render_work; } - delete call; + if (state_dumped) + break; } - // Reached the end of trace - flushRendering(); + exit_work_queues(); +} + + +static void +mainLoop() { + addCallbacks(retracer); + + long long startTime = 0; + frameNo = 0; + + startTime = os::getTime(); + + do_all_calls(); + + if (!use_threads) + /* + * Reached the end of trace; if using threads we do the flush + * when exiting the threads. + */ + flushRendering(); long long endTime = os::getTime(); float timeInterval = (endTime - startTime) * (1.0 / os::timeFrequency); @@ -211,7 +294,8 @@ usage(const char *argv0) { " -S CALLSET calls to snapshot (default is every frame)\n" " -v increase output verbosity\n" " -D CALLNO dump state at specific call no\n" - " -w waitOnFinish on final frame\n"; + " -w waitOnFinish on final frame\n" + " -t enable threading\n"; } @@ -289,6 +373,8 @@ int main(int argc, char **argv) } else if (!strcmp(arg, "-ppd")) { retrace::profilingPixelsDrawn = true; } + } else if (!strcmp(arg, "-t")) { + use_threads = true; } else { std::cerr << "error: unknown option " << arg << "\n"; usage(argv[0]);