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>
diff --git a/src/gpu/vk/GrVkOpsRenderPass.cpp b/src/gpu/vk/GrVkOpsRenderPass.cpp
index 01ff901..c880ace 100644
--- a/src/gpu/vk/GrVkOpsRenderPass.cpp
+++ b/src/gpu/vk/GrVkOpsRenderPass.cpp
@@ -112,7 +112,9 @@
vkColorOps,
vkStencilOps);
}
- SkASSERT(fCurrentRenderPass);
+ if (!fCurrentRenderPass) {
+ return false;
+ }
VkClearValue vkClearColor;
vkClearColor.color.float32[0] = clearColor[0];
@@ -380,7 +382,9 @@
vkColorOps,
vkStencilOps);
}
- SkASSERT(fCurrentRenderPass);
+ if (!fCurrentRenderPass) {
+ return;
+ }
VkClearValue vkClearColor;
memset(&vkClearColor, 0, sizeof(VkClearValue));
diff --git a/src/gpu/vk/GrVkRenderPass.cpp b/src/gpu/vk/GrVkRenderPass.cpp
index a022af6..818b3b8 100644
--- a/src/gpu/vk/GrVkRenderPass.cpp
+++ b/src/gpu/vk/GrVkRenderPass.cpp
@@ -42,17 +42,34 @@
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 @@
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 @@
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 @@
}
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 @@
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 {
diff --git a/src/gpu/vk/GrVkRenderPass.h b/src/gpu/vk/GrVkRenderPass.h
index 6ec1a85..1474c7b 100644
--- a/src/gpu/vk/GrVkRenderPass.h
+++ b/src/gpu/vk/GrVkRenderPass.h
@@ -18,17 +18,6 @@
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 @@
}
};
- 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 @@
#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;
diff --git a/src/gpu/vk/GrVkRenderTarget.cpp b/src/gpu/vk/GrVkRenderTarget.cpp
index ff42b58..af7b97d 100644
--- a/src/gpu/vk/GrVkRenderTarget.cpp
+++ b/src/gpu/vk/GrVkRenderTarget.cpp
@@ -259,8 +259,6 @@
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 @@
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;
}
diff --git a/src/gpu/vk/GrVkRenderTarget.h b/src/gpu/vk/GrVkRenderTarget.h
index 2f7ec83..99bac20 100644
--- a/src/gpu/vk/GrVkRenderTarget.h
+++ b/src/gpu/vk/GrVkRenderTarget.h
@@ -64,6 +64,7 @@
SkASSERT(!fCachedSimpleRenderPass);
this->createSimpleRenderPass();
}
+ SkASSERT(fCompatibleRPHandle.isValid() == SkToBool(fCachedSimpleRenderPass));
return fCompatibleRPHandle;
}
const GrVkRenderPass* externalRenderPass() const {
diff --git a/src/gpu/vk/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp
index 96bdaa8..73204c5 100644
--- a/src/gpu/vk/GrVkResourceProvider.cpp
+++ b/src/gpu/vk/GrVkResourceProvider.cpp
@@ -119,9 +119,11 @@
}
}
- 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 @@
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 @@
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 @@
const GrVkRenderPass* renderPass = compatibleSet.getRenderPass(fGpu,
colorOps,
stencilOps);
+ if (!renderPass) {
+ return nullptr;
+ }
renderPass->ref();
return renderPass;
}
@@ -533,10 +539,10 @@
////////////////////////////////////////////////////////////////////////////////
-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 @@
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;
}
diff --git a/src/gpu/vk/GrVkResourceProvider.h b/src/gpu/vk/GrVkResourceProvider.h
index 8449a88..32baa60 100644
--- a/src/gpu/vk/GrVkResourceProvider.h
+++ b/src/gpu/vk/GrVkResourceProvider.h
@@ -218,7 +218,7 @@
// 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;