Add GPU draw time to the compositor diagnostic overlay. (
bug 1352151 part 7, r=bas)
--- a/gfx/layers/composite/Diagnostics.cpp
+++ b/gfx/layers/composite/Diagnostics.cpp
@@ -56,28 +56,40 @@ Diagnostics::GetFrameOverlayString(const
float pixelFillRatio = aStats.mInvalidPixels
? float(aStats.mPixelsFilled) / float(aStats.mInvalidPixels)
: 0.0f;
float screenFillRatio = aStats.mScreenPixels
? float(aStats.mPixelsFilled) / float(aStats.mScreenPixels)
: 0.0f;
+ if (aStats.mDrawTime) {
+ mGPUDrawMs.Add(aStats.mDrawTime.value());
+ }
+
+ std::string gpuTimeString;
+ if (mGPUDrawMs.Empty()) {
+ gpuTimeString = "N/A";
+ } else {
+ gpuTimeString = nsPrintfCString("%0.1fms", mGPUDrawMs.Average()).get();
+ }
+
// DL = nsDisplayListBuilder
// FLB = FrameLayerBuilder
// R = ClientLayerManager::EndTransaction
// CP = ShadowLayerForwarder::EndTransaction (txn build)
// TX = LayerTransactionChild::SendUpdate (IPDL serialize+send)
// UP = LayerTransactionParent::RecvUpdate (IPDL deserialize, update, APZ update)
// CC_BUILD = Container prepare/composite frame building
// CC_EXEC = Container render/composite drawing
nsPrintfCString line1("FPS: %d (TXN: %d)", fps, txnFps);
- nsPrintfCString line2("[CC] Build: %0.1fms Exec: %0.1fms Fill Ratio: %0.1f/%0.1f",
+ nsPrintfCString line2("[CC] Build: %0.1fms Exec: %0.1fms GPU: %s Fill Ratio: %0.1f/%0.1f",
mPrepareMs.Average(),
mCompositeMs.Average(),
+ gpuTimeString.c_str(),
pixelFillRatio,
screenFillRatio);
nsPrintfCString line3("[Content] DL: %0.1fms FLB: %0.1fms Raster: %0.1fms",
mDlbMs.Average(),
mFlbMs.Average(),
mRasterMs.Average());
nsPrintfCString line4("[IPDL] Build: %0.1fms Send: %0.1fms Update: %0.1fms",
mSerializeMs.Average(),
--- a/gfx/layers/composite/Diagnostics.h
+++ b/gfx/layers/composite/Diagnostics.h
@@ -3,16 +3,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_gfx_layers_composite_Diagnostics_h
#define mozilla_gfx_layers_composite_Diagnostics_h
#include "FPSCounter.h"
#include "gfxPrefs.h"
+#include "mozilla/Maybe.h"
#include "mozilla/TimeStamp.h"
#include <deque>
#include <string>
#include <utility>
namespace mozilla {
namespace layers {
@@ -26,36 +27,42 @@ public:
void Add(float aValue) {
if (mHistory.size() > kMaxHistory) {
mHistory.pop_front();
}
mHistory.push_back(Entry(aValue, TimeStamp::Now()));
}
float Average() const;
+ bool Empty() const {
+ return mHistory.empty();
+ }
private:
static const size_t kMaxHistory = 60;
std::deque<Entry> mHistory;
};
+// These statistics are collected by layers backends, preferably by the GPU
struct GPUStats
{
GPUStats()
: mInvalidPixels(0),
mScreenPixels(0),
mPixelsFilled(0)
{}
uint32_t mInvalidPixels;
uint32_t mScreenPixels;
uint32_t mPixelsFilled;
+ Maybe<float> mDrawTime;
};
+// Collects various diagnostics about layers performance.
class Diagnostics
{
public:
Diagnostics();
void RecordPaintTimes(const PaintTiming& aPaintTimes);
void RecordUpdateTime(float aValue) {
mUpdateMs.Add(aValue);
@@ -96,14 +103,15 @@ private:
TimedMetric mDlbMs;
TimedMetric mFlbMs;
TimedMetric mRasterMs;
TimedMetric mSerializeMs;
TimedMetric mSendMs;
TimedMetric mUpdateMs;
TimedMetric mPrepareMs;
TimedMetric mCompositeMs;
+ TimedMetric mGPUDrawMs;
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_gfx_layers_composite_Diagnostics_h
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -548,17 +548,17 @@ LayerManagerComposite::RootLayer() const
void
LayerManagerComposite::InvalidateDebugOverlay(nsIntRegion& aInvalidRegion, const IntRect& aBounds)
{
bool drawFps = gfxPrefs::LayersDrawFPS();
bool drawFrameCounter = gfxPrefs::DrawFrameCounter();
bool drawFrameColorBars = gfxPrefs::CompositorDrawColorBars();
if (drawFps || drawFrameCounter) {
- aInvalidRegion.Or(aInvalidRegion, nsIntRect(0, 0, 600, 400));
+ aInvalidRegion.Or(aInvalidRegion, nsIntRect(0, 0, 650, 400));
}
if (drawFrameColorBars) {
aInvalidRegion.Or(aInvalidRegion, nsIntRect(0, 0, 10, aBounds.height));
}
#ifdef USE_SKIA
bool drawPaintTimes = gfxPrefs::AlwaysPaint();
if (drawPaintTimes) {
@@ -634,17 +634,17 @@ LayerManagerComposite::RenderDebugOverla
std::string text = mDiagnostics->GetFrameOverlayString(stats);
mTextRenderer->RenderText(
mCompositor,
text,
IntPoint(2, 5),
Matrix4x4(),
30,
- 600);
+ 650);
if (mUnusedApzTransformWarning) {
// If we have an unused APZ transform on this composite, draw a 20x20 red box
// in the top-right corner
EffectChain effects;
effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(1, 0, 0, 1));
mCompositor->DrawQuad(gfx::Rect(aBounds.width - 20, 0, 20, 20),
aBounds, effects, alpha, gfx::Matrix4x4());
--- a/gfx/layers/d3d11/DiagnosticsD3D11.cpp
+++ b/gfx/layers/d3d11/DiagnosticsD3D11.cpp
@@ -23,24 +23,46 @@ DiagnosticsD3D11::Start(uint32_t aPixels
mCurrentFrame = FrameQueries();
CD3D11_QUERY_DESC desc(D3D11_QUERY_PIPELINE_STATISTICS);
mDevice->CreateQuery(&desc, getter_AddRefs(mCurrentFrame.stats));
if (mCurrentFrame.stats) {
mContext->Begin(mCurrentFrame.stats);
}
mCurrentFrame.pixelsPerFrame = aPixelsPerFrame;
+
+ desc = CD3D11_QUERY_DESC(D3D11_QUERY_TIMESTAMP_DISJOINT);
+ mDevice->CreateQuery(&desc, getter_AddRefs(mCurrentFrame.timing));
+ if (mCurrentFrame.timing) {
+ mContext->Begin(mCurrentFrame.timing);
+ }
+
+ desc = CD3D11_QUERY_DESC(D3D11_QUERY_TIMESTAMP);
+ mDevice->CreateQuery(&desc, getter_AddRefs(mCurrentFrame.frameBegin));
+ if (mCurrentFrame.frameBegin) {
+ mContext->End(mCurrentFrame.frameBegin);
+ }
}
void
DiagnosticsD3D11::End()
{
if (mCurrentFrame.stats) {
mContext->End(mCurrentFrame.stats);
}
+ if (mCurrentFrame.frameBegin) {
+ CD3D11_QUERY_DESC desc(D3D11_QUERY_TIMESTAMP);
+ mDevice->CreateQuery(&desc, getter_AddRefs(mCurrentFrame.frameEnd));
+ if (mCurrentFrame.frameEnd) {
+ mContext->End(mCurrentFrame.frameEnd);
+ }
+ }
+ if (mCurrentFrame.timing) {
+ mContext->End(mCurrentFrame.timing);
+ }
}
void
DiagnosticsD3D11::Cancel()
{
mCurrentFrame = FrameQueries();
}
@@ -50,13 +72,25 @@ DiagnosticsD3D11::Query(GPUStats* aStats
// Collect pixel shader stats.
if (mPrevFrame.stats) {
D3D11_QUERY_DATA_PIPELINE_STATISTICS stats;
if (WaitForGPUQuery(mDevice, mContext, mPrevFrame.stats, &stats)) {
aStats->mInvalidPixels = mPrevFrame.pixelsPerFrame;
aStats->mPixelsFilled = uint32_t(stats.PSInvocations);
}
}
+ if (mPrevFrame.timing) {
+ UINT64 begin, end;
+ D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timing;
+ if (WaitForGPUQuery(mDevice, mContext, mPrevFrame.timing, &timing) &&
+ !timing.Disjoint &&
+ WaitForGPUQuery(mDevice, mContext, mPrevFrame.frameBegin, &begin) &&
+ WaitForGPUQuery(mDevice, mContext, mPrevFrame.frameEnd, &end))
+ {
+ float timeMs = float(end - begin) / float(timing.Frequency) * 1000.0f;
+ aStats->mDrawTime = Some(timeMs);
+ }
+ }
}
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/d3d11/DiagnosticsD3D11.h
+++ b/gfx/layers/d3d11/DiagnosticsD3D11.h
@@ -32,16 +32,19 @@ private:
// When using the diagnostic overlay, we double-buffer some queries for
// frame statistics.
struct FrameQueries {
FrameQueries() : pixelsPerFrame(0)
{}
RefPtr<ID3D11Query> stats;
+ RefPtr<ID3D11Query> timing;
+ RefPtr<ID3D11Query> frameBegin;
+ RefPtr<ID3D11Query> frameEnd;
uint32_t pixelsPerFrame;
};
FrameQueries mPrevFrame;
FrameQueries mCurrentFrame;
};
} // namespace layers
} // namespace mozilla