Fix computation of texture size for approximately-fit deferred proxies
authorRobert Phillips <robertphillips@google.com>
Thu, 17 Nov 2016 19:43:51 +0000 (14:43 -0500)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Thu, 17 Nov 2016 20:47:18 +0000 (20:47 +0000)
For approximate-fit deferred proxies asserts were firing when the instantiated size was larger than the pre-computed exact-fit size.

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4972

Change-Id: I879e16b86ab4d9ef9834163c24ccd6507fe4b94a
Reviewed-on: https://skia-review.googlesource.com/4972
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
include/gpu/GrSurface.h
src/gpu/GrRenderTargetProxy.cpp
src/gpu/GrSurface.cpp
src/gpu/GrTextureProxy.cpp
src/gpu/GrTextureRenderTargetProxy.cpp
tests/ProxyTest.cpp

index 3f91a2f..46b9986 100644 (file)
@@ -129,8 +129,9 @@ public:
     void setLastOpList(GrOpList* opList);
     GrOpList* getLastOpList() { return fLastOpList; }
 
-    static size_t WorstCaseSize(const GrSurfaceDesc& desc);
-    static size_t ComputeSize(const GrSurfaceDesc& desc, int colorSamplesPerPixel, bool hasMIPMaps);
+    static size_t WorstCaseSize(const GrSurfaceDesc& desc, bool useNextPow2 = false);
+    static size_t ComputeSize(const GrSurfaceDesc& desc, int colorSamplesPerPixel,
+                              bool hasMIPMaps, bool useNextPow2 = false);
 
 protected:
     // Methods made available via GrSurfacePriv
index 8eb335d..cb9b97a 100644 (file)
@@ -71,6 +71,6 @@ size_t GrRenderTargetProxy::onGpuMemorySize() const {
     }
 
     // TODO: do we have enough information to improve this worst case estimate?
-    return GrSurface::ComputeSize(fDesc, fDesc.fSampleCnt+1, false);
+    return GrSurface::ComputeSize(fDesc, fDesc.fSampleCnt+1, false, SkBackingFit::kApprox == fFit);
 }
 
index 7f571b8..f67bfd4 100644 (file)
@@ -13,6 +13,7 @@
 #include "SkBitmap.h"
 #include "SkGrPriv.h"
 #include "SkImageEncoder.h"
+#include "SkMathPriv.h"
 #include <stdio.h>
 
 GrSurface::~GrSurface() {
@@ -25,9 +26,12 @@ GrSurface::~GrSurface() {
     SkASSERT(NULL == fReleaseProc);
 }
 
-size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc) {
+size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc, bool useNextPow2) {
     size_t size;
 
+    int width = useNextPow2 ? GrNextPow2(desc.fWidth) : desc.fWidth;
+    int height = useNextPow2 ? GrNextPow2(desc.fHeight) : desc.fHeight;
+
     bool isRenderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
     if (isRenderTarget) {
         // We own one color value for each MSAA sample.
@@ -38,7 +42,7 @@ size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc) {
         }
         SkASSERT(kUnknown_GrPixelConfig != desc.fConfig);
         SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
-        size_t colorBytes = (size_t) desc.fWidth * desc.fHeight * GrBytesPerPixel(desc.fConfig);
+        size_t colorBytes = (size_t) width * height * GrBytesPerPixel(desc.fConfig);
 
         // This would be a nice assert to have (i.e., we aren't creating 0 width/height surfaces).
         // Unfortunately Chromium seems to want to do this.
@@ -48,9 +52,9 @@ size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc) {
         size += colorBytes/3; // in case we have to mipmap
     } else {
         if (GrPixelConfigIsCompressed(desc.fConfig)) {
-            size = GrCompressedFormatDataSize(desc.fConfig, desc.fWidth, desc.fHeight);
+            size = GrCompressedFormatDataSize(desc.fConfig, width, height);
         } else {
-            size = (size_t) desc.fWidth * desc.fHeight * GrBytesPerPixel(desc.fConfig);
+            size = (size_t) width * height * GrBytesPerPixel(desc.fConfig);
         }
 
         size += size/3;  // in case we have to mipmap
@@ -61,14 +65,18 @@ size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc) {
 
 size_t GrSurface::ComputeSize(const GrSurfaceDesc& desc,
                               int colorSamplesPerPixel,
-                              bool hasMIPMaps) {
+                              bool hasMIPMaps,
+                              bool useNextPow2) {
     size_t colorSize;
 
+    int width = useNextPow2 ? GrNextPow2(desc.fWidth) : desc.fWidth;
+    int height = useNextPow2 ? GrNextPow2(desc.fHeight) : desc.fHeight;
+
     SkASSERT(kUnknown_GrPixelConfig != desc.fConfig);
     if (GrPixelConfigIsCompressed(desc.fConfig)) {
-        colorSize = GrCompressedFormatDataSize(desc.fConfig, desc.fWidth, desc.fHeight);
+        colorSize = GrCompressedFormatDataSize(desc.fConfig, width, height);
     } else {
-        colorSize = (size_t) desc.fWidth * desc.fHeight * GrBytesPerPixel(desc.fConfig);
+        colorSize = (size_t) width * height * GrBytesPerPixel(desc.fConfig);
     }
     SkASSERT(colorSize > 0);
 
@@ -80,7 +88,7 @@ size_t GrSurface::ComputeSize(const GrSurfaceDesc& desc,
         finalSize += colorSize/3;
     }
 
-    SkASSERT(finalSize <= WorstCaseSize(desc));
+    SkASSERT(finalSize <= WorstCaseSize(desc, useNextPow2));
     return finalSize;
 }
 
index 9798747..77a8402 100644 (file)
@@ -35,5 +35,5 @@ size_t GrTextureProxy::onGpuMemorySize() const {
 
     static const bool kHasMipMaps = true;
     // TODO: add tracking of mipmap state to improve the estimate
-    return GrSurface::ComputeSize(fDesc, 1, kHasMipMaps);
+    return GrSurface::ComputeSize(fDesc, 1, kHasMipMaps, SkBackingFit::kApprox == fFit);
 }
index 95451e9..212ea0a 100644 (file)
@@ -36,6 +36,6 @@ size_t GrTextureRenderTargetProxy::onGpuMemorySize() const {
     }
 
     // TODO: do we have enough information to improve this worst case estimate?
-    return GrSurface::ComputeSize(fDesc, fDesc.fSampleCnt+1, true);
+    return GrSurface::ComputeSize(fDesc, fDesc.fSampleCnt+1, true, SkBackingFit::kApprox == fFit);
 }
 
index 8d59cae..a228e16 100644 (file)
@@ -136,6 +136,13 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredProxyTest, reporter, ctxInfo) {
                                 sk_sp<GrSurfaceProxy> sProxy(GrSurfaceProxy::MakeDeferred(
                                                                                 caps, desc, 
                                                                                 fit, budgeted));
+                                // This forces the proxy to compute and cache its pre-instantiation\r
+                                // size guess. Later, when it is actually instantiated, it checks\r
+                                // that the instantiated size is <= to the pre-computation. \r
+                                // If the proxy never computed its pre-instantiation size then the\r
+                                // check is skipped.\r
+                                sProxy->gpuMemorySize();
+
                                 check_surface(reporter, sProxy.get(), origin,
                                               widthHeight, widthHeight, config,
                                               kInvalidResourceID, budgeted);
@@ -151,6 +158,13 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredProxyTest, reporter, ctxInfo) {
                                                                                       desc,
                                                                                       fit,
                                                                                       budgeted));
+                            // This forces the proxy to compute and cache its pre-instantiation\r
+                            // size guess. Later, when it is actually instantiated, it checks\r
+                            // that the instantiated size is <= to the pre-computation. \r
+                            // If the proxy never computed its pre-instantiation size then the\r
+                            // check is skipped.
+                            sProxy->gpuMemorySize();
+
                             check_surface(reporter, sProxy.get(), origin,
                                           widthHeight, widthHeight, config,
                                           kInvalidResourceID, budgeted);