Support making a VkRenderPasses with self dependencies.

The self dependencies allow us to use xfer barriers for advanced blends.
If we don't have the advanced blend extension the self dependency render
passes will also have an input attachment on them which can be used to
read the dst value in the shader.

Also has some renaming of previously plumbed values to better match what
we are doing.

Bug: skia:10409
Change-Id: I3b343064627921b8dc3debeeb6869b0f4b2dcc42
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/310337
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Greg Daniel 2020-08-14 13:11:18 -04:00 committed by Skia Commit-Bot
parent 8b07b9f55a
commit ed629c191d
12 changed files with 206 additions and 152 deletions

View File

@ -371,6 +371,8 @@ void GrVkCaps::init(const GrContextOptions& contextOptions, const GrVkInterface*
fShouldAlwaysUseDedicatedImageMemory = true;
}
fMaxInputAttachmentDescriptors = properties.limits.maxDescriptorSetInputAttachments;
this->initGrCaps(vkInterface, physDev, properties, memoryProperties, features, extensions);
this->initShaderCaps(properties, features);
@ -1707,14 +1709,14 @@ GrProgramDesc GrVkCaps::makeDesc(GrRenderTarget* rt, const GrProgramInfo& progra
// GrVkPipelineStateBuilder.cpp).
b.add32(GrVkGpu::kShader_PersistentCacheKeyType);
bool willReadDst = false; // TODO: get this from GrProgramInfo
bool usesXferBarrier = false; // TODO: get this from GrProgramInfo
if (rt) {
GrVkRenderTarget* vkRT = (GrVkRenderTarget*) rt;
bool needsStencil = programInfo.numStencilSamples() || programInfo.isStencilEnabled();
// TODO: support failure in getSimpleRenderPass
const GrVkRenderPass* rp = vkRT->getSimpleRenderPass(needsStencil, willReadDst);
const GrVkRenderPass* rp = vkRT->getSimpleRenderPass(needsStencil, usesXferBarrier);
SkASSERT(rp);
rp->genKey(&b);
@ -1727,7 +1729,7 @@ GrProgramDesc GrVkCaps::makeDesc(GrRenderTarget* rt, const GrProgramInfo& progra
GrVkRenderTarget::ReconstructAttachmentsDescriptor(*this, programInfo,
&attachmentsDescriptor,
&attachmentFlags);
SkASSERT(rp->isCompatible(attachmentsDescriptor, attachmentFlags, willReadDst));
SkASSERT(rp->isCompatible(attachmentsDescriptor, attachmentFlags, usesXferBarrier));
}
#endif
} else {
@ -1740,7 +1742,7 @@ GrProgramDesc GrVkCaps::makeDesc(GrRenderTarget* rt, const GrProgramInfo& progra
// kExternal_AttachmentFlag is only set for wrapped secondary command buffers - which
// will always go through the above 'rt' path (i.e., we can always pass 0 as the final
// parameter to GenKey).
GrVkRenderPass::GenKey(&b, attachmentFlags, attachmentsDescriptor, willReadDst, 0);
GrVkRenderPass::GenKey(&b, attachmentFlags, attachmentsDescriptor, usesXferBarrier, 0);
}
GrStencilSettings stencil = programInfo.nonGLStencilSettings();

View File

@ -160,6 +160,8 @@ public:
return fMaxPerPoolCachedSecondaryCommandBuffers;
}
uint32_t maxInputAttachmentDescriptors() const { return fMaxInputAttachmentDescriptors; }
bool mustInvalidatePrimaryCmdBufferStateAfterClearAttachments() const {
return fMustInvalidatePrimaryCmdBufferStateAfterClearAttachments;
}
@ -336,6 +338,8 @@ private:
// buffers per primary anyways.
int fMaxPerPoolCachedSecondaryCommandBuffers = 100;
uint32_t fMaxInputAttachmentDescriptors = 0;
typedef GrCaps INHERITED;
};

View File

@ -443,10 +443,10 @@ bool GrVkPrimaryCommandBuffer::beginRenderPass(GrVkGpu* gpu,
bool forSecondaryCB) {
SkASSERT(fIsActive);
SkASSERT(!fActiveRenderPass);
SkASSERT(renderPass->isCompatible(*target, renderPass->hasInputSelfDependency()));
SkASSERT(renderPass->isCompatible(*target, renderPass->hasSelfDependency()));
const GrVkFramebuffer* framebuffer = target->getFramebuffer(
renderPass->hasStencilAttachment(), renderPass->hasInputSelfDependency());
renderPass->hasStencilAttachment(), renderPass->hasSelfDependency());
if (!framebuffer) {
return false;
}
@ -474,7 +474,7 @@ bool GrVkPrimaryCommandBuffer::beginRenderPass(GrVkGpu* gpu,
fActiveRenderPass = renderPass;
this->addResource(renderPass);
target->addResources(*this, renderPass->hasStencilAttachment(),
renderPass->hasInputSelfDependency());
renderPass->hasSelfDependency());
return true;
}

View File

