Centralize computation of GrRenderTarget & GrTexture VRAM consumption
authorRobert Phillips <robertphillips@google.com>
Thu, 3 Nov 2016 14:19:14 +0000 (10:19 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Thu, 3 Nov 2016 16:44:50 +0000 (16:44 +0000)
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4310

Change-Id: I676749ecf1e489f825799b619a15a45fc7dcd219
Reviewed-on: https://skia-review.googlesource.com/4310
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>

include/gpu/GrRenderTarget.h
include/gpu/GrTexture.h
include/private/GrSurfaceProxy.h
src/gpu/GrRenderTarget.cpp
src/gpu/GrRenderTargetProxy.cpp
src/gpu/GrTexture.cpp
src/gpu/GrTextureProxy.cpp
src/gpu/gl/GrGLRenderTarget.cpp
src/gpu/gl/GrGLRenderTarget.h
src/gpu/vk/GrVkRenderTarget.cpp
src/gpu/vk/GrVkRenderTarget.h

index dcbe8ea974aa64d3c8269a1a2adfd42d740ba21a..ad96229dc72a03411f5342639acd0553329173c0 100644 (file)
@@ -119,6 +119,8 @@ public:
         return (GrRenderTargetOpList*) this->getLastOpList();
     }
 
+    static size_t ComputeSize(const GrSurfaceDesc& desc, int colorValuesPerPixel);
+
 protected:
     enum class Flags {
         kNone                = 0,
index 211f1937da72b32740e769014a7735ee89b3fadd..c86496c3cf506be6771b6fa3b14681464d787940 100644 (file)
@@ -45,6 +45,8 @@ public:
     inline GrTexturePriv texturePriv();
     inline const GrTexturePriv texturePriv() const;
 
+    static size_t ComputeSize(const GrSurfaceDesc&, bool hasMipMaps);
+
 protected:
     GrTexture(GrGpu*, const GrSurfaceDesc&, GrSLType, bool wasMipMapDataProvided);
 
index 37669fee1926eb61bee17999299331905b0b8386..e748853cfd09d09a6b4a881ea2ae5a552c24e208 100644 (file)
@@ -120,10 +120,6 @@ public:
      * @return the amount of GPU memory used in bytes
      */
     size_t gpuMemorySize() const {
-        if (fTarget) {
-            return fTarget->gpuMemorySize();
-        }
-
         if (kInvalidGpuMemorySize == fGpuMemorySize) {
             fGpuMemorySize = this->onGpuMemorySize();
             SkASSERT(kInvalidGpuMemorySize != fGpuMemorySize);
@@ -154,15 +150,17 @@ protected:
     const uint32_t      fUniqueID; // set from the backing resource for wrapped resources
 
     static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);
+    SkDEBUGCODE(size_t getRawGpuMemorySize_debugOnly() const { return fGpuMemorySize; })
+
+private:
+    virtual size_t onGpuMemorySize() const = 0;
+
     // This entry is lazily evaluated so, when the proxy wraps a resource, the resource
     // will be called but, when the proxy is deferred, it will compute the answer itself.
     // If the proxy computes its own answer that answer is checked (in debug mode) in
     // the instantiation method.
     mutable size_t      fGpuMemorySize;
 
-private:
-    virtual size_t onGpuMemorySize() const = 0;
-
     // The last opList that wrote to or is currently going to write to this surface
     // The opList can be closed (e.g., no render target context is currently bound
     // to this renderTarget).
@@ -171,6 +169,7 @@ private:
     // and the opList of a destination surface to which this one is being drawn or copied.
     GrOpList* fLastOpList;
 
+
     typedef GrIORefProxy INHERITED;
 };
 
index e7782cc85204dd2de122f90be691ca9af6c9cc5b..282886643581b2272ca853d20597720909e3e747 100644 (file)
@@ -84,12 +84,23 @@ void GrRenderTarget::onAbandon() {
     INHERITED::onAbandon();
 }
 
+size_t GrRenderTarget::ComputeSize(const GrSurfaceDesc& desc, int colorValuesPerPixel) {
+    SkASSERT(kUnknown_GrPixelConfig != desc.fConfig);
+    SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
+    size_t colorBytes = GrBytesPerPixel(desc.fConfig);
+    SkASSERT(colorBytes > 0);
+
+    size_t rtSize = colorValuesPerPixel * desc.fWidth * desc.fHeight * colorBytes;
+    SkASSERT(rtSize <= WorstCaseSize(desc));
+    return rtSize;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 bool GrRenderTargetPriv::attachStencilAttachment(GrStencilAttachment* stencil) {
     if (!stencil && !fRenderTarget->fStencilAttachment) {
         // No need to do any work since we currently don't have a stencil attachment and
-        // we're not acctually adding one.
+        // we're not actually adding one.
         return true;
     }
     fRenderTarget->fStencilAttachment = stencil;
@@ -122,3 +133,4 @@ int GrRenderTargetPriv::maxWindowRectangles() const {
     return (this->flags() & Flags::kWindowRectsSupport) ?
            fRenderTarget->getGpu()->caps()->maxWindowRectangles() : 0;
 }
+
index d965e6b6291cb00393c37a9fafeacc91652af9b9..ac8f5edb764139d8982c486a0f146d1c085897c0 100644 (file)
@@ -54,8 +54,8 @@ GrRenderTarget* GrRenderTargetProxy::instantiate(GrTextureProvider* texProvider)
     }
 
 #ifdef SK_DEBUG
-    if (kInvalidGpuMemorySize != fGpuMemorySize) {
-        SkASSERT(fTarget->gpuMemorySize() <= fGpuMemorySize);    
+    if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
+        SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());    
     }
 #endif
 
@@ -81,13 +81,8 @@ size_t GrRenderTargetProxy::onGpuMemorySize() const {
         return fTarget->gpuMemorySize();
     }
 
-    SkASSERT(kUnknown_GrPixelConfig != fDesc.fConfig);
-    SkASSERT(!GrPixelConfigIsCompressed(fDesc.fConfig));
-    size_t colorBytes = GrBytesPerPixel(fDesc.fConfig);
-    SkASSERT(colorBytes > 0);
-
     // TODO: do we have enough information to improve this worst case estimate?
-    return (fDesc.fSampleCnt + 1) * fDesc.fWidth * fDesc.fHeight * colorBytes;
+    return GrRenderTarget::ComputeSize(fDesc, fDesc.fSampleCnt+1);
 }
 
 sk_sp<GrRenderTargetProxy> GrRenderTargetProxy::Make(const GrCaps& caps,
index bb1a6bb08111fb86a7cbdcaff9cdc87a5a62d708..91036bc156795c9afcad12fe2f38253f783369a0 100644 (file)
@@ -35,27 +35,31 @@ void GrTexture::dirtyMipMaps(bool mipMapsDirty) {
     }
 }
 
