summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--retrace/glretrace.hpp9
-rwxr-xr-xretrace/glretrace_main.cpp80
-rw-r--r--retrace/metric_helper.cpp85
-rw-r--r--retrace/retrace.hpp4
-rw-r--r--retrace/retrace_main.cpp36
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);
}