diff --git a/src/gpu/vk/GrVkRenderPass.cpp b/src/gpu/vk/GrVkRenderPass.cpp index c56bafa92d..6a0f953a1c 100644 --- a/src/gpu/vk/GrVkRenderPass.cpp +++ b/src/gpu/vk/GrVkRenderPass.cpp @@ -23,16 +23,16 @@ void setup_vk_attachment_description(VkAttachmentDescription* attachment, SkAssertResult(GrSampleCountToVkSampleCount(desc.fSamples, &attachment->samples)); switch (layout) { case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - attachment->loadOp = desc.fLoadOp; - attachment->storeOp = desc.fStoreOp; + attachment->loadOp = desc.fLoadStoreOps.fLoadOp; + attachment->storeOp = desc.fLoadStoreOps.fStoreOp; attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; break; case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachment->storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachment->stencilLoadOp = desc.fLoadOp; - attachment->stencilStoreOp = desc.fStoreOp; + attachment->stencilLoadOp = desc.fLoadStoreOps.fLoadOp; + attachment->stencilStoreOp = desc.fLoadStoreOps.fStoreOp; break; default: SkFAIL("Unexpected attachment layout"); @@ -43,15 +43,21 @@ void setup_vk_attachment_description(VkAttachmentDescription* attachment, } void GrVkRenderPass::initSimple(const GrVkGpu* gpu, const GrVkRenderTarget& target) { - // Get attachment information from render target. This includes which attachments the render - // target has (color, resolve, stencil) and the attachments format and sample count. - target.getAttachmentsDescriptor(&fAttachmentsDescriptor, &fAttachmentFlags); + static const GrVkRenderPass::LoadStoreOps kBasicLoadStoreOps(VK_ATTACHMENT_LOAD_OP_LOAD, + VK_ATTACHMENT_STORE_OP_STORE); + this->init(gpu, target, kBasicLoadStoreOps, kBasicLoadStoreOps, kBasicLoadStoreOps); +} + +void GrVkRenderPass::init(const GrVkGpu* gpu, + const LoadStoreOps& colorOp, + const LoadStoreOps& resolveOp, + const LoadStoreOps& stencilOp) { uint32_t numAttachments = fAttachmentsDescriptor.fAttachmentCount; // Attachment descriptions to be set on the render pass SkTArray attachments(numAttachments); attachments.reset(numAttachments); - memset(attachments.begin(), 0, numAttachments*sizeof(VkAttachmentDescription)); + memset(attachments.begin(), 0, numAttachments * sizeof(VkAttachmentDescription)); // Refs to attachments on the render pass (as described by teh VkAttachmentDescription above), // that are used by the subpass. @@ -70,6 +76,7 @@ void GrVkRenderPass::initSimple(const GrVkGpu* gpu, const GrVkRenderTarget& targ subpassDesc.pInputAttachments = nullptr; if (fAttachmentFlags & kColor_AttachmentFlag) { // set up color attachment + fAttachmentsDescriptor.fColor.fLoadStoreOps = colorOp; setup_vk_attachment_description(&attachments[currentAttachment], fAttachmentsDescriptor.fColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); @@ -88,6 +95,7 @@ void GrVkRenderPass::initSimple(const GrVkGpu* gpu, const GrVkRenderTarget& targ if (fAttachmentFlags & kResolve_AttachmentFlag) { // set up resolve attachment + fAttachmentsDescriptor.fResolve.fLoadStoreOps = resolveOp; setup_vk_attachment_description(&attachments[currentAttachment], fAttachmentsDescriptor.fResolve, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); @@ -102,6 +110,7 @@ void GrVkRenderPass::initSimple(const GrVkGpu* gpu, const GrVkRenderTarget& targ if (fAttachmentFlags & kStencil_AttachmentFlag) { // set up stencil attachment + fAttachmentsDescriptor.fStencil.fLoadStoreOps = stencilOp; setup_vk_attachment_description(&attachments[currentAttachment], fAttachmentsDescriptor.fStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); @@ -138,6 +147,27 @@ void GrVkRenderPass::initSimple(const GrVkGpu* gpu, const GrVkRenderTarget& targ &fRenderPass)); } +void GrVkRenderPass::init(const GrVkGpu* gpu, + const GrVkRenderPass& compatibleRenderPass, + const LoadStoreOps& colorOp, + const LoadStoreOps& resolveOp, + const LoadStoreOps& stencilOp) { + fAttachmentFlags = compatibleRenderPass.fAttachmentFlags; + fAttachmentsDescriptor = compatibleRenderPass.fAttachmentsDescriptor; + this->init(gpu, colorOp, resolveOp, stencilOp); +} + +void GrVkRenderPass::init(const GrVkGpu* gpu, + const GrVkRenderTarget& target, + const LoadStoreOps& colorOp, + const LoadStoreOps& resolveOp, + const LoadStoreOps& stencilOp) { + // Get attachment information from render target. This includes which attachments the render + // target has (color, resolve, stencil) and the attachments format and sample count. + target.getAttachmentsDescriptor(&fAttachmentsDescriptor, &fAttachmentFlags); + this->init(gpu, colorOp, resolveOp, stencilOp); +} + void GrVkRenderPass::freeGPUData(const GrVkGpu* gpu) const { GR_VK_CALL(gpu->vkInterface(), DestroyRenderPass(gpu->device(), fRenderPass, nullptr)); } @@ -231,6 +261,27 @@ bool GrVkRenderPass::isCompatible(const GrVkRenderTarget& target) const { return true; } +bool GrVkRenderPass::equalLoadStoreOps(const LoadStoreOps& colorOps, + const LoadStoreOps& resolveOps, + const LoadStoreOps& stencilOps) const { + if (fAttachmentFlags & kColor_AttachmentFlag) { + if (fAttachmentsDescriptor.fColor.fLoadStoreOps != colorOps) { + return false; + } + } + if (fAttachmentFlags & kResolve_AttachmentFlag) { + if (fAttachmentsDescriptor.fResolve.fLoadStoreOps != resolveOps) { + return false; + } + } + if (fAttachmentFlags & kStencil_AttachmentFlag) { + if (fAttachmentsDescriptor.fStencil.fLoadStoreOps != stencilOps) { + return false; + } + } + return true; +} + void GrVkRenderPass::genKey(GrProcessorKeyBuilder* b) const { b->add32(fAttachmentFlags); if (fAttachmentFlags & kColor_AttachmentFlag) { diff --git a/src/gpu/vk/GrVkRenderPass.h b/src/gpu/vk/GrVkRenderPass.h index 082cccda77..b4f4b2b2bb 100644 --- a/src/gpu/vk/GrVkRenderPass.h +++ b/src/gpu/vk/GrVkRenderPass.h @@ -21,25 +21,51 @@ class GrVkRenderTarget; class GrVkRenderPass : public GrVkResource { public: GrVkRenderPass() : INHERITED(), fRenderPass(VK_NULL_HANDLE) {} + + struct LoadStoreOps { + VkAttachmentLoadOp fLoadOp; + VkAttachmentStoreOp fStoreOp; + + LoadStoreOps(VkAttachmentLoadOp loadOp, VkAttachmentStoreOp storeOp) + : fLoadOp(loadOp) + , fStoreOp(storeOp) {} + + bool operator==(const LoadStoreOps& right) const { + return fLoadOp == right.fLoadOp && fStoreOp == right.fStoreOp; + } + + bool operator!=(const LoadStoreOps& right) const { + return !(*this == right); + } + }; + void initSimple(const GrVkGpu* gpu, const GrVkRenderTarget& target); + void init(const GrVkGpu* gpu, + const GrVkRenderTarget& target, + const LoadStoreOps& colorOp, + const LoadStoreOps& resolveOp, + const LoadStoreOps& stencilOp); + + void init(const GrVkGpu* gpu, + const GrVkRenderPass& compatibleRenderPass, + const LoadStoreOps& colorOp, + const LoadStoreOps& resolveOp, + const LoadStoreOps& stencilOp); struct AttachmentsDescriptor { struct AttachmentDesc { VkFormat fFormat; int fSamples; - VkAttachmentLoadOp fLoadOp; - VkAttachmentStoreOp fStoreOp; + LoadStoreOps fLoadStoreOps; AttachmentDesc() : fFormat(VK_FORMAT_UNDEFINED) , fSamples(0) - , fLoadOp(VK_ATTACHMENT_LOAD_OP_LOAD) - , fStoreOp(VK_ATTACHMENT_STORE_OP_STORE) {} + , fLoadStoreOps(VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE) {} bool operator==(const AttachmentDesc& right) const { return (fFormat == right.fFormat && fSamples == right.fSamples && - fLoadOp == right.fLoadOp && - fStoreOp == right.fStoreOp); + fLoadStoreOps == right.fLoadStoreOps); } bool operator!=(const AttachmentDesc& right) const { return !(*this == right); @@ -84,6 +110,10 @@ public: // basic RenderPasses that can be used when creating a VkFrameBuffer object. bool isCompatible(const GrVkRenderTarget& target) const; + bool equalLoadStoreOps(const LoadStoreOps& colorOps, + const LoadStoreOps& resolveOps, + const LoadStoreOps& stencilOps) const; + VkRenderPass vkRenderPass() const { return fRenderPass; } void genKey(GrProcessorKeyBuilder* b) const; @@ -91,6 +121,11 @@ public: private: GrVkRenderPass(const GrVkRenderPass&); + void init(const GrVkGpu* gpu, + const LoadStoreOps& colorOps, + const LoadStoreOps& resolveOps, + const LoadStoreOps& stencilOps); + void freeGPUData(const GrVkGpu* gpu) const override; VkRenderPass fRenderPass; diff --git a/src/gpu/vk/GrVkRenderTarget.h b/src/gpu/vk/GrVkRenderTarget.h index 0467371ecb..735f5cdf7c 100644 --- a/src/gpu/vk/GrVkRenderTarget.h +++ b/src/gpu/vk/GrVkRenderTarget.h @@ -65,7 +65,6 @@ public: GrBackendObject getRenderTargetHandle() const override; - // Returns the total number of attachments void getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor* desc, GrVkRenderPass::AttachmentFlags* flags) const; diff --git a/src/gpu/vk/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp index fdc9e90686..cd3ba47bca 100644 --- a/src/gpu/vk/GrVkResourceProvider.cpp +++ b/src/gpu/vk/GrVkResourceProvider.cpp @@ -10,7 +10,6 @@ #include "GrTextureParams.h" #include "GrVkCommandBuffer.h" #include "GrVkPipeline.h" -#include "GrVkRenderPass.h" #include "GrVkSampler.h" #include "GrVkUtil.h" @@ -134,6 +133,33 @@ GrVkResourceProvider::findCompatibleRenderPass(const CompatibleRPHandle& compati return renderPass; } +const GrVkRenderPass* GrVkResourceProvider::findRenderPass( + const GrVkRenderTarget& target, + const GrVkRenderPass::LoadStoreOps& colorOps, + const GrVkRenderPass::LoadStoreOps& resolveOps, + const GrVkRenderPass::LoadStoreOps& stencilOps, + CompatibleRPHandle* compatibleHandle) { + // 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(*compatibleHandle, colorOps, resolveOps, stencilOps); +} + +const GrVkRenderPass* +GrVkResourceProvider::findRenderPass(const CompatibleRPHandle& compatibleHandle, + const GrVkRenderPass::LoadStoreOps& colorOps, + const GrVkRenderPass::LoadStoreOps& resolveOps, + const GrVkRenderPass::LoadStoreOps& stencilOps) { + SkASSERT(compatibleHandle.isValid() && compatibleHandle.toIndex() < fRenderPassArray.count()); + CompatibleRenderPassSet& compatibleSet = fRenderPassArray[compatibleHandle.toIndex()]; + const GrVkRenderPass* renderPass = compatibleSet.getRenderPass(fGpu, + colorOps, + resolveOps, + stencilOps); + renderPass->ref(); + return renderPass; +} + GrVkDescriptorPool* GrVkResourceProvider::findOrCreateCompatibleDescriptorPool( VkDescriptorType type, uint32_t count) { return new GrVkDescriptorPool(fGpu, type, count); @@ -295,6 +321,24 @@ bool GrVkResourceProvider::CompatibleRenderPassSet::isCompatible( return fRenderPasses[0]->isCompatible(target); } +GrVkRenderPass* GrVkResourceProvider::CompatibleRenderPassSet::getRenderPass( + const GrVkGpu* gpu, + const GrVkRenderPass::LoadStoreOps& colorOps, + const GrVkRenderPass::LoadStoreOps& resolveOps, + const GrVkRenderPass::LoadStoreOps& stencilOps) { + for (int i = 0; i < fRenderPasses.count(); ++i) { + int idx = (i + fLastReturnedIndex) % fRenderPasses.count(); + if (fRenderPasses[idx]->equalLoadStoreOps(colorOps, resolveOps, stencilOps)) { + fLastReturnedIndex = idx; + return fRenderPasses[idx]; + } + } + GrVkRenderPass* renderPass = fRenderPasses.push_back(); + renderPass->init(gpu, *this->getCompatibleRenderPass(), colorOps, resolveOps, stencilOps); + fLastReturnedIndex = fRenderPasses.count() - 1; + return renderPass; +} + void GrVkResourceProvider::CompatibleRenderPassSet::releaseResources(const GrVkGpu* gpu) { for (int i = 0; i < fRenderPasses.count(); ++i) { if (fRenderPasses[i]) { diff --git a/src/gpu/vk/GrVkResourceProvider.h b/src/gpu/vk/GrVkResourceProvider.h index 5368a212b4..e754501cba 100644 --- a/src/gpu/vk/GrVkResourceProvider.h +++ b/src/gpu/vk/GrVkResourceProvider.h @@ -12,6 +12,7 @@ #include "GrResourceHandle.h" #include "GrVkDescriptorPool.h" #include "GrVkPipelineState.h" +#include "GrVkRenderPass.h" #include "GrVkResource.h" #include "GrVkUtil.h" #include "SkTArray.h" @@ -27,7 +28,6 @@ class GrTextureParams; class GrVkCommandBuffer; class GrVkGpu; class GrVkPipeline; -class GrVkRenderPass; class GrVkRenderTarget; class GrVkSampler; @@ -59,21 +59,23 @@ public: // findCompatibleRenderPass(GrVkRenderTarget&, CompatibleRPHandle*). const GrVkRenderPass* findCompatibleRenderPass(const CompatibleRPHandle& compatibleHandle); -#if 0 - // TODO: + // Finds or creates a render pass that matches the target and LoadStoreOps, increments the + // refcount, and returns. The caller can optionally pass in a pointer to a CompatibleRPHandle. + // If this is non null it will be set to a handle that can be used in the furutre to quickly + // return a GrVkRenderPasses without the need inspecting a GrVkRenderTarget. const GrVkRenderPass* findRenderPass(const GrVkRenderTarget& target, - VkAttachmentLoadOp colorLoad, - VkAttachmentStoreOp colorStore, - VkAttachmentLoadOp stencilLoad, - VkAttachmentStoreOp stencilStore, + const GrVkRenderPass::LoadStoreOps& colorOps, + const GrVkRenderPass::LoadStoreOps& resolveOps, + const GrVkRenderPass::LoadStoreOps& stencilOps, CompatibleRPHandle* compatibleHandle = nullptr); + // The CompatibleRPHandle must be a valid handle previously set by a call to findRenderPass or + // findCompatibleRenderPass. const GrVkRenderPass* findRenderPass(const CompatibleRPHandle& compatibleHandle, - VkAttachmentLoadOp colorLoad, - VkAttachmentStoreOp colorStore, - VkAttachmentLoadOp stencilLoad, - VkAttachmentStoreOp stencilStore); -#endif + const GrVkRenderPass::LoadStoreOps& colorOps, + const GrVkRenderPass::LoadStoreOps& resolveOps, + const GrVkRenderPass::LoadStoreOps& stencilOps); + GrVkCommandBuffer* createCommandBuffer(); void checkCommandBuffers(); @@ -175,6 +177,11 @@ private: return fRenderPasses[0]; } + GrVkRenderPass* getRenderPass(const GrVkGpu* gpu, + const GrVkRenderPass::LoadStoreOps& colorOps, + const GrVkRenderPass::LoadStoreOps& resolveOps, + const GrVkRenderPass::LoadStoreOps& stencilOps); + void releaseResources(const GrVkGpu* gpu); void abandonResources();