From 06555614b7385c49964d27aaeec68dec6ff31744 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Sun, 22 Apr 2012 09:36:59 +0100 Subject: [PATCH] Share more code between glretrace and d3dretrace. --- retrace/CMakeLists.txt | 32 ++-- retrace/d3dretrace_main.cpp | 78 +++------- retrace/glretrace.hpp | 9 -- retrace/glretrace.py | 6 +- retrace/glretrace_cgl.cpp | 4 +- retrace/glretrace_egl.cpp | 6 +- retrace/glretrace_glx.cpp | 14 +- retrace/glretrace_main.cpp | 280 ++++++---------------------------- retrace/glretrace_wgl.cpp | 10 +- retrace/glws.cpp | 3 - retrace/glws.hpp | 5 +- retrace/glws_cocoa.mm | 2 +- retrace/glws_egl_xlib.cpp | 2 +- retrace/glws_glx.cpp | 2 +- retrace/glws_wgl.cpp | 2 +- retrace/retrace.cpp | 8 - retrace/retrace.hpp | 38 ++++- retrace/retrace_main.cpp | 296 ++++++++++++++++++++++++++++++++++++ 18 files changed, 447 insertions(+), 350 deletions(-) create mode 100644 retrace/retrace_main.cpp diff --git a/retrace/CMakeLists.txt b/retrace/CMakeLists.txt index 8cc9cd8..b5e89dc 100644 --- a/retrace/CMakeLists.txt +++ b/retrace/CMakeLists.txt @@ -32,6 +32,19 @@ add_custom_command ( ) add_library (retrace_common + retrace.cpp + retrace_main.cpp + retrace_stdc.cpp +) + +target_link_libraries (retrace_common + common + ${PNG_LIBRARIES} + ${ZLIB_LIBRARIES} + ${SNAPPY_LIBRARIES} +) + +add_library (glretrace_common glretrace_gl.cpp glretrace_cgl.cpp glretrace_glx.cpp @@ -42,12 +55,11 @@ add_library (retrace_common glstate_images.cpp glstate_params.cpp glstate_shaders.cpp - retrace.cpp - retrace_stdc.cpp glws.cpp ) -add_dependencies (retrace_common glproc) +add_dependencies (glretrace_common glproc) + if (WIN32 OR APPLE OR X11_FOUND) add_executable (glretrace @@ -58,11 +70,8 @@ if (WIN32 OR APPLE OR X11_FOUND) target_link_libraries (glretrace retrace_common + glretrace_common glproc_gl - common - ${PNG_LIBRARIES} - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} ) if (WIN32) @@ -103,11 +112,8 @@ if (ENABLE_EGL AND X11_FOUND AND NOT WIN32 AND NOT APPLE) target_link_libraries (eglretrace retrace_common + glretrace_common glproc_egl - common - ${PNG_LIBRARIES} - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} ${X11_X11_LIB} ${CMAKE_THREAD_LIBS_INIT} dl @@ -144,9 +150,7 @@ if (WIN32 AND DirectX_D3DX9_INCLUDE_DIR) d3dretrace_d3d9.cpp ) target_link_libraries (d3dretrace - common - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} + retrace_common ) install (TARGETS d3dretrace RUNTIME DESTINATION bin) diff --git a/retrace/d3dretrace_main.cpp b/retrace/d3dretrace_main.cpp index 133f3a7..e4a8986 100644 --- a/retrace/d3dretrace_main.cpp +++ b/retrace/d3dretrace_main.cpp @@ -31,73 +31,39 @@ #include "d3dretrace.hpp" -namespace d3dretrace { - -static void display(void) { - retrace::Retracer retracer; - - retracer.addCallbacks(d3d9_callbacks); - - trace::Call *call; - - while ((call = retrace::parser.parse_call())) { - retracer.retrace(*call); +void +retrace::setUp(void) { +} - delete call; - } - exit(0); +void +retrace::addCallbacks(retrace::Retracer &retracer) +{ + retracer.addCallbacks(d3dretrace::d3d9_callbacks); } -static void usage(void) { - std::cout << - "Usage: d3dretrace [OPTION] TRACE\n" - "Replay TRACE.\n" - "\n" - " -v increase output verbosity\n" - ; +image::Image * +retrace::getSnapshot(void) { + return NULL; } -extern "C" -int main(int argc, char **argv) +bool +retrace::dumpState(std::ostream &os) { + return false; +} - int i; - for (i = 1; i < argc; ++i) { - const char *arg = argv[i]; - - if (arg[0] != '-') { - break; - } - - if (!strcmp(arg, "--")) { - break; - } else if (!strcmp(arg, "--help")) { - usage(); - return 0; - } else if (!strcmp(arg, "-v")) { - ++retrace::verbosity; - } else { - std::cerr << "error: unknown option " << arg << "\n"; - usage(); - return 1; - } - } - - for ( ; i < argc; ++i) { - if (!retrace::parser.open(argv[i])) { - std::cerr << "error: failed to open " << argv[i] << "\n"; - return 1; - } - - display(); - retrace::parser.close(); - } +void +retrace::flushRendering(void) { +} - return 0; +void +retrace::waitForInput(void) { } -} /* namespace glretrace */ +void +retrace::cleanUp(void) { +} diff --git a/retrace/glretrace.hpp b/retrace/glretrace.hpp index 8ba2a80..100d5a8 100644 --- a/retrace/glretrace.hpp +++ b/retrace/glretrace.hpp @@ -33,21 +33,12 @@ namespace glretrace { -extern bool double_buffer; extern bool insideGlBeginEnd; extern glws::Profile defaultProfile; extern glws::Visual *visual[glws::PROFILE_MAX]; extern glws::Drawable *drawable; extern glws::Context *context; -extern unsigned frame; -extern long long startTime; -extern bool wait; - -extern bool benchmark; - -extern unsigned dump_state; - void checkGlError(trace::Call &call); diff --git a/retrace/glretrace.py b/retrace/glretrace.py index e6a0b58..c0edb20 100644 --- a/retrace/glretrace.py +++ b/retrace/glretrace.py @@ -215,7 +215,7 @@ class GlRetracer(Retracer): # Post-snapshots if function.name in ('glFlush', 'glFinish'): - print ' if (!glretrace::double_buffer) {' + print ' if (!retrace::doubleBuffer) {' print ' glretrace::frame_complete(call);' print ' }' if is_draw_array or is_draw_elements or is_misc_draw: @@ -250,7 +250,7 @@ class GlRetracer(Retracer): print ' glretrace::insideGlBeginEnd = false;' if function.name.startswith('gl') and not function.name.startswith('glX'): - print r' if (!glretrace::context && !retrace::benchmark && !retrace::profiling) {' + print r' if (retrace::debug && !glretrace::context) {' print r' retrace::warning(call) << "no current context\n";' print r' }' @@ -286,7 +286,7 @@ class GlRetracer(Retracer): print ' glretrace::insideGlBeginEnd = true;' elif function.name.startswith('gl'): # glGetError is not allowed inside glBegin/glEnd - print ' if (!retrace::benchmark && !retrace::profiling && !glretrace::insideGlBeginEnd) {' + print ' if (retrace::debug && !glretrace::insideGlBeginEnd) {' print ' glretrace::checkGlError(call);' if function.name in ('glProgramStringARB', 'glProgramStringNV'): print r' GLint error_position = -1;' diff --git a/retrace/glretrace_cgl.cpp b/retrace/glretrace_cgl.cpp index 63b94b4..fccd532 100644 --- a/retrace/glretrace_cgl.cpp +++ b/retrace/glretrace_cgl.cpp @@ -70,7 +70,7 @@ getContext(unsigned long long ctx) { it = context_map.find(ctx); if (it == context_map.end()) { glws::Context *context; - context_map[ctx] = context = glws::createContext(visual[glretrace::defaultProfile], sharedContext, glretrace::defaultProfile); + context_map[ctx] = context = glws::createContext(visual[glretrace::defaultProfile], sharedContext, glretrace::defaultProfile, retrace::debug); if (!sharedContext) { sharedContext = context; } @@ -101,7 +101,7 @@ static void retrace_CGLSetCurrentContext(trace::Call &call) { static void retrace_CGLFlushDrawable(trace::Call &call) { if (drawable && context) { - if (double_buffer) { + if (retrace::doubleBuffer) { drawable->swapBuffers(); } else { glFlush(); diff --git a/retrace/glretrace_egl.cpp b/retrace/glretrace_egl.cpp index d7b14ec..1f8020a 100644 --- a/retrace/glretrace_egl.cpp +++ b/retrace/glretrace_egl.cpp @@ -169,7 +169,7 @@ static void retrace_eglCreateContext(trace::Call &call) { } - glws::Context *context = glws::createContext(glretrace::visual[profile], share_context, profile); + glws::Context *context = glws::createContext(glretrace::visual[profile], share_context, profile, retrace::debug); if (!context) { const char *name; switch (profile) { @@ -218,7 +218,7 @@ static void retrace_eglMakeCurrent(trace::Call &call) { if (drawable && context) { glFlush(); - if (!double_buffer) { + if (!retrace::doubleBuffer) { frame_complete(call); } } @@ -238,7 +238,7 @@ static void retrace_eglMakeCurrent(trace::Call &call) { static void retrace_eglSwapBuffers(trace::Call &call) { frame_complete(call); - if (double_buffer && drawable) { + if (retrace::doubleBuffer && drawable) { drawable->swapBuffers(); } else { glFlush(); diff --git a/retrace/glretrace_glx.cpp b/retrace/glretrace_glx.cpp index 7342908..20afe51 100644 --- a/retrace/glretrace_glx.cpp +++ b/retrace/glretrace_glx.cpp @@ -62,7 +62,7 @@ getContext(unsigned long long context_ptr) { ContextMap::const_iterator it; it = context_map.find(context_ptr); if (it == context_map.end()) { - return (context_map[context_ptr] = glws::createContext(visual[glretrace::defaultProfile], NULL, glretrace::defaultProfile)); + return (context_map[context_ptr] = glws::createContext(visual[glretrace::defaultProfile], NULL, glretrace::defaultProfile, retrace::debug)); } return it->second; @@ -72,7 +72,7 @@ static void retrace_glXCreateContext(trace::Call &call) { unsigned long long orig_context = call.ret->toUIntPtr(); glws::Context *share_context = getContext(call.arg(2).toUIntPtr()); - glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile); + glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile, retrace::debug); context_map[orig_context] = context; } @@ -80,7 +80,7 @@ static void retrace_glXCreateContextAttribsARB(trace::Call &call) { unsigned long long orig_context = call.ret->toUIntPtr(); glws::Context *share_context = getContext(call.arg(2).toUIntPtr()); - glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile); + glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile, retrace::debug); context_map[orig_context] = context; } @@ -94,7 +94,7 @@ static void retrace_glXMakeCurrent(trace::Call &call) { if (drawable && context) { glFlush(); - if (!double_buffer) { + if (!retrace::doubleBuffer) { frame_complete(call); } } @@ -123,7 +123,7 @@ static void retrace_glXDestroyContext(trace::Call &call) { static void retrace_glXSwapBuffers(trace::Call &call) { frame_complete(call); - if (double_buffer) { + if (retrace::doubleBuffer) { drawable->swapBuffers(); } else { glFlush(); @@ -134,7 +134,7 @@ static void retrace_glXCreateNewContext(trace::Call &call) { unsigned long long orig_context = call.ret->toUIntPtr(); glws::Context *share_context = getContext(call.arg(3).toUIntPtr()); - glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile); + glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile, retrace::debug); context_map[orig_context] = context; } @@ -148,7 +148,7 @@ static void retrace_glXMakeContextCurrent(trace::Call &call) { if (drawable && context) { glFlush(); - if (!double_buffer) { + if (!retrace::doubleBuffer) { frame_complete(call); } } diff --git a/retrace/glretrace_main.cpp b/retrace/glretrace_main.cpp index 011a354..429208b 100644 --- a/retrace/glretrace_main.cpp +++ b/retrace/glretrace_main.cpp @@ -26,12 +26,7 @@ #include -#include "os_binary.hpp" -#include "os_string.hpp" -#include "os_time.hpp" -#include "image.hpp" #include "retrace.hpp" -#include "trace_callset.hpp" #include "glproc.hpp" #include "glstate.hpp" #include "glretrace.hpp" @@ -39,24 +34,12 @@ namespace glretrace { -bool double_buffer = true; bool insideGlBeginEnd = false; glws::Profile defaultProfile = glws::PROFILE_COMPAT; glws::Visual *visual[glws::PROFILE_MAX]; glws::Drawable *drawable = NULL; glws::Context *context = NULL; -unsigned frame = 0; -long long startTime = 0; -bool wait = false; - -static const char *compare_prefix = NULL; -static const char *snapshot_prefix = NULL; -static trace::CallSet snapshot_frequency; -static trace::CallSet compare_frequency; - -unsigned dump_state = ~0; - void checkGlError(trace::Call &call) { GLenum error = glGetError(); @@ -139,56 +122,8 @@ updateDrawable(int width, int height) { } -static void -snapshot(unsigned call_no) { - assert(snapshot_prefix || compare_prefix); - - if (!drawable) { - return; - } - - image::Image *ref = NULL; - - if (compare_prefix) { - os::String filename = os::String::format("%s%010u.png", compare_prefix, call_no); - ref = image::readPNG(filename); - if (!ref) { - return; - } - if (retrace::verbosity >= 0) { - std::cout << "Read " << filename << "\n"; - } - } - - image::Image *src = glstate::getDrawBufferImage(); - if (!src) { - return; - } - - if (snapshot_prefix) { - if (snapshot_prefix[0] == '-' && snapshot_prefix[1] == 0) { - char comment[21]; - snprintf(comment, sizeof comment, "%u", call_no); - src->writePNM(std::cout, comment); - } else { - os::String filename = os::String::format("%s%010u.png", snapshot_prefix, call_no); - if (src->writePNG(filename) && retrace::verbosity >= 0) { - std::cout << "Wrote " << filename << "\n"; - } - } - } - - if (ref) { - std::cout << "Snapshot " << call_no << " average precision of " << src->compare(*ref) << " bits\n"; - delete ref; - } - - delete src; -} - - void frame_complete(trace::Call &call) { - ++frame; + retrace::frameComplete(call); if (!drawable) { return; @@ -200,190 +135,75 @@ void frame_complete(trace::Call &call) { } -static void display(void) { - retrace::Retracer retracer; - - retracer.addCallbacks(gl_callbacks); - retracer.addCallbacks(glx_callbacks); - retracer.addCallbacks(wgl_callbacks); - retracer.addCallbacks(cgl_callbacks); - retracer.addCallbacks(egl_callbacks); - - startTime = os::getTime(); - trace::Call *call; - - while ((call = retrace::parser.parse_call())) { - bool swapRenderTarget = call->flags & trace::CALL_FLAG_SWAP_RENDERTARGET; - bool doSnapshot = - snapshot_frequency.contains(*call) || - compare_frequency.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. - snapshot(call->no); - } else { - // Whereas for ordinate fbo/rendertarget changes we use the - // previous call's number. - snapshot(call->no - 1); - } - } - - retracer.retrace(*call); - - if (doSnapshot && !swapRenderTarget) { - snapshot(call->no); - } - - if (!insideGlBeginEnd && - drawable && context && - call->no >= dump_state) { - glstate::dumpCurrentContext(std::cout); - exit(0); - } - - delete call; +} /* namespace glretrace */ + + +void +retrace::setUp(void) { + if (retrace::coreProfile) { + glretrace::defaultProfile = glws::PROFILE_CORE; } - // Reached the end of trace - glFlush(); + glws::init(); - long long endTime = os::getTime(); - float timeInterval = (endTime - startTime) * (1.0 / os::timeFrequency); + glretrace::visual[glws::PROFILE_COMPAT] = glws::createVisual(retrace::doubleBuffer, glws::PROFILE_COMPAT); + glretrace::visual[glws::PROFILE_CORE] = glws::createVisual(retrace::doubleBuffer, glws::PROFILE_CORE); + glretrace::visual[glws::PROFILE_ES1] = glws::createVisual(retrace::doubleBuffer, glws::PROFILE_ES1); + glretrace::visual[glws::PROFILE_ES2] = glws::createVisual(retrace::doubleBuffer, glws::PROFILE_ES2); +} - if ((retrace::verbosity >= -1) || (retrace::profiling)) { - std::cout << - "Rendered " << frame << " frames" - " in " << timeInterval << " secs," - " average of " << (frame/timeInterval) << " fps\n"; - } - if (wait) { - while (glws::processEvents()) {} - } else { - exit(0); - } +void +retrace::addCallbacks(retrace::Retracer &retracer) +{ + retracer.addCallbacks(glretrace::gl_callbacks); + retracer.addCallbacks(glretrace::glx_callbacks); + retracer.addCallbacks(glretrace::wgl_callbacks); + retracer.addCallbacks(glretrace::cgl_callbacks); + retracer.addCallbacks(glretrace::egl_callbacks); } -static void usage(void) { - std::cout << - "Usage: glretrace [OPTION] TRACE\n" - "Replay TRACE.\n" - "\n" - " -b benchmark mode (no error checking or warning messages)\n" - " -p profiling mode (run whole trace, dump profiling info)\n" - " -c PREFIX compare against snapshots\n" - " -C CALLSET calls to compare (default is every frame)\n" - " -core use core profile\n" - " -db use a double buffer visual (default)\n" - " -sb use a single buffer visual\n" - " -s PREFIX take snapshots; `-` for PNM stdout output\n" - " -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 wait on final frame\n"; +image::Image * +retrace::getSnapshot(void) { + if (!glretrace::drawable) { + return NULL; + } + + return glstate::getDrawBufferImage(); } -extern "C" -int main(int argc, char **argv) + +bool +retrace::dumpState(std::ostream &os) { - assert(compare_frequency.empty()); - assert(snapshot_frequency.empty()); - - int i; - for (i = 1; i < argc; ++i) { - const char *arg = argv[i]; - - if (arg[0] != '-') { - break; - } - - if (!strcmp(arg, "--")) { - break; - } else if (!strcmp(arg, "-b")) { - retrace::benchmark = true; - retrace::verbosity = -1; - glws::debug = false; - } else if (!strcmp(arg, "-p")) { - retrace::profiling = true; - retrace::verbosity = -1; - glws::debug = false; - } else if (!strcmp(arg, "-c")) { - compare_prefix = argv[++i]; - if (compare_frequency.empty()) { - compare_frequency = trace::CallSet(trace::FREQUENCY_FRAME); - } - } else if (!strcmp(arg, "-C")) { - compare_frequency = trace::CallSet(argv[++i]); - if (compare_prefix == NULL) { - compare_prefix = ""; - } - } else if (!strcmp(arg, "-D")) { - dump_state = atoi(argv[++i]); - retrace::verbosity = -2; - } else if (!strcmp(arg, "-core")) { - defaultProfile = glws::PROFILE_CORE; - } else if (!strcmp(arg, "-db")) { - double_buffer = true; - } else if (!strcmp(arg, "-sb")) { - double_buffer = false; - } else if (!strcmp(arg, "--help")) { - usage(); - return 0; - } else if (!strcmp(arg, "-s")) { - snapshot_prefix = argv[++i]; - if (snapshot_frequency.empty()) { - snapshot_frequency = trace::CallSet(trace::FREQUENCY_FRAME); - } - if (snapshot_prefix[0] == '-' && snapshot_prefix[1] == 0) { - os::setBinaryMode(stdout); - retrace::verbosity = -2; - } - } else if (!strcmp(arg, "-S")) { - snapshot_frequency = trace::CallSet(argv[++i]); - if (snapshot_prefix == NULL) { - snapshot_prefix = ""; - } - } else if (!strcmp(arg, "-v")) { - ++retrace::verbosity; - } else if (!strcmp(arg, "-w")) { - wait = true; - } else { - std::cerr << "error: unknown option " << arg << "\n"; - usage(); - return 1; - } + if (glretrace::insideGlBeginEnd || + !glretrace::drawable || + !glretrace::context) { + return false; } - glws::init(); - visual[glws::PROFILE_COMPAT] = glws::createVisual(double_buffer, glws::PROFILE_COMPAT); - visual[glws::PROFILE_CORE] = glws::createVisual(double_buffer, glws::PROFILE_CORE); - visual[glws::PROFILE_ES1] = glws::createVisual(double_buffer, glws::PROFILE_ES1); - visual[glws::PROFILE_ES2] = glws::createVisual(double_buffer, glws::PROFILE_ES2); + glstate::dumpCurrentContext(os); - for ( ; i < argc; ++i) { - if (!retrace::parser.open(argv[i])) { - std::cerr << "error: failed to open " << argv[i] << "\n"; - return 1; - } + return true; +} - display(); +void +retrace::flushRendering(void) { + glFlush(); +} - retrace::parser.close(); +void +retrace::waitForInput(void) { + while (glws::processEvents()) { } +} +void +retrace::cleanUp(void) { for (int n = 0; n < glws::PROFILE_MAX; n++) { - delete visual[n]; + delete glretrace::visual[n]; } glws::cleanup(); - - return 0; } - -} /* namespace glretrace */ diff --git a/retrace/glretrace_wgl.cpp b/retrace/glretrace_wgl.cpp index 447d177..5ede7e1 100644 --- a/retrace/glretrace_wgl.cpp +++ b/retrace/glretrace_wgl.cpp @@ -56,7 +56,7 @@ getDrawable(unsigned long long hdc) { static void retrace_wglCreateContext(trace::Call &call) { unsigned long long orig_context = call.ret->toUIntPtr(); - glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], NULL, glretrace::defaultProfile); + glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], NULL, glretrace::defaultProfile, retrace::debug); context_map[orig_context] = context; } @@ -66,7 +66,7 @@ static void retrace_wglDeleteContext(trace::Call &call) { static void retrace_wglMakeCurrent(trace::Call &call) { if (drawable && context) { glFlush(); - if (!double_buffer) { + if (!retrace::doubleBuffer) { frame_complete(call); } } @@ -99,7 +99,7 @@ static void retrace_wglSetPixelFormat(trace::Call &call) { static void retrace_wglSwapBuffers(trace::Call &call) { frame_complete(call); - if (double_buffer) { + if (retrace::doubleBuffer) { drawable->swapBuffers(); } else { glFlush(); @@ -114,7 +114,7 @@ static void retrace_wglShareLists(trace::Call &call) { glws::Context *old_context = context_map[hglrc2]; glws::Context *new_context = - glws::createContext(old_context->visual, share_context, glretrace::defaultProfile); + glws::createContext(old_context->visual, share_context, glretrace::defaultProfile, retrace::debug); if (new_context) { if (context == old_context) { glws::makeCurrent(drawable, new_context); @@ -223,7 +223,7 @@ static void retrace_wglCreateContextAttribsARB(trace::Call &call) { share_context = context_map[call.arg(1).toUIntPtr()]; } - glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile); + glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile, retrace::debug); context_map[orig_context] = context; } diff --git a/retrace/glws.cpp b/retrace/glws.cpp index c5c41eb..4e07ede 100644 --- a/retrace/glws.cpp +++ b/retrace/glws.cpp @@ -30,9 +30,6 @@ namespace glws { -bool debug = true; - - bool checkExtension(const char *extName, const char *extString) { diff --git a/retrace/glws.hpp b/retrace/glws.hpp index 9afebf4..05903a7 100644 --- a/retrace/glws.hpp +++ b/retrace/glws.hpp @@ -46,9 +46,6 @@ enum Profile { }; -extern bool debug; - - bool checkExtension(const char *extName, const char *extString); @@ -155,7 +152,7 @@ Drawable * createDrawable(const Visual *visual, int width = 32, int height = 32); Context * -createContext(const Visual *visual, Context *shareContext = 0, Profile profile = PROFILE_COMPAT); +createContext(const Visual *visual, Context *shareContext = 0, Profile profile = PROFILE_COMPAT, bool debug = false); bool makeCurrent(Drawable *drawable, Context *context); diff --git a/retrace/glws_cocoa.mm b/retrace/glws_cocoa.mm index 7f696fa..2ac3091 100644 --- a/retrace/glws_cocoa.mm +++ b/retrace/glws_cocoa.mm @@ -208,7 +208,7 @@ createDrawable(const Visual *visual, int width, int height) } Context * -createContext(const Visual *visual, Context *shareContext, Profile profile) +createContext(const Visual *visual, Context *shareContext, Profile profile, bool debug) { NSOpenGLPixelFormat *pixelFormat = static_cast(visual)->pixelFormat; NSOpenGLContext *share_context = nil; diff --git a/retrace/glws_egl_xlib.cpp b/retrace/glws_egl_xlib.cpp index 6655781..0b8f34c 100644 --- a/retrace/glws_egl_xlib.cpp +++ b/retrace/glws_egl_xlib.cpp @@ -356,7 +356,7 @@ createDrawable(const Visual *visual, int width, int height) } Context * -createContext(const Visual *_visual, Context *shareContext, Profile profile) +createContext(const Visual *_visual, Context *shareContext, Profile profile, bool debug) { const EglVisual *visual = static_cast(_visual); EGLContext share_context = EGL_NO_CONTEXT; diff --git a/retrace/glws_glx.cpp b/retrace/glws_glx.cpp index c151db1..1573bb9 100644 --- a/retrace/glws_glx.cpp +++ b/retrace/glws_glx.cpp @@ -296,7 +296,7 @@ createDrawable(const Visual *visual, int width, int height) } Context * -createContext(const Visual *_visual, Context *shareContext, Profile profile) +createContext(const Visual *_visual, Context *shareContext, Profile profile, bool debug) { const GlxVisual *visual = static_cast(_visual); GLXContext share_context = NULL; diff --git a/retrace/glws_wgl.cpp b/retrace/glws_wgl.cpp index 887a528..c7e84c3 100644 --- a/retrace/glws_wgl.cpp +++ b/retrace/glws_wgl.cpp @@ -283,7 +283,7 @@ createDrawable(const Visual *visual, int width, int height) } Context * -createContext(const Visual *visual, Context *shareContext, Profile profile) +createContext(const Visual *visual, Context *shareContext, Profile profile, bool debug) { if (profile != PROFILE_COMPAT) { return NULL; diff --git a/retrace/retrace.cpp b/retrace/retrace.cpp index bd3dd99..25c3f64 100644 --- a/retrace/retrace.cpp +++ b/retrace/retrace.cpp @@ -35,14 +35,6 @@ namespace retrace { -trace::Parser parser; - - -int verbosity = 0; -bool benchmark = false; -bool profiling = false; - - static bool call_dumped = false; diff --git a/retrace/retrace.hpp b/retrace/retrace.hpp index f0bc453..2f75dbe 100644 --- a/retrace/retrace.hpp +++ b/retrace/retrace.hpp @@ -38,6 +38,11 @@ #include "trace_parser.hpp" +namespace image { + class Image; +} + + namespace retrace { @@ -185,9 +190,9 @@ toPointer(trace::Value &value, bool bind = false); extern int verbosity; /** - * Avoid expensive checks when benchmarking. + * Debugging checks. */ -extern bool benchmark; +extern bool debug; /** * Add profiling data to the dump when retracing. @@ -195,6 +200,10 @@ extern bool benchmark; extern bool profiling; +extern bool doubleBuffer; +extern bool coreProfile; + + std::ostream &warning(trace::Call &call); @@ -241,6 +250,31 @@ public: }; +void +setUp(void); + +void +addCallbacks(retrace::Retracer &retracer); + +void +frameComplete(trace::Call &call); + +image::Image * +getSnapshot(void); + +bool +dumpState(std::ostream &os); + +void +flushRendering(void); + +void +waitForInput(void); + +void +cleanUp(void); + + } /* namespace retrace */ #endif /* _RETRACE_HPP_ */ diff --git a/retrace/retrace_main.cpp b/retrace/retrace_main.cpp new file mode 100644 index 0000000..f91928b --- /dev/null +++ b/retrace/retrace_main.cpp @@ -0,0 +1,296 @@ +/************************************************************************** + * + * Copyright 2011 Jose Fonseca + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#include +#include + +#include "os_binary.hpp" +#include "os_time.hpp" +#include "image.hpp" +#include "trace_callset.hpp" +#include "trace_dump.hpp" +#include "retrace.hpp" + + +static bool wait = false; + +static const char *comparePrefix = NULL; +static const char *snapshotPrefix = NULL; +static trace::CallSet snapshotFrequency; +static trace::CallSet compareFrequency; + +static unsigned dumpStateCallNo = ~0; + + +namespace retrace { + + +trace::Parser parser; + + +int verbosity = 0; +bool debug = true; +bool profiling = false; + + +bool doubleBuffer = true; +bool coreProfile = false; + + +static unsigned frameNo = 0; + + +void +frameComplete(trace::Call &call) { + ++frameNo; +} + + +static void +takeSnapshot(unsigned call_no) { + assert(snapshotPrefix || comparePrefix); + + image::Image *ref = NULL; + + if (comparePrefix) { + os::String filename = os::String::format("%s%010u.png", comparePrefix, call_no); + ref = image::readPNG(filename); + if (!ref) { + return; + } + if (retrace::verbosity >= 0) { + std::cout << "Read " << filename << "\n"; + } + } + + image::Image *src = getSnapshot(); + if (!src) { + return; + } + + if (snapshotPrefix) { + if (snapshotPrefix[0] == '-' && snapshotPrefix[1] == 0) { + char comment[21]; + snprintf(comment, sizeof comment, "%u", call_no); + src->writePNM(std::cout, comment); + } else { + os::String filename = os::String::format("%s%010u.png", snapshotPrefix, call_no); + if (src->writePNG(filename) && retrace::verbosity >= 0) { + std::cout << "Wrote " << filename << "\n"; + } + } + } + + if (ref) { + std::cout << "Snapshot " << call_no << " average precision of " << src->compare(*ref) << " bits\n"; + delete ref; + } + + delete src; + + return; +} + + +static void +mainLoop() { + retrace::Retracer retracer; + + addCallbacks(retracer); + + long long startTime = 0; + + startTime = os::getTime(); + trace::Call *call; + + 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); + } + } + + retracer.retrace(*call); + + if (doSnapshot && !swapRenderTarget) { + takeSnapshot(call->no); + } + + if (call->no >= dumpStateCallNo && + dumpState(std::cout)) { + exit(0); + } + + delete call; + } + + // Reached the end of trace + flushRendering(); + + long long endTime = os::getTime(); + float timeInterval = (endTime - startTime) * (1.0 / os::timeFrequency); + + if ((retrace::verbosity >= -1) || (retrace::profiling)) { + std::cout << + "Rendered " << frameNo << " frames" + " in " << timeInterval << " secs," + " average of " << (frameNo/timeInterval) << " fps\n"; + } + + if (wait) { + waitForInput(); + } else { + exit(0); + } +} + + +} /* namespace retrace */ + + +static void +usage(const char *argv0) { + std::cout << + "Usage: " << argv0 << " [OPTION] TRACE\n" + "Replay TRACE.\n" + "\n" + " -b benchmark mode (no error checking or warning messages)\n" + " -p profiling mode (run whole trace, dump profiling info)\n" + " -c PREFIX compare against snapshots\n" + " -C CALLSET calls to compare (default is every frame)\n" + " -core use core profile\n" + " -db use a double buffer visual (default)\n" + " -sb use a single buffer visual\n" + " -s PREFIX take snapshots; `-` for PNM stdout output\n" + " -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 wait on final frame\n"; +} + + +extern "C" +int main(int argc, char **argv) +{ + assert(compareFrequency.empty()); + assert(snapshotFrequency.empty()); + + int i; + for (i = 1; i < argc; ++i) { + const char *arg = argv[i]; + + if (arg[0] != '-') { + break; + } + + if (!strcmp(arg, "--")) { + break; + } else if (!strcmp(arg, "-b")) { + retrace::debug = false; + retrace::verbosity = -1; + } else if (!strcmp(arg, "-p")) { + retrace::debug = false; + retrace::profiling = true; + retrace::verbosity = -1; + } else if (!strcmp(arg, "-c")) { + comparePrefix = argv[++i]; + if (compareFrequency.empty()) { + compareFrequency = trace::CallSet(trace::FREQUENCY_FRAME); + } + } else if (!strcmp(arg, "-C")) { + compareFrequency = trace::CallSet(argv[++i]); + if (comparePrefix == NULL) { + comparePrefix = ""; + } + } else if (!strcmp(arg, "-D")) { + dumpStateCallNo = atoi(argv[++i]); + retrace::verbosity = -2; + } else if (!strcmp(arg, "-core")) { + retrace::coreProfile = true; + } else if (!strcmp(arg, "-db")) { + retrace::doubleBuffer = true; + } else if (!strcmp(arg, "-sb")) { + retrace::doubleBuffer = false; + } else if (!strcmp(arg, "--help")) { + usage(argv[0]); + return 0; + } else if (!strcmp(arg, "-s")) { + snapshotPrefix = argv[++i]; + if (snapshotFrequency.empty()) { + snapshotFrequency = trace::CallSet(trace::FREQUENCY_FRAME); + } + if (snapshotPrefix[0] == '-' && snapshotPrefix[1] == 0) { + os::setBinaryMode(stdout); + retrace::verbosity = -2; + } + } else if (!strcmp(arg, "-S")) { + snapshotFrequency = trace::CallSet(argv[++i]); + if (snapshotPrefix == NULL) { + snapshotPrefix = ""; + } + } else if (!strcmp(arg, "-v")) { + ++retrace::verbosity; + } else if (!strcmp(arg, "-w")) { + wait = true; + } else { + std::cerr << "error: unknown option " << arg << "\n"; + usage(argv[0]); + return 1; + } + } + + retrace::setUp(); + + for ( ; i < argc; ++i) { + if (!retrace::parser.open(argv[i])) { + std::cerr << "error: failed to open " << argv[i] << "\n"; + return 1; + } + + retrace::mainLoop(); + + retrace::parser.close(); + } + + retrace::cleanUp(); + + return 0; +} + -- 2.43.0