Vulkan resource lifecycle management 68/316868/7
authorDavid Steele <david.steele@samsung.com>
Wed, 28 Aug 2024 16:18:56 +0000 (17:18 +0100)
committerDavid Steele <david.steele@samsung.com>
Mon, 30 Sep 2024 16:57:25 +0000 (17:57 +0100)
For Vulkan implementation of graphics resources:
  Added discard queue, that's cleaned down during Flush().

Added ResourceWithDeleter as a secondary interface on top of ResourceBase, to allow
Program/Pipeline to inherit solely from ResourceBase, and not have to utilize the
same resource deleters that the main graphics objects require.

Removed VkResource inheritance completely from Impl classes.
Kept VkResource as VkSharedResource, as we may still use this on RenderPassImpl

All Impl classes now have a public Destroy method which is called from their
destructor, but may also be called earlier if needed. Note, CommandBuffers should
not be deleted directly, but instead returned to the command pool for re-use.

Implemented owned containers for some Impl objects using
std::unique_ptr. Framebuffer owns it's attachments, Swapchain owns
it's framebuffers.

Change-Id: I651ed4d041cd2fb3e7698304eeede66625031945

47 files changed:
dali/internal/graphics/vulkan-impl/vulkan-buffer-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-buffer-impl.h
dali/internal/graphics/vulkan-impl/vulkan-buffer.cpp
dali/internal/graphics/vulkan-impl/vulkan-buffer.h
dali/internal/graphics/vulkan-impl/vulkan-command-buffer-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-command-buffer-impl.h
dali/internal/graphics/vulkan-impl/vulkan-command-buffer.cpp
dali/internal/graphics/vulkan-impl/vulkan-command-buffer.h
dali/internal/graphics/vulkan-impl/vulkan-command-pool-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-command-pool-impl.h
dali/internal/graphics/vulkan-impl/vulkan-fence-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.h
dali/internal/graphics/vulkan-impl/vulkan-framebuffer.cpp
dali/internal/graphics/vulkan-impl/vulkan-framebuffer.h
dali/internal/graphics/vulkan-impl/vulkan-graphics-controller.cpp
dali/internal/graphics/vulkan-impl/vulkan-graphics-controller.h
dali/internal/graphics/vulkan-impl/vulkan-graphics-resource.h
dali/internal/graphics/vulkan-impl/vulkan-image-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-image-impl.h
dali/internal/graphics/vulkan-impl/vulkan-image-view-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-image-view-impl.h
dali/internal/graphics/vulkan-impl/vulkan-memory-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-memory-impl.h
dali/internal/graphics/vulkan-impl/vulkan-pipeline.cpp
dali/internal/graphics/vulkan-impl/vulkan-pipeline.h
dali/internal/graphics/vulkan-impl/vulkan-program.cpp
dali/internal/graphics/vulkan-impl/vulkan-program.h
dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.h
dali/internal/graphics/vulkan-impl/vulkan-render-target.h
dali/internal/graphics/vulkan-impl/vulkan-sampler-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-sampler-impl.h
dali/internal/graphics/vulkan-impl/vulkan-sampler.cpp
dali/internal/graphics/vulkan-impl/vulkan-sampler.h
dali/internal/graphics/vulkan-impl/vulkan-shader-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-shader-impl.h
dali/internal/graphics/vulkan-impl/vulkan-surface-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-surface-impl.h
dali/internal/graphics/vulkan-impl/vulkan-swapchain-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-swapchain-impl.h
dali/internal/graphics/vulkan-impl/vulkan-texture.cpp
dali/internal/graphics/vulkan-impl/vulkan-texture.h
dali/internal/graphics/vulkan-impl/vulkan-types.h
dali/internal/graphics/vulkan/vulkan-device.cpp
dali/internal/graphics/vulkan/vulkan-device.h
dali/internal/graphics/vulkan/vulkan-graphics-impl.cpp

index 48a952d4d0756712a81769de4420c1514bd3593e..1ffcbf6723e62e47b5d00640734caab70ee904dd 100644 (file)
@@ -54,6 +54,11 @@ BufferImpl::BufferImpl(Device& device, const vk::BufferCreateInfo& createInfo)
 {
 }
 
+BufferImpl::~BufferImpl()
+{
+  Destroy();
+}
+
 void BufferImpl::Initialize(vk::MemoryPropertyFlags memoryProperties)
 {
   // Allocate
@@ -84,19 +89,16 @@ void BufferImpl::Initialize(vk::MemoryPropertyFlags memoryProperties)
   }
 }
 
-void BufferImpl::DestroyNow()
+void BufferImpl::Destroy()
 {
-  DestroyVulkanResources(mDevice.GetLogicalDevice(), mBuffer, mMemory->ReleaseVkObject(), &mDevice.GetAllocator());
-  mBuffer = nullptr;
-  mMemory = nullptr;
-}
+  DALI_LOG_INFO(gVulkanFilter, Debug::General, "Destroying buffer: %p\n", static_cast<VkBuffer>(mBuffer));
 
-void BufferImpl::DestroyVulkanResources(vk::Device device, vk::Buffer buffer, vk::DeviceMemory memory, const vk::AllocationCallbacks* allocator)
-{
-  DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: buffer->%p\n", static_cast<VkBuffer>(buffer));
+  auto device = mDevice.GetLogicalDevice();
+  device.destroyBuffer(mBuffer, mDevice.GetAllocator());
 
-  device.destroyBuffer(buffer, allocator);
-  device.freeMemory(memory, allocator);
+  mMemory.reset();
+  mBuffer = nullptr;
+  mMemory = nullptr;
 }
 
 Graphics::MemoryRequirements BufferImpl::GetMemoryRequirements()
