Add a second stencil attachment to GrRenderTarget for dmsaa

As we move toward dmsaa, we need stencil attachments on the single and
multisample attachments both. This is only a temporary solution until
the new surface world is finished.

Bug: skia:11396
Change-Id: I48928343e1fc9fd2e00362a534be9eb3ade92656
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/399838
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Chris Dalton 2021-04-23 13:11:44 -06:00 committed by Skia Commit-Bot
parent 9a0da785a5
commit e0fe23a65e
40 changed files with 144 additions and 137 deletions

View File

@ -605,8 +605,9 @@ public:
// width and height may be larger than rt (if underlying API allows it).
// Returns nullptr if compatible sb could not be created, otherwise the caller owns the ref on
// the GrAttachment.
virtual sk_sp<GrAttachment> makeStencilAttachmentForRenderTarget(const GrRenderTarget*,
SkISize dimensions) = 0;
virtual sk_sp<GrAttachment> makeStencilAttachment(const GrBackendFormat& colorFormat,
SkISize dimensions,
int numStencilSamples) = 0;
virtual GrBackendFormat getPreferredStencilFormat(const GrBackendFormat&) = 0;

View File

@ -563,11 +563,12 @@ bool GrOpsTask::onExecute(GrOpFlushState* flushState) {
GrAttachment* stencil = nullptr;
if (proxy->needsStencil()) {
if (!flushState->resourceProvider()->attachStencilAttachment(renderTarget)) {
if (!flushState->resourceProvider()->attachStencilAttachment(renderTarget,
fUsesMSAASurface)) {
SkDebugf("WARNING: failed to attach a stencil buffer. Rendering will be skipped.\n");
return false;
}
stencil = renderTarget->getStencilAttachment();
stencil = renderTarget->getStencilAttachment(fUsesMSAASurface);
}
GrLoadOp stencilLoadOp;

View File

@ -21,39 +21,46 @@ GrRenderTarget::GrRenderTarget(GrGpu* gpu,
GrProtected isProtected,
GrAttachment* stencil)
: INHERITED(gpu, dimensions, isProtected)
, fStencilAttachment(stencil)
, fSampleCnt(sampleCount) {
if (this->numSamples() > 1) {
fMSAAStencilAttachment.reset(stencil);
} else {
fStencilAttachment.reset(stencil);
}
}
GrRenderTarget::~GrRenderTarget() = default;
void GrRenderTarget::onRelease() {
fStencilAttachment = nullptr;
fMSAAStencilAttachment = nullptr;
INHERITED::onRelease();
}
void GrRenderTarget::onAbandon() {
fStencilAttachment = nullptr;
fMSAAStencilAttachment = nullptr;
INHERITED::onAbandon();
}
void GrRenderTarget::attachStencilAttachment(sk_sp<GrAttachment> stencil) {
if (!stencil && !fStencilAttachment) {
void GrRenderTarget::attachStencilAttachment(sk_sp<GrAttachment> stencil, bool useMSAASurface) {
auto stencilAttachment = (useMSAASurface) ? &GrRenderTarget::fMSAAStencilAttachment
: &GrRenderTarget::fStencilAttachment;
if (!stencil && !(this->*stencilAttachment)) {
// No need to do any work since we currently don't have a stencil attachment and
// we're not actually adding one.
return;
}
fStencilAttachment = std::move(stencil);
if (!this->completeStencilAttachment()) {
fStencilAttachment = nullptr;
if (!this->completeStencilAttachment(stencil.get(), useMSAASurface)) {
return;
}
this->*stencilAttachment = std::move(stencil);
}
int GrRenderTarget::numStencilBits() const {
SkASSERT(this->getStencilAttachment());
return GrBackendFormatStencilBits(this->getStencilAttachment()->backendFormat());
int GrRenderTarget::numStencilBits(bool useMSAASurface) const {
return GrBackendFormatStencilBits(this->getStencilAttachment(useMSAASurface)->backendFormat());
}

View File

@ -41,13 +41,20 @@ public:
virtual GrBackendRenderTarget getBackendRenderTarget() const = 0;
GrAttachment* getStencilAttachment() const { return fStencilAttachment.get(); }
GrAttachment* getStencilAttachment(bool useMSAASurface) const {
return (useMSAASurface) ? fMSAAStencilAttachment.get() : fStencilAttachment.get();
}
GrAttachment* getStencilAttachment() const {
return getStencilAttachment(this->numSamples() > 1);
}
// Checked when this object is asked to attach a stencil buffer.
virtual bool canAttemptStencilAttachment() const = 0;
virtual bool canAttemptStencilAttachment(bool useMSAASurface) const = 0;
void attachStencilAttachment(sk_sp<GrAttachment> stencil);
void attachStencilAttachment(sk_sp<GrAttachment> stencil, bool useMSAASurface);
int numStencilBits() const;
int numStencilBits(bool useMSAASurface) const;
/**
* Returns a unique key that identifies this render target's sample pattern. (Must be
@ -75,9 +82,10 @@ private:
// GrAttachment. When this is called, the GrAttachment has already been put onto
// the GrRenderTarget. This function must return false if any failures occur when completing the
// stencil attachment.
virtual bool completeStencilAttachment() = 0;
virtual bool completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) = 0;
sk_sp<GrAttachment> fStencilAttachment;
sk_sp<GrAttachment> fMSAAStencilAttachment;
int fSampleCnt;
using INHERITED = GrSurface;

View File

@ -89,15 +89,6 @@ bool GrRenderTargetProxy::instantiate(GrResourceProvider* resourceProvider) {
return true;
}
bool GrRenderTargetProxy::canChangeStencilAttachment() const {
if (!fTarget) {
// If we aren't instantiated, then we definitely are an internal render target. Ganesh is
// free to change stencil attachments on internal render targets.
return true;
}
return fTarget->asRenderTarget()->canAttemptStencilAttachment();
}
sk_sp<GrSurface> GrRenderTargetProxy::createSurface(GrResourceProvider* resourceProvider) const {
sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, fSampleCnt,
GrRenderable::kYes, GrMipmapped::kNo);

View File

@ -157,8 +157,6 @@ protected:
sk_sp<GrSurface> createSurface(GrResourceProvider*) const override;
private:
bool canChangeStencilAttachment() const;
size_t onUninstantiatedGpuMemorySize() const override;
SkDEBUGCODE(void onValidateSurface(const GrSurface*) override;)

View File

@ -493,15 +493,15 @@ sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType
return buffer;
}
bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt) {
bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, bool useMSAASurface) {
SkASSERT(rt);
GrAttachment* stencil = rt->getStencilAttachment();
GrAttachment* stencil = rt->getStencilAttachment(useMSAASurface);
if (stencil) {
SkASSERT(stencil->numSamples() == rt->numSamples());
return true;
}
if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment(useMSAASurface)) {
GrUniqueKey sbKey;
#if 0
@ -510,8 +510,7 @@ bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt) {
height = SkNextPow2(height);
}
#endif
GrBackendFormat stencilFormat =
this->gpu()->getPreferredStencilFormat(rt->backendFormat());
GrBackendFormat stencilFormat = this->gpu()->getPreferredStencilFormat(rt->backendFormat());
if (!stencilFormat.isValid()) {
return false;
}
@ -523,15 +522,16 @@ bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt) {
auto stencil = this->findByUniqueKey<GrAttachment>(sbKey);
if (!stencil) {
// Need to try and create a new stencil
stencil = this->gpu()->makeStencilAttachmentForRenderTarget(rt, rt->dimensions());
stencil = this->gpu()->makeStencilAttachment(rt->backendFormat(), rt->dimensions(),
rt->numSamples());
if (!stencil) {
return false;
}
this->assignUniqueKeyToResource(sbKey, stencil.get());
}
rt->attachStencilAttachment(std::move(stencil));
rt->attachStencilAttachment(std::move(stencil), useMSAASurface);
}
stencil = rt->getStencilAttachment();
stencil = rt->getStencilAttachment(useMSAASurface);
SkASSERT(!stencil || stencil->numSamples() == rt->numSamples());
return stencil != nullptr;
}

View File

@ -267,10 +267,10 @@ public:
const void* data = nullptr);
/**
* If passed in render target already has a stencil buffer with at least "numSamples" samples,
* return true. Otherwise attempt to attach one and return true on success.
* If passed in render target already has a stencil buffer on the specified surface, return
* true. Otherwise attempt to attach one and return true on success.
*/
bool attachStencilAttachment(GrRenderTarget* rt);
bool attachStencilAttachment(GrRenderTarget* rt, bool useMSAASurface);
sk_sp<GrAttachment> makeMSAAAttachment(SkISize dimensions,
const GrBackendFormat& format,

View File

@ -865,7 +865,7 @@ sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendRenderTarget(const GrBackendRenderT
// We don't allow the client to supply a premade stencil buffer. We always create one if needed.
SkASSERT(!rt.stencilBits());
if (tgt) {
SkASSERT(tgt->canAttemptStencilAttachment());
SkASSERT(tgt->canAttemptStencilAttachment(tgt->numSamples() > 1));
}
return std::move(tgt);
@ -881,15 +881,12 @@ sk_sp<GrGpuBuffer> GrD3DGpu::onCreateBuffer(size_t sizeInBytes, GrGpuBufferType
return std::move(buffer);
}
sk_sp<GrAttachment> GrD3DGpu::makeStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
SkISize dimensions) {
SkASSERT(dimensions.width() >= rt->width());
SkASSERT(dimensions.height() >= rt->height());
sk_sp<GrAttachment> GrD3DGpu::makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
SkISize dimensions, int numStencilSamples) {
DXGI_FORMAT sFmt = this->d3dCaps().preferredStencilFormat();
fStats.incStencilAttachmentCreates();
return GrD3DAttachment::MakeStencil(this, dimensions, rt->numSamples(), sFmt);
return GrD3DAttachment::MakeStencil(this, dimensions, numStencilSamples, sFmt);
}
bool GrD3DGpu::createTextureResourceForBackendSurface(DXGI_FORMAT dxgiFormat,

View File

@ -76,8 +76,8 @@ public:
}
#endif
sk_sp<GrAttachment> makeStencilAttachmentForRenderTarget(const GrRenderTarget*,
SkISize dimensions) override;
sk_sp<GrAttachment> makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
SkISize dimensions, int numStencilSamples) override;
GrBackendFormat getPreferredStencilFormat(const GrBackendFormat&) override {
return GrBackendFormat::MakeDxgi(this->d3dCaps().preferredStencilFormat());

View File

@ -39,7 +39,8 @@ public:
const GrD3DTextureResource* msaaTextureResource() const;
GrD3DTextureResource* msaaTextureResource();
bool canAttemptStencilAttachment() const override {
bool canAttemptStencilAttachment(bool useMSAASurface) const override {
SkASSERT(useMSAASurface == (this->numSamples() > 1));
return true;
}
@ -106,7 +107,10 @@ private:
GrD3DGpu* getD3DGpu() const;
bool completeStencilAttachment() override { return true; }
bool completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) override {
SkASSERT(useMSAASurface == (this->numSamples() > 1));
return true;
}
// In Direct3D we call the release proc after we are finished with the underlying
// GrD3DTextureResource::Resource object (which occurs after the GPU finishes all work on it).

View File

@ -293,10 +293,10 @@ sk_sp<GrRenderTarget> GrDawnGpu::onWrapBackendRenderTarget(const GrBackendRender
return GrDawnRenderTarget::MakeWrapped(this, dimensions, sampleCnt, info);
}
sk_sp<GrAttachment> GrDawnGpu::makeStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
SkISize dimensions) {
sk_sp<GrAttachment> GrDawnGpu::makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
SkISize dimensions, int numStencilSamples) {
fStats.incStencilAttachmentCreates();
return GrDawnAttachment::MakeStencil(this, dimensions, rt->numSamples());
return GrDawnAttachment::MakeStencil(this, dimensions, numStencilSamples);
}
GrBackendTexture GrDawnGpu::onCreateBackendTexture(SkISize dimensions,

View File

@ -59,8 +59,8 @@ public:
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
#endif
sk_sp<GrAttachment> makeStencilAttachmentForRenderTarget(const GrRenderTarget*,
SkISize dimensions) override;
sk_sp<GrAttachment> makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
SkISize dimensions, int numStencilSamples) override;
GrBackendFormat getPreferredStencilFormat(const GrBackendFormat&) override {
return GrBackendFormat::MakeDawn(wgpu::TextureFormat::Depth24PlusStencil8);

View File

@ -331,7 +331,7 @@ sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
#ifdef SK_DEBUG
if (programInfo.isStencilEnabled()) {
SkASSERT(renderTarget->numStencilBits() == 8);
SkASSERT(renderTarget->numStencilBits(renderTarget->numSamples() > 1) == 8);
}
#endif
depthStencilState = create_depth_stencil_state(programInfo, depthStencilFormat);

View File

@ -35,7 +35,8 @@ size_t GrDawnRenderTarget::onGpuMemorySize() const {
GrMipmapped::kNo);
}
bool GrDawnRenderTarget::completeStencilAttachment() {
bool GrDawnRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) {
SkASSERT(useMSAASurface == (this->numSamples() > 1));
return true;
}

View File

@ -22,7 +22,8 @@ public:
~GrDawnRenderTarget() override;
bool canAttemptStencilAttachment() const override {
bool canAttemptStencilAttachment(bool useMSAASurface) const override {
SkASSERT(useMSAASurface == (this->numSamples() > 1));
return true;
}
@ -43,7 +44,7 @@ protected:
// This accounts for the texture's memory and any MSAA renderbuffer's memory.
size_t onGpuMemorySize() const override;
bool completeStencilAttachment() override;
bool completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) override;
GrDawnRenderTargetInfo fInfo;
using INHERITED = GrRenderTarget;
};

View File

@ -21,7 +21,8 @@ GrDawnTextureRenderTarget::GrDawnTextureRenderTarget(GrDawnGpu* gpu,
, GrDawnRenderTarget(gpu, dimensions, sampleCnt,
GrDawnRenderTargetInfo(textureInfo)) {}
bool GrDawnTextureRenderTarget::canAttemptStencilAttachment() const {
bool GrDawnTextureRenderTarget::canAttemptStencilAttachment(bool useMSAASurface) const {
SkASSERT(useMSAASurface == (this->numSamples() > 1));
return true;
}

View File

@ -27,7 +27,7 @@ public:
const GrDawnTextureInfo& textureInfo,
GrMipmapStatus mipmapStatus);
bool canAttemptStencilAttachment() const override;
bool canAttemptStencilAttachment(bool useMSAASurface) const override;
GrBackendFormat backendFormat() const override { return GrDawnTexture::backendFormat(); }

View File

@ -1686,14 +1686,11 @@ GrGLuint GrGLGpu::createTexture(SkISize dimensions,
return 0;
}
sk_sp<GrAttachment> GrGLGpu::makeStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
SkISize dimensions) {
SkASSERT(dimensions.width() >= rt->width());
SkASSERT(dimensions.height() >= rt->height());
sk_sp<GrAttachment> GrGLGpu::makeStencilAttachment(const GrBackendFormat& colorFormat,
SkISize dimensions, int numStencilSamples) {
GrGLAttachment::IDDesc sbDesc;
int sIdx = this->getCompatibleStencilIndex(rt->backendFormat().asGLFormat());
int sIdx = this->getCompatibleStencilIndex(colorFormat.asGLFormat());
if (sIdx < 0) {
return nullptr;
}
@ -1709,8 +1706,8 @@ sk_sp<GrAttachment> GrGLGpu::makeStencilAttachmentForRenderTarget(const GrRender
GrGLenum glFmt = GrGLFormatToEnum(sFmt);
// we do this "if" so that we don't call the multisample
// version on a GL that doesn't have an MSAA extension.
if (rt->numSamples() > 1) {
if (!this->renderbufferStorageMSAA(*fGLContext, rt->numSamples(), glFmt,
if (numStencilSamples > 1) {
if (!this->renderbufferStorageMSAA(*fGLContext, numStencilSamples, glFmt,
dimensions.width(), dimensions.height())) {
GL_CALL(DeleteRenderbuffers(1, &sbDesc.fRenderbufferID));
return nullptr;
@ -1728,7 +1725,7 @@ sk_sp<GrAttachment> GrGLGpu::makeStencilAttachmentForRenderTarget(const GrRender
return sk_sp<GrAttachment>(new GrGLAttachment(
this, sbDesc, dimensions, GrAttachment::UsageFlags::kStencilAttachment,
rt->numSamples(), sFmt));
numStencilSamples, sFmt));
}
////////////////////////////////////////////////////////////////////////////////
@ -1838,10 +1835,10 @@ bool GrGLGpu::flushGLState(GrRenderTarget* renderTarget, bool useMultisampleFBO,
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(renderTarget);
GrStencilSettings stencil;
if (programInfo.isStencilEnabled()) {
SkASSERT(glRT->getStencilAttachment());
SkASSERT(glRT->getStencilAttachment(useMultisampleFBO));
stencil.reset(*programInfo.userStencilSettings(),
programInfo.pipeline().hasStencilClip(),
glRT->numStencilBits());
glRT->numStencilBits(useMultisampleFBO));
}
this->flushStencil(stencil, programInfo.origin());
this->flushScissorTest(GrScissorTest(programInfo.pipeline().isScissorTestEnabled()));
@ -2040,13 +2037,14 @@ void GrGLGpu::endCommandBuffer(GrRenderTarget* rt, bool useMultisampleFBO,
}
void GrGLGpu::clearStencilClip(const GrScissorState& scissor, bool insideStencilMask,
GrRenderTarget* target, GrSurfaceOrigin origin) {
GrRenderTarget* target, bool useMultisampleFBO,
GrSurfaceOrigin origin) {
SkASSERT(target);
SkASSERT(!this->caps()->performStencilClearsAsDraws());
SkASSERT(!scissor.enabled() || !this->caps()->performPartialClearsAsDraws());
this->handleDirtyContext();
GrAttachment* sb = target->getStencilAttachment();
GrAttachment* sb = target->getStencilAttachment(useMultisampleFBO);
if (!sb) {
// We should only get here if we marked a proxy as requiring a SB. However,
// the SB creation could later fail. Likely clipping is going to go awry now.
@ -2072,7 +2070,7 @@ void GrGLGpu::clearStencilClip(const GrScissorState& scissor, bool insideStencil
value = 0;
}
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
this->flushRenderTargetNoColorWrites(glRT, glRT->stencilIsOnMultisampleFBO());
this->flushRenderTargetNoColorWrites(glRT, useMultisampleFBO);
this->flushScissor(scissor, glRT->height(), origin);
this->disableWindowRectangles();
@ -2164,7 +2162,7 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
GrOpsRenderPass* GrGLGpu::onGetOpsRenderPass(
GrRenderTarget* rt,
bool useMSAASurface,
bool useMultisampleFBO,
GrAttachment*,
GrSurfaceOrigin origin,
const SkIRect& bounds,
@ -2176,7 +2174,7 @@ GrOpsRenderPass* GrGLGpu::onGetOpsRenderPass(
fCachedOpsRenderPass = std::make_unique<GrGLOpsRenderPass>(this);
}
fCachedOpsRenderPass->set(rt, useMSAASurface, bounds, origin, colorInfo, stencilInfo);
fCachedOpsRenderPass->set(rt, useMultisampleFBO, bounds, origin, colorInfo, stencilInfo);
return fCachedOpsRenderPass.get();
}

View File

@ -113,7 +113,7 @@ public:
// Thus this is the implementation of the clearStencil call for the corresponding passthrough
// function on GrGLOpsrenderPass.
void clearStencilClip(const GrScissorState&, bool insideStencilMask,
GrRenderTarget*, GrSurfaceOrigin);
GrRenderTarget*, bool useMultisampleFBO, GrSurfaceOrigin);
void beginCommandBuffer(GrRenderTarget*, bool useMultisampleFBO,
const SkIRect& bounds, GrSurfaceOrigin,
@ -128,8 +128,8 @@ public:
fHWBoundRenderTargetUniqueID.makeInvalid();
}
sk_sp<GrAttachment> makeStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
SkISize dimensions) override;
sk_sp<GrAttachment> makeStencilAttachment(const GrBackendFormat& colorFormat,
SkISize dimensions, int numStencilSamples) override;
sk_sp<GrAttachment> makeMSAAAttachment(SkISize dimensions,
const GrBackendFormat& format,
@ -332,7 +332,7 @@ private:
GrGpuFinishedContext finishedContext) override;
GrOpsRenderPass* onGetOpsRenderPass(GrRenderTarget*,
bool useMSAASurface,
bool useMultisampleFBO,
GrAttachment*,
GrSurfaceOrigin,
const SkIRect&,

View File

@ -390,5 +390,5 @@ void GrGLOpsRenderPass::onClear(const GrScissorState& scissor, std::array<float,
}
void GrGLOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) {
fGpu->clearStencilClip(scissor, insideStencilMask, fRenderTarget, fOrigin);
fGpu->clearStencilClip(scissor, insideStencilMask, fRenderTarget, fUseMultisampleFBO, fOrigin);
}

View File

@ -100,11 +100,12 @@ sk_sp<GrGLRenderTarget> GrGLRenderTarget::MakeWrapped(GrGLGpu* gpu,
}
GrBackendRenderTarget GrGLRenderTarget::getBackendRenderTarget() const {
bool useMultisampleFBO = (this->numSamples() > 1);
GrGLFramebufferInfo fbi;
fbi.fFBOID = (this->numSamples() > 1) ? fMultisampleFBOID : fSingleSampleFBOID;
fbi.fFBOID = (useMultisampleFBO) ? fMultisampleFBOID : fSingleSampleFBOID;
fbi.fFormat = GrGLFormatToEnum(this->format());
int numStencilBits = 0;
if (GrAttachment* stencil = this->getStencilAttachment()) {
if (GrAttachment* stencil = this->getStencilAttachment(useMultisampleFBO)) {
numStencilBits = GrBackendFormatStencilBits(stencil->backendFormat());
}
@ -123,13 +124,12 @@ size_t GrGLRenderTarget::onGpuMemorySize() const {
fTotalMemorySamplesPerPixel, GrMipmapped::kNo);
}
bool GrGLRenderTarget::completeStencilAttachment() {
bool GrGLRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMultisampleFBO) {
SkASSERT(useMultisampleFBO == (this->numSamples() > 1));
GrGLGpu* gpu = this->getGLGpu();
const GrGLInterface* interface = gpu->glInterface();
GrAttachment* stencil = this->getStencilAttachment();
GrGLuint stencilFBOID = (useMultisampleFBO) ? fMultisampleFBOID : fSingleSampleFBOID;
GrGLuint stencilFBOID = (this->stencilIsOnMultisampleFBO()) ? fMultisampleFBOID
: fSingleSampleFBOID;
gpu->invalidateBoundRenderTarget();
gpu->bindFramebuffer(GR_GL_FRAMEBUFFER, stencilFBOID);
@ -203,7 +203,8 @@ GrGLGpu* GrGLRenderTarget::getGLGpu() const {
return static_cast<GrGLGpu*>(this->getGpu());
}
bool GrGLRenderTarget::canAttemptStencilAttachment() const {
bool GrGLRenderTarget::canAttemptStencilAttachment(bool useMultisampleFBO) const {
SkASSERT(useMultisampleFBO == (this->numSamples() > 1));
if (this->getGpu()->getContext()->priv().caps()->avoidStencilBuffers()) {
return false;
}

View File

@ -44,17 +44,11 @@ public:
GrGLuint singleSampleFBOID() const { return fSingleSampleFBOID; }
GrGLuint multisampleFBOID() const { return fMultisampleFBOID; }
// If we have a multisample FBO, that is always where the stencil goes. With dynamic MSAA there
// will be a multisample FBO even if numSamples is 1.
bool stencilIsOnMultisampleFBO() const {
return this->numSamples() > 1 || fMultisampleFBOID != 0;
}
GrBackendRenderTarget getBackendRenderTarget() const override;
GrBackendFormat backendFormat() const override;
bool canAttemptStencilAttachment() const override;
bool canAttemptStencilAttachment(bool useMultisampleFBO) const override;
// GrGLRenderTarget overrides dumpMemoryStatistics so it can log its texture and renderbuffer
// components separately.
@ -85,7 +79,7 @@ private:
void setFlags(const GrGLCaps&, const IDs&);
GrGLGpu* getGLGpu() const;
bool completeStencilAttachment() override;
bool completeStencilAttachment(GrAttachment* stencil, bool useMultisampleFBO) override;
size_t onGpuMemorySize() const override;

View File

@ -53,7 +53,7 @@ void GrGLTextureRenderTarget::dumpMemoryStatistics(
#endif
}
bool GrGLTextureRenderTarget::canAttemptStencilAttachment() const {
bool GrGLTextureRenderTarget::canAttemptStencilAttachment(bool useMultisampleFBO) const {
// The RT FBO of GrGLTextureRenderTarget is never created from a
// wrapped FBO, so we only care about the flag.
return !this->getGpu()->getContext()->priv().caps()->avoidStencilBuffers();

View File

@ -31,7 +31,7 @@ public:
const GrGLRenderTarget::IDs&,
GrMipmapStatus);
bool canAttemptStencilAttachment() const override;
bool canAttemptStencilAttachment(bool useMultisampleFBO) const override;
void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;

View File

@ -210,12 +210,12 @@ sk_sp<GrGpuBuffer> GrMockGpu::onCreateBuffer(size_t sizeInBytes, GrGpuBufferType
return sk_sp<GrGpuBuffer>(new GrMockBuffer(this, sizeInBytes, type, accessPattern));
}
sk_sp<GrAttachment> GrMockGpu::makeStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
SkISize dimensions) {
sk_sp<GrAttachment> GrMockGpu::makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
SkISize dimensions, int numStencilSamples) {
fStats.incStencilAttachmentCreates();
return sk_sp<GrAttachment>(
new GrMockAttachment(this, dimensions, GrAttachment::UsageFlags::kStencilAttachment,
rt->numSamples()));
numStencilSamples));
}
GrBackendTexture GrMockGpu::onCreateBackendTexture(SkISize dimensions,

View File

@ -143,8 +143,8 @@ private:
return true;
}
sk_sp<GrAttachment> makeStencilAttachmentForRenderTarget(const GrRenderTarget*,
SkISize dimensions) override;
sk_sp<GrAttachment> makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
SkISize dimensions, int numStencilSamples) override;
GrBackendFormat getPreferredStencilFormat(const GrBackendFormat&) override {
return GrBackendFormat::MakeMock(GrColorType::kUnknown, SkImage::CompressionType::kNone,

View File

@ -100,8 +100,15 @@ public:
this->registerWithCacheWrapped(GrWrapCacheable::kNo);
}
bool canAttemptStencilAttachment() const override { return true; }
bool completeStencilAttachment() override { return true; }
bool canAttemptStencilAttachment(bool useMSAASurface) const override {
SkASSERT(useMSAASurface == (this->numSamples() > 1));
return true;
}
bool completeStencilAttachment(GrAttachment*, bool useMSAASurface) override {
SkASSERT(useMSAASurface == (this->numSamples() > 1));
return true;
}
size_t onGpuMemorySize() const override {
int numColorSamples = this->numSamples();

View File

@ -233,8 +233,8 @@ private:
GrColorType dstColorType, id<MTLBuffer> transferBuffer, size_t offset,
size_t imageBytes, size_t rowBytes);
sk_sp<GrAttachment> makeStencilAttachmentForRenderTarget(
const GrRenderTarget*, SkISize dimensions) override;
sk_sp<GrAttachment> makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
SkISize dimensions, int numStencilSamples) override;
GrBackendFormat getPreferredStencilFormat(const GrBackendFormat&) override {
return GrBackendFormat::MakeMtl(this->mtlCaps().preferredStencilFormat());

View File

@ -532,17 +532,12 @@ bool GrMtlGpu::clearTexture(GrMtlTexture* tex, size_t bpp, uint32_t levelMask) {
return true;
}
sk_sp<GrAttachment> GrMtlGpu::makeStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
SkISize dimensions) {
SkASSERT(dimensions.width() >= rt->width());
SkASSERT(dimensions.height() >= rt->height());
int samples = rt->numSamples();
sk_sp<GrAttachment> GrMtlGpu::makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
SkISize dimensions, int numStencilSamples) {
MTLPixelFormat sFmt = this->mtlCaps().preferredStencilFormat();
fStats.incStencilAttachmentCreates();
return GrMtlAttachment::GrMtlAttachment::MakeStencil(this, dimensions, samples, sFmt);
return GrMtlAttachment::GrMtlAttachment::MakeStencil(this, dimensions, numStencilSamples, sFmt);
}
sk_sp<GrTexture> GrMtlGpu::onCreateTexture(SkISize dimensions,

View File

@ -77,7 +77,7 @@ void GrMtlPipelineState::setData(const GrRenderTarget* renderTarget,
#ifdef SK_DEBUG
if (programInfo.isStencilEnabled()) {
SkASSERT(renderTarget->getStencilAttachment());
SkASSERT(renderTarget->numStencilBits() == 8);
SkASSERT(renderTarget->numStencilBits(renderTarget->numSamples() > 1) == 8);
}
#endif

View File

@ -28,7 +28,8 @@ public:
~GrMtlRenderTarget() override;
bool canAttemptStencilAttachment() const override {
bool canAttemptStencilAttachment(bool useMSAASurface) const override {
SkASSERT(useMSAASurface == (this->numSamples() > 1));
return true;
}
@ -80,7 +81,7 @@ private:
Wrapped);
GrMtlRenderTarget(GrMtlGpu* gpu, SkISize, id<MTLTexture> colorTexture, Wrapped);
bool completeStencilAttachment() override;
bool completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) override;
using INHERITED = GrRenderTarget;
};

View File

@ -145,7 +145,8 @@ void GrMtlRenderTarget::onRelease() {
INHERITED::onRelease();
}
bool GrMtlRenderTarget::completeStencilAttachment() {
bool GrMtlRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) {
SkASSERT(useMSAASurface == (this->numSamples() > 1));
return true;
}

View File

@ -1342,7 +1342,7 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTa
// We don't allow the client to supply a premade stencil buffer. We always create one if needed.
SkASSERT(!backendRT.stencilBits());
if (tgt) {
SkASSERT(tgt->canAttemptStencilAttachment());
SkASSERT(tgt->canAttemptStencilAttachment(tgt->numSamples() > 1));
}
return std::move(tgt);
@ -1468,15 +1468,12 @@ bool GrVkGpu::onRegenerateMipMapLevels(GrTexture* tex) {
////////////////////////////////////////////////////////////////////////////////
sk_sp<GrAttachment> GrVkGpu::makeStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
SkISize dimensions) {
SkASSERT(dimensions.width() >= rt->width());
SkASSERT(dimensions.height() >= rt->height());
sk_sp<GrAttachment> GrVkGpu::makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
SkISize dimensions, int numStencilSamples) {
VkFormat sFmt = this->vkCaps().preferredStencilFormat();
fStats.incStencilAttachmentCreates();
return GrVkAttachment::MakeStencil(this, dimensions, rt->numSamples(), sFmt);
return GrVkAttachment::MakeStencil(this, dimensions, numStencilSamples, sFmt);
}
sk_sp<GrAttachment> GrVkGpu::makeMSAAAttachment(SkISize dimensions,

View File

@ -108,8 +108,8 @@ public:
}
#endif
sk_sp<GrAttachment> makeStencilAttachmentForRenderTarget(const GrRenderTarget*,
SkISize dimensions) override;
sk_sp<GrAttachment> makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
SkISize dimensions, int numStencilSamples) override;
GrBackendFormat getPreferredStencilFormat(const GrBackendFormat&) override {
return GrBackendFormat::MakeVk(this->vkCaps().preferredStencilFormat());

View File

@ -78,7 +78,7 @@ GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::findOrCreatePipelin
#ifdef SK_DEBUG
if (programInfo.isStencilEnabled()) {
SkASSERT(renderTarget->getStencilAttachment());
SkASSERT(renderTarget->numStencilBits() == 8);
SkASSERT(renderTarget->numStencilBits(renderTarget->numSamples() > 1) == 8);
SkASSERT(renderTarget->getStencilAttachment()->numSamples() == programInfo.numSamples());
}
#endif

View File

@ -227,8 +227,9 @@ GrVkAttachment* GrVkRenderTarget::msaaAttachment() {
: this->colorAttachment();
}
bool GrVkRenderTarget::completeStencilAttachment() {
bool GrVkRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
SkASSERT(useMSAASurface == (this->numSamples() > 1));
return true;
}

View File

@ -100,7 +100,8 @@ public:
bool wrapsSecondaryCommandBuffer() const { return SkToBool(fExternalFramebuffer); }
sk_sp<GrVkFramebuffer> externalFramebuffer() const;
bool canAttemptStencilAttachment() const override {
bool canAttemptStencilAttachment(bool useMSAASurface) const override {
SkASSERT(useMSAASurface == (this->numSamples() > 1));
// We don't know the status of the stencil attachment for wrapped external secondary command
// buffers so we just assume we don't have one.
return !this->wrapsSecondaryCommandBuffer();
@ -168,7 +169,7 @@ private:
SelfDependencyFlags selfDepFlags,
LoadFromResolve);
bool completeStencilAttachment() override;
bool completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) override;
// In Vulkan we call the release proc after we are finished with the underlying
// GrVkImage::Resource object (which occurs after the GPU has finished all work on it).

View File

@ -96,7 +96,7 @@ static sk_sp<GrRenderTarget> create_RT_with_SB(GrResourceProvider* provider,
return nullptr;
}
if (!provider->attachStencilAttachment(tex->asRenderTarget())) {
if (!provider->attachStencilAttachment(tex->asRenderTarget(), sampleCount > 1)) {
return nullptr;
}
SkASSERT(get_SB(tex->asRenderTarget()));

View File

@ -1007,7 +1007,8 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceAttachStencil_Gpu, reporter, ctxInf
// our surface functions.
auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(surface->getCanvas());
GrRenderTarget* rt = sdc->accessRenderTarget();
REPORTER_ASSERT(reporter, resourceProvider->attachStencilAttachment(rt));
REPORTER_ASSERT(reporter,
resourceProvider->attachStencilAttachment(rt, rt->numSamples() > 1));
}
}
}