Add onMemoryDump to GrContext
Adds an entry point to GrContext to allow enumeration and tracing of GPU resources via the newly added SkTraceMemoryDump. Plan is for Chrome to call this on each of its GrContexts. Dumps both the total size of GPU resources, as well as the total purgeable size. BUG=526261 Review URL: https://codereview.chromium.org/1313743002
This commit is contained in:
parent
eb00eaba0c
commit
0a5fa484fd
@ -336,6 +336,7 @@
|
||||
'<(skia_src_path)/gpu/gl/GrGLStencilAttachment.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLTexture.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLTexture.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLTextureRenderTarget.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLTextureRenderTarget.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLUtil.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLUtil.h',
|
||||
|
@ -43,6 +43,7 @@ class GrTextureParams;
|
||||
class GrVertexBuffer;
|
||||
class GrStrokeInfo;
|
||||
class GrSoftwarePathRenderer;
|
||||
class SkTraceMemoryDump;
|
||||
|
||||
class SK_API GrContext : public SkRefCnt {
|
||||
public:
|
||||
@ -358,6 +359,9 @@ public:
|
||||
to an array of 3 entries */
|
||||
void setTextContextAtlasSizes_ForTesting(const GrBatchAtlasConfig* configs);
|
||||
|
||||
/** Enumerates all cached GPU resources and dumps their memory to traceMemoryDump. */
|
||||
void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
|
||||
|
||||
private:
|
||||
GrGpu* fGpu;
|
||||
const GrCaps* fCaps;
|
||||
|
@ -15,6 +15,7 @@
|
||||
class GrContext;
|
||||
class GrGpu;
|
||||
class GrResourceCache;
|
||||
class SkTraceMemoryDump;
|
||||
|
||||
/**
|
||||
* Base class for GrGpuResource. Handles the various types of refs we need. Separated out as a base
|
||||
@ -138,7 +139,7 @@ private:
|
||||
*/
|
||||
class SK_API GrGpuResource : public GrIORef<GrGpuResource> {
|
||||
public:
|
||||
|
||||
|
||||
|
||||
enum LifeCycle {
|
||||
/**
|
||||
@ -252,6 +253,13 @@ public:
|
||||
*/
|
||||
void abandon();
|
||||
|
||||
/**
|
||||
* Dumps memory usage information for this GrGpuResource to traceMemoryDump.
|
||||
* Typically, subclasses should not need to override this, and should only
|
||||
* need to override setMemoryBacking.
|
||||
**/
|
||||
virtual void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
|
||||
|
||||
protected:
|
||||
// This must be called by every GrGpuObject. It should be called once the object is fully
|
||||
// initialized (i.e. not in a base class constructor).
|
||||
@ -288,6 +296,12 @@ protected:
|
||||
**/
|
||||
void setScratchKey(const GrScratchKey& scratchKey);
|
||||
|
||||
/**
|
||||
* Allows subclasses to add additional backing information to the SkTraceMemoryDump. Called by
|
||||
* onMemoryDump. The default implementation adds no backing information.
|
||||
**/
|
||||
virtual void setMemoryBacking(SkTraceMemoryDump*, const SkString&) const {}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Frees the object in the underlying 3D API. Called by CacheAccess.
|
||||
|
@ -105,7 +105,7 @@ void GrContext::DrawingMgr::flush() {
|
||||
}
|
||||
}
|
||||
|
||||
GrDrawContext* GrContext::DrawingMgr::drawContext(const SkSurfaceProps* surfaceProps) {
|
||||
GrDrawContext* GrContext::DrawingMgr::drawContext(const SkSurfaceProps* surfaceProps) {
|
||||
if (this->abandoned()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -119,7 +119,7 @@ GrDrawContext* GrContext::DrawingMgr::drawContext(const SkSurfaceProps* surfaceP
|
||||
}
|
||||
|
||||
// For now, everyone gets a faux creation ref
|
||||
return SkRef(fDrawContext[props.pixelGeometry()][props.isUseDeviceIndependentFonts()]);
|
||||
return SkRef(fDrawContext[props.pixelGeometry()][props.isUseDeviceIndependentFonts()]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -759,3 +759,8 @@ void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes)
|
||||
fResourceCache->setLimits(maxTextures, maxTextureBytes);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
|
||||
fResourceCache->dumpMemoryStatistics(traceMemoryDump);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "GrResourceCache.h"
|
||||
#include "GrGpu.h"
|
||||
#include "GrGpuResourcePriv.h"
|
||||
#include "SkTraceMemoryDump.h"
|
||||
|
||||
static inline GrResourceCache* get_resource_cache(GrGpu* gpu) {
|
||||
SkASSERT(gpu);
|
||||
@ -52,6 +53,23 @@ void GrGpuResource::abandon() {
|
||||
fGpuMemorySize = 0;
|
||||
}
|
||||
|
||||
void GrGpuResource::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
|
||||
// Dump resource as "skia/gpu_resources/resource_#".
|
||||
SkString dumpName("skia/gpu_resources/resource_");
|
||||
dumpName.appendS32(this->getUniqueID());
|
||||
|
||||
traceMemoryDump->dumpNumericValue(dumpName.c_str(), "size", "bytes", this->gpuMemorySize());
|
||||
|
||||
if (this->isPurgeable()) {
|
||||
traceMemoryDump->dumpNumericValue(dumpName.c_str(), "purgeable_size", "bytes",
|
||||
this->gpuMemorySize());
|
||||
}
|
||||
|
||||
// Call setMemoryBacking to allow sub-classes with implementation specific backings (such as GL
|
||||
// objects) to provide additional information.
|
||||
this->setMemoryBacking(traceMemoryDump, dumpName);
|
||||
}
|
||||
|
||||
const SkData* GrGpuResource::setCustomData(const SkData* data) {
|
||||
SkSafeRef(data);
|
||||
fData.reset(data);
|
||||
|
@ -616,6 +616,15 @@ void GrResourceCache::notifyFlushOccurred() {
|
||||
}
|
||||
}
|
||||
|
||||
void GrResourceCache::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
|
||||
for (int i = 0; i < fNonpurgeableResources.count(); ++i) {
|
||||
fNonpurgeableResources[i]->dumpMemoryStatistics(traceMemoryDump);
|
||||
}
|
||||
for (int i = 0; i < fPurgeableQueue.count(); ++i) {
|
||||
fPurgeableQueue.at(i)->dumpMemoryStatistics(traceMemoryDump);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void GrResourceCache::validate() const {
|
||||
// Reduce the frequency of validations for large resource counts.
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
class GrCaps;
|
||||
class SkString;
|
||||
class SkTraceMemoryDump;
|
||||
|
||||
/**
|
||||
* Manages the lifetime of all GrGpuResource instances.
|
||||
@ -178,7 +179,7 @@ public:
|
||||
fOverBudgetCB = overBudgetCB;
|
||||
fOverBudgetData = data;
|
||||
}
|
||||
|
||||
|
||||
void notifyFlushOccurred();
|
||||
|
||||
#if GR_GPU_STATS
|
||||
@ -188,6 +189,9 @@ public:
|
||||
// This function is for unit testing and is only defined in test tools.
|
||||
void changeTimestamp(uint32_t newTimestamp);
|
||||
|
||||
// Enumerates all cached resources and dumps their details to traceMemoryDump.
|
||||
void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
|
||||
|
||||
private:
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// @name Methods accessible via ResourceAccess
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "GrGLIndexBuffer.h"
|
||||
#include "GrGLGpu.h"
|
||||
#include "SkTraceMemoryDump.h"
|
||||
|
||||
GrGLIndexBuffer::GrGLIndexBuffer(GrGLGpu* gpu, const Desc& desc)
|
||||
: INHERITED(gpu, desc.fSizeInBytes, desc.fDynamic, 0 == desc.fID)
|
||||
@ -48,3 +49,11 @@ bool GrGLIndexBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLIndexBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
|
||||
const SkString& dumpName) const {
|
||||
SkString buffer_id;
|
||||
buffer_id.appendU32(this->bufferID());
|
||||
traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer",
|
||||
buffer_id.c_str());
|
||||
}
|
||||
|
@ -33,6 +33,8 @@ public:
|
||||
protected:
|
||||
void onAbandon() override;
|
||||
void onRelease() override;
|
||||
void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
|
||||
const SkString& dumpName) const override;
|
||||
|
||||
private:
|
||||
void* onMap() override;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "GrRenderTargetPriv.h"
|
||||
#include "GrGLGpu.h"
|
||||
#include "GrGLUtil.h"
|
||||
#include "SkTraceMemoryDump.h"
|
||||
|
||||
#define GPUGL static_cast<GrGLGpu*>(this->getGpu())
|
||||
#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
|
||||
@ -43,20 +44,7 @@ void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
|
||||
fViewport.fWidth = desc.fWidth;
|
||||
fViewport.fHeight = desc.fHeight;
|
||||
|
||||
// We own one color value for each MSAA sample.
|
||||
int colorValuesPerPixel = SkTMax(1, fDesc.fSampleCnt);
|
||||
if (fTexFBOID != kUnresolvableFBOID && fTexFBOID != fRTFBOID) {
|
||||
// If we own the resolve buffer then that is one more sample per pixel.
|
||||
colorValuesPerPixel += 1;
|
||||
} else if (fTexFBOID != 0) {
|
||||
// For auto-resolving FBOs, the MSAA buffer is free.
|
||||
colorValuesPerPixel = 1;
|
||||
}
|
||||
SkASSERT(kUnknown_GrPixelConfig != fDesc.fConfig);
|
||||
SkASSERT(!GrPixelConfigIsCompressed(fDesc.fConfig));
|
||||
size_t colorBytes = GrBytesPerPixel(fDesc.fConfig);
|
||||
SkASSERT(colorBytes > 0);
|
||||
fGpuMemorySize = colorValuesPerPixel * fDesc.fWidth * fDesc.fHeight * colorBytes;
|
||||
fGpuMemorySize = this->totalSamples() * this->totalBytesPerSample();
|
||||
|
||||
SkASSERT(fGpuMemorySize <= WorseCaseSize(desc));
|
||||
}
|
||||
@ -160,3 +148,62 @@ GrGLGpu* GrGLRenderTarget::getGLGpu() const {
|
||||
return static_cast<GrGLGpu*>(this->getGpu());
|
||||
}
|
||||
|
||||
void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
|
||||
// Don't log the backing texture's contribution to the memory size. This will be handled by the
|
||||
// texture object.
|
||||
|
||||
// Log any renderbuffer's contribution to memory. We only do this if we own the renderbuffer
|
||||
// (have a fMSColorRenderbufferID).
|
||||
if (fMSColorRenderbufferID) {
|
||||
size_t size = this->msaaSamples() * this->totalBytesPerSample();
|
||||
|
||||
// Due to this resource having both a texture and a renderbuffer component, dump as
|
||||
// skia/gpu_resources/resource_#/renderbuffer
|
||||
SkString dumpName("skia/gpu_resources/resource_");
|
||||
dumpName.appendS32(this->getUniqueID());
|
||||
dumpName.append("/renderbuffer");
|
||||
|
||||
traceMemoryDump->dumpNumericValue(dumpName.c_str(), "size", "bytes", size);
|
||||
|
||||
if (this->isPurgeable()) {
|
||||
traceMemoryDump->dumpNumericValue(dumpName.c_str(), "purgeable_size", "bytes", size);
|
||||
}
|
||||
|
||||
SkString renderbuffer_id;
|
||||
renderbuffer_id.appendU32(fMSColorRenderbufferID);
|
||||
traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_renderbuffer",
|
||||
renderbuffer_id.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
size_t GrGLRenderTarget::totalBytesPerSample() const {
|
||||
SkASSERT(kUnknown_GrPixelConfig != fDesc.fConfig);
|
||||
SkASSERT(!GrPixelConfigIsCompressed(fDesc.fConfig));
|
||||
size_t colorBytes = GrBytesPerPixel(fDesc.fConfig);
|
||||
SkASSERT(colorBytes > 0);
|
||||
|
||||
return fDesc.fWidth * fDesc.fHeight * colorBytes;
|
||||
}
|
||||
|
||||
int GrGLRenderTarget::msaaSamples() const {
|
||||
if (fTexFBOID == kUnresolvableFBOID || fTexFBOID != fRTFBOID) {
|
||||
// If the render target's FBO is external (fTexFBOID == kUnresolvableFBOID), or if we own
|
||||
// the render target's FBO (fTexFBOID == fRTFBOID) then we use the provided sample count.
|
||||
return SkTMax(1, fDesc.fSampleCnt);
|
||||
}
|
||||
|
||||
// When fTexFBOID == fRTFBOID, we either are not using MSAA, or MSAA is auto resolving, so use
|
||||
// 0 for the sample count.
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GrGLRenderTarget::totalSamples() const {
|
||||
int total_samples = this->msaaSamples();
|
||||
|
||||
if (fTexFBOID != kUnresolvableFBOID) {
|
||||
// If we own the resolve buffer then that is one more sample per pixel.
|
||||
total_samples += 1;
|
||||
}
|
||||
|
||||
return total_samples;
|
||||
}
|
||||
|
@ -66,6 +66,10 @@ public:
|
||||
return kCached_LifeCycle == fRTLifecycle || kUncached_LifeCycle == fRTLifecycle;
|
||||
}
|
||||
|
||||
// GrGLRenderTarget overrides dumpMemoryStatistics so it can log its texture and renderbuffer
|
||||
// components seperately.
|
||||
void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;
|
||||
|
||||
protected:
|
||||
// The public constructor registers this object with the cache. However, only the most derived
|
||||
// class should register with the cache. This constructor does not do the registration and
|
||||
@ -89,6 +93,12 @@ private:
|
||||
GrGLGpu* getGLGpu() const;
|
||||
bool completeStencilAttachment() override;
|
||||
|
||||
// The total size of the resource (including all pixels) for a single sample.
|
||||
size_t totalBytesPerSample() const;
|
||||
int msaaSamples() const;
|
||||
// The number total number of samples, including both MSAA and resolve texture samples.
|
||||
int totalSamples() const;
|
||||
|
||||
GrGLuint fRTFBOID;
|
||||
GrGLuint fTexFBOID;
|
||||
GrGLuint fMSColorRenderbufferID;
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "GrGLStencilAttachment.h"
|
||||
#include "GrGLGpu.h"
|
||||
#include "SkTraceMemoryDump.h"
|
||||
|
||||
size_t GrGLStencilAttachment::onGpuMemorySize() const {
|
||||
uint64_t size = this->width();
|
||||
@ -33,3 +34,11 @@ void GrGLStencilAttachment::onAbandon() {
|
||||
|
||||
INHERITED::onAbandon();
|
||||
}
|
||||
|
||||
void GrGLStencilAttachment::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
|
||||
const SkString& dumpName) const {
|
||||
SkString renderbuffer_id;
|
||||
renderbuffer_id.appendU32(this->renderbufferID());
|
||||
traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_renderbuffer",
|
||||
renderbuffer_id.c_str());
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ protected:
|
||||
// overrides of GrResource
|
||||
void onRelease() override;
|
||||
void onAbandon() override;
|
||||
void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
|
||||
const SkString& dumpName) const override;
|
||||
|
||||
private:
|
||||
size_t onGpuMemorySize() const override;
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "GrGLTexture.h"
|
||||
#include "GrGLGpu.h"
|
||||
#include "SkTraceMemoryDump.h"
|
||||
|
||||
#define GPUGL static_cast<GrGLGpu*>(this->getGpu())
|
||||
#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
|
||||
@ -51,3 +52,11 @@ void GrGLTexture::onAbandon() {
|
||||
GrBackendObject GrGLTexture::getTextureHandle() const {
|
||||
return static_cast<GrBackendObject>(this->textureID());
|
||||
}
|
||||
|
||||
void GrGLTexture::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
|
||||
const SkString& dumpName) const {
|
||||
SkString texture_id;
|
||||
texture_id.appendU32(this->textureID());
|
||||
traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_texture",
|
||||
texture_id.c_str());
|
||||
}
|
||||
|
@ -63,6 +63,8 @@ protected:
|
||||
|
||||
void onAbandon() override;
|
||||
void onRelease() override;
|
||||
void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
|
||||
const SkString& dumpName) const override;
|
||||
|
||||
private:
|
||||
TexParams fTexParams;
|
||||
|
39
src/gpu/gl/GrGLTextureRenderTarget.cpp
Normal file
39
src/gpu/gl/GrGLTextureRenderTarget.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrGLTextureRenderTarget.h"
|
||||
|
||||
#include "SkTraceMemoryDump.h"
|
||||
|
||||
// GrGLTextureRenderTarget must dump both of its superclasses.
|
||||
void GrGLTextureRenderTarget::dumpMemoryStatistics(
|
||||
SkTraceMemoryDump* traceMemoryDump) const {
|
||||
GrGLRenderTarget::dumpMemoryStatistics(traceMemoryDump);
|
||||
|
||||
// Also dump the GrGLTexture's memory. Due to this resource having both a
|
||||
// texture and a
|
||||
// renderbuffer component, dump as skia/gpu_resources/resource_#/texture
|
||||
SkString dumpName("skia/gpu_resources/resource_");
|
||||
dumpName.appendS32(this->getUniqueID());
|
||||
dumpName.append("/texture");
|
||||
|
||||
// Use the texture's gpuMemorySize, not our own, which includes the
|
||||
// renderbuffer as well.
|
||||
size_t size = GrGLTexture::gpuMemorySize();
|
||||
|
||||
traceMemoryDump->dumpNumericValue(dumpName.c_str(), "size", "bytes", size);
|
||||
|
||||
if (this->isPurgeable()) {
|
||||
traceMemoryDump->dumpNumericValue(dumpName.c_str(), "purgeable_size",
|
||||
"bytes", size);
|
||||
}
|
||||
|
||||
SkString texture_id;
|
||||
texture_id.appendU32(this->textureID());
|
||||
traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_texture",
|
||||
texture_id.c_str());
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
#ifndef GrGLTextureRenderTarget_DEFINED
|
||||
#define GrGLTextureRenderTarget_DEFINED
|
||||
|
||||
#include "GrGLGpu.h"
|
||||
#include "GrGLTexture.h"
|
||||
#include "GrGLRenderTarget.h"
|
||||
|
||||
@ -34,6 +35,8 @@ public:
|
||||
this->registerWithCache();
|
||||
}
|
||||
|
||||
void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;
|
||||
|
||||
protected:
|
||||
void onAbandon() override {
|
||||
GrGLRenderTarget::onAbandon();
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "GrGLVertexBuffer.h"
|
||||
#include "GrGLGpu.h"
|
||||
#include "SkTraceMemoryDump.h"
|
||||
|
||||
GrGLVertexBuffer::GrGLVertexBuffer(GrGLGpu* gpu, const Desc& desc)
|
||||
: INHERITED(gpu, desc.fSizeInBytes, desc.fDynamic, 0 == desc.fID)
|
||||
@ -48,3 +49,11 @@ bool GrGLVertexBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLVertexBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
|
||||
const SkString& dumpName) const {
|
||||
SkString buffer_id;
|
||||
buffer_id.appendU32(this->bufferID());
|
||||
traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer",
|
||||
buffer_id.c_str());
|
||||
}
|
||||
|
@ -33,6 +33,8 @@ public:
|
||||
protected:
|
||||
void onAbandon() override;
|
||||
void onRelease() override;
|
||||
void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
|
||||
const SkString& dumpName) const override;
|
||||
|
||||
private:
|
||||
void* onMap() override;
|
||||
|
@ -674,6 +674,7 @@ SRCS = ['include/private/SkChecksum.h',
|
||||
'src/gpu/gl/GrGLRenderTarget.cpp',
|
||||
'src/gpu/gl/GrGLStencilAttachment.cpp',
|
||||
'src/gpu/gl/GrGLTexture.cpp',
|
||||
'src/gpu/gl/GrGLTextureRenderTarget.cpp'
|
||||
'src/gpu/gl/GrGLUtil.cpp',
|
||||
'src/gpu/gl/GrGLVertexArray.cpp',
|
||||
'src/gpu/gl/GrGLVertexBuffer.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user