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>
This commit is contained in:
Chris Dalton 2018-02-22 13:41:37 -07:00 committed by Skia Commit-Bot
parent ee77da2c0b
commit 2612baecd8
9 changed files with 49 additions and 24 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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());

View File

@ -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");

View File

@ -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));

View File

@ -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).

View File

@ -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;