Reland "Add ability to specify different GP textures for each mesh in a draw."
This reverts commit deeb655912b90d9b19d692f4b6ebe55ff4ce90cb.
Reason for revert: Fix landed for incorrect chaining logic: https://skia-review.googlesource.com/148380
Original change's description:
> Revert "Add ability to specify different GP textures for each mesh in a draw."
>
> This reverts commit d1b8a166db27ffb8e550c4e853afbd67025948bf.
>
> Reason for revert: breaks android apps, by drawing overlapping content out of painters order.
>
> Original change's description:
> > Add ability to specify different GP textures for each mesh in a draw.
> >
> > Uses GrPipeline::DynamicStateArrays to allow per-mesh GP textures when
> > drawing an array of GrMeshes.
> >
> > Uses this along with op-chaining to make drawing multiple TextureOps
> > with different textures faster.
> >
> > Change-Id: Iec4da1b72a13d0e0c94c8a8568fe4221c539dfcf
> > Reviewed-on: https://skia-review.googlesource.com/145960
> > Commit-Queue: Brian Salomon <bsalomon@google.com>
> > Reviewed-by: Brian Osman <brianosman@google.com>
>
> TBR=bsalomon@google.com,robertphillips@google.com,brianosman@google.com
>
> # Not skipping CQ checks because original CL landed > 1 day ago.
>
> Change-Id: I5c686b85adb378ba7faf34576efce74aebd348f7
> Reviewed-on: https://skia-review.googlesource.com/147260
> Reviewed-by: Derek Sollenberger <djsollen@google.com>
> Reviewed-by: Brian Osman <brianosman@google.com>
> Commit-Queue: Brian Osman <brianosman@google.com>
TBR=djsollen@google.com,bsalomon@google.com,robertphillips@google.com,brianosman@google.com
# Not skipping CQ checks because original CL landed > 1 day ago.
Change-Id: I90173d4072c64b9ec4c87989e63e4ed283bd4829
Reviewed-on: https://skia-review.googlesource.com/148681
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 2ba3639..fa86c2f 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -611,7 +611,7 @@
}
template <typename Pos, Domain D, GrAA AA>
- void tess(void* v, const GrGeometryProcessor* gp) {
+ void tess(void* v, const GrGeometryProcessor* gp) const {
using Vertex = TextureGeometryProcessor::Vertex<Pos, D, AA>;
SkASSERT(gp->debugOnly_vertexStride() == sizeof(Vertex));
auto vertices = static_cast<Vertex*>(v);
@@ -628,16 +628,25 @@
}
void onPrepareDraws(Target* target) override {
- if (!fProxy->instantiate(target->resourceProvider())) {
- return;
+ bool hasPerspective = false;
+ Domain domain = Domain::kNo;
+ int numOps = 0;
+ for (const auto& op : ChainRange<TextureOp>(this)) {
+ ++numOps;
+ hasPerspective |= op.fPerspective;
+ if (op.fDomain) {
+ domain = Domain::kYes;
+ }
+ if (!op.fProxy->instantiate(target->resourceProvider())) {
+ return;
+ }
}
- Domain domain = fDomain ? Domain::kYes : Domain::kNo;
bool coverageAA = GrAAType::kCoverage == this->aaType();
sk_sp<GrGeometryProcessor> gp = TextureGeometryProcessor::Make(
fProxy->textureType(), fProxy->config(), fFilter,
std::move(fTextureColorSpaceXform), std::move(fPaintColorSpaceXform), coverageAA,
- fPerspective, domain, *target->caps().shaderCaps());
+ hasPerspective, domain, *target->caps().shaderCaps());
GrPipeline::InitArgs args;
args.fProxy = target->proxy();
args.fCaps = &target->caps();
@@ -648,8 +657,17 @@
}
auto clip = target->detachAppliedClip();
- auto* fixedDynamicState = target->allocFixedDynamicState(clip.scissorState().rect(), 1);
- fixedDynamicState->fPrimitiveProcessorTextures[0] = fProxy;
+ // We'll use a dynamic state array for the GP textures when there are multiple ops.
+ // Otherwise, we use fixed dynamic state to specify the single op's proxy.
+ GrPipeline::DynamicStateArrays* dynamicStateArrays = nullptr;
+ GrPipeline::FixedDynamicState* fixedDynamicState;
+ if (numOps > 1) {
+ dynamicStateArrays = target->allocDynamicStateArrays(numOps, 1, false);
+ fixedDynamicState = target->allocFixedDynamicState(clip.scissorState().rect(), 0);
+ } else {
+ fixedDynamicState = target->allocFixedDynamicState(clip.scissorState().rect(), 1);
+ fixedDynamicState->fPrimitiveProcessorTextures[0] = fProxy;
+ }
const auto* pipeline =
target->allocPipeline(args, GrProcessorSet::MakeEmptySet(), std::move(clip));
using TessFn = decltype(&TextureOp::tess<SkPoint, Domain::kNo, GrAA::kNo>);
@@ -673,42 +691,50 @@
};
#undef TESS_FN_AND_VERTEX_SIZE
int tessFnIdx = 0;
- tessFnIdx |= coverageAA ? 0x1 : 0x0;
- tessFnIdx |= fDomain ? 0x2 : 0x0;
- tessFnIdx |= fPerspective ? 0x4 : 0x0;
+ tessFnIdx |= coverageAA ? 0x1 : 0x0;
+ tessFnIdx |= (domain == Domain::kYes) ? 0x2 : 0x0;
+ tessFnIdx |= hasPerspective ? 0x4 : 0x0;
SkASSERT(kTessFnsAndVertexSizes[tessFnIdx].fVertexSize == gp->debugOnly_vertexStride());
- int vstart;
- const GrBuffer* vbuffer;
- void* vdata = target->makeVertexSpace(kTessFnsAndVertexSizes[tessFnIdx].fVertexSize,
- 4 * fDraws.count(), &vbuffer, &vstart);
- if (!vdata) {
- SkDebugf("Could not allocate vertices\n");
- return;
- }
-
- (this->*(kTessFnsAndVertexSizes[tessFnIdx].fTessFn))(vdata, gp.get());
-
- GrPrimitiveType primitiveType =
- fDraws.count() > 1 ? GrPrimitiveType::kTriangles : GrPrimitiveType::kTriangleStrip;
- GrMesh* mesh = target->allocMesh(primitiveType);
- if (fDraws.count() > 1) {
- sk_sp<const GrBuffer> ibuffer = target->resourceProvider()->refQuadIndexBuffer();
- if (!ibuffer) {
- SkDebugf("Could not allocate quad indices\n");
+ GrMesh* meshes = target->allocMeshes(numOps);
+ int i = 0;
+ for (const auto& op : ChainRange<TextureOp>(this)) {
+ int vstart;
+ const GrBuffer* vbuffer;
+ void* vdata = target->makeVertexSpace(kTessFnsAndVertexSizes[tessFnIdx].fVertexSize,
+ 4 * op.fDraws.count(), &vbuffer, &vstart);
+ if (!vdata) {
+ SkDebugf("Could not allocate vertices\n");
return;
}
- mesh->setIndexedPatterned(ibuffer.get(), 6, 4, fDraws.count(),
- GrResourceProvider::QuadCountOfQuadBuffer());
- } else {
- mesh->setNonIndexedNonInstanced(4);
+
+ (op.*(kTessFnsAndVertexSizes[tessFnIdx].fTessFn))(vdata, gp.get());
+
+ if (op.fDraws.count() > 1) {
+ meshes[i].setPrimitiveType(GrPrimitiveType::kTriangles);
+ sk_sp<const GrBuffer> ibuffer = target->resourceProvider()->refQuadIndexBuffer();
+ if (!ibuffer) {
+ SkDebugf("Could not allocate quad indices\n");
+ return;
+ }
+ meshes[i].setIndexedPatterned(ibuffer.get(), 6, 4, op.fDraws.count(),
+ GrResourceProvider::QuadCountOfQuadBuffer());
+ } else {
+ meshes[i].setPrimitiveType(GrPrimitiveType::kTriangleStrip);
+ meshes[i].setNonIndexedNonInstanced(4);
+ }
+ meshes[i].setVertexData(vbuffer, vstart);
+ if (dynamicStateArrays) {
+ dynamicStateArrays->fPrimitiveProcessorTextures[i] = op.fProxy;
+ }
+ ++i;
}
- mesh->setVertexData(vbuffer, vstart);
- target->draw(std::move(gp), pipeline, fixedDynamicState, mesh);
+ target->draw(std::move(gp), pipeline, fixedDynamicState, dynamicStateArrays, meshes,
+ numOps);
}
- CombineResult onCombineIfPossible(GrOp* t, const GrCaps&) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
const auto* that = t->cast<TextureOp>();
if (!GrColorSpaceXform::Equals(fTextureColorSpaceXform.get(),
that->fTextureColorSpaceXform.get())) {
@@ -721,7 +747,17 @@
if (this->aaType() != that->aaType()) {
return CombineResult::kCannotCombine;
}
- if (fProxy->uniqueID() != that->fProxy->uniqueID() || fFilter != that->fFilter) {
+ if (fFilter != that->fFilter) {
+ return CombineResult::kCannotCombine;
+ }
+ if (fProxy->uniqueID() != that->fProxy->uniqueID() || that->isChained()) {
+ // We can't merge across different proxies (and we're disallowed from merging when
+ // 'that' is chained. Check if we can be chained with 'that'.
+ if (fProxy->config() == that->fProxy->config() &&
+ fProxy->textureType() == that->fProxy->textureType() &&
+ caps.dynamicStateArrayGeometryProcessorTextureSupport()) {
+ return CombineResult::kMayChain;
+ }
return CombineResult::kCannotCombine;
}
fDraws.push_back_n(that->fDraws.count(), that->fDraws.begin());