aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@digia.com>2014-10-09 12:39:14 +0200
committerUlf Hermann <ulf.hermann@digia.com>2014-10-15 12:24:40 +0300
commit7ae08a61b19508c374b4d8220346cb062b0a003d (patch)
treeaaacf28fc841f9c402edcea9bd831f868542a7f5
parentf70cbad9b18757848888ac7d8d4af4349d606fa2 (diff)
Improve appearance of Scene Graph profiler.
It shouldn't display 0-size timings and it should distinguish the threads more clearly. Also, we display the gross render time in addition to the render time breakdown. This seems to be rather important information for users. Change-Id: I3c1d94f1489902a815c20831e8e1059c815ef129 Reviewed-by: Kai Koehne <kai.koehne@digia.com>
-rw-r--r--plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp170
1 files changed, 93 insertions, 77 deletions
diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp
index fee5fa2d13..3937e76553 100644
--- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp
+++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp
@@ -31,21 +31,23 @@ using namespace QmlProfiler;
static const char *ThreadLabels[] = {
"GUI Thread",
- "Render Thread"
+ "Render Thread",
+ "Render Thread Details"
};
static const char *StageLabels[] = {
"Polish",
"Wait",
- "Sync",
+ "GUI Thread Sync",
"Animations",
- "Sync",
+ "Render Thread Sync",
+ "Render",
"Swap",
- "Material Compile",
"Render Preprocess",
"Render Update",
"Render Bind",
- "Render",
+ "Render Render",
+ "Material Compile",
"Glyph Render",
"Glyph Upload",
"Texture Bind",
@@ -58,20 +60,22 @@ static const char *StageLabels[] = {
enum SceneGraphCategoryType {
SceneGraphGUIThread,
SceneGraphRenderThread,
+ SceneGraphRenderThreadDetails,
MaximumSceneGraphCategoryType
};
enum SceneGraphStage {
- Polish = 0,
+ MinimumSceneGraphStage = 0,
+ Polish = MinimumSceneGraphStage,
Wait,
GUIThreadSync,
Animations,
MaximumGUIThreadStage,
RenderThreadSync = MaximumGUIThreadStage,
+ Render,
Swap,
- Material,
MaximumRenderThreadStage,
RenderPreprocess = MaximumRenderThreadStage,
@@ -80,7 +84,10 @@ enum SceneGraphStage {
RenderRender,
MaximumRenderStage,
- GlyphRender = MaximumRenderStage,
+ Material = MaximumRenderStage,
+ MaximumMaterialStage,
+
+ GlyphRender = MaximumMaterialStage,
GlyphStore,
MaximumGlyphStage,
@@ -104,6 +111,10 @@ public:
void flattenLoads();
QVector<SceneGraphEvent> data;
+ qint64 insert(qint64 start, qint64 duration, int typeIndex, SceneGraphStage stage,
+ int glyphCount = -1);
+ static const char *threadLabel(SceneGraphStage stage);
+
private:
Q_DECLARE_PUBLIC(SceneGraphTimelineModel)
};
@@ -143,10 +154,10 @@ QVariantList SceneGraphTimelineModel::labels() const
QVariantList result;
if (d->expanded && !d->hidden && !isEmpty()) {
- for (int i = 0; i < MaximumSceneGraphStage; ++i) {
+ for (SceneGraphStage i = MinimumSceneGraphStage; i < MaximumSceneGraphStage;
+ i = static_cast<SceneGraphStage>(i + 1)) {
QVariantMap element;
- element.insert(QLatin1String("displayName"), tr(ThreadLabels[i < MaximumGUIThreadStage ?
- SceneGraphGUIThread : SceneGraphRenderThread]));
+ element.insert(QLatin1String("displayName"), tr(d->threadLabel(i)));
element.insert(QLatin1String("description"), tr(StageLabels[i]));
element.insert(QLatin1String("id"), i);
result << element;
@@ -162,8 +173,8 @@ QVariantMap SceneGraphTimelineModel::details(int index) const
QVariantMap result;
const SceneGraphEvent *ev = &d->data[index];
- result.insert(QLatin1String("displayName"), tr(ThreadLabels[ev->stage < MaximumGUIThreadStage ?
- SceneGraphGUIThread : SceneGraphRenderThread]));
+ result.insert(QLatin1String("displayName"),
+ tr(d->threadLabel(static_cast<SceneGraphStage>(ev->stage))));
result.insert(tr("Stage"), tr(StageLabels[ev->stage]));
result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(range(index).duration));
if (ev->glyphCount >= 0)
@@ -189,93 +200,72 @@ void SceneGraphTimelineModel::loadData()
switch ((QmlDebug::SceneGraphFrameType)type.detailType) {
case QmlDebug::SceneGraphRendererFrame: {
+ // Breakdown of render times. We repeat "render" here as "net" render time. It would
+ // look incomplete if that was left out as the printf profiler lists it, too, and people
+ // are apparently comparing that. Unfortunately it is somewhat redundant as the other
+ // parts of the breakdown are usually very short.
qint64 startTime = event.startTime - event.numericData1 - event.numericData2 -
event.numericData3 - event.numericData4;
- d->data.insert(insert(startTime, event.numericData1, event.typeIndex),
- SceneGraphEvent(RenderPreprocess));
- startTime += event.numericData1;
- d->data.insert(insert(startTime, event.numericData2, event.typeIndex),
- SceneGraphEvent(RenderUpdate));
- startTime += event.numericData2;
- d->data.insert(insert(startTime, event.numericData3, event.typeIndex),
- SceneGraphEvent(RenderBind));
- startTime += event.numericData3;
- d->data.insert(insert(startTime, event.numericData4, event.typeIndex),
- SceneGraphEvent(RenderRender));
+ startTime += d->insert(startTime, event.numericData1, event.typeIndex,
+ RenderPreprocess);
+ startTime += d->insert(startTime, event.numericData2, event.typeIndex, RenderUpdate);
+ startTime += d->insert(startTime, event.numericData3, event.typeIndex, RenderBind);
+ d->insert(startTime, event.numericData4, event.typeIndex, RenderRender);
break;
}
case QmlDebug::SceneGraphAdaptationLayerFrame: {
qint64 startTime = event.startTime - event.numericData2 - event.numericData3;
- d->data.insert(insert(startTime, event.numericData2, event.typeIndex),
- SceneGraphEvent(GlyphRender, event.numericData1));
- startTime += event.numericData2;
- d->data.insert(insert(startTime, event.numericData3, event.typeIndex),
- SceneGraphEvent(GlyphStore, event.numericData1));
+ startTime += d->insert(startTime, event.numericData2, event.typeIndex, GlyphRender,
+ event.numericData1);
+ d->insert(startTime, event.numericData3, event.typeIndex, GlyphStore,
+ event.numericData1);
break;
}
case QmlDebug::SceneGraphContextFrame: {
- d->data.insert(insert(event.startTime - event.numericData1, event.numericData1,
- event.typeIndex), SceneGraphEvent(Material));
+ d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex,
+ Material);
break;
}
case QmlDebug::SceneGraphRenderLoopFrame: {
qint64 startTime = event.startTime - event.numericData1 - event.numericData2 -
event.numericData3;
- d->data.insert(insert(startTime, event.numericData1, event.typeIndex),
- SceneGraphEvent(RenderThreadSync));
- startTime += event.numericData1 + event.numericData2;
- // Skip actual rendering. We get a SceneGraphRendererFrame for that
- d->data.insert(insert(startTime, event.numericData3, event.typeIndex),
- SceneGraphEvent(Swap));
+ startTime += d->insert(startTime, event.numericData1, event.typeIndex,
+ RenderThreadSync);
+ startTime += d->insert(startTime, event.numericData2, event.typeIndex,
+ Render);
+ d->insert(startTime, event.numericData3, event.typeIndex, Swap);
break;
}
case QmlDebug::SceneGraphTexturePrepare: {
qint64 startTime = event.startTime - event.numericData1 - event.numericData2 -
event.numericData3 - event.numericData4 - event.numericData5;
-
- d->data.insert(insert(startTime, event.numericData1, event.typeIndex),
- SceneGraphEvent(TextureBind));
- startTime += event.numericData1;
- d->data.insert(insert(startTime, event.numericData2, event.typeIndex),
- SceneGraphEvent(TextureConvert));
- startTime += event.numericData2;
- d->data.insert(insert(startTime, event.numericData3, event.typeIndex),
- SceneGraphEvent(TextureSwizzle));
- startTime += event.numericData3;
- d->data.insert(insert(startTime, event.numericData4, event.typeIndex),
- SceneGraphEvent(TextureUpload));
- startTime += event.numericData4;
- d->data.insert(insert(startTime, event.numericData5, event.typeIndex),
- SceneGraphEvent(TextureMipmap));
+ startTime += d->insert(startTime, event.numericData1, event.typeIndex, TextureBind);
+ startTime += d->insert(startTime, event.numericData2, event.typeIndex, TextureConvert);
+ startTime += d->insert(startTime, event.numericData3, event.typeIndex, TextureSwizzle);
+ startTime += d->insert(startTime, event.numericData4, event.typeIndex, TextureUpload);
+ d->insert(startTime, event.numericData5, event.typeIndex, TextureMipmap);
break;
}
case QmlDebug::SceneGraphPolishAndSync: {
qint64 startTime = event.startTime - event.numericData1 - event.numericData2 -
event.numericData3 - event.numericData4;
- d->data.insert(insert(startTime, event.numericData1, event.typeIndex),
- SceneGraphEvent(Polish));
- startTime += event.numericData1;
- d->data.insert(insert(startTime, event.numericData2, event.typeIndex),
- SceneGraphEvent(Wait));
- startTime += event.numericData2;
- d->data.insert(insert(startTime, event.numericData3, event.typeIndex),
- SceneGraphEvent(GUIThreadSync));
- startTime += event.numericData3;
- d->data.insert(insert(startTime, event.numericData4, event.typeIndex),
- SceneGraphEvent(Animations));
+ startTime += d->insert(startTime, event.numericData1, event.typeIndex, Polish);
+ startTime += d->insert(startTime, event.numericData2, event.typeIndex, Wait);
+ startTime += d->insert(startTime, event.numericData3, event.typeIndex, GUIThreadSync);
+ d->insert(startTime, event.numericData4, event.typeIndex, Animations);
break;
}
case QmlDebug::SceneGraphWindowsAnimations: {
// GUI thread, separate animations stage
- d->data.insert(insert(event.startTime - event.numericData1, event.numericData1,
- event.typeIndex), SceneGraphEvent(Animations));
+ d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex,
+ Animations);
break;
}
case QmlDebug::SceneGraphPolishFrame: {
// GUI thread, separate polish stage
- d->data.insert(insert(event.startTime - event.numericData1, event.numericData1,
- event.typeIndex), SceneGraphEvent(Polish));
+ d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex,
+ Polish);
break;
}
default: break;
@@ -302,18 +292,16 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads()
const Range &start = q->range(i);
// Don't try to put render thread events in GUI row and vice versa.
// Rows below those are free for all.
- event.rowNumberCollapsed = (event.stage < MaximumGUIThreadStage ? SceneGraphGUIThread :
- SceneGraphRenderThread);
+ if (event.stage < MaximumGUIThreadStage)
+ event.rowNumberCollapsed = SceneGraphGUIThread;
+ else if (event.stage < MaximumRenderThreadStage)
+ event.rowNumberCollapsed = SceneGraphRenderThread;
+ else
+ event.rowNumberCollapsed = SceneGraphRenderThreadDetails;
+
while (eventEndTimes.count() > event.rowNumberCollapsed &&
- eventEndTimes[event.rowNumberCollapsed] > start.start) {
+ eventEndTimes[event.rowNumberCollapsed] > start.start)
++event.rowNumberCollapsed;
- if (event.stage < MaximumGUIThreadStage) {
- if (event.rowNumberCollapsed == SceneGraphRenderThread)
- ++event.rowNumberCollapsed;
- } else if (event.rowNumberCollapsed == SceneGraphGUIThread) {
- ++event.rowNumberCollapsed;
- }
- }
while (eventEndTimes.count() <= event.rowNumberCollapsed)
eventEndTimes << 0; // increase stack length, proper value added below
@@ -330,6 +318,34 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads()
expandedRowCount = MaximumSceneGraphStage + 1;
}
+/*!
+ * Inserts an event characterized by \a start time, \a duration, \a typeIndex, \a stage and possibly
+ * \a glyphCount (if it's a \c GlyphRender or \c GlyphStore event) into the scene graph model if its
+ * \a duration is greater than 0. Returns \a duration in that case; otherwise returns 0.
+ */
+qint64 SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::insert(qint64 start,
+ qint64 duration, int typeIndex, SceneGraphStage stage, int glyphCount)
+{
+ if (duration <= 0)
+ return 0;
+
+ Q_Q(SceneGraphTimelineModel);
+ data.insert(q->insert(start, duration, typeIndex), SceneGraphEvent(stage, glyphCount));
+ return duration;
+}
+
+const char *SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::threadLabel(
+ SceneGraphStage stage)
+{
+ if (stage < MaximumGUIThreadStage)
+ return ThreadLabels[SceneGraphGUIThread];
+ else if (stage < MaximumRenderThreadStage)
+ return ThreadLabels[SceneGraphRenderThread];
+ else
+ return ThreadLabels[SceneGraphRenderThreadDetails];
+
+}
+
void SceneGraphTimelineModel::clear()
{
Q_D(SceneGraphTimelineModel);