-size_t GrTexture::onGpuMemorySize() const {
+size_t GrTexture::ComputeSize(const GrSurfaceDesc& desc, bool hasMipMaps) {
     size_t textureSize;
 
-    if (GrPixelConfigIsCompressed(fDesc.fConfig)) {
-        textureSize = GrCompressedFormatDataSize(fDesc.fConfig, fDesc.fWidth, fDesc.fHeight);
+    if (GrPixelConfigIsCompressed(desc.fConfig)) {
+        textureSize = GrCompressedFormatDataSize(desc.fConfig, desc.fWidth, desc.fHeight);
     } else {
-        textureSize = (size_t) fDesc.fWidth * fDesc.fHeight * GrBytesPerPixel(fDesc.fConfig);
+        textureSize = (size_t) desc.fWidth * desc.fHeight * GrBytesPerPixel(desc.fConfig);
     }
 
-    if (this->texturePriv().hasMipMaps()) {
+    if (hasMipMaps) {
         // We don't have to worry about the mipmaps being a different size than
         // we'd expect because we never change fDesc.fWidth/fHeight.
         textureSize += textureSize/3;
     }
 
-    SkASSERT(!SkToBool(fDesc.fFlags & kRenderTarget_GrSurfaceFlag));
-    SkASSERT(textureSize <= WorstCaseSize(fDesc));
+    SkASSERT(!SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag));
+    SkASSERT(textureSize <= WorstCaseSize(desc));
 
     return textureSize;
 }
 
+size_t GrTexture::onGpuMemorySize() const {
+    return ComputeSize(fDesc, this->texturePriv().hasMipMaps());
+}
+
 void GrTexture::validateDesc() const {
     if (this->asRenderTarget()) {
         // This texture has a render target
index 9aae7057c4999d3e7946a14961c9fe978dc8fc05..d60bf90ba47065d87a6232512a22273a1ff111c1 100644 (file)
@@ -31,8 +31,8 @@ GrTexture* GrTextureProxy::instantiate(GrTextureProvider* texProvider) {
     }
 
 #ifdef SK_DEBUG
-    if (kInvalidGpuMemorySize != fGpuMemorySize) {
-        SkASSERT(fTarget->gpuMemorySize() <= fGpuMemorySize);
+    if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
+        SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
     }
 #endif
 
@@ -40,21 +40,13 @@ GrTexture* GrTextureProxy::instantiate(GrTextureProvider* texProvider) {
 }
 
 size_t GrTextureProxy::onGpuMemorySize() const {
-    size_t textureSize;
-
-    if (GrPixelConfigIsCompressed(fDesc.fConfig)) {
-        textureSize = GrCompressedFormatDataSize(fDesc.fConfig, fDesc.fWidth, fDesc.fHeight);
-    } else {
-        textureSize = (size_t) fDesc.fWidth * fDesc.fHeight * GrBytesPerPixel(fDesc.fConfig);
+    if (fTarget) {
+        return fTarget->gpuMemorySize();
     }
 
+    static const bool kHasMipMaps = true;
     // TODO: add tracking of mipmap state to improve the estimate
-    textureSize += textureSize/3;
-
-    SkASSERT(!SkToBool(fDesc.fFlags & kRenderTarget_GrSurfaceFlag));
-    SkASSERT(textureSize <= GrSurface::WorstCaseSize(fDesc));
-
-    return textureSize;
+    return GrTexture::ComputeSize(fDesc, kHasMipMaps);
 }
 
 sk_sp<GrTextureProxy> GrTextureProxy::Make(GrTextureProvider* texProvider,
index 65366bd380f4ebe789835d64506e9797901ebe29..2f92e0a82da389ae6436845fe8c8b8503e970eaf 100644 (file)
@@ -59,9 +59,7 @@ void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
     fViewport.fWidth  = desc.fWidth;
     fViewport.fHeight = desc.fHeight;
 
-    fGpuMemorySize = this->totalSamples() * this->totalBytesPerSample();
-
-    SkASSERT(fGpuMemorySize <= WorstCaseSize(desc));
+    fNumSamplesOwnedPerPixel = this->totalSamples();
 }
 
 sk_sp<GrGLRenderTarget> GrGLRenderTarget::MakeWrapped(GrGLGpu* gpu,
@@ -84,7 +82,7 @@ sk_sp<GrGLRenderTarget> GrGLRenderTarget::MakeWrapped(GrGLGpu* gpu,
 }
 
 size_t GrGLRenderTarget::onGpuMemorySize() const {
-    return fGpuMemorySize;
+    return GrRenderTarget::ComputeSize(fDesc, fNumSamplesOwnedPerPixel);
 }
 
 bool GrGLRenderTarget::completeStencilAttachment() {
@@ -185,7 +183,7 @@ void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump)
     // 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();
+        size_t size = GrRenderTarget::ComputeSize(fDesc, this->msaaSamples());
 
         // Due to this resource having both a texture and a renderbuffer component, dump as
         // skia/gpu_resources/resource_#/renderbuffer
@@ -206,15 +204,6 @@ void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump)
     }
 }
 
-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
index 08dd88d523716e2cfbcfac814f66d209b6a306de..fc18e304377d68c16c6d3108568a67c921973cf1 100644 (file)
@@ -89,8 +89,6 @@ 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;
@@ -106,9 +104,10 @@ private:
     // we want the rendering to be at top left (GL has origin in bottom left)
     GrGLIRect   fViewport;
 
-    // onGpuMemorySize() needs to know the VRAM footprint of the FBO(s). However, abandon and
-    // release zero out the IDs and the cache needs to know the size even after those actions.
-    size_t      fGpuMemorySize;
+    // The RenderTarget needs to be able to report its VRAM footprint even after abandon and
+    // release have potentially zeroed out the IDs (e.g., so the cache can reset itself). Since
+    // the IDs are just required for the computation in totalSamples we cache that result here.
+    int         fNumSamplesOwnedPerPixel;
 
     typedef GrRenderTarget INHERITED;
 };
index e2f0019d9c53f60089edf2d46d6def7bc65e6ac9..278c939c22b0dba108111dd94f2542eb27a7cef8 100644 (file)
@@ -39,8 +39,6 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
     , fFramebuffer(nullptr)
     , fCachedSimpleRenderPass(nullptr) {
     SkASSERT(desc.fSampleCnt);
-    // The plus 1 is to account for the resolve texture.
-    fColorValuesPerPixel = desc.fSampleCnt + 1; // TODO: this still correct?
     this->createFramebuffer(gpu);
     this->registerWithCache(budgeted);
 }
@@ -64,8 +62,6 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
     , fFramebuffer(nullptr)
     , fCachedSimpleRenderPass(nullptr) {
     SkASSERT(desc.fSampleCnt);
-    // The plus 1 is to account for the resolve texture.
-    fColorValuesPerPixel = desc.fSampleCnt + 1; // TODO: this still correct?
     this->createFramebuffer(gpu);
 }
 
@@ -86,7 +82,6 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
     , fFramebuffer(nullptr)
     , fCachedSimpleRenderPass(nullptr) {
     SkASSERT(!desc.fSampleCnt);
-    fColorValuesPerPixel = 1;
     this->createFramebuffer(gpu);
     this->registerWithCache(budgeted);
 }
@@ -107,7 +102,6 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
     , fFramebuffer(nullptr)
     , fCachedSimpleRenderPass(nullptr) {
     SkASSERT(!desc.fSampleCnt);
-    fColorValuesPerPixel = 1;
     this->createFramebuffer(gpu);
 }
 
index 0855a6d02000650ab9975c79295026a116047dce..2e2f60a5fd109eefdcf6e372afffd2174a1e082d 100644 (file)
@@ -99,11 +99,8 @@ protected:
 
     // This accounts for the texture's memory and any MSAA renderbuffer's memory.
     size_t onGpuMemorySize() const override {
-        SkASSERT(kUnknown_GrPixelConfig != fDesc.fConfig);
-        SkASSERT(!GrPixelConfigIsCompressed(fDesc.fConfig));
-        size_t colorBytes = GrBytesPerPixel(fDesc.fConfig);
-        SkASSERT(colorBytes > 0);
-        return fColorValuesPerPixel * fDesc.fWidth * fDesc.fHeight * colorBytes;
+        // The plus 1 is to account for the resolve texture.
+        return GrRenderTarget::ComputeSize(fDesc, fDesc.fSampleCnt+1); // TODO: this still correct?
     }
 
     void createFramebuffer(GrVkGpu* gpu);
@@ -138,7 +135,6 @@ private:
     void abandonInternalObjects();
 
     const GrVkFramebuffer*     fFramebuffer;
-    int                        fColorValuesPerPixel;
 
     // This is a cached pointer to a simple render pass. The render target should unref it
     // once it is done with it.