Handle failure to create VkRenderPasses in vulkan backend.

Bug: skia:9603
Change-Id: I8c56f399d58b109d163ff69b654d07edbc44dde0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/253497
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2019-11-07 17:15:45 -05:00 committed by Skia Commit-Bot
parent 4d0fe38f29
commit ed98476cf2
7 changed files with 111 additions and 77 deletions

View File

@ -112,7 +112,9 @@ bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
vkColorOps,
vkStencilOps);
}
SkASSERT(fCurrentRenderPass);
if (!fCurrentRenderPass) {
return false;
}
VkClearValue vkClearColor;
vkClearColor.color.float32[0] = clearColor[0];
@ -380,7 +382,9 @@ void GrVkOpsRenderPass::addAdditionalRenderPass(bool mustUseSecondaryCommandBuff
vkColorOps,
vkStencilOps);
}
SkASSERT(fCurrentRenderPass);
if (!fCurrentRenderPass) {
return;
}
VkClearValue vkClearColor;
memset(&vkClearColor, 0, sizeof(VkClearValue));

View File

@ -42,17 +42,34 @@ void setup_vk_attachment_description(VkAttachmentDescription* attachment,
attachment->finalLayout = layout;
}
void GrVkRenderPass::initSimple(GrVkGpu* gpu, const GrVkRenderTarget& target) {
GrVkRenderPass* GrVkRenderPass::CreateSimple(GrVkGpu* gpu, const GrVkRenderTarget& target) {
static const GrVkRenderPass::LoadStoreOps kBasicLoadStoreOps(VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE);
this->init(gpu, target, kBasicLoadStoreOps, kBasicLoadStoreOps);
AttachmentFlags attachmentFlags;
AttachmentsDescriptor attachmentsDescriptor;
// Get attachment information from render target. This includes which attachments the render
// target has (color, stencil) and the attachments format and sample count.
target.getAttachmentsDescriptor(&attachmentsDescriptor, &attachmentFlags);
return Create(gpu, attachmentFlags, attachmentsDescriptor, kBasicLoadStoreOps,
kBasicLoadStoreOps);
}
void GrVkRenderPass::init(GrVkGpu* gpu,
const LoadStoreOps& colorOp,
const LoadStoreOps& stencilOp) {
uint32_t numAttachments = fAttachmentsDescriptor.fAttachmentCount;
GrVkRenderPass* GrVkRenderPass::Create(GrVkGpu* gpu,
const GrVkRenderPass& compatibleRenderPass,
const LoadStoreOps& colorOp,
const LoadStoreOps& stencilOp) {
AttachmentFlags attachmentFlags = compatibleRenderPass.fAttachmentFlags;
AttachmentsDescriptor attachmentsDescriptor = compatibleRenderPass.fAttachmentsDescriptor;
return Create(gpu, attachmentFlags, attachmentsDescriptor, colorOp, stencilOp);
}
GrVkRenderPass* GrVkRenderPass::Create(GrVkGpu* gpu,
AttachmentFlags attachmentFlags,
AttachmentsDescriptor& attachmentsDescriptor,
const LoadStoreOps& colorOp,
const LoadStoreOps& stencilOp) {
uint32_t numAttachments = attachmentsDescriptor.fAttachmentCount;
// Attachment descriptions to be set on the render pass
SkTArray<VkAttachmentDescription> attachments(numAttachments);
attachments.reset(numAttachments);
@ -74,11 +91,13 @@ void GrVkRenderPass::init(GrVkGpu* gpu,
subpassDesc.pInputAttachments = nullptr;
subpassDesc.pResolveAttachments = nullptr;
if (fAttachmentFlags & kColor_AttachmentFlag) {
uint32_t clearValueCount = 0;
if (attachmentFlags & kColor_AttachmentFlag) {
// set up color attachment
fAttachmentsDescriptor.fColor.fLoadStoreOps = colorOp;
attachmentsDescriptor.fColor.fLoadStoreOps = colorOp;
setup_vk_attachment_description(&attachments[currentAttachment],
fAttachmentsDescriptor.fColor,
attachmentsDescriptor.fColor,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// setup subpass use of attachment
colorRef.attachment = currentAttachment++;
@ -86,7 +105,7 @@ void GrVkRenderPass::init(GrVkGpu* gpu,
subpassDesc.colorAttachmentCount = 1;
if (VK_ATTACHMENT_LOAD_OP_CLEAR == colorOp.fLoadOp) {
fClearValueCount = colorRef.attachment + 1;
clearValueCount = colorRef.attachment + 1;
}
} else {
// I don't think there should ever be a time where we don't have a color attachment
@ -97,17 +116,17 @@ void GrVkRenderPass::init(GrVkGpu* gpu,
}
subpassDesc.pColorAttachments = &colorRef;
if (fAttachmentFlags & kStencil_AttachmentFlag) {
if (attachmentFlags & kStencil_AttachmentFlag) {
// set up stencil attachment
fAttachmentsDescriptor.fStencil.fLoadStoreOps = stencilOp;
attachmentsDescriptor.fStencil.fLoadStoreOps = stencilOp;
setup_vk_attachment_description(&attachments[currentAttachment],
fAttachmentsDescriptor.fStencil,
attachmentsDescriptor.fStencil,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
// setup subpass use of attachment
stencilRef.attachment = currentAttachment++;
stencilRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
if (VK_ATTACHMENT_LOAD_OP_CLEAR == stencilOp.fLoadOp) {
fClearValueCount = SkTMax(fClearValueCount, stencilRef.attachment + 1);
clearValueCount = SkTMax(clearValueCount, stencilRef.attachment + 1);
}
} else {
stencilRef.attachment = VK_ATTACHMENT_UNUSED;
@ -133,31 +152,34 @@ void GrVkRenderPass::init(GrVkGpu* gpu,
createInfo.dependencyCount = 0;
createInfo.pDependencies = nullptr;
GR_VK_CALL_ERRCHECK(gpu, CreateRenderPass(gpu->device(), &createInfo, nullptr, &fRenderPass));
VkResult result;
VkRenderPass renderPass;
GR_VK_CALL_RESULT(gpu, result, CreateRenderPass(gpu->device(),
&createInfo,
nullptr,
&renderPass));
if (result != VK_SUCCESS) {
return nullptr;
}
VkExtent2D granularity;
// Get granularity for this render pass
GR_VK_CALL(gpu->vkInterface(), GetRenderAreaGranularity(gpu->device(),
fRenderPass,
&fGranularity));
renderPass,
&granularity));
return new GrVkRenderPass(renderPass, attachmentFlags, attachmentsDescriptor, granularity,
clearValueCount);
}
void GrVkRenderPass::init(GrVkGpu* gpu,
const GrVkRenderPass& compatibleRenderPass,
const LoadStoreOps& colorOp,
const LoadStoreOps& stencilOp) {
fAttachmentFlags = compatibleRenderPass.fAttachmentFlags;
fAttachmentsDescriptor = compatibleRenderPass.fAttachmentsDescriptor;
this->init(gpu, colorOp, stencilOp);
}
void GrVkRenderPass::init(GrVkGpu* gpu,
const GrVkRenderTarget& target,
const LoadStoreOps& colorOp,
const LoadStoreOps& stencilOp) {
// Get attachment information from render target. This includes which attachments the render
// target has (color, stencil) and the attachments format and sample count.
target.getAttachmentsDescriptor(&fAttachmentsDescriptor, &fAttachmentFlags);
this->init(gpu, colorOp, stencilOp);
GrVkRenderPass::GrVkRenderPass(VkRenderPass renderPass, AttachmentFlags flags,
const AttachmentsDescriptor& descriptor,
const VkExtent2D& granularity, uint32_t clearValueCount)
: fRenderPass(renderPass)
, fAttachmentFlags(flags)
, fAttachmentsDescriptor(descriptor)
, fGranularity(granularity)
, fClearValueCount(clearValueCount) {
}
void GrVkRenderPass::freeGPUData(GrVkGpu* gpu) const {

View File

@ -18,17 +18,6 @@ class GrVkRenderTarget;
class GrVkRenderPass : public GrVkResource {
public:
GrVkRenderPass() : INHERITED(), fRenderPass(VK_NULL_HANDLE), fClearValueCount(0) {}
// Used when importing an external render pass. In this case we have to explicitly be told the
// color attachment index
explicit GrVkRenderPass(VkRenderPass renderPass, uint32_t colorAttachmentIndex)
: INHERITED()
, fRenderPass(renderPass)
, fAttachmentFlags(kExternal_AttachmentFlag)
, fClearValueCount(0)
, fColorAttachmentIndex(colorAttachmentIndex) {}
struct LoadStoreOps {
VkAttachmentLoadOp fLoadOp;
VkAttachmentStoreOp fStoreOp;
@ -46,16 +35,20 @@ public:
}
};
void initSimple(GrVkGpu* gpu, const GrVkRenderTarget& target);
void init(GrVkGpu* gpu,
const GrVkRenderTarget& target,
const LoadStoreOps& colorOp,
const LoadStoreOps& stencilOp);
static GrVkRenderPass* CreateSimple(GrVkGpu* gpu, const GrVkRenderTarget& target);
static GrVkRenderPass* Create(GrVkGpu* gpu,
const GrVkRenderPass& compatibleRenderPass,
const LoadStoreOps& colorOp,
const LoadStoreOps& stencilOp);
void init(GrVkGpu* gpu,
const GrVkRenderPass& compatibleRenderPass,
const LoadStoreOps& colorOp,
const LoadStoreOps& stencilOp);
// Used when importing an external render pass. In this case we have to explicitly be told the
// color attachment index
explicit GrVkRenderPass(VkRenderPass renderPass, uint32_t colorAttachmentIndex)
: INHERITED()
, fRenderPass(renderPass)
, fAttachmentFlags(kExternal_AttachmentFlag)
, fClearValueCount(0)
, fColorAttachmentIndex(colorAttachmentIndex) {}
struct AttachmentsDescriptor {
struct AttachmentDesc {
@ -132,11 +125,14 @@ public:
#endif
private:
GrVkRenderPass(const GrVkRenderPass&);
GrVkRenderPass(VkRenderPass, AttachmentFlags, const AttachmentsDescriptor&,
const VkExtent2D& granularity, uint32_t clearValueCount);
void init(GrVkGpu* gpu,
const LoadStoreOps& colorOps,
const LoadStoreOps& stencilOps);
static GrVkRenderPass* Create(GrVkGpu* gpu,
AttachmentFlags,
AttachmentsDescriptor&,
const LoadStoreOps& colorOps,
const LoadStoreOps& stencilOps);
bool isCompatible(const AttachmentsDescriptor&, const AttachmentFlags&) const;

View File

@ -259,8 +259,6 @@ const GrVkRenderPass* GrVkRenderTarget::createSimpleRenderPass() {
fCachedSimpleRenderPass =
this->getVkGpu()->resourceProvider().findCompatibleRenderPass(*this, &fCompatibleRPHandle);
// TODO: allow for the above call to fail and handle returning null from getSimpleRenderPass
SkASSERT(fCachedSimpleRenderPass);
return fCachedSimpleRenderPass;
}
@ -278,8 +276,11 @@ const GrVkFramebuffer* GrVkRenderTarget::createFramebuffer() {
GrVkGpu* gpu = this->getVkGpu();
// Stencil attachment view is stored in the base RT stencil attachment
const GrVkImageView* stencilView = this->stencilAttachmentView();
fCachedFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(),
this->getSimpleRenderPass(),
const GrVkRenderPass* renderPass = this->getSimpleRenderPass();
if (!renderPass) {
return nullptr;
}
fCachedFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(), renderPass,
fColorAttachmentView, stencilView);
return fCachedFramebuffer;
}

View File

@ -64,6 +64,7 @@ public:
SkASSERT(!fCachedSimpleRenderPass);
this->createSimpleRenderPass();
}
SkASSERT(fCompatibleRPHandle.isValid() == SkToBool(fCachedSimpleRenderPass));
return fCompatibleRPHandle;
}
const GrVkRenderPass* externalRenderPass() const {

View File

@ -119,9 +119,11 @@ GrVkResourceProvider::findCompatibleRenderPass(const GrVkRenderTarget& target,
}
}
const GrVkRenderPass* renderPass =
fRenderPassArray.emplace_back(fGpu, target).getCompatibleRenderPass();
renderPass->ref();
GrVkRenderPass* renderPass = GrVkRenderPass::CreateSimple(fGpu, target);
if (!renderPass) {
return nullptr;
}
fRenderPassArray.emplace_back(renderPass);
if (compatibleHandle) {
*compatibleHandle = CompatibleRPHandle(fRenderPassArray.count() - 1);
@ -134,6 +136,7 @@ GrVkResourceProvider::findCompatibleRenderPass(const CompatibleRPHandle& compati
SkASSERT(compatibleHandle.isValid() && compatibleHandle.toIndex() < fRenderPassArray.count());
int index = compatibleHandle.toIndex();
const GrVkRenderPass* renderPass = fRenderPassArray[index].getCompatibleRenderPass();
SkASSERT(renderPass);
renderPass->ref();
return renderPass;
}
@ -167,10 +170,10 @@ const GrVkRenderPass* GrVkResourceProvider::findRenderPass(
GrVkResourceProvider::CompatibleRPHandle* pRPHandle = compatibleHandle ? compatibleHandle
: &tempRPHandle;
*pRPHandle = target->compatibleRenderPassHandle();
if (!pRPHandle->isValid()) {
return nullptr;
}
// This will get us the handle to (and possible create) the compatible set for the specific
// GrVkRenderPass we are looking for.
this->findCompatibleRenderPass(*target, compatibleHandle);
return this->findRenderPass(*pRPHandle, colorOps, stencilOps);
}
@ -183,6 +186,9 @@ GrVkResourceProvider::findRenderPass(const CompatibleRPHandle& compatibleHandle,
const GrVkRenderPass* renderPass = compatibleSet.getRenderPass(fGpu,
colorOps,
stencilOps);
if (!renderPass) {
return nullptr;
}
renderPass->ref();
return renderPass;
}
@ -533,10 +539,10 @@ void GrVkResourceProvider::storePipelineCacheData() {
////////////////////////////////////////////////////////////////////////////////
GrVkResourceProvider::CompatibleRenderPassSet::CompatibleRenderPassSet(
GrVkGpu* gpu, const GrVkRenderTarget& target) : fLastReturnedIndex(0) {
fRenderPasses.emplace_back(new GrVkRenderPass());
fRenderPasses[0]->initSimple(gpu, target);
GrVkResourceProvider::CompatibleRenderPassSet::CompatibleRenderPassSet(GrVkRenderPass* renderPass)
: fLastReturnedIndex(0) {
renderPass->ref();
fRenderPasses.push_back(renderPass);
}
bool GrVkResourceProvider::CompatibleRenderPassSet::isCompatible(
@ -558,8 +564,12 @@ GrVkRenderPass* GrVkResourceProvider::CompatibleRenderPassSet::getRenderPass(
return fRenderPasses[idx];
}
}
GrVkRenderPass* renderPass = fRenderPasses.emplace_back(new GrVkRenderPass());
renderPass->init(gpu, *this->getCompatibleRenderPass(), colorOps, stencilOps);
GrVkRenderPass* renderPass = GrVkRenderPass::Create(gpu, *this->getCompatibleRenderPass(),
colorOps, stencilOps);
if (!renderPass) {
return nullptr;
}
fRenderPasses.push_back(renderPass);
fLastReturnedIndex = fRenderPasses.count() - 1;
return renderPass;
}

View File

@ -218,7 +218,7 @@ private:
// This will always construct the basic load store render pass (all attachments load and
// store their data) so that there is at least one compatible VkRenderPass that can be used
// with this set.
CompatibleRenderPassSet(GrVkGpu* gpu, const GrVkRenderTarget& target);
CompatibleRenderPassSet(GrVkRenderPass* renderPass);
bool isCompatible(const GrVkRenderTarget& target) const;