Add explicit clear of stencil buffer before opLists that use them

Change-Id: I9e2468e1331c6593dbc6da3ad510f08d1c589e8d
Reviewed-on: https://skia-review.googlesource.com/32041
Commit-Queue: Stan Iliev <stani@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Robert Phillips 2017-08-08 18:00:03 -04:00 committed by Skia Commit-Bot
parent 8d8b016f52
commit 952144753d
19 changed files with 159 additions and 64 deletions

View File

@ -371,8 +371,9 @@ public:
// awkward workaround that goes away after MDB is complete and the render target is known from
// the GrRenderTargetOpList.
virtual GrGpuCommandBuffer* createCommandBuffer(
const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) = 0;
GrRenderTarget*, GrSurfaceOrigin,
const GrGpuCommandBuffer::LoadAndStoreInfo&,
const GrGpuCommandBuffer::StencilLoadAndStoreInfo&) = 0;
// Called by GrDrawingManager when flushing.
// Provides a hook for post-flush actions (e.g. Vulkan command buffer submits). This will also
@ -479,7 +480,7 @@ public:
int width,
int height) = 0;
// clears target's entire stencil buffer to 0
virtual void clearStencil(GrRenderTarget* target) = 0;
virtual void clearStencil(GrRenderTarget* target, int clearValue) = 0;
// Determines whether a texture will need to be rescaled in order to be used with the
// GrSamplerParams. This variation is called when the caller will create a new texture using the

View File

@ -53,9 +53,17 @@ public:
GrColor fClearColor;
};
// Load-time clears of the stencil buffer are always to 0 so we don't store
// an 'fStencilClearValue'
struct StencilLoadAndStoreInfo {
LoadOp fLoadOp;
StoreOp fStoreOp;
};
GrGpuCommandBuffer() {}
virtual ~GrGpuCommandBuffer() {}
virtual void begin() = 0;
// Signals the end of recording to the command buffer and that it can now be submitted.
virtual void end() = 0;

View File

@ -82,6 +82,9 @@ public:
int32_t uniqueID() const { return fUniqueID; }
void setRequiresStencil() { this->setFlag(kClearStencilBuffer_Flag); }
bool requiresStencil() { return this->isSetFlag(kClearStencilBuffer_Flag); }
/*
* Dump out the GrOpList dependency DAG
*/
@ -104,6 +107,8 @@ private:
kWasOutput_Flag = 0x02, //!< Flag for topological sorting
kTempMark_Flag = 0x04, //!< Flag for topological sorting
kClearStencilBuffer_Flag = 0x08 //!< Clear the SB before executing the ops
};
void setFlag(uint32_t flag) {

View File

@ -1761,6 +1761,8 @@ uint32_t GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<Gr
if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
appliedClip.hasStencilClip()) {
this->getOpList()->setRequiresStencil();
// This forces instantiation of the render target.
GrRenderTarget* rt = this->accessRenderTarget();
if (!rt) {

View File

@ -84,16 +84,30 @@ void GrRenderTargetOpList::prepareOps(GrOpFlushState* flushState) {
}
}
static std::unique_ptr<GrGpuCommandBuffer> create_command_buffer(GrGpu* gpu) {
static std::unique_ptr<GrGpuCommandBuffer> create_command_buffer(GrGpu* gpu,
GrRenderTarget* rt,
GrSurfaceOrigin origin,
bool clearSB) {
static const GrGpuCommandBuffer::LoadAndStoreInfo kBasicLoadStoreInfo {
GrGpuCommandBuffer::LoadOp::kLoad,
GrGpuCommandBuffer::StoreOp::kStore,
GrColor_ILLEGAL
};
// TODO:
// We would like to (at this level) only ever clear & discard. We would need
// to stop splitting up higher level opLists for copyOps to achieve that.
// Note: we would still need SB loads and stores but they would happen at a
// lower level (inside the VK command buffer).
const GrGpuCommandBuffer::StencilLoadAndStoreInfo stencilLoadAndStoreInfo {
clearSB ? GrGpuCommandBuffer::LoadOp::kClear : GrGpuCommandBuffer::LoadOp::kLoad,
GrGpuCommandBuffer::StoreOp::kStore,
};
std::unique_ptr<GrGpuCommandBuffer> buffer(
gpu->createCommandBuffer(kBasicLoadStoreInfo, // Color
kBasicLoadStoreInfo)); // Stencil
gpu->createCommandBuffer(rt, origin,
kBasicLoadStoreInfo, // Color
stencilLoadAndStoreInfo)); // Stencil
return buffer;
}
@ -116,8 +130,13 @@ bool GrRenderTargetOpList::executeOps(GrOpFlushState* flushState) {
SkASSERT(fTarget.get()->priv().peekRenderTarget());
std::unique_ptr<GrGpuCommandBuffer> commandBuffer = create_command_buffer(flushState->gpu());
std::unique_ptr<GrGpuCommandBuffer> commandBuffer = create_command_buffer(
flushState->gpu(),
fTarget.get()->priv().peekRenderTarget(),
fTarget.get()->origin(),
this->requiresStencil());
flushState->setCommandBuffer(commandBuffer.get());
commandBuffer->begin();
// Draw all the generated geometry.
for (int i = 0; i < fRecordedOps.count(); ++i) {
@ -133,8 +152,12 @@ bool GrRenderTargetOpList::executeOps(GrOpFlushState* flushState) {
commandBuffer.reset();
flushState->setCommandBuffer(commandBuffer.get());
} else if (!commandBuffer) {
commandBuffer = create_command_buffer(flushState->gpu());
commandBuffer = create_command_buffer(flushState->gpu(),
fTarget.get()->priv().peekRenderTarget(),
fTarget.get()->origin(),
false);
flushState->setCommandBuffer(commandBuffer.get());
commandBuffer->begin();
}
GrOpFlushState::DrawOpArgs opArgs {

View File

@ -450,7 +450,6 @@ GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget*
height = SkNextPow2(height);
}
#endif
bool newStencil = false;
GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height,
rt->numStencilSamples(), &sbKey);
GrStencilAttachment* stencil = static_cast<GrStencilAttachment*>(
@ -460,21 +459,14 @@ GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget*
stencil = this->gpu()->createStencilAttachmentForRenderTarget(rt, width, height);
if (stencil) {
this->assignUniqueKeyToResource(sbKey, stencil);
newStencil = true;
}
}
if (rt->renderTargetPriv().attachStencilAttachment(stencil)) {
if (newStencil) {
// Right now we're clearing the stencil attachment here after it is
// attached to a RT for the first time. When we start matching
// stencil buffers with smaller color targets this will no longer
// be correct because it won't be guaranteed to clear the entire
// sb.
// We used to clear down in the GL subclass using a special purpose
// FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported
// FBO status.
this->gpu()->clearStencil(rt);
}
#ifdef SK_DEBUG
// Fill the SB with an inappropriate value. opLists that use the
// SB should clear it properly.
this->gpu()->clearStencil(rt, 0xFFFF);
#endif
}
}
return rt->renderTargetPriv().getStencilAttachment();

View File

@ -2004,8 +2004,8 @@ void GrGLGpu::clear(const GrFixedClip& clip, GrColor color, GrRenderTarget* targ
GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
}
void GrGLGpu::clearStencil(GrRenderTarget* target) {
if (nullptr == target) {
void GrGLGpu::clearStencil(GrRenderTarget* target, int clearValue) {
if (!target) {
return;
}
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
@ -2015,7 +2015,7 @@ void GrGLGpu::clearStencil(GrRenderTarget* target) {
this->disableWindowRectangles();
GL_CALL(StencilMask(0xffffffff));
GL_CALL(ClearStencil(0));
GL_CALL(ClearStencil(clearValue));
GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
fHWStencilSettings.invalidate();
}
@ -2448,9 +2448,10 @@ bool GrGLGpu::onReadPixels(GrSurface* surface,
}
GrGpuCommandBuffer* GrGLGpu::createCommandBuffer(
const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) {
return new GrGLGpuCommandBuffer(this);
GrRenderTarget* rt, GrSurfaceOrigin,
const GrGpuCommandBuffer::LoadAndStoreInfo&,
const GrGpuCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) {
return new GrGLGpuCommandBuffer(this, rt, stencilInfo);
}
void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bounds, bool disableSRGB) {

View File

@ -142,11 +142,12 @@ public:
return &this->glContext();
}
void clearStencil(GrRenderTarget*) override;
void clearStencil(GrRenderTarget*, int clearValue) override;
GrGpuCommandBuffer* createCommandBuffer(
const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) override;
GrRenderTarget*, GrSurfaceOrigin,
const GrGpuCommandBuffer::LoadAndStoreInfo&,
const GrGpuCommandBuffer::StencilLoadAndStoreInfo&) override;
void invalidateBoundRenderTarget() {
fHWBoundRenderTargetUniqueID.makeInvalid();

View File

@ -24,10 +24,20 @@ class GrGLGpuCommandBuffer : public GrGpuCommandBuffer {
* pass through functions to corresponding calls in the GrGLGpu class.
*/
public:
GrGLGpuCommandBuffer(GrGLGpu* gpu) : fGpu(gpu), fRenderTarget(nullptr) {}
GrGLGpuCommandBuffer(GrGLGpu* gpu, GrRenderTarget* rt,
const GrGpuCommandBuffer::StencilLoadAndStoreInfo& stencilInfo)
: fGpu(gpu)
, fRenderTarget(static_cast<GrGLRenderTarget*>(rt)) {
fClearSB = LoadOp::kClear == stencilInfo.fLoadOp;
}
~GrGLGpuCommandBuffer() override {}
void begin() override {
if (fClearSB) {
fGpu->clearStencil(fRenderTarget, 0x0);
}
}
void end() override {}
void discard(GrRenderTargetProxy* proxy) override {
@ -94,6 +104,7 @@ private:
GrGLGpu* fGpu;
GrGLRenderTarget* fRenderTarget;
bool fClearSB;
typedef GrGpuCommandBuffer INHERITED;
};

View File

@ -39,8 +39,10 @@ GrGpu* GrMockGpu::Create(const GrMockOptions* mockOptions, const GrContextOption
}
GrGpuCommandBuffer* GrMockGpu::createCommandBuffer(const GrGpuCommandBuffer::LoadAndStoreInfo&,
const GrGpuCommandBuffer::LoadAndStoreInfo&) {
GrGpuCommandBuffer* GrMockGpu::createCommandBuffer(
GrRenderTarget*, GrSurfaceOrigin,
const GrGpuCommandBuffer::LoadAndStoreInfo&,
const GrGpuCommandBuffer::StencilLoadAndStoreInfo&) {
return new GrMockGpuCommandBuffer(this);
}

View File

@ -43,8 +43,10 @@ public:
*effectiveSampleCnt = rt->numStencilSamples();
}
GrGpuCommandBuffer* createCommandBuffer(const GrGpuCommandBuffer::LoadAndStoreInfo&,
const GrGpuCommandBuffer::LoadAndStoreInfo&) override;
GrGpuCommandBuffer* createCommandBuffer(
GrRenderTarget*, GrSurfaceOrigin,
const GrGpuCommandBuffer::LoadAndStoreInfo&,
const GrGpuCommandBuffer::StencilLoadAndStoreInfo&) override;
GrFence SK_WARN_UNUSED_RESULT insertFence() override { return 0; }
bool waitFence(GrFence, uint64_t) override { return true; }
@ -129,7 +131,7 @@ private:
GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*,
int width,
int height) override;
void clearStencil(GrRenderTarget* target) override {}
void clearStencil(GrRenderTarget*, int clearValue) override {}
GrBackendObject createTestingOnlyBackendTexture(void* pixels, int w, int h, GrPixelConfig,
bool isRT) override;

View File

@ -20,6 +20,7 @@ public:
GrRenderTargetProxy*) override {}
void discard(GrRenderTargetProxy*) override {}
void insertEventMarker(GrRenderTargetProxy*, const char*) override {}
void begin() override {}
void end() override {}
int numDraws() const { return fNumDraws; }

View File

@ -47,8 +47,10 @@ public:
void onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
int* effectiveSampleCnt, SamplePattern*) override {}
GrGpuCommandBuffer* createCommandBuffer(const GrGpuCommandBuffer::LoadAndStoreInfo&,
const GrGpuCommandBuffer::LoadAndStoreInfo&) override {
GrGpuCommandBuffer* createCommandBuffer(
GrRenderTarget*, GrSurfaceOrigin,
const GrGpuCommandBuffer::LoadAndStoreInfo&,
const GrGpuCommandBuffer::StencilLoadAndStoreInfo&) override {
return nullptr;
}
@ -138,7 +140,7 @@ private:
return nullptr;
}
void clearStencil(GrRenderTarget* target) override {}
void clearStencil(GrRenderTarget* target, int clearValue) override {}
GrBackendObject createTestingOnlyBackendTexture(void* pixels, int w, int h,
GrPixelConfig config, bool isRT) override {

View File

@ -384,7 +384,7 @@ void GrVkPrimaryCommandBuffer::end(const GrVkGpu* gpu) {
void GrVkPrimaryCommandBuffer::beginRenderPass(const GrVkGpu* gpu,
const GrVkRenderPass* renderPass,
const VkClearValue* clearValues,
const VkClearValue clearValues[],
const GrVkRenderTarget& target,
const SkIRect& bounds,
bool forSecondaryCB) {
@ -403,7 +403,15 @@ void GrVkPrimaryCommandBuffer::beginRenderPass(const GrVkGpu* gpu,
beginInfo.renderPass = renderPass->vkRenderPass();
beginInfo.framebuffer = target.framebuffer()->framebuffer();
beginInfo.renderArea = renderArea;
beginInfo.clearValueCount = renderPass->clearValueCount();
// TODO: have clearValueCount return the index of the last attachment that
// requires a clear instead of the number of total clears.
uint32_t stencilIndex;
if (renderPass->stencilAttachmentIndex(&stencilIndex)) {
beginInfo.clearValueCount = renderPass->clearValueCount() ? 2 : 0;
} else {
beginInfo.clearValueCount = renderPass->clearValueCount();
}
beginInfo.pClearValues = clearValues;
VkSubpassContents contents = forSecondaryCB ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS

View File

@ -185,7 +185,7 @@ public:
// in the render pass.
void beginRenderPass(const GrVkGpu* gpu,
const GrVkRenderPass* renderPass,
const VkClearValue* clearValues,
const VkClearValue clearValues[],
const GrVkRenderTarget& target,
const SkIRect& bounds,
bool forSecondaryCB);

View File

@ -258,9 +258,10 @@ void GrVkGpu::disconnect(DisconnectType type) {
///////////////////////////////////////////////////////////////////////////////
GrGpuCommandBuffer* GrVkGpu::createCommandBuffer(
GrRenderTarget* rt, GrSurfaceOrigin origin,
const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) {
return new GrVkGpuCommandBuffer(this, colorInfo, stencilInfo);
const GrGpuCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) {
return new GrVkGpuCommandBuffer(this, rt, origin, colorInfo, stencilInfo);
}
void GrVkGpu::submitCommandBuffer(SyncQueue sync) {
@ -1474,8 +1475,8 @@ void GrVkGpu::onFinishFlush(bool insertedSemaphore) {
this->submitCommandBuffer(kSkip_SyncQueue);
}
void GrVkGpu::clearStencil(GrRenderTarget* target) {
if (nullptr == target) {
void GrVkGpu::clearStencil(GrRenderTarget* target, int clearValue) {
if (!target) {
return;
}
GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment();
@ -1483,7 +1484,8 @@ void GrVkGpu::clearStencil(GrRenderTarget* target) {
VkClearDepthStencilValue vkStencilColor;
memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
vkStencilColor.depth = 0.0f;
vkStencilColor.stencil = clearValue;
vkStencil->setImageLayout(this,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
@ -1971,6 +1973,7 @@ void adjust_bounds_to_granularity(SkIRect* dstBounds, const SkIRect& srcBounds,
void GrVkGpu::submitSecondaryCommandBuffer(const SkTArray<GrVkSecondaryCommandBuffer*>& buffers,
const GrVkRenderPass* renderPass,
const VkClearValue* colorClear,
const VkClearValue* stencilClear,
GrVkRenderTarget* target,
const SkIRect& bounds) {
const SkIRect* pBounds = &bounds;
@ -1993,7 +1996,20 @@ void GrVkGpu::submitSecondaryCommandBuffer(const SkTArray<GrVkSecondaryCommandBu
pBounds = &adjustedBounds;
}
fCurrentCmdBuffer->beginRenderPass(this, renderPass, colorClear, *target, *pBounds, true);
#ifdef SK_DEBUG
uint32_t index;
bool result = renderPass->colorAttachmentIndex(&index);
SkASSERT(result && 0 == index);
result = renderPass->stencilAttachmentIndex(&index);
if (result) {
SkASSERT(1 == index);
}
#endif
VkClearValue clears[2];
clears[0].color = colorClear->color;
clears[1].depthStencil = stencilClear->depthStencil;
fCurrentCmdBuffer->beginRenderPass(this, renderPass, clears, *target, *pBounds, true);
for (int i = 0; i < buffers.count(); ++i) {
fCurrentCmdBuffer->executeCommands(this, buffers[i]);
}

View File

@ -94,11 +94,12 @@ public:
int width,
int height) override;
void clearStencil(GrRenderTarget* target) override;
void clearStencil(GrRenderTarget* target, int clearValue) override;
GrGpuCommandBuffer* createCommandBuffer(
const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) override;
GrRenderTarget*, GrSurfaceOrigin,
const GrGpuCommandBuffer::LoadAndStoreInfo&,
const GrGpuCommandBuffer::StencilLoadAndStoreInfo&) override;
void addMemoryBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
@ -123,7 +124,7 @@ public:
void submitSecondaryCommandBuffer(const SkTArray<GrVkSecondaryCommandBuffer*>&,
const GrVkRenderPass*,
const VkClearValue*,
const VkClearValue*, const VkClearValue*,
GrVkRenderTarget*,
const SkIRect& bounds);

View File

@ -22,9 +22,10 @@
#include "GrVkTexture.h"
#include "SkRect.h"
void get_vk_load_store_ops(const GrGpuCommandBuffer::LoadAndStoreInfo& info,
void get_vk_load_store_ops(GrGpuCommandBuffer::LoadOp loadOpIn,
GrGpuCommandBuffer::StoreOp storeOpIn,
VkAttachmentLoadOp* loadOp, VkAttachmentStoreOp* storeOp) {
switch (info.fLoadOp) {
switch (loadOpIn) {
case GrGpuCommandBuffer::LoadOp::kLoad:
*loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
break;
@ -39,7 +40,7 @@ void get_vk_load_store_ops(const GrGpuCommandBuffer::LoadAndStoreInfo& info,
*loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
}
switch (info.fStoreOp) {
switch (storeOpIn) {
case GrGpuCommandBuffer::StoreOp::kStore:
*storeOp = VK_ATTACHMENT_STORE_OP_STORE;
break;
@ -53,19 +54,22 @@ void get_vk_load_store_ops(const GrGpuCommandBuffer::LoadAndStoreInfo& info,
}
GrVkGpuCommandBuffer::GrVkGpuCommandBuffer(GrVkGpu* gpu,
GrRenderTarget* rt, GrSurfaceOrigin origin,
const LoadAndStoreInfo& colorInfo,
const LoadAndStoreInfo& stencilInfo)
const StencilLoadAndStoreInfo& stencilInfo)
: fGpu(gpu)
, fRenderTarget(nullptr)
, fOrigin(kTopLeft_GrSurfaceOrigin)
, fClearColor(GrColor4f::FromGrColor(colorInfo.fClearColor))
, fLastPipelineState(nullptr) {
get_vk_load_store_ops(colorInfo.fLoadOp, colorInfo.fStoreOp,
&fVkColorLoadOp, &fVkColorStoreOp);
get_vk_load_store_ops(colorInfo, &fVkColorLoadOp, &fVkColorStoreOp);
get_vk_load_store_ops(stencilInfo, &fVkStencilLoadOp, &fVkStencilStoreOp);
get_vk_load_store_ops(stencilInfo.fLoadOp, stencilInfo.fStoreOp,
&fVkStencilLoadOp, &fVkStencilStoreOp);
fCurrentCmdInfo = -1;
this->init(static_cast<GrVkRenderTarget*>(rt), origin);
}
void GrVkGpuCommandBuffer::init(GrVkRenderTarget* target, GrSurfaceOrigin origin) {
@ -96,6 +100,9 @@ void GrVkGpuCommandBuffer::init(GrVkRenderTarget* target, GrSurfaceOrigin origin
cbInfo.fColorClearValue.color.float32[2] = fClearColor.fRGBA[2];
cbInfo.fColorClearValue.color.float32[3] = fClearColor.fRGBA[3];
cbInfo.fStencilClearValue.depthStencil.depth = 0;
cbInfo.fStencilClearValue.depthStencil.stencil = 0;
cbInfo.fBounds.setEmpty();
cbInfo.fIsEmpty = true;
cbInfo.fStartsWithClear = false;
@ -118,6 +125,13 @@ GrVkGpuCommandBuffer::~GrVkGpuCommandBuffer() {
GrGpu* GrVkGpuCommandBuffer::gpu() { return fGpu; }
GrRenderTarget* GrVkGpuCommandBuffer::renderTarget() { return fRenderTarget; }
void GrVkGpuCommandBuffer::begin() {
// TODO: remove this - see skbug.com/6936
if (VK_ATTACHMENT_LOAD_OP_CLEAR == fVkStencilLoadOp) {
fGpu->clearStencil(fRenderTarget, 0x0);
}
}
void GrVkGpuCommandBuffer::end() {
if (fCurrentCmdInfo >= 0) {
fCommandBufferInfos[fCurrentCmdInfo].currentCmdBuf()->end(fGpu);
@ -178,7 +192,9 @@ void GrVkGpuCommandBuffer::onSubmit() {
cbInfo.fBounds.roundOut(&iBounds);
fGpu->submitSecondaryCommandBuffer(cbInfo.fCommandBuffers, cbInfo.fRenderPass,
&cbInfo.fColorClearValue, fRenderTarget, iBounds);
&cbInfo.fColorClearValue,
&cbInfo.fStencilClearValue,
fRenderTarget, iBounds);
}
}
}
@ -410,6 +426,7 @@ void GrVkGpuCommandBuffer::addAdditionalRenderPass() {
// It shouldn't matter what we set the clear color to here since we will assume loading of the
// attachment.
memset(&cbInfo.fColorClearValue, 0, sizeof(VkClearValue));
memset(&cbInfo.fStencilClearValue, 0, sizeof(VkClearValue));
cbInfo.fBounds.setEmpty();
cbInfo.fIsEmpty = true;
cbInfo.fStartsWithClear = false;

View File

@ -23,12 +23,13 @@ class GrVkSecondaryCommandBuffer;
class GrVkGpuCommandBuffer : public GrGpuCommandBuffer, private GrMesh::SendToGpuImpl {
public:
GrVkGpuCommandBuffer(GrVkGpu* gpu,
const LoadAndStoreInfo& colorInfo,
const LoadAndStoreInfo& stencilInfo);
GrVkGpuCommandBuffer(GrVkGpu*, GrRenderTarget*, GrSurfaceOrigin,
const LoadAndStoreInfo&,
const StencilLoadAndStoreInfo&);
~GrVkGpuCommandBuffer() override;
void begin() override;
void end() override;
void discard(GrRenderTargetProxy*) override;
@ -111,6 +112,7 @@ private:
const GrVkRenderPass* fRenderPass;
SkTArray<GrVkSecondaryCommandBuffer*> fCommandBuffers;
VkClearValue fColorClearValue;
VkClearValue fStencilClearValue;
SkRect fBounds;
bool fIsEmpty;
bool fStartsWithClear;