aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2018-02-22 13:41:37 -0700
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-22 21:06:05 +0000
commit2612baecd8c5b8deeaef18057a57562f45150023 (patch)
tree6dc6d1690d66d1136a51f9847e6f72d8dbc26c08
parentee77da2c0bb44b92409d5eaf2b7ae7530f650a24 (diff)
ccpr: Prefer atlas sizes under 4k on ARM
Bug: skia: Change-Id: Ib5afb84647efe2e64a3ec2f9da422b39228431e9 Reviewed-on: https://skia-review.googlesource.com/108871 Commit-Queue: Chris Dalton <csmartdalton@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
-rw-r--r--include/gpu/GrCaps.h7
-rw-r--r--src/gpu/GrCaps.cpp2
-rw-r--r--src/gpu/ccpr/GrCCAtlas.cpp41
-rw-r--r--src/gpu/ccpr/GrCCAtlas.h9
-rw-r--r--src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp3
-rw-r--r--src/gpu/gl/GrGLCaps.cpp6
-rw-r--r--src/gpu/mock/GrMockCaps.h1
-rw-r--r--src/gpu/mtl/GrMtlCaps.mm1
-rw-r--r--src/gpu/vk/GrVkCaps.cpp3
9 files changed, 49 insertions, 24 deletions
diff --git a/include/gpu/GrCaps.h b/include/gpu/GrCaps.h
index 9d6ef0deaf..e8449bbcb4 100644
--- a/include/gpu/GrCaps.h
+++ b/include/gpu/GrCaps.h
@@ -133,7 +133,13 @@ public:
int maxVertexAttributes() const { return fMaxVertexAttributes; }
int maxRenderTargetSize() const { return fMaxRenderTargetSize; }
+
+ /** This is the largest render target size that can be used without incurring extra perfomance
+ cost. It is usually the max RT size, unless larger render targets are known to be slower. */
+ int maxPreferredRenderTargetSize() const { return fMaxPreferredRenderTargetSize; }
+
int maxTextureSize() const { return fMaxTextureSize; }
+
/** This is the maximum tile size to use by GPU devices for rendering sw-backed images/bitmaps.
It is usually the max texture size, unless we're overriding it for testing. */
int maxTileSize() const { SkASSERT(fMaxTileSize <= fMaxTextureSize); return fMaxTileSize; }
@@ -276,6 +282,7 @@ protected:
int fBufferMapThreshold;
int fMaxRenderTargetSize;
+ int fMaxPreferredRenderTargetSize;
int fMaxVertexAttributes;
int fMaxTextureSize;
int fMaxTileSize;
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index 08e26bd1b5..8cfbc5faea 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -68,6 +68,7 @@ GrCaps::GrCaps(const GrContextOptions& options) {
fMaxVertexAttributes = 0;
fMaxRenderTargetSize = 1;
+ fMaxPreferredRenderTargetSize = 1;
fMaxTextureSize = 1;
fMaxRasterSamples = 0;
fMaxWindowRectangles = 0;
@@ -179,6 +180,7 @@ void GrCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendS32("Max Vertex Attributes", fMaxVertexAttributes);
writer->appendS32("Max Texture Size", fMaxTextureSize);
writer->appendS32("Max Render Target Size", fMaxRenderTargetSize);
+ writer->appendS32("Max Preferred Render Target Size", fMaxPreferredRenderTargetSize);
writer->appendS32("Max Raster Samples", fMaxRasterSamples);
writer->appendS32("Max Window Rectangles", fMaxWindowRectangles);
writer->appendS32("Max Clip Analytic Fragment Processors", fMaxClipAnalyticFPs);
diff --git a/src/gpu/ccpr/GrCCAtlas.cpp b/src/gpu/ccpr/GrCCAtlas.cpp
index 97b28fb480..ce5cddb6d4 100644
--- a/src/gpu/ccpr/GrCCAtlas.cpp
+++ b/src/gpu/ccpr/GrCCAtlas.cpp
@@ -18,6 +18,9 @@
#include "ccpr/GrCCPathParser.h"
#include "ops/GrDrawOp.h"
+static constexpr int kAtlasMinSize = 1024;
+static constexpr int kPadding = 1;
+
class GrCCAtlas::Node {
public:
Node(std::unique_ptr<Node> previous, int l, int t, int r, int b)
@@ -25,10 +28,15 @@ public:
Node* previous() const { return fPrevious.get(); }
- bool addRect(int w, int h, SkIPoint16* loc) {
- static constexpr int kPad = 1;
-
- if (!fRectanizer.addRect(w + kPad, h + kPad, loc)) {
+ bool addRect(int w, int h, SkIPoint16* loc, int maxAtlasSize) {
+ // Pad all paths except those that are expected to take up an entire physical texture.
+ if (w < maxAtlasSize) {
+ w = SkTMin(w + kPadding, maxAtlasSize);
+ }
+ if (h < maxAtlasSize) {
+ h = SkTMin(h + kPadding, maxAtlasSize);
+ }
+ if (!fRectanizer.addRect(w, h, loc)) {
return false;
}
loc->fX += fX;
@@ -76,18 +84,20 @@ private:
typedef GrDrawOp INHERITED;
};
-GrCCAtlas::GrCCAtlas(const GrCaps& caps, int minWidth, int minHeight)
- : fMaxAtlasSize(caps.maxRenderTargetSize()), fDrawBounds{0, 0} {
- SkASSERT(fMaxAtlasSize <= caps.maxTextureSize());
- SkASSERT(SkTMax(minWidth, minHeight) <= fMaxAtlasSize);
- int initialSize = GrNextPow2(SkTMax(minWidth, minHeight));
- initialSize = SkTMax(int(kMinSize), initialSize);
+GrCCAtlas::GrCCAtlas(const GrCaps& caps, int minSize)
+ : fMaxAtlasSize(SkTMax(minSize, caps.maxPreferredRenderTargetSize())) {
+ // Caller should have cropped any paths to the destination render target instead of asking for
+ // an atlas larger than maxRenderTargetSize.
+ SkASSERT(fMaxAtlasSize <= caps.maxRenderTargetSize());
+ int initialSize = GrNextPow2(minSize + kPadding);
+ initialSize = SkTMax(kAtlasMinSize, initialSize);
initialSize = SkTMin(initialSize, fMaxAtlasSize);
fHeight = fWidth = initialSize;
- fTopNode = skstd::make_unique<Node>(nullptr, 0, 0, initialSize, initialSize);
+ fTopNode = skstd::make_unique<Node>(nullptr, 0, 0, fWidth, fHeight);
}
-GrCCAtlas::~GrCCAtlas() {}
+GrCCAtlas::~GrCCAtlas() {
+}
bool GrCCAtlas::addRect(int w, int h, SkIPoint16* loc) {
// This can't be called anymore once setCoverageCountBatchID() has been called.
@@ -104,17 +114,14 @@ bool GrCCAtlas::addRect(int w, int h, SkIPoint16* loc) {
}
bool GrCCAtlas::internalPlaceRect(int w, int h, SkIPoint16* loc) {
- SkASSERT(SkTMax(w, h) < fMaxAtlasSize);
-
for (Node* node = fTopNode.get(); node; node = node->previous()) {
- if (node->addRect(w, h, loc)) {
+ if (node->addRect(w, h, loc, fMaxAtlasSize)) {
return true;
}
}
// The rect didn't fit. Grow the atlas and try again.
do {
- SkASSERT(SkTMax(fWidth, fHeight) <= fMaxAtlasSize);
if (fWidth == fMaxAtlasSize && fHeight == fMaxAtlasSize) {
return false;
}
@@ -127,7 +134,7 @@ bool GrCCAtlas::internalPlaceRect(int w, int h, SkIPoint16* loc) {
fWidth = SkTMin(fWidth * 2, fMaxAtlasSize);
fTopNode = skstd::make_unique<Node>(std::move(fTopNode), left, 0, fWidth, fHeight);
}
- } while (!fTopNode->addRect(w, h, loc));
+ } while (!fTopNode->addRect(w, h, loc, fMaxAtlasSize));
return true;
}
diff --git a/src/gpu/ccpr/GrCCAtlas.h b/src/gpu/ccpr/GrCCAtlas.h
index cac82af894..184022ee96 100644
--- a/src/gpu/ccpr/GrCCAtlas.h
+++ b/src/gpu/ccpr/GrCCAtlas.h
@@ -26,11 +26,9 @@ struct SkIPoint16;
*/
class GrCCAtlas {
public:
- static constexpr int kMinSize = 1024;
-
using CoverageCountBatchID = int;
- GrCCAtlas(const GrCaps&, int minWidth, int minHeight);
+ GrCCAtlas(const GrCaps&, int minSize);
~GrCCAtlas();
bool addRect(int devWidth, int devHeight, SkIPoint16* loc);
@@ -55,10 +53,9 @@ private:
const int fMaxAtlasSize;
- int fWidth;
- int fHeight;
- SkISize fDrawBounds;
+ int fWidth, fHeight;
std::unique_ptr<Node> fTopNode;
+ SkISize fDrawBounds = {0, 0};
CoverageCountBatchID fCoverageCountBatchID SkDEBUGCODE(= 0);
sk_sp<GrTextureProxy> fTextureProxy;
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index ec3681dfcf..90d89dec60 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -486,7 +486,8 @@ GrCCAtlas* GrCoverageCountingPathRenderer::placeParsedPathInAtlas(
auto coverageCountBatchID = fPerFlushPathParser->closeCurrentBatch();
fPerFlushAtlases.back().setCoverageCountBatchID(coverageCountBatchID);
}
- fPerFlushAtlases.emplace_back(*onFlushRP->caps(), w, h).addRect(w, h, &atlasLocation);
+ fPerFlushAtlases.emplace_back(*onFlushRP->caps(), SkTMax(w, h));
+ SkAssertResult(fPerFlushAtlases.back().addRect(w, h, &atlasLocation));
}
*atlasOffsetX = atlasLocation.x() - static_cast<int16_t>(clippedPathIBounds.left());
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index d71194ed6f..3bdf5d0e60 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -483,6 +483,12 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
// Our render targets are always created with textures as the color
// attachment, hence this min:
fMaxRenderTargetSize = SkTMin(fMaxTextureSize, fMaxRenderTargetSize);
+ fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
+
+ if (kARM_GrGLVendor == ctxInfo.vendor()) {
+ // On Mali G71, RT's above 4k have been observed to incur a performance cost.
+ fMaxPreferredRenderTargetSize = SkTMin(4096, fMaxPreferredRenderTargetSize);
+ }
fGpuTracingSupport = ctxInfo.hasExtension("GL_EXT_debug_marker");
diff --git a/src/gpu/mock/GrMockCaps.h b/src/gpu/mock/GrMockCaps.h
index d96a690b31..e75a2c63ff 100644
--- a/src/gpu/mock/GrMockCaps.h
+++ b/src/gpu/mock/GrMockCaps.h
@@ -20,6 +20,7 @@ public:
fBufferMapThreshold = SK_MaxS32; // Overridable in GrContextOptions.
fMaxTextureSize = options.fMaxTextureSize;
fMaxRenderTargetSize = SkTMin(options.fMaxRenderTargetSize, fMaxTextureSize);
+ fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
fMaxVertexAttributes = options.fMaxVertexAttributes;
fShaderCaps.reset(new GrShaderCaps(contextOptions));
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index 865aa37fe6..93d801fd72 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -118,6 +118,7 @@ void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {
}
}
}
+ fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
fMaxTextureSize = fMaxRenderTargetSize;
// Init sample counts. All devices support 1 (i.e. 0 in skia).
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 3fc5a08acb..88d820a62c 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -165,6 +165,9 @@ void GrVkCaps::initGrCaps(const VkPhysicalDeviceProperties& properties,
fMaxRenderTargetSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
fMaxTextureSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
+ // TODO: check if RT's larger than 4k incur a performance cost on ARM.
+ fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
+
// Assuming since we will always map in the end to upload the data we might as well just map
// from the get go. There is no hard data to suggest this is faster or slower.
fBufferMapThreshold = 0;