Use texture barriers to read directly from the RT
Updates GrXferProcessor to read directly from the RT texture when
texture barriers are supported and it needs to know the dst color.
Also adds the notion of an Xfer barrier and uses it to issue texture
barriers when the XP will read the RT.
BUG=skia:
Review URL: https://codereview.chromium.org/1040303002
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index e52e4f9..d868bcb 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -78,8 +78,20 @@
if (!pipelineBuilder.willXPNeedDstCopy(*this->caps(), colorPOI, coveragePOI)) {
return true;
}
- SkIRect copyRect;
+
GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
+
+ if (this->caps()->textureBarrierSupport()) {
+ if (GrTexture* rtTex = rt->asTexture()) {
+ // The render target is a texture, se we can read from it directly in the shader. The XP
+ // will be responsible to detect this situation and request a texture barrier.
+ dstCopy->setTexture(rtTex);
+ dstCopy->setOffset(0, 0);
+ return true;
+ }
+ }
+
+ SkIRect copyRect;
pipelineBuilder.clip().getConservativeBounds(rt, ©Rect);
if (drawBounds) {
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 5784781..b2dbec6 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -304,6 +304,9 @@
const SkIRect& srcRect,
const SkIPoint& dstPoint) = 0;
+ // Called before certain draws in order to guarantee coherent results from dst reads.
+ virtual void xferBarrier(GrXferBarrierType) = 0;
+
struct DrawArgs {
typedef GrDrawTarget::DrawInfo DrawInfo;
DrawArgs(const GrPrimitiveProcessor* primProc,
diff --git a/src/gpu/GrTargetCommands.cpp b/src/gpu/GrTargetCommands.cpp
index c448db9..24ee32d 100644
--- a/src/gpu/GrTargetCommands.cpp
+++ b/src/gpu/GrTargetCommands.cpp
@@ -341,6 +341,10 @@
gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
}
+void GrTargetCommands::XferBarrier::execute(GrGpu* gpu, const SetState* state) {
+ gpu->xferBarrier(fBarrierType);
+}
+
GrTargetCommands::Cmd* GrTargetCommands::recordCopySurface(GrSurface* dst,
GrSurface* src,
const SkIRect& srcRect,
@@ -375,6 +379,8 @@
fPrevState = ss;
iodb->recordTraceMarkersIfNecessary(ss);
}
+
+ this->recordXferBarrierIfNecessary(iodb, pipelineInfo);
return true;
}
@@ -398,6 +404,25 @@
fPrevState = ss;
iodb->recordTraceMarkersIfNecessary(ss);
}
+
+ this->recordXferBarrierIfNecessary(iodb, pipelineInfo);
return true;
}
+void GrTargetCommands::recordXferBarrierIfNecessary(GrInOrderDrawBuffer* iodb,
+ const GrDrawTarget::PipelineInfo& info) {
+ SkASSERT(fPrevState);
+ const GrXferProcessor& xp = *fPrevState->getXferProcessor();
+ GrRenderTarget* rt = fPrevState->getRenderTarget();
+
+ GrXferBarrierType barrierType;
+ if (!xp.willNeedXferBarrier(rt, *iodb->caps(), &barrierType)) {
+ return;
+ }
+
+ XferBarrier* xb = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, XferBarrier, ());
+ xb->fBarrierType = barrierType;
+
+ iodb->recordTraceMarkersIfNecessary(xb);
+}
+
diff --git a/src/gpu/GrTargetCommands.h b/src/gpu/GrTargetCommands.h
index cff9898..4ab41db 100644
--- a/src/gpu/GrTargetCommands.h
+++ b/src/gpu/GrTargetCommands.h
@@ -56,6 +56,7 @@
kDrawPath_CmdType = 6,
kDrawPaths_CmdType = 7,
kDrawBatch_CmdType = 8,
+ kXferBarrier_CmdType = 9,
};
Cmd(CmdType type) : fMarkerID(-1), fType(type) {}
@@ -151,6 +152,8 @@
GrBatch*,
const GrDrawTarget::PipelineInfo&);
+ void recordXferBarrierIfNecessary(GrInOrderDrawBuffer*, const GrDrawTarget::PipelineInfo&);
+
struct Draw : public Cmd {
Draw(const GrDrawTarget::DrawInfo& info) : Cmd(kDraw_CmdType), fInfo(info) {}
@@ -276,6 +279,12 @@
const GrPipeline* getPipeline() const {
return reinterpret_cast<const GrPipeline*>(fPipeline.get());
}
+ GrRenderTarget* getRenderTarget() const {
+ return this->getPipeline()->getRenderTarget();
+ }
+ const GrXferProcessor* getXferProcessor() const {
+ return this->getPipeline()->getXferProcessor();
+ }
void execute(GrGpu*, const SetState*) override;
@@ -303,6 +312,14 @@
GrBatchTarget* fBatchTarget;
};
+ struct XferBarrier : public Cmd {
+ XferBarrier() : Cmd(kXferBarrier_CmdType) {}
+
+ void execute(GrGpu*, const SetState*) override;
+
+ GrXferBarrierType fBarrierType;
+ };
+
static const int kCmdBufferInitialSizeInBytes = 8 * 1024;
typedef void* TCmdAlign; // This wouldn't be enough align if a command used long double.
diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp
index 3c5d3dd..23739f2 100644
--- a/src/gpu/GrTest.cpp
+++ b/src/gpu/GrTest.cpp
@@ -170,6 +170,8 @@
return false;
}
+ void xferBarrier(GrXferBarrierType) override {}
+
private:
void onResetContext(uint32_t resetBits) override {}
diff --git a/src/gpu/GrXferProcessor.cpp b/src/gpu/GrXferProcessor.cpp
index de08ef0..42ac153 100644
--- a/src/gpu/GrXferProcessor.cpp
+++ b/src/gpu/GrXferProcessor.cpp
@@ -32,6 +32,19 @@
this->onGetGLProcessorKey(caps, b);
}
+bool GrXferProcessor::willNeedXferBarrier(const GrRenderTarget* rt,
+ const GrDrawTargetCaps& caps,
+ GrXferBarrierType* outBarrierType) const {
+ if (static_cast<const GrSurface*>(rt) == this->getDstCopyTexture()) {
+ // Texture barriers are required when a shader reads and renders to the same texture.
+ SkASSERT(rt);
+ SkASSERT(caps.textureBarrierSupport());
+ *outBarrierType = kTexture_GrXferBarrierType;
+ return true;
+ }
+ return false;
+}
+
///////////////////////////////////////////////////////////////////////////////
GrXferProcessor* GrXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 2c46f9b..4421b3c 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -2727,6 +2727,15 @@
return false;
}
+void GrGLGpu::xferBarrier(GrXferBarrierType type) {
+ switch (type) {
+ case kTexture_GrXferBarrierType:
+ SkASSERT(this->caps()->textureBarrierSupport());
+ GL_CALL(TextureBarrier());
+ return;
+ }
+}
+
void GrGLGpu::didAddGpuTraceMarker() {
if (this->caps()->gpuTracingSupport()) {
const GrTraceMarkerSet& markerArray = this->getActiveTraceMarkers();
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index d833ca5..5357142 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -105,6 +105,8 @@
const SkIRect& srcRect,
const SkIPoint& dstPoint) override;
+ void xferBarrier(GrXferBarrierType) override;
+
void buildProgramDesc(GrProgramDesc*,
const GrPrimitiveProcessor&,
const GrPipeline&,