aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2017-12-04 11:45:51 -0700
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-12-05 21:12:48 +0000
commita3e9271ec41db6c3b6886e50053f37d345ab1d5c (patch)
tree97772078cf13d954ac4ba135fcd20feda6bb22e1
parent60691a5127852631b03250f15fa6cda9a504befc (diff)
CCPR: Eliminate texel buffers
Points cost 8 bytes and indices cost 4. If a point is accessed twice, it's a wash whether we duplicate it or index. This change eliminates texel buffers by duplicating points across instance arrays. This reduces our dependence on extensions as well as getting rid of our indirect memory access pattern in vertex shaders. As a result of this change, memory usage by GPU buffers will only be a fraction larger at worst, and slightly better at best. Bug: skia: Cq-Include-Trybots: skia.primary:Test-Debian9-Clang-GCE-CPU-AVX2-x86_64-Release-All-SKNX_NO_SIMD Change-Id: I3c7f03772edd4f850d5fdd7b55552647335c1b52 Reviewed-on: https://skia-review.googlesource.com/79185 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
-rw-r--r--samplecode/SampleCCPRGeometry.cpp98
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageOp.cpp117
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageOp.h9
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageProcessor.cpp44
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageProcessor.h81
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp14
-rw-r--r--src/gpu/ccpr/GrCCPRCubicShader.cpp8
-rw-r--r--src/gpu/ccpr/GrCCPRCubicShader.h4
-rw-r--r--src/gpu/ccpr/GrCCPRPathProcessor.cpp6
-rw-r--r--src/gpu/ccpr/GrCCPRPathProcessor.h18
-rw-r--r--src/gpu/ccpr/GrCCPRQuadraticShader.cpp8
-rw-r--r--src/gpu/ccpr/GrCCPRQuadraticShader.h4
-rw-r--r--src/gpu/ccpr/GrCCPRTriangleShader.cpp8
-rw-r--r--src/gpu/ccpr/GrCCPRTriangleShader.h5
-rw-r--r--src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp2
-rw-r--r--tests/GrCCPRTest.cpp2
16 files changed, 196 insertions, 232 deletions
diff --git a/samplecode/SampleCCPRGeometry.cpp b/samplecode/SampleCCPRGeometry.cpp
index 16041f5be7..a8f0d9e02c 100644
--- a/samplecode/SampleCCPRGeometry.cpp
+++ b/samplecode/SampleCCPRGeometry.cpp
@@ -26,15 +26,11 @@
#include "ops/GrDrawOp.h"
using TriangleInstance = GrCCPRCoverageProcessor::TriangleInstance;
-using CurveInstance = GrCCPRCoverageProcessor::CurveInstance;
+using CubicInstance = GrCCPRCoverageProcessor::CubicInstance;
using RenderPass = GrCCPRCoverageProcessor::RenderPass;
static constexpr float kDebugBloat = 40;
-static int num_points(RenderPass renderPass) {
- return renderPass >= RenderPass::kSerpentineHulls ? 4 : 3;
-}
-
static int is_quadratic(RenderPass renderPass) {
return renderPass >= RenderPass::kQuadraticHulls && renderPass < RenderPass::kSerpentineHulls;
}
@@ -74,9 +70,8 @@ private:
{100.05f, 300.95f}
};
- SkTArray<SkPoint> fGpuPoints;
- SkTArray<int32_t> fInstanceData;
- int fInstanceCount;
+ SkTArray<TriangleInstance> fTriangleInstances;
+ SkTArray<CubicInstance> fCubicInstances;
typedef SampleView INHERITED;
};
@@ -135,7 +130,7 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
SkPath outline;
outline.moveTo(fPoints[0]);
- if (4 == num_points(fRenderPass)) {
+ if (GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
outline.cubicTo(fPoints[1], fPoints[2], fPoints[3]);
} else if (is_quadratic(fRenderPass)) {
outline.quadTo(fPoints[1], fPoints[3]);
@@ -179,7 +174,7 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
pointsPaint.setStrokeWidth(8);
pointsPaint.setAntiAlias(true);
- if (4 == num_points(fRenderPass)) {
+ if (GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
int w = this->width(), h = this->height();
canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, fPoints, pointsPaint);
draw_klm_line(w, h, canvas, &fCubicKLM[0], SK_ColorYELLOW);
@@ -198,13 +193,10 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
}
void CCPRGeometryView::updateGpuData() {
- int vertexCount = num_points(fRenderPass);
+ fTriangleInstances.reset();
+ fCubicInstances.reset();
- fGpuPoints.reset();
- fInstanceData.reset();
- fInstanceCount = 0;
-
- if (4 == vertexCount) {
+ if (GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
double t[2], s[2];
SkCubicType type = GrPathUtils::getCubicKLM(fPoints, &fCubicKLM, t, s);
if (RenderPass::kSerpentineHulls == fRenderPass && SkCubicType::kLoop == type) {
@@ -224,7 +216,6 @@ void CCPRGeometryView::updateGpuData() {
geometry.beginContour(fPoints[0]);
geometry.cubicTo(fPoints[1], fPoints[2], fPoints[3], kDebugBloat/2, kDebugBloat/2);
geometry.endContour();
- fGpuPoints.push_back_n(geometry.points().count(), geometry.points().begin());
int ptsIdx = 0;
for (GrCCPRGeometry::Verb verb : geometry.verbs()) {
switch (verb) {
@@ -236,10 +227,8 @@ void CCPRGeometryView::updateGpuData() {
continue;
case GrCCPRGeometry::Verb::kMonotonicSerpentineTo:
case GrCCPRGeometry::Verb::kMonotonicLoopTo:
- fInstanceData.push_back(ptsIdx);
- fInstanceData.push_back(0); // Atlas offset.
+ fCubicInstances.push_back().set(&geometry.points()[ptsIdx], 0, 0);
ptsIdx += 3;
- ++fInstanceCount;
continue;
default: continue;
}
@@ -249,7 +238,7 @@ void CCPRGeometryView::updateGpuData() {
geometry.beginContour(fPoints[0]);
geometry.quadraticTo(fPoints[1], fPoints[3]);
geometry.endContour();
- fGpuPoints.push_back_n(geometry.points().count(), geometry.points().begin());
+ int ptsIdx = 0;
for (GrCCPRGeometry::Verb verb : geometry.verbs()) {
if (GrCCPRGeometry::Verb::kBeginContour == verb ||
GrCCPRGeometry::Verb::kEndOpenContour == verb ||
@@ -257,59 +246,58 @@ void CCPRGeometryView::updateGpuData() {
continue;
}
SkASSERT(GrCCPRGeometry::Verb::kMonotonicQuadraticTo == verb);
- fInstanceData.push_back(2 * fInstanceCount++); // Pts idx.
- fInstanceData.push_back(0); // Atlas offset.
+ fTriangleInstances.push_back().set(&geometry.points()[ptsIdx], Sk2f(0, 0));
+ ptsIdx += 2;
}
} else {
- fGpuPoints.push_back(fPoints[0]);
- fGpuPoints.push_back(fPoints[1]);
- fGpuPoints.push_back(fPoints[3]);
- fInstanceData.push_back(0);
- fInstanceData.push_back(1);
- fInstanceData.push_back(2);
- fInstanceData.push_back(0); // Atlas offset.
- fInstanceCount = 1;
+ fTriangleInstances.push_back().set(fPoints[0], fPoints[1], fPoints[3], Sk2f(0, 0));
}
}
void CCPRGeometryView::Op::onExecute(GrOpFlushState* state) {
- if (fView->fInstanceData.empty()) {
- return;
- }
-
GrResourceProvider* rp = state->resourceProvider();
GrContext* context = state->gpu()->getContext();
GrGLGpu* glGpu = kOpenGL_GrBackend == context->contextPriv().getBackend() ?
static_cast<GrGLGpu*>(state->gpu()) : nullptr;
- int vertexCount = num_points(fView->fRenderPass);
- sk_sp<GrBuffer> pointsBuffer(rp->createBuffer(fView->fGpuPoints.count() * sizeof(SkPoint),
- kTexel_GrBufferType, kDynamic_GrAccessPattern,
+ bool isCubic = GrCCPRCoverageProcessor::RenderPassIsCubic(fView->fRenderPass);
+ GrMesh mesh(isCubic ? GrPrimitiveType::kLinesAdjacency : GrPrimitiveType::kTriangles);
+ if (isCubic) {
+ if (fView->fCubicInstances.empty()) {
+ return;
+ }
+ sk_sp<GrBuffer> instBuff(rp->createBuffer(fView->fCubicInstances.count() *
+ sizeof(CubicInstance), kVertex_GrBufferType,
+ kDynamic_GrAccessPattern,
GrResourceProvider::kNoPendingIO_Flag |
GrResourceProvider::kRequireGpuMemory_Flag,
- fView->fGpuPoints.begin()));
- if (!pointsBuffer) {
- return;
- }
-
- sk_sp<GrBuffer> instanceBuffer(rp->createBuffer(fView->fInstanceData.count() * sizeof(int),
- kVertex_GrBufferType, kDynamic_GrAccessPattern,
- GrResourceProvider::kNoPendingIO_Flag |
- GrResourceProvider::kRequireGpuMemory_Flag,
- fView->fInstanceData.begin()));
- if (!instanceBuffer) {
- return;
+ fView->fCubicInstances.begin()));
+ if (!instBuff) {
+ return;
+ }
+ mesh.setInstanced(instBuff.get(), fView->fCubicInstances.count(), 0, 4);
+ } else {
+ if (fView->fTriangleInstances.empty()) {
+ return;
+ }
+ sk_sp<GrBuffer> instBuff(rp->createBuffer(fView->fTriangleInstances.count() *
+ sizeof(TriangleInstance), kVertex_GrBufferType,
+ kDynamic_GrAccessPattern,
+ GrResourceProvider::kNoPendingIO_Flag |
+ GrResourceProvider::kRequireGpuMemory_Flag,
+ fView->fTriangleInstances.begin()));
+ if (!instBuff) {
+ return;
+ }
+ mesh.setInstanced(instBuff.get(), fView->fTriangleInstances.count(), 0, 3);
}
GrPipeline pipeline(state->drawOpArgs().fProxy, GrPipeline::ScissorState::kDisabled,
SkBlendMode::kSrcOver);
- GrCCPRCoverageProcessor ccprProc(fView->fRenderPass, pointsBuffer.get());
+ GrCCPRCoverageProcessor ccprProc(fView->fRenderPass);
SkDEBUGCODE(ccprProc.enableDebugVisualizations(kDebugBloat);)
- GrMesh mesh(4 == vertexCount ? GrPrimitiveType::kLinesAdjacency : GrPrimitiveType::kTriangles);
- mesh.setInstanced(instanceBuffer.get(), fView->fInstanceCount, 0, vertexCount);
-
if (glGpu) {
glGpu->handleDirtyContext();
GR_GL_CALL(glGpu->glInterface(), PolygonMode(GR_GL_FRONT_AND_BACK, GR_GL_LINE));
@@ -348,7 +336,7 @@ private:
SkView::Click* CCPRGeometryView::onFindClickHandler(SkScalar x, SkScalar y, unsigned) {
for (int i = 0; i < 4; ++i) {
- if (4 != num_points(fRenderPass) && 2 == i) {
+ if (!GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass) && 2 == i) {
continue;
}
if (fabs(x - fPoints[i].x()) < 20 && fabsf(y - fPoints[i].y()) < 20) {
diff --git a/src/gpu/ccpr/GrCCPRCoverageOp.cpp b/src/gpu/ccpr/GrCCPRCoverageOp.cpp
index 4d985a563f..8786ed4338 100644
--- a/src/gpu/ccpr/GrCCPRCoverageOp.cpp
+++ b/src/gpu/ccpr/GrCCPRCoverageOp.cpp
@@ -14,11 +14,10 @@
#include "SkPath.h"
#include "SkPathPriv.h"
#include "SkPoint.h"
-#include "SkNx.h"
#include "ccpr/GrCCPRGeometry.h"
using TriangleInstance = GrCCPRCoverageProcessor::TriangleInstance;
-using CurveInstance = GrCCPRCoverageProcessor::CurveInstance;
+using CubicInstance = GrCCPRCoverageProcessor::CubicInstance;
void GrCCPRCoverageOpsBuilder::parsePath(const SkMatrix& m, const SkPath& path, SkRect* devBounds,
SkRect* devBounds45) {
@@ -147,7 +146,7 @@ void GrCCPRCoverageOpsBuilder::saveParsedPath(ScissorMode scissorMode,
fPathsInfo.push_back() = {
scissorMode,
- (int32_t) (((uint32_t) (int32_t) atlasOffsetY << 16) | (atlasOffsetX & 0xffff)),
+ atlasOffsetX, atlasOffsetY,
std::move(fTerminatingOp)
};
@@ -194,8 +193,9 @@ void GrCCPRCoverageOpsBuilder::emitOp(SkISize drawBounds) {
// elements past the end for this method to use as scratch space.
//
// Returns the next triangle instance after the final one emitted.
-static TriangleInstance* emit_recursive_fan(SkTArray<int32_t, true>& indices, int firstIndex,
- int indexCount, int32_t packedAtlasOffset,
+static TriangleInstance* emit_recursive_fan(const SkTArray<SkPoint, true>& pts,
+ SkTArray<int32_t, true>& indices, int firstIndex,
+ int indexCount, const Sk2f& atlasOffset,
TriangleInstance out[]) {
if (indexCount < 3) {
return out;
@@ -203,22 +203,19 @@ static TriangleInstance* emit_recursive_fan(SkTArray<int32_t, true>& indices, in
const int32_t oneThirdCount = indexCount / 3;
const int32_t twoThirdsCount = (2 * indexCount) / 3;
- *out++ = {
- indices[firstIndex],
- indices[firstIndex + oneThirdCount],
- indices[firstIndex + twoThirdsCount],
- packedAtlasOffset
- };
+ out++->set(pts[indices[firstIndex]],
+ pts[indices[firstIndex + oneThirdCount]],
+ pts[indices[firstIndex + twoThirdsCount]], atlasOffset);
- out = emit_recursive_fan(indices, firstIndex, oneThirdCount + 1, packedAtlasOffset, out);
- out = emit_recursive_fan(indices, firstIndex + oneThirdCount,
- twoThirdsCount - oneThirdCount + 1, packedAtlasOffset, out);
+ out = emit_recursive_fan(pts, indices, firstIndex, oneThirdCount + 1, atlasOffset, out);
+ out = emit_recursive_fan(pts, indices, firstIndex + oneThirdCount,
+ twoThirdsCount - oneThirdCount + 1, atlasOffset, out);
int endIndex = firstIndex + indexCount;
int32_t oldValue = indices[endIndex];
indices[endIndex] = indices[firstIndex];
- out = emit_recursive_fan(indices, firstIndex + twoThirdsCount, indexCount - twoThirdsCount + 1,
- packedAtlasOffset, out);
+ out = emit_recursive_fan(pts, indices, firstIndex + twoThirdsCount,
+ indexCount - twoThirdsCount + 1, atlasOffset, out);
indices[endIndex] = oldValue;
return out;
@@ -228,40 +225,53 @@ bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
SkTArray<std::unique_ptr<GrCCPRCoverageOp>>* ops) {
SkASSERT(!fParsingPath);
- const SkTArray<SkPoint, true>& points = fGeometry.points();
- sk_sp<GrBuffer> pointsBuffer = onFlushRP->makeBuffer(kTexel_GrBufferType,
- points.count() * 2 * sizeof(float),
- points.begin());
- if (!pointsBuffer) {
- return false;
- }
-
- // Configure the instance buffer layout.
+ // Here we build a single instance buffer to share with every draw call from every CoverageOP we
+ // plan to produce.
+ //
+ // CoverageOps process 4 different types of primitives (triangles, quadratics, serpentines,
+ // loops), and each primitive type is further divided into instances that require a scissor and
+ // those that don't. This leaves us with 8 independent instance arrays to build for the GPU.
+ //
+ // Rather than placing each instance array in its own GPU buffer, we allocate a single
+ // megabuffer and lay them all out side-by-side. We can offset the "baseInstance" parameter in
+ // our draw calls to direct the GPU to the applicable elements within a given array.
+ //
+ // We already know how big to make each of the 8 arrays from fTallies[kNumScissorModes], so
+ // layout is straightforward.
PrimitiveTallies baseInstances[kNumScissorModes];
- // int4 indices.
+
+ // Start with triangles and quadratics. They both view the instance buffer as an array of
+ // TriangleInstance[], so we can just start at zero and lay them out one after the other.
baseInstances[0].fTriangles = 0;
baseInstances[1].fTriangles = baseInstances[0].fTriangles + fTallies[0].fTriangles;
- // int2 indices (curves index the buffer as int2 rather than int4).
- baseInstances[0].fQuadratics = (baseInstances[1].fTriangles + fTallies[1].fTriangles) * 2;
+ baseInstances[0].fQuadratics = baseInstances[1].fTriangles + fTallies[1].fTriangles;
baseInstances[1].fQuadratics = baseInstances[0].fQuadratics + fTallies[0].fQuadratics;
- baseInstances[0].fSerpentines = baseInstances[1].fQuadratics + fTallies[1].fQuadratics;
+ int triEndIdx = baseInstances[1].fQuadratics + fTallies[1].fQuadratics;
+
+ // Cubics (loops and serpentines) view the same instance buffer as an array of CubicInstance[].
+ // So, reinterpreting the instance data as CubicInstance[], we start them on the first index
+ // that will not overwrite previous TriangleInstance data.
+ int cubicBaseIdx = GR_CT_DIV_ROUND_UP(triEndIdx * sizeof(TriangleInstance),
+ sizeof(CubicInstance));
+ baseInstances[0].fSerpentines = cubicBaseIdx;
baseInstances[1].fSerpentines = baseInstances[0].fSerpentines + fTallies[0].fSerpentines;
baseInstances[0].fLoops = baseInstances[1].fSerpentines + fTallies[1].fSerpentines;
baseInstances[1].fLoops = baseInstances[0].fLoops + fTallies[0].fLoops;
- int instanceBufferSize = (baseInstances[1].fLoops + fTallies[1].fLoops) * sizeof(CurveInstance);
+ int cubicEndIdx = baseInstances[1].fLoops + fTallies[1].fLoops;
sk_sp<GrBuffer> instanceBuffer = onFlushRP->makeBuffer(kVertex_GrBufferType,
- instanceBufferSize);
+ cubicEndIdx * sizeof(CubicInstance));
if (!instanceBuffer) {
return false;
}
TriangleInstance* triangleInstanceData = static_cast<TriangleInstance*>(instanceBuffer->map());
- CurveInstance* curveInstanceData = reinterpret_cast<CurveInstance*>(triangleInstanceData);
- SkASSERT(curveInstanceData);
+ CubicInstance* cubicInstanceData = reinterpret_cast<CubicInstance*>(triangleInstanceData);
+ SkASSERT(cubicInstanceData);
PathInfo* currPathInfo = fPathsInfo.begin();
- int32_t packedAtlasOffset;
+ float atlasOffsetX, atlasOffsetY;
+ Sk2f atlasOffset;
int ptsIdx = -1;
PrimitiveTallies instanceIndices[2] = {baseInstances[0], baseInstances[1]};
PrimitiveTallies* currIndices;
@@ -273,20 +283,24 @@ bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
PrimitiveTallies initialBaseInstances[] = {baseInstances[0], baseInstances[1]};
#endif
+ const SkTArray<SkPoint, true>& pts = fGeometry.points();
+
// Expand the ccpr verbs into GPU instance buffers.
for (GrCCPRGeometry::Verb verb : fGeometry.verbs()) {
switch (verb) {
case GrCCPRGeometry::Verb::kBeginPath:
SkASSERT(currFan.empty());
currIndices = &instanceIndices[(int)currPathInfo->fScissorMode];
- packedAtlasOffset = currPathInfo->fPackedAtlasOffset;
+ atlasOffsetX = static_cast<float>(currPathInfo->fAtlasOffsetX);
+ atlasOffsetY = static_cast<float>(currPathInfo->fAtlasOffsetY);
+ atlasOffset = {atlasOffsetX, atlasOffsetY};
#ifdef SK_DEBUG
if (ScissorMode::kScissored == currPathInfo->fScissorMode) {
++numScissoredPaths;
}
#endif
if (auto op = std::move(currPathInfo->fTerminatingOp)) {
- op->setBuffers(pointsBuffer, instanceBuffer, baseInstances, instanceIndices);
+ op->setInstanceBuffer(instanceBuffer, baseInstances, instanceIndices);
baseInstances[0] = instanceIndices[0];
baseInstances[1] = instanceIndices[1];
SkDEBUGCODE(numScissorBatches += op->fScissorBatches.count());
@@ -307,19 +321,21 @@ bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
case GrCCPRGeometry::Verb::kMonotonicQuadraticTo:
SkASSERT(!currFan.empty());
- curveInstanceData[currIndices->fQuadratics++] = {ptsIdx, packedAtlasOffset};
+ triangleInstanceData[currIndices->fQuadratics++].set(&pts[ptsIdx], atlasOffset);
currFan.push_back(ptsIdx += 2);
continue;
case GrCCPRGeometry::Verb::kMonotonicSerpentineTo:
SkASSERT(!currFan.empty());
- curveInstanceData[currIndices->fSerpentines++] = {ptsIdx, packedAtlasOffset};
+ cubicInstanceData[currIndices->fSerpentines++].set(&pts[ptsIdx],
+ atlasOffsetX, atlasOffsetY);
currFan.push_back(ptsIdx += 3);
continue;
case GrCCPRGeometry::Verb::kMonotonicLoopTo:
SkASSERT(!currFan.empty());
- curveInstanceData[currIndices->fLoops++] = {ptsIdx, packedAtlasOffset};
+ cubicInstanceData[currIndices->fLoops++].set(&pts[ptsIdx],
+ atlasOffsetX, atlasOffsetY);
currFan.push_back(ptsIdx += 3);
continue;
@@ -334,7 +350,7 @@ bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
// fanSize + log3(fanSize), but we approximate with log2.
currFan.push_back_n(SkNextLog2(fanSize));
SkDEBUGCODE(TriangleInstance* end =)
- emit_recursive_fan(currFan, 0, fanSize, packedAtlasOffset,
+ emit_recursive_fan(pts, currFan, 0, fanSize, atlasOffset,
triangleInstanceData + currIndices->fTriangles);
currIndices->fTriangles += fanSize - 2;
SkASSERT(triangleInstanceData + currIndices->fTriangles == end);
@@ -347,30 +363,28 @@ bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
instanceBuffer->unmap();
if (auto op = std::move(fTerminatingOp)) {
- op->setBuffers(std::move(pointsBuffer), std::move(instanceBuffer), baseInstances,
- instanceIndices);
+ op->setInstanceBuffer(std::move(instanceBuffer), baseInstances, instanceIndices);
SkDEBUGCODE(numScissorBatches += op->fScissorBatches.count());
ops->push_back(std::move(op));
}
SkASSERT(currPathInfo == fPathsInfo.end());
- SkASSERT(ptsIdx == points.count() - 1);
+ SkASSERT(ptsIdx == pts.count() - 1);
SkASSERT(numScissoredPaths == numScissorBatches);
SkASSERT(instanceIndices[0].fTriangles == initialBaseInstances[1].fTriangles);
- SkASSERT(instanceIndices[1].fTriangles * 2 == initialBaseInstances[0].fQuadratics);
+ SkASSERT(instanceIndices[1].fTriangles == initialBaseInstances[0].fQuadratics);
SkASSERT(instanceIndices[0].fQuadratics == initialBaseInstances[1].fQuadratics);
- SkASSERT(instanceIndices[1].fQuadratics == initialBaseInstances[0].fSerpentines);
+ SkASSERT(instanceIndices[1].fQuadratics == triEndIdx);
SkASSERT(instanceIndices[0].fSerpentines == initialBaseInstances[1].fSerpentines);
SkASSERT(instanceIndices[1].fSerpentines == initialBaseInstances[0].fLoops);
SkASSERT(instanceIndices[0].fLoops == initialBaseInstances[1].fLoops);
- SkASSERT(instanceIndices[1].fLoops * (int) sizeof(CurveInstance) == instanceBufferSize);
+ SkASSERT(instanceIndices[1].fLoops == cubicEndIdx);
return true;
}
-void GrCCPRCoverageOp::setBuffers(sk_sp<GrBuffer> pointsBuffer, sk_sp<GrBuffer> instanceBuffer,
- const PrimitiveTallies baseInstances[kNumScissorModes],
- const PrimitiveTallies endInstances[kNumScissorModes]) {
- fPointsBuffer = std::move(pointsBuffer);
+void GrCCPRCoverageOp::setInstanceBuffer(sk_sp<GrBuffer> instanceBuffer,
+ const PrimitiveTallies baseInstances[kNumScissorModes],
+ const PrimitiveTallies endInstances[kNumScissorModes]) {
fInstanceBuffer = std::move(instanceBuffer);
fBaseInstances[0] = baseInstances[0];
fBaseInstances[1] = baseInstances[1];
@@ -381,7 +395,6 @@ void GrCCPRCoverageOp::setBuffers(sk_sp<GrBuffer> pointsBuffer, sk_sp<GrBuffer>
void GrCCPRCoverageOp::onExecute(GrOpFlushState* flushState) {
using RenderPass = GrCCPRCoverageProcessor::RenderPass;
- SkASSERT(fPointsBuffer);
SkASSERT(fInstanceBuffer);
GrPipeline pipeline(flushState->drawOpArgs().fProxy, GrPipeline::ScissorState::kEnabled,
@@ -456,7 +469,7 @@ void GrCCPRCoverageOp::drawMaskPrimitives(GrOpFlushState* flushState, const GrPi
SkASSERT(fMeshesScratchBuffer.count() == fDynamicStatesScratchBuffer.count());
if (!fMeshesScratchBuffer.empty()) {
- GrCCPRCoverageProcessor proc(renderPass, fPointsBuffer.get());
+ GrCCPRCoverageProcessor proc(renderPass);
SkASSERT(flushState->rtCommandBuffer());
flushState->rtCommandBuffer()->draw(pipeline, proc, fMeshesScratchBuffer.begin(),
fDynamicStatesScratchBuffer.begin(),
diff --git a/src/gpu/ccpr/GrCCPRCoverageOp.h b/src/gpu/ccpr/GrCCPRCoverageOp.h
index ba818a1b12..571e29a8cf 100644
--- a/src/gpu/ccpr/GrCCPRCoverageOp.h
+++ b/src/gpu/ccpr/GrCCPRCoverageOp.h
@@ -91,7 +91,7 @@ private:
// Every kBeginPath verb has a corresponding PathInfo entry.
struct PathInfo {
ScissorMode fScissorMode;
- int32_t fPackedAtlasOffset; // (offsetY << 16) | (offsetX & 0xffff)
+ int16_t fAtlasOffsetX, fAtlasOffsetY;
std::unique_ptr<GrCCPRCoverageOp> fTerminatingOp;
};
@@ -154,15 +154,14 @@ private:
GrOp::HasAABloat::kNo, GrOp::IsZeroArea::kNo);
}
- void setBuffers(sk_sp<GrBuffer> pointsBuffer, sk_sp<GrBuffer> instanceBuffer,
- const PrimitiveTallies baseInstances[kNumScissorModes],
- const PrimitiveTallies endInstances[kNumScissorModes]);
+ void setInstanceBuffer(sk_sp<GrBuffer> instanceBuffer,
+ const PrimitiveTallies baseInstances[kNumScissorModes],
+ const PrimitiveTallies endInstances[kNumScissorModes]);
void drawMaskPrimitives(GrOpFlushState*, const GrPipeline&,
const GrCCPRCoverageProcessor::RenderPass, GrPrimitiveType,
int vertexCount, int PrimitiveTallies::* instanceType) const;
- sk_sp<GrBuffer> fPointsBuffer;
sk_sp<GrBuffer> fInstanceBuffer;
PrimitiveTallies fBaseInstances[kNumScissorModes];
PrimitiveTallies fInstanceCounts[kNumScissorModes];
diff --git a/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp b/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp
index 1dc129f2ba..d77324dd6f 100644
--- a/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp
@@ -13,30 +13,28 @@
#include "ccpr/GrCCPRTriangleShader.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
-static GrVertexAttribType instance_array_format(GrCCPRCoverageProcessor::RenderPass renderPass) {
- switch (renderPass) {
- case GrCCPRCoverageProcessor::RenderPass::kTriangleHulls:
- case GrCCPRCoverageProcessor::RenderPass::kTriangleEdges:
- case GrCCPRCoverageProcessor::RenderPass::kTriangleCorners:
- return kInt4_GrVertexAttribType;
- case GrCCPRCoverageProcessor::RenderPass::kQuadraticHulls:
- case GrCCPRCoverageProcessor::RenderPass::kQuadraticCorners:
- case GrCCPRCoverageProcessor::RenderPass::kSerpentineHulls:
- case GrCCPRCoverageProcessor::RenderPass::kLoopHulls:
- case GrCCPRCoverageProcessor::RenderPass::kSerpentineCorners:
- case GrCCPRCoverageProcessor::RenderPass::kLoopCorners:
- return kInt2_GrVertexAttribType;
- }
- SK_ABORT("Unexpected GrCCPRCoverageProcessor::RenderPass.");
- return kInt4_GrVertexAttribType;
-}
-
-GrCCPRCoverageProcessor::GrCCPRCoverageProcessor(RenderPass renderPass, GrBuffer* pointsBuffer)
+GrCCPRCoverageProcessor::GrCCPRCoverageProcessor(RenderPass renderPass)
: INHERITED(kGrCCPRCoverageProcessor_ClassID)
- , fRenderPass(renderPass)
- , fInstanceAttrib(this->addInstanceAttrib("instance", instance_array_format(fRenderPass))) {
- fPointsBufferAccess.reset(kRG_float_GrPixelConfig, pointsBuffer, kVertex_GrShaderFlag);
- this->addBufferAccess(&fPointsBufferAccess);
+ , fRenderPass(renderPass) {
+ if (RenderPassIsCubic(fRenderPass)) {
+ this->addInstanceAttrib("X", kFloat4_GrVertexAttribType);
+ this->addInstanceAttrib("Y", kFloat4_GrVertexAttribType);
+
+ SkASSERT(offsetof(CubicInstance, fX) ==
+ this->getInstanceAttrib(InstanceAttribs::kX).fOffsetInRecord);
+ SkASSERT(offsetof(CubicInstance, fY) ==
+ this->getInstanceAttrib(InstanceAttribs::kY).fOffsetInRecord);
+ SkASSERT(sizeof(CubicInstance) == this->getInstanceStride());
+ } else {
+ this->addInstanceAttrib("X", kFloat3_GrVertexAttribType);
+ this->addInstanceAttrib("Y", kFloat3_GrVertexAttribType);
+
+ SkASSERT(offsetof(TriangleInstance, fX) ==
+ this->getInstanceAttrib(InstanceAttribs::kX).fOffsetInRecord);
+ SkASSERT(offsetof(TriangleInstance, fY) ==
+ this->getInstanceAttrib(InstanceAttribs::kY).fOffsetInRecord);
+ SkASSERT(sizeof(TriangleInstance) == this->getInstanceStride());
+ }
this->setWillUseGeoShader();
}
diff --git a/src/gpu/ccpr/GrCCPRCoverageProcessor.h b/src/gpu/ccpr/GrCCPRCoverageProcessor.h
index 9c5d6901f9..3c4050a73b 100644
--- a/src/gpu/ccpr/GrCCPRCoverageProcessor.h
+++ b/src/gpu/ccpr/GrCCPRCoverageProcessor.h
@@ -9,6 +9,7 @@
#define GrCCPRCoverageProcessor_DEFINED
#include "GrGeometryProcessor.h"
+#include "SkNx.h"
#include "glsl/GrGLSLGeometryProcessor.h"
#include "glsl/GrGLSLVarying.h"
@@ -25,12 +26,9 @@ class GrGLSLShaderBuilder;
* below). Once all of a path's primitives have been drawn, the render target contains a composite
* coverage count that can then be used to draw the path (see GrCCPRPathProcessor).
*
- * Caller provides the primitives' (x,y) input points in an fp32x2 (RG) texel buffer, and an
- * instance buffer with a single int32x4 attrib (for triangles) or int32x2 (for curves) defined
- * below. There are no vertex attribs.
- *
- * Draw calls are instanced, with one vertex per bezier point (3 for triangles). They use the
- * corresponding GrPrimitiveType as defined below.
+ * Draw calls are instanced. They use use the corresponding GrPrimitiveTypes as defined below.
+ * Caller fills out the primitives' atlas-space vertices and control points in instance arrays
+ * using the provided structs below. There are no vertex attribs.
*/
class GrCCPRCoverageProcessor : public GrGeometryProcessor {
public:
@@ -38,21 +36,25 @@ public:
static constexpr GrPrimitiveType kQuadraticsGrPrimitiveType = GrPrimitiveType::kTriangles;
static constexpr GrPrimitiveType kCubicsGrPrimitiveType = GrPrimitiveType::kLinesAdjacency;
- struct TriangleInstance {
- int32_t fPt0Idx;
- int32_t fPt1Idx;
- int32_t fPt2Idx;
- int32_t fPackedAtlasOffset; // (offsetY << 16) | (offsetX & 0xffff)
+ enum class InstanceAttribs : int {
+ kX,
+ kY
};
- GR_STATIC_ASSERT(4 * 4 == sizeof(TriangleInstance));
+ struct TriangleInstance { // Also used by quadratics.
+ float fX[3];
+ float fY[3];
- struct CurveInstance {
- int32_t fPtsIdx;
- int32_t fPackedAtlasOffset; // (offsetY << 16) | (offsetX & 0xffff)
+ void set(const SkPoint[3], const Sk2f& trans);
+ void set(const SkPoint&, const SkPoint&, const SkPoint&, const Sk2f& trans);
};
- GR_STATIC_ASSERT(2 * 4 == sizeof(CurveInstance));
+ struct CubicInstance {
+ float fX[4];
+ float fY[4];
+
+ void set(const SkPoint[4], float dx, float dy);
+ };
/**
* All primitive shapes (triangles and convex closed curve segments) require more than one
@@ -76,6 +78,10 @@ public:
kLoopCorners
};
+ static constexpr bool RenderPassIsCubic(RenderPass pass) {
+ return pass >= RenderPass::kSerpentineHulls && pass <= RenderPass::kLoopCorners;
+ }
+
static const char* GetRenderPassName(RenderPass);
/**
@@ -117,11 +123,6 @@ public:
// (number of wedges for a hull, number of edges, or number of corners.)
virtual int getNumSegments() const = 0;
- // Appends an expression that fetches input point # "pointId" from the texel buffer.
- virtual void appendInputPointFetch(const GrCCPRCoverageProcessor&, GrGLSLShaderBuilder*,
- const TexelBufferHandle& pointsBuffer,
- const char* pointId) const = 0;
-
// Determines the winding direction of the primitive. The subclass must write a value of
// either -1, 0, or +1 to "outputWind" (e.g. "sign(area)"). Fractional values are not valid.
virtual void emitWind(GrGLSLShaderBuilder*, const char* pts,
@@ -194,13 +195,16 @@ public:
GrGLSLGeoToFrag fWind{kHalf_GrSLType};
};
- GrCCPRCoverageProcessor(RenderPass, GrBuffer* pointsBuffer);
+ GrCCPRCoverageProcessor(RenderPass);
- const char* instanceAttrib() const { return fInstanceAttrib.fName; }
const char* name() const override { return GetRenderPassName(fRenderPass); }
SkString dumpInfo() const override {
return SkStringPrintf("%s\n%s", this->name(), this->INHERITED::dumpInfo().c_str());
}
+ const Attribute& getInstanceAttrib(InstanceAttribs attribID) const {
+ return this->getAttrib((int)attribID);
+ }
+
void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
@@ -221,18 +225,29 @@ private:
static GrGLSLPrimitiveProcessor* CreateGSImpl(std::unique_ptr<Shader>);
- int atlasOffsetIdx() const {
- SkASSERT(kInt2_GrVertexAttribType == fInstanceAttrib.fType ||
- kInt4_GrVertexAttribType == fInstanceAttrib.fType);
- return kInt4_GrVertexAttribType == fInstanceAttrib.fType ? 3 : 1;
- }
-
- const RenderPass fRenderPass;
- const Attribute& fInstanceAttrib;
- BufferAccess fPointsBufferAccess;
- SkDEBUGCODE(float fDebugBloat = 0;)
+ const RenderPass fRenderPass;
+ SkDEBUGCODE(float fDebugBloat = 0;)
typedef GrGeometryProcessor INHERITED;
};
+inline void GrCCPRCoverageProcessor::TriangleInstance::set(const SkPoint p[3], const Sk2f& trans) {
+ this->set(p[0], p[1], p[2], trans);
+}
+
+inline void GrCCPRCoverageProcessor::TriangleInstance::set(const SkPoint& p0, const SkPoint& p1,
+ const SkPoint& p2, const Sk2f& trans) {
+ Sk2f P0 = Sk2f::Load(&p0) + trans;
+ Sk2f P1 = Sk2f::Load(&p1) + trans;
+ Sk2f P2 = Sk2f::Load(&p2) + trans;
+ Sk2f::Store3(this, P0, P1, P2);
+}
+
+inline void GrCCPRCoverageProcessor::CubicInstance::set(const SkPoint p[4], float dx, float dy) {
+ Sk4f X,Y;
+ Sk4f::Load2(p, &X, &Y);
+ (X + dx).store(&fX);
+ (Y + dy).store(&fY);
+}
+
#endif
diff --git a/src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp b/src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp
index 5286a29508..51791a1628 100644
--- a/src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp
+++ b/src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp
@@ -28,17 +28,9 @@ protected:
// Vertex shader.
GrGLSLVertexBuilder* v = args.fVertBuilder;
- // The Intel GLSL compiler hits an internal assertion if we index the input attrib itself
- // with sk_VertexID.
- v->codeAppendf("int pointID = sk_VertexID;");
- v->codeAppend ("float2 self = ");
- fShader->appendInputPointFetch(proc, v, args.fTexelBuffers[0], "pointID");
- v->codeAppend (".xy;");
- v->codeAppendf("int packedoffset = %s[%i];",
- proc.fInstanceAttrib.fName, proc.atlasOffsetIdx());
- v->codeAppend ("float2 atlasoffset = float2((packedoffset << 16) >> 16, "
- "packedoffset >> 16);");
- v->codeAppend ("self += atlasoffset;");
+ v->codeAppendf("float2 self = float2(%s[sk_VertexID], %s[sk_VertexID]);",
+ proc.getInstanceAttrib(InstanceAttribs::kX).fName,
+ proc.getInstanceAttrib(InstanceAttribs::kY).fName);
gpArgs->fPositionVar.set(kFloat2_GrSLType, "self");
// Geometry shader.
diff --git a/src/gpu/ccpr/GrCCPRCubicShader.cpp b/src/gpu/ccpr/GrCCPRCubicShader.cpp
index 62d9a838b0..59cd2a8537 100644
--- a/src/gpu/ccpr/GrCCPRCubicShader.cpp
+++ b/src/gpu/ccpr/GrCCPRCubicShader.cpp
@@ -9,14 +9,6 @@
#include "glsl/GrGLSLFragmentShaderBuilder.h"
-void GrCCPRCubicShader::appendInputPointFetch(const GrCCPRCoverageProcessor& proc,
- GrGLSLShaderBuilder* s,
- const TexelBufferHandle& pointsBuffer,
- const char* pointId) const {
- s->appendTexelFetch(pointsBuffer,
- SkStringPrintf("%s.x + %s", proc.instanceAttrib(), pointId).c_str());
-}
-
void GrCCPRCubicShader::emitWind(GrGLSLShaderBuilder* s, const char* pts,
const char* outputWind) const {
diff --git a/src/gpu/ccpr/GrCCPRCubicShader.h b/src/gpu/ccpr/GrCCPRCubicShader.h
index a6d597d3c8..8cfacd61bb 100644
--- a/src/gpu/ccpr/GrCCPRCubicShader.h
+++ b/src/gpu/ccpr/GrCCPRCubicShader.h
@@ -33,10 +33,6 @@ protected:
int getNumInputPoints() const final { return 4; }
- void appendInputPointFetch(const GrCCPRCoverageProcessor&, GrGLSLShaderBuilder*,
- const TexelBufferHandle& pointsBuffer,
- const char* pointId) const final;
-
void emitWind(GrGLSLShaderBuilder*, const char* pts, const char* outputWind) const final;
void emitSetupCode(GrGLSLShaderBuilder*, const char* pts, const char* segmentId,
diff --git a/src/gpu/ccpr/GrCCPRPathProcessor.cpp b/src/gpu/ccpr/GrCCPRPathProcessor.cpp
index ff3c60c134..612035af4a 100644
--- a/src/gpu/ccpr/GrCCPRPathProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPRPathProcessor.cpp
@@ -51,7 +51,9 @@ GR_DECLARE_STATIC_UNIQUE_KEY(gIndexBufferKey);
GrCCPRPathProcessor::GrCCPRPathProcessor(GrResourceProvider* rp, sk_sp<GrTextureProxy> atlas,
SkPath::FillType fillType, const GrShaderCaps& shaderCaps)
: INHERITED(kGrCCPRPathProcessor_ClassID)
- , fFillType(fillType) {
+ , fFillType(fillType)
+ , fAtlasAccess(std::move(atlas), GrSamplerState::Filter::kNearest,
+ GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag) {
this->addInstanceAttrib("devbounds", kFloat4_GrVertexAttribType);
this->addInstanceAttrib("devbounds45", kFloat4_GrVertexAttribType);
this->addInstanceAttrib("view_matrix", kFloat4_GrVertexAttribType);
@@ -77,8 +79,6 @@ GrCCPRPathProcessor::GrCCPRPathProcessor(GrResourceProvider* rp, sk_sp<GrTexture
this->addVertexAttrib("edge_norms", kFloat4_GrVertexAttribType);
- fAtlasAccess.reset(std::move(atlas), GrSamplerState::Filter::kNearest,
- GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag);
fAtlasAccess.instantiate(rp);
this->addTextureSampler(&fAtlasAccess);
}
diff --git a/src/gpu/ccpr/GrCCPRPathProcessor.h b/src/gpu/ccpr/GrCCPRPathProcessor.h
index 82711756ee..7ad314e1d6 100644
--- a/src/gpu/ccpr/GrCCPRPathProcessor.h
+++ b/src/gpu/ccpr/GrCCPRPathProcessor.h
@@ -41,13 +41,13 @@ public:
static constexpr int kNumInstanceAttribs = 1 + (int)InstanceAttribs::kColor;
struct Instance {
- SkRect fDevBounds;
- SkRect fDevBounds45; // Bounding box in "| 1 -1 | * devCoords" space.
- // | 1 1 |
- std::array<float, 4> fViewMatrix; // {kScaleX, kSkewy, kSkewX, kScaleY}
- std::array<float, 2> fViewTranslate;
- std::array<int16_t, 2> fAtlasOffset;
- uint32_t fColor;
+ SkRect fDevBounds;
+ SkRect fDevBounds45; // Bounding box in "| 1 -1 | * devCoords" space.
+ // | 1 1 |
+ std::array<float, 4> fViewMatrix; // {kScaleX, kSkewy, kSkewX, kScaleY}
+ std::array<float, 2> fViewTranslate;
+ std::array<int16_t, 2> fAtlasOffset;
+ uint32_t fColor;
GR_STATIC_ASSERT(SK_SCALAR_IS_FLOAT);
};
@@ -77,8 +77,8 @@ public:
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
private:
- const SkPath::FillType fFillType;
- TextureSampler fAtlasAccess;
+ const SkPath::FillType fFillType;
+ const TextureSampler fAtlasAccess;
typedef GrGeometryProcessor INHERITED;
};
diff --git a/src/gpu/ccpr/GrCCPRQuadraticShader.cpp b/src/gpu/ccpr/GrCCPRQuadraticShader.cpp
index bdef285f1a..6dd062b923 100644
--- a/src/gpu/ccpr/GrCCPRQuadraticShader.cpp
+++ b/src/gpu/ccpr/GrCCPRQuadraticShader.cpp
@@ -9,14 +9,6 @@
#include "glsl/GrGLSLFragmentShaderBuilder.h"
-void GrCCPRQuadraticShader::appendInputPointFetch(const GrCCPRCoverageProcessor& proc,
- GrGLSLShaderBuilder* s,
- const TexelBufferHandle& pointsBuffer,
- const char* pointId) const {
- s->appendTexelFetch(pointsBuffer,
- SkStringPrintf("%s.x + %s", proc.instanceAttrib(), pointId).c_str());
-}
-
void GrCCPRQuadraticShader::emitWind(GrGLSLShaderBuilder* s, const char* pts,
const char* outputWind) const {
s->codeAppendf("float area_times_2 = determinant(float2x2(%s[1] - %s[0], %s[2] - %s[0]));",
diff --git a/src/gpu/ccpr/GrCCPRQuadraticShader.h b/src/gpu/ccpr/GrCCPRQuadraticShader.h
index 38dd14e737..4877edec44 100644
--- a/src/gpu/ccpr/GrCCPRQuadraticShader.h
+++ b/src/gpu/ccpr/GrCCPRQuadraticShader.h
@@ -24,10 +24,6 @@ class GrCCPRQuadraticShader : public GrCCPRCoverageProcessor::Shader {
protected:
int getNumInputPoints() const final { return 3; }
- void appendInputPointFetch(const GrCCPRCoverageProcessor&, GrGLSLShaderBuilder*,
- const TexelBufferHandle& pointsBuffer,
- const char* pointId) const override;
-
void emitWind(GrGLSLShaderBuilder*, const char* pts, const char* outputWind) const final;
void emitSetupCode(GrGLSLShaderBuilder*, const char* pts, const char* segmentId,
diff --git a/src/gpu/ccpr/GrCCPRTriangleShader.cpp b/src/gpu/ccpr/GrCCPRTriangleShader.cpp
index a1f4198f86..c2c624b1ae 100644
--- a/src/gpu/ccpr/GrCCPRTriangleShader.cpp
+++ b/src/gpu/ccpr/GrCCPRTriangleShader.cpp
@@ -10,14 +10,6 @@
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLVertexGeoBuilder.h"
-void GrCCPRTriangleShader::appendInputPointFetch(const GrCCPRCoverageProcessor& proc,
- GrGLSLShaderBuilder* s,
- const TexelBufferHandle& pointsBuffer,
- const char* pointId) const {
- s->appendTexelFetch(pointsBuffer,
- SkStringPrintf("%s[%s]", proc.instanceAttrib(), pointId).c_str());
-}
-
void GrCCPRTriangleShader::emitWind(GrGLSLShaderBuilder* s, const char* pts,
const char* outputWind) const {
s->codeAppendf("%s = sign(determinant(float2x2(%s[1] - %s[0], %s[2] - %s[0])));",
diff --git a/src/gpu/ccpr/GrCCPRTriangleShader.h b/src/gpu/ccpr/GrCCPRTriangleShader.h
index 64e54954a2..a0bbb66819 100644
--- a/src/gpu/ccpr/GrCCPRTriangleShader.h
+++ b/src/gpu/ccpr/GrCCPRTriangleShader.h
@@ -18,11 +18,6 @@ class GrCCPRTriangleShader : public GrCCPRCoverageProcessor::Shader {
public:
int getNumInputPoints() const final { return 3; }
int getNumSegments() const final { return 3; } // 3 wedges, 3 edges, 3 corners.
-
- void appendInputPointFetch(const GrCCPRCoverageProcessor&, GrGLSLShaderBuilder*,
- const TexelBufferHandle& pointsBuffer,
- const char* pointId) const final;
-
void emitWind(GrGLSLShaderBuilder* s, const char* pts, const char* outputWind) const final;
};
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index 95fd619dcd..937fd4824b 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -39,10 +39,8 @@ static void crop_path(const SkPath& path, const SkIRect& cropbox, SkPath* out) {
bool GrCoverageCountingPathRenderer::IsSupported(const GrCaps& caps) {
const GrShaderCaps& shaderCaps = *caps.shaderCaps();
return shaderCaps.geometryShaderSupport() &&
- shaderCaps.texelBufferSupport() &&
shaderCaps.integerSupport() &&
shaderCaps.flatInterpolationSupport() &&
- shaderCaps.maxVertexSamplers() >= 1 &&
caps.instanceAttribSupport() &&
GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
caps.isConfigTexturable(kAlpha_half_GrPixelConfig) &&
diff --git a/tests/GrCCPRTest.cpp b/tests/GrCCPRTest.cpp
index 33246bfc88..1164ed8ca0 100644
--- a/tests/GrCCPRTest.cpp
+++ b/tests/GrCCPRTest.cpp
@@ -120,10 +120,8 @@ public:
mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fRenderable[0] = true;
mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fTexturable = true;
mockOptions.fGeometryShaderSupport = true;
- mockOptions.fTexelBufferSupport = true;
mockOptions.fIntegerSupport = true;
mockOptions.fFlatInterpolationSupport = true;
- mockOptions.fMaxVertexSamplers = 1;
GrContextOptions ctxOptions;
ctxOptions.fAllowPathMaskCaching = false;