add support for clears to Metal backend
Bug: skia:
Change-Id: I35d9fcf096d078d6dc04093e3591df0ac12079b7
Reviewed-on: https://skia-review.googlesource.com/c/161821
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/GrCaps.h b/src/gpu/GrCaps.h
index 0027ee9..918ac14 100644
--- a/src/gpu/GrCaps.h
+++ b/src/gpu/GrCaps.h
@@ -253,6 +253,10 @@
return fDynamicStateArrayGeometryProcessorTextureSupport;
}
+ virtual bool performPartialClearsAsDraws() const {
+ return false;
+ }
+
/**
* This is can be called before allocating a texture to be a dst for copySurface. This is only
* used for doing dst copies needed in blends, thus the src is always a GrRenderTargetProxy. It
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index ddefb79..4beae87 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -240,9 +240,9 @@
bool canDiscardOutsideDstRect = false);
// Returns a GrGpuRTCommandBuffer which GrOpLists send draw commands to instead of directly
- // to the Gpu object.
+ // to the Gpu object. The 'bounds' rect is the content rect of the destination.
virtual GrGpuRTCommandBuffer* getCommandBuffer(
- GrRenderTarget*, GrSurfaceOrigin,
+ GrRenderTarget*, GrSurfaceOrigin, const SkRect& bounds,
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) = 0;
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 3333328..369eee8 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -294,12 +294,26 @@
// This path doesn't handle coalescing of full screen clears b.c. it
// has to clear the entire render target - not just the content area.
// It could be done but will take more finagling.
- std::unique_ptr<GrOp> op(GrClearOp::Make(fRenderTargetContext->fContext, rtRect,
- color, !clearRect));
- if (!op) {
- return;
+ if (clearRect && fRenderTargetContext->caps()->performPartialClearsAsDraws()) {
+ GrPaint paint;
+ paint.setColor4f(GrColor4f::FromGrColor(color));
+ SkRect scissor = SkRect::Make(rtRect);
+ std::unique_ptr<GrDrawOp> op(GrRectOpFactory::MakeNonAAFill(fRenderTargetContext->fContext,
+ std::move(paint), SkMatrix::I(),
+ scissor, GrAAType::kNone));
+ if (!op) {
+ return;
+ }
+ fRenderTargetContext->addDrawOp(GrFixedClip(), std::move(op));
}
- fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
+ else {
+ std::unique_ptr<GrOp> op(GrClearOp::Make(fRenderTargetContext->fContext, rtRect,
+ color, !clearRect));
+ if (!op) {
+ return;
+ }
+ fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
+ }
}
void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
@@ -329,11 +343,26 @@
if (isFull) {
this->getRTOpList()->fullClear(fContext, color);
} else {
- std::unique_ptr<GrOp> op(GrClearOp::Make(fContext, clip, color, this->asSurfaceProxy()));
- if (!op) {
- return;
+ if (this->caps()->performPartialClearsAsDraws()) {
+ GrPaint paint;
+ paint.setColor4f(GrColor4f::FromGrColor(color));
+ SkRect scissor = SkRect::Make(clip.scissorRect());
+ std::unique_ptr<GrDrawOp> op(GrRectOpFactory::MakeNonAAFill(fContext, std::move(paint),
+ SkMatrix::I(), scissor,
+ GrAAType::kNone));
+ if (!op) {
+ return;
+ }
+ this->addDrawOp(clip, std::move(op));
}
- this->getRTOpList()->addOp(std::move(op), *this->caps());
+ else {
+ std::unique_ptr<GrOp> op(GrClearOp::Make(fContext, clip, color,
+ this->asSurfaceProxy()));
+ if (!op) {
+ return;
+ }
+ this->getRTOpList()->addOp(std::move(op), *this->caps());
+ }
}
}
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 8215df7..41f4a67 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -118,6 +118,7 @@
static GrGpuRTCommandBuffer* create_command_buffer(GrGpu* gpu,
GrRenderTarget* rt,
GrSurfaceOrigin origin,
+ const SkRect& bounds,
GrLoadOp colorLoadOp,
GrColor loadClearColor,
GrLoadOp stencilLoadOp) {
@@ -137,7 +138,7 @@
GrStoreOp::kStore,
};
- return gpu->getCommandBuffer(rt, origin, kColorLoadStoreInfo, stencilLoadAndStoreInfo);
+ return gpu->getCommandBuffer(rt, origin, bounds, kColorLoadStoreInfo, stencilLoadAndStoreInfo);
}
// TODO: this is where GrOp::renderTarget is used (which is fine since it
@@ -164,6 +165,7 @@
flushState->gpu(),
fTarget.get()->peekRenderTarget(),
fTarget.get()->origin(),
+ fTarget.get()->getBoundsRect(),
fColorLoadOp,
fLoadClearColor,
fStencilLoadOp);
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index d5a8d42..938ead1 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -2174,7 +2174,7 @@
}
GrGpuRTCommandBuffer* GrGLGpu::getCommandBuffer(
- GrRenderTarget* rt, GrSurfaceOrigin origin,
+ GrRenderTarget* rt, GrSurfaceOrigin origin, const SkRect& bounds,
const GrGpuRTCommandBuffer::LoadAndStoreInfo& colorInfo,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) {
if (!fCachedRTCommandBuffer) {
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 4fa1752..87f452f 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -121,7 +121,7 @@
void clearStencil(GrRenderTarget*, int clearValue);
GrGpuRTCommandBuffer* getCommandBuffer(
- GrRenderTarget*, GrSurfaceOrigin,
+ GrRenderTarget*, GrSurfaceOrigin, const SkRect&,
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) override;
diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp
index 8a8aee6..a7a83e3 100644
--- a/src/gpu/mock/GrMockGpu.cpp
+++ b/src/gpu/mock/GrMockGpu.cpp
@@ -48,7 +48,7 @@
}
GrGpuRTCommandBuffer* GrMockGpu::getCommandBuffer(
- GrRenderTarget* rt, GrSurfaceOrigin origin,
+ GrRenderTarget* rt, GrSurfaceOrigin origin, const SkRect& bounds,
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) {
return new GrMockGpuRTCommandBuffer(this, rt, origin);
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index 8155e62..64b267b 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -25,7 +25,7 @@
~GrMockGpu() override {}
GrGpuRTCommandBuffer* getCommandBuffer(
- GrRenderTarget*, GrSurfaceOrigin,
+ GrRenderTarget*, GrSurfaceOrigin, const SkRect&,
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) override;
diff --git a/src/gpu/mtl/GrMtlCaps.h b/src/gpu/mtl/GrMtlCaps.h
index c10f656..e72ea83 100644
--- a/src/gpu/mtl/GrMtlCaps.h
+++ b/src/gpu/mtl/GrMtlCaps.h
@@ -80,6 +80,10 @@
return false;
}
+ bool performPartialClearsAsDraws() const override {
+ return true;
+ }
+
private:
void initFeatureSet(MTLFeatureSet featureSet);
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index 5c5d257..28036bf 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -88,7 +88,7 @@
bool canDiscardOutsideDstRect) override;
GrGpuRTCommandBuffer* getCommandBuffer(
- GrRenderTarget*, GrSurfaceOrigin,
+ GrRenderTarget*, GrSurfaceOrigin, const SkRect& bounds,
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) override;
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index 6624eef..37e7608 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -107,10 +107,10 @@
}
GrGpuRTCommandBuffer* GrMtlGpu::getCommandBuffer(
- GrRenderTarget* renderTarget, GrSurfaceOrigin origin,
+ GrRenderTarget* renderTarget, GrSurfaceOrigin origin, const SkRect& bounds,
const GrGpuRTCommandBuffer::LoadAndStoreInfo& colorInfo,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) {
- return new GrMtlGpuRTCommandBuffer(this, renderTarget, origin, colorInfo, stencilInfo);
+ return new GrMtlGpuRTCommandBuffer(this, renderTarget, origin, bounds, colorInfo, stencilInfo);
}
GrGpuTextureCommandBuffer* GrMtlGpu::getCommandBuffer(GrTexture* texture,
diff --git a/src/gpu/mtl/GrMtlGpuCommandBuffer.h b/src/gpu/mtl/GrMtlGpuCommandBuffer.h
index 83efb07..db63860 100644
--- a/src/gpu/mtl/GrMtlGpuCommandBuffer.h
+++ b/src/gpu/mtl/GrMtlGpuCommandBuffer.h
@@ -43,6 +43,7 @@
class GrMtlGpuRTCommandBuffer : public GrGpuRTCommandBuffer, private GrMesh::SendToGpuImpl {
public:
GrMtlGpuRTCommandBuffer(GrMtlGpu* gpu, GrRenderTarget* rt, GrSurfaceOrigin origin,
+ const SkRect& bounds,
const GrGpuRTCommandBuffer::LoadAndStoreInfo& colorInfo,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo& stencilInfo);
@@ -83,7 +84,7 @@
int meshCount,
const SkRect& bounds) override;
- void onClear(const GrFixedClip& clip, GrColor color) override {}
+ void onClear(const GrFixedClip& clip, GrColor color) override;
void onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) override;
@@ -119,6 +120,8 @@
int baseInstance, GrPrimitiveRestart) final;
GrMtlGpu* fGpu;
+ // GrRenderTargetProxy bounds
+ SkRect fBounds;
GrGpuRTCommandBuffer::LoadAndStoreInfo fColorLoadAndStoreInfo;
GrGpuRTCommandBuffer::StencilLoadAndStoreInfo fStencilLoadAndStoreInfo;
diff --git a/src/gpu/mtl/GrMtlGpuCommandBuffer.mm b/src/gpu/mtl/GrMtlGpuCommandBuffer.mm
index 2b3b020..9864690 100644
--- a/src/gpu/mtl/GrMtlGpuCommandBuffer.mm
+++ b/src/gpu/mtl/GrMtlGpuCommandBuffer.mm
@@ -15,11 +15,12 @@
#include "GrRenderTargetPriv.h"
GrMtlGpuRTCommandBuffer::GrMtlGpuRTCommandBuffer(
- GrMtlGpu* gpu, GrRenderTarget* rt, GrSurfaceOrigin origin,
+ GrMtlGpu* gpu, GrRenderTarget* rt, GrSurfaceOrigin origin, const SkRect& bounds,
const GrGpuRTCommandBuffer::LoadAndStoreInfo& colorInfo,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo& stencilInfo)
: INHERITED(rt, origin)
, fGpu(gpu)
+ , fBounds(bounds)
, fColorLoadAndStoreInfo(colorInfo)
, fStencilLoadAndStoreInfo(stencilInfo)
, fRenderPassDesc(this->createRenderPassDesc()) {
@@ -178,6 +179,19 @@
fCommandBufferInfo.fBounds.join(bounds);
}
+void GrMtlGpuRTCommandBuffer::onClear(const GrFixedClip& clip, GrColor color) {
+ // if we end up here from absClear, the clear bounds may be bigger than the RT proxy bounds -
+ // but in that case, scissor should be enabled, so this check should still succeed
+ SkASSERT(!clip.scissorEnabled() || clip.scissorRect().contains(fBounds));
+ const auto& clear = GrColor4f::FromGrColor(color).fRGBA;
+ fRenderPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(clear[0], clear[1], clear[2],
+ clear[3]);
+ fRenderPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
+ this->internalBegin();
+ this->internalEnd();
+ fRenderPassDesc.colorAttachments[0].loadAction = MTLLoadActionLoad;
+}
+
void GrMtlGpuRTCommandBuffer::onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
SkASSERT(!clip.hasWindowRectangles());
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index d002955..2e6d97d 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -281,7 +281,7 @@
///////////////////////////////////////////////////////////////////////////////
GrGpuRTCommandBuffer* GrVkGpu::getCommandBuffer(
- GrRenderTarget* rt, GrSurfaceOrigin origin,
+ GrRenderTarget* rt, GrSurfaceOrigin origin, const SkRect& bounds,
const GrGpuRTCommandBuffer::LoadAndStoreInfo& colorInfo,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) {
if (!fCachedRTCommandBuffer) {
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 80645a3..3b9a2e5 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -92,7 +92,7 @@
int height) override;
GrGpuRTCommandBuffer* getCommandBuffer(
- GrRenderTarget*, GrSurfaceOrigin,
+ GrRenderTarget*, GrSurfaceOrigin, const SkRect&,
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) override;