From b3c5c88c61d6765aac052afc0e5b685719802441 Mon Sep 17 00:00:00 2001 From: David Steele Date: Tue, 9 Jul 2024 19:02:55 +0100 Subject: [PATCH] Implementing basic render pass through graphics API Rather than relying on test code in PresentRenderTarget, this instead sets up basic command buffers properly, and expects Begin, BeginRenderPass, EndRenderPass, End commands, Controller::SubmitCommandBuffers and ::PresentRenderTarget to work in the right way. Suggested test code is to create an empty app with a single actor/renderer pair that has a RenderCallback attached. Change-Id: I828f37aa704bacd18487d9c0a516051b91f6e5fd --- automated-tests/.gitignore | 3 +- .../.gitignore-with-autogenerated-files | 1 + .../.gitignore-without-autogenerated-files | 1 + .../adaptor-framework/render-surface-interface.h | 2 +- .../common/combined-update-render-controller.cpp | 4 +- .../graphics/vulkan-impl/vulkan-command-buffer.cpp | 90 ++++++---- .../graphics/vulkan-impl/vulkan-command-buffer.h | 16 ++ .../vulkan-impl/vulkan-framebuffer-impl.cpp | 72 +++++--- .../graphics/vulkan-impl/vulkan-framebuffer-impl.h | 24 ++- .../graphics/vulkan-impl/vulkan-framebuffer.cpp | 32 ++-- .../vulkan-impl/vulkan-graphics-controller.cpp | 58 +++--- .../vulkan-impl/vulkan-render-pass-impl.cpp | 194 ++++++++++----------- .../graphics/vulkan-impl/vulkan-render-pass-impl.h | 43 ++++- .../graphics/vulkan-impl/vulkan-render-pass.cpp | 50 +----- .../graphics/vulkan-impl/vulkan-render-pass.h | 41 ++--- .../graphics/vulkan-impl/vulkan-swapchain-impl.cpp | 13 +- dali/internal/graphics/vulkan-impl/vulkan-types.h | 123 +++++++++---- 17 files changed, 425 insertions(+), 342 deletions(-) diff --git a/automated-tests/.gitignore b/automated-tests/.gitignore index 34dc85b..3ada789 100644 --- a/automated-tests/.gitignore +++ b/automated-tests/.gitignore @@ -2,4 +2,5 @@ build build.log tct*core.h -results_xml.* \ No newline at end of file +results_xml.* +/CMakeLists.txt diff --git a/automated-tests/.gitignore-with-autogenerated-files b/automated-tests/.gitignore-with-autogenerated-files index f039d8a..c80740e 100644 --- a/automated-tests/.gitignore-with-autogenerated-files +++ b/automated-tests/.gitignore-with-autogenerated-files @@ -2,3 +2,4 @@ build build.log tct*core.h +/CMakeLists.txt \ No newline at end of file diff --git a/automated-tests/.gitignore-without-autogenerated-files b/automated-tests/.gitignore-without-autogenerated-files index 8f3f9e2..1680e0e 100644 --- a/automated-tests/.gitignore-without-autogenerated-files +++ b/automated-tests/.gitignore-without-autogenerated-files @@ -1,3 +1,4 @@ *.xml build build.log +/CMakeLists.txt \ No newline at end of file diff --git a/dali/integration-api/adaptor-framework/render-surface-interface.h b/dali/integration-api/adaptor-framework/render-surface-interface.h index 7747374..e5ffe8f 100644 --- a/dali/integration-api/adaptor-framework/render-surface-interface.h +++ b/dali/integration-api/adaptor-framework/render-surface-interface.h @@ -260,7 +260,7 @@ private: protected: Dali::Internal::Adaptor::AdaptorInternalServices* mAdaptor; - Dali::Graphics::GraphicsInterface* mGraphics; + Dali::Graphics::GraphicsInterface* mGraphics; Dali::DisplayConnection* mDisplayConnection; WeakHandle mScene; bool mFullSwapNextFrame; ///< Whether the full surface swap is required diff --git a/dali/internal/adaptor/common/combined-update-render-controller.cpp b/dali/internal/adaptor/common/combined-update-render-controller.cpp index 30ca2dc..85d5cb9 100644 --- a/dali/internal/adaptor/common/combined-update-render-controller.cpp +++ b/dali/internal/adaptor/common/combined-update-render-controller.cpp @@ -545,7 +545,7 @@ void CombinedUpdateRenderController::UpdateRenderThread() NotifyGraphicsInitialised(); - //@todo Vk swaps this around, but we need to support surfaceless context for multi-window + // Generate swapchains if needed graphics.ConfigureSurface(mAdaptorInterfaces.GetRenderSurfaceInterface()); // Tell core it has a context @@ -777,7 +777,7 @@ void CombinedUpdateRenderController::UpdateRenderThread() AddPerformanceMarker(PerformanceInterface::RENDER_START); TRACE_UPDATE_RENDER_BEGIN("DALI_RENDER"); - // Upload shared resources + // Upload shared resources and process render messages TRACE_UPDATE_RENDER_BEGIN("DALI_PRE_RENDER"); mCore.PreRender(renderStatus, mForceClear); TRACE_UPDATE_RENDER_END("DALI_PRE_RENDER"); diff --git a/dali/internal/graphics/vulkan-impl/vulkan-command-buffer.cpp b/dali/internal/graphics/vulkan-impl/vulkan-command-buffer.cpp index 274cfdf..c6dd727 100644 --- a/dali/internal/graphics/vulkan-impl/vulkan-command-buffer.cpp +++ b/dali/internal/graphics/vulkan-impl/vulkan-command-buffer.cpp @@ -58,10 +58,27 @@ void CommandBuffer::DiscardResource() void CommandBuffer::Begin(const Graphics::CommandBufferBeginInfo& info) { + if(mCommandBufferImpl) + { + mCommandBufferImpl->Begin(static_cast(info.usage), nullptr); + } } void CommandBuffer::End() { + if(mCommandBufferImpl) + { + mCommandBufferImpl->End(); + } +} + +void CommandBuffer::Reset() +{ + if(mCommandBufferImpl) + { + mCommandBufferImpl->Reset(); + } + mLastSwapchain = nullptr; } void CommandBuffer::BindVertexBuffers(uint32_t firstBinding, @@ -98,59 +115,63 @@ void CommandBuffer::BindIndexBuffer(const Graphics::Buffer& buffer, { } -void CommandBuffer::BeginRenderPass(Graphics::RenderPass* renderPass, - Graphics::RenderTarget* renderTarget, +void CommandBuffer::BeginRenderPass(Graphics::RenderPass* gfxRenderPass, + Graphics::RenderTarget* gfxRenderTarget, Rect2D renderArea, const std::vector& clearValues) { - //@todo Find a better place to auto-insert begin/end. - // mCommandBufferImpl->Begin(vk::CommandBufferUsageFlagBits::eOneTimeSubmit, nullptr ); - - auto vulkanRenderPass = static_cast(renderPass); - auto vulkanRenderTarget = static_cast(renderTarget); - auto surface = vulkanRenderTarget->GetSurface(); - auto& device = mController.GetGraphicsDevice(); + auto renderPass = static_cast(gfxRenderPass); + auto renderTarget = static_cast(gfxRenderTarget); + auto surface = renderTarget->GetSurface(); + auto& device = mController.GetGraphicsDevice(); FramebufferImpl* framebuffer; - vk::RenderPass vkRenderPass; + RenderPassImpl* renderPassImpl; if(surface) { auto window = static_cast(surface); auto surfaceId = window->GetSurfaceId(); auto swapchain = device.GetSwapchainForSurfaceId(surfaceId); + mLastSwapchain = swapchain; framebuffer = swapchain->GetCurrentFramebuffer(); - vkRenderPass = framebuffer->GetRenderPass(); + renderPassImpl = framebuffer->GetRenderPass(renderPass); } else { - auto coreFramebuffer = vulkanRenderTarget->GetFramebuffer(); + auto coreFramebuffer = renderTarget->GetFramebuffer(); framebuffer = coreFramebuffer->GetImpl(); - vkRenderPass = vulkanRenderPass->GetImpl()->GetVkHandle(); + renderPassImpl = framebuffer->GetRenderPass(renderPass); } std::vector vkClearValues; - for(auto clearValue : clearValues) + + auto attachments = renderPass->GetCreateInfo().attachments; + if(attachments != nullptr && + !attachments->empty() && + attachments->front().loadOp == Graphics::AttachmentLoadOp::CLEAR) { - vk::ClearColorValue color; - color.float32[0] = clearValue.color.r; - color.float32[1] = clearValue.color.g; - color.float32[2] = clearValue.color.b; - color.float32[3] = clearValue.color.a; - vkClearValues.emplace_back(color); + for(auto clearValue : clearValues) + { + vk::ClearColorValue color; + color.float32[0] = clearValue.color.r; + color.float32[1] = clearValue.color.g; + color.float32[2] = clearValue.color.b; + color.float32[3] = clearValue.color.a; + vkClearValues.emplace_back(color); + } } - /** - mCommandBufferImpl->BeginRenderPass( vk::RenderPassBeginInfo{} - .setFramebuffer( framebuffer->GetVkHandle() ) - .setRenderPass( vkRenderPass ) - .setRenderArea( { {0, 0}, { renderArea.width, renderArea.height } } ) - .setPClearValues( vkClearValues.data() ) - .setClearValueCount( uint32_t(framebuffer->GetClearValues().size()) ), - vk::SubpassContents::eInline ); -*/ + + mCommandBufferImpl->BeginRenderPass(vk::RenderPassBeginInfo{} + .setFramebuffer(framebuffer->GetVkHandle()) + .setRenderPass(renderPassImpl->GetVkHandle()) + .setRenderArea({{0, 0}, {renderArea.width, renderArea.height}}) + .setPClearValues(vkClearValues.data()) + .setClearValueCount(uint32_t(framebuffer->GetClearValues().size())), + vk::SubpassContents::eInline); } void CommandBuffer::EndRenderPass(Graphics::SyncObject* syncObject) { - // mCommandBufferImpl->EndRenderPass(); + mCommandBufferImpl->EndRenderPass(); } void CommandBuffer::ExecuteCommandBuffers(std::vector&& commandBuffers) @@ -183,10 +204,6 @@ void CommandBuffer::DrawNative(const DrawNativeInfo* drawInfo) { } -void CommandBuffer::Reset() -{ -} - void CommandBuffer::SetScissor(Rect2D value) { } @@ -247,4 +264,9 @@ void CommandBuffer::SetDepthWriteEnable(bool depthWriteEnable) { } +Swapchain* CommandBuffer::GetLastSwapchain() const +{ + return mLastSwapchain; +} + } // namespace Dali::Graphics::Vulkan diff --git a/dali/internal/graphics/vulkan-impl/vulkan-command-buffer.h b/dali/internal/graphics/vulkan-impl/vulkan-command-buffer.h index ba73457..5bad086 100644 --- a/dali/internal/graphics/vulkan-impl/vulkan-command-buffer.h +++ b/dali/internal/graphics/vulkan-impl/vulkan-command-buffer.h @@ -24,6 +24,7 @@ namespace Dali::Graphics::Vulkan { class CommandBufferImpl; +class Swapchain; using CommandBufferResource = Resource; @@ -337,8 +338,23 @@ public: */ void SetDepthWriteEnable(bool depthWriteEnable) override; +public: //API + /** + * Get the last swapchain referenced by a BeginRenderPass command in this command buffer. + * + * @todo Should split the command buffer up into multiple buffers if there is more than one + * render target referenced in it. + */ + Swapchain* GetLastSwapchain() const; + + CommandBufferImpl* GetImpl() const + { + return mCommandBufferImpl; + } + private: CommandBufferImpl* mCommandBufferImpl; + Swapchain* mLastSwapchain{nullptr}; }; } // namespace Dali::Graphics::Vulkan diff --git a/dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.cpp b/dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.cpp index c0b8cdd..4810bf3 100644 --- a/dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.cpp +++ b/dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -122,11 +124,12 @@ FramebufferImpl* FramebufferImpl::New( std::vector& attachments, uint32_t width, uint32_t height, - bool hasDepthAttachments, - bool takeRenderPassOwnership) + bool hasDepthAttachments) { std::vector imageViewAttachments; + DALI_ASSERT_ALWAYS(renderPass != nullptr && "You require more render passes!"); + std::transform(attachments.cbegin(), attachments.cend(), std::back_inserter(imageViewAttachments), @@ -142,11 +145,10 @@ FramebufferImpl* FramebufferImpl::New( return new FramebufferImpl(device, attachments, vkFramebuffer, - renderPass->GetVkHandle(), + *renderPass, width, height, - hasDepthAttachments, - takeRenderPassOwnership); + hasDepthAttachments); } FramebufferImpl* FramebufferImpl::New( @@ -183,11 +185,10 @@ FramebufferImpl* FramebufferImpl::New( auto attachments = std::vector{}; // Flag that indicates if the render pass is externally provided - bool renderPassTakeOwnership = false; if(renderPass == nullptr) { - renderPass = RenderPassImpl::New(device, colorAttachments, depthAttachment); - renderPassTakeOwnership = true; + // Create compatible render pass + renderPass = RenderPassImpl::New(device, colorAttachments, depthAttachment); } attachments.reserve(colorAttachments.size()); attachments.insert(attachments.begin(), colorAttachments.begin(), colorAttachments.end()); @@ -195,26 +196,24 @@ FramebufferImpl* FramebufferImpl::New( { attachments.push_back(depthAttachment); } - return FramebufferImpl::New(device, renderPass, attachments, width, height, hasDepth, renderPassTakeOwnership); + return FramebufferImpl::New(device, renderPass, attachments, width, height, hasDepth); } FramebufferImpl::FramebufferImpl(Device& graphicsDevice, const std::vector& attachments, vk::Framebuffer vkHandle, - vk::RenderPass renderPass, + const RenderPassImpl& renderPassImpl, uint32_t width, uint32_t height, - bool hasDepthAttachment, - bool takeRenderPassOwnership) + bool hasDepthAttachment) : mGraphicsDevice(&graphicsDevice), mWidth(width), mHeight(height), mAttachments(attachments), mFramebuffer(vkHandle), - mRenderPass(renderPass), - mHasDepthAttachment(hasDepthAttachment), - mRenderPassOwned(takeRenderPassOwnership) + mHasDepthAttachment(hasDepthAttachment) { + mRenderPasses.push_back(RenderPassMapElement{nullptr, const_cast(&renderPassImpl)}); } uint32_t FramebufferImpl::GetWidth() const @@ -303,9 +302,42 @@ uint32_t FramebufferImpl::GetAttachmentCount(AttachmentType type) const return 0u; } -vk::RenderPass FramebufferImpl::GetRenderPass() const +RenderPassImpl* FramebufferImpl::GetRenderPass(RenderPass* renderPass) { - return mRenderPass; + auto attachments = renderPass->GetCreateInfo().attachments; + auto matchLoadOp = attachments->front().loadOp; + auto matchStoreOp = attachments->front().storeOp; + + for(auto& element : mRenderPasses) + { + // Test renderpass first + if(element.renderPass != nullptr) + { + auto firstAttachment = element.renderPass->GetCreateInfo().attachments->front(); + if(firstAttachment.loadOp == matchLoadOp && + firstAttachment.storeOp == matchStoreOp) + { + return element.renderPassImpl; + } + } + else + { + DALI_ASSERT_DEBUG(element.renderPassImpl != nullptr && "Render pass list doesn't contain impl"); + auto createInfo = element.renderPassImpl->GetCreateInfo(); + + if(createInfo.attachmentDescriptions[0].loadOp == VkLoadOpType(matchLoadOp).loadOp && + createInfo.attachmentDescriptions[0].storeOp == VkStoreOpType(matchStoreOp).storeOp) + { + // Point at passed in render pass... should be a weak ptr... What's lifecycle?! + element.renderPass = renderPass; + return element.renderPassImpl; + } + } + } + + // @todo create new render pass from existing + load/store op, add it to mRenderPasses, and return it. + + return mRenderPasses[0].renderPassImpl; } vk::Framebuffer FramebufferImpl::GetVkHandle() const @@ -333,7 +365,8 @@ bool FramebufferImpl::OnDestroy() auto device = mGraphicsDevice->GetLogicalDevice(); auto frameBuffer = mFramebuffer; - vk::RenderPass renderPass = mRenderPassOwned ? mRenderPass : vk::RenderPass{}; + ///@todo Destroy all render passes. + vk::RenderPass renderPass = mRenderPasses[0].renderPassImpl->GetVkHandle(); auto allocator = &mGraphicsDevice->GetAllocator(); @@ -346,8 +379,7 @@ bool FramebufferImpl::OnDestroy() { DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: render pass->%p\n", static_cast(renderPass)) device.destroyRenderPass(renderPass, allocator); - } - }); + } }); return false; } diff --git a/dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.h b/dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.h index e0ccee5..bcf567d 100644 --- a/dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.h +++ b/dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.h @@ -22,6 +22,7 @@ namespace Dali::Graphics::Vulkan { +class RenderPass; class RenderPassImpl; enum class AttachmentType @@ -85,8 +86,7 @@ public: std::vector& attachments, uint32_t width, uint32_t height, - bool hasDepthAttachment, - bool takeRenderPassOwnership); + bool hasDepthAttachment); static FramebufferImpl* New( Vulkan::Device& device, @@ -99,11 +99,10 @@ public: FramebufferImpl(Device& graphicsDevice, const std::vector& attachments, vk::Framebuffer vkHandle, - vk::RenderPass renderPass, + const RenderPassImpl& renderPass, uint32_t width, uint32_t height, - bool hasDepthAttachment, - bool takeRenderPassOwnership); + bool hasDepthAttachment); [[nodiscard]] uint32_t GetWidth() const; @@ -115,7 +114,7 @@ public: [[nodiscard]] uint32_t GetAttachmentCount(AttachmentType type) const; - [[nodiscard]] vk::RenderPass GetRenderPass() const; + [[nodiscard]] RenderPassImpl* GetRenderPass(RenderPass* renderPass); // May mutate mRenderPasses [[nodiscard]] vk::Framebuffer GetVkHandle() const; @@ -129,11 +128,20 @@ private: uint32_t mWidth; uint32_t mHeight; + /** + * Structure to map RenderPass to RenderPassImpl. + */ + struct RenderPassMapElement + { + RenderPass* renderPass{nullptr}; + RenderPassImpl* renderPassImpl{nullptr}; + }; + using RenderPasses = std::vector; + std::vector mAttachments; vk::Framebuffer mFramebuffer; - vk::RenderPass mRenderPass; + RenderPasses mRenderPasses; bool mHasDepthAttachment{false}; - bool mRenderPassOwned{false}; }; } // Namespace Dali::Graphics::Vulkan diff --git a/dali/internal/graphics/vulkan-impl/vulkan-framebuffer.cpp b/dali/internal/graphics/vulkan-impl/vulkan-framebuffer.cpp index a98e484..bbea6b2 100644 --- a/dali/internal/graphics/vulkan-impl/vulkan-framebuffer.cpp +++ b/dali/internal/graphics/vulkan-impl/vulkan-framebuffer.cpp @@ -39,29 +39,27 @@ Framebuffer::~Framebuffer() = default; bool Framebuffer::InitializeResource() { - /* - * Renderpass handling. - * We get passed VulkanRenderPass - * For actual framebuffer creation, we need at least the first VulkanRenderPass to have a VulkanRenderPassImpl created - * and for subsequent VulkanRenderPasses to be compatible with the first (and can be created on the fly) - */ - // Create attachments - auto renderPass = static_cast(mCreateInfo.renderPasses[0]); - - auto renderPassImpl = renderPass->GetImpl(); // Only generate actual render pass if needed - if(!renderPassImpl) + std::vector colorAttachments; + // for(auto& attachment : mCreateInfo.colorAttachments) { - renderPass->InitializeResource(); + // auto graphicsTexture = static_cast(attachment.texture); + // colorAttachments.push_back(FramebufferAttachment::NewColorAttachment(attachment.texture->GetVkHandle(), clearColor, AttachmentType::COLOR, false); + } + FramebufferAttachment* depthStencilAttachment{nullptr}; + if(mCreateInfo.depthStencilAttachment.depthTexture || mCreateInfo.depthStencilAttachment.stencilTexture) + { + // depthStencilAttachment = FramebufferAttachment::NewDepthAttachment(); } - auto& device = mController.GetGraphicsDevice(); - std::vector colorAttachments; - FramebufferAttachment* depthStencilAttachment{nullptr}; - //@todo FINISH ME! (Needs texture -> image view bindings) + // Create initial render pass. + auto renderPassImpl = RenderPassImpl::New(mController.GetGraphicsDevice(), + colorAttachments, + depthStencilAttachment); + + auto& device = mController.GetGraphicsDevice(); mFramebufferImpl = FramebufferImpl::New(device, renderPassImpl, colorAttachments, depthStencilAttachment, mCreateInfo.size.width, mCreateInfo.size.height); - //@todo Store all the render passes here. Will be used later to generate compatible render pass impls. return true; } diff --git a/dali/internal/graphics/vulkan-impl/vulkan-graphics-controller.cpp b/dali/internal/graphics/vulkan-impl/vulkan-graphics-controller.cpp index 3696eaa..8f808e8 100644 --- a/dali/internal/graphics/vulkan-impl/vulkan-graphics-controller.cpp +++ b/dali/internal/graphics/vulkan-impl/vulkan-graphics-controller.cpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace Dali::Graphics::Vulkan { @@ -121,7 +122,7 @@ struct VulkanGraphicsController::Impl void AcquireNextFramebuffer() { - // for all swapchains acquire new framebuffer + // @todo for all swapchains acquire new framebuffer auto surface = mGraphicsDevice->GetSurface(0u); auto swapchain = mGraphicsDevice->GetSwapchainForSurfaceId(0u); @@ -168,33 +169,31 @@ Integration::GraphicsConfig& VulkanGraphicsController::GetGraphicsConfig() return *this; } +void VulkanGraphicsController::FrameStart() +{ + mImpl->mCapacity = 0; + mImpl->AcquireNextFramebuffer(); +} + void VulkanGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo) { + // Figure out where to submit each command buffer. + for(auto gfxCmdBuffer : submitInfo.cmdBuffer) + { + auto cmdBuffer = static_cast(gfxCmdBuffer); + auto swapchain = cmdBuffer->GetLastSwapchain(); + if(swapchain) + { + swapchain->Submit(cmdBuffer->GetImpl()); + } + } } void VulkanGraphicsController::PresentRenderTarget(Graphics::RenderTarget* renderTarget) { - // Test code to create a render pass to clear the surface - mImpl->AcquireNextFramebuffer(); - - auto swapchain = mImpl->mGraphicsDevice->GetSwapchainForSurfaceId(0u); - - CommandPool* commandPool = mImpl->mGraphicsDevice->GetCommandPool(std::this_thread::get_id()); - auto primaryCommandBuffer = commandPool->NewCommandBuffer(true); - - primaryCommandBuffer->Begin(vk::CommandBufferUsageFlagBits::eOneTimeSubmit, nullptr); - primaryCommandBuffer->BeginRenderPass(vk::RenderPassBeginInfo{} - .setFramebuffer(swapchain->GetCurrentFramebuffer()->GetVkHandle()) - .setRenderPass(swapchain->GetCurrentFramebuffer()->GetRenderPass()) - .setRenderArea({{0, 0}, {swapchain->GetCurrentFramebuffer()->GetWidth(), swapchain->GetCurrentFramebuffer()->GetHeight()}}) - .setPClearValues(swapchain->GetCurrentFramebuffer()->GetClearValues().data()) - .setClearValueCount(uint32_t(swapchain->GetCurrentFramebuffer()->GetClearValues().size())), - vk::SubpassContents::eInline); - primaryCommandBuffer->EndRenderPass(); - primaryCommandBuffer->End(); - - // Submit command buffer - swapchain->Submit(primaryCommandBuffer); + auto surface = static_cast(renderTarget)->GetSurface(); + auto surfaceId = static_cast(surface)->GetSurfaceId(); + auto swapchain = mImpl->mGraphicsDevice->GetSwapchainForSurfaceId(surfaceId); swapchain->Present(); } @@ -265,15 +264,9 @@ UniquePtr VulkanGraphicsController::CreateCommandBuffer UniquePtr VulkanGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, UniquePtr&& oldRenderPass) { - // If this is for a surface, then we already have a render pass hidden inside the swapchain... - // The surface should have a GraphicsSurfaceId, which can be used to get the swapchain. - // But, we want to create multiple render passes in Core on a scene's surface... - // Now, renderPassCreateInfo contains renderTarget, so this implementation can decide to generate - // surface's swapchain framebuffers based on this new renderpass. Though, should be explicit about it! - auto renderPass = NewObject(renderPassCreateInfo, *this, std::move(oldRenderPass)); + auto renderPass = UniquePtr(new Vulkan::RenderPass(renderPassCreateInfo, *this)); - //auto vkRenderPass = static_cast(renderPass.get()); - //vkRenderPass->InitializeResource(); // This may create an actual resource. + // Don't create actual vulkan resource here. It will instead be done on demand. (e.g. framebuffer creation, CommandBuffer::BeginRenderPass()) return renderPass; } @@ -493,11 +486,6 @@ Graphics::UniquePtr VulkanGraphicsController::ReleaseTextureF return texture; } -void VulkanGraphicsController::FrameStart() -{ - mImpl->mCapacity = 0; -} - std::size_t VulkanGraphicsController::GetCapacity() const { return mImpl->mCapacity; diff --git a/dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.cpp b/dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.cpp index 2d3d40a..67a6f1f 100644 --- a/dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.cpp +++ b/dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.cpp @@ -16,8 +16,6 @@ #include -#include - #include #include #include @@ -31,13 +29,57 @@ extern Debug::Filter* gVulkanFilter; namespace Dali::Graphics::Vulkan { -namespace -{ -vk::RenderPass CreateCompatibleRenderPass( + +RenderPassImpl* RenderPassImpl::New( Vulkan::Device& device, const std::vector& colorAttachments, - FramebufferAttachment* depthAttachment, - std::vector& attachments) + FramebufferAttachment* depthAttachment) +{ + auto renderPass = new RenderPassImpl(device, colorAttachments, depthAttachment); + return renderPass; +} + +RenderPassImpl::RenderPassImpl(Vulkan::Device& device, + const std::vector& colorAttachments, + FramebufferAttachment* depthAttachment) +: mGraphicsDevice(&device) +{ + CreateCompatibleCreateInfo(colorAttachments, depthAttachment); + CreateRenderPass(); +} + +RenderPassImpl::~RenderPassImpl() = default; + +vk::RenderPass RenderPassImpl::GetVkHandle() +{ + return mVkRenderPass; +} + +bool RenderPassImpl::OnDestroy() +{ + if(mVkRenderPass) + { + auto device = mGraphicsDevice->GetLogicalDevice(); + auto allocator = &mGraphicsDevice->GetAllocator(); + auto renderPass = mVkRenderPass; + mGraphicsDevice->DiscardResource([device, renderPass, allocator]() + { + DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: swap chain->%p\n", static_cast(renderPass)) + device.destroyRenderPass(renderPass, allocator); }); + + mVkRenderPass = nullptr; + } + return false; +} + +std::vector& RenderPassImpl::GetAttachments() +{ + return mAttachments; +} + +void RenderPassImpl::CreateCompatibleCreateInfo( + const std::vector& colorAttachments, + FramebufferAttachment* depthAttachment) { auto hasDepth = false; if(depthAttachment) @@ -48,16 +90,14 @@ vk::RenderPass CreateCompatibleRenderPass( // The total number of attachments auto totalAttachmentCount = hasDepth ? colorAttachments.size() + 1 : colorAttachments.size(); - attachments.clear(); - attachments.reserve(totalAttachmentCount); + mAttachments.clear(); + mAttachments.reserve(totalAttachmentCount); // This vector stores the attachment references - auto colorAttachmentReferences = std::vector{}; - colorAttachmentReferences.reserve(colorAttachments.size()); + mCreateInfo.colorAttachmentReferences.reserve(colorAttachments.size()); // This vector stores the attachment descriptions - auto attachmentDescriptions = std::vector{}; - attachmentDescriptions.reserve(totalAttachmentCount); + mCreateInfo.attachmentDescriptions.reserve(totalAttachmentCount); // For each color attachment... for(auto i = 0u; i < colorAttachments.size(); ++i) @@ -76,15 +116,14 @@ vk::RenderPass CreateCompatibleRenderPass( assert(imageLayout == vk::ImageLayout::eColorAttachmentOptimal); // Add a reference and a descriptions and image views to their respective vectors - colorAttachmentReferences.push_back(vk::AttachmentReference{}.setLayout(imageLayout).setAttachment(U32(i))); + mCreateInfo.colorAttachmentReferences.push_back(vk::AttachmentReference{}.setLayout(imageLayout).setAttachment(U32(i))); - attachmentDescriptions.push_back(colorAttachments[i]->GetDescription()); + mCreateInfo.attachmentDescriptions.push_back(colorAttachments[i]->GetDescription()); - attachments.push_back(colorAttachments[i]->GetImageView()->GetVkHandle()); + mAttachments.push_back(colorAttachments[i]->GetImageView()->GetVkHandle()); } // Follow the exact same procedure as color attachments - auto depthAttachmentReference = vk::AttachmentReference{}; if(hasDepth) { auto imageLayout = depthAttachment->GetImageView()->GetImage()->GetImageLayout(); @@ -96,107 +135,54 @@ vk::RenderPass CreateCompatibleRenderPass( assert(imageLayout == vk::ImageLayout::eDepthStencilAttachmentOptimal); - depthAttachmentReference.setLayout(imageLayout); - depthAttachmentReference.setAttachment(U32(colorAttachmentReferences.size())); + mCreateInfo.depthAttachmentReference.setLayout(imageLayout); + mCreateInfo.depthAttachmentReference.setAttachment(U32(mCreateInfo.colorAttachmentReferences.size())); - attachmentDescriptions.push_back(depthAttachment->GetDescription()); + mCreateInfo.attachmentDescriptions.push_back(depthAttachment->GetDescription()); - attachments.push_back(depthAttachment->GetImageView()->GetVkHandle()); + mAttachments.push_back(depthAttachment->GetImageView()->GetVkHandle()); } // Creating a single subpass per framebuffer - auto subpassDesc = vk::SubpassDescription{}; - subpassDesc.setPipelineBindPoint(vk::PipelineBindPoint::eGraphics); - subpassDesc.setColorAttachmentCount(U32(colorAttachments.size())); + mCreateInfo.subpassDesc.setPipelineBindPoint(vk::PipelineBindPoint::eGraphics); + mCreateInfo.subpassDesc.setColorAttachmentCount(U32(colorAttachments.size())); if(hasDepth) { - subpassDesc.setPDepthStencilAttachment(&depthAttachmentReference); + mCreateInfo.subpassDesc.setPDepthStencilAttachment(&mCreateInfo.depthAttachmentReference); } - subpassDesc.setPColorAttachments(colorAttachmentReferences.data()); + mCreateInfo.subpassDesc.setPColorAttachments(mCreateInfo.colorAttachmentReferences.data()); // Creating 2 subpass dependencies using VK_SUBPASS_EXTERNAL to leverage the implicit image layout // transitions provided by the driver - std::array subpassDependencies{ - - vk::SubpassDependency{}.setSrcSubpass(VK_SUBPASS_EXTERNAL).setDstSubpass(0).setSrcStageMask(vk::PipelineStageFlagBits::eBottomOfPipe).setDstStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput).setSrcAccessMask(vk::AccessFlagBits::eMemoryRead).setDstAccessMask(vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite).setDependencyFlags(vk::DependencyFlagBits::eByRegion), - - vk::SubpassDependency{}.setSrcSubpass(0).setDstSubpass(VK_SUBPASS_EXTERNAL).setSrcStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput).setDstStageMask(vk::PipelineStageFlagBits::eBottomOfPipe).setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite).setDstAccessMask(vk::AccessFlagBits::eMemoryRead).setDependencyFlags(vk::DependencyFlagBits::eByRegion) - - }; - - // Create the render pass - auto renderPassCreateInfo = vk::RenderPassCreateInfo{}.setAttachmentCount(U32(attachmentDescriptions.size())).setPAttachments(attachmentDescriptions.data()).setPSubpasses(&subpassDesc).setSubpassCount(1).setPDependencies(subpassDependencies.data()); - - auto vkRenderPass = VkAssert(device.GetLogicalDevice().createRenderPass(renderPassCreateInfo, device.GetAllocator())); - return vkRenderPass; -} - -} // namespace - -RenderPassImpl* RenderPassImpl::New( - Vulkan::Device& device, - const std::vector& colorAttachments, - FramebufferAttachment* depthAttachment) -{ - std::vector attachments{}; - auto vkRenderPass = CreateCompatibleRenderPass(device, colorAttachments, depthAttachment, attachments); - - auto renderPass = new RenderPassImpl(device, vkRenderPass); - renderPass->SetAttachments(attachments); - return renderPass; -} - -RenderPassImpl::RenderPassImpl(Vulkan::Device& device, vk::RenderPass renderPass) -: mGraphicsDevice(&device), - mVkRenderPass(renderPass) -{ -} - -RenderPassImpl::RenderPassImpl( - Vulkan::Device& device, - const Graphics::RenderPassCreateInfo& createInfo, - std::vector& colorAttachments, - FramebufferAttachment* depthAttachment) -: mGraphicsDevice(&device) -{ - // @todo Do mostly as CreateCompatibleRenderPass above, but instead, get the attachment - // descriptions from the createInfo passed in here. - mVkRenderPass = CreateCompatibleRenderPass(*mGraphicsDevice, colorAttachments, depthAttachment, mAttachments); -} - -RenderPassImpl::~RenderPassImpl() = default; - -vk::RenderPass RenderPassImpl::GetVkHandle() -{ - return mVkRenderPass; -} - -bool RenderPassImpl::OnDestroy() -{ - if(mVkRenderPass) - { - auto device = mGraphicsDevice->GetLogicalDevice(); - auto allocator = &mGraphicsDevice->GetAllocator(); - auto renderPass = mVkRenderPass; - mGraphicsDevice->DiscardResource([device, renderPass, allocator]() - { - DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: swap chain->%p\n", static_cast(renderPass)) - device.destroyRenderPass(renderPass, allocator); }); - - mVkRenderPass = nullptr; - } - return false; -} - -std::vector& RenderPassImpl::GetAttachments() -{ - return mAttachments; + mCreateInfo.subpassDependencies = { + vk::SubpassDependency{} + .setSrcSubpass(VK_SUBPASS_EXTERNAL) + .setDstSubpass(0) + .setSrcStageMask(vk::PipelineStageFlagBits::eBottomOfPipe) + .setDstStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput) + .setSrcAccessMask(vk::AccessFlagBits::eMemoryRead) + .setDstAccessMask(vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite) + .setDependencyFlags(vk::DependencyFlagBits::eByRegion), + + vk::SubpassDependency{} + .setSrcSubpass(0) + .setDstSubpass(VK_SUBPASS_EXTERNAL) + .setSrcStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput) + .setDstStageMask(vk::PipelineStageFlagBits::eBottomOfPipe) + .setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite) + .setDstAccessMask(vk::AccessFlagBits::eMemoryRead) + .setDependencyFlags(vk::DependencyFlagBits::eByRegion)}; + + mCreateInfo.createInfo.setAttachmentCount(U32(mCreateInfo.attachmentDescriptions.size())) + .setPAttachments(mCreateInfo.attachmentDescriptions.data()) + .setPSubpasses(&mCreateInfo.subpassDesc) + .setSubpassCount(1) + .setPDependencies(mCreateInfo.subpassDependencies.data()); } -void RenderPassImpl::SetAttachments(std::vector& attachments) +void RenderPassImpl::CreateRenderPass() { - // @todo Remove? How can we late bind attachments? Recreate the whole RP? - mAttachments = std::move(attachments); + mVkRenderPass = VkAssert(mGraphicsDevice->GetLogicalDevice().createRenderPass(mCreateInfo.createInfo, mGraphicsDevice->GetAllocator())); } } // namespace Dali::Graphics::Vulkan diff --git a/dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.h b/dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.h index 58630a6..6122634 100644 --- a/dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.h +++ b/dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.h @@ -27,30 +27,63 @@ class Device; class VulkanGraphicsController; class RenderTarget; +/** + * Holder class for Vulkan RenderPass object. + * + * We need a render pass to create a Framebuffer; this can create a + * compatible render pass given the specific attachments. + * + * FramebufferImpl will own it's RenderPassImpl(s), NOT the Graphics::RenderPass + * implementation. + * + * When we want to use the FramebufferImpl (CommandBuffer::BeginRenderPass), then + * we try and match the supplied Graphics::RenderPass to the creating render pass. + * FramebufferImpl will create a separate compatible RenderPassImpl if a matching + * render pass is NOT found. + */ class RenderPassImpl final : public Dali::Graphics::Vulkan::VkManaged { public: + struct CreateInfo + { + std::vector colorAttachmentReferences; + vk::AttachmentReference depthAttachmentReference; + std::vector attachmentDescriptions; + vk::SubpassDescription subpassDesc; + std::array subpassDependencies; + vk::RenderPassCreateInfo createInfo; + }; + static RenderPassImpl* New( Vulkan::Device& device, const std::vector& colorAttachments, FramebufferAttachment* depthAttachment); - RenderPassImpl(Vulkan::Device& device, vk::RenderPass renderPass); - - RenderPassImpl(Vulkan::Device& device, const Graphics::RenderPassCreateInfo& createInfo, std::vector& colorAttachments, FramebufferAttachment* depthAttachment); + RenderPassImpl(Vulkan::Device& device, const std::vector& colorAttachments, FramebufferAttachment* depthAttachment); ~RenderPassImpl() override; vk::RenderPass GetVkHandle(); + bool OnDestroy() override; + std::vector& GetAttachments(); - void SetAttachments(std::vector& attachments); + CreateInfo& GetCreateInfo() + { + return mCreateInfo; + } - bool OnDestroy() override; +private: + void CreateCompatibleCreateInfo( + const std::vector& colorAttachments, + FramebufferAttachment* depthAttachment); + + void CreateRenderPass(); private: Device* mGraphicsDevice; + CreateInfo mCreateInfo; vk::RenderPass mVkRenderPass; std::vector mAttachments{}; }; diff --git a/dali/internal/graphics/vulkan-impl/vulkan-render-pass.cpp b/dali/internal/graphics/vulkan-impl/vulkan-render-pass.cpp index b2f8faf..fd8a104 100644 --- a/dali/internal/graphics/vulkan-impl/vulkan-render-pass.cpp +++ b/dali/internal/graphics/vulkan-impl/vulkan-render-pass.cpp @@ -24,54 +24,16 @@ namespace Dali::Graphics::Vulkan { RenderPass::RenderPass(const Graphics::RenderPassCreateInfo& createInfo, VulkanGraphicsController& controller) -: RenderPassResource(createInfo, controller), - mRenderPassImpl(nullptr) +: mCreateInfo(createInfo), + mController(controller) { -} - -RenderPass::~RenderPass() = default; - -bool RenderPass::InitializeResource() -{ - auto renderTarget = static_cast(mCreateInfo.renderTarget); - auto framebuffer = renderTarget->GetFramebuffer(); - if(framebuffer) - { - auto vkFramebuffer = framebuffer->GetImpl(); - - // Note, Vulkan framebuffer can now be used with compatible render passes in vkBeginRenderPass. - // So we can create multiple render passes. - - std::vector colorAttachments = vkFramebuffer->GetAttachments(AttachmentType::COLOR); - ; - std::vector depthAttachment = vkFramebuffer->GetAttachments(AttachmentType::DEPTH_STENCIL); - ; - - mRenderPassImpl = new RenderPassImpl(mController.GetGraphicsDevice(), mCreateInfo, colorAttachments, depthAttachment[0]); - } - else + if(createInfo.attachments) { - // RenderTarget must be a surface. - // Create a new render pass that's compatible with the surface's framebuffer. - // - // Does that mean it has to use the fbo's color attachment? YES. - // I.e. should we generate separate RenderPassImpls for each of the surface's framebuffers? - // GetImpl() then needs bufferIndex + mAttachments.insert(mAttachments.end(), createInfo.attachments->begin(), createInfo.attachments->end()); + mCreateInfo.attachments = &mAttachments; } - return true; } -void RenderPass::DestroyResource() -{ -} - -void RenderPass::DiscardResource() -{ -} - -RenderPassImpl* RenderPass::GetImpl() -{ - return mRenderPassImpl; -} +RenderPass::~RenderPass() = default; } // namespace Dali::Graphics::Vulkan diff --git a/dali/internal/graphics/vulkan-impl/vulkan-render-pass.h b/dali/internal/graphics/vulkan-impl/vulkan-render-pass.h index 897bf4e..e358493 100644 --- a/dali/internal/graphics/vulkan-impl/vulkan-render-pass.h +++ b/dali/internal/graphics/vulkan-impl/vulkan-render-pass.h @@ -20,42 +20,39 @@ #include -#include #include +#include namespace Dali::Graphics::Vulkan { class RenderPassImpl; -using RenderPassResource = Resource; -class RenderPass : public RenderPassResource +/** + * This class represents a set of render pass operations. + * + * This class is not directly associated with a graphics resource, and is not + * responsible for the lifetime of actual vulkan render pass objects. That is + * instead the responsibility of the Framebuffer implementation. + * + * When this render pass is used, the Framebuffer will find or create a compatible + * render pass implementation, and cache it. + */ +class RenderPass : public Graphics::RenderPass { public: RenderPass(const Graphics::RenderPassCreateInfo& createInfo, VulkanGraphicsController& controller); ~RenderPass() override; - /** - * @brief Called when GL resources are destroyed - */ - void DestroyResource() override; - - /** - * @brief Called when initializing the resource - * - * @return True on success - */ - bool InitializeResource() override; - - /** - * @brief Called when UniquePtr<> on client-side dies - */ - void DiscardResource() override; - - RenderPassImpl* GetImpl(); + [[nodiscard]] const Graphics::RenderPassCreateInfo& GetCreateInfo() const + { + return mCreateInfo; + } private: - RenderPassImpl* mRenderPassImpl; + Graphics::RenderPassCreateInfo mCreateInfo; + VulkanGraphicsController& mController; + std::vector mAttachments; }; } // namespace Dali::Graphics::Vulkan diff --git a/dali/internal/graphics/vulkan-impl/vulkan-swapchain-impl.cpp b/dali/internal/graphics/vulkan-impl/vulkan-swapchain-impl.cpp index d9f98f0..53e321a 100644 --- a/dali/internal/graphics/vulkan-impl/vulkan-swapchain-impl.cpp +++ b/dali/internal/graphics/vulkan-impl/vulkan-swapchain-impl.cpp @@ -22,13 +22,6 @@ #include #include -#if 0 -#include -#include -#include -#include -#endif - #include #if defined(DEBUG_ENABLED) @@ -167,8 +160,7 @@ void Swapchain::CreateVkSwapchain( auto presentModes = surface->GetSurfacePresentModes(); auto found = std::find_if(presentModes.begin(), presentModes.end(), - [&](vk::PresentModeKHR mode) - { + [&](vk::PresentModeKHR mode) { return presentMode == mode; }); @@ -394,8 +386,7 @@ bool Swapchain::OnDestroy() auto swapchain = mSwapchainKHR; auto allocator = &mGraphicsDevice.GetAllocator(); - mGraphicsDevice.DiscardResource([device, swapchain, allocator]() - { + mGraphicsDevice.DiscardResource([device, swapchain, allocator]() { DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: swap chain->%p\n", static_cast(swapchain)) device.destroySwapchainKHR(swapchain, allocator); }); diff --git a/dali/internal/graphics/vulkan-impl/vulkan-types.h b/dali/internal/graphics/vulkan-impl/vulkan-types.h index 785fb44..cc31808 100644 --- a/dali/internal/graphics/vulkan-impl/vulkan-types.h +++ b/dali/internal/graphics/vulkan-impl/vulkan-types.h @@ -20,10 +20,11 @@ // EXTERNAL INCLUDES #include -#include -#include #include +#include +#include +#include #include // Ensure we can use this type name safely. @@ -32,7 +33,6 @@ #undef WAYLAND #endif - namespace Dali::Graphics { @@ -40,12 +40,12 @@ namespace { // Default value use to clear the stencil buffer constexpr auto STENCIL_DEFAULT_CLEAR_VALUE = 255u; -} +} // namespace -template< typename T, typename... Args > -std::unique_ptr< T > MakeUnique( Args&& ... args ) +template +std::unique_ptr MakeUnique(Args&&... args) { - return std::unique_ptr< T >( new T( std::forward< Args >( args )... ) ); + return std::unique_ptr(new T(std::forward(args)...)); } namespace Vulkan @@ -78,54 +78,54 @@ class Texture; /** * Unique pointers to Vulkan types */ -using UniqueQueue = std::unique_ptr< Queue >; +using UniqueQueue = std::unique_ptr; /** * Reference wrappers */ -using QueueRef = std::reference_wrapper< Queue >; +using QueueRef = std::reference_wrapper; -template< typename T > -T VkAssert( const vk::ResultValue< T >& result, vk::Result expected = vk::Result::eSuccess ) +template +T VkAssert(const vk::ResultValue& result, vk::Result expected = vk::Result::eSuccess) { - assert( result.result == expected ); + assert(result.result == expected); return result.value; } -inline vk::Result VkAssert( vk::Result result, vk::Result expected = vk::Result::eSuccess ) +inline vk::Result VkAssert(vk::Result result, vk::Result expected = vk::Result::eSuccess) { - assert( result == expected ); + assert(result == expected); return result; } -inline vk::Result VkTest( vk::Result result, vk::Result expected = vk::Result::eSuccess ) +inline vk::Result VkTest(vk::Result result, vk::Result expected = vk::Result::eSuccess) { // todo: log if result different than expected? return result; } -template< typename T > -inline uint32_t U32( T value ) +template +inline uint32_t U32(T value) { - return static_cast< uint32_t >(value); + return static_cast(value); } -template -inline int32_t I32( T value ) +template +inline int32_t I32(T value) { - return static_cast< int32_t >( value ); + return static_cast(value); } -template -inline float F32( T value ) +template +inline float F32(T value) { - return static_cast< float >( value ); + return static_cast(value); } -template -inline double F64( T value ) +template +inline double F64(T value) { - return static_cast< double >( value ); + return static_cast(value); } enum class Platform @@ -136,22 +136,72 @@ enum class Platform WAYLAND, }; +struct VkLoadOpType +{ + constexpr explicit VkLoadOpType(Graphics::AttachmentLoadOp op) + { + switch(op) + { + case Graphics::AttachmentLoadOp::LOAD: + { + loadOp = vk::AttachmentLoadOp::eLoad; + break; + } + case Graphics::AttachmentLoadOp::CLEAR: + { + loadOp = vk::AttachmentLoadOp::eClear; + break; + } + case Graphics::AttachmentLoadOp::DONT_CARE: + { + loadOp = vk::AttachmentLoadOp::eDontCare; + break; + } + } + } + vk::AttachmentLoadOp loadOp{vk::AttachmentLoadOp::eDontCare}; +}; + +struct VkStoreOpType +{ + constexpr explicit VkStoreOpType(Graphics::AttachmentStoreOp op) + { + switch(op) + { + case Graphics::AttachmentStoreOp::STORE: + { + Assign(vk::AttachmentStoreOp::eStore); + break; + } + case Graphics::AttachmentStoreOp::DONT_CARE: + { + Assign(vk::AttachmentStoreOp::eDontCare); + break; + } + } + } + constexpr inline void Assign(vk::AttachmentStoreOp op) + { + storeOp = op; + } + vk::AttachmentStoreOp storeOp{vk::AttachmentStoreOp::eDontCare}; +}; + class VkManaged { public: - VkManaged() = default; virtual ~VkManaged() = default; void Release() { - OnRelease( --mRefCount ); + OnRelease(--mRefCount); - if( mRefCount == 0 ) + if(mRefCount == 0) { // orphaned - if( !Destroy() ) + if(!Destroy()) { delete this; } @@ -160,7 +210,7 @@ public: void Retain() { - OnRetain( ++mRefCount ); + OnRetain(++mRefCount); } uint32_t GetRefCount() @@ -173,11 +223,11 @@ public: return OnDestroy(); } - virtual void OnRetain( uint32_t refcount ) + virtual void OnRetain(uint32_t refcount) { } - virtual void OnRelease( uint32_t refcount ) + virtual void OnRelease(uint32_t refcount) { } @@ -187,13 +237,10 @@ public: } private: - - std::atomic_uint mRefCount{ 0u }; + std::atomic_uint mRefCount{0u}; }; - } // namespace Vulkan } // namespace Dali::Graphics - #endif // DALI_GRAPHICS_VULKAN_TYPES -- 2.7.4