index 9e59418d911008f0f30e8254b412c0e4b7ffc311..0a09ef9c0e9da02f72d914c42e64613e055d2351 100644 (file)
 
 #include <dali/graphics-api/graphics-types.h>
 #include <dali/internal/graphics/vulkan-impl/vulkan-memory-impl.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-types.h>
 #include <dali/internal/graphics/vulkan/vulkan-device.h>
 
 #include <cstdint>
 
 namespace Dali::Graphics::Vulkan
 {
-class BufferImpl // : public VkManaged
+class BufferImpl
 {
 public:
   static BufferImpl* New(Vulkan::Device& device, size_t size, vk::BufferUsageFlags usageFlags);
 
   static BufferImpl* New(Vulkan::Device& device, size_t size, vk::SharingMode sharingMode, vk::BufferUsageFlags usageFlags, vk::MemoryPropertyFlags memoryProperties);
 
+  /** Destructor */
+  ~BufferImpl();
+
   /**
    * Returns buffer usage flags
    * @return
@@ -75,7 +79,7 @@ public:
    * @note Calling this function is unsafe and makes any further use of
    * buffer invalid.
    */
-  void DestroyNow();
+  void Destroy();
 
   BufferImpl(const Buffer&)            = delete;
   BufferImpl& operator=(const Buffer&) = delete;
index e725d77d32eb3094f09c966d2ca9037910b7fa68..075f7b700baba7bd42ec9d376a5c69e5d6f2a54d 100644 (file)
 #include <dali/public-api/common/dali-common.h>
 
 // EXTERNAL INCLUDES
-#include <cstdint>
 
 namespace Dali::Graphics::Vulkan
 {
-
 Buffer::Buffer(const Graphics::BufferCreateInfo& createInfo, VulkanGraphicsController& controller)
 : BufferResource(createInfo, controller)
 {
@@ -121,8 +119,7 @@ void Buffer::DestroyResource()
     }
     mBufferPtr = nullptr;
   }
-  // Deestroy GPU allocation
-  else
+  else // Destroy GPU allocation
   {
     delete(mBufferImpl);
     mBufferImpl = nullptr;
index 72caa86415463b8e4463e1bc43451d197f34002c..a6fb0ebb01adbf11c7cd9a69a5e875903e4f7418 100644 (file)
@@ -45,8 +45,6 @@ public:
    * @copydoc Graphics::Vulkan::Resource::InitializeResource();
    */
   bool InitializeResource() override;
-  void InitializeCPUBuffer();
-  void InitializeGPUBuffer();
 
   /**
    * @return false - Vulkan should always allocate GPU buffers
@@ -59,6 +57,23 @@ public:
    */
   void DiscardResource() override;
 
+  /**
+   * @copydoc Graphics::Vulkan::Resource::GetAllocationCallbacks()
+   */
+  [[nodiscard]] const Graphics::AllocationCallbacks* GetAllocationCallbacks() const override
+  {
+    return mCreateInfo.allocationCallbacks;
+  }
+
+  /**
+   * @copydoc Graphics::Vulkan::Resource::InvokeDeleter()
+   * Only intended for use by discard queue.
+   */
+  void InvokeDeleter() override
+  {
+    this->~Buffer();
+  }
+
   void Bind(Graphics::BufferUsage bindingTarget) const;
 
   BufferImpl* GetImpl()
@@ -70,6 +85,10 @@ public:
     return nullptr;
   }
 
+private:
+  void InitializeCPUBuffer();
+  void InitializeGPUBuffer();
+
 private:
   union
   {
index 85e869e1132962e128cf4b778754cc846ed7d6c8..200f3f829ba04578d1dd9ea5e377f18b99db7ade 100644 (file)
@@ -58,7 +58,15 @@ CommandBufferImpl::CommandBufferImpl(CommandPool&                         comman
 {
 }
 
-CommandBufferImpl::~CommandBufferImpl() = default;
+CommandBufferImpl::~CommandBufferImpl()
+{
+  Destroy();
+}
+
+void CommandBufferImpl::Destroy()
+{
+  // Command buffer Pool cleanup will remove the vulkan command buffer
+}
 
 /** Begin recording */
 void CommandBufferImpl::Begin(vk::CommandBufferUsageFlags       usageFlags,
@@ -68,7 +76,6 @@ void CommandBufferImpl::Begin(vk::CommandBufferUsageFlags       usageFlags,
   auto info = vk::CommandBufferBeginInfo{};
 
   vk::CommandBufferInheritanceInfo defaultInheritanceInfo{};
-  defaultInheritanceInfo.sType                = vk::StructureType::eCommandBufferInheritanceInfo;
   defaultInheritanceInfo.pNext                = nullptr;
   defaultInheritanceInfo.subpass              = 0;
   defaultInheritanceInfo.occlusionQueryEnable = false;
@@ -289,12 +296,6 @@ uint32_t CommandBufferImpl::GetPoolAllocationIndex() const
   return mPoolAllocationIndex;
 }
 
-bool CommandBufferImpl::OnDestroy()
-{
-  mOwnerCommandPool->ReleaseCommandBuffer(*this);
-  return true;
-}
-
 void CommandBufferImpl::Draw(uint32_t vertexCount,
                              uint32_t instanceCount,
                              uint32_t firstVertex,
index 5f05d5dd6a86a5429ec0be0e0c2bdc6a56c31ac6..73c0323abf14664250948c2a5a7aabe3a91e0622 100644 (file)
@@ -32,7 +32,7 @@ class Device;
 class CommandPool;
 class PipelineImpl;
 
-class CommandBufferImpl : public VkManaged
+class CommandBufferImpl
 {
   friend class CommandPool;
 
@@ -41,7 +41,9 @@ class CommandBufferImpl : public VkManaged
 public:
   CommandBufferImpl() = delete;
 
-  ~CommandBufferImpl() override;
+  ~CommandBufferImpl();
+
+  void Destroy();
 
   /** Begin recording */
   void Begin(vk::CommandBufferUsageFlags usageFlags, vk::CommandBufferInheritanceInfo* inheritanceInfo);
@@ -101,12 +103,6 @@ public:
 
   void CopyImage(Vulkan::Image* srcImage, vk::ImageLayout srcLayout, Image* dstImage, vk::ImageLayout dstLayout, const std::vector<vk::ImageCopy>& regions);
 
-  /**
-   * Implements VkManaged::OnDestroy
-   * @return
-   */
-  bool OnDestroy() override;
-
   void SetScissor(Rect2D value);
   void SetViewport(Viewport value);
 
index 8d085cf08797747f457878a9433245bdc7dcf58a..1cba175a78257c27db0deeae0587ba57b3666cca 100644 (file)
@@ -61,6 +61,9 @@ CommandBuffer::~CommandBuffer() = default;
 
 void CommandBuffer::DestroyResource()
 {
+  // Don't delete the impl, it's pool allocated and should have been
+  // returned to the command pool for re-use.
+  mCommandBufferImpl = nullptr;
 }
 
 bool CommandBuffer::InitializeResource()
@@ -70,6 +73,7 @@ bool CommandBuffer::InitializeResource()
 
 void CommandBuffer::DiscardResource()
 {
+  mController.DiscardResource(this);
 }
 
 void CommandBuffer::Begin(const Graphics::CommandBufferBeginInfo& info)
index 5bad086886548728a064dd151ec85635b156cfa6..fe6f42510035fb745abccf68d11116e8a6840cf8 100644 (file)
@@ -33,22 +33,6 @@ class CommandBuffer : public CommandBufferResource
 public:
   CommandBuffer(const Graphics::CommandBufferCreateInfo& createInfo, VulkanGraphicsController& controller);
   ~CommandBuffer() 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;
 
   void Begin(const Graphics::CommandBufferBeginInfo& info) override;
 
@@ -338,7 +322,42 @@ public:
    */
   void SetDepthWriteEnable(bool depthWriteEnable) override;
 
-public: //API
+public: // VulkanResource API
+  /**
+   * @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;
+
+  /**
+   * @copydoc Graphics::Vulkan::Resource::GetAllocationCallbacks()
+   */
+  [[nodiscard]] const Graphics::AllocationCallbacks* GetAllocationCallbacks() const override
+  {
+    return mCreateInfo.allocationCallbacks;
+  }
+
+  /**
+   * @copydoc Graphics::Vulkan::Resource::InvokeDeleter()
+   * Only intended for use by discard queue.
+   */
+  void InvokeDeleter() override
+  {
+    this->~CommandBuffer();
+  }
+
+public: // API
   /**
    * Get the last swapchain referenced by a BeginRenderPass command in this command buffer.
    *
index ddc6d04b1be3c29b46800234b4cbea3993e27fdf..8bc279e16a0f5721d427ef1673cff9917e60fa3b 100644 (file)
@@ -19,8 +19,8 @@
 #include <dali/internal/graphics/vulkan-impl/vulkan-command-pool-impl.h>
 
 // INTERNAL INCLUDES
-#include <dali/internal/graphics/vulkan/vulkan-device.h>
 #include <dali/internal/graphics/vulkan-impl/vulkan-command-buffer-impl.h>
+#include <dali/internal/graphics/vulkan/vulkan-device.h>
 
 #include <dali/integration-api/debug.h>
 
@@ -34,47 +34,46 @@ namespace Dali::Graphics::Vulkan
  *
  * Struct: InternalPool
  */
-CommandPool::InternalPool::Node::Node( uint32_t _nextFreeIndex, CommandBufferImpl* _commandBuffer )
-: nextFreeIndex( _nextFreeIndex ),
-  commandBuffer( _commandBuffer )
+CommandPool::InternalPool::Node::Node(uint32_t _nextFreeIndex, CommandBufferImpl* _commandBuffer)
+: nextFreeIndex(_nextFreeIndex),
+  commandBuffer(_commandBuffer)
 {
 }
 
-CommandPool::InternalPool::InternalPool( CommandPool& owner, Vulkan::Device* graphics,
-                                         uint32_t initialCapacity, bool isPrimary )
-: mOwner( owner ),
-  mGraphicsDevice( graphics ),
+CommandPool::InternalPool::InternalPool(CommandPool& owner, Vulkan::Device* graphics, uint32_t initialCapacity, bool isPrimary)
+: mOwner(owner),
+  mGraphicsDevice(graphics),
   mPoolData{},
-  mFirstFree( INVALID_NODE_INDEX ),
-  mCapacity( initialCapacity ),
-  mAllocationCount( 0u ),
-  mIsPrimary( isPrimary )
+  mFirstFree(INVALID_NODE_INDEX),
+  mCapacity(initialCapacity),
+  mAllocationCount(0u),
+  mIsPrimary(isPrimary)
 {
   // don't allocate anything if initial capacity is 0
-  if( initialCapacity )
+  if(initialCapacity)
   {
-    Resize( initialCapacity );
+    Resize(initialCapacity);
   }
 }
 
 CommandPool::InternalPool::~InternalPool()
 {
   // free all buffers here
-  for( auto&& cmd : mPoolData )
+  for(auto&& cmd : mPoolData)
   {
     delete cmd.commandBuffer;
   }
 }
 
-std::vector< vk::CommandBuffer >
-CommandPool::InternalPool::AllocateVkCommandBuffers( vk::CommandBufferAllocateInfo allocateInfo )
+std::vector<vk::CommandBuffer>
+CommandPool::InternalPool::AllocateVkCommandBuffers(vk::CommandBufferAllocateInfo allocateInfo)
 {
-  return VkAssert( mGraphicsDevice->GetLogicalDevice().allocateCommandBuffers( allocateInfo ) );
+  return VkAssert(mGraphicsDevice->GetLogicalDevice().allocateCommandBuffers(allocateInfo));
 }
 
-void CommandPool::InternalPool::Resize( uint32_t newCapacity )
+void CommandPool::InternalPool::Resize(uint32_t newCapacity)
 {
-  if( newCapacity <= mPoolData.size() )
+  if(newCapacity <= mPoolData.size())
   {
     return;
   }
@@ -82,42 +81,42 @@ void CommandPool::InternalPool::Resize( uint32_t newCapacity )
   auto diff = newCapacity - mPoolData.size();
 
   auto allocateInfo = vk::CommandBufferAllocateInfo{}
-          .setCommandBufferCount( U32( diff ) )
-          .setCommandPool( mOwner.GetVkHandle() )
-          .setLevel( mIsPrimary ? vk::CommandBufferLevel::ePrimary : vk::CommandBufferLevel::eSecondary );
-  auto newBuffers = AllocateVkCommandBuffers( allocateInfo );
+                        .setCommandBufferCount(U32(diff))
+                        .setCommandPool(mOwner.GetVkHandle())
+                        .setLevel(mIsPrimary ? vk::CommandBufferLevel::ePrimary : vk::CommandBufferLevel::eSecondary);
+  auto newBuffers = AllocateVkCommandBuffers(allocateInfo);
 
-  uint32_t i = U32( mPoolData.size() + 1 );
+  uint32_t i = U32(mPoolData.size() + 1);
 
-  mFirstFree = U32( mPoolData.size() );
-  if( !mPoolData.empty() )
+  mFirstFree = U32(mPoolData.size());
+  if(!mPoolData.empty())
   {
     mPoolData.back()
-             .nextFreeIndex = U32( mPoolData.size() );
+      .nextFreeIndex = U32(mPoolData.size());
   }
-  for( auto&& cmdbuf : newBuffers )
+  for(auto&& cmdbuf : newBuffers)
   {
-    auto commandBuffer = new CommandBufferImpl( mOwner, i - 1, allocateInfo, cmdbuf );
-    mPoolData.emplace_back( i, commandBuffer );
+    auto commandBuffer = new CommandBufferImpl(mOwner, i - 1, allocateInfo, cmdbuf);
+    mPoolData.emplace_back(i, commandBuffer);
     ++i;
   }
   mPoolData.back().nextFreeIndex = INVALID_NODE_INDEX;
-  mCapacity = U32( mPoolData.size() );
+  mCapacity                      = U32(mPoolData.size());
 }
 
-CommandBufferImpl* CommandPool::InternalPool::AllocateCommandBuffer( bool reset )
+CommandBufferImpl* CommandPool::InternalPool::AllocateCommandBuffer(bool reset)
 {
   // resize if no more nodes
-  if( mFirstFree == INVALID_NODE_INDEX )
+  if(mFirstFree == INVALID_NODE_INDEX)
   {
     auto newSize = static_cast<uint32_t>(mPoolData.empty() ? 1 : 2 * mPoolData.size());
-    Resize( U32( newSize ) );
+    Resize(U32(newSize));
   }
 
   auto& node = mPoolData[mFirstFree];
   mFirstFree = node.nextFreeIndex;
 
-  if( reset )
+  if(reset)
   {
     node.commandBuffer->Reset();
   }
@@ -126,13 +125,13 @@ CommandBufferImpl* CommandPool::InternalPool::AllocateCommandBuffer( bool reset
   return node.commandBuffer;
 }
 
-void CommandPool::InternalPool::ReleaseCommandBuffer(CommandBufferImpl& buffer, bool reset )
+void CommandPool::InternalPool::ReleaseCommandBuffer(CommandBufferImpl& buffer, bool reset)
 {
-  auto indexInPool = buffer.GetPoolAllocationIndex();
+  auto indexInPool                     = buffer.GetPoolAllocationIndex();
   mPoolData[indexInPool].nextFreeIndex = mFirstFree;
-  mFirstFree = indexInPool;
+  mFirstFree                           = indexInPool;
 
-  if( reset )
+  if(reset)
   {
     buffer.Reset();
   }
@@ -149,9 +148,9 @@ uint32_t CommandPool::InternalPool::GetAllocationCount() const
   return mAllocationCount;
 }
 
-CommandPool* CommandPool::New( Device& graphics, const vk::CommandPoolCreateInfo& createInfo )
+CommandPool* CommandPool::New(Device& graphics, const vk::CommandPoolCreateInfo& createInfo)
 {
-  auto pool = new CommandPool( graphics, createInfo );
+  auto pool = new CommandPool(graphics, createInfo);
 
   if(pool)
   {
@@ -161,27 +160,30 @@ CommandPool* CommandPool::New( Device& graphics, const vk::CommandPoolCreateInfo
   return pool;
 }
 
-CommandPool* CommandPool::New( Device& graphics )
+CommandPool* CommandPool::New(Device& graphics)
 {
-  return New( graphics, vk::CommandPoolCreateInfo{} );
+  return New(graphics, vk::CommandPoolCreateInfo{});
 }
 
 bool CommandPool::Initialize()
 {
-  mCreateInfo.setFlags( vk::CommandPoolCreateFlagBits::eResetCommandBuffer );
-  mCommandPool = VkAssert( mGraphicsDevice->GetLogicalDevice().createCommandPool( mCreateInfo, mGraphicsDevice->GetAllocator() ) );
-  mInternalPoolPrimary = std::make_unique< InternalPool >( *this, mGraphicsDevice, 0, true );
-  mInternalPoolSecondary = std::make_unique< InternalPool >( *this, mGraphicsDevice, 0, false );
+  mCreateInfo.setFlags(vk::CommandPoolCreateFlagBits::eResetCommandBuffer);
+  mCommandPool           = VkAssert(mGraphicsDevice->GetLogicalDevice().createCommandPool(mCreateInfo, mGraphicsDevice->GetAllocator()));
+  mInternalPoolPrimary   = std::make_unique<InternalPool>(*this, mGraphicsDevice, 0, true);
+  mInternalPoolSecondary = std::make_unique<InternalPool>(*this, mGraphicsDevice, 0, false);
   return true;
 }
 
-CommandPool::CommandPool( Device& graphics, const vk::CommandPoolCreateInfo& createInfo )
-: mGraphicsDevice( &graphics ),
-  mCreateInfo( createInfo )
+CommandPool::CommandPool(Device& graphics, const vk::CommandPoolCreateInfo& createInfo)
+: mGraphicsDevice(&graphics),
+  mCreateInfo(createInfo)
 {
 }
 
-CommandPool::~CommandPool() = default;
+CommandPool::~CommandPool()
+{
+  Destroy();
+}
 
 vk::CommandPool CommandPool::GetVkHandle() const
 {
@@ -193,34 +195,34 @@ Device& CommandPool::GetGraphicsDevice() const
   return *mGraphicsDevice;
 }
 
-CommandBufferImpl* CommandPool::NewCommandBuffer( const vk::CommandBufferAllocateInfo& allocateInfo )
+CommandBufferImpl* CommandPool::NewCommandBuffer(const vk::CommandBufferAllocateInfo& allocateInfo)
 {
-  return NewCommandBuffer( allocateInfo.level == vk::CommandBufferLevel::ePrimary );
+  return NewCommandBuffer(allocateInfo.level == vk::CommandBufferLevel::ePrimary);
 }
 
-CommandBufferImpl* CommandPool::NewCommandBuffer( bool isPrimary )
+CommandBufferImpl* CommandPool::NewCommandBuffer(bool isPrimary)
 {
   auto& usedPool = isPrimary ? *mInternalPoolPrimary : *mInternalPoolSecondary;
-  return usedPool.AllocateCommandBuffer( false );
+  return usedPool.AllocateCommandBuffer(false);
 }
 
-void CommandPool::Reset( bool releaseResources )
+void CommandPool::Reset(bool releaseResources)
 {
   mGraphicsDevice->GetLogicalDevice()
-           .resetCommandPool( mCommandPool,
-                              releaseResources ? vk::CommandPoolResetFlagBits::eReleaseResources
-                                               : vk::CommandPoolResetFlags{} );
+    .resetCommandPool(mCommandPool,
+                      releaseResources ? vk::CommandPoolResetFlagBits::eReleaseResources
+                                       : vk::CommandPoolResetFlags{});
 }
 
-bool CommandPool::ReleaseCommandBuffer(CommandBufferImpl& buffer )
+bool CommandPool::ReleaseCommandBuffer(CommandBufferImpl& buffer)
 {
-  if( buffer.IsPrimary() )
+  if(buffer.IsPrimary() && mInternalPoolPrimary)
   {
-    mInternalPoolPrimary->ReleaseCommandBuffer( buffer );
+    mInternalPoolPrimary->ReleaseCommandBuffer(buffer);
   }
-  else
+  else if(mInternalPoolSecondary)
   {
-    mInternalPoolSecondary->ReleaseCommandBuffer( buffer );
+    mInternalPoolSecondary->ReleaseCommandBuffer(buffer);
   }
   return false;
 }
@@ -237,26 +239,23 @@ uint32_t CommandPool::GetAllocationCount() const
          mInternalPoolSecondary->GetAllocationCount();
 }
 
-uint32_t CommandPool::GetAllocationCount( vk::CommandBufferLevel level ) const
+uint32_t CommandPool::GetAllocationCount(vk::CommandBufferLevel level) const
 {
-  return level == vk::CommandBufferLevel::ePrimary ?
-         mInternalPoolPrimary->GetAllocationCount() :
-         mInternalPoolSecondary->GetAllocationCount();
+  return level == vk::CommandBufferLevel::ePrimary ? mInternalPoolPrimary->GetAllocationCount() : mInternalPoolSecondary->GetAllocationCount();
 }
 
-bool CommandPool::OnDestroy()
+void CommandPool::Destroy()
 {
-  auto device = mGraphicsDevice->GetLogicalDevice();
-  auto commandPool = mCommandPool;
+  auto device    = mGraphicsDevice->GetLogicalDevice();
   auto allocator = &mGraphicsDevice->GetAllocator();
 
-  mGraphicsDevice->DiscardResource( [ device, commandPool, allocator ]() {
-    DALI_LOG_INFO( gVulkanFilter, Debug::General, "Invoking deleter function: command pool->%p\n",
-                   static_cast< VkCommandPool >( commandPool ) )
-    device.destroyCommandPool( commandPool, allocator );
-  } );
+  if(mCommandPool)
+  {
+    DALI_LOG_INFO(gVulkanFilter, Debug::General, "Destroying command pool: %p\n", static_cast<VkCommandPool>(mCommandPool));
+    device.destroyCommandPool(mCommandPool, allocator);
 
-  return false;
+    mCommandPool = nullptr;
+  }
 }
 
 } // namespace Dali::Graphics::Vulkan
index 497991e7e0966881a48d619145068dacc5e1982a..dcf17b598824e222e007858435d05df1f645f45e 100644 (file)
@@ -24,7 +24,7 @@ namespace Dali::Graphics::Vulkan
 class Device;
 class CommandBufferImpl;
 
-class CommandPool : public VkManaged
+class CommandPool
 {
 public: // Construction, destruction
   /**
@@ -46,7 +46,7 @@ public: // Construction, destruction
 
   CommandPool(Device& graphicsDevice, const vk::CommandPoolCreateInfo& createInfo);
 
-  ~CommandPool() override;
+  ~CommandPool();
 
   vk::CommandPool GetVkHandle() const;
 
@@ -54,7 +54,7 @@ public: // Construction, destruction
 
   bool Initialize();
 
-  bool OnDestroy() override; // TODO: Queue deleter for destruction
+  void Destroy();
 
   /**
    * Resets command pool
index 38c15ef5557bead8e3e76565d14c0a2131b0a329..3019e4dd9065b07e4e87d9865f849fde24b19b89 100644 (file)
@@ -27,7 +27,6 @@ extern Debug::Filter* gVulkanFilter;
 
 namespace Dali::Graphics::Vulkan
 {
-
 FenceImpl* FenceImpl::New(Device& graphicsDevice, const vk::FenceCreateInfo& fenceCreateInfo)
 {
   auto fence = new FenceImpl(graphicsDevice);
index 933cbf51bd2ef8880c991da3b817c2cff90e4f5e..6c281e77426a704aa6cea18a45e8094d8229ced2 100644 (file)
@@ -32,9 +32,9 @@ extern Debug::Filter* gVulkanFilter;
 
 namespace Dali::Graphics::Vulkan
 {
-FramebufferAttachment* FramebufferAttachment::NewColorAttachment(ImageView*          imageView,
-                                                                 vk::ClearColorValue clearColorValue,
-                                                                 bool                presentable)
+FramebufferAttachment* FramebufferAttachment::NewColorAttachment(std::unique_ptr<ImageView>& imageView,
+                                                                 vk::ClearColorValue         clearColorValue,
+                                                                 bool                        presentable)
 {
   assert(imageView->GetImage()->GetUsageFlags() & vk::ImageUsageFlagBits::eColorAttachment);
 
@@ -46,8 +46,8 @@ FramebufferAttachment* FramebufferAttachment::NewColorAttachment(ImageView*
 }
 
 FramebufferAttachment* FramebufferAttachment::NewDepthAttachment(
-  ImageView*                 imageView,
-  vk::ClearDepthStencilValue clearDepthStencilValue)
+  std::unique_ptr<ImageView>& imageView,
+  vk::ClearDepthStencilValue  clearDepthStencilValue)
 {
   assert(imageView->GetImage()->GetUsageFlags() & vk::ImageUsageFlagBits::eDepthStencilAttachment);
 
@@ -59,15 +59,15 @@ FramebufferAttachment* FramebufferAttachment::NewDepthAttachment(
   return attachment;
 }
 
-FramebufferAttachment::FramebufferAttachment(ImageView*     imageView,
-                                             vk::ClearValue clearColor,
-                                             AttachmentType type,
-                                             bool           presentable)
-: mImageView(imageView),
-  mClearValue(clearColor),
+FramebufferAttachment::FramebufferAttachment(std::unique_ptr<ImageView>& imageView,
+                                             vk::ClearValue              clearColor,
+                                             AttachmentType              type,
+                                             bool                        presentable)
+: mClearValue(clearColor),
   mType(type)
 {
-  auto image = imageView->GetImage();
+  mImageView.swap(imageView);
+  auto image = mImageView->GetImage();
 
   auto sampleCountFlags = image->GetSampleCount();
 
@@ -92,7 +92,7 @@ FramebufferAttachment::FramebufferAttachment(ImageView*     imageView,
 
 ImageView* FramebufferAttachment::GetImageView() const
 {
-  return mImageView;
+  return mImageView.get();
 }
 
 const vk::AttachmentDescription& FramebufferAttachment::GetDescription() const
@@ -112,31 +112,34 @@ AttachmentType FramebufferAttachment::GetType() const
 
 bool FramebufferAttachment::IsValid() const
 {
-  return mImageView;
+  return mImageView != nullptr;
 }
 
 // FramebufferImpl -------------------------------
 
 FramebufferImpl* FramebufferImpl::New(
-  Vulkan::Device&                      device,
-  RenderPassImpl*                      renderPass,
-  std::vector<FramebufferAttachment*>& attachments,
-  uint32_t                             width,
-  uint32_t                             height,
-  bool                                 hasDepthAttachments)
+  Vulkan::Device&   device,
+  RenderPassImpl*   renderPass,
+  OwnedAttachments& attachments,
+  uint32_t          width,
+  uint32_t          height,
+  bool              hasDepthAttachments)
 {
-  std::vector<vk::ImageView> imageViewAttachments;
-
   DALI_ASSERT_ALWAYS(renderPass != nullptr && "You require more render passes!");
 
-  std::transform(attachments.cbegin(),
-                 attachments.cend(),
-                 std::back_inserter(imageViewAttachments),
-                 [&](FramebufferAttachment* entry) {
-                   return entry->GetImageView()->GetVkHandle();
-                 });
+  std::vector<vk::ImageView> imageViewAttachments;
+  for(auto& attachment : attachments)
+  {
+    imageViewAttachments.emplace_back(attachment->GetImageView()->GetVkHandle());
+  }
 
-  auto framebufferCreateInfo = vk::FramebufferCreateInfo{}.setRenderPass(renderPass->GetVkHandle()).setPAttachments(imageViewAttachments.data()).setLayers(1).setWidth(width).setHeight(height).setAttachmentCount(U32(attachments.size()));
+  auto framebufferCreateInfo = vk::FramebufferCreateInfo{}
+                                 .setRenderPass(renderPass->GetVkHandle())
+                                 .setPAttachments(imageViewAttachments.data())
+                                 .setLayers(1)
+                                 .setWidth(width)
+                                 .setHeight(height)
+                                 .setAttachmentCount(U32(attachments.size()));
 
   auto vkFramebuffer = VkAssert(device.GetLogicalDevice().createFramebuffer(framebufferCreateInfo, device.GetAllocator()));
 
@@ -150,18 +153,20 @@ FramebufferImpl* FramebufferImpl::New(
 }
 
 FramebufferImpl* FramebufferImpl::New(
-  Vulkan::Device&                            device,
-  RenderPassImpl*                            renderPass,
-  const std::vector<FramebufferAttachment*>& colorAttachments,
-  FramebufferAttachment*                     depthAttachment,
-  uint32_t                                   width,
-  uint32_t                                   height)
+  Vulkan::Device&                         device,
+  RenderPassImpl*                         renderPass,
+  OwnedAttachments&                       colorAttachments,
+  std::unique_ptr<FramebufferAttachment>& depthAttachment,
+  uint32_t                                width,
+  uint32_t                                height)
 {
   assert((!colorAttachments.empty() || depthAttachment) && "Cannot create framebuffer. Please provide at least one attachment");
 
-  auto colorAttachmentsValid = true;
+  auto                                colorAttachmentsValid = true;
+  std::vector<FramebufferAttachment*> attachments;
   for(auto& attachment : colorAttachments)
   {
+    attachments.emplace_back(attachment.get());
     if(!attachment->IsValid())
     {
       colorAttachmentsValid = false;
@@ -180,40 +185,56 @@ FramebufferImpl* FramebufferImpl::New(
   }
 
   // This vector stores the attachments (vk::ImageViews)
-  auto attachments = std::vector<FramebufferAttachment*>{};
 
   // Flag that indicates if the render pass is externally provided
   if(renderPass == nullptr)
   {
     // Create compatible vulkan render pass
-    renderPass = RenderPassImpl::New(device, colorAttachments, depthAttachment);
+    renderPass = RenderPassImpl::New(device, attachments, depthAttachment.get());
   }
-  attachments.reserve(colorAttachments.size());
-  attachments.insert(attachments.begin(), colorAttachments.begin(), colorAttachments.end());
+
+  OwnedAttachments ownedAttachments(std::move(colorAttachments));
   if(hasDepth)
   {
-    attachments.push_back(depthAttachment);
+    ownedAttachments.emplace_back(std::move(depthAttachment));
   }
-  return FramebufferImpl::New(device, renderPass, attachments, width, height, hasDepth);
+  return FramebufferImpl::New(device, renderPass, ownedAttachments, width, height, hasDepth);
 }
 
-FramebufferImpl::FramebufferImpl(Device&                                    graphicsDevice,
-                                 const std::vector<FramebufferAttachment*>& attachments,
-                                 vk::Framebuffer                            vkHandle,
-                                 const RenderPassImpl&                      renderPassImpl,
-                                 uint32_t                                   width,
-                                 uint32_t                                   height,
-                                 bool                                       hasDepthAttachment)
+FramebufferImpl::FramebufferImpl(Device&               graphicsDevice,
+                                 OwnedAttachments&     attachments,
+                                 vk::Framebuffer       vkHandle,
+                                 const RenderPassImpl& renderPassImpl,
+                                 uint32_t              width,
+                                 uint32_t              height,
+                                 bool                  hasDepthAttachment)
 : mGraphicsDevice(&graphicsDevice),
   mWidth(width),
   mHeight(height),
-  mAttachments(attachments),
+  mAttachments(std::move(attachments)),
   mFramebuffer(vkHandle),
   mHasDepthAttachment(hasDepthAttachment)
 {
   mRenderPasses.push_back(RenderPassMapElement{nullptr, const_cast<RenderPassImpl*>(&renderPassImpl)});
 }
 
+void FramebufferImpl::Destroy()
+{
+  auto device = mGraphicsDevice->GetLogicalDevice();
+
+  mRenderPasses.clear();
+  mAttachments.clear();
+
+  if(mFramebuffer)
+  {
+    auto allocator = &mGraphicsDevice->GetAllocator();
+
+    DALI_LOG_INFO(gVulkanFilter, Debug::General, "Destroying Framebuffer: %p\n", static_cast<VkFramebuffer>(mFramebuffer));
+    device.destroyFramebuffer(mFramebuffer, allocator);
+  }
+  mFramebuffer = nullptr;
+}
+
 uint32_t FramebufferImpl::GetWidth() const
 {
   return mWidth;
@@ -230,12 +251,14 @@ FramebufferAttachment* FramebufferImpl::GetAttachment(AttachmentType type, uint3
   {
     case AttachmentType::COLOR:
     {
-      return mAttachments[index];
+      return mAttachments[index].get();
     }
     case AttachmentType::DEPTH_STENCIL:
     {
       if(mHasDepthAttachment)
-        return mAttachments.back();
+      {
+        return mAttachments.back().get();
+      }
     }
     case AttachmentType::INPUT:
     case AttachmentType::RESOLVE:
@@ -256,7 +279,10 @@ std::vector<FramebufferAttachment*> FramebufferImpl::GetAttachments(AttachmentTy
     {
       auto numColorAttachments = mHasDepthAttachment ? mAttachments.size() - 1 : mAttachments.size();
       retval.reserve(numColorAttachments);
-      retval.insert(retval.end(), mAttachments.begin(), mAttachments.begin() + numColorAttachments);
+      for(size_t i = 0; i < numColorAttachments; ++i)
+      {
+        retval.emplace_back(mAttachments[i].get());
+      }
       break;
     }
     case AttachmentType::DEPTH_STENCIL:
@@ -264,7 +290,7 @@ std::vector<FramebufferAttachment*> FramebufferImpl::GetAttachments(AttachmentTy
       if(mHasDepthAttachment)
       {
         retval.reserve(1);
-        retval.push_back(mAttachments.back());
+        retval.emplace_back(mAttachments.back().get());
       }
       break;
     }
@@ -369,39 +395,15 @@ std::vector<vk::ClearValue> FramebufferImpl::GetClearValues() const
 {
   auto result = std::vector<vk::ClearValue>{};
 
-  std::transform(mAttachments.begin(), // @todo & color clear enabled / depth clear enabled
-                 mAttachments.end(),
-                 std::back_inserter(result),
-                 [](FramebufferAttachment* attachment) {
-                   return attachment->GetClearValue();
-                 });
+  // @todo & color clear enabled / depth clear enabled
+  for(auto& attachment : mAttachments)
+  {
+    result.emplace_back(attachment->GetClearValue());
+  }
 
   return result;
 }
 
-bool FramebufferImpl::OnDestroy()
-{
-  auto device      = mGraphicsDevice->GetLogicalDevice();
-  auto frameBuffer = mFramebuffer;
-
-  ///@todo Destroy all render passes.
-  vk::RenderPass renderPass = mRenderPasses[0].renderPassImpl->GetVkHandle();
-
-  auto allocator = &mGraphicsDevice->GetAllocator();
-
-  mGraphicsDevice->DiscardResource([device, frameBuffer, renderPass, allocator]() {
-                                     DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: framebuffer->%p\n", static_cast<VkFramebuffer>(frameBuffer))
-                                     device.destroyFramebuffer(frameBuffer, allocator);
-
-                                     if(renderPass)
-                                     {
-                                       DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: render pass->%p\n", static_cast<VkRenderPass>(renderPass))
-                                       device.destroyRenderPass(renderPass, allocator);
-                                     } });
-
-  return false;
-}
-
 } // namespace Dali::Graphics::Vulkan
 
 // Namespace Graphics
index 63782b22efc2826040c5ec74966d269092216124..2d10f0c3f8f4341795f4ce25189da896011aee45 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <dali/internal/graphics/vulkan-impl/vulkan-types.h>
 
+#include <dali/internal/graphics/vulkan-impl/vulkan-image-view-impl.h>
+
 namespace Dali::Graphics::Vulkan
 {
 class RenderPass;
@@ -37,20 +39,41 @@ enum class AttachmentType
 
 class Device;
 
-class FramebufferAttachment : public VkManaged
+class FramebufferAttachment
 {
 public:
-  FramebufferAttachment(ImageView*     imageView,
-                        vk::ClearValue clearColor,
-                        AttachmentType type,
-                        bool           presentable);
+  /**
+   * Constructor
+   *
+   * @param[in] imageView The imageview of the attachment
+   * @param[in] clearColor The color used to clear this attachment during CLEAR_OP
+   * @param[in] type The attachment type (usually COLOR or DEPTH_STENCIL)
+   * @param[in] presentable Whether the attachment is presentable (changes final layout)
+   */
+  FramebufferAttachment(std::unique_ptr<ImageView>& imageView,
+                        vk::ClearValue              clearColor,
+                        AttachmentType              type,
+                        bool                        presentable);
 
-  static FramebufferAttachment* NewColorAttachment(ImageView*          imageView,
-                                                   vk::ClearColorValue clearColorValue,
-                                                   bool                presentable);
+  /**
+   * Creates a new color attachment.
+   *
+   * @param[in] imageView The imageview of the attachment
+   * @param[in] clearColorValue The color used to clear this attachment during CLEAR_OP
+   * @param[in] presentable Whether the attachment is presentable (changes final layout)
+   */
+  static FramebufferAttachment* NewColorAttachment(std::unique_ptr<ImageView>& imageView,
+                                                   vk::ClearColorValue         clearColorValue,
+                                                   bool                        presentable);
 
-  static FramebufferAttachment* NewDepthAttachment(ImageView*                 imageView,
-                                                   vk::ClearDepthStencilValue clearDepthStencilValue);
+  /**
+   * Creates a new depth attachment.
+   *
+   * @param[in] imageView The imageview of the attachment
+   * @param[in] clearDepthStencilValue The value used to clear this attachment during CLEAR_OP
+   */
+  static FramebufferAttachment* NewDepthAttachment(std::unique_ptr<ImageView>& imageView,
+                                                   vk::ClearDepthStencilValue  clearDepthStencilValue);
 
   [[nodiscard]] ImageView* GetImageView() const;
 
@@ -65,44 +88,84 @@ public:
 private:
   FramebufferAttachment() = default;
 
-  ImageView*                mImageView{nullptr};
-  vk::AttachmentDescription mDescription;
-  vk::ClearValue            mClearValue;
-  AttachmentType            mType{AttachmentType::UNDEFINED};
+  std::unique_ptr<ImageView> mImageView;
+  vk::AttachmentDescription  mDescription;
+  vk::ClearValue             mClearValue;
+  AttachmentType             mType{AttachmentType::UNDEFINED};
 };
 
+using OwnedAttachments = std::vector<std::unique_ptr<FramebufferAttachment>>;
+
 /**
  * FramebufferImpl encapsulates following objects:
  * - Images ( attachments )
  * - FramebufferImpl
  * - ImageViews
+ * - RenderPasses
  */
-class FramebufferImpl : public VkManaged
+class FramebufferImpl
 {
 public:
+  /**
+   * @brief Create a new Framebuffer
+   *
+   * @param[in] device The vulkan device
+   * @param[in] renderPass A shared handle to a compatible render pass.
+   * @param[in] attachments The attachments. Framebuffer takes ownership of these
+   * @param[in] width Width of the framebuffer
+   * @param[in] height Height of the framebuffer
+   * @param[in] hasDepthAttachment True if the last attachment is a depth buffer
+   *
+   * @return A new framebuffer object
+   */
   static FramebufferImpl* New(
-    Vulkan::Device&                      device,
-    RenderPassImpl*                      renderPass,
-    std::vector<FramebufferAttachment*>& attachments,
-    uint32_t                             width,
-    uint32_t                             height,
-    bool                                 hasDepthAttachment);
+    Vulkan::Device&   device,
+    RenderPassImpl*   renderPass,
+    OwnedAttachments& attachments,
+    uint32_t          width,
+    uint32_t          height,
+    bool              hasDepthAttachment);
 
+  /**
+   * @brief Create a new Framebuffer
+   *
+   * @param[in] device The vulkan device
+   * @param[in] renderPass A shared handle to a compatible render pass.
+   * @param[in] attachments The attachments. Framebuffer takes ownership of these
+   * @param[in] width Width of the framebuffer
+   * @param[in] height Height of the framebuffer
+   * @param[in] hasDepthAttachment True if the last attachment is a depth buffer
+   *
+   * @return A new framebuffer object
+   */
   static FramebufferImpl* New(
-    Vulkan::Device&                            device,
-    RenderPassImpl*                            renderPass,
-    const std::vector<FramebufferAttachment*>& colorAttachments,
-    FramebufferAttachment*                     depthAttachment,
-    uint32_t                                   width,
-    uint32_t                                   height);
-
-  FramebufferImpl(Device&                                    graphicsDevice,
-                  const std::vector<FramebufferAttachment*>& attachments,
-                  vk::Framebuffer                            vkHandle,
-                  const RenderPassImpl&                      renderPass,
-                  uint32_t                                   width,
-                  uint32_t                                   height,
-                  bool                                       hasDepthAttachment);
+    Vulkan::Device&                         device,
+    RenderPassImpl*                         renderPass,
+    OwnedAttachments&                       colorAttachments,
+    std::unique_ptr<FramebufferAttachment>& depthAttachment,
+    uint32_t                                width,
+    uint32_t                                height);
+
+  /**
+   * @brief Constructor
+   *
+   * @param[in] graphicsDevice The vulkan device
+   * @param[in] attachments The attachments - framebuffer takes ownership
+   * @param[in] vkHandle a handle to a created framebuffer
+   * @param[in] renderPass a handle to a compatible render pass
+   * @param[in] width Width of the framebuffer
+   * @param[in] height Height of the framebuffer
+   * @param[in] hasDepthAttachment True if the last attachment is a depth buffer
+   */
+  FramebufferImpl(Device&               graphicsDevice,
+                  OwnedAttachments&     attachments,
+                  vk::Framebuffer       vkHandle,
+                  const RenderPassImpl& renderPass,
+                  uint32_t              width,
+                  uint32_t              height,
+                  bool                  hasDepthAttachment);
+
+  void Destroy();
 
   [[nodiscard]] uint32_t GetWidth() const;
 
@@ -124,8 +187,6 @@ public:
 
   [[nodiscard]] std::vector<vk::ClearValue> GetClearValues() const;
 
-  bool OnDestroy() override;
-
 private:
   Device* mGraphicsDevice;
 
@@ -142,10 +203,10 @@ private:
   };
   using RenderPasses = std::vector<RenderPassMapElement>;
 
-  std::vector<FramebufferAttachment*> mAttachments;
-  vk::Framebuffer                     mFramebuffer;
-  RenderPasses                        mRenderPasses;
-  bool                                mHasDepthAttachment{false};
+  OwnedAttachments mAttachments;
+  vk::Framebuffer  mFramebuffer;
+  RenderPasses     mRenderPasses;
+  bool             mHasDepthAttachment{false};
 };
 
 } // Namespace Dali::Graphics::Vulkan
index 70f1817a5e916f08b83aeba200471c12fb93caf0..18d40723e0375f84ab5173d93d4652d530470c31 100644 (file)
 #include <dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.h>
 #include <dali/internal/graphics/vulkan-impl/vulkan-render-pass.h>
 
-namespace Dali
-{
-namespace Graphics
-{
-namespace Vulkan
+namespace Dali::Graphics::Vulkan
 {
 Framebuffer::Framebuffer(const FramebufferCreateInfo& createInfo, VulkanGraphicsController& controller)
 : Resource(createInfo, controller),
@@ -39,25 +35,20 @@ Framebuffer::~Framebuffer() = default;
 bool Framebuffer::InitializeResource()
 {
   // Create attachments
-  std::vector<FramebufferAttachment*> colorAttachments;
+  OwnedAttachments colorAttachments;
   // for(auto& attachment : mCreateInfo.colorAttachments)
   {
     // auto graphicsTexture = static_cast<const Vulkan::Texture*>(attachment.texture);
     // colorAttachments.push_back(FramebufferAttachment::NewColorAttachment(attachment.texture->GetVkHandle(), clearColor, AttachmentType::COLOR, false);
   }
-  FramebufferAttachment* depthStencilAttachment{nullptr};
+  std::unique_ptr<FramebufferAttachment> depthStencilAttachment;
   if(mCreateInfo.depthStencilAttachment.depthTexture || mCreateInfo.depthStencilAttachment.stencilTexture)
   {
     // depthStencilAttachment = FramebufferAttachment::NewDepthAttachment();
   }
 
-  // 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);
+  mFramebufferImpl = FramebufferImpl::New(device, nullptr, colorAttachments, depthStencilAttachment, mCreateInfo.size.width, mCreateInfo.size.height);
 
   return true;
 }
@@ -70,6 +61,4 @@ void Framebuffer::DiscardResource()
 {
 }
 
-} // namespace Vulkan
-} // namespace Graphics
-} // namespace Dali
+} // namespace Dali::Graphics::Vulkan
index 11b86e5ea0ff0ab4bcd3ad8f8ed186c6a2156fdf..447422ad7eb8594a9ab39e3d9cfef7669cd5a312 100644 (file)
@@ -20,8 +20,8 @@
 
 #include <dali/internal/graphics/vulkan-impl/vulkan-graphics-resource.h>
 
-#include <dali/graphics-api/graphics-framebuffer.h>
 #include <dali/graphics-api/graphics-framebuffer-create-info.h>
+#include <dali/graphics-api/graphics-framebuffer.h>
 
 namespace Dali
 {
@@ -32,6 +32,7 @@ namespace Vulkan
 class FramebufferImpl;
 
 using FramebufferResource = Resource<Graphics::Framebuffer, Graphics::FramebufferCreateInfo>;
+
 class Framebuffer : public FramebufferResource
 {
 public:
@@ -40,7 +41,7 @@ public:
   ~Framebuffer() override;
 
   /**
-   * @brief Called when GL resources are destroyed
+   * @brief Called when resources are destroyed
    */
   void DestroyResource() override;
 
@@ -56,10 +57,28 @@ public:
    */
   void DiscardResource() override;
 
+  /**
+   * @copydoc Graphics::Vulkan::ResourceBase::GetAllocationCallbacks()
+   */
+  [[nodiscard]] const Graphics::AllocationCallbacks* GetAllocationCallbacks() const override
+  {
+    return mCreateInfo.allocationCallbacks;
+  }
+
+  /**
+   * @copydoc Graphics::Vulkan::ResourceBase::InvokeDeleter()
+   * Only intended for use by discard queue.
+   */
+  void InvokeDeleter() override
+  {
+    this->~Framebuffer();
+  }
+
   FramebufferImpl* GetImpl()
   {
     return mFramebufferImpl;
   }
+
 private:
   FramebufferImpl* mFramebufferImpl;
 };
index 70877483a98ec4eb6e69d219248f8e96c9e76893..f2a717bf5045e3d1ac628cc068321a17a91ad9cb 100644 (file)
@@ -71,13 +71,13 @@ static bool TestCopyRectIntersection(const ResourceTransferRequest* srcRequest,
  *
  * When Graphics object dies the unique pointer (Graphics::UniquePtr)
  * doesn't destroy it directly but passes the ownership back
- * to the Controller. The VKDeleter is responsible for passing
- * the object to the discard queue (by calling Resource::DiscardResource()).
+ * to the Controller. The GraphicsDeleter is responsible for passing
+ * the graphics object to the discard queue (by calling Resource::DiscardResource()).
  */
 template<typename T>
-struct VKDeleter
+struct GraphicsDeleter
 {
-  VKDeleter() = default;
+  GraphicsDeleter() = default;
 
   void operator()(T* object)
   {
@@ -94,7 +94,7 @@ struct VKDeleter
  * @param[out] out Unique pointer to the return object
  */
 template<class VKType, class GfxCreateInfo, class T>
-auto NewObject(const GfxCreateInfo& info, VulkanGraphicsController& controller, T&& oldObject)
+auto NewGraphicsObject(const GfxCreateInfo& info, VulkanGraphicsController& controller, T&& oldObject)
 {
   // Use allocator
   using Type = typename T::element_type;
@@ -105,7 +105,7 @@ auto NewObject(const GfxCreateInfo& info, VulkanGraphicsController& controller,
       sizeof(VKType),
       0,
       info.allocationCallbacks->userData);
-    return UPtr(new(memory) VKType(info, controller), VKDeleter<VKType>());
+    return UPtr(new(memory) VKType(info, controller), GraphicsDeleter<VKType>());
   }
   else // Use standard allocator
   {
@@ -116,7 +116,7 @@ auto NewObject(const GfxCreateInfo& info, VulkanGraphicsController& controller,
       // If succeeded, attach the object to the unique_ptr and return it back
       if(static_cast<VKType*>(reusedObject)->TryRecycle(info, controller))
       {
-        return UPtr(reusedObject, VKDeleter<VKType>());
+        return UPtr(reusedObject, GraphicsDeleter<VKType>());
       }
       else
       {
@@ -126,8 +126,8 @@ auto NewObject(const GfxCreateInfo& info, VulkanGraphicsController& controller,
       }
     }
 
-    // Create brand new object
-    UPtr gfxObject(new VKType(info, controller), VKDeleter<VKType>());
+    // Create brand-new object
+    UPtr gfxObject(new VKType(info, controller), GraphicsDeleter<VKType>());
     static_cast<VKType*>(gfxObject.get())->InitializeResource(); // @todo Consider using create queues?
     return gfxObject;
   }
@@ -410,7 +410,7 @@ struct VulkanGraphicsController::Impl
           // Do not destroy
           if(buffer != mTextureStagingBuffer->GetImpl())
           {
-            buffer->DestroyNow();
+            buffer->Destroy();
           }
         }
         else if(request.requestType == TransferRequestType::IMAGE_TO_IMAGE)
@@ -418,7 +418,7 @@ struct VulkanGraphicsController::Impl
           auto& image = request.imageToImageInfo.srcImage;
           if(image->GetVkHandle())
           {
-            image->DestroyNow();
+            image->Destroy();
           }
         }
       }
@@ -428,12 +428,74 @@ struct VulkanGraphicsController::Impl
     }
   }
 
+  /**
+   * @brief Processes a discard queue for objects created with NewObject
+   *
+   * @param[in,out] queue Reference to the queue
+   */
+  template<class ResourceType>
+  void ProcessResourceDiscardQueue(std::queue<ResourceType*>& queue)
+  {
+    while(!queue.empty())
+    {
+      auto* object = const_cast<ResourceType*>(queue.front());
+
+      // Destroy
+      object->DestroyResource();
+
+      auto* allocationCallbacks = object->GetAllocationCallbacks();
+      if(allocationCallbacks)
+      {
+        object->InvokeDeleter();
+        allocationCallbacks->freeCallback(object, allocationCallbacks->userData);
+      }
+      else
+      {
+        delete object;
+      }
+      queue.pop();
+    }
+  }
+
+  /**
+   * Processes a discard queue for direct instantiated objects
+   */
+  template<class ResourceType>
+  void ProcessDiscardQueue(std::queue<ResourceType*>& queue)
+  {
+    while(!queue.empty())
+    {
+      auto* object = queue.front();
+
+      // Destroy
+      object->DestroyResource();
+      delete object;
+
+      queue.pop();
+    }
+  }
+
+  void GarbageCollect()
+  {
+    ProcessResourceDiscardQueue<ResourceWithDeleter>(mResourceDiscardQueue);
+    ProcessDiscardQueue<ResourceBase>(mDiscardQueue);
+  }
+
+  void Flush()
+  {
+    // Flush any outstanding queues.
+
+    GarbageCollect();
+  }
+
   VulkanGraphicsController& mGraphicsController;
   Vulkan::Device*           mGraphicsDevice{nullptr};
 
   // used for texture<->buffer<->memory transfers
-  std::vector<ResourceTransferRequest> mResourceTransferRequests;
-  std::recursive_mutex                 mResourceTransferMutex{};
+  std::vector<ResourceTransferRequest>     mResourceTransferRequests;
+  std::recursive_mutex                     mResourceTransferMutex{};
+  std::queue<Vulkan::ResourceBase*>        mDiscardQueue;
+  std::queue<Vulkan::ResourceWithDeleter*> mResourceDiscardQueue;
 
   std::unique_ptr<Vulkan::Buffer>       mTextureStagingBuffer{};
   Dali::SharedFuture                    mTextureStagingBufferFuture{};
@@ -453,7 +515,10 @@ VulkanGraphicsController::VulkanGraphicsController()
 {
 }
 
-VulkanGraphicsController::~VulkanGraphicsController() = default;
+VulkanGraphicsController::~VulkanGraphicsController()
+{
+  mImpl->GarbageCollect();
+}
 
 void VulkanGraphicsController::Initialize(Dali::Graphics::VulkanGraphics& graphicsImplementation,
                                           Vulkan::Device&                 graphicsDevice)
@@ -484,6 +549,12 @@ void VulkanGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo
       swapchain->Submit(cmdBuffer->GetImpl());
     }
   }
+
+  // If flush bit set, flush all pending tasks
+  if(submitInfo.flags & (0 | SubmitFlagBits::FLUSH))
+  {
+    Flush();
+  }
 }
 
 void VulkanGraphicsController::PresentRenderTarget(Graphics::RenderTarget* renderTarget)