@ -322,10 +322,10 @@ GrOpsRenderPass* GrVkGpu::getOpsRenderPass(
fCachedOpsRenderPass = std::make_unique<GrVkOpsRenderPass>(this);
}
bool willReadDst = false; // TODO: we should be passing this value
bool usesXferBarrier = false; // TODO: we should be passing this value
if (!fCachedOpsRenderPass->set(rt, stencil, origin, bounds,
colorInfo, stencilInfo, sampledProxies, willReadDst)) {
if (!fCachedOpsRenderPass->set(rt, stencil, origin, bounds, colorInfo, stencilInfo,
sampledProxies, usesXferBarrier)) {
return nullptr;
}
return fCachedOpsRenderPass.get();

View File

@ -105,7 +105,7 @@ bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
}
const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
vkRT->compatibleRenderPassHandle(withStencil, fWillReadDst);
vkRT->compatibleRenderPassHandle(withStencil, fUsesXferBarriers);
if (rpHandle.isValid()) {
fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
vkColorOps,
@ -116,7 +116,7 @@ bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
vkStencilOps,
nullptr,
withStencil,
fWillReadDst);
fUsesXferBarriers);
}
if (!fCurrentRenderPass) {
return false;
@ -135,8 +135,8 @@ bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
fCurrentRenderPass = nullptr;
return false;
}
fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(withStencil, fWillReadDst),
fCurrentRenderPass);
fCurrentSecondaryCommandBuffer->begin(
fGpu, vkRT->getFramebuffer(withStencil, fUsesXferBarriers), fCurrentRenderPass);
}
if (!fGpu->beginRenderPass(fCurrentRenderPass, &vkClearColor, vkRT, fOrigin, fBounds,
@ -212,7 +212,7 @@ bool GrVkOpsRenderPass::set(GrRenderTarget* rt, GrStencilAttachment* stencil,
const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies,
bool willReadDst) {
bool usesXferBarrier) {
SkASSERT(!fRenderTarget);
SkASSERT(fGpu == rt->getContext()->priv().getGpu());
@ -243,7 +243,7 @@ bool GrVkOpsRenderPass::set(GrRenderTarget* rt, GrStencilAttachment* stencil,
SkASSERT(bounds.isEmpty() || SkIRect::MakeWH(rt->width(), rt->height()).contains(bounds));
fBounds = bounds;
fWillReadDst = willReadDst;
fUsesXferBarriers = usesXferBarrier;
if (this->wrapsSecondaryCommandBuffer()) {
return this->initWrapped();
@ -392,7 +392,7 @@ void GrVkOpsRenderPass::addAdditionalRenderPass(bool mustUseSecondaryCommandBuff
bool withStencil = fCurrentRenderPass->hasStencilAttachment();
const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
vkRT->compatibleRenderPassHandle(withStencil, fWillReadDst);
vkRT->compatibleRenderPassHandle(withStencil, fUsesXferBarriers);
SkASSERT(fCurrentRenderPass);
fCurrentRenderPass->unref();
if (rpHandle.isValid()) {
@ -405,7 +405,7 @@ void GrVkOpsRenderPass::addAdditionalRenderPass(bool mustUseSecondaryCommandBuff
vkStencilOps,
nullptr,
withStencil,
fWillReadDst);
fUsesXferBarriers);
}
if (!fCurrentRenderPass) {
return;
@ -422,8 +422,8 @@ void GrVkOpsRenderPass::addAdditionalRenderPass(bool mustUseSecondaryCommandBuff
fCurrentRenderPass = nullptr;
return;
}
fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(withStencil, fWillReadDst),
fCurrentRenderPass);
fCurrentSecondaryCommandBuffer->begin(
fGpu, vkRT->getFramebuffer(withStencil, fUsesXferBarriers), fCurrentRenderPass);
}
// We use the same fBounds as the whole GrVkOpsRenderPass since we have no way of tracking the

View File

@ -36,7 +36,7 @@ public:
const GrOpsRenderPass::LoadAndStoreInfo&,
const GrOpsRenderPass::StencilLoadAndStoreInfo&,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies,
bool willReadDst);
bool usesXferBarrier);
void reset();
void submit();
@ -96,7 +96,7 @@ private:
GrVkPipelineState* fCurrentPipelineState = nullptr;
bool fCurrentCBIsEmpty = true;
SkIRect fBounds;
bool fWillReadDst = false;
bool fUsesXferBarriers = false;
GrVkGpu* fGpu;
#ifdef SK_DEBUG

View File

@ -45,12 +45,12 @@ void setup_vk_attachment_description(VkAttachmentDescription* attachment,
GrVkRenderPass* GrVkRenderPass::CreateSimple(GrVkGpu* gpu,
AttachmentsDescriptor* attachmentsDescriptor,
AttachmentFlags attachmentFlags,
bool needsInputSelfDependency) {
bool needsSelfDependency) {
static const GrVkRenderPass::LoadStoreOps kBasicLoadStoreOps(VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE);
return Create(gpu, attachmentFlags, attachmentsDescriptor, kBasicLoadStoreOps,
kBasicLoadStoreOps, needsInputSelfDependency);
kBasicLoadStoreOps, needsSelfDependency);
}
GrVkRenderPass* GrVkRenderPass::Create(GrVkGpu* gpu,
@ -59,9 +59,9 @@ GrVkRenderPass* GrVkRenderPass::Create(GrVkGpu* gpu,
const LoadStoreOps& stencilOp) {
AttachmentFlags attachmentFlags = compatibleRenderPass.fAttachmentFlags;
AttachmentsDescriptor attachmentsDescriptor = compatibleRenderPass.fAttachmentsDescriptor;
bool needsInputSelfDependency = compatibleRenderPass.fHasInputSelfDependency;
bool needsSelfDependency = compatibleRenderPass.fHasSelfDependency;
return Create(gpu, attachmentFlags, &attachmentsDescriptor, colorOp, stencilOp,
needsInputSelfDependency);
needsSelfDependency);
}
GrVkRenderPass* GrVkRenderPass::Create(GrVkGpu* gpu,
@ -69,13 +69,13 @@ GrVkRenderPass* GrVkRenderPass::Create(GrVkGpu* gpu,
AttachmentsDescriptor* attachmentsDescriptor,
const LoadStoreOps& colorOp,
const LoadStoreOps& stencilOp,
bool needsInputSelfDependency) {
bool needsSelfDependency) {
// TODO: We need to create a subpass where we have a color attachment ref and an input
// attachment ref. Both refs will point to the same color attachment on the render pass. We also
// need to create a self dependency for that subpass so that we can use barriers. Finally, the
// color attachment will need to be set to the GENERAL layout since it will be used for reading
// and writing here.
SkASSERT(!needsInputSelfDependency);
SkASSERT(!needsSelfDependency);
uint32_t numAttachments = attachmentsDescriptor->fAttachmentCount;
// Attachment descriptions to be set on the render pass
@ -101,27 +101,66 @@ GrVkRenderPass* GrVkRenderPass::Create(GrVkGpu* gpu,
uint32_t clearValueCount = 0;
VkSubpassDependency dependency;
int numDependecies = 0;
if (attachmentFlags & kColor_AttachmentFlag) {
// set up color attachment
bool needsGeneralLayout =
needsSelfDependency && !gpu->caps()->advancedBlendEquationSupport();
VkImageLayout layout = needsGeneralLayout ? VK_IMAGE_LAYOUT_GENERAL
: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachmentsDescriptor->fColor.fLoadStoreOps = colorOp;
setup_vk_attachment_description(&attachments[currentAttachment],
attachmentsDescriptor->fColor,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
layout);
// setup subpass use of attachment
colorRef.attachment = currentAttachment++;
colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
colorRef.layout = layout;
subpassDesc.colorAttachmentCount = 1;
if (needsSelfDependency) {
numDependecies = 1;
dependency.srcSubpass = 0;
dependency.dstSubpass = 0;
dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
if (gpu->caps()->advancedBlendEquationSupport()) {
// If we have coherent support we shouldn't be needing a self dependency
SkASSERT(!gpu->caps()->advancedCoherentBlendEquationSupport());
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.srcAccessMask =
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT;
} else {
SkASSERT(gpu->vkCaps().maxInputAttachmentDescriptors());
subpassDesc.inputAttachmentCount = 1;
subpassDesc.pInputAttachments = &colorRef;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependency.srcAccessMask =
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
dependency.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
}
}
if (VK_ATTACHMENT_LOAD_OP_CLEAR == colorOp.fLoadOp) {
clearValueCount = colorRef.attachment + 1;
}
} else {
// I don't think there should ever be a time where we don't have a color attachment
SkASSERT(false);
SkASSERT(!needsSelfDependency);
colorRef.attachment = VK_ATTACHMENT_UNUSED;
colorRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
subpassDesc.colorAttachmentCount = 0;
}
subpassDesc.pColorAttachments = &colorRef;
if (attachmentFlags & kStencil_AttachmentFlag) {
@ -157,8 +196,8 @@ GrVkRenderPass* GrVkRenderPass::Create(GrVkGpu* gpu,
createInfo.pAttachments = attachments.begin();
createInfo.subpassCount = 1;
createInfo.pSubpasses = &subpassDesc;
createInfo.dependencyCount = 0;
createInfo.pDependencies = nullptr;
createInfo.dependencyCount = numDependecies;
createInfo.pDependencies = &dependency;
VkResult result;
VkRenderPass renderPass;
@ -177,18 +216,18 @@ GrVkRenderPass* GrVkRenderPass::Create(GrVkGpu* gpu,
&granularity));
return new GrVkRenderPass(gpu, renderPass, attachmentFlags, *attachmentsDescriptor,
needsInputSelfDependency, granularity, clearValueCount);
needsSelfDependency, granularity, clearValueCount);
}
GrVkRenderPass::GrVkRenderPass(const GrVkGpu* gpu, VkRenderPass renderPass, AttachmentFlags flags,
const AttachmentsDescriptor& descriptor,
bool hasInputSelfDependency,
bool hasSelfDependency,
const VkExtent2D& granularity, uint32_t clearValueCount)
: INHERITED(gpu)
, fRenderPass(renderPass)
, fAttachmentFlags(flags)
, fAttachmentsDescriptor(descriptor)
, fHasInputSelfDependency(hasInputSelfDependency)
, fHasSelfDependency(hasSelfDependency)
, fGranularity(granularity)
, fClearValueCount(clearValueCount) {
}
@ -223,7 +262,7 @@ bool GrVkRenderPass::stencilAttachmentIndex(uint32_t* index) const {
bool GrVkRenderPass::isCompatible(const AttachmentsDescriptor& desc,
const AttachmentFlags& flags,
bool hasInputSelfDependency) const {
bool hasSelfDependency) const {
SkASSERT(!(fAttachmentFlags & kExternal_AttachmentFlag));
if (flags != fAttachmentFlags) {
return false;
@ -240,7 +279,7 @@ bool GrVkRenderPass::isCompatible(const AttachmentsDescriptor& desc,
}
}
if (fHasInputSelfDependency != hasInputSelfDependency) {
if (fHasSelfDependency != hasSelfDependency) {
return false;
}
@ -248,20 +287,20 @@ bool GrVkRenderPass::isCompatible(const AttachmentsDescriptor& desc,
}
bool GrVkRenderPass::isCompatible(const GrVkRenderTarget& target,
bool hasInputSelfDependency) const {
bool hasSelfDependency) const {
SkASSERT(!(fAttachmentFlags & kExternal_AttachmentFlag));
AttachmentsDescriptor desc;
AttachmentFlags flags;
target.getAttachmentsDescriptor(&desc, &flags, this->hasStencilAttachment());
return this->isCompatible(desc, flags, hasInputSelfDependency);
return this->isCompatible(desc, flags, hasSelfDependency);
}
bool GrVkRenderPass::isCompatible(const GrVkRenderPass& renderPass) const {
SkASSERT(!(fAttachmentFlags & kExternal_AttachmentFlag));
return this->isCompatible(renderPass.fAttachmentsDescriptor, renderPass.fAttachmentFlags,
renderPass.fHasInputSelfDependency);
renderPass.fHasSelfDependency);
}
bool GrVkRenderPass::isCompatibleExternalRP(VkRenderPass renderPass) const {
@ -286,14 +325,14 @@ bool GrVkRenderPass::equalLoadStoreOps(const LoadStoreOps& colorOps,
}
void GrVkRenderPass::genKey(GrProcessorKeyBuilder* b) const {
GenKey(b, fAttachmentFlags, fAttachmentsDescriptor, fHasInputSelfDependency,
GenKey(b, fAttachmentFlags, fAttachmentsDescriptor, fHasSelfDependency,
(uint64_t)fRenderPass);
}
void GrVkRenderPass::GenKey(GrProcessorKeyBuilder* b,
AttachmentFlags attachmentFlags,
const AttachmentsDescriptor& attachmentsDescriptor,
bool hasInputSelfDependency,
bool hasSelfDependency,
uint64_t externalRenderPass) {
b->add32(attachmentFlags);
if (attachmentFlags & kColor_AttachmentFlag) {
@ -305,7 +344,7 @@ void GrVkRenderPass::GenKey(GrProcessorKeyBuilder* b,
b->add32(attachmentsDescriptor.fStencil.fSamples);
}
b->add32(hasInputSelfDependency);
b->add32(hasSelfDependency);
if (attachmentFlags & kExternal_AttachmentFlag) {
SkASSERT(!(attachmentFlags & ~kExternal_AttachmentFlag));

View File

@ -42,7 +42,7 @@ public:
: INHERITED(gpu)
, fRenderPass(renderPass)
, fAttachmentFlags(kExternal_AttachmentFlag)
, fHasInputSelfDependency(false)
, fHasSelfDependency(false)
, fClearValueCount(0)
, fColorAttachmentIndex(colorAttachmentIndex) {}
@ -87,7 +87,7 @@ public:
static GrVkRenderPass* CreateSimple(GrVkGpu*,
AttachmentsDescriptor*,
AttachmentFlags,
bool needsInputSelfDependency);
bool needsSelfDependency);
static GrVkRenderPass* Create(GrVkGpu*,
const GrVkRenderPass& compatibleRenderPass,
const LoadStoreOps& colorOp,
@ -100,7 +100,7 @@ public:
bool stencilAttachmentIndex(uint32_t* index) const;
bool hasStencilAttachment() const { return fAttachmentFlags & kStencil_AttachmentFlag; }
bool hasInputSelfDependency() const { return fHasInputSelfDependency; }
bool hasSelfDependency() const { return fHasSelfDependency; }
// Returns whether or not the structure of a RenderTarget matches that of the VkRenderPass in
// this object. Specifically this compares that the number of attachments, format of
@ -135,7 +135,7 @@ public:
static void GenKey(GrProcessorKeyBuilder*,
AttachmentFlags,
const AttachmentsDescriptor&,
bool hasInputSelfDependency,
bool hasSelfDependency,
uint64_t externalRenderPass);
#ifdef SK_TRACE_MANAGED_RESOURCES
@ -154,14 +154,14 @@ private:
AttachmentsDescriptor*,
const LoadStoreOps& colorOps,
const LoadStoreOps& stencilOps,
bool needsInputSelfDependency);
bool needsSelfDependency);
void freeGPUData() const override;
VkRenderPass fRenderPass;
AttachmentFlags fAttachmentFlags;
AttachmentsDescriptor fAttachmentsDescriptor;
bool fHasInputSelfDependency;
bool fHasSelfDependency;
VkExtent2D fGranularity;
uint32_t fClearValueCount;
// For internally created render passes we assume the color attachment index is always 0.

View File

@ -225,11 +225,12 @@ bool GrVkRenderTarget::completeStencilAttachment() {
return true;
}
const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass(bool withStencil, bool willReadDst) {
const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass(bool withStencil,
bool needsXferBarrier) {
if (withStencil) {
if (willReadDst) {
if (fCachedStencilDstReadRenderPass) {
return fCachedStencilDstReadRenderPass;
if (needsXferBarrier) {
if (fCachedStencilSelfDepRenderPass) {
return fCachedStencilSelfDepRenderPass;
}
} else {
if (fCachedStencilRenderPass) {
@ -237,9 +238,9 @@ const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass(bool withStencil, bo
}
}
} else {
if (willReadDst) {
if (fCachedDstReadRenderPass) {
return fCachedDstReadRenderPass;
if (needsXferBarrier) {
if (fCachedSelfDepRenderPass) {
return fCachedSelfDepRenderPass;
}
} else {
if (fCachedSimpleRenderPass) {
@ -248,45 +249,46 @@ const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass(bool withStencil, bo
}
}
return this->createSimpleRenderPass(withStencil, willReadDst);
return this->createSimpleRenderPass(withStencil, needsXferBarrier);
}
const GrVkRenderPass* GrVkRenderTarget::createSimpleRenderPass(bool withStencil, bool willReadDst) {
const GrVkRenderPass* GrVkRenderTarget::createSimpleRenderPass(bool withStencil,
bool needsXferBarrier) {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
GrVkResourceProvider& rp = this->getVkGpu()->resourceProvider();
if (withStencil) {
if (willReadDst) {
SkASSERT(!fCachedStencilDstReadRenderPass);
fCachedStencilDstReadRenderPass = rp.findCompatibleRenderPass(
*this, &fCompatibleStencilDstReadRPHandle, withStencil, willReadDst);
return fCachedStencilDstReadRenderPass;
if (needsXferBarrier) {
SkASSERT(!fCachedStencilSelfDepRenderPass);
fCachedStencilSelfDepRenderPass = rp.findCompatibleRenderPass(
*this, &fCompatibleStencilSelfDepRPHandle, withStencil, needsXferBarrier);
return fCachedStencilSelfDepRenderPass;
} else {
SkASSERT(!fCachedStencilRenderPass);
fCachedStencilRenderPass = rp.findCompatibleRenderPass(
*this, &fCompatibleStencilRPHandle, withStencil, willReadDst);
*this, &fCompatibleStencilRPHandle, withStencil, needsXferBarrier);
return fCachedStencilRenderPass;
}
} else {
if (willReadDst) {
SkASSERT(!fCachedDstReadRenderPass);
fCachedDstReadRenderPass = rp.findCompatibleRenderPass(
*this, &fCompatibleDstReadRPHandle, withStencil, willReadDst);
return fCachedDstReadRenderPass;
if (needsXferBarrier) {
SkASSERT(!fCachedSelfDepRenderPass);
fCachedSelfDepRenderPass = rp.findCompatibleRenderPass(
*this, &fCompatibleSelfDepRPHandle, withStencil, needsXferBarrier);
return fCachedSelfDepRenderPass;
} else {
SkASSERT(!fCachedSimpleRenderPass);
fCachedSimpleRenderPass = rp.findCompatibleRenderPass(*
this, &fCompatibleRPHandle, withStencil, willReadDst);
fCachedSimpleRenderPass = rp.findCompatibleRenderPass(
*this, &fCompatibleRPHandle, withStencil, needsXferBarrier);
return fCachedSimpleRenderPass;
}
}
}
const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer(bool withStencil, bool willReadDst) {
const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer(bool withStencil, bool needsXferBarrier) {
if (withStencil) {
if (willReadDst) {
if (fCachedStencilDstReadFramebuffer) {
return fCachedStencilDstReadFramebuffer;
if (needsXferBarrier) {
if (fCachedStencilSelfDepFramebuffer) {
return fCachedStencilSelfDepFramebuffer;
}
} else {
if (fCachedStencilFramebuffer) {
@ -294,9 +296,9 @@ const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer(bool withStencil, bool w
}
}
} else {
if (willReadDst) {
if (fCachedDstReadFramebuffer) {
return fCachedDstReadFramebuffer;
if (needsXferBarrier) {
if (fCachedSelfDepFramebuffer) {
return fCachedSelfDepFramebuffer;
}
} else {
if (fCachedFramebuffer) {
@ -304,14 +306,15 @@ const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer(bool withStencil, bool w
}
}
}
return this->createFramebuffer(withStencil, willReadDst);
return this->createFramebuffer(withStencil, needsXferBarrier);
}
const GrVkFramebuffer* GrVkRenderTarget::createFramebuffer(bool withStencil, bool willReadDst) {
const GrVkFramebuffer* GrVkRenderTarget::createFramebuffer(bool withStencil,
bool needsXferBarrier) {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
GrVkGpu* gpu = this->getVkGpu();
const GrVkRenderPass* renderPass = this->getSimpleRenderPass(withStencil, willReadDst);
const GrVkRenderPass* renderPass = this->getSimpleRenderPass(withStencil, needsXferBarrier);
if (!renderPass) {
return nullptr;
}
@ -323,17 +326,17 @@ const GrVkFramebuffer* GrVkRenderTarget::createFramebuffer(bool withStencil, boo
stencilView);
if (withStencil) {
if (willReadDst) {
SkASSERT(!fCachedStencilDstReadFramebuffer);
fCachedStencilDstReadFramebuffer = frameBuffer;
if (needsXferBarrier) {
SkASSERT(!fCachedStencilSelfDepFramebuffer);
fCachedStencilSelfDepFramebuffer = frameBuffer;
} else {
SkASSERT(!fCachedStencilFramebuffer);
fCachedStencilFramebuffer = frameBuffer;
}
} else {
if (willReadDst) {
SkASSERT(!fCachedDstReadFramebuffer);
fCachedDstReadFramebuffer = frameBuffer;
if (needsXferBarrier) {
SkASSERT(!fCachedSelfDepFramebuffer);
fCachedSelfDepFramebuffer = frameBuffer;
} else {
SkASSERT(!fCachedFramebuffer);
fCachedFramebuffer = frameBuffer;
@ -408,17 +411,17 @@ GrVkRenderTarget::~GrVkRenderTarget() {
SkASSERT(!fColorAttachmentView);
SkASSERT(!fCachedFramebuffer);
SkASSERT(!fCachedStencilFramebuffer);
SkASSERT(!fCachedDstReadFramebuffer);
SkASSERT(!fCachedStencilDstReadFramebuffer);
SkASSERT(!fCachedSelfDepFramebuffer);
SkASSERT(!fCachedStencilSelfDepFramebuffer);
SkASSERT(!fCachedSimpleRenderPass);
SkASSERT(!fCachedStencilRenderPass);
SkASSERT(!fCachedDstReadRenderPass);
SkASSERT(!fCachedStencilDstReadRenderPass);
SkASSERT(!fCachedSelfDepRenderPass);
SkASSERT(!fCachedStencilSelfDepRenderPass);
}
void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer, bool withStencil,
bool willReadDst) {
commandBuffer.addResource(this->getFramebuffer(withStencil, willReadDst));
bool needsXferBarrier) {
commandBuffer.addResource(this->getFramebuffer(withStencil, needsXferBarrier));
commandBuffer.addResource(this->colorAttachmentView());
commandBuffer.addResource(this->msaaImageResource() ? this->msaaImageResource()
: this->resource());
@ -450,13 +453,13 @@ void GrVkRenderTarget::releaseInternalObjects() {
fCachedStencilFramebuffer->unref();
fCachedStencilFramebuffer = nullptr;
}
if (fCachedDstReadFramebuffer) {
fCachedDstReadFramebuffer->unref();
fCachedDstReadFramebuffer = nullptr;
if (fCachedSelfDepFramebuffer) {
fCachedSelfDepFramebuffer->unref();
fCachedSelfDepFramebuffer = nullptr;
}
if (fCachedStencilDstReadFramebuffer) {
fCachedStencilDstReadFramebuffer->unref();
fCachedStencilDstReadFramebuffer = nullptr;
if (fCachedStencilSelfDepFramebuffer) {
fCachedStencilSelfDepFramebuffer->unref();
fCachedStencilSelfDepFramebuffer = nullptr;
}
if (fCachedSimpleRenderPass) {
fCachedSimpleRenderPass->unref();
@ -466,13 +469,13 @@ void GrVkRenderTarget::releaseInternalObjects() {
fCachedStencilRenderPass->unref();
fCachedStencilRenderPass = nullptr;
}
if (fCachedDstReadRenderPass) {
fCachedDstReadRenderPass->unref();
fCachedDstReadRenderPass = nullptr;
if (fCachedSelfDepRenderPass) {
fCachedSelfDepRenderPass->unref();
fCachedSelfDepRenderPass = nullptr;
}
if (fCachedStencilDstReadRenderPass) {
fCachedStencilDstReadRenderPass->unref();
fCachedStencilDstReadRenderPass = nullptr;
if (fCachedStencilSelfDepRenderPass) {
fCachedStencilSelfDepRenderPass->unref();
fCachedStencilSelfDepRenderPass = nullptr;
}
for (int i = 0; i < fGrSecondaryCommandBuffers.count(); ++i) {
SkASSERT(fGrSecondaryCommandBuffers[i]);

View File

@ -43,7 +43,7 @@ public:
GrBackendFormat backendFormat() const override { return this->getBackendFormat(); }
const GrVkFramebuffer* getFramebuffer(bool withStencil, bool willReadDst);
const GrVkFramebuffer* getFramebuffer(bool withStencil, bool needsXferBarrier);
const GrVkImageView* colorAttachmentView() const { return fColorAttachmentView; }
const GrManagedResource* msaaImageResource() const {
if (fMSAAImage) {
@ -56,49 +56,49 @@ public:
const GrManagedResource* stencilImageResource() const;
const GrVkImageView* stencilAttachmentView() const;
const GrVkRenderPass* getSimpleRenderPass(bool withStencil, bool willReadDst);
const GrVkRenderPass* getSimpleRenderPass(bool withStencil, bool needsXferBarrier);
GrVkResourceProvider::CompatibleRPHandle compatibleRenderPassHandle(bool withStencil,
bool willReadDst) {
bool needsXferBarrier) {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
GrVkResourceProvider::CompatibleRPHandle* pRPHandle;
if (withStencil) {
if (willReadDst) {
pRPHandle = &fCompatibleStencilDstReadRPHandle;
if (needsXferBarrier) {
pRPHandle = &fCompatibleStencilSelfDepRPHandle;
} else {
pRPHandle = &fCompatibleStencilRPHandle;
}
} else {
if (willReadDst) {
pRPHandle = &fCompatibleDstReadRPHandle;
if (needsXferBarrier) {
pRPHandle = &fCompatibleSelfDepRPHandle;
} else {
pRPHandle = &fCompatibleRPHandle;
}
}
if (!pRPHandle->isValid()) {
this->createSimpleRenderPass(withStencil, willReadDst);
this->createSimpleRenderPass(withStencil, needsXferBarrier);
}
#ifdef SK_DEBUG
if (withStencil) {
if (willReadDst) {
SkASSERT(pRPHandle->isValid() == SkToBool(fCachedStencilDstReadRenderPass));
SkASSERT(fCachedStencilDstReadRenderPass->hasStencilAttachment());
SkASSERT(fCachedStencilDstReadRenderPass->hasInputSelfDependency());
if (needsXferBarrier) {
SkASSERT(pRPHandle->isValid() == SkToBool(fCachedStencilSelfDepRenderPass));
SkASSERT(fCachedStencilSelfDepRenderPass->hasStencilAttachment());
SkASSERT(fCachedStencilSelfDepRenderPass->hasSelfDependency());
} else {
SkASSERT(pRPHandle->isValid() == SkToBool(fCachedStencilRenderPass));
SkASSERT(fCachedStencilRenderPass->hasStencilAttachment());
SkASSERT(!fCachedStencilRenderPass->hasInputSelfDependency());
SkASSERT(!fCachedStencilRenderPass->hasSelfDependency());
}
} else {
if (willReadDst) {
SkASSERT(pRPHandle->isValid() == SkToBool(fCachedDstReadRenderPass));
SkASSERT(!fCachedDstReadRenderPass->hasStencilAttachment());
SkASSERT(fCachedDstReadRenderPass->hasInputSelfDependency());
if (needsXferBarrier) {
SkASSERT(pRPHandle->isValid() == SkToBool(fCachedSelfDepRenderPass));
SkASSERT(!fCachedSelfDepRenderPass->hasStencilAttachment());
SkASSERT(fCachedSelfDepRenderPass->hasSelfDependency());
} else {
SkASSERT(pRPHandle->isValid() == SkToBool(fCachedSimpleRenderPass));
SkASSERT(!fCachedSimpleRenderPass->hasStencilAttachment());
SkASSERT(!fCachedSimpleRenderPass->hasInputSelfDependency());
SkASSERT(!fCachedSimpleRenderPass->hasSelfDependency());
}
}
#endif
@ -136,7 +136,7 @@ public:
GrVkRenderPass::AttachmentsDescriptor* desc,
GrVkRenderPass::AttachmentFlags* flags);
void addResources(GrVkCommandBuffer& commandBuffer, bool withStencil, bool willReadDst);
void addResources(GrVkCommandBuffer& commandBuffer, bool withStencil, bool needsXferBarrier);
void addWrappedGrSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer> cmdBuffer) {
fGrSecondaryCommandBuffers.push_back(std::move(cmdBuffer));
@ -202,8 +202,8 @@ private:
GrVkGpu* getVkGpu() const;
const GrVkRenderPass* createSimpleRenderPass(bool withStencil, bool willReadDst);
const GrVkFramebuffer* createFramebuffer(bool withStencil, bool willReadDst);
const GrVkRenderPass* createSimpleRenderPass(bool withStencil, bool needsXferBarrier);
const GrVkFramebuffer* createFramebuffer(bool withStencil, bool needsXferBarrier);
bool completeStencilAttachment() override;
@ -222,25 +222,27 @@ private:
const GrVkFramebuffer* fCachedFramebuffer = nullptr;
const GrVkFramebuffer* fCachedStencilFramebuffer = nullptr;
const GrVkFramebuffer* fCachedDstReadFramebuffer = nullptr;
const GrVkFramebuffer* fCachedStencilDstReadFramebuffer = nullptr;
const GrVkFramebuffer* fCachedSelfDepFramebuffer = nullptr;
const GrVkFramebuffer* fCachedStencilSelfDepFramebuffer = nullptr;
// Cached pointers to a simple, stencil, and dst read render passes. The render target should
// unref them once it is done with them.
// Cached pointers to a simple, stencil, and self dependency render passes. The render target
// should unref them once it is done with them.
const GrVkRenderPass* fCachedSimpleRenderPass = nullptr;
const GrVkRenderPass* fCachedStencilRenderPass = nullptr;
const GrVkRenderPass* fCachedDstReadRenderPass = nullptr;
const GrVkRenderPass* fCachedStencilDstReadRenderPass = nullptr;
const GrVkRenderPass* fCachedSelfDepRenderPass = nullptr;
const GrVkRenderPass* fCachedStencilSelfDepRenderPass = nullptr;
// This is a handle to be used to quickly get a GrVkRenderPass that is compatible with
// this render target if its stencil buffer is ignored.
GrVkResourceProvider::CompatibleRPHandle fCompatibleRPHandle;
// Same as above but taking the render target's stencil buffer into account
GrVkResourceProvider::CompatibleRPHandle fCompatibleStencilRPHandle;
// RenderPass where the render target is also read as an input attachment
GrVkResourceProvider::CompatibleRPHandle fCompatibleDstReadRPHandle;
// RenderPass where there is also a self dependency to be used for advanced blending barriers.
// If the the gpu doesn't support VK_EXT_blend_operation_advanced the render pass will also have
// an input attachment to be used for dst reads.
GrVkResourceProvider::CompatibleRPHandle fCompatibleSelfDepRPHandle;
// Same as above but taking the render target's stencil buffer into account
GrVkResourceProvider::CompatibleRPHandle fCompatibleStencilDstReadRPHandle;
GrVkResourceProvider::CompatibleRPHandle fCompatibleStencilSelfDepRPHandle;
// If this render target wraps an external VkCommandBuffer, then this handle will be that
// VkCommandBuffer and not VK_NULL_HANDLE. In this case the render target will not be backed by

View File

@ -104,24 +104,25 @@ GrVkPipeline* GrVkResourceProvider::createPipeline(const GrProgramInfo& programI
const GrVkRenderPass*
GrVkResourceProvider::findCompatibleRenderPass(const GrVkRenderTarget& target,
CompatibleRPHandle* compatibleHandle,
bool withStencil, bool willReadDst) {
bool withStencil,
bool needsSelfDependency) {
// Get attachment information from render target. This includes which attachments the render
// target has (color, stencil) and the attachments format and sample count.
GrVkRenderPass::AttachmentFlags attachmentFlags;
GrVkRenderPass::AttachmentsDescriptor attachmentsDesc;
target.getAttachmentsDescriptor(&attachmentsDesc, &attachmentFlags, withStencil);
return this->findCompatibleRenderPass(&attachmentsDesc, attachmentFlags, willReadDst,
return this->findCompatibleRenderPass(&attachmentsDesc, attachmentFlags, needsSelfDependency,
compatibleHandle);
}
const GrVkRenderPass*
GrVkResourceProvider::findCompatibleRenderPass(GrVkRenderPass::AttachmentsDescriptor* desc,
GrVkRenderPass::AttachmentFlags attachmentFlags,
bool willReadDst,
bool needsSelfDependency,
CompatibleRPHandle* compatibleHandle) {
for (int i = 0; i < fRenderPassArray.count(); ++i) {
if (fRenderPassArray[i].isCompatible(*desc, attachmentFlags, willReadDst)) {
if (fRenderPassArray[i].isCompatible(*desc, attachmentFlags, needsSelfDependency)) {
const GrVkRenderPass* renderPass = fRenderPassArray[i].getCompatibleRenderPass();
renderPass->ref();
if (compatibleHandle) {
@ -132,7 +133,7 @@ GrVkResourceProvider::findCompatibleRenderPass(GrVkRenderPass::AttachmentsDescri
}
GrVkRenderPass* renderPass = GrVkRenderPass::CreateSimple(fGpu, desc, attachmentFlags,
willReadDst);
needsSelfDependency);
if (!renderPass) {
return nullptr;
}
@ -166,15 +167,16 @@ const GrVkRenderPass* GrVkResourceProvider::findCompatibleExternalRenderPass(
}
const GrVkRenderPass* GrVkResourceProvider::findRenderPass(
GrVkRenderTarget* target,
const GrVkRenderPass::LoadStoreOps& colorOps,
const GrVkRenderPass::LoadStoreOps& stencilOps,
CompatibleRPHandle* compatibleHandle,
bool withStencil, bool willReadDst) {
GrVkRenderTarget* target,
const GrVkRenderPass::LoadStoreOps& colorOps,
const GrVkRenderPass::LoadStoreOps& stencilOps,
CompatibleRPHandle* compatibleHandle,
bool withStencil,
bool needsSelfDependency) {
GrVkResourceProvider::CompatibleRPHandle tempRPHandle;
GrVkResourceProvider::CompatibleRPHandle* pRPHandle = compatibleHandle ? compatibleHandle
: &tempRPHandle;
*pRPHandle = target->compatibleRenderPassHandle(withStencil, willReadDst);
*pRPHandle = target->compatibleRenderPassHandle(withStencil, needsSelfDependency);
if (!pRPHandle->isValid()) {
return nullptr;
}
@ -511,11 +513,12 @@ GrVkResourceProvider::CompatibleRenderPassSet::CompatibleRenderPassSet(GrVkRende
bool GrVkResourceProvider::CompatibleRenderPassSet::isCompatible(
const GrVkRenderPass::AttachmentsDescriptor& attachmentsDescriptor,
GrVkRenderPass::AttachmentFlags attachmentFlags,
bool willReadDst) const {
bool needsSelfDependency) const {
// The first GrVkRenderpass should always exists since we create the basic load store
// render pass on create
SkASSERT(fRenderPasses[0]);
return fRenderPasses[0]->isCompatible(attachmentsDescriptor, attachmentFlags, willReadDst);
return fRenderPasses[0]->isCompatible(attachmentsDescriptor, attachmentFlags,
needsSelfDependency);
}
GrVkRenderPass* GrVkResourceProvider::CompatibleRenderPassSet::getRenderPass(

View File

@ -59,10 +59,10 @@ public:
// compatible GrVkRenderPasses without the need inspecting a GrVkRenderTarget.
const GrVkRenderPass* findCompatibleRenderPass(const GrVkRenderTarget& target,
CompatibleRPHandle* compatibleHandle,
bool withStencil, bool willReadDst);
bool withStencil, bool needsSelfDependency);
const GrVkRenderPass* findCompatibleRenderPass(GrVkRenderPass::AttachmentsDescriptor*,
GrVkRenderPass::AttachmentFlags,
bool willReadDst,
bool needsSelfDependency,
CompatibleRPHandle* compatibleHandle = nullptr);
const GrVkRenderPass* findCompatibleExternalRenderPass(VkRenderPass,
@ -77,7 +77,8 @@ public:
const GrVkRenderPass::LoadStoreOps& colorOps,
const GrVkRenderPass::LoadStoreOps& stencilOps,
CompatibleRPHandle* compatibleHandle,
bool withStencil, bool willReadDst);
bool withStencil,
bool needsSelfDependency);
// The CompatibleRPHandle must be a valid handle previously set by a call to findRenderPass or
// findCompatibleRenderPass.
@ -230,7 +231,7 @@ private:
bool isCompatible(const GrVkRenderPass::AttachmentsDescriptor&,
GrVkRenderPass::AttachmentFlags,
bool willReadDst) const;
bool needsSelfDependency) const;
const GrVkRenderPass* getCompatibleRenderPass() const {
// The first GrVkRenderpass should always exist since we create the basic load store