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:
parent
ee77da2c0b
commit
2612baecd8
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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).
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user