summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Janes <mark.a.janes@intel.com>2017-04-03 21:09:11 -0700
committerMark Janes <mark.a.janes@intel.com>2017-06-19 14:04:51 -0700
commitaabb76b85595e211560d2d01b1f78c9188ea5e51 (patch)
treebf13f9fd61c669232b02f04f4f70b0a8dfec3c18
parentc49e091b8949520b01c9d174dafb2f0121896c3f (diff)
Support multiple contexts
Metrics can only be collected for a single context, with the current implementation of INTEL_performance_query. Stop/start metrics before and after context switches, and collect metrics from each context before publishing. Reorganize renders into contexts. Contexts contain renders for a GL context, and manage state changes that must be intstrumented as contexts switch. Eliminate awkward checking of current context when retracing metrics. Subsequent features (state tracking/uniforms) will be per-context.
-rw-r--r--lib/trace/trace_parser.hpp1
-rw-r--r--retrace/daemon/CMakeLists.txt2
-rw-r--r--retrace/daemon/glframe_metrics.cpp210
-rw-r--r--retrace/daemon/glframe_metrics.hpp19
-rw-r--r--retrace/daemon/glframe_retrace.cpp249
-rw-r--r--retrace/daemon/glframe_retrace.hpp5
-rw-r--r--retrace/daemon/glframe_retrace_context.cpp397
-rw-r--r--retrace/daemon/glframe_retrace_context.hpp108
-rw-r--r--retrace/daemon/glframe_retrace_interface.hpp3
-rw-r--r--retrace/daemon/glframe_retrace_render.cpp73
-rw-r--r--retrace/daemon/glframe_retrace_render.hpp5
-rw-r--r--retrace/daemon/glframe_state.cpp18
-rw-r--r--retrace/daemon/glframe_state.hpp2
-rw-r--r--retrace/daemon/test/retrace_metrics_test.cpp4
-rw-r--r--retrace/daemon/ui/main.cpp2
-rw-r--r--retrace/retrace_swizzle.cpp2
16 files changed, 783 insertions, 317 deletions
diff --git a/lib/trace/trace_parser.hpp b/lib/trace/trace_parser.hpp
index dad9f9cf..747fb8f9 100644
--- a/lib/trace/trace_parser.hpp
+++ b/lib/trace/trace_parser.hpp
@@ -34,7 +34,6 @@
#include "trace_model.hpp"
#include "trace_api.hpp"
-
namespace trace {
diff --git a/retrace/daemon/CMakeLists.txt b/retrace/daemon/CMakeLists.txt
index fea03d69..2d3a3c33 100644
--- a/retrace/daemon/CMakeLists.txt
+++ b/retrace/daemon/CMakeLists.txt
@@ -56,6 +56,8 @@ set (RETRACE_SOURCES
glframe_perf_enabled.hpp
glframe_retrace.cpp
glframe_retrace.hpp
+ glframe_retrace_context.cpp
+ glframe_retrace_context.hpp
glframe_retrace_interface.hpp
glframe_retrace_render.cpp
glframe_retrace_render.hpp
diff --git a/retrace/daemon/glframe_metrics.cpp b/retrace/daemon/glframe_metrics.cpp
index 05d28972..3e3b57e8 100644
--- a/retrace/daemon/glframe_metrics.cpp
+++ b/retrace/daemon/glframe_metrics.cpp
@@ -36,6 +36,7 @@
#include "glframe_glhelper.hpp"
#include "glframe_logger.hpp"
+#include "glretrace.hpp"
using glretrace::ExperimentId;
using glretrace::GlFunctions;
@@ -43,10 +44,13 @@ using glretrace::MetricId;
using glretrace::NoAssign;
using glretrace::NoCopy;
using glretrace::OnFrameRetrace;
-using glretrace::PerfMetricGroup;
using glretrace::PerfMetrics;
+using glretrace::PerfMetricsContext;
using glretrace::RenderId;
using glretrace::SelectionId;
+using glretrace::GL;
+using glretrace::glretrace_delay;
+using glretrace::ID_PREFIX_MASK;
namespace {
@@ -75,7 +79,6 @@ class PerfMetric : public NoCopy, NoAssign {
std::string m_name, m_description;
};
-} // namespace
class PerfMetricGroup : public NoCopy, NoAssign {
public:
@@ -85,17 +88,12 @@ class PerfMetricGroup : public NoCopy, NoAssign {
void metrics(std::vector<MetricDescription> *m) const;
void begin(RenderId render);
void end(RenderId render);
- void publish(MetricId metric,
- ExperimentId experimentCount,
- SelectionId selectionCount,
- OnFrameRetrace *callback);
+ void publish(MetricId metric, PerfMetrics::MetricMap *m);
private:
std::string m_query_name;
const int m_query_id;
unsigned int m_data_size;
- unsigned int m_number_counters;
- unsigned int m_capabilities_mask;
std::vector<unsigned char> m_data_buf;
std::map<MetricId, PerfMetric *> m_metrics;
@@ -107,7 +105,34 @@ class PerfMetricGroup : public NoCopy, NoAssign {
std::vector<unsigned int> m_free_query_handles;
};
-PerfMetrics::PerfMetrics(OnFrameRetrace *cb) : current_group(NULL) {
+} // namespace
+
+namespace glretrace {
+
+class PerfMetricsContext : public NoCopy, NoAssign {
+ public:
+ explicit PerfMetricsContext(OnFrameRetrace *cb);
+ ~PerfMetricsContext();
+ int groupCount() const;
+ void selectMetric(MetricId metric);
+ void selectGroup(int index);
+ void begin(RenderId render);
+ void end();
+ void publish(PerfMetrics::MetricMap *metrics);
+ private:
+ std::vector<PerfMetricGroup *> groups;
+ // indicates offset in groups of PerfMetricGroup reporting MetricId
+ std::map<MetricId, int> metric_map;
+ // indicates the group that will handle subsequent begin/end calls
+ PerfMetricGroup *current_group;
+ MetricId current_metric;
+ RenderId current_render;
+};
+
+} // namespace glretrace
+
+PerfMetricsContext::PerfMetricsContext(OnFrameRetrace *cb)
+ : current_group(NULL) {
GLuint query_id;
GLint count;
bool has_metrics = false;
@@ -121,7 +146,7 @@ PerfMetrics::PerfMetrics(OnFrameRetrace *cb) : current_group(NULL) {
return;
GlFunctions::GetFirstPerfQueryIdINTEL(&query_id);
- if (query_id == -1)
+ if (query_id == GLuint(-1))
return;
if (query_id == 0)
@@ -167,10 +192,12 @@ PerfMetrics::PerfMetrics(OnFrameRetrace *cb) : current_group(NULL) {
ids.push_back(i.second.id);
descriptions.push_back(i.second.description);
}
- cb->onMetricList(ids, names, descriptions);
+ if (cb)
+ // only send metrics list on first context
+ cb->onMetricList(ids, names, descriptions);
}
-PerfMetrics::~PerfMetrics() {
+PerfMetricsContext::~PerfMetricsContext() {
for (auto g : groups)
delete g;
groups.clear();
@@ -246,25 +273,12 @@ PerfMetricGroup::begin(RenderId render) {
m_extant_query_handles[render] = query_handle;
}
+static const MetricId ALL_METRICS_IN_GROUP = MetricId(~ID_PREFIX_MASK);
+
void
PerfMetricGroup::publish(MetricId metric,
- ExperimentId experimentCount,
- SelectionId selectionCount,
- OnFrameRetrace *callback) {
- const bool publish_all = ((metric() | ID_PREFIX_MASK) == -1);
- const int publish_count = m_extant_query_handles.size();
- std::map<MetricId, MetricSeries> out_data;
- if (publish_all) {
- for (auto i : m_metrics) {
- out_data[i.first].data.reserve(publish_count);
- out_data[i.first].metric = i.first;
- }
- } else {
- assert(m_metrics.find(metric) != m_metrics.end());
- out_data[metric].data.reserve(publish_count);
- out_data[metric].metric = metric;
- }
-
+ PerfMetrics::MetricMap *out_metrics) {
+ const bool publish_all = (metric == ALL_METRICS_IN_GROUP);
for (auto extant_query : m_extant_query_handles) {
memset(m_data_buf.data(), 0, m_data_buf.size());
GLuint bytes_written;
@@ -274,22 +288,19 @@ PerfMetricGroup::publish(MetricId metric,
&bytes_written);
assert(bytes_written == m_data_size);
- // TODO(majanes) verify order of m_extant_query_handles is by
- // RenderId
- for (auto desired_metric : out_data) {
- MetricId m = desired_metric.first;
- out_data[m].data.push_back(m_metrics[m]->getMetric(m_data_buf));
+ if (publish_all) {
+ for (auto desired_metric : m_metrics) {
+ MetricId met_id = desired_metric.first;
+ (*out_metrics)[met_id][extant_query.first] =
+ desired_metric.second->getMetric(m_data_buf);
+ }
+ } else {
+ (*out_metrics)[metric][extant_query.first] =
+ m_metrics[metric]->getMetric(m_data_buf);
}
m_free_query_handles.push_back(extant_query.second);
}
m_extant_query_handles.clear();
- if (callback) {
- for (auto desired_metric : out_data) {
- callback->onMetrics(desired_metric.second,
- experimentCount,
- selectionCount);
- }
- }
for (auto free_query : m_free_query_handles) {
GlFunctions::DeletePerfQueryINTEL(free_query);
}
@@ -298,7 +309,8 @@ PerfMetricGroup::publish(MetricId metric,
void
PerfMetricGroup::end(RenderId render) {
- GlFunctions::EndPerfQueryINTEL(m_extant_query_handles[render]);
+ if (m_extant_query_handles.find(render) != m_extant_query_handles.end())
+ GlFunctions::EndPerfQueryINTEL(m_extant_query_handles[render]);
}
@@ -381,40 +393,130 @@ PerfMetric::getMetric(const std::vector<unsigned char> &data) const {
}
void
-PerfMetrics::selectMetric(MetricId metric) {
+PerfMetricsContext::selectMetric(MetricId metric) {
assert(metric_map.find(metric) != metric_map.end());
current_metric = metric;
current_group = groups[metric_map[metric]];
}
void
-PerfMetrics::publish(ExperimentId experimentCount,
- SelectionId selectionCount,
- OnFrameRetrace *callback) {
- current_group->publish(current_metric, experimentCount,
- selectionCount, callback);
+PerfMetricsContext::publish(PerfMetrics::MetricMap *metrics) {
+ current_group->publish(current_metric, metrics);
}
void
-PerfMetrics::begin(RenderId render) {
+PerfMetricsContext::begin(RenderId render) {
current_group->begin(render);
current_render = render;
}
void
-PerfMetrics::end() {
+PerfMetricsContext::end() {
current_group->end(current_render);
}
int
-PerfMetrics::groupCount() const {
+PerfMetricsContext::groupCount() const {
return groups.size();
}
void
-PerfMetrics::selectGroup(int index) {
+PerfMetricsContext::selectGroup(int index) {
current_group = groups[index];
- // choose an invalid metric to represent "all metrics"
- current_metric = MetricId(~ID_PREFIX_MASK);
+ current_metric = ALL_METRICS_IN_GROUP;
}
+PerfMetrics::PerfMetrics(OnFrameRetrace *cb)
+ : m_current_group(0) {
+ Context *c = getCurrentContext();
+ m_current_context = new PerfMetricsContext(cb);
+ m_contexts[c] = m_current_context;
+}
+
+PerfMetrics::~PerfMetrics() {
+ for (auto i : m_contexts) {
+ delete i.second;
+ }
+ m_contexts.clear();
+}
+
+int
+PerfMetrics::groupCount() const {
+ assert(!m_contexts.empty());
+ return m_contexts.begin()->second->groupCount();
+}
+
+void
+PerfMetrics::selectMetric(MetricId metric) {
+ m_data.clear();
+ m_current_metric = metric;
+ for (auto i : m_contexts)
+ i.second->selectMetric(metric);
+}
+
+void
+PerfMetrics::selectGroup(int index) {
+ m_current_group = index;
+ m_current_metric = ALL_METRICS_IN_GROUP;
+ for (auto i : m_contexts)
+ i.second->selectGroup(index);
+}
+
+void
+PerfMetrics::begin(RenderId render) {
+ if (!m_current_context) {
+ beginContext();
+ }
+ m_current_context->begin(render);
+}
+
+void
+PerfMetrics::end() {
+ if (m_current_context)
+ m_current_context->end();
+}
+
+void
+PerfMetrics::publish(ExperimentId experimentCount,
+ SelectionId selectionCount,
+ OnFrameRetrace *callback) {
+ for (auto i : m_contexts)
+ i.second->publish(&m_data);
+
+ for (auto i : m_data) {
+ MetricSeries s;
+ s.metric = i.first;
+ s.data.resize(i.second.rbegin()->first.index() + 1);
+ for (auto datapoint : i.second)
+ s.data[datapoint.first.index()] = datapoint.second;
+ callback->onMetrics(s, experimentCount, selectionCount);
+ }
+ m_data.clear();
+}
+
+void
+PerfMetrics::beginContext() {
+ Context *c = getCurrentContext();
+ auto entry = m_contexts.find(c);
+ if (entry != m_contexts.end()) {
+ m_current_context = entry->second;
+ } else {
+ // create a new metrics context
+ GRLOG(glretrace::WARN, "new context in frame");
+ m_current_context = new PerfMetricsContext(NULL);
+ m_contexts[c] = m_current_context;
+ }
+ m_current_context->selectGroup(m_current_group);
+ if (m_current_metric() &&
+ (m_current_metric != ALL_METRICS_IN_GROUP))
+ m_current_context->selectMetric(m_current_metric);
+}
+
+void
+PerfMetrics::endContext() {
+ if (m_current_context) {
+ m_current_context->end();
+ m_current_context->publish(&m_data);
+ }
+ m_current_context = NULL;
+}
diff --git a/retrace/daemon/glframe_metrics.hpp b/retrace/daemon/glframe_metrics.hpp
index 3099b2a7..41180f64 100644
--- a/retrace/daemon/glframe_metrics.hpp
+++ b/retrace/daemon/glframe_metrics.hpp
@@ -36,7 +36,8 @@
namespace glretrace {
-class PerfMetricGroup;
+class PerfMetricsContext;
+struct Context;
class PerfMetrics : public NoCopy, NoAssign {
public:
@@ -50,14 +51,16 @@ class PerfMetrics : public NoCopy, NoAssign {
void publish(ExperimentId experimentCount,
SelectionId selectionCount,
OnFrameRetrace *callback);
+ // call before changing to another context
+ void endContext();
+ void beginContext();
+ typedef std::map<MetricId, std::map<RenderId, float>> MetricMap;
private:
- std::vector<PerfMetricGroup *> groups;
- // indicates offset in groups of PerfMetricGroup reporting MetricId
- std::map<MetricId, int> metric_map;
- // indicates the group that will handle subsequent begin/end calls
- PerfMetricGroup *current_group;
- MetricId current_metric;
- RenderId current_render;
+ PerfMetricsContext* m_current_context;
+ std::map<Context*, PerfMetricsContext*> m_contexts;
+ MetricMap m_data;
+ int m_current_group;
+ MetricId m_current_metric;
};
} // namespace glretrace
diff --git a/retrace/daemon/glframe_retrace.cpp b/retrace/daemon/glframe_retrace.cpp
index b9fa7f4c..da421c93 100644
--- a/retrace/daemon/glframe_retrace.cpp
+++ b/retrace/daemon/glframe_retrace.cpp
@@ -36,9 +36,11 @@
#include <vector>
#include "glframe_glhelper.hpp"
+#include "glframe_gpu_speed.hpp"
#include "glframe_logger.hpp"
#include "glframe_metrics.hpp"
#include "glframe_perf_enabled.hpp"
+#include "glframe_retrace_context.hpp"
#include "glframe_retrace_render.hpp"
#include "glframe_stderr.hpp"
#include "glretrace.hpp"
@@ -50,7 +52,6 @@
#include "glstate.hpp"
#include "glstate_internal.hpp"
#include "trace_dump.hpp"
-#include "glframe_gpu_speed.hpp"
using glretrace::ExperimentId;
using glretrace::FrameRetrace;
@@ -84,29 +85,21 @@ static StdErrRedirect assemblyOutput;
#endif
FrameRetrace::FrameRetrace()
- : m_tracker(&assemblyOutput) {
+ : m_tracker(&assemblyOutput),
+ m_metrics(NULL) {
}
FrameRetrace::~FrameRetrace() {
- delete m_metrics;
+ if (m_metrics)
+ delete m_metrics;
parser->close();
retrace::cleanUp();
}
-int currentRenderBuffer() {
- glstate::Context context;
- const GLenum framebuffer_binding = context.ES ?
- GL_FRAMEBUFFER_BINDING :
- GL_DRAW_FRAMEBUFFER_BINDING;
- GLint draw_framebuffer = 0;
- GlFunctions::GetIntegerv(framebuffer_binding, &draw_framebuffer);
- return draw_framebuffer;
-}
-
void
FrameRetrace::openFile(const std::string &filename,
- const std::vector<unsigned char> &md5,
- uint64_t fileSize,
+ const std::vector<unsigned char> &,
+ uint64_t,
uint32_t framenumber,
OnFrameRetrace *callback) {
check_gpu_speed(callback);
@@ -133,7 +126,7 @@ FrameRetrace::openFile(const std::string &filename,
// play up to the requested frame
trace::Call *call;
- int current_frame = 0;
+ unsigned int current_frame = 0;
while ((call = parser->parse_call()) && current_frame < framenumber) {
std::stringstream call_stream;
trace::dump(*call, call_stream,
@@ -165,36 +158,31 @@ FrameRetrace::openFile(const std::string &filename,
return;
}
+ // sends list of available metrics to ui
m_metrics = new PerfMetrics(callback);
parser->getBookmark(frame_start.start);
- int current_render_buffer = currentRenderBuffer();
- // play through the frame, recording renders and call counts
+ // play through the frame, recording each context
+ RenderId current_render(0);
while (true) {
- auto r = new RetraceRender(parser, &retracer, &m_tracker);
- if (r->endsFrame()) {
- delete r;
+ auto c = new RetraceContext(current_render, parser, &retracer, &m_tracker);
+ current_render = RenderId(current_render.index() + c->getRenderCount());
+ m_contexts.push_back(c);
+ if (c->endsFrame()) {
break;
}
- m_renders.push_back(r);
-
- const int new_render_buffer = currentRenderBuffer();
- if (new_render_buffer != current_render_buffer) {
- if (m_renders.size() > 1) // don't record the very first draw as
- // ending a render target
- render_target_regions.push_back(RenderId(m_renders.size() - 1));
- current_render_buffer = new_render_buffer;
- }
}
- // record the final render as ending a render target region
- render_target_regions.push_back(RenderId(m_renders.size() - 1));
callback->onFileOpening(false, true, current_frame);
}
int
FrameRetrace::getRenderCount() const {
- return m_renders.size();
+ int count = 0;
+ for (auto i : m_contexts) {
+ count += i->getRenderCount();
+ }
+ return count;
}
void
@@ -205,75 +193,9 @@ FrameRetrace::retraceRenderTarget(ExperimentId experimentCount,
OnFrameRetrace *callback) const {
// reset to beginning of frame
parser->setBookmark(frame_start.start);
-
- bool clear_once = true;
-
- // play up to the beginning of the render
- RenderId current_render_id(0);
- for (const auto &sequence : selection.series) {
- while (current_render_id < sequence.begin) {
- m_renders[current_render_id.index()]->retraceRenderTarget(m_tracker,
- NORMAL_RENDER);
- ++current_render_id;
- }
-
- while (current_render_id < sequence.end) {
- if ((options & glretrace::CLEAR_BEFORE_RENDER) && clear_once) {
- GlFunctions::Clear(GL_COLOR_BUFFER_BIT);
- GlFunctions::Clear(GL_DEPTH_BUFFER_BIT);
- GlFunctions::Clear(GL_STENCIL_BUFFER_BIT);
- GlFunctions::Clear(GL_ACCUM_BUFFER_BIT);
- // ignore errors from unsupported clears
- GlFunctions::GetError();
-
- // don't clear the frame buffer before every sequence. We
- // want to clear everything before the first selection.
- clear_once = false;
- }
-
- // play up to the end of the render
- m_renders[current_render_id.index()]->retraceRenderTarget(m_tracker,
- type);
- ++current_render_id;
- }
-
- if (!(options & glretrace::STOP_AT_RENDER)) {
- // play to the end of the render target
-
- const RenderId last_render = lastRenderForRTRegion(current_render_id);
- while (current_render_id < last_render) {
- const int i = current_render_id.index();
- m_renders[i]->retraceRenderTarget(m_tracker,
- NORMAL_RENDER);
- ++current_render_id;
- }
- }
- }
-
- Image *i = glstate::getDrawBufferImage(0);
- if (!i) {
- GRLOGF(WARN, "Failed to obtain draw buffer image for render id: %d",
- current_render_id());
- if (callback)
- callback->onError(RETRACE_WARN, "Failed to obtain draw buffer image");
- } else {
- std::stringstream png;
- i->writePNG(png);
-
- std::vector<unsigned char> d;
- const int bytes = png.str().size();
- d.resize(bytes);
- memcpy(d.data(), png.str().c_str(), bytes);
- if (callback)
- callback->onRenderTarget(selection.id, experimentCount, d);
- }
-
- // play to the rest of the frame
- while (current_render_id.index() < m_renders.size()) {
- m_renders[current_render_id.index()]->retraceRenderTarget(m_tracker,
- NORMAL_RENDER);
- ++current_render_id;
- }
+ for (auto i : m_contexts)
+ i->retraceRenderTarget(experimentCount, selection, type, options,
+ m_tracker, callback);
}
void
@@ -283,31 +205,8 @@ FrameRetrace::retraceShaderAssembly(const RenderSelection &selection,
parser->setBookmark(frame_start.start);
StateTrack tmp_tracker = m_tracker;
- RenderId current_render_id(0);
- for (const auto &sequence : selection.series) {
- // play up to the end of the render
- while (current_render_id < sequence.begin) {
- m_renders[current_render_id.index()]->retrace(&tmp_tracker);
- ++current_render_id;
- }
- while (current_render_id < sequence.end) {
- m_renders[current_render_id.index()]->retrace(&tmp_tracker);
- callback->onShaderAssembly(current_render_id,
- selection.id,
- tmp_tracker.currentVertexShader(),
- tmp_tracker.currentFragmentShader(),
- tmp_tracker.currentTessControlShader(),
- tmp_tracker.currentTessEvalShader(),
- tmp_tracker.currentGeomShader(),
- tmp_tracker.currentCompShader());
- ++current_render_id;
- }
- }
- // play to the rest of the frame
- while (current_render_id.index() < m_renders.size()) {
- m_renders[current_render_id.index()]->retrace(&tmp_tracker);
- ++current_render_id;
- }
+ for (auto i : m_contexts)
+ i->retraceShaderAssembly(selection, &m_tracker, callback);
}
FrameState::FrameState(const std::string &filename,
@@ -347,9 +246,9 @@ FrameRetrace::retraceMetrics(const std::vector<MetricId> &ids,
// retrace the frame once to warm up the gpu, ensuring that the gpu
// is not throttled
parser->setBookmark(frame_start.start);
- for (int i = 0; i < m_renders.size(); ++i) {
- m_renders[i]->retrace(m_tracker);
- }
+
+ for (auto i : m_contexts)
+ i->retraceMetrics(NULL, m_tracker);
const int render_count = getRenderCount();
for (const auto &id : ids) {
@@ -368,16 +267,12 @@ FrameRetrace::retraceMetrics(const std::vector<MetricId> &ids,
SelectionId(0));
continue;
}
-
m_metrics->selectMetric(id);
- for (int i = 0; i < m_renders.size(); ++i) {
- m_metrics->begin(RenderId(i));
- m_renders[i]->retrace(m_tracker);
- m_metrics->end();
- }
+ for (auto i : m_contexts)
+ i->retraceMetrics(m_metrics, m_tracker);
m_metrics->publish(experimentCount,
SelectionId(0), // this use case is not based
- // on render selection
+ // on render selection
callback);
}
}
@@ -389,44 +284,19 @@ FrameRetrace::retraceAllMetrics(const RenderSelection &selection,
// retrace the frame once to warm up the gpu, ensuring that the gpu
// is not throttled
parser->setBookmark(frame_start.start);
- for (int i = 0; i < m_renders.size(); ++i) {
- m_renders[i]->retrace(m_tracker);
- }
+ for (auto i : m_contexts)
+ i->retraceMetrics(NULL, m_tracker);
for (int i = 0; i < m_metrics->groupCount(); ++i) {
- bool query_active = false;
m_metrics->selectGroup(i);
parser->setBookmark(frame_start.start);
- // iterate through the RenderSelection, and insert begin/end
- // around each RenderSeries
- auto currentRenderSequence = selection.series.begin();
- for (int i = 0; i < m_renders.size(); ++i) {
- if (currentRenderSequence != selection.series.end()) {
- if (RenderId(i) == currentRenderSequence->end) {
- m_metrics->end();
- query_active = false;
- ++currentRenderSequence;
- }
- if (currentRenderSequence != selection.series.end() &&
- (RenderId(i) == currentRenderSequence->begin)) {
- m_metrics->begin(RenderId(i));
- query_active = true;
- }
- }
- m_renders[i]->retrace(m_tracker);
- }
- if (query_active)
- m_metrics->end();
- m_metrics->publish(experimentCount, selection.id, callback);
- }
-}
-RenderId
-FrameRetrace::lastRenderForRTRegion(RenderId render) const {
- for (auto rt_render : render_target_regions)
- if (rt_render > render)
- return rt_render;
- return render_target_regions.back();
+ for (auto i : m_contexts)
+ i->retraceAllMetrics(selection, m_metrics, m_tracker);
+ }
+ m_metrics->publish(experimentCount,
+ selection.id,
+ callback);
}
void
@@ -440,41 +310,16 @@ FrameRetrace::replaceShaders(RenderId renderId,
const std::string &comp,
OnFrameRetrace *callback) {
GRLOGF(DEBUG, "%s\n%s", vs.c_str(), fs.c_str());
- std::string message;
- const bool result = m_renders[renderId.index()]->replaceShaders(&m_tracker,
- vs, fs,
- tessControl,
- tessEval,
- geom,
- comp,
- &message);
- if (!result)
- GRLOGF(WARN, "compile failed: %s", message.c_str());
- callback->onShaderCompile(renderId, experimentCount,
- result, message);
+ for (auto i : m_contexts)
+ if (i->replaceShaders(renderId, experimentCount, &m_tracker,
+ vs, fs, tessControl, tessEval,
+ geom, comp, callback))
+ return;
}
void
FrameRetrace::retraceApi(const RenderSelection &selection,
OnFrameRetrace *callback) {
- if (selection.series.empty()) {
- // empty selection: display the full api log
- for (RenderId currentRender(0);
- currentRender.index() < m_renders.size();
- ++currentRender) {
- m_renders[currentRender.index()]->onApi(selection.id,
- currentRender,
- callback);
- }
- return;
- }
- for (auto sequence : selection.series) {
- auto currentRender = sequence.begin;
- while (currentRender < sequence.end) {
- m_renders[currentRender.index()]->onApi(selection.id,
- currentRender,
- callback);
- ++currentRender;
- }
- }
+ for (auto i : m_contexts)
+ i->retraceApi(selection, callback);
}
diff --git a/retrace/daemon/glframe_retrace.hpp b/retrace/daemon/glframe_retrace.hpp
index 5102e888..6f5dd9f1 100644
--- a/retrace/daemon/glframe_retrace.hpp
+++ b/retrace/daemon/glframe_retrace.hpp
@@ -54,6 +54,7 @@ struct RenderBookmark {
class PerfMetrics;
class RetraceRender;
+class RetraceContext;
class FrameRetrace : public IFrameRetrace {
public:
FrameRetrace();
@@ -105,14 +106,12 @@ class FrameRetrace : public IFrameRetrace {
// retrace::Retracer retracer;
RenderBookmark frame_start;
- std::vector<RetraceRender*> m_renders;
+ std::vector<RetraceContext*> m_contexts;
StateTrack m_tracker;
PerfMetrics * m_metrics;
// each entry is the last render in an RT region
std::vector<RenderId> render_target_regions;
-
- RenderId lastRenderForRTRegion(RenderId render) const;
};
} /* namespace glretrace */
diff --git a/retrace/daemon/glframe_retrace_context.cpp b/retrace/daemon/glframe_retrace_context.cpp
new file mode 100644
index 00000000..0fc02e5e
--- /dev/null
+++ b/retrace/daemon/glframe_retrace_context.cpp
@@ -0,0 +1,397 @@
+/**************************************************************************
+ *
+ * Copyright 2017 Intel Corporation
+ * 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.
+ *
+ * Authors:
+ * Mark Janes <mark.a.janes@intel.com>
+ **************************************************************************/
+
+#include "glframe_retrace_context.hpp"
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "trace_model.hpp"
+#include "glframe_glhelper.hpp"
+#include "glretrace.hpp"
+#include "glframe_logger.hpp"
+#include "glframe_metrics.hpp"
+#include "glframe_retrace_render.hpp"
+#include "glstate.hpp"
+
+using glretrace::RenderId;
+using glretrace::RenderSelection;
+using glretrace::RetraceContext;
+using glretrace::WARN;
+using image::Image;
+
+RetraceContext::RetraceContext(RenderId current_render,
+ trace::AbstractParser *parser,
+ retrace::Retracer *retracer,
+ StateTrack *tracker)
+ : m_parser(parser), m_retracer(retracer),
+ m_context_switch(NULL), m_ends_frame(false) {
+ m_parser->getBookmark(m_start_bookmark);
+ trace::Call *call = parser->parse_call();
+ if (RetraceRender::changesContext(*call))
+ m_context_switch = call;
+ else
+ delete call;
+
+ m_parser->setBookmark(m_start_bookmark);
+
+ int current_render_buffer = RetraceRender::currentRenderBuffer();
+ // play through the frame, generating renders
+ while (true) {
+ auto r = new RetraceRender(parser, retracer, tracker);
+ if (r->endsFrame()) {
+ delete r;
+ m_ends_frame = true;
+ break;
+ }
+ m_renders[current_render] = r;
+ ++current_render;
+
+ // peek ahead to see if next call is in the following context
+ m_parser->getBookmark(m_end_bookmark);
+ call = parser->parse_call();
+ m_parser->setBookmark(m_end_bookmark);
+ if (RetraceRender::changesContext(*call)) {
+ m_parser->setBookmark(m_end_bookmark);
+ delete call;
+ break;
+ }
+
+ const int new_render_buffer = RetraceRender::currentRenderBuffer();
+
+ // consider refactoring context to be a container of rt regions
+ if (new_render_buffer != current_render_buffer) {
+ if (m_renders.size() > 1) // don't record the very first draw as
+ // ending a render target
+ end_render_target_regions.push_back(RenderId(m_renders.size() - 1));
+ current_render_buffer = new_render_buffer;
+ }
+ }
+}
+
+int
+RetraceContext::getRenderCount() const {
+ return m_renders.size();
+}
+
+bool isFirstRender(RenderId id, const RenderSelection &s) {
+ return id == s.series.front().begin;
+}
+
+RenderId lastRender(const RenderSelection &s) {
+ return RenderId(s.series.back().end() - 1);
+}
+
+
+bool isSelected(RenderId id, const RenderSelection &s) {
+ for (auto seq : s.series) {
+ if (id >= seq.end)
+ continue;
+ if (id < seq.begin)
+ return false;
+ return true;
+ }
+ return false;
+}
+
+RenderId
+RetraceContext::lastRenderForRTRegion(RenderId render) const {
+ for (auto rt_render : end_render_target_regions)
+ if (rt_render > render)
+ return RenderId(rt_render() - 1);
+ // last render for the context is the final render for the last
+ // region.
+ return m_renders.rbegin()->first;
+}
+
+void
+RetraceContext::retraceRenderTarget(ExperimentId experimentCount,
+ const RenderSelection &selection,
+ RenderTargetType type,
+ RenderOptions options,
+ const StateTrack &tracker,
+ OnFrameRetrace *callback) const {
+ auto current_render = m_renders.begin();
+ // play up to the beginning of the first render
+ while (current_render->first < selection.series.front().begin) {
+ current_render->second->retraceRenderTarget(tracker, NORMAL_RENDER);
+ ++current_render;
+ if (current_render == m_renders.end())
+ // played through the context
+ return;
+ }
+
+ // TODO(majanes) possibly should be clearing on the first selected
+ // render of the last selected framebuffer
+ if (selection.series.front().begin == current_render->first) {
+ // this is the first render of the selection
+ if ((options & glretrace::CLEAR_BEFORE_RENDER)) {
+ GlFunctions::Clear(GL_COLOR_BUFFER_BIT);
+ GlFunctions::Clear(GL_DEPTH_BUFFER_BIT);
+ GlFunctions::Clear(GL_STENCIL_BUFFER_BIT);
+ GlFunctions::Clear(GL_ACCUM_BUFFER_BIT);
+ // ignore errors from unsupported clears
+ GlFunctions::GetError();
+ }
+ }
+
+ // play through the selected renders
+ const RenderId last_render = lastRender(selection);
+ while (current_render->first < selection.series.back().end) {
+ RenderTargetType current_type = type;
+ if (!isSelected(current_render->first, selection))
+ // unselected renders don't get highlighting
+ type = NORMAL_RENDER;
+ const bool is_last_render = (current_render->first == last_render);
+ current_render->second->retraceRenderTarget(tracker,
+ current_type);
+ ++current_render;
+
+ if (is_last_render)
+ // reached end of selection
+ break;
+ if (current_render == m_renders.end())
+ // played through the context
+ break;
+ }
+
+ if ((!(options & glretrace::STOP_AT_RENDER)) &&
+ (current_render != m_renders.end())) {
+ // play through to the end of the currently attached framebuffer
+ RenderId last_render_in_rt_region =
+ lastRenderForRTRegion(last_render);
+ while (current_render->first <= last_render_in_rt_region) {
+ current_render->second->retraceRenderTarget(tracker,
+ NORMAL_RENDER);
+ ++current_render;
+ if (current_render == m_renders.end())
+ // played through the context
+ break;
+ }
+ }
+
+ // report an image if the last selected render is in this context
+ const bool contains_last_render =
+ ((last_render >= m_renders.begin()->first) &&
+ (last_render <= m_renders.rbegin()->first));
+ if (contains_last_render) {
+ Image *i = glstate::getDrawBufferImage(0);
+ if (!i) {
+ GRLOG(WARN, "Failed to obtain draw buffer image for render id");
+ if (callback)
+ callback->onError(RETRACE_WARN, "Failed to obtain draw buffer image");
+ } else {
+ std::stringstream png;
+ i->writePNG(png);
+
+ std::vector<unsigned char> d;
+ const int bytes = png.str().size();
+ d.resize(bytes);
+ memcpy(d.data(), png.str().c_str(), bytes);
+ if (callback)
+ callback->onRenderTarget(selection.id, experimentCount, d);
+ }
+ }
+
+ // play to the rest of the context
+ while (current_render != m_renders.end()) {
+ current_render->second->retraceRenderTarget(tracker,
+ NORMAL_RENDER);
+ ++current_render;
+ }
+}
+
+void
+RetraceContext::retraceMetrics(PerfMetrics *perf,
+ const StateTrack &tracker) const {
+ // NULL perf is passed for a warm-up round
+ if (m_context_switch)
+ m_retracer->retrace(*m_context_switch);
+ if (perf)
+ perf->beginContext();
+ for (auto i : m_renders) {
+ if (perf)
+ perf->begin(i.first);
+ i.second->retrace(tracker);
+ if (perf)
+ perf->end();
+ }
+ if (perf)
+ perf->endContext();
+}
+
+
+class CleanPerf {
+ public:
+ CleanPerf(glretrace::PerfMetrics *perf,
+ bool *active) : m_perf(perf),
+ m_active(active) {}
+ ~CleanPerf() {
+ if (*m_active) {
+ m_perf->end();
+ }
+ m_perf->endContext();
+ }
+ private:
+ glretrace::PerfMetrics *m_perf;
+ bool *m_active;
+};
+
+void
+RetraceContext::retraceAllMetrics(const RenderSelection &selection,
+ PerfMetrics *perf,
+ const StateTrack &tracker) const {
+ if (m_context_switch)
+ m_retracer->retrace(*m_context_switch);
+ perf->beginContext();
+
+ // iterate through the RenderSelection, and insert begin/end
+ // around each RenderSeries
+ // auto currentRenderSequence = selection.series.begin();
+ auto current_render = m_renders.begin();
+ bool metrics_active = false;
+ CleanPerf cleanup(perf, &metrics_active);
+ if (isSelected(current_render->first, selection)) {
+ // continues a selection from the previous context
+ perf->begin(current_render->first);
+ metrics_active = true;
+ }
+
+ for (auto sequence : selection.series) {
+ if (current_render->first >= sequence.end)
+ // this sequence ended before our context begins
+ continue;
+
+ while (current_render->first < sequence.begin) {
+ current_render->second->retrace(tracker);
+ ++current_render;
+ if (current_render == m_renders.end())
+ return;
+ }
+
+ if ((current_render->first == sequence.begin) && (!metrics_active)) {
+ perf->begin(current_render->first);
+ metrics_active = true;
+ }
+
+ while (current_render->first < sequence.end) {
+ current_render->second->retrace(tracker);
+ ++current_render;
+ if (current_render == m_renders.end())
+ return;
+ }
+
+ if (sequence.end == current_render->first) {
+ assert(metrics_active);
+ metrics_active = false;
+ perf->end();
+ }
+ }
+
+ // CleanPerf destructor will end context
+}
+
+bool
+RetraceContext::endsFrame() const {
+ return m_ends_frame;
+}
+
+bool
+RetraceContext::replaceShaders(RenderId renderId,
+ ExperimentId experimentCount,
+ StateTrack *tracker,
+ const std::string &vs,
+ const std::string &fs,
+ const std::string &tessControl,
+ const std::string &tessEval,
+ const std::string &geom,
+ const std::string &comp,
+ OnFrameRetrace *callback) {
+ auto r = m_renders.find(renderId);
+ if (r == m_renders.end())
+ return true;
+ std::string message;
+ const bool result = r->second->replaceShaders(tracker,
+ vs, fs,
+ tessControl,
+ tessEval,
+ geom,
+ comp,
+ &message);
+ if (!result)
+ GRLOGF(WARN, "compile failed: %s", message.c_str());
+ callback->onShaderCompile(renderId, experimentCount,
+ result, message);
+ return result;
+}
+
+void
+RetraceContext::retraceApi(const RenderSelection &selection,
+ OnFrameRetrace *callback) {
+ if (selection.series.empty()) {
+ // empty selection: display the full api log
+ for (auto r : m_renders)
+ r.second->onApi(selection.id, r.first, callback);
+ return;
+ }
+ for (auto sequence : selection.series) {
+ auto currentRender = sequence.begin;
+ while (currentRender < sequence.end) {
+ auto r = m_renders.find(currentRender);
+ if (r != m_renders.end())
+ r->second->onApi(selection.id,
+ currentRender,
+ callback);
+ ++currentRender;
+ }
+ }
+}
+
+
+void
+RetraceContext::retraceShaderAssembly(const RenderSelection &selection,
+ StateTrack *tracker,
+ OnFrameRetrace *callback) {
+ trace::ParseBookmark bm;
+ m_parser->getBookmark(bm);
+ assert(bm.offset == m_start_bookmark.offset);
+
+ for (auto r : m_renders) {
+ r.second->retrace(tracker);
+ if (isSelected(r.first, selection)) {
+ callback->onShaderAssembly(r.first,
+ selection.id,
+ tracker->currentVertexShader(),
+ tracker->currentFragmentShader(),
+ tracker->currentTessControlShader(),
+ tracker->currentTessEvalShader(),
+ tracker->currentGeomShader(),
+ tracker->currentCompShader());
+ }
+ }
+}
diff --git a/retrace/daemon/glframe_retrace_context.hpp b/retrace/daemon/glframe_retrace_context.hpp
new file mode 100644
index 00000000..b5c056c0
--- /dev/null
+++ b/retrace/daemon/glframe_retrace_context.hpp
@@ -0,0 +1,108 @@
+/**************************************************************************
+ *
+ * Copyright 2017 Intel Corporation
+ * 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.
+ *
+ * Authors:
+ * Mark Janes <mark.a.janes@intel.com>
+ **************************************************************************/
+
+#ifndef _GLFRAME_RETRACE_CONTEXT_HPP_
+#define _GLFRAME_RETRACE_CONTEXT_HPP_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "glframe_retrace_interface.hpp"
+#include "glframe_retrace.hpp"
+#include "trace_parser.hpp"
+
+namespace trace {
+class AbstractParser;
+class Call;
+}
+namespace retrace {
+class Retracer;
+}
+
+namespace glretrace {
+
+struct Context;
+
+class StateTrack;
+class OnFrameRetrace;
+class ExperimentId;
+class MetricId;
+class PerfMetrics;
+class RetraceRender;
+
+class RetraceContext {
+ public:
+ RetraceContext(RenderId current_render,
+ trace::AbstractParser *parser,
+ retrace::Retracer *retracer,
+ StateTrack *tracker);
+ void retraceRenderTarget(ExperimentId experimentCount,
+ const RenderSelection &selection,
+ RenderTargetType type,
+ RenderOptions options,
+ const StateTrack &tracker,
+ OnFrameRetrace *callback) const;
+ void retraceMetrics(PerfMetrics *perf, const StateTrack &tracker) const;
+ void retraceAllMetrics(const RenderSelection &selection,
+ PerfMetrics *perf,
+ const StateTrack &tracker) const;
+ bool endsFrame() const;
+ bool replaceShaders(RenderId renderId,
+ ExperimentId experimentCount,
+ StateTrack *tracker,
+ const std::string &vs,
+ const std::string &fs,
+ const std::string &tessControl,
+ const std::string &tessEval,
+ const std::string &geom,
+ const std::string &comp,
+ OnFrameRetrace *callback);
+ void retraceApi(const RenderSelection &selection,
+ OnFrameRetrace *callback);
+ void retraceShaderAssembly(const RenderSelection &selection,
+ StateTrack *tracker,
+ OnFrameRetrace *callback);
+ int getRenderCount() const;
+
+ private:
+ trace::AbstractParser *m_parser;
+ retrace::Retracer *m_retracer;
+ trace::ParseBookmark m_start_bookmark, m_end_bookmark;
+ trace::Call *m_context_switch;
+ RenderBookmark m_context_start;
+ std::map<RenderId, RetraceRender*> m_renders;
+ std::vector<RenderId> end_render_target_regions;
+ bool m_ends_frame;
+
+ RenderId lastRenderForRTRegion(RenderId render) const;
+};
+
+} // namespace glretrace
+
+#endif // _GLFRAME_RETRACE_CONTEXT_HPP_
+
diff --git a/retrace/daemon/glframe_retrace_interface.hpp b/retrace/daemon/glframe_retrace_interface.hpp
index 5ef4e2d5..0a20dc09 100644
--- a/retrace/daemon/glframe_retrace_interface.hpp
+++ b/retrace/daemon/glframe_retrace_interface.hpp
@@ -90,6 +90,8 @@ class RenderId {
uint32_t index() const { return value & (~ID_PREFIX_MASK); }
bool operator<(const RenderId &o) const { return value < o.value; }
bool operator>(const RenderId &o) const { return value > o.value; }
+ bool operator>=(const RenderId &o) const { return value >= o.value; }
+ bool operator<=(const RenderId &o) const { return value <= o.value; }
bool operator==(const RenderId &o) const { return value == o.value; }
private:
uint32_t value;
@@ -114,6 +116,7 @@ class MetricId {
uint32_t counter() const { return (value & 0x0FFFF); }
bool operator<(const MetricId &o) const { return value < o.value; }
bool operator==(const MetricId &o) const { return value == o.value; }
+ bool operator!=(const MetricId &o) const { return value != o.value; }
private:
// low 16 bits are the counter number
// middle 32 bits are the group
diff --git a/retrace/daemon/glframe_retrace_render.cpp b/retrace/daemon/glframe_retrace_render.cpp
index a9435cd4..7420eb12 100644
--- a/retrace/daemon/glframe_retrace_render.cpp
+++ b/retrace/daemon/glframe_retrace_render.cpp
@@ -33,12 +33,15 @@
#include "glframe_glhelper.hpp"
#include "glframe_logger.hpp"
+#include "glframe_metrics.hpp"
#include "glframe_state.hpp"
#include "retrace.hpp"
+#include "glstate_internal.hpp"
#include "trace_parser.hpp"
using glretrace::DEBUG;
using glretrace::GlFunctions;
+using glretrace::PerfMetrics;
using glretrace::RetraceRender;
using glretrace::SelectionId;
using glretrace::StateTrack;
@@ -46,29 +49,39 @@ using glretrace::RenderTargetType;
using glretrace::RenderId;
using glretrace::OnFrameRetrace;
-bool changesContext(const trace::Call * const call) {
- if (strncmp(call->name(), "glXMakeCurrent", strlen("glXMakeCurrent")) == 0)
- return true;
- return false;
-}
-
static const std::string simple_fs =
"void main(void) {\n"
" gl_FragColor = vec4(1,0,1,1);\n"
"}";
bool
-RetraceRender::isRender(const trace::Call &call) {
- return (call.flags & trace::CALL_FLAG_RENDER) ||
- (strcmp("glDispatchCompute", call.name()) == 0) ||
- (strcmp("glDispatchComputeIndirect",
- call.name()) == 0);
+isCompute(const trace::Call &call) {
+ return ((strcmp("glDispatchCompute", call.name()) == 0) ||
+ (strcmp("glDispatchComputeIndirect",
+ call.name()) == 0));
}
bool
-isCompute(const trace::Call &call) {
- return (RetraceRender::isRender(call) &&
- (!(call.flags & trace::CALL_FLAG_RENDER)));
+RetraceRender::changesContext(const trace::Call &call) {
+ if (strncmp(call.name(), "glXMakeCurrent", strlen("glXMakeCurrent")) == 0)
+ return true;
+ return false;
+}
+
+bool
+RetraceRender::isRender(const trace::Call &call) {
+ return ((call.flags & trace::CALL_FLAG_RENDER) || isCompute(call));
+}
+
+int
+RetraceRender::currentRenderBuffer() {
+ glstate::Context context;
+ const GLenum framebuffer_binding = context.ES ?
+ GL_FRAMEBUFFER_BINDING :
+ GL_DRAW_FRAMEBUFFER_BINDING;
+ GLint draw_framebuffer = 0;
+ GlFunctions::GetIntegerv(framebuffer_binding, &draw_framebuffer);
+ return draw_framebuffer;
}
RetraceRender::RetraceRender(trace::AbstractParser *parser,
@@ -78,29 +91,39 @@ RetraceRender::RetraceRender(trace::AbstractParser *parser,
m_rt_program(-1),
m_retrace_program(-1),
m_end_of_frame(false),
- m_highlight_rt(false) {
+ m_highlight_rt(false),
+ m_changes_context(false) {
m_parser->getBookmark(m_bookmark.start);
trace::Call *call = NULL;
std::stringstream call_stream;
bool compute = false;
+ trace::ParseBookmark call_start;
while ((call = parser->parse_call())) {
- trace::dump(*call, call_stream,
- trace::DUMP_FLAG_NO_COLOR);
- m_api_calls.push_back(call_stream.str());
- call_stream.str("");
-
tracker->flush();
m_retracer->retrace(*call);
tracker->track(*call);
m_end_of_frame = call->flags & trace::CALL_FLAG_END_FRAME;
const bool render = isRender(*call);
compute = isCompute(*call);
- assert(!changesContext(call));
+ if (changesContext(*call)) {
+ m_changes_context = true;
+ if (m_api_calls.size() > 0) {
+ // this ought to be in the next context
+ m_parser->setBookmark(call_start);
+ delete call;
+ break;
+ }
+ }
+ trace::dump(*call, call_stream,
+ trace::DUMP_FLAG_NO_COLOR);
+ m_api_calls.push_back(call_stream.str());
+ call_stream.str("");
delete call;
++(m_bookmark.numberOfCalls);
if (render || m_end_of_frame)
break;
+ m_parser->getBookmark(call_start);
}
m_original_program = tracker->CurrentProgram();
m_original_vs = tracker->currentVertexShader().shader;
@@ -138,7 +161,7 @@ RetraceRender::retraceRenderTarget(const StateTrack &tracker,
assert(bm.offset == m_bookmark.start.offset);
// play up to but not past the end of the render
- for (uint calls = 0; calls < m_bookmark.numberOfCalls - 1; ++calls) {
+ for (unsigned int calls = 0; calls < m_bookmark.numberOfCalls - 1; ++calls) {
trace::Call *call = m_parser->parse_call();
assert(call);
tracker.retraceProgramSideEffects(m_original_program, call, m_retracer);
@@ -187,7 +210,7 @@ RetraceRender::retrace(StateTrack *tracker) const {
tracker->flush();
// play up to but not past the end of the render
- for (uint calls = 0; calls < m_bookmark.numberOfCalls - 1; ++calls) {
+ for (unsigned int calls = 0; calls < m_bookmark.numberOfCalls - 1; ++calls) {
trace::Call *call = m_parser->parse_call();
assert(call);
@@ -225,12 +248,14 @@ RetraceRender::retrace(const StateTrack &tracker) const {
assert(bm.offset == m_bookmark.start.offset);
// play up to but not past the end of the render
- for (uint calls = 0; calls < m_bookmark.numberOfCalls - 1; ++calls) {
+ for (unsigned int calls = 0; calls < m_bookmark.numberOfCalls - 1; ++calls) {
trace::Call *call = m_parser->parse_call();
assert(call);
tracker.retraceProgramSideEffects(m_original_program, call, m_retracer);
+ // context change must be on the first call of the render
+ assert((!changesContext(*call)) || calls == 0);
m_retracer->retrace(*call);
delete(call);
diff --git a/retrace/daemon/glframe_retrace_render.hpp b/retrace/daemon/glframe_retrace_render.hpp
index 64908487..a553c678 100644
--- a/retrace/daemon/glframe_retrace_render.hpp
+++ b/retrace/daemon/glframe_retrace_render.hpp
@@ -47,6 +47,7 @@ class StateTrack;
class OnFrameRetrace;
class ExperimentId;
class MetricId;
+class PerfMetrics;
class RetraceRender {
public:
@@ -75,6 +76,8 @@ class RetraceRender {
RenderId renderId,
OnFrameRetrace *callback);
static bool isRender(const trace::Call &c);
+ static bool changesContext(const trace::Call &c);
+ static int currentRenderBuffer();
private:
trace::AbstractParser *m_parser;
@@ -88,7 +91,7 @@ class RetraceRender {
m_modified_tess_eval, m_modified_tess_control,
m_modified_geom, m_modified_comp;
int m_rt_program, m_retrace_program, m_original_program;
- bool m_end_of_frame, m_highlight_rt;
+ bool m_end_of_frame, m_highlight_rt, m_changes_context;
std::vector<std::string> m_api_calls;
};
diff --git a/retrace/daemon/glframe_state.cpp b/retrace/daemon/glframe_state.cpp
index 49975878..44ee0f99 100644
--- a/retrace/daemon/glframe_state.cpp
+++ b/retrace/daemon/glframe_state.cpp
@@ -61,7 +61,6 @@ StateTrack::TrackMap StateTrack::lookup;
StateTrack::StateTrack(OutputPoller *p)
: m_poller(p),
current_program(0),
- current_context(0),
empty_shader() {
}
@@ -90,20 +89,6 @@ StateTrack::TrackMap::track(StateTrack *tracker, const Call &call) {
return true;
}
-bool
-changesContext(const trace::Call &call) {
- if (strncmp(call.name(), "glXMakeCurrent", strlen("glXMakeCurrent")) == 0)
- return true;
- return false;
-}
-
-uint64_t
-getContext(const trace::Call &call) {
- assert(changesContext(call));
- // there ought to be a const variant for this
- return const_cast<trace::Call &>(call).arg(2).toUIntPtr();
-}
-
// TODO(majanes): use a lookup table
void
StateTrack::track(const Call &call) {
@@ -118,9 +103,6 @@ StateTrack::track(const Call &call) {
#endif
}
- if (changesContext(call))
- current_context = getContext(call);
-
#ifndef WIN32
// on Linux we can parse for shader assembly data on every call.
parse();
diff --git a/retrace/daemon/glframe_state.hpp b/retrace/daemon/glframe_state.hpp
index f32159e2..52a73aa8 100644
--- a/retrace/daemon/glframe_state.hpp
+++ b/retrace/daemon/glframe_state.hpp
@@ -98,7 +98,6 @@ class StateTrack {
const ShaderAssembly &currentGeomShader() const;
const ShaderAssembly &currentCompShader() const;
void onAssembly(ShaderType st, AssemblyType at, const std::string &assembly);
- uint64_t currentContext() const { return current_context; }
int useProgram(int orig_program,
const std::string &vs, const std::string &fs,
const std::string &tessControl, const std::string &tessEval,
@@ -147,7 +146,6 @@ class StateTrack {
OutputPoller *m_poller;
int current_program;
- uint64_t current_context;
std::map<int, std::string> shader_to_source;
std::map<int, int> shader_to_type;
std::map<std::string, int> source_to_shader;
diff --git a/retrace/daemon/test/retrace_metrics_test.cpp b/retrace/daemon/test/retrace_metrics_test.cpp
index 22aa4c25..9eb41d81 100644
--- a/retrace/daemon/test/retrace_metrics_test.cpp
+++ b/retrace/daemon/test/retrace_metrics_test.cpp
@@ -117,10 +117,10 @@ TEST_F(RetraceTest, SingleMetricData) {
FrameRetrace rt;
rt.openFile(test_file, md5, fileSize, 7, &cb);
- p.begin(RenderId(1));
+ p.begin(RenderId(0));
RenderSelection s;
s.id = SelectionId(0);
- s.series.push_back(RenderSequence(RenderId(1), RenderId(2)));
+ s.series.push_back(RenderSequence(RenderId(0), RenderId(1)));
rt.retraceRenderTarget(ExperimentId(0), s,
glretrace::NORMAL_RENDER,
glretrace::STOP_AT_RENDER, &cb);
diff --git a/retrace/daemon/ui/main.cpp b/retrace/daemon/ui/main.cpp
index 0c8be714..84dd572b 100644
--- a/retrace/daemon/ui/main.cpp
+++ b/retrace/daemon/ui/main.cpp
@@ -77,7 +77,7 @@ int main(int argc, char *argv[]) {
GlFunctions::Init();
Logger::Create();
- Logger::SetSeverity(glretrace::WARN);
+ Logger::SetSeverity(glretrace::DEBUG);
Socket::Init();
Logger::Begin();
diff --git a/retrace/retrace_swizzle.cpp b/retrace/retrace_swizzle.cpp
index c308334d..e6d0696b 100644
--- a/retrace/retrace_swizzle.cpp
+++ b/retrace/retrace_swizzle.cpp
@@ -122,7 +122,7 @@ addRegion(trace::Call &call, unsigned long long address, void *buffer, unsigned
#ifdef NDEBUG
false
#else
- true
+ false
#endif
;
if (debug) {