@@ -792,6 +863,7 @@ bool VulkanGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool e
 
 void VulkanGraphicsController::RunGarbageCollector(size_t numberOfDiscardedRenderers)
 {
+  mImpl->GarbageCollect();
 }
 
 void VulkanGraphicsController::DiscardUnusedResources()
@@ -810,12 +882,12 @@ bool VulkanGraphicsController::IsDrawOnResumeRequired()
 
 UniquePtr<Graphics::RenderTarget> VulkanGraphicsController::CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, UniquePtr<Graphics::RenderTarget>&& oldRenderTarget)
 {
-  return NewObject<Vulkan::RenderTarget>(renderTargetCreateInfo, *this, std::move(oldRenderTarget));
+  return NewGraphicsObject<Vulkan::RenderTarget>(renderTargetCreateInfo, *this, std::move(oldRenderTarget));
 }
 
 UniquePtr<Graphics::CommandBuffer> VulkanGraphicsController::CreateCommandBuffer(const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo, UniquePtr<Graphics::CommandBuffer>&& oldCommandBuffer)
 {
-  return NewObject<Vulkan::CommandBuffer>(commandBufferCreateInfo, *this, std::move(oldCommandBuffer));
+  return NewGraphicsObject<Vulkan::CommandBuffer>(commandBufferCreateInfo, *this, std::move(oldCommandBuffer));
 }
 
 UniquePtr<Graphics::RenderPass> VulkanGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, UniquePtr<Graphics::RenderPass>&& oldRenderPass)
