From defb6c9a59ffc2ae3c20fe8862316adc9b628674 Mon Sep 17 00:00:00 2001 From: Guido Reina Date: Thu, 19 Nov 2020 13:57:57 +0100 Subject: [PATCH 1/2] updated GLStateChecker and added Readme --- utils/GLStateChecker.py | 23 ++++++++++++++++------- utils/Readme.md | 11 +++++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 utils/Readme.md diff --git a/utils/GLStateChecker.py b/utils/GLStateChecker.py index 2dd59a5226..91699444a5 100644 --- a/utils/GLStateChecker.py +++ b/utils/GLStateChecker.py @@ -3,11 +3,18 @@ import tempfile import os import re +import string # pip install jsondiff --user import jsondiff import json -apitrace = "T:\\Utilities\\apitrace-msvc\\x64\\bin\\apitrace.exe" +import argparse + +parser = argparse.ArgumentParser(description='checks OpenGL states when entering/leaving Render() and during module creation (only Renderer[23]DModule)') +parser.add_argument('args', nargs='+', help='the args you want to pass to MegaMol') +parser.add_argument('--apitrace', action='store', help='the full path of apitrace.exe', default='T:\\Utilities\\apitrace-msvc\\x64\\bin\\apitrace.exe') +parser.add_argument('--exe', action='store', help='the frontend you want to use (defaults to megamol.exe)', default='megamol.exe') +parseResult = parser.parse_args() groupstack = [] @@ -20,7 +27,7 @@ def safeString(text): def findDebugGroups(startnum, endnum, mmtracefile): # dump that frame #c:\utilities\apitrace-8.0.20190414-win64\bin\apitrace.exe dump mmconsole.trace --calls=23165-23562 - args = [apitrace, 'dump', '--calls=' + startnum + '-' + endnum, '--color=never', mmtracefile] + args = [parseResult.apitrace, 'dump', '--calls=' + startnum + '-' + endnum, '--color=never', mmtracefile] proc = subprocess.run(args, capture_output=True) res = proc.stdout.decode("utf-8") @@ -45,12 +52,12 @@ def findDebugGroups(startnum, endnum, mmtracefile): else: # dump both states # c:\utilities\apitrace-msvc\x64\bin\apitrace.exe replay -D 167273 mmconsole.1.trace > before.json - args = [apitrace, 'replay', '-D', groupstart, mmtracefile] + args = [parseResult.apitrace, 'replay', '-D', groupstart, mmtracefile] proc = subprocess.run(args, capture_output=True) text = safeString(proc.stdout.decode("ascii")) before = json.loads(text) - args = [apitrace, 'replay', '-D', groupend, mmtracefile] + args = [parseResult.apitrace, 'replay', '-D', groupend, mmtracefile] proc = subprocess.run(args, capture_output=True) text = safeString(proc.stdout.decode("ascii")) after = json.loads(text) @@ -87,14 +94,16 @@ def findDebugGroups(startnum, endnum, mmtracefile): mmtracefile = next(tempfile._get_candidate_names()) + ".trace" args = sys.argv -args[0] = 'mmconsole.exe' -args = [apitrace, "trace", "-o", mmtracefile] + args +args = [parseResult.apitrace, "trace", "-o", mmtracefile, parseResult.exe] + parseResult.args + +sep = " " +print("running " + sep.join(args)) proc = subprocess.run(args, capture_output=True) #mmtracefile = "t0zmtikm.trace" # find frame delimiters -args = [apitrace, 'dump', '--grep=SwapBuffers', '--color=never', mmtracefile] +args = [parseResult.apitrace, 'dump', '--grep=SwapBuffers', '--color=never', mmtracefile] proc = subprocess.run(args, capture_output=True) res = proc.stdout.decode("utf-8") frames = res.split(os.linesep + os.linesep) diff --git a/utils/Readme.md b/utils/Readme.md new file mode 100644 index 0000000000..84cfb93e82 --- /dev/null +++ b/utils/Readme.md @@ -0,0 +1,11 @@ +## GLStateChecker.py + +This utility automatically checks the GL state when a callback of a Renderer[23]DModule is entered and left. Same applies to Create(). To use it, follow these steps: +1. compile MegaMol after uncommenting `#define RIG_RENDERCALLS_WITH_DEBUGGROUPS` in core\include\mmcore\RigRendering.h +2. have Python 3.7 or newer installed +3. have jsondiff installed `pip install jsondiff --user` +4. install apitrace https://apitrace.github.io/ somewhere +5. fix the apitrace path in `GLStateChecker.py` `apitrace = "T:\\Utilities\\apitrace-msvc\\x64\\bin\\apitrace.exe"` +6. go to the MegaMol bin directory +7. run `python \GLStateChecker.py ` +8. Frames 0 and 1 as well as 1 and 2 will looked at \ No newline at end of file From f3bc443960e57078608a8deab40c09b9ad0d76fe Mon Sep 17 00:00:00 2001 From: Guido Reina Date: Thu, 19 Nov 2020 17:04:47 +0100 Subject: [PATCH 2/2] update GLStateChecker to work with new View/Renderers also, more command line parameters and stuff --- core/src/Call.cpp | 20 ++++++++------------ core/src/Module.cpp | 6 ++++-- utils/GLStateChecker.py | 40 ++++++++++++++++++++++++++++++++-------- utils/Readme.md | 14 +++++++------- 4 files changed, 51 insertions(+), 29 deletions(-) diff --git a/core/src/Call.cpp b/core/src/Call.cpp index 8e9c6b93dd..41644b4ee6 100644 --- a/core/src/Call.cpp +++ b/core/src/Call.cpp @@ -13,6 +13,7 @@ #ifdef RIG_RENDERCALLS_WITH_DEBUGGROUPS # include "mmcore/view/Renderer2DModule.h" # include "mmcore/view/Renderer3DModule.h" +# include "mmcore/view/Renderer3DModule_2.h" # include "vislib/graphics/gl/IncludeAllGL.h" #endif #include "mmcore/utility/log/Log.h" @@ -53,26 +54,21 @@ bool Call::operator()(unsigned int func) { if (this->callee != nullptr) { #ifdef RIG_RENDERCALLS_WITH_DEBUGGROUPS auto f = this->callee->GetCallbackFuncName(func); - auto p3 = dynamic_cast(callee->Parent().get()); - auto p2 = dynamic_cast(callee->Parent().get()); - if (p3) { - std::string output = p3->ClassName(); + auto parent = callee->Parent().get(); + auto p3 = dynamic_cast(parent); + auto p3_2 = dynamic_cast(parent); + auto p2 = dynamic_cast(parent); + if (p3 || p3_2 || p2) { + std::string output = dynamic_cast(parent)->ClassName(); output += "::"; output += f; glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1234, -1, output.c_str()); // megamol::core::utility::log::Log::DefaultLog.WriteInfo("called %s::%s", p3->ClassName(), f); } - if (p2) { - std::string output = p2->ClassName(); - output += "::"; - output += f; - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1234, -1, output.c_str()); - // megamol::core::utility::log::Log::DefaultLog.WriteInfo("called %s::%s", p2->ClassName(), f); - } #endif res = this->callee->InCall(this->funcMap[func], *this); #ifdef RIG_RENDERCALLS_WITH_DEBUGGROUPS - if (p2 || p3) glPopDebugGroup(); + if (p2 || p3 || p3_2) glPopDebugGroup(); #endif } // megamol::core::utility::log::Log::DefaultLog.WriteInfo("calling %s, idx %i, result %s (%s)", this->ClassName(), func, diff --git a/core/src/Module.cpp b/core/src/Module.cpp index c582764a1d..12ce4f4fd1 100644 --- a/core/src/Module.cpp +++ b/core/src/Module.cpp @@ -20,6 +20,7 @@ #ifdef RIG_RENDERCALLS_WITH_DEBUGGROUPS #include "mmcore/view/Renderer2DModule.h" #include "mmcore/view/Renderer3DModule.h" +#include "mmcore/view/Renderer3DModule_2.h" #include "vislib/graphics/gl/IncludeAllGL.h" #endif @@ -69,8 +70,9 @@ bool Module::Create(std::vector resources) if (!this->created) { #ifdef RIG_RENDERCALLS_WITH_DEBUGGROUPS auto p3 = dynamic_cast(this); + auto p3_2 = dynamic_cast(this); auto p2 = dynamic_cast(this); - if (p2 || p3) { + if (p2 || p3 || p3_2) { std::string output = this->ClassName(); output += "::create"; glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1234, -1, output.c_str()); @@ -78,7 +80,7 @@ bool Module::Create(std::vector resources) #endif this->created = this->create(); #ifdef RIG_RENDERCALLS_WITH_DEBUGGROUPS - if (p2 || p3) glPopDebugGroup(); + if (p2 || p3 || p3_2) glPopDebugGroup(); #endif Log::DefaultLog.WriteMsg(Log::LEVEL_INFO + 350, "%s module \"%s\"\n", ((this->created) ? "Created" diff --git a/utils/GLStateChecker.py b/utils/GLStateChecker.py index 91699444a5..50a05cefc8 100644 --- a/utils/GLStateChecker.py +++ b/utils/GLStateChecker.py @@ -11,10 +11,26 @@ import argparse parser = argparse.ArgumentParser(description='checks OpenGL states when entering/leaving Render() and during module creation (only Renderer[23]DModule)') -parser.add_argument('args', nargs='+', help='the args you want to pass to MegaMol') +parser.add_argument('args', nargs=argparse.REMAINDER, help='The args you want to pass to MegaMol. Separate from the rest using \'--\' to allow for dashes inside those.') parser.add_argument('--apitrace', action='store', help='the full path of apitrace.exe', default='T:\\Utilities\\apitrace-msvc\\x64\\bin\\apitrace.exe') parser.add_argument('--exe', action='store', help='the frontend you want to use (defaults to megamol.exe)', default='megamol.exe') +parser.add_argument('--keeptrace', action='count', help='do not delete the trace file') + parseResult = parser.parse_args() +the_apitrace = parseResult.apitrace +the_exe = parseResult.exe +the_args = parseResult.args +the_keeptrace = parseResult.keeptrace +# the_apitrace = 'C:\\Utilities\\apitrace-msvc\\x64\\bin\\apitrace.exe' +# the_exe = 'mmconsole.exe' +# the_args = ['-p', '..\\examples\\testspheres.lua'] +# the_keeptrace = 1 + +if not os.path.isfile(the_apitrace): + sys.exit("cannot find apitrace executable ({}), please use --apitrace to specify".format(the_apitrace)) + +if not os.path.isfile(the_exe): + sys.exit("cannot find the executable ({}), please use --exe to specify".format(the_exe)) groupstack = [] @@ -27,7 +43,7 @@ def safeString(text): def findDebugGroups(startnum, endnum, mmtracefile): # dump that frame #c:\utilities\apitrace-8.0.20190414-win64\bin\apitrace.exe dump mmconsole.trace --calls=23165-23562 - args = [parseResult.apitrace, 'dump', '--calls=' + startnum + '-' + endnum, '--color=never', mmtracefile] + args = [the_apitrace, 'dump', '--calls=' + startnum + '-' + endnum, '--color=never', mmtracefile] proc = subprocess.run(args, capture_output=True) res = proc.stdout.decode("utf-8") @@ -52,12 +68,12 @@ def findDebugGroups(startnum, endnum, mmtracefile): else: # dump both states # c:\utilities\apitrace-msvc\x64\bin\apitrace.exe replay -D 167273 mmconsole.1.trace > before.json - args = [parseResult.apitrace, 'replay', '-D', groupstart, mmtracefile] + args = [the_apitrace, 'replay', '-D', groupstart, mmtracefile] proc = subprocess.run(args, capture_output=True) text = safeString(proc.stdout.decode("ascii")) before = json.loads(text) - args = [parseResult.apitrace, 'replay', '-D', groupend, mmtracefile] + args = [the_apitrace, 'replay', '-D', groupend, mmtracefile] proc = subprocess.run(args, capture_output=True) text = safeString(proc.stdout.decode("ascii")) after = json.loads(text) @@ -94,19 +110,24 @@ def findDebugGroups(startnum, endnum, mmtracefile): mmtracefile = next(tempfile._get_candidate_names()) + ".trace" args = sys.argv -args = [parseResult.apitrace, "trace", "-o", mmtracefile, parseResult.exe] + parseResult.args +args = [the_apitrace, "trace", "-o", mmtracefile, the_exe] + the_args sep = " " +sepnewline = "\n" print("running " + sep.join(args)) proc = subprocess.run(args, capture_output=True) #mmtracefile = "t0zmtikm.trace" # find frame delimiters -args = [parseResult.apitrace, 'dump', '--grep=SwapBuffers', '--color=never', mmtracefile] +args = [the_apitrace, 'dump', '--grep=SwapBuffers', '--color=never', mmtracefile] proc = subprocess.run(args, capture_output=True) -res = proc.stdout.decode("utf-8") +res = proc.stdout.decode("utf-8") frames = res.split(os.linesep + os.linesep) +the_re = re.compile(r"^\s*//") +the_check = lambda x : not the_re.match(x) +frames = list(filter(the_check, list(filter(None, frames)))) +# print("found frame delimiters at commands: " + sepnewline.join(frames)) startf = frames[0] endf = frames[1] @@ -125,4 +146,7 @@ def findDebugGroups(startnum, endnum, mmtracefile): findDebugGroups(startnum, endnum, mmtracefile) # cleanup -os.remove(mmtracefile) \ No newline at end of file +if (the_keeptrace > 0): + print("keeping the trace file ({}) around".format(mmtracefile)) +else: + os.remove(mmtracefile) \ No newline at end of file diff --git a/utils/Readme.md b/utils/Readme.md index 84cfb93e82..cf51220f68 100644 --- a/utils/Readme.md +++ b/utils/Readme.md @@ -2,10 +2,10 @@ This utility automatically checks the GL state when a callback of a Renderer[23]DModule is entered and left. Same applies to Create(). To use it, follow these steps: 1. compile MegaMol after uncommenting `#define RIG_RENDERCALLS_WITH_DEBUGGROUPS` in core\include\mmcore\RigRendering.h -2. have Python 3.7 or newer installed -3. have jsondiff installed `pip install jsondiff --user` -4. install apitrace https://apitrace.github.io/ somewhere -5. fix the apitrace path in `GLStateChecker.py` `apitrace = "T:\\Utilities\\apitrace-msvc\\x64\\bin\\apitrace.exe"` -6. go to the MegaMol bin directory -7. run `python \GLStateChecker.py ` -8. Frames 0 and 1 as well as 1 and 2 will looked at \ No newline at end of file +1. have Python 3.7 or newer installed +1. have jsondiff installed `pip install jsondiff --user` +1. install apitrace https://apitrace.github.io/ somewhere +1. go to the MegaMol install/bin directory (where megamol.exe is) +1. run `python \GLStateChecker.py --apitrace --exe -- ` +1. close MegaMol +1. Frames 0 and 1 as well as 1 and 2 will looked at. This involves a lot of apitrace replace for all rigged calls, so please be patient. \ No newline at end of file