Alter approximate scratch texture binning after 1024
As the powers-of-2 get larger the coarse binning can burn a lot of VRAM.
Granted it isn't the best metric but, with this CL, the number of textures created and scratch textures reused remains unchanged when running the GMs.
Change-Id: I84abbbae0ed01aabb387671b5ee0e4fcdb82b671
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/226226
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/core/SkMathPriv.h b/src/core/SkMathPriv.h
index fb2389f..d0ce3b2 100644
--- a/src/core/SkMathPriv.h
+++ b/src/core/SkMathPriv.h
@@ -215,7 +215,7 @@
///////////////////////////////////////////////////////////////////////////////
/**
- * Return the next power of 2 >= n.
+ * Return the smallest power-of-2 >= n.
*/
static inline uint32_t GrNextPow2(uint32_t n) {
return n ? (1 << (32 - SkCLZ(n - 1))) : 1;
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 2e23380..79cfbf4 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -569,6 +569,7 @@
out->appendf("Transfers from Surface: %d\n", fTransfersFromSurface);
out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates);
out->appendf("Number of draws: %d\n", fNumDraws);
+ out->appendf("Number of Scratch Textures reused %d\n", fNumScratchTexturesReused);
}
void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) {
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index cf5bbe2..fa64036 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -340,27 +340,41 @@
int renderTargetBinds() const { return fRenderTargetBinds; }
void incRenderTargetBinds() { fRenderTargetBinds++; }
+
int shaderCompilations() const { return fShaderCompilations; }
void incShaderCompilations() { fShaderCompilations++; }
+
int textureCreates() const { return fTextureCreates; }
void incTextureCreates() { fTextureCreates++; }
+
int textureUploads() const { return fTextureUploads; }
void incTextureUploads() { fTextureUploads++; }
+
int transfersToTexture() const { return fTransfersToTexture; }
- int transfersFromSurface() const { return fTransfersFromSurface; }
void incTransfersToTexture() { fTransfersToTexture++; }
+
+ int transfersFromSurface() const { return fTransfersFromSurface; }
void incTransfersFromSurface() { fTransfersFromSurface++; }
+
+ int stencilAttachmentCreates() const { return fStencilAttachmentCreates; }
void incStencilAttachmentCreates() { fStencilAttachmentCreates++; }
+
+ int numDraws() const { return fNumDraws; }
void incNumDraws() { fNumDraws++; }
+
+ int numFailedDraws() const { return fNumFailedDraws; }
void incNumFailedDraws() { ++fNumFailedDraws; }
+
+ int numFinishFlushes() const { return fNumFinishFlushes; }
void incNumFinishFlushes() { ++fNumFinishFlushes; }
+
+ int numScratchTexturesReused() const { return fNumScratchTexturesReused; }
+ void incNumScratchTexturesReused() { ++fNumScratchTexturesReused; }
+
#if GR_TEST_UTILS
void dump(SkString*);
void dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values);
#endif
- int numDraws() const { return fNumDraws; }
- int numFailedDraws() const { return fNumFailedDraws; }
- int numFinishFlushes() const { return fNumFinishFlushes; }
private:
int fRenderTargetBinds = 0;
int fShaderCompilations = 0;
@@ -372,6 +386,7 @@
int fNumDraws = 0;
int fNumFailedDraws = 0;
int fNumFinishFlushes = 0;
+ int fNumScratchTexturesReused = 0;
#else
#if GR_TEST_UTILS
diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp
index 0e171a8..db9ead2 100644
--- a/src/gpu/GrResourceProvider.cpp
+++ b/src/gpu/GrResourceProvider.cpp
@@ -209,6 +209,32 @@
return fGpu->createTexture(desc, budgeted);
}
+// Map 'value' to a larger multiple of 2. Values <= 'kMagicTol' will pop up to
+// the next power of 2. Those above 'kMagicTol' will only go up half the floor power of 2.
+uint32_t GrResourceProvider::MakeApprox(uint32_t value) {
+ static const int kMagicTol = 1024;
+
+ value = SkTMax(kMinScratchTextureSize, value);
+
+ if (SkIsPow2(value)) {
+ return value;
+ }
+
+ uint32_t ceilPow2 = GrNextPow2(value);
+ if (value <= kMagicTol) {
+ return ceilPow2;
+ }
+
+ uint32_t floorPow2 = ceilPow2 >> 1;
+ uint32_t mid = floorPow2 + (floorPow2 >> 1);
+
+ if (value <= mid) {
+ return mid;
+ }
+
+ return ceilPow2;
+}
+
sk_sp<GrTexture> GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc,
Flags flags) {
ASSERT_SINGLE_OWNER
@@ -233,12 +259,12 @@
SkTCopyOnFirstWrite<GrSurfaceDesc> copyDesc(desc);
- // bin by pow2 with a reasonable min
+ // bin by some multiple or power of 2 with a reasonable min
if (!SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag) &&
(fGpu->caps()->reuseScratchTextures() || (desc.fFlags & kRenderTarget_GrSurfaceFlag))) {
GrSurfaceDesc* wdesc = copyDesc.writable();
- wdesc->fWidth = SkTMax(kMinScratchTextureSize, GrNextPow2(desc.fWidth));
- wdesc->fHeight = SkTMax(kMinScratchTextureSize, GrNextPow2(desc.fHeight));
+ wdesc->fWidth = MakeApprox(wdesc->fWidth);
+ wdesc->fHeight = MakeApprox(wdesc->fHeight);
}
if (auto tex = this->refScratchTexture(*copyDesc, flags)) {
@@ -273,6 +299,7 @@
GrSurface::WorstCaseSize(desc),
scratchFlags);
if (resource) {
+ fGpu->stats()->incNumScratchTexturesReused();
GrSurface* surface = static_cast<GrSurface*>(resource);
return sk_sp<GrTexture>(surface->asTexture());
}
diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h
index 46b4710..1ac19ec 100644
--- a/src/gpu/GrResourceProvider.h
+++ b/src/gpu/GrResourceProvider.h
@@ -253,6 +253,8 @@
const GrCaps* caps() const { return fCaps.get(); }
bool overBudget() const { return fCache->overBudget(); }
+ static uint32_t MakeApprox(uint32_t value);
+
inline GrResourceProviderPriv priv();
inline const GrResourceProviderPriv priv() const;
diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp
index d29d50d..87d9e9c 100644
--- a/src/gpu/GrSurface.cpp
+++ b/src/gpu/GrSurface.cpp
@@ -16,15 +16,11 @@
#include "src/core/SkMathPriv.h"
#include "src/gpu/SkGr.h"
-size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc, bool useNextPow2) {
+size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc, bool binSize) {
size_t size;
- int width = useNextPow2
- ? SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(desc.fWidth))
- : desc.fWidth;
- int height = useNextPow2
- ? SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(desc.fHeight))
- : desc.fHeight;
+ int width = binSize ? GrResourceProvider::MakeApprox(desc.fWidth) : desc.fWidth;
+ int height = binSize ? GrResourceProvider::MakeApprox(desc.fHeight) : desc.fHeight;
bool isRenderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
if (isRenderTarget) {
@@ -63,15 +59,11 @@
int height,
int colorSamplesPerPixel,
GrMipMapped mipMapped,
- bool useNextPow2) {
+ bool binSize) {
size_t colorSize;
- width = useNextPow2
- ? SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(width))
- : width;
- height = useNextPow2
- ? SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(height))
- : height;
+ width = binSize ? GrResourceProvider::MakeApprox(width) : width;
+ height = binSize ? GrResourceProvider::MakeApprox(height) : height;
SkASSERT(kUnknown_GrPixelConfig != config);
if (GrPixelConfigIsCompressed(config)) {
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 903a74e..9bcfa7c 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -316,7 +316,7 @@
if (SkBackingFit::kExact == fFit) {
return fWidth;
}
- return SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(fWidth));
+ return GrResourceProvider::MakeApprox(fWidth);
}
int GrSurfaceProxy::worstCaseHeight() const {
@@ -328,7 +328,7 @@
if (SkBackingFit::kExact == fFit) {
return fHeight;
}
- return SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(fHeight));
+ return GrResourceProvider::MakeApprox(fHeight);
}
#ifdef SK_DEBUG
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index a3761aa..34a2bd4 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -32,7 +32,7 @@
size_t GrTexture::onGpuMemorySize() const {
return GrSurface::ComputeSize(this->config(), this->width(), this->height(), 1,
- this->texturePriv().mipMapped(), false);
+ this->texturePriv().mipMapped());
}
/////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/mtl/GrMtlTextureRenderTarget.h b/src/gpu/mtl/GrMtlTextureRenderTarget.h
index a358909..68f716f 100644
--- a/src/gpu/mtl/GrMtlTextureRenderTarget.h
+++ b/src/gpu/mtl/GrMtlTextureRenderTarget.h
@@ -73,7 +73,7 @@
++numColorSamples;
}
return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
- numColorSamples, GrMipMapped::kNo, false);
+ numColorSamples, GrMipMapped::kNo);
}
};