diff options
author | ccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-25 20:03:08 +0000 |
---|---|---|
committer | ccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-25 20:03:08 +0000 |
commit | 3d21e02ecb88cb2a86045a1678ca99edee62622d (patch) | |
tree | 0d325b828c9112abc3dfa3e757d50defd67e6154 | |
parent | 189230a0b89f399b0fdf3147855d48138523bd71 (diff) | |
download | chromium_src-3d21e02ecb88cb2a86045a1678ca99edee62622d.zip chromium_src-3d21e02ecb88cb2a86045a1678ca99edee62622d.tar.gz chromium_src-3d21e02ecb88cb2a86045a1678ca99edee62622d.tar.bz2 |
Report memory usage statistics from the renderer.
Add functions to PrioritizedTextureManager to report the amount of visible and nearly-visible memory, based on the requested set of textures to draw (note that this is a superset of the backings that will be visible and nearly-visible). Add a unittest for this functionality.
Add infrastructure in the Proxy to send this data to the renderer. From here the data will go to the WebGraphicsContext3D, then the GPU command buffer, and finally the GPU memory manager.
BUG=134750
Review URL: https://chromiumcodereview.appspot.com/11230064
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@164154 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | cc/delegated_renderer_layer_impl_unittest.cc | 1 | ||||
-rw-r--r-- | cc/gl_renderer.cc | 5 | ||||
-rw-r--r-- | cc/gl_renderer.h | 2 | ||||
-rw-r--r-- | cc/layer_tree_host_impl.cc | 2 | ||||
-rw-r--r-- | cc/layer_tree_host_impl.h | 1 | ||||
-rw-r--r-- | cc/layer_tree_host_impl_unittest.cc | 1 | ||||
-rw-r--r-- | cc/prioritized_texture_manager.cc | 34 | ||||
-rw-r--r-- | cc/prioritized_texture_manager.h | 12 | ||||
-rw-r--r-- | cc/prioritized_texture_unittest.cc | 63 | ||||
-rw-r--r-- | cc/priority_calculator.cc | 10 | ||||
-rw-r--r-- | cc/priority_calculator.h | 1 | ||||
-rw-r--r-- | cc/renderer.h | 2 | ||||
-rw-r--r-- | cc/single_thread_proxy.cc | 10 | ||||
-rw-r--r-- | cc/single_thread_proxy.h | 1 | ||||
-rw-r--r-- | cc/software_renderer.h | 2 | ||||
-rw-r--r-- | cc/thread_proxy.cc | 10 | ||||
-rw-r--r-- | cc/thread_proxy.h | 1 |
17 files changed, 155 insertions, 3 deletions
diff --git a/cc/delegated_renderer_layer_impl_unittest.cc b/cc/delegated_renderer_layer_impl_unittest.cc index 8e3b43e..c8ecda0 100644 --- a/cc/delegated_renderer_layer_impl_unittest.cc +++ b/cc/delegated_renderer_layer_impl_unittest.cc @@ -52,6 +52,7 @@ public: virtual void setNeedsCommitOnImplThread() OVERRIDE { } virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector>, double wallClockTime) OVERRIDE { } virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE { return true; } + virtual void sendManagedMemoryStats() OVERRIDE { } protected: scoped_ptr<GraphicsContext> createContext() diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc index b059d76..f287aec 100644 --- a/cc/gl_renderer.cc +++ b/cc/gl_renderer.cc @@ -184,6 +184,11 @@ void GLRenderer::setVisible(bool visible) enforceMemoryPolicy(); } +void GLRenderer::sendManagedMemoryStats(size_t bytesVisible, size_t bytesVisibleAndNearby, size_t bytesAllocated) +{ + // This message cannot reach the GPU process until WebKit changes land. +} + void GLRenderer::releaseRenderPassTextures() { m_renderPassTextures.clear(); diff --git a/cc/gl_renderer.h b/cc/gl_renderer.h index 0a5ec31..fc6810f 100644 --- a/cc/gl_renderer.h +++ b/cc/gl_renderer.h @@ -56,6 +56,8 @@ public: virtual void setVisible(bool) OVERRIDE; + virtual void sendManagedMemoryStats(size_t bytesVisible, size_t bytesVisibleAndNearby, size_t bytesAllocated) OVERRIDE; + protected: GLRenderer(RendererClient*, ResourceProvider*); diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc index d228ba1..eca5aa2 100644 --- a/cc/layer_tree_host_impl.cc +++ b/cc/layer_tree_host_impl.cc @@ -259,6 +259,7 @@ void LayerTreeHostImpl::commitComplete() // Recompute max scroll position; must be after layer content bounds are // updated. updateMaxScrollPosition(); + m_client->sendManagedMemoryStats(); } bool LayerTreeHostImpl::canDraw() @@ -648,6 +649,7 @@ void LayerTreeHostImpl::enforceManagedMemoryPolicy(const ManagedMemoryPolicy& po m_client->setNeedsCommitOnImplThread(); m_client->onCanDrawStateChanged(canDraw()); } + m_client->sendManagedMemoryStats(); } void LayerTreeHostImpl::setManagedMemoryPolicy(const ManagedMemoryPolicy& policy) diff --git a/cc/layer_tree_host_impl.h b/cc/layer_tree_host_impl.h index 7ce1d31..1dc750d 100644 --- a/cc/layer_tree_host_impl.h +++ b/cc/layer_tree_host_impl.h @@ -43,6 +43,7 @@ public: virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector>, double wallClockTime) = 0; // Returns true if resources were deleted by this call. virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) = 0; + virtual void sendManagedMemoryStats() = 0; }; // PinchZoomViewport models the bounds and offset of the viewport that is used during a pinch-zoom operation. diff --git a/cc/layer_tree_host_impl_unittest.cc b/cc/layer_tree_host_impl_unittest.cc index 68a4b7f..106a702 100644 --- a/cc/layer_tree_host_impl_unittest.cc +++ b/cc/layer_tree_host_impl_unittest.cc @@ -88,6 +88,7 @@ public: virtual void setNeedsCommitOnImplThread() OVERRIDE { m_didRequestCommit = true; } virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector>, double wallClockTime) OVERRIDE { } virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE { return m_reduceMemoryResult; } + virtual void sendManagedMemoryStats() OVERRIDE { } void setReduceMemoryResult(bool reduceMemoryResult) { m_reduceMemoryResult = reduceMemoryResult; } diff --git a/cc/prioritized_texture_manager.cc b/cc/prioritized_texture_manager.cc index 6ad408e..c41b347 100644 --- a/cc/prioritized_texture_manager.cc +++ b/cc/prioritized_texture_manager.cc @@ -25,6 +25,10 @@ PrioritizedTextureManager::PrioritizedTextureManager(size_t maxMemoryLimitBytes, , m_memoryAvailableBytes(0) , m_pool(pool) , m_backingsTailNotSorted(false) + , m_memoryVisibleBytes(0) + , m_memoryVisibleAndNearbyBytes(0) + , m_memoryVisibleLastPushedBytes(0) + , m_memoryVisibleAndNearbyLastPushedBytes(0) { } @@ -40,6 +44,18 @@ PrioritizedTextureManager::~PrioritizedTextureManager() DCHECK(m_backings.empty()); } +size_t PrioritizedTextureManager::memoryVisibleBytes() const +{ + DCHECK(Proxy::isImplThread()); + return m_memoryVisibleLastPushedBytes; +} + +size_t PrioritizedTextureManager::memoryVisibleAndNearbyBytes() const +{ + DCHECK(Proxy::isImplThread()); + return m_memoryVisibleAndNearbyLastPushedBytes; +} + void PrioritizedTextureManager::prioritizeTextures() { TRACE_EVENT0("cc", "PrioritizedTextureManager::prioritizeTextures"); @@ -52,9 +68,17 @@ void PrioritizedTextureManager::prioritizeTextures() TextureVector& sortedTextures = m_tempTextureVector; sortedTextures.clear(); - // Copy all textures into a vector and sort them. - for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) - sortedTextures.push_back(*it); + // Copy all textures into a vector, sort them, and collect memory requirements statistics. + m_memoryVisibleBytes = 0; + m_memoryVisibleAndNearbyBytes = 0; + for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) { + PrioritizedTexture* texture = (*it); + sortedTextures.push_back(texture); + if (PriorityCalculator::priorityIsHigher(texture->requestPriority(), PriorityCalculator::allowVisibleOnlyCutoff())) + m_memoryVisibleBytes += texture->bytes(); + if (PriorityCalculator::priorityIsHigher(texture->requestPriority(), PriorityCalculator::allowVisibleAndNearbyCutoff())) + m_memoryVisibleAndNearbyBytes += texture->bytes(); + } std::sort(sortedTextures.begin(), sortedTextures.end(), compareTextures); // Compute a priority cutoff based on memory pressure @@ -118,6 +142,10 @@ void PrioritizedTextureManager::pushTexturePrioritiesToBackings() (*it)->updatePriority(); sortBackings(); assertInvariants(); + + // Push memory requirements to the impl thread structure. + m_memoryVisibleLastPushedBytes = m_memoryVisibleBytes; + m_memoryVisibleAndNearbyLastPushedBytes = m_memoryVisibleAndNearbyBytes; } void PrioritizedTextureManager::updateBackingsInDrawingImplTree() diff --git a/cc/prioritized_texture_manager.h b/cc/prioritized_texture_manager.h index 47f283a..952b584 100644 --- a/cc/prioritized_texture_manager.h +++ b/cc/prioritized_texture_manager.h @@ -69,6 +69,10 @@ public: // than this cutoff will be allowed. void setExternalPriorityCutoff(int priorityCutoff) { m_externalPriorityCutoff = priorityCutoff; } + // Return the amount of texture memory required at particular cutoffs. + size_t memoryVisibleBytes() const; + size_t memoryVisibleAndNearbyBytes() const; + void prioritizeTextures(); void clearPriorities(); @@ -174,6 +178,14 @@ private: TextureVector m_tempTextureVector; + // Statistics about memory usage at priority cutoffs, computed at prioritizeTextures. + size_t m_memoryVisibleBytes; + size_t m_memoryVisibleAndNearbyBytes; + + // Statistics copied at the time of pushTexturePrioritiesToBackings. + size_t m_memoryVisibleLastPushedBytes; + size_t m_memoryVisibleAndNearbyLastPushedBytes; + DISALLOW_COPY_AND_ASSIGN(PrioritizedTextureManager); }; diff --git a/cc/prioritized_texture_unittest.cc b/cc/prioritized_texture_unittest.cc index c223870..61c80d3 100644 --- a/cc/prioritized_texture_unittest.cc +++ b/cc/prioritized_texture_unittest.cc @@ -642,4 +642,67 @@ TEST_F(PrioritizedTextureTest, clearUploadsToEvictedResources) } +TEST_F(PrioritizedTextureTest, usageStatistics) +{ + const size_t maxTextures = 5; + scoped_ptr<PrioritizedTextureManager> textureManager = createManager(maxTextures); + scoped_ptr<PrioritizedTexture> textures[maxTextures]; + + for (size_t i = 0; i < maxTextures; ++i) + textures[i] = textureManager->createTexture(m_textureSize, m_textureFormat); + + textures[0]->setRequestPriority(PriorityCalculator::allowVisibleOnlyCutoff() - 1); + textures[1]->setRequestPriority(PriorityCalculator::allowVisibleOnlyCutoff()); + textures[2]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff() - 1); + textures[3]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff()); + textures[4]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff() + 1); + + // Set max limit to 2 textures. + textureManager->setMaxMemoryLimitBytes(texturesMemorySize(2)); + prioritizeTexturesAndBackings(textureManager.get()); + + // The first two textures should be available, others should not. + for (size_t i = 0; i < 2; ++i) + EXPECT_TRUE(validateTexture(textures[i], false)); + for (size_t i = 2; i < maxTextures; ++i) + EXPECT_FALSE(validateTexture(textures[i], false)); + + // Validate the statistics. + { + DebugScopedSetImplThread implThread; + EXPECT_EQ(texturesMemorySize(2), textureManager->memoryUseBytes()); + EXPECT_EQ(texturesMemorySize(1), textureManager->memoryVisibleBytes()); + EXPECT_EQ(texturesMemorySize(3), textureManager->memoryVisibleAndNearbyBytes()); + } + + // Re-prioritize the textures, but do not push the values to backings. + textures[0]->setRequestPriority(PriorityCalculator::allowVisibleOnlyCutoff() - 1); + textures[1]->setRequestPriority(PriorityCalculator::allowVisibleOnlyCutoff() - 1); + textures[2]->setRequestPriority(PriorityCalculator::allowVisibleOnlyCutoff() - 1); + textures[3]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff() - 1); + textures[4]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff()); + textureManager->prioritizeTextures(); + + // Verify that we still see the old values. + { + DebugScopedSetImplThread implThread; + EXPECT_EQ(texturesMemorySize(2), textureManager->memoryUseBytes()); + EXPECT_EQ(texturesMemorySize(1), textureManager->memoryVisibleBytes()); + EXPECT_EQ(texturesMemorySize(3), textureManager->memoryVisibleAndNearbyBytes()); + } + + // Push priorities to backings, and verify we see the new values. + { + DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked; + textureManager->pushTexturePrioritiesToBackings(); + EXPECT_EQ(texturesMemorySize(2), textureManager->memoryUseBytes()); + EXPECT_EQ(texturesMemorySize(3), textureManager->memoryVisibleBytes()); + EXPECT_EQ(texturesMemorySize(4), textureManager->memoryVisibleAndNearbyBytes()); + } + + DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked; + textureManager->clearAllMemory(resourceProvider()); +} + + } // namespace diff --git a/cc/priority_calculator.cc b/cc/priority_calculator.cc index e2bb0c7..fc250d9 100644 --- a/cc/priority_calculator.cc +++ b/cc/priority_calculator.cc @@ -27,6 +27,10 @@ static const int visibleOnlyPriorityCutoff = 4; static const int notVisibleBasePriority = 1000000; static const int notVisibleLimitPriority = 1900000; +// Arbitrarily define "nearby" to be 2000 pixels. A better estimate +// would be percent-of-viewport or percent-of-screen. +static const int visibleAndNearbyPriorityCutoff = notVisibleBasePriority + 2000; + // Small animated layers are treated as though they are 512 pixels // from being visible. static const int smallAnimatedLayerPriority = notVisibleBasePriority + 512; @@ -116,6 +120,12 @@ int PriorityCalculator::allowVisibleOnlyCutoff() } // static +int PriorityCalculator::allowVisibleAndNearbyCutoff() +{ + return visibleAndNearbyPriorityCutoff; +} + +// static int PriorityCalculator::allowEverythingCutoff() { return everythingPriorityCutoff; diff --git a/cc/priority_calculator.h b/cc/priority_calculator.h index e8daa90..761b6d5 100644 --- a/cc/priority_calculator.h +++ b/cc/priority_calculator.h @@ -27,6 +27,7 @@ public: static int allowNothingCutoff(); static int allowVisibleOnlyCutoff(); + static int allowVisibleAndNearbyCutoff(); static int allowEverythingCutoff(); }; diff --git a/cc/renderer.h b/cc/renderer.h index 5edd957..dfb6a87 100644 --- a/cc/renderer.h +++ b/cc/renderer.h @@ -67,6 +67,8 @@ public: virtual void setVisible(bool) = 0; + virtual void sendManagedMemoryStats(size_t bytesVisible, size_t bytesVisibleAndNearby, size_t bytesAllocated) = 0; + protected: explicit Renderer(RendererClient* client) : m_client(client) diff --git a/cc/single_thread_proxy.cc b/cc/single_thread_proxy.cc index 9667e75..d9918fa 100644 --- a/cc/single_thread_proxy.cc +++ b/cc/single_thread_proxy.cc @@ -286,6 +286,16 @@ bool SingleThreadProxy::reduceContentsTextureMemoryOnImplThread(size_t limitByte return m_layerTreeHost->contentsTextureManager()->reduceMemoryOnImplThread(limitBytes, priorityCutoff, m_layerTreeHostImpl->resourceProvider()); } +void SingleThreadProxy::sendManagedMemoryStats() +{ + DCHECK(Proxy::isImplThread()); + if (m_layerTreeHostImpl.get() && m_layerTreeHostImpl->renderer()) + m_layerTreeHostImpl->renderer()->sendManagedMemoryStats( + m_layerTreeHost->contentsTextureManager()->memoryVisibleBytes(), + m_layerTreeHost->contentsTextureManager()->memoryVisibleAndNearbyBytes(), + m_layerTreeHost->contentsTextureManager()->memoryUseBytes()); +} + // Called by the legacy scheduling path (e.g. where render_widget does the scheduling) void SingleThreadProxy::compositeImmediately() { diff --git a/cc/single_thread_proxy.h b/cc/single_thread_proxy.h index 5b5e208..9ade5f8 100644 --- a/cc/single_thread_proxy.h +++ b/cc/single_thread_proxy.h @@ -54,6 +54,7 @@ public: virtual void setNeedsCommitOnImplThread() OVERRIDE; virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector>, double wallClockTime) OVERRIDE; virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE; + virtual void sendManagedMemoryStats() OVERRIDE; // Called by the legacy path where RenderWidget does the scheduling. void compositeImmediately(); diff --git a/cc/software_renderer.h b/cc/software_renderer.h index 92961ca..1f1604b 100644 --- a/cc/software_renderer.h +++ b/cc/software_renderer.h @@ -36,6 +36,8 @@ public: virtual void setVisible(bool) OVERRIDE; + virtual void sendManagedMemoryStats(size_t bytesVisible, size_t bytesVisibleAndNearby, size_t bytesAllocated) OVERRIDE { } + protected: virtual void bindFramebufferToOutputSurface(DrawingFrame&) OVERRIDE; virtual bool bindFramebufferToTexture(DrawingFrame&, const ScopedTexture*, const gfx::Rect& framebufferRect) OVERRIDE; diff --git a/cc/thread_proxy.cc b/cc/thread_proxy.cc index 94685da..ace26b5 100644 --- a/cc/thread_proxy.cc +++ b/cc/thread_proxy.cc @@ -368,6 +368,16 @@ bool ThreadProxy::reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int return true; } +void ThreadProxy::sendManagedMemoryStats() +{ + DCHECK(isImplThread()); + if (m_layerTreeHostImpl.get() && m_layerTreeHostImpl->renderer()) + m_layerTreeHostImpl->renderer()->sendManagedMemoryStats( + m_layerTreeHost->contentsTextureManager()->memoryVisibleBytes(), + m_layerTreeHost->contentsTextureManager()->memoryVisibleAndNearbyBytes(), + m_layerTreeHost->contentsTextureManager()->memoryUseBytes()); +} + void ThreadProxy::setNeedsRedraw() { DCHECK(isMainThread()); diff --git a/cc/thread_proxy.h b/cc/thread_proxy.h index aab144a..58c8fd4 100644 --- a/cc/thread_proxy.h +++ b/cc/thread_proxy.h @@ -62,6 +62,7 @@ public: virtual void setNeedsCommitOnImplThread() OVERRIDE; virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector>, double wallClockTime) OVERRIDE; virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE; + virtual void sendManagedMemoryStats() OVERRIDE; // SchedulerClient implementation virtual void scheduledActionBeginFrame() OVERRIDE; |