diff options
-rw-r--r-- | retrace/glretrace.hpp | 9 | ||||
-rwxr-xr-x | retrace/glretrace_main.cpp | 80 | ||||
-rw-r--r-- | retrace/metric_helper.cpp | 85 | ||||
-rw-r--r-- | retrace/retrace.hpp | 4 | ||||
-rw-r--r-- | retrace/retrace_main.cpp | 36 |
5 files changed, 212 insertions, 2 deletions
diff --git a/retrace/glretrace.hpp b/retrace/glretrace.hpp index f85db570..4bb4b4b5 100644 --- a/retrace/glretrace.hpp +++ b/retrace/glretrace.hpp @@ -72,6 +72,11 @@ struct Context { } }; +extern bool metricBackendsSetup; +extern bool profilingBoundaries[QUERY_BOUNDARY_LIST_END]; +extern std::vector<MetricBackend*> metricBackends; +extern MetricBackend* curMetricBackend; + extern glprofile::Profile defaultProfile; extern bool supportsARBShaderObjects; @@ -133,6 +138,10 @@ void endProfile(trace::Call &call, bool isDraw); MetricBackend* getBackend(std::string backendName); +bool isLastPass(); + +void enableMetricsFromCLI(const char* metrics, QueryBoundary pollingRule); + GLenum blockOnFence(trace::Call &call, GLsync sync, GLbitfield flags); diff --git a/retrace/glretrace_main.cpp b/retrace/glretrace_main.cpp index f68b0791..d4aa14c8 100755 --- a/retrace/glretrace_main.cpp +++ b/retrace/glretrace_main.cpp @@ -218,6 +218,16 @@ flushQueries() { void beginProfile(trace::Call &call, bool isDraw) { + if (retrace::profilingWithBackends) { + if (profilingBoundaries[QUERY_BOUNDARY_CALL] || + profilingBoundaries[QUERY_BOUNDARY_DRAWCALL]) { + if (curMetricBackend) { + curMetricBackend->beginQuery(isDraw ? QUERY_BOUNDARY_DRAWCALL : QUERY_BOUNDARY_CALL); + } + } + return; + } + glretrace::Context *currentContext = glretrace::getCurrentContext(); /* Create call query */ @@ -261,6 +271,15 @@ beginProfile(trace::Call &call, bool isDraw) { void endProfile(trace::Call &call, bool isDraw) { + if (retrace::profilingWithBackends) { + if (profilingBoundaries[QUERY_BOUNDARY_CALL] || + profilingBoundaries[QUERY_BOUNDARY_DRAWCALL]) { + if (curMetricBackend) { + curMetricBackend->endQuery(isDraw ? QUERY_BOUNDARY_DRAWCALL : QUERY_BOUNDARY_CALL); + } + } + return; + } /* CPU profiling for all calls */ if (retrace::profilingCpuTimes) { @@ -418,11 +437,56 @@ initContext() { getCurrentRss(currentRss); retrace::profiler.setBaseRssUsage(currentRss); } + + if (retrace::profilingWithBackends) { + if (!metricBackendsSetup) { + if (retrace::profilingCallsMetricsString) { + enableMetricsFromCLI(retrace::profilingCallsMetricsString, + QUERY_BOUNDARY_CALL); + } + if (retrace::profilingFramesMetricsString) { + enableMetricsFromCLI(retrace::profilingFramesMetricsString, + QUERY_BOUNDARY_FRAME); + } + if (retrace::profilingDrawCallsMetricsString) { + enableMetricsFromCLI(retrace::profilingDrawCallsMetricsString, + QUERY_BOUNDARY_DRAWCALL); + } + unsigned numPasses = 0; + for (auto &b : metricBackends) { + b->generatePasses(); + numPasses += b->getNumPasses(); + } + retrace::numPasses = numPasses > 0 ? numPasses : 1; + metricBackendsSetup = 1; + } + + unsigned numPasses = 0; + for (auto &b : metricBackends) { + numPasses += b->getNumPasses(); + if (retrace::curPass < numPasses) { + curMetricBackend = b; + b->beginPass(); // begin pass + break; + } + } + + if (profilingBoundaries[QUERY_BOUNDARY_FRAME]) { + if (curMetricBackend) { + curMetricBackend->beginQuery(QUERY_BOUNDARY_FRAME); + } + } + } } void frame_complete(trace::Call &call) { - if (retrace::profiling) { + if (retrace::profilingWithBackends) { + if (curMetricBackend) { + curMetricBackend->endQuery(QUERY_BOUNDARY_FRAME); + } + } + else if (retrace::profiling) { /* Complete any remaining queries */ flushQueries(); @@ -444,6 +508,10 @@ frame_complete(trace::Call &call) { !currentDrawable->visible) { retrace::warning(call) << "could not infer drawable size (glViewport never called)\n"; } + + if (curMetricBackend) { + curMetricBackend->beginQuery(QUERY_BOUNDARY_FRAME); + } } @@ -660,10 +728,20 @@ retrace::flushRendering(void) { void retrace::finishRendering(void) { + if (profilingWithBackends && glretrace::curMetricBackend) { + (glretrace::curMetricBackend)->endQuery(QUERY_BOUNDARY_FRAME); + } + glretrace::Context *currentContext = glretrace::getCurrentContext(); if (currentContext) { glFinish(); } + + if (retrace::profilingWithBackends) { + if (glretrace::curMetricBackend) { + (glretrace::curMetricBackend)->endPass(); + } + } } void diff --git a/retrace/metric_helper.cpp b/retrace/metric_helper.cpp index 4e6e4cf8..fc0868ff 100644 --- a/retrace/metric_helper.cpp +++ b/retrace/metric_helper.cpp @@ -1,11 +1,96 @@ #include <string> +#include <vector> +#include <set> +#include <regex> +#include <iostream> +#include "retrace.hpp" #include "metric_backend.hpp" namespace glretrace { +bool metricBackendsSetup = false; +bool profilingBoundaries[QUERY_BOUNDARY_LIST_END] = {false}; +std::vector<MetricBackend*> metricBackends; // to be populated in initContext() +MetricBackend* curMetricBackend = nullptr; // backend active in the current pass + MetricBackend* getBackend(std::string backendName) { return nullptr; // to be populated with backends } +bool +isLastPass() { + return ( retrace::curPass + 1 >= retrace::numPasses ); +} + +void enableMetricsFromCLI(const char* metrics, QueryBoundary pollingRule) { + const std::regex rOuter("\\s*([^:]+):\\s*([^;]*);?"); // backend: (...) + const std::regex rInner("\\s*\\[\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\]\\s*,?" + "|\\s*([^;,]+),?"); // [g, i] | metricName + std::unique_ptr<Metric> p; + std::string metricName; + + auto rOuter_it = std::cregex_token_iterator(metrics, + metrics+std::strlen(metrics), + rOuter, {1,2}); + auto rOuter_end = std::cregex_token_iterator(); + while (rOuter_it != rOuter_end) { + static std::set<MetricBackend*> backendsHash; // for not allowing duplicates + std::string backendName = (rOuter_it++)->str(); + MetricBackend* backend = getBackend(backendName); + if (!backend) { + std::cerr << "Warning: No backend \"" << backendName << "\"." + << std::endl; + rOuter_it++; + continue; + } + if (!backend->isSupported()) { + std::cerr << "Warning: Backend \"" << backendName + << "\" is not supported." << std::endl; + rOuter_it++; + continue; + } + /** + * order in metricBackends is important for output + * also there should be no duplicates + */ + if (backendsHash.find(backend) == backendsHash.end()) { + metricBackends.push_back(backend); + backendsHash.insert(backend); + } + + auto rInner_it = std::cregex_token_iterator(rOuter_it->first, rOuter_it->second, + rInner, {1,2,3}); + auto rInner_end = std::cregex_token_iterator(); + while (rInner_it != rInner_end) { + if (rInner_it->matched) { + std::string groupId = (rInner_it++)->str(); + std::string metricId = (rInner_it++)->str(); + rInner_it++; + p = backend->getMetricById(std::stoi(groupId), std::stoi(metricId)); + metricName = "[" + groupId + ", " + metricId + "]"; + } else { + rInner_it++; + rInner_it++; + metricName = (rInner_it++)->str(); + p = backend->getMetricByName(metricName); + } + + if (!p) { + std::cerr << "Warning: No metric \"" << metricName + << "\"." << std::endl; + continue; + } + int error = backend->enableMetric(p.get(), pollingRule); + if (error) { + std::cerr << "Warning: Metric " << metricName << " not enabled" + " (error " << error << ")." << std::endl; + } else { + profilingBoundaries[pollingRule] = true; + } + } + rOuter_it++; + } +} + } /* namespace glretrace */ diff --git a/retrace/retrace.hpp b/retrace/retrace.hpp index b3816389..d9a5930b 100644 --- a/retrace/retrace.hpp +++ b/retrace/retrace.hpp @@ -124,6 +124,10 @@ extern bool forceWindowed; */ extern unsigned curPass; extern unsigned numPasses; +extern bool profilingWithBackends; +extern char* profilingCallsMetricsString; +extern char* profilingFramesMetricsString; +extern char* profilingDrawCallsMetricsString; extern bool profiling; extern bool profilingCpuTimes; diff --git a/retrace/retrace_main.cpp b/retrace/retrace_main.cpp index f488e12a..1c6c3a87 100644 --- a/retrace/retrace_main.cpp +++ b/retrace/retrace_main.cpp @@ -87,6 +87,10 @@ unsigned samples = 1; unsigned curPass = 0; unsigned numPasses = 1; +bool profilingWithBackends = false; +char* profilingCallsMetricsString; +char* profilingFramesMetricsString; +char* profilingDrawCallsMetricsString; bool profiling = false; bool profilingGpuTimes = false; @@ -631,6 +635,9 @@ usage(const char *argv0) { " --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" + " --pcalls call profiling metrics selection\n" + " --pframes frame profiling metrics selection\n" + " --pdrawcalls draw call profiling metrics selection\n" " --call-nos[=BOOL] use call numbers in snapshot filenames\n" " --core use core profile\n" " --db use a double buffer visual (default)\n" @@ -663,6 +670,9 @@ enum { PGPU_OPT, PPD_OPT, PMEM_OPT, + PCALLS_OPT, + PFRAMES_OPT, + PDRAWCALLS_OPT, SB_OPT, SNAPSHOT_FORMAT_OPT, LOOP_OPT, @@ -692,6 +702,9 @@ longOptions[] = { {"pgpu", no_argument, 0, PGPU_OPT}, {"ppd", no_argument, 0, PPD_OPT}, {"pmem", no_argument, 0, PMEM_OPT}, + {"pcalls", required_argument, 0, PCALLS_OPT}, + {"pframes", required_argument, 0, PFRAMES_OPT}, + {"pdrawcalls", required_argument, 0, PDRAWCALLS_OPT}, {"sb", no_argument, 0, SB_OPT}, {"snapshot-prefix", required_argument, 0, 's'}, {"snapshot-format", required_argument, 0, SNAPSHOT_FORMAT_OPT}, @@ -868,6 +881,27 @@ int main(int argc, char **argv) retrace::profilingMemoryUsage = true; break; + case PCALLS_OPT: + retrace::debug = 0; + retrace::profiling = true; + retrace::verbosity = -1; + retrace::profilingWithBackends = true; + retrace::profilingCallsMetricsString = optarg; + break; + case PFRAMES_OPT: + retrace::debug = 0; + retrace::profiling = true; + retrace::verbosity = -1; + retrace::profilingWithBackends = true; + retrace::profilingFramesMetricsString = optarg; + break; + case PDRAWCALLS_OPT: + retrace::debug = 0; + retrace::profiling = true; + retrace::verbosity = -1; + retrace::profilingWithBackends = true; + retrace::profilingDrawCallsMetricsString = optarg; + break; default: std::cerr << "error: unknown option " << opt << "\n"; usage(argv[0]); @@ -892,7 +926,7 @@ int main(int argc, char **argv) #endif retrace::setUp(); - if (retrace::profiling) { + if (retrace::profiling && !retrace::profilingWithBackends) { retrace::profiler.setup(retrace::profilingCpuTimes, retrace::profilingGpuTimes, retrace::profilingPixelsDrawn, retrace::profilingMemoryUsage); } |