@@ -828,12 +900,12 @@ UniquePtr<Graphics::RenderPass> VulkanGraphicsController::CreateRenderPass(const
 
 UniquePtr<Graphics::Buffer> VulkanGraphicsController::CreateBuffer(const Graphics::BufferCreateInfo& bufferCreateInfo, UniquePtr<Graphics::Buffer>&& oldBuffer)
 {
-  return NewObject<Vulkan::Buffer>(bufferCreateInfo, *this, std::move(oldBuffer));
+  return NewGraphicsObject<Vulkan::Buffer>(bufferCreateInfo, *this, std::move(oldBuffer));
 }
 
 UniquePtr<Graphics::Texture> VulkanGraphicsController::CreateTexture(const Graphics::TextureCreateInfo& textureCreateInfo, UniquePtr<Graphics::Texture>&& oldTexture)
 {
-  return NewObject<Vulkan::Texture>(textureCreateInfo, *this, std::move(oldTexture));
+  return NewGraphicsObject<Vulkan::Texture>(textureCreateInfo, *this, std::move(oldTexture));
 }
 
 UniquePtr<Graphics::Framebuffer> VulkanGraphicsController::CreateFramebuffer(const Graphics::FramebufferCreateInfo& framebufferCreateInfo, UniquePtr<Graphics::Framebuffer>&& oldFramebuffer)
@@ -858,7 +930,7 @@ UniquePtr<Graphics::Shader> VulkanGraphicsController::CreateShader(const Graphic
 
 UniquePtr<Graphics::Sampler> VulkanGraphicsController::CreateSampler(const Graphics::SamplerCreateInfo& samplerCreateInfo, UniquePtr<Graphics::Sampler>&& oldSampler)
 {
-  return NewObject<Vulkan::Sampler>(samplerCreateInfo, *this, std::move(oldSampler));
+  return NewGraphicsObject<Vulkan::Sampler>(samplerCreateInfo, *this, std::move(oldSampler));
 }
 
 UniquePtr<Graphics::SyncObject> VulkanGraphicsController::CreateSyncObject(const Graphics::SyncObjectCreateInfo& syncObjectCreateInfo,
@@ -867,6 +939,16 @@ UniquePtr<Graphics::SyncObject> VulkanGraphicsController::CreateSyncObject(const
   return UniquePtr<Graphics::SyncObject>{};
 }
 
+void VulkanGraphicsController::DiscardResource(Vulkan::ResourceBase* resource)
+{
+  mImpl->mDiscardQueue.push(resource);
+}
+
+void VulkanGraphicsController::DiscardResource(Vulkan::ResourceWithDeleter* resource)
+{
+  mImpl->mResourceDiscardQueue.push(resource);
+}
+
 UniquePtr<Graphics::Memory> VulkanGraphicsController::MapBufferRange(const MapBufferInfo& mapInfo)
 {
   // @todo: Process create queues
@@ -909,7 +991,7 @@ MemoryRequirements VulkanGraphicsController::GetTextureMemoryRequirements(Graphi
 
 TextureProperties VulkanGraphicsController::GetTextureProperties(const Graphics::Texture& gfxTexture)
 {
-  Vulkan::Texture* texture = const_cast<Vulkan::Texture*>(static_cast<const Vulkan::Texture*>(&gfxTexture));
+  auto* texture = const_cast<Vulkan::Texture*>(static_cast<const Vulkan::Texture*>(&gfxTexture));
   return texture->GetProperties();
 }
 
@@ -992,40 +1074,6 @@ std::string VulkanGraphicsController::GetFragmentShaderPrefix()
   return "";
 }
 
-void VulkanGraphicsController::Add(Vulkan::RenderTarget* renderTarget)
-{
-  // @todo Add create resource queues?
-  renderTarget->InitializeResource();
-}
-
-void VulkanGraphicsController::DiscardResource(Vulkan::RenderTarget* renderTarget)
-{
-  // @todo Add discard queues
-}
-
-void VulkanGraphicsController::DiscardResource(Vulkan::Buffer* buffer)
-{
-  // @todo Add discard queues
-}
-
-void VulkanGraphicsController::DiscardResource(Vulkan::Pipeline* buffer)
-{
-  // @todo Add discard queues
-}
-
-void VulkanGraphicsController::DiscardResource(Vulkan::Program* program)
-{
-  // @todo Add discard queues
-}
-
-void VulkanGraphicsController::DiscardResource(Vulkan::Sampler* sampler)
-{
-}
-
-void VulkanGraphicsController::DiscardResource(Vulkan::Texture* texture)
-{
-}
-
 Vulkan::Device& VulkanGraphicsController::GetGraphicsDevice()
 {
   return *mImpl->mGraphicsDevice;
@@ -1083,6 +1131,11 @@ Graphics::UniquePtr<Graphics::Texture> VulkanGraphicsController::ReleaseTextureF
   return gfxTexture;
 }
 
+void VulkanGraphicsController::Flush()
+{
+  mImpl->Flush();
+}
+
 std::size_t VulkanGraphicsController::GetCapacity() const
 {
   return mImpl->mCapacity;
index a21f735045f58b8806e073063a3674f1ffb1b47a..0e10695eb306e68e3ab21827f59d045b26cd0e12 100644 (file)
@@ -269,6 +269,14 @@ public:
   UniquePtr<Graphics::SyncObject> CreateSyncObject(const Graphics::SyncObjectCreateInfo& syncObjectCreateInfo,
                                                    UniquePtr<Graphics::SyncObject>&&     oldSyncObject) override;
 
+  /**
+   * Add the graphics resource to a discard queue for later destruction
+   * @param[in] resource The graphics resource to discard.
+   */
+  void DiscardResource(Vulkan::ResourceBase* resource);
+
+  void DiscardResource(Vulkan::ResourceWithDeleter* program);
+
   /**
    * @brief Maps memory associated with Buffer object
    *
@@ -365,14 +373,6 @@ public:
    */
   bool GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData) override;
 
-  void Add(Vulkan::RenderTarget* renderTarget);
-  void DiscardResource(Vulkan::RenderTarget* renderTarget);
-  void DiscardResource(Vulkan::Buffer* buffer);
-  void DiscardResource(Vulkan::Pipeline* buffer);
-  void DiscardResource(Vulkan::Program* renderProgram);
-  void DiscardResource(Vulkan::Sampler* sampler);
-  void DiscardResource(Vulkan::Texture* texture);
-
 public: // Integration::GraphicsConfig
   bool        IsBlendEquationSupported(DevelBlendEquation::Type blendEquation) override;
   uint32_t    GetShaderLanguageVersion() override;
@@ -433,6 +433,11 @@ public: // For debug
   std::size_t GetCapacity() const;
 
 private:
+  /**
+   * Flush all outstanding queues.
+   */
+  void Flush();
+
   bool IsAdvancedBlendEquationSupported();
 
   struct Impl;
index e1d0f11bb2a1fceceed49b48f7196172c6635fd2..4d145c9b0a2073e8e750803ca26dc470d0f339e2 100644 (file)
  *
  */
 
+#include <dali/graphics-api/graphics-types.h>
+
 namespace Dali::Graphics::Vulkan
 {
 class VulkanGraphicsController;
 
+/**
+ * Interface class for graphics resources
+ */
+class ResourceBase
+{
+public:
+  /**
+   * @brief Destroys resource
+   *
+   * This function must be implemented by the derived class.
+   * It should perform final destruction of used GL resources.
+   */
+  virtual void DestroyResource() = 0;
+
+  /**
+   * @brief Initializes resource
+   *
+   * This function must be implemented by the derived class.
+   * It should initialize all necessary GL resources.
+   *
+   * @return True on success
+   */
+  virtual bool InitializeResource() = 0;
+
+  /**
+   * @brief Discards resource by adding it to the discard queue
+   */
+  virtual void DiscardResource() = 0;
+
+  virtual ~ResourceBase() = default;
+};
+
+class ResourceWithDeleter : public ResourceBase
+{
+public:
+  /**
+   * @brief Get the allocation callbacks for this object
+   */
+  [[nodiscard]] virtual const Graphics::AllocationCallbacks* GetAllocationCallbacks() const = 0;
+
+  /**
+   * @brief Invoke the deleter of the derived type.
+   */
+  virtual void InvokeDeleter() = 0;
+
+  ~ResourceWithDeleter() override = default;
+};
+
 /**
  * @brief Base class for the Graphics resource.
+ * A graphics resource is any Graphics API object created by the controller that
+ * requires lifecycle management.
+ * It explicitly does not include Vulkan Impl objects that wrap a vkHandle.
  */
-template<class BASE, class CreateInfo>
-class Resource : public BASE
+template<class GraphicsType, class CreateInfo>
+class Resource : public GraphicsType, public ResourceWithDeleter
 {
 public:
   /**
@@ -79,34 +132,11 @@ public:
     return mController;
   }
 
-  /**
-   * @brief Destroys resource
-   *
-   * This function must be implemented by the derived class.
-   * It should perform final destruction of used GL resources.
-   */
-  virtual void DestroyResource() = 0;
-
-  /**
-   * @brief Initializes resource
-   *
-   * This function must be implemented by the derived class.
-   * It should initialize all necessary GL resources.
-   *
-   * @return True on success
-   */
-  virtual bool InitializeResource() = 0;
-
-  /**
-   * @brief Discards resource by adding it to the discard queue
-   */
-  virtual void DiscardResource() = 0;
-
   /**
    * @brief returns pointer to base
    * @return
    */
-  BASE* GetBase()
+  GraphicsType* GetBase()
   {
     return this;
   }
index 20b95d12d90e46f02169399fe6e90ac8db9c782b..470d1bd919aada7159cac0f85a2a0d2294000046 100644 (file)
@@ -83,6 +83,18 @@ void Image::Initialize()
   VkAssert(mDevice.GetLogicalDevice().createImage(&mCreateInfo, &mDevice.GetAllocator("IMAGE"), &mImage));
 }
 
+void Image::Destroy()
+{
+  DALI_LOG_INFO(gVulkanFilter, Debug::General, "Destroying image: %p\n", static_cast<VkImage>(mImage));
+  auto device = mDevice.GetLogicalDevice();
+  if(mImage)
+  {
+    device.destroyImage(mImage, mDevice.GetAllocator());
+  }
+  mImage = nullptr;
+  mMemory.reset();
+}
+
 void Image::AllocateAndBind(vk::MemoryPropertyFlags memoryProperties)
 {
   auto requirements    = mDevice.GetLogicalDevice().getImageMemoryRequirements(mImage);
@@ -255,38 +267,6 @@ vk::SampleCountFlagBits Image::GetSampleCount() const
   return mCreateInfo.samples;
 }
 
-void Image::DestroyNow()
-{
-  DestroyVulkanResources(mDevice.GetLogicalDevice(), mImage, mMemory->ReleaseVkObject(), &mDevice.GetAllocator());
-  mImage  = nullptr;
-  mMemory = nullptr;
-}
-
-bool Image::OnDestroy()
-{
-  if(!mIsExternal)
-  {
-    if(mImage)
-    {
-      auto device    = mDevice.GetLogicalDevice();
-      auto image     = mImage;
-      auto allocator = &mDevice.GetAllocator();
-      auto memory    = mMemory->ReleaseVkObject();
-
-      mDevice.DiscardResource([device, image, memory, allocator]() { DestroyVulkanResources(device, image, memory, allocator); });
-    }
-  }
-
-  return false;
-}
-
-void Image::DestroyVulkanResources(vk::Device device, vk::Image image, vk::DeviceMemory memory, const vk::AllocationCallbacks* allocator)
-{
-  DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: image->%p\n", static_cast<VkImage>(image))
-  device.destroyImage(image, allocator);
-  device.freeMemory(memory, allocator);
-}
-
 } // namespace Vulkan
 
 } // namespace Graphics
index 8454583f2d62799e30ad9804a42f010808b0a79c..dc9ea516fb32777bc377e349ad2c652248ce536d 100644 (file)
@@ -53,6 +53,14 @@ public:
    */
   void Initialize();
 
+  /**
+   * Destroys underlying Vulkan resources on the caller thread.
+   *
+   * @note Calling this function is unsafe and makes any further use of
+   * image invalid.
+   */
+  void Destroy();
+
   /**
    * Allocate memory for the image and bind it.
    * Kept separate from Initialize because reasons. ?!?!
@@ -149,32 +157,12 @@ public:
     return mMemory.get();
   }
 
-  bool OnDestroy();
-
-  /**
-   * Destroys underlying Vulkan resources on the caller thread.
-   *
-   * @note Calling this function is unsafe and makes any further use of
-   * image invalid.
-   */
-  void DestroyNow();
-
-  /**
-   * Destroys used Vulkan resource objects
-   * @param device Vulkan device
-   * @param image Vulkan image
-   * @param memory Vulkan device memory
-   * @param allocator Pointer to the Vulkan allocator callbacks
-   */
-  static void DestroyVulkanResources(vk::Device device, vk::Image image, vk::DeviceMemory memory, const vk::AllocationCallbacks* allocator);
-
 private:
-  Device&              mDevice;
-  vk::ImageCreateInfo  mCreateInfo;
-  vk::Image            mImage;
-  vk::ImageLayout      mImageLayout;
-  vk::ImageAspectFlags mAspectFlags;
-
+  Device&                     mDevice;
+  vk::ImageCreateInfo         mCreateInfo;
+  vk::Image                   mImage;
+  vk::ImageLayout             mImageLayout;
+  vk::ImageAspectFlags        mAspectFlags;
   std::unique_ptr<MemoryImpl> mMemory;
   bool                        mIsExternal;
 };
index 15fb6fda0282b705aaea9054728f5100616ac45d..9d921c00c4edbb5f8d4cd99472ff6b74b1e29a4c 100644 (file)
@@ -110,6 +110,13 @@ ImageView::~ImageView()
   Destroy();
 }
 
+void ImageView::Destroy()
+{
+  DALI_LOG_INFO(gVulkanFilter, Debug::General, "Destroying ImageView: %p\n", static_cast<VkImageView>(mImageView));
+  auto device = mDevice.GetLogicalDevice();
+  device.destroyImageView(mImageView, mDevice.GetAllocator());
+}
+
 vk::ImageView ImageView::GetVkHandle() const
 {
   return mImageView;
@@ -135,12 +142,6 @@ vk::ImageAspectFlags ImageView::GetImageAspectMask() const
   return vk::ImageAspectFlags();
 }
 
-void ImageView::Destroy()
-{
-  auto device = mDevice.GetLogicalDevice();
-  device.destroyImageView(mImageView, mDevice.GetAllocator());
-}
-
 } // namespace Vulkan
 } // namespace Graphics
 } // namespace Dali
