aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu')
-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
14 files changed, 153 insertions, 175 deletions
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) &&