Reduce stencil buffer clearing

TBR=bsalomon@google.com
Bug: skia:6953
Change-Id: I079f90711297ee290f2d4011cfcb18b764554deb
Reviewed-on: https://skia-review.googlesource.com/40691
Reviewed-by: Robert Phillips <robertphillips@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Robert Phillips 2017-08-30 16:44:40 -04:00
parent dff47afd5a
commit cb2e235e6f
10 changed files with 61 additions and 22 deletions

View File

@ -403,6 +403,7 @@ skia_gpu_sources = [
"$_src/gpu/gl/GrGLGLSL.h",
"$_src/gpu/gl/GrGLGpu.cpp",
"$_src/gpu/gl/GrGLGpu.h",
"$_src/gpu/gl/GrGLGpuCommandBuffer.cpp",
"$_src/gpu/gl/GrGLGpuCommandBuffer.h",
"$_src/gpu/gl/GrGLGpuProgramCache.cpp",
"$_src/gpu/gl/GrGLExtensions.cpp",

View File

@ -25,6 +25,8 @@ class GrStencilAttachment;
*/
class GrRenderTarget : virtual public GrSurface {
public:
virtual bool alwaysClearStencil() const { return false; }
// GrSurface overrides
GrRenderTarget* asRenderTarget() override { return this; }
const GrRenderTarget* asRenderTarget() const override { return this; }

View File

@ -97,7 +97,7 @@ static std::unique_ptr<GrGpuRTCommandBuffer> create_command_buffer(GrGpu* gpu,
GrLoadOp colorLoadOp,
GrColor loadClearColor,
GrLoadOp stencilLoadOp) {
const GrGpuRTCommandBuffer::LoadAndStoreInfo kBasicLoadStoreInfo {
const GrGpuRTCommandBuffer::LoadAndStoreInfo kColorLoadStoreInfo {
colorLoadOp,
GrStoreOp::kStore,
loadClearColor
@ -115,8 +115,8 @@ static std::unique_ptr<GrGpuRTCommandBuffer> create_command_buffer(GrGpu* gpu,
std::unique_ptr<GrGpuRTCommandBuffer> buffer(
gpu->createCommandBuffer(rt, origin,
kBasicLoadStoreInfo, // Color
stencilLoadAndStoreInfo)); // Stencil
kColorLoadStoreInfo,
stencilLoadAndStoreInfo));
return buffer;
}

View File

@ -451,6 +451,7 @@ GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget*
height = SkNextPow2(height);
}
#endif
SkDEBUGCODE(bool newStencil = false;)
GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height,
rt->numStencilSamples(), &sbKey);
GrStencilAttachment* stencil = static_cast<GrStencilAttachment*>(
@ -460,13 +461,18 @@ GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget*
stencil = this->gpu()->createStencilAttachmentForRenderTarget(rt, width, height);
if (stencil) {
this->assignUniqueKeyToResource(sbKey, stencil);
SkDEBUGCODE(newStencil = true;)
}
}
if (rt->renderTargetPriv().attachStencilAttachment(stencil)) {
#ifdef SK_DEBUG
// Fill the SB with an inappropriate value. opLists that use the
// SB should clear it properly.
this->gpu()->clearStencil(rt, 0xFFFF);
if (newStencil) {
SkASSERT(stencil->isDirty());
this->gpu()->clearStencil(rt, 0xFFFF);
SkASSERT(stencil->isDirty());
}
#endif
}
}

View File

@ -17,9 +17,7 @@ class GrResourceKey;
class GrStencilAttachment : public GrGpuResource {
public:
virtual ~GrStencilAttachment() {
~GrStencilAttachment() override {
// TODO: allow SB to be purged and detach itself from rts
}
@ -27,6 +25,9 @@ public:
int height() const { return fHeight; }
int bits() const { return fBits; }
int numSamples() const { return fSampleCnt; }
bool isDirty() const { return fIsDirty; }
void cleared() { fIsDirty = false; }
// We create a unique stencil buffer at each width, height and sampleCnt and share it for
// all render targets that require a stencil with those params.
@ -35,11 +36,12 @@ public:
protected:
GrStencilAttachment(GrGpu* gpu, int width, int height, int bits, int sampleCnt)
: GrGpuResource(gpu)
, fWidth(width)
, fHeight(height)
, fBits(bits)
, fSampleCnt(sampleCnt) {
: INHERITED(gpu)
, fWidth(width)
, fHeight(height)
, fBits(bits)
, fSampleCnt(sampleCnt)
, fIsDirty(true) {
}
private:
@ -48,6 +50,7 @@ private:
int fHeight;
int fBits;
int fSampleCnt;
bool fIsDirty;
typedef GrGpuResource INHERITED;
};

View File

@ -1960,6 +1960,12 @@ void GrGLGpu::clearStencil(GrRenderTarget* target, int clearValue) {
if (!target) {
return;
}
GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
// this should only be called internally when we know we have a
// stencil buffer.
SkASSERT(sb);
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
this->flushRenderTarget(glRT, &SkIRect::EmptyIRect());
@ -1970,6 +1976,9 @@ void GrGLGpu::clearStencil(GrRenderTarget* target, int clearValue) {
GL_CALL(ClearStencil(clearValue));
GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
fHWStencilSettings.invalidate();
if (!clearValue) {
sb->cleared();
}
}
void GrGLGpu::clearStencilClip(const GrFixedClip& clip,

View File

@ -0,0 +1,24 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLGpuCommandBuffer.h"
#include "GrFixedClip.h"
#include "GrRenderTargetPriv.h"
void GrGLGpuRTCommandBuffer::begin() {
if (GrLoadOp::kClear == fColorLoadAndStoreInfo.fLoadOp) {
fGpu->clear(GrFixedClip::Disabled(), fColorLoadAndStoreInfo.fClearColor,
fRenderTarget, fOrigin);
}
if (GrLoadOp::kClear == fStencilLoadAndStoreInfo.fLoadOp) {
GrStencilAttachment* sb = fRenderTarget->renderTargetPriv().getStencilAttachment();
if (sb && (sb->isDirty() || fRenderTarget->alwaysClearStencil())) {
fGpu->clearStencil(fRenderTarget, 0x0);
}
}
}

View File

@ -61,15 +61,7 @@ public:
~GrGLGpuRTCommandBuffer() override {}
void begin() override {
if (GrLoadOp::kClear == fColorLoadAndStoreInfo.fLoadOp) {
fGpu->clear(GrFixedClip::Disabled(), fColorLoadAndStoreInfo.fClearColor,
fRenderTarget, fOrigin);
}
if (GrLoadOp::kClear == fStencilLoadAndStoreInfo.fLoadOp) {
fGpu->clearStencil(fRenderTarget, 0x0);
}
}
void begin() override;
void end() override {}
void discard() override { }

View File

@ -75,7 +75,7 @@ sk_sp<GrGLRenderTarget> GrGLRenderTarget::MakeWrapped(GrGLGpu* gpu,
format.fPacked = false;
format.fStencilBits = stencilBits;
format.fTotalBits = stencilBits;
// Owndership of sb is passed to the GrRenderTarget so doesn't need to be deleted
// Ownership of sb is passed to the GrRenderTarget so doesn't need to be deleted
sb = new GrGLStencilAttachment(gpu, sbDesc, desc.fWidth, desc.fHeight,
desc.fSampleCnt, format);
}

View File

@ -19,6 +19,8 @@ class GrGLStencilAttachment;
class GrGLRenderTarget : public GrRenderTarget {
public:
bool alwaysClearStencil() const override { return 0 == fRTFBOID; }
// set fTexFBOID to this value to indicate that it is multisampled but
// Gr doesn't know how to resolve it.
enum { kUnresolvableFBOID = 0 };