index b7454ad4c8d9319e1971e397e84cc94215a0110f..28830291b368695ba93859126b05ef1cd055d114 100644 (file)
@@ -52,6 +52,8 @@ public:
 
   ~ImageView();
 
+  void Destroy();
+
   /**
    *
    * @return
@@ -79,8 +81,6 @@ public:
    */
   [[nodiscard]] vk::ImageAspectFlags GetImageAspectMask() const;
 
-  void Destroy();
-
 private:
   Device&                 mDevice;
   const Image&            mImage;
index 83bcf5d7200d107584c4b7e55e6869cc46c56e2e..ce333d4c0b10f14e5d45f8bbdbe324a83d3baa5a 100644 (file)
@@ -77,13 +77,6 @@ void MemoryImpl::Unmap()
   }
 }
 
-vk::DeviceMemory MemoryImpl::ReleaseVkObject()
-{
-  auto retval  = deviceMemory;
-  deviceMemory = nullptr;
-  return retval;
-}
-
 void MemoryImpl::Flush()
 {
   // Don't flush if we are using host coherent memory - it's un-necessary
index c9a2e47f1e7dd2fbe054f852e1ca80b16ecd9be8..40a2fb72f6add92c059b8e72f571af3512fbfb64 100644 (file)
@@ -38,7 +38,7 @@ public:
   }
 
   // No copy constructor or assignment operator
-  MemoryImpl(MemoryImpl&) = delete;
+  MemoryImpl(MemoryImpl&)            = delete;
   MemoryImpl& operator=(MemoryImpl&) = delete;
 
   void* Map();
@@ -49,13 +49,6 @@ public:
 
   void Flush();
 
-  /**
-   * Releases vk::DeviceMemory object so it can be deleted
-   * externally
-   * @return
-   */
-  vk::DeviceMemory ReleaseVkObject();
-
   [[nodiscard]] vk::DeviceMemory GetVkHandle() const;
 
 private:
index 6cf4fc4bae1d84a9827ca7634c0ca22165a0caec..95a4b03d48d07c29d4d5647a829f1c63f0fd6b9f 100644 (file)
@@ -56,6 +56,11 @@ Pipeline::Pipeline(const Graphics::PipelineCreateInfo& createInfo, VulkanGraphic
   mPipeline = std::make_unique<PipelineImpl>(createInfo, controller, pipelineCache);
 }
 
+bool Pipeline::InitializeResource()
+{
+  return true;
+}
+
 void Pipeline::DiscardResource()
 {
   // Send pipeline to discard queue if refcount is 0
index 2e92309d240c51e96cea64da7f7f2915f9af3c15..8f3d16b6c397177b1e079f40fe9bce1e79734a74 100644 (file)
@@ -35,7 +35,7 @@ class PipelineCache;
 /**
  * @brief Pipeline class wraps the PipelineImpl
  */
-class Pipeline : public Graphics::Pipeline
+class Pipeline : public Graphics::Pipeline, public Vulkan::ResourceBase
 {
 public:
   Pipeline() = delete;
@@ -82,22 +82,23 @@ public:
   bool operator==(const PipelineImpl* impl) const;
 
   /**
-   * @brief Run by UniquePtr to discard resource
+   * @brief Initialize the resource
    */
-  void DiscardResource();
+  bool InitializeResource() override;
+
+  /**
+   * @brief trigger discard
+   */
+  void DiscardResource() override;
 
   /**
    * @brief Destroy resource
-   *
-   * Despite this class doesn't inherit Resource it must provide
-   * (so it won't duplicate same data) same set of functions
-   * so it can work with resource management functions of Controller.
    */
-  void DestroyResource();
+  void DestroyResource() override;
 
 private:
   std::unique_ptr<PipelineImpl> mPipeline; // TODO: it may need to be changed when we have caching
 };
 
 } // namespace Dali::Graphics::Vulkan
-#endif
\ No newline at end of file
+#endif
index 0f50162c774c795d0bf3274aae254f9ee7afd140..d5eda21ea2de1c737498bad52ceccea8ab5f57bd 100644 (file)
@@ -64,9 +64,19 @@ const ProgramCreateInfo& Program::GetCreateInfo() const
   return GetImplementation()->GetCreateInfo();
 }
 
+bool Program::InitializeResource()
+{
+  return true;
+}
+
 void Program::DiscardResource()
 {
   GetController().DiscardResource(this);
 }
 
+void Program::DestroyResource()
+{
+  // nothing to do here
+}
+
 }; // namespace Dali::Graphics::Vulkan
index 041bbe0e38eb22a049cd954dd80251149b794d57..bc19a4264a2eaefd8a6bbbfa9eb22f4eb21bf219 100644 (file)
@@ -28,6 +28,7 @@ namespace Dali::Graphics::Vulkan
 {
 class Reflection;
 class ProgramImpl;
+
 /**
  * @brief Wrapper for the program implementation
  *
@@ -37,7 +38,7 @@ class ProgramImpl;
  * within Graphics API is a set of shader stages linked together
  * so the reflection can do its work on it.
  */
-class Program : public Graphics::Program
+class Program : public Graphics::Program, public Vulkan::ResourceBase
 {
 public:
   /**
@@ -59,7 +60,6 @@ public:
 
   /**
    * @brief Returns reference to the Reflection object
-
    * @return Reflection
    */
   [[nodiscard]] const Vulkan::Reflection& GetReflection() const;
@@ -103,10 +103,15 @@ public:
     return (program.mProgram != mProgram);
   }
 
+  /**
+   * @brief Initialize the resource
+   */
+  bool InitializeResource() override;
+
   /**
    * @brief Run by UniquePtr to discard resource
    */
-  void DiscardResource();
+  void DiscardResource() override;
 
   /**
    * @brief Destroying resources
@@ -114,10 +119,7 @@ public:
    * This function is kept for compatibility with Resource<> class
    * so can the object can be use with templated functions.
    */
-  void DestroyResource()
-  {
-    // nothing to do here
-  }
+  void DestroyResource() override;
 
   bool TryRecycle(const Graphics::ProgramCreateInfo& createInfo, VulkanGraphicsController& controller)
   {
@@ -129,4 +131,4 @@ private:
 };
 } // namespace Dali::Graphics::Vulkan
 
-#endif //DALI_GRAPHICS_VULKAN_PROGRAM_H
+#endif // DALI_GRAPHICS_VULKAN_PROGRAM_H
index eceb474669330b1336354c9ba70f929da0b9bf27..c9b2ebd04267009457bbe38afdc3c4c2c036d100 100644 (file)
@@ -49,26 +49,24 @@ RenderPassImpl::RenderPassImpl(Vulkan::Device&                            device
 
 RenderPassImpl::~RenderPassImpl() = default;
 
-vk::RenderPass RenderPassImpl::GetVkHandle()
-{
-  return mVkRenderPass;
-}
-
-bool RenderPassImpl::OnDestroy()
+void RenderPassImpl::Destroy()
 {
   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<VkRenderPass>(renderPass))
-      device.destroyRenderPass(renderPass, allocator); });
+
+    DALI_LOG_INFO(gVulkanFilter, Debug::General, "Destroying render pass: %p\n", static_cast<VkRenderPass>(renderPass));
+    device.destroyRenderPass(renderPass, allocator);
 
     mVkRenderPass = nullptr;
   }
-  return false;
+}
+
+vk::RenderPass RenderPassImpl::GetVkHandle()
+{
+  return mVkRenderPass;
 }
 
 std::vector<vk::ImageView>& RenderPassImpl::GetAttachments()
index 612263476dabcfc460b15521cd391b0c5dfb0902..ade80a0b6cff5b6c96f70a22ad5c3dd83e500caf 100644 (file)
@@ -41,7 +41,7 @@ class RenderTarget;
  * FramebufferImpl will create a separate compatible RenderPassImpl if a matching
  * render pass is NOT found.
  */
-class RenderPassImpl final : public Dali::Graphics::Vulkan::VkManaged
+class RenderPassImpl
 {
 public:
   struct CreateInfo
@@ -61,11 +61,11 @@ public:
 
   RenderPassImpl(Vulkan::Device& device, const std::vector<FramebufferAttachment*>& colorAttachments, FramebufferAttachment* depthAttachment);
 
-  ~RenderPassImpl() override;
+  ~RenderPassImpl();
 
-  vk::RenderPass GetVkHandle();
+  void Destroy();
 
-  bool OnDestroy() override;
+  vk::RenderPass GetVkHandle();
 
   std::vector<vk::ImageView>& GetAttachments();
 
index d3c43100211a68a0c69cdf32580729848a70c26e..15dcb08890296714ac15864cbc822086b2c99db5 100644 (file)
@@ -60,6 +60,23 @@ public:
    */
   void DiscardResource() override;
 
+  /**
+   * @copydoc Graphics::Vulkan::Resource::GetAllocationCallbacks()
+   */
+  [[nodiscard]] const Graphics::AllocationCallbacks* GetAllocationCallbacks() const override
+  {
+    return mCreateInfo.allocationCallbacks;
+  }
+
+  /**
+   * @copydoc Graphics::Vulkan::Resource::InvokeDeleter()
+   * Only intended for use by discard queue.
+   */
+  void InvokeDeleter() override
+  {
+    this->~RenderTarget();
+  }
+
   /**
    * @brief Returns framebuffer associated with the render target
    */
@@ -91,4 +108,4 @@ private:
 
 } // namespace Dali::Graphics::Vulkan
 
-#endif //DALI_INTERNAL_GRAPHICS_VULKAN_RENDER_TARGET_H
+#endif // DALI_INTERNAL_GRAPHICS_VULKAN_RENDER_TARGET_H
index f35d10048a45fe0a736214a9d964b34544c3f059..b950c3d3e8bab48d9d112a41c316379d1d6e242d 100644 (file)
@@ -39,13 +39,25 @@ SamplerImpl::SamplerImpl(Device& device, const vk::SamplerCreateInfo& samplerCre
 {
 }
 
-SamplerImpl::~SamplerImpl() = default;
+SamplerImpl::~SamplerImpl()
+{
+  Destroy();
+}
 
 void SamplerImpl::Initialize()
 {
   VkAssert(mDevice.GetLogicalDevice().createSampler(&mCreateInfo, &mDevice.GetAllocator("SAMPLER"), &mSampler));
 }
 
+void SamplerImpl::Destroy()
+{
+  if(mSampler)
+  {
+    mDevice.GetLogicalDevice().destroySampler(mSampler);
+    mSampler = nullptr;
+  }
+}
+
 vk::Sampler SamplerImpl::GetVkHandle() const
 {
   return mSampler;
index e8f040e1e2c147d76d5bcad627e51f9387c78831..7028627b0e6d21dd90dc605f7e8a9f848aa17741 100644 (file)
@@ -36,6 +36,8 @@ public:
 
   void Initialize();
 
+  void Destroy();
+
   /**
    * Returns VkSampler object
    * @return
index ffc2b5b8da220339c8ce9fa7435c98eed04b0547..4ad402bb55f00b87d03e7c03e6fcc21e5c53e83d 100644 (file)
@@ -24,7 +24,6 @@
 
 namespace Dali::Graphics::Vulkan
 {
-
 namespace
 {
 constexpr vk::Filter ConvertFilter(Dali::Graphics::SamplerFilter filter)
@@ -82,7 +81,11 @@ Sampler::~Sampler() = default;
 
 void Sampler::DestroyResource()
 {
-  // For now, no GPU resources are initialized so nothing to destroy
+  if(mSamplerImpl)
+  {
+    mSamplerImpl->Destroy();
+    mSamplerImpl = nullptr;
+  }
 }
 
 bool Sampler::InitializeResource()
index ac42ac0d9044b4c6469eaa19857aa8c7e94aac83..715a66eab4f54fa8a8e388b5790a3dd17cf31d80 100644 (file)
@@ -48,7 +48,7 @@ public:
   /**
    * @brief Called when GPU resources are destroyed
    */
-  void DestroyResource();
+  void DestroyResource() override;
 
   /**
    * @brief Called when initializing the resource
@@ -67,6 +67,23 @@ public:
     return mSamplerImpl;
   }
 
+  /**
+   * @copydoc Graphics::Vulkan::Resource::GetAllocationCallbacks()
+   */
+  [[nodiscard]] const Graphics::AllocationCallbacks* GetAllocationCallbacks() const override
+  {
+    return mCreateInfo.allocationCallbacks;
+  }
+
+  /**
+   * @copydoc Graphics::Vulkan::Resource::InvokeDeleter()
+   * Only intended for use by discard queue.
+   */
+  void InvokeDeleter() override
+  {
+    this->~Sampler();
+  }
+
 private:
   SamplerImpl* mSamplerImpl;
 };
index 3ecc55acba45b5fb28ccfa2ccbc815ee34bb5afc..fe89ecdcb62638983881072f21328e876fa626d2 100644 (file)
@@ -163,6 +163,12 @@ uint32_t ShaderImpl::Release()
   return mImpl->refCount;
 }
 
+void ShaderImpl::Destroy()
+{
+  mImpl->Destroy();
+  mImpl.reset();
+}
+
 [[nodiscard]] uint32_t ShaderImpl::IncreaseFlushCount()
 {
   return ++mImpl->flushCount;
index 288dac426bb59b7d7677a147324d1a0f884adc23..06e90c39e0407da69bd24dc201451d927bf50ee7 100644 (file)
@@ -21,7 +21,9 @@
 // INTERNAL INCLUDES
 #include <dali/graphics-api/graphics-shader-create-info.h>
 #include <dali/graphics-api/graphics-shader.h>
-#include <dali/internal/graphics/vulkan-impl/vulkan-graphics-resource.h>
+
+#include <dali/internal/graphics/vulkan-impl/vulkan-graphics-controller.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-types.h>
 
 // EXTERNAL INCLUDES
 #include <vulkan/vulkan.hpp>
@@ -36,7 +38,7 @@ public:
    * @param[in] createInfo Valid createInfo structure
    * @param[in] controller Reference to the controller
    */
-  ShaderImpl(const Graphics::ShaderCreateInfo& createInfo, Graphics::Vulkan::VulkanGraphicsController& controller);
+  ShaderImpl(const Graphics::ShaderCreateInfo& createInfo, VulkanGraphicsController& controller);
 
   /**
    * @brief destructor
@@ -61,6 +63,11 @@ public:
    */
   [[nodiscard]] uint32_t GetRefCount() const;
 
+  /**
+   * @brief Destroys Vulkan shader module
+   */
+  void Destroy();
+
   /**
    * Whilst unreferenced, increase the flush count and return it
    *
@@ -82,11 +89,6 @@ public:
    */
   [[nodiscard]] bool Compile() const;
 
-  /**
-   * @brief Destroys Vulkan shader module
-   */
-  void Destroy();
-
   /**
    * @brief Returns Vulkan resource
    * @return Valid Vulkan shader resource
index ba41033ad2e138969da75acf452826320090bd52..f98bf8a9896bf5bde40e87ae9bb8d8e516861f37 100644 (file)
@@ -19,8 +19,8 @@
 #include <dali/internal/graphics/vulkan-impl/vulkan-surface-impl.h>
 
 // INTERNAL INCLUDES
-#include <dali/internal/graphics/vulkan/vulkan-device.h>
 #include <dali/integration-api/debug.h>
+#include <dali/internal/graphics/vulkan/vulkan-device.h>
 
 #if defined(DEBUG_ENABLED)
 extern Debug::Filter* gVulkanFilter;
@@ -29,13 +29,30 @@ extern Debug::Filter* gVulkanFilter;
 namespace Dali::Graphics::Vulkan
 {
 
-SurfaceImpl::SurfaceImpl( Device& device, vk::SurfaceKHR surfaceKhr)
-: mGraphicsDevice( device ),
+SurfaceImpl::SurfaceImpl(Device& device, vk::SurfaceKHR surfaceKhr)
+: mGraphicsDevice(device),
   mSurface(surfaceKhr)
 {
 }
 
-SurfaceImpl::~SurfaceImpl() = default;
+SurfaceImpl::~SurfaceImpl()
+{
+  Destroy();
+};
+
+void SurfaceImpl::Destroy()
+{
+  if(mSurface)
+  {
+    auto instance  = mGraphicsDevice.GetInstance();
+    auto surface   = mSurface;
+    auto allocator = &mGraphicsDevice.GetAllocator();
+
+    DALI_LOG_INFO(gVulkanFilter, Debug::General, "Destroying surface: %p\n", static_cast<VkSurfaceKHR>(surface));
+    instance.destroySurfaceKHR(surface, allocator);
+    mSurface = nullptr;
+  }
+}
 
 vk::SurfaceKHR SurfaceImpl::GetVkHandle() const
 {
@@ -54,42 +71,43 @@ vk::SurfaceCapabilitiesKHR& SurfaceImpl::GetCapabilities()
 
 bool SurfaceImpl::GetSupportedFormats(
   vk::SurfaceFormatKHR requestedFormat,
-  vk::Format& swapchainImageFormat,
-  vk::ColorSpaceKHR& swapchainColorSpace)
+  vk::Format&          swapchainImageFormat,
+  vk::ColorSpaceKHR&   swapchainColorSpace)
 {
-  bool found=false;
-  auto supportedFormats = VkAssert( mGraphicsDevice.GetPhysicalDevice().getSurfaceFormatsKHR( mSurface ) );
+  bool found            = false;
+  auto supportedFormats = VkAssert(mGraphicsDevice.GetPhysicalDevice().getSurfaceFormatsKHR(mSurface));
 
   // If the surface format list only includes one entry with VK_FORMAT_UNDEFINED,
   // there is no preferred format, so we assume vk::Format::eB8G8R8A8Unorm
-  if( supportedFormats.size() == 1 && supportedFormats[0].format == vk::Format::eUndefined )
+  if(supportedFormats.size() == 1 && supportedFormats[0].format == vk::Format::eUndefined)
   {
-    swapchainColorSpace = supportedFormats[0].colorSpace;
+    swapchainColorSpace  = supportedFormats[0].colorSpace;
     swapchainImageFormat = vk::Format::eB8G8R8A8Unorm;
   }
   else // Try to find the requested format in the list
   {
     auto iter = std::find_if(supportedFormats.begin(),
                              supportedFormats.end(),
-                             [ & ]( vk::SurfaceFormatKHR supportedFormat ) {
+                             [&](vk::SurfaceFormatKHR supportedFormat)
+                             {
                                return requestedFormat == supportedFormat.format;
-                             } );
+                             });
     // If found assign it.
-    if( iter != supportedFormats.end() )
+    if(iter != supportedFormats.end())
     {
-      found = true;
-      auto surfaceFormat = *iter;
-      swapchainColorSpace = surfaceFormat.colorSpace;
+      found                = true;
+      auto surfaceFormat   = *iter;
+      swapchainColorSpace  = surfaceFormat.colorSpace;
       swapchainImageFormat = surfaceFormat.format;
     }
     else // Requested format not found...attempt to use the first one on the list
     {
-      auto surfaceFormat = supportedFormats[0];
-      swapchainColorSpace = surfaceFormat.colorSpace;
+      auto surfaceFormat   = supportedFormats[0];
+      swapchainColorSpace  = surfaceFormat.colorSpace;
       swapchainImageFormat = surfaceFormat.format;
     }
   }
-  assert( swapchainImageFormat != vk::Format::eUndefined && "Could not find a supported swap chain image format." );
+  assert(swapchainImageFormat != vk::Format::eUndefined && "Could not find a supported swap chain image format.");
   return found;
 }
 
@@ -99,29 +117,10 @@ std::vector<vk::PresentModeKHR> SurfaceImpl::GetSurfacePresentModes()
   return presentModes;
 }
 
-void SurfaceImpl::UpdateSize( unsigned int width, unsigned int height )
+void SurfaceImpl::UpdateSize(unsigned int width, unsigned int height)
 {
-  mCapabilities.currentExtent.width = width;
+  mCapabilities.currentExtent.width  = width;
   mCapabilities.currentExtent.height = height;
 }
 
-bool SurfaceImpl::OnDestroy()
-{
-  if( mSurface )
-  {
-    auto instance = mGraphicsDevice.GetInstance();
-    auto surface = mSurface;
-    auto allocator = &mGraphicsDevice.GetAllocator();
-
-    mGraphicsDevice.DiscardResource( [ instance, surface, allocator ]() {
-      DALI_LOG_INFO( gVulkanFilter, Debug::General, "Invoking deleter function: surface->%p\n",
-                     static_cast< VkSurfaceKHR >( surface ) )
-      instance.destroySurfaceKHR( surface, allocator );
-    } );
-
-    mSurface = nullptr;
-  }
-  return false;
-}
-
 } // namespace Dali::Graphics::Vulkan
index 0542131abbf29a634665a846dd21651bd6ab4652..73744657b025c195ea8e6739c7041a42c20d9602 100644 (file)
@@ -25,12 +25,14 @@ namespace Dali::Graphics::Vulkan
 {
 class Device;
 
-class SurfaceImpl final : public Dali::Graphics::Vulkan::VkManaged
+class SurfaceImpl
 {
 public:
   explicit SurfaceImpl(Device& device, vk::SurfaceKHR surfaceKhr);
 
-  ~SurfaceImpl() final;
+  ~SurfaceImpl();
+
+  void Destroy();
 
   /**
    * @return the handle to this surface
@@ -57,16 +59,14 @@ public:
    */
   bool GetSupportedFormats(
     vk::SurfaceFormatKHR requestedFormat,
-    vk::Format& swapchainImageFormat,
-    vk::ColorSpaceKHR& swapchainColorSpace);
+    vk::Format&          swapchainImageFormat,
+    vk::ColorSpaceKHR&   swapchainColorSpace);
 
   /**
    * Update size of surface
    */
   void UpdateSize(unsigned int width, unsigned int height);
 
-  bool OnDestroy() override;
-
 private:
   Device&                    mGraphicsDevice;
   vk::SurfaceKHR             mSurface;
index 1f4f0ae980e633df3bf8dc195ca71a6300ac2e2e..87ea40c6241b5065a519e6d2377d19bf7a068a14 100644 (file)
@@ -100,7 +100,9 @@ Swapchain::Swapchain(Device& graphicsDevice, Queue& presentationQueue)
 {
 }
 
-Swapchain::~Swapchain() = default;
+Swapchain::~Swapchain()
+{
+}
 
 void Swapchain::CreateVkSwapchain(
   vk::SwapchainKHR   oldSwapchain,
@@ -161,7 +163,8 @@ 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;
                             });
 
@@ -193,6 +196,22 @@ void Swapchain::CreateVkSwapchain(
   mSwapchainKHR = VkAssert(mGraphicsDevice.GetLogicalDevice().createSwapchainKHR(mSwapchainCreateInfoKHR, mGraphicsDevice.GetAllocator()));
 }
 
+void Swapchain::Destroy()
+{
+  if(mSwapchainKHR)
+  {
+    auto device    = mGraphicsDevice.GetLogicalDevice();
+    auto swapchain = mSwapchainKHR;
+    auto allocator = &mGraphicsDevice.GetAllocator();
+    mFramebuffers.clear();
+    mSwapchainBuffers.clear();
+
+    DALI_LOG_INFO(gVulkanFilter, Debug::General, "Destroying SwapChain: %p\n", static_cast<VkSwapchainKHR>(swapchain));
+    device.destroySwapchainKHR(swapchain, allocator);
+    mSwapchainKHR = nullptr;
+  }
+}
+
 void Swapchain::CreateFramebuffers()
 {
   assert(mSwapchainKHR && "Needs a swapchain before creating framebuffers");
@@ -227,19 +246,28 @@ void Swapchain::CreateFramebuffers()
                                                               mSwapchainCreateInfoKHR.imageFormat,
                                                               mSwapchainCreateInfoKHR.imageExtent);
 
-    auto colorImageView = ImageView::NewFromImage(mGraphicsDevice, *colorImage);
+    std::unique_ptr<ImageView> colorImageView;
+    colorImageView.reset(ImageView::NewFromImage(mGraphicsDevice, *colorImage));
 
     // A new color attachment for each framebuffer
-    auto colorAttachment = FramebufferAttachment::NewColorAttachment(colorImageView,
-                                                                     clearColor,
-                                                                     true); // presentable
-
-    mFramebuffers.push_back(FramebufferImpl::New(mGraphicsDevice,
-                                                 compatibleRenderPass,
-                                                 {colorAttachment},
-                                                 nullptr,
-                                                 mSwapchainCreateInfoKHR.imageExtent.width,
-                                                 mSwapchainCreateInfoKHR.imageExtent.height));
+    OwnedAttachments attachments;
+    attachments.emplace_back(FramebufferAttachment::NewColorAttachment(colorImageView,
+                                                                       clearColor,
+                                                                       true));
+    std::unique_ptr<FramebufferAttachment>                       depthAttachment;
+    std::unique_ptr<FramebufferImpl, void (*)(FramebufferImpl*)> framebuffer(
+      FramebufferImpl::New(mGraphicsDevice,
+                           compatibleRenderPass,
+                           attachments,
+                           depthAttachment,
+                           mSwapchainCreateInfoKHR.imageExtent.width,
+                           mSwapchainCreateInfoKHR.imageExtent.height),
+      [](FramebufferImpl* framebuffer1)
+      {
+        framebuffer1->Destroy();
+        delete framebuffer1;
+      });
+    mFramebuffers.push_back(std::move(framebuffer));
 
     if(compatibleRenderPass == nullptr)
     {
@@ -264,7 +292,7 @@ FramebufferImpl* Swapchain::GetCurrentFramebuffer() const
 
 FramebufferImpl* Swapchain::GetFramebuffer(uint32_t index) const
 {
-  return mFramebuffers[index];
+  return mFramebuffers[index].get();
 }
 
 FramebufferImpl* Swapchain::AcquireNextFramebuffer(bool shouldCollectGarbageNow)
@@ -319,8 +347,8 @@ FramebufferImpl* Swapchain::AcquireNextFramebuffer(bool shouldCollectGarbageNow)
   // cause a stall ( nvidia, ubuntu )
   if(mFrameCounter >= mSwapchainBuffers.size())
   {
-    vk::Result result = swapchainBuffer->endOfFrameFence->GetStatus();
-    if(result == vk::Result::eNotReady)
+    vk::Result status = swapchainBuffer->endOfFrameFence->GetStatus();
+    if(status == vk::Result::eNotReady)
     {
       swapchainBuffer->endOfFrameFence->Wait();
       swapchainBuffer->endOfFrameFence->Reset();
@@ -332,7 +360,7 @@ FramebufferImpl* Swapchain::AcquireNextFramebuffer(bool shouldCollectGarbageNow)
   }
   // mGraphicsDevice.CollectGarbage();
 
-  return mFramebuffers[mSwapchainImageIndex];
+  return mFramebuffers[mSwapchainImageIndex].get();
 }
 
 void Swapchain::Submit(CommandBufferImpl* commandBuffer)
@@ -391,23 +419,6 @@ void Swapchain::Present()
   mFrameCounter++;
 }
 
-bool Swapchain::OnDestroy()
-{
-  if(mSwapchainKHR)
-  {
-    auto device    = mGraphicsDevice.GetLogicalDevice();
-    auto swapchain = mSwapchainKHR;
-    auto allocator = &mGraphicsDevice.GetAllocator();
-
-    mGraphicsDevice.DiscardResource([device, swapchain, allocator]() {
-      DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: swap chain->%p\n", static_cast<VkSwapchainKHR>(swapchain))
-      device.destroySwapchainKHR(swapchain, allocator); });
-
-    mSwapchainKHR = nullptr;
-  }
-  return false;
-}
-
 bool Swapchain::IsValid() const
 {
   return mIsValid;
index aacaa7327b28464a1dfc595382780606e16668d9..92380475f2c581cf6111dada6126880de50ceaf5 100644 (file)
@@ -33,7 +33,7 @@ class SwapchainBuffer;
 /**
  * Creates swapchain for given surface and queue
  */
-class Swapchain : public VkManaged
+class Swapchain
 {
 public:
   static Swapchain* NewSwapchain(
@@ -47,11 +47,13 @@ public:
 
   Swapchain(Device& graphicsDevice, Queue& presentationQueue);
 
-  ~Swapchain() override;
+  ~Swapchain();
 
   Swapchain(const Swapchain&)            = delete;
   Swapchain& operator=(const Swapchain&) = delete;
 
+  void Destroy();
+
   /**
    * Automatically create framebuffers (generating compatible render passes)
    */
@@ -94,8 +96,6 @@ public:
    */
   void Present();
 
-  bool OnDestroy() override;
-
   /**
    * Returns true when swapchain expired
    * @return
@@ -143,16 +143,14 @@ private:
   /**
    * FramebufferImpl object associated with the buffer
    */
-  std::vector<FramebufferImpl*> mFramebuffers;
+  using OwnedFramebuffer = std::unique_ptr<FramebufferImpl, void (*)(FramebufferImpl*)>;
+  std::vector<OwnedFramebuffer> mFramebuffers;
 
   /**
    * Array of swapchain buffers
    */
   std::vector<std::unique_ptr<SwapchainBuffer>> mSwapchainBuffers;
-
-  FenceImpl* mBetweenRenderPassFence{};
-
-  uint32_t mFrameCounter{0u}; ///< Current frame number
+  uint32_t                                      mFrameCounter{0u}; ///< Current frame number
 
   bool mIsValid; // indicates whether the swapchain is still valid or requires to be recreated
 };
index fa6a1f8dfc0dd3dbec6776874104cbcbae6fd5f2..2121f0b6868cb4119bcc9e9c63400417c92ae5f5 100644 (file)
@@ -928,7 +928,8 @@ bool Texture::TryConvertPixelData(const void* pData, uint32_t sizeInBytes, uint3
     return false;
   }
 
-  auto it = std::find_if(COLOR_CONVERSION_TABLE.begin(), COLOR_CONVERSION_TABLE.end(), [&](auto& item) { return item.oldFormat == mConvertFromFormat; });
+  auto it = std::find_if(COLOR_CONVERSION_TABLE.begin(), COLOR_CONVERSION_TABLE.end(), [&](auto& item)
+                         { return item.oldFormat == mConvertFromFormat; });
 
   // No suitable format, return empty array
   if(it == COLOR_CONVERSION_TABLE.end())
@@ -950,7 +951,8 @@ bool Texture::TryConvertPixelData(const void* pData, uint32_t sizeInBytes, uint3
     return false;
   }
 
-  auto it = std::find_if(COLOR_CONVERSION_TABLE.begin(), COLOR_CONVERSION_TABLE.end(), [&](auto& item) { return item.oldFormat == mConvertFromFormat; });
+  auto it = std::find_if(COLOR_CONVERSION_TABLE.begin(), COLOR_CONVERSION_TABLE.end(), [&](auto& item)
+                         { return item.oldFormat == mConvertFromFormat; });
 
   // No suitable format, return empty array
   if(it == COLOR_CONVERSION_TABLE.end())
@@ -1099,7 +1101,8 @@ vk::Format Texture::ValidateFormat(vk::Format sourceFormat)
   // if format isn't supported, see whether suitable conversion is implemented
   if(!formatFlags)
   {
-    auto it = std::find_if(COLOR_CONVERSION_TABLE.begin(), COLOR_CONVERSION_TABLE.end(), [&](auto& item) { return item.oldFormat == sourceFormat; });
+    auto it = std::find_if(COLOR_CONVERSION_TABLE.begin(), COLOR_CONVERSION_TABLE.end(), [&](auto& item)
+                           { return item.oldFormat == sourceFormat; });
 
     // No suitable format, return empty array
     if(it != COLOR_CONVERSION_TABLE.end())
@@ -1160,10 +1163,26 @@ bool Texture::InitializeResource()
 
 void Texture::DestroyResource()
 {
+  if(mImageView)
+  {
+    mImageView->Destroy();
+    mImageView = nullptr;
+  }
+  if(mImage)
+  {
+    mImage->Destroy();
+    mImage = nullptr;
+  }
+  if(mSampler)
+  {
+    mSampler->Destroy();
+    mSampler = nullptr;
+  }
 }
 
 void Texture::DiscardResource()
 {
+  mController.DiscardResource(this);
 }
 
 void Texture::SetFormatAndUsage()
index b64f977554fd0baa56ab6e23c9bcc1d343bdfcb5..d3d16beace846098cacd5b3db435ada5db91b804 100644 (file)
@@ -42,11 +42,36 @@ public:
   Texture(const Graphics::TextureCreateInfo& createInfo, VulkanGraphicsController& controller);
   ~Texture();
 
+  /**
+   * @copydoc Graphics::Vulkan::Resource::InitializeResource();
+   */
   bool InitializeResource() override;
 
+  /**
+   * @copydoc Graphics::Vulkan::Resource::DiscardResource();
+   */
+  void DiscardResource() override;
+  /**
+   * @copydoc Graphics::Vulkan::Resource::DestroyResource();
+   */
   void DestroyResource() override;
 
-  void DiscardResource() override;
+  /**
+   * @copydoc Graphics::Vulkan::Resource::GetAllocationCallbacks()
+   */
+  [[nodiscard]] const Graphics::AllocationCallbacks* GetAllocationCallbacks() const override
+  {
+    return mCreateInfo.allocationCallbacks;
+  }
+
+  /**
+   * @copydoc Graphics::Vulkan::Resource::InvokeDeleter()
+   * Only intended for use by discard queue.
+   */
+  void InvokeDeleter() override
+  {
+    this->~Texture();
+  }
 
   bool IsSamplerImmutable() const;
 
index 5d9b1e0b7273efd83ae88596ff673f1d72d0492c..1810932db7da5bd02a8daa073e5582061d4820d4 100644 (file)
@@ -35,7 +35,6 @@
 
 namespace Dali::Graphics
 {
-
 namespace
 {
 // Default value use to clear the stencil buffer
@@ -50,7 +49,6 @@ std::unique_ptr<T> MakeUnique(Args&&... args)
 
 namespace Vulkan
 {
-
 /**
  * Forward class declarations
  */
@@ -194,12 +192,12 @@ struct VkStoreOpType
   vk::AttachmentStoreOp storeOp{vk::AttachmentStoreOp::eDontCare};
 };
 
-class VkManaged
+class VkSharedResource // E.g. render pass
 {
 public:
-  VkManaged() = default;
+  VkSharedResource() = default;
 
-  virtual ~VkManaged() = default;
+  virtual ~VkSharedResource() = default;
 
   void Release()
   {
index 2796b7fbf799cbdca2630a0c13f291cd1cf9ba3d..5065b96687118a1941fc40128714b3afbe038b72 100644 (file)
@@ -95,6 +95,7 @@ Device::~Device()
   DALI_LOG_STREAM(gVulkanFilter, Debug::General, "DESTROYING GRAPHICS CONTEXT--------------------------------\n");
 
   SwapBuffers();
+  ReleaseCommandPools();
 
   // We are done with all resources (technically... . If not we will get a ton of validation layer errors)
   // Kill the Vulkan logical device
@@ -379,7 +380,8 @@ Swapchain* Device::CreateSwapchain(SurfaceImpl*       surface,
     // during replacing the swapchain
     auto khr = oldSwapchain->GetVkHandle();
     oldSwapchain->SetVkHandle(nullptr);
-    oldSwapchain->Release();
+    oldSwapchain->Destroy();
+    delete oldSwapchain;
 
     mLogicalDevice.destroySwapchainKHR(khr, *mAllocator);
   }
@@ -437,8 +439,8 @@ Queue& Device::GetPresentQueue() const
 
 void Device::DiscardResource(std::function<void()> deleter)
 {
-  // std::lock_guard< std::mutex > lock( mMutex );
-  // mDiscardQueue[mCurrentBufferIndex].push_back( std::move( deleter ) );
+  // For now, just call immediately.
+  deleter();
 }
 
 Image* Device::CreateImageFromExternal(vk::Image externalImage, vk::Format imageFormat, vk::Extent2D extent)
@@ -543,6 +545,15 @@ CommandPool* Device::GetCommandPool(std::thread::id threadId)
   return commandPool;
 }
 
+void Device::ReleaseCommandPools()
+{
+  for(auto& commandPool : mCommandPools)
+  {
+    commandPool.second->Reset(true);
+    delete commandPool.second;
+  }
+}
+
 void Device::SurfaceResized(unsigned int width, unsigned int height)
 {
   // Get main window's surface
index 3742807fd8f1bd185c40dc6ca1673374feb5d38b..e40de4b167594800420faee06884ba3b6dcf5918 100644 (file)
@@ -153,6 +153,8 @@ private: // Methods
 
   std::vector<const char*> PrepareDefaultInstanceExtensions();
 
+  void ReleaseCommandPools();
+
 private: // Members
   vk::PhysicalDevice mPhysicalDevice;
   vk::Device         mLogicalDevice;
@@ -166,10 +168,10 @@ private: // Members
   std::vector<vk::QueueFamilyProperties> mQueueFamilyProperties;
 
   // Sets of queues
-  std::vector<std::unique_ptr<Queue> > mAllQueues;
-  std::vector<Queue*>                  mGraphicsQueues;
-  std::vector<Queue*>                  mTransferQueues;
-  std::vector<Queue*>                  mComputeQueues;
+  std::vector<std::unique_ptr<Queue>> mAllQueues;
+  std::vector<Queue*>                 mGraphicsQueues;
+  std::vector<Queue*>                 mTransferQueues;
+  std::vector<Queue*>                 mComputeQueues;
 
   CommandPoolMap mCommandPools;
 
index 43ffa2b6c001c6e5ecad4f19fa8b73d6a8b69f13..e9680d745ce033bb9bfa51f7bfefec13df6f69b1 100644 (file)
@@ -98,9 +98,9 @@ Graphics::SurfaceId VulkanGraphics::CreateSurface(
   return surfaceId;
 }
 
-void VulkanGraphics::DestroySurface(Graphics::SurfaceId)
+void VulkanGraphics::DestroySurface(Graphics::SurfaceId surfaceId)
 {
-  // @todo Destroy swapchain.
+  mGraphicsDevice.DestroySurface(surfaceId);
 }
 
 bool VulkanGraphics::ReplaceSurface(Graphics::SurfaceId surface, int width, int height)
@@ -132,6 +132,7 @@ void VulkanGraphics::Shutdown()
 
 void VulkanGraphics::Destroy()
 {
+  mGraphicsController.RunGarbageCollector(0);
 }
 
 void VulkanGraphics::Pause()