Refactored the Vulkan::Image class
authorAngelos Gkountis <a.gkountis@samsung.com>
Wed, 30 May 2018 14:32:52 +0000 (15:32 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Mon, 11 Jun 2018 16:50:56 +0000 (16:50 +0000)
> Removed the PIMPL pattern.
> Renamed the static method New that created a RefCountedImage from an external Vulkan image handle to NewFromExternal.
> Removed the Vk prefix from certain getter methods in the Vulkan::Image class.
> Moved the image creation login to the Vulkan::Graphics class.
> Moved the image memory binding logic to the Vulkan::Graphics class.
> Renamed the BindMemory method of the Vulkan::Image class to AssingMemory.
> AssignMemory now only assigns the RefCountedGpuMemoryBlock to the image to increase the ref count. To bind memory to an image, users should use the Graphics::BindImageMemory(<image>, <memory>, <offset>) method.
> Altered already existing image creation code to use the new paradigm.

Change-Id: I32bd621dcd59eac7c24a0759798bde15a7870083

dali/graphics/vulkan/tests/texture-test.cpp
dali/graphics/vulkan/vulkan-framebuffer.cpp
dali/graphics/vulkan/vulkan-graphics-texture.cpp
dali/graphics/vulkan/vulkan-graphics.cpp
dali/graphics/vulkan/vulkan-graphics.h
dali/graphics/vulkan/vulkan-image-view.h
dali/graphics/vulkan/vulkan-image.cpp
dali/graphics/vulkan/vulkan-image.h
dali/graphics/vulkan/vulkan-resource-cache.h
dali/graphics/vulkan/vulkan-swapchain.cpp

index 71198ba..23dbfce 100644 (file)
@@ -68,22 +68,25 @@ struct Texture
   bool Initialise()
   {
     // create image
-    mImage = Image::New( mGraphics,
-                         vk::ImageCreateInfo{}
-                           .setFormat( mPixmap.pixelFormat )
-                           .setInitialLayout( vk::ImageLayout::ePreinitialized )
-                           .setSamples( vk::SampleCountFlagBits::e1 )
-                           .setSharingMode( vk::SharingMode::eExclusive )
-                           .setUsage( vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst )
-                           .setExtent( {mPixmap.width, mPixmap.height, 1} )
-                           .setArrayLayers( 1 )
-                           .setImageType( vk::ImageType::e2D )
-                           .setTiling( vk::ImageTiling::eOptimal )
-                           .setMipLevels( 1 ) );
-
-    // allocate memory and bind to the image
-    auto& allocator = mGraphics.GetDeviceMemoryManager().GetDefaultAllocator();
-    mImage->BindMemory( allocator.Allocate( mImage, vk::MemoryPropertyFlagBits::eDeviceLocal ) );
+    auto imageCreateInfo = vk::ImageCreateInfo{}
+            .setFormat( mPixmap.pixelFormat )
+            .setInitialLayout( vk::ImageLayout::ePreinitialized )
+            .setSamples( vk::SampleCountFlagBits::e1 )
+            .setSharingMode( vk::SharingMode::eExclusive )
+            .setUsage( vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst )
+            .setExtent( {mPixmap.width, mPixmap.height, 1} )
+            .setArrayLayers( 1 )
+            .setImageType( vk::ImageType::e2D )
+            .setTiling( vk::ImageTiling::eOptimal )
+            .setMipLevels( 1 );
+
+    mImage = mGraphics.CreateImage( imageCreateInfo );
+
+    auto& allocator = mGraphics
+            .GetDeviceMemoryManager()
+            .GetDefaultAllocator();
+
+    mGraphics.BindImageMemory( mImage, allocator.Allocate( mImage, vk::MemoryPropertyFlagBits::eDeviceLocal ), 0 );
 
     // create transient buffer to copy data
     auto size = mPixmap.data.size()*sizeof(mPixmap.data[0]);
index 7ae876b..652ea84 100644 (file)
@@ -58,7 +58,7 @@ struct Framebuffer::Impl
       vk::AttachmentDescription attDesc{};
       attDesc.setSamples( vk::SampleCountFlagBits::e1 )
         .setInitialLayout( vk::ImageLayout::eUndefined )
-        .setFormat( colorAttachment->GetImage()->GetVkFormat() )
+        .setFormat( colorAttachment->GetImage()->GetFormat() )
         .setStencilStoreOp( vk::AttachmentStoreOp::eDontCare )
         .setStencilLoadOp( vk::AttachmentLoadOp::eDontCare )
         .setLoadOp( vk::AttachmentLoadOp::eClear )
@@ -87,7 +87,7 @@ struct Framebuffer::Impl
       vk::AttachmentDescription attDesc{};
       attDesc.setSamples( vk::SampleCountFlagBits::e1 )
              .setInitialLayout( vk::ImageLayout::eUndefined )
-             .setFormat( mDepthStencilImageViewAttachment->GetImage()->GetVkFormat() )
+             .setFormat( mDepthStencilImageViewAttachment->GetImage()->GetFormat() )
              .setStencilStoreOp( vk::AttachmentStoreOp::eDontCare )
              .setStencilLoadOp( vk::AttachmentLoadOp::eDontCare )
              .setLoadOp( vk::AttachmentLoadOp::eClear )
index 63afce1..800eb01 100644 (file)
@@ -154,27 +154,33 @@ struct Texture::Impl
     return true;
   }
 
-  // creates image with preallocated memory and default sampler, no data
+  // creates image with pre-allocated memory and default sampler, no data
   // uploaded at this point
   bool Initialise()
   {
-    //TODO: Create image using the Graphics class
     // create image
-    mImage = Image::New( mGraphics,
-                         vk::ImageCreateInfo{}
-                           .setFormat( mPixmap.pixelFormat )
-                           .setInitialLayout( vk::ImageLayout::ePreinitialized )
-                           .setSamples( vk::SampleCountFlagBits::e1 )
-                           .setSharingMode( vk::SharingMode::eExclusive )
-                           .setUsage( vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst )
-                           .setExtent( {mPixmap.width, mPixmap.height, 1} )
-                           .setArrayLayers( 1 )
-                           .setImageType( vk::ImageType::e2D )
-                           .setTiling( vk::ImageTiling::eOptimal )
-                           .setMipLevels( 1 ) );
-    // allocate memory and bind to the image
-    auto& allocator = mGraphics.GetDeviceMemoryManager().GetDefaultAllocator();
-    mImage->BindMemory( allocator.Allocate( mImage, vk::MemoryPropertyFlagBits::eDeviceLocal ) );
+    auto imageCreateInfo = vk::ImageCreateInfo{}
+            .setFormat( mPixmap.pixelFormat )
+            .setInitialLayout( vk::ImageLayout::ePreinitialized )
+            .setSamples( vk::SampleCountFlagBits::e1 )
+            .setSharingMode( vk::SharingMode::eExclusive )
+            .setUsage( vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst )
+            .setExtent( {mPixmap.width, mPixmap.height, 1} )
+            .setArrayLayers( 1 )
+            .setImageType( vk::ImageType::e2D )
+            .setTiling( vk::ImageTiling::eOptimal )
+            .setMipLevels( 1 );
+
+    // Create the image handle
+    mImage = mGraphics.CreateImage( imageCreateInfo );
+
+    // allocate memory for the image
+    auto memory = mGraphics.GetDeviceMemoryManager()
+            .GetDefaultAllocator()
+            .Allocate(mImage, vk::MemoryPropertyFlagBits::eDeviceLocal );
+
+    // bind the allocated memory to the image
+    mGraphics.BindImageMemory( mImage, memory, 0 );
 
     // create default image view
     mImageView = mGraphics.CreateImageView(mImage);
index 15ca0c9..8bb95ff 100644 (file)
@@ -36,6 +36,7 @@
 #include <dali/graphics/vulkan/vulkan-resource-cache.h>
 #include <dali/graphics/vulkan/vulkan-debug.h>
 #include <dali/graphics/vulkan/vulkan-fence.h>
+#include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-handle.h>
 
 #include <dali/graphics-api/graphics-api-controller.h>
 
@@ -289,9 +290,13 @@ RefCountedFramebuffer Graphics::CreateFramebuffer()
   NotImplemented()
 }
 
-RefCountedImage Graphics::CreateImage()
+RefCountedImage Graphics::CreateImage( const vk::ImageCreateInfo& imageCreateInfo )
 {
-  NotImplemented()
+  auto refCountedImage = Image::New(*this, imageCreateInfo);
+
+  VkAssert( mDevice.createImage( &imageCreateInfo, mAllocator.get(), refCountedImage->Ref() ) );
+
+  return refCountedImage;
 }
 
 RefCountedImageView Graphics::CreateImageView( const vk::ImageViewCreateFlags& flags,
@@ -321,16 +326,16 @@ RefCountedImageView Graphics::CreateImageView( RefCountedImage image )
   vk::ComponentMapping componentsMapping = { vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG,
                                              vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA };
   vk::ImageAspectFlags aspectFlags{};
-  if( image->GetVkImageUsageFlags() & vk::ImageUsageFlagBits::eColorAttachment )
+  if( image->GetUsageFlags() & vk::ImageUsageFlagBits::eColorAttachment )
   {
     aspectFlags |= vk::ImageAspectFlagBits::eColor;
     //componentsMapping = { vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eB,vk::ComponentSwizzle::eA };
   }
-  if( image->GetVkImageUsageFlags() & vk::ImageUsageFlagBits::eDepthStencilAttachment )
+  if( image->GetUsageFlags() & vk::ImageUsageFlagBits::eDepthStencilAttachment )
   {
     aspectFlags |= ( vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil );
   }
-  if( image->GetVkImageUsageFlags() & vk::ImageUsageFlagBits::eSampled )
+  if( image->GetUsageFlags() & vk::ImageUsageFlagBits::eSampled )
   {
     aspectFlags |= ( vk::ImageAspectFlagBits::eColor );
     //componentsMapping = { vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eR,vk::ComponentSwizzle::eA };
@@ -346,7 +351,7 @@ RefCountedImageView Graphics::CreateImageView( RefCountedImage image )
   return CreateImageView( {},
                           image,
                           vk::ImageViewType::e2D,
-                          image->GetVkFormat(),
+                          image->GetFormat(),
                           componentsMapping,
                           subresourceRange );
 }
@@ -424,6 +429,13 @@ vk::Result Graphics::ResetFences( const std::vector< RefCountedFence >& fences )
 
   return mDevice.resetFences( vkFenceHandles );
 }
+
+vk::Result Graphics::BindImageMemory( RefCountedImage image, RefCountedGpuMemoryBlock memory, uint32_t offset )
+{
+  auto result = VkAssert( mDevice.bindImageMemory( image->GetVkHandle(), *memory, offset ) );
+  image->AssignMemory(memory);
+  return result;
+}
 // --------------------------------------------------------------------------------------------------------------
 
 // Getters ------------------------------------------------------------------------------------------------------
@@ -612,6 +624,12 @@ void Graphics::RemoveBuffer( Buffer& buffer )
   mResourceCache->RemoveBuffer( buffer );
 }
 
+void Graphics::RemoveImage( Image& image )
+{
+  std::lock_guard< std::mutex > lock{ mMutex };
+  mResourceCache->RemoveImage( image );
+}
+
 void Graphics::RemoveShader( Shader& shader )
 {
   std::lock_guard< std::mutex > lock{ mMutex };
@@ -770,12 +788,8 @@ std::vector< vk::DeviceQueueCreateInfo > Graphics::GetQueueCreateInfos()
     {
       transferFamily = queueFamilyIndex;
     }
-    if( mPhysicalDevice.getSurfaceSupportKHR( queueFamilyIndex, mSurfaceFBIDMap.begin()
-                                                                               ->second
-                                                                               .surface
-                                                                               ->GetSurfaceKHR())
-                       .value &&
-        presentFamily == -1u )
+    if( mPhysicalDevice.getSurfaceSupportKHR( queueFamilyIndex, mSurfaceFBIDMap.begin()->second.
+            surface->GetSurfaceKHR()).value && presentFamily == -1u )
     {
       presentFamily = queueFamilyIndex;
     }
index 4cb64d8..af31ca3 100644 (file)
@@ -49,15 +49,25 @@ namespace Vulkan
 {
 
 class Buffer;
+
 class Image;
+
 class Pipeline;
+
 class Shader;
+
 class Framebuffer;
+
 class Surface;
+
 class CommandPool;
+
 class DescriptorPool;
+
 class GpuMemoryManager;
+
 class PipelineCache;
+
 class ResourceCache;
 
 using SurfaceFactory = Dali::Integration::Graphics::SurfaceFactory;
@@ -73,46 +83,72 @@ class Graphics
 
 public:
   Graphics();
-  Graphics(const Graphics&) = delete;
-  Graphics& operator=(const Graphics&) = delete;
+
+  Graphics( const Graphics& ) = delete;
+
+  Graphics& operator=( const Graphics& ) = delete;
+
   ~Graphics();
 
 public: // Create methods
 
-  void                                    Create();
-  void                                    CreateDevice();
-  FBID                                    CreateSurface(std::unique_ptr< SurfaceFactory > surfaceFactory);
-  RefCountedSwapchain                     CreateSwapchainForSurface( RefCountedSurface surface );
-  RefCountedShader                        CreateShader(); //will see if this will work
-  RefCountedPipeline                      CreatePipeline();
-  RefCountedFence                         CreateFence( const vk::FenceCreateInfo& fenceCreateInfo );
-  RefCountedBuffer                        CreateBuffer( size_t size, BufferType type );
-  RefCountedBuffer                        CreateBuffer( const vk::BufferCreateInfo& bufferCreateInfo );
-  RefCountedFramebuffer                   CreateFramebuffer();
-  RefCountedImage                         CreateImage();
-  RefCountedImageView                     CreateImageView(const vk::ImageViewCreateFlags& flags,
-                                                          const RefCountedImage& image,
-                                                          vk::ImageViewType viewType,
-                                                          vk::Format format,
-                                                          vk::ComponentMapping components,
-                                                          vk::ImageSubresourceRange subresourceRange);
-  RefCountedImageView                     CreateImageView(RefCountedImage image);
-  RefCountedDescriptorPool                CreateDescriptorPool();
-  RefCountedCommandPool                   CreateCommandPool(const vk::CommandPoolCreateInfo& info);
-  RefCountedCommandBuffer                 CreateCommandBuffer();
-  std::vector< RefCountedCommandBuffer >  CreateCommandBuffers();
-  RefCountedGpuMemoryBlock                CreateGpuMemoryBlock();
-  RefCountedDescriptorSet                 CreateDescriptorSet();
-  RefCountedSampler                       CreateSampler();
+  void Create();
+
+  void CreateDevice();
+
+  FBID CreateSurface( std::unique_ptr< SurfaceFactory > surfaceFactory );
+
+  RefCountedSwapchain CreateSwapchainForSurface( RefCountedSurface surface );
+
+  RefCountedShader CreateShader(); //will see if this will work
+  RefCountedPipeline CreatePipeline();
+
+  RefCountedFence CreateFence( const vk::FenceCreateInfo& fenceCreateInfo );
+
+  RefCountedBuffer CreateBuffer( size_t size, BufferType type );
+
+  RefCountedBuffer CreateBuffer( const vk::BufferCreateInfo& bufferCreateInfo );
+
+  RefCountedFramebuffer CreateFramebuffer();
+
+  RefCountedImage CreateImage( const vk::ImageCreateInfo& imageCreateInfo );
+
+  RefCountedImageView CreateImageView( const vk::ImageViewCreateFlags& flags,
+                                       const RefCountedImage& image,
+                                       vk::ImageViewType viewType,
+                                       vk::Format format,
+                                       vk::ComponentMapping components,
+                                       vk::ImageSubresourceRange subresourceRange );
+
+  RefCountedImageView CreateImageView( RefCountedImage image );
+
+  RefCountedDescriptorPool CreateDescriptorPool();
+
+  RefCountedCommandPool CreateCommandPool( const vk::CommandPoolCreateInfo& info );
+
+  RefCountedCommandBuffer CreateCommandBuffer();
+
+  std::vector< RefCountedCommandBuffer > CreateCommandBuffers();
+
+  RefCountedGpuMemoryBlock CreateGpuMemoryBlock();
+
+  RefCountedDescriptorSet CreateDescriptorSet();
+
+  RefCountedSampler CreateSampler();
 
 public: // Actions
   vk::Result WaitForFence( RefCountedFence fence, uint32_t timeout = 0 );
+
   vk::Result WaitForFences( const std::vector< RefCountedFence >& fences,
                             bool waitAll = true,
-                            uint32_t timeout = std::numeric_limits< uint32_t >::max() );
+                            uint32_t timeout = std::numeric_limits< uint32_t >::max());
+
   vk::Result ResetFence( RefCountedFence fence );
+
   vk::Result ResetFences( const std::vector< RefCountedFence >& fences );
 
+  vk::Result BindImageMemory( RefCountedImage image, RefCountedGpuMemoryBlock memory, uint32_t offset);
+
 public: // Getters
   RefCountedSurface GetSurface( FBID surfaceId );
 
@@ -132,9 +168,12 @@ public: // Getters
 
   const vk::PhysicalDeviceMemoryProperties& GetMemoryProperties() const;
 
-  Queue& GetGraphicsQueue(uint32_t index = 0u) const;
-  Queue& GetTransferQueue(uint32_t index = 0u) const;
-  Queue& GetComputeQueue(uint32_t index = 0u) const;
+  Queue& GetGraphicsQueue( uint32_t index = 0u ) const;
+
+  Queue& GetTransferQueue( uint32_t index = 0u ) const;
+
+  Queue& GetComputeQueue( uint32_t index = 0u ) const;
+
   Queue& GetPresentQueue() const;
 
   Platform GetDefaultPlatform() const;
@@ -146,76 +185,95 @@ public: // Getters
 public: //Cache management methods
 
   void AddBuffer( RefCountedBuffer buffer );
+
   void AddImage( RefCountedImage image );
+
   void AddShader( RefCountedShader shader );
+
   void AddCommandPool( RefCountedCommandPool pool );
+
   void AddDescriptorPool( RefCountedDescriptorPool pool );
+
   void AddFramebuffer( RefCountedFramebuffer framebuffer );
 
   RefCountedShader FindShader( vk::ShaderModule shaderModule );
+
   RefCountedImage FindImage( vk::Image image );
 
   void RemoveBuffer( Buffer& buffer );
+
+  void RemoveImage( Image& image );
+
   void RemoveShader( Shader& shader );
+
   void RemoveCommandPool( CommandPool& commandPool );
+
   void RemoveDescriptorPool( DescriptorPool& pool );
+
   void RemoveFramebuffer( Framebuffer& framebuffer );
+
   void RemoveSampler( Sampler& sampler );
 
   void CollectGarbage();
 
-  void DiscardResource(std::function<void()> deleter);
+  void DiscardResource( std::function< void() > deleter );
 
 private: // Methods
 
-  void                                      CreateInstance( const std::vector<const char*>& extensions,
-                                                            const std::vector<const char*>& validationLayers );
-  void                                      DestroyInstance();
-  void                                      PreparePhysicalDevice();
-  void                                      GetPhysicalDeviceProperties();
-  void                                      GetQueueFamilyProperties();
-  std::vector< vk::DeviceQueueCreateInfo >  GetQueueCreateInfos();
-  std::vector<const char*>                  PrepareDefaultInstanceExtensions();
+  void CreateInstance( const std::vector< const char* >& extensions,
+                       const std::vector< const char* >& validationLayers );
+
+  void DestroyInstance();
+
+  void PreparePhysicalDevice();
+
+  void GetPhysicalDeviceProperties();
+
+  void GetQueueFamilyProperties();
+
+  std::vector< vk::DeviceQueueCreateInfo > GetQueueCreateInfos();
+
+  std::vector< const char* > PrepareDefaultInstanceExtensions();
 
 private: // Members
 
-  std::unique_ptr<GpuMemoryManager>                           mDeviceMemoryManager;
+  std::unique_ptr< GpuMemoryManager > mDeviceMemoryManager;
 
-  vk::Instance                                                mInstance;
-  std::unique_ptr<vk::AllocationCallbacks>                    mAllocator{nullptr};
+  vk::Instance mInstance;
+  std::unique_ptr< vk::AllocationCallbacks > mAllocator{ nullptr };
 
   // physical device
   vk::PhysicalDevice mPhysicalDevice;
 
   // logical device
-  vk::Device                                                  mDevice;
+  vk::Device mDevice;
 
   // physical device properties
-  std::unique_ptr< vk::PhysicalDeviceProperties >             mPhysicalDeviceProperties;
-  std::unique_ptr< vk::PhysicalDeviceMemoryProperties >       mPhysicalDeviceMemoryProperties;
-  std::unique_ptr< vk::PhysicalDeviceFeatures >               mPhysicalDeviceFeatures;
+  std::unique_ptr< vk::PhysicalDeviceProperties > mPhysicalDeviceProperties;
+  std::unique_ptr< vk::PhysicalDeviceMemoryProperties > mPhysicalDeviceMemoryProperties;
+  std::unique_ptr< vk::PhysicalDeviceFeatures > mPhysicalDeviceFeatures;
 
   // queue family properties
-  std::vector< vk::QueueFamilyProperties >                    mQueueFamilyProperties;
+  std::vector< vk::QueueFamilyProperties > mQueueFamilyProperties;
 
-  std::unordered_map< FBID, SwapchainSurfacePair >            mSurfaceFBIDMap;
-  FBID mBaseFBID{0u};
+  std::unordered_map< FBID, SwapchainSurfacePair > mSurfaceFBIDMap;
+  FBID mBaseFBID{ 0u };
 
   // Sets of queues
-  std::vector< std::unique_ptr<Queue> >                       mGraphicsQueues;
-  std::vector< std::unique_ptr<Queue> >                       mTransferQueues;
-  std::vector< std::unique_ptr<Queue> >                       mComputeQueues;
+  std::vector< std::unique_ptr< Queue > > mGraphicsQueues;
+  std::vector< std::unique_ptr< Queue > > mTransferQueues;
+  std::vector< std::unique_ptr< Queue > > mComputeQueues;
   //std::unique_ptr< Queue > mPresentQueue;
 
-  Platform                                                    mPlatform  { Platform::UNDEFINED };
+  Platform mPlatform{ Platform::UNDEFINED };
 
-  std::unique_ptr<Dali::Graphics::VulkanAPI::Controller>      mGfxController;
+  std::unique_ptr< Dali::Graphics::VulkanAPI::Controller > mGfxController;
 
   // TODO: rename
-  std::unique_ptr<PipelineCache>                              mPipelineDatabase;
+  std::unique_ptr< PipelineCache > mPipelineDatabase;
 
-  std::mutex                                                  mMutex;
-  std::unique_ptr< ResourceCache >                            mResourceCache;
+  std::mutex mMutex;
+  std::unique_ptr< ResourceCache > mResourceCache;
 
 };
 
index f322ca7..fe2aa28 100644 (file)
@@ -82,6 +82,8 @@ public:
 
   operator vk::ImageView*();
 
+  //TODO: Use the graphics class to manage lifetime.
+
 private:
   ImageView( Graphics& graphics,
              RefCountedImage image,
index 16603b1..ac1b9f6 100644 (file)
@@ -25,143 +25,110 @@ namespace Graphics
 {
 namespace Vulkan
 {
-struct Image::Impl
-{
-  Impl( Image& owner, Graphics& graphics, vk::ImageCreateInfo createInfo, vk::Image externalImage = nullptr )
-  : mOwner( owner ),
-    mGraphics( graphics ),
-    mVkImage( externalImage ),
-    mCreateInfo( std::move( createInfo ) ),
-    mIsExternal( static_cast<bool>( externalImage ) )
-  {
-    mVkImageLayout = mCreateInfo.initialLayout;
-  }
-
-  ~Impl()
-  {
-    if( !mIsExternal )
-    {
-      // destroy
-    }
-  }
-
-  bool Initialise()
-  {
-    if( !mIsExternal )
-    {
-      mVkImage = VkAssert( mGraphics.GetDevice().createImage( mCreateInfo, mGraphics.GetAllocator() ) );
-      if( !mVkImage )
-      {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  void BindMemory( const RefCountedGpuMemoryBlock& handle )
-  {
-    mGraphics.GetDevice().bindImageMemory( mVkImage, *handle, 0 );
-    mDeviceMemory = handle;
-  }
-
-  Image&              mOwner;
-  Graphics&           mGraphics;
-  vk::Image           mVkImage;
-  vk::ImageLayout     mVkImageLayout;
-  vk::ImageCreateInfo mCreateInfo;
-
-  RefCountedGpuMemoryBlock   mDeviceMemory;
-  bool mIsExternal;
-};
 
 Image::~Image() = default;
 
 RefCountedImage Image::New( Graphics& graphics, vk::ImageCreateInfo createInfo )
 {
-  RefCountedImage retval( new Image( graphics, createInfo, nullptr ) );
-  if( !retval->mImpl->Initialise() )
-  {
-    retval.Reset();
-  }
-  else
-  {
-    graphics.AddImage( retval );
-  }
-  return retval;
+  return RefCountedImage( new Image( graphics, createInfo, nullptr ) );
 }
 
-RefCountedImage Image::New( Graphics& graphics, vk::ImageCreateInfo createInfo, vk::Image externalImage )
+RefCountedImage Image::NewFromExternal( Graphics& graphics, vk::ImageCreateInfo createInfo, vk::Image externalImage )
 {
-  RefCountedImage retval( new Image( graphics, createInfo, externalImage ) );
-  if( !retval->mImpl->Initialise() )
-  {
-    retval.Reset();
-  }
-  else
-  {
-    graphics.AddImage( retval );
-  }
-  return retval;
+  return RefCountedImage( new Image( graphics, createInfo, externalImage ) );
 }
 
 Image::Image( Graphics& graphics, const vk::ImageCreateInfo& createInfo, vk::Image externalImage )
+        : mGraphics(&graphics),
+          mCreateInfo(createInfo),
+          mImage(externalImage),
+          mImageLayout(mCreateInfo.initialLayout),
+          mIsExternal( static_cast<bool>(externalImage))
 {
-  mImpl = MakeUnique<Impl>( *this, graphics, createInfo, externalImage );
 }
 
 vk::Image Image::GetVkHandle() const
 {
-  return mImpl->mVkImage;
+  return mImage;
 }
 
-vk::ImageLayout Image::GetVkImageLayout() const
+vk::ImageLayout Image::GetImageLayout() const
 {
-  return mImpl->mVkImageLayout;
+  return mImageLayout;
 }
 
 uint32_t Image::GetWidth() const
 {
-  return mImpl->mCreateInfo.extent.width;
+  return mCreateInfo.extent.width;
 }
 
 uint32_t Image::GetHeight() const
 {
-  return mImpl->mCreateInfo.extent.height;
+  return mCreateInfo.extent.height;
 }
 
 uint32_t Image::GetLayerCount() const
 {
-  return mImpl->mCreateInfo.arrayLayers;
+  return mCreateInfo.arrayLayers;
 }
 
 uint32_t Image::GetMipLevelCount() const
 {
-  return mImpl->mCreateInfo.mipLevels;
+  return mCreateInfo.mipLevels;
+}
+
+vk::Format Image::GetFormat() const
+{
+  return mCreateInfo.format;
+}
+
+vk::ImageType Image::GetImageType() const
+{
+  return mCreateInfo.imageType;
+}
+
+vk::ImageTiling Image::GetImageTiling() const
+{
+  return mCreateInfo.tiling;
+}
+
+void Image::AssignMemory( RefCountedGpuMemoryBlock memory )
+{
+  mDeviceMemory = memory;
 }
 
-vk::Format Image::GetVkFormat() const
+const Image& Image::ConstRef()
 {
-  return mImpl->mCreateInfo.format;
+  return *this;
 }
 
-vk::ImageType Image::GetVkImageType() const
+Image& Image::Ref()
 {
-  return mImpl->mCreateInfo.imageType;
+  return *this;
 }
 
-vk::ImageTiling Image::GetVkImageTiling() const
+Image::operator vk::Image*()
 {
-  return mImpl->mCreateInfo.tiling;
+  return &mImage;
 }
 
-void Image::BindMemory( const RefCountedGpuMemoryBlock& handle )
+vk::ImageUsageFlags Image::GetUsageFlags() const
 {
-  mImpl->BindMemory( handle );
+  return mCreateInfo.usage;
 }
 
-vk::ImageUsageFlags Image::GetVkImageUsageFlags() const
+bool Image::OnDestroy()
 {
-  return mImpl->mCreateInfo.usage;
+  if( !mIsExternal )
+  {
+    mGraphics->RemoveImage(*this);
+
+    mGraphics->DiscardResource([this]() {
+      mGraphics->GetDevice().destroyImage(mImage, mGraphics->GetAllocator());
+    });
+  }
+
+  return false;
 }
 
 } // namespace Vulkan
index 1da112b..90e5647 100644 (file)
@@ -26,8 +26,7 @@ namespace Graphics
 {
 namespace Vulkan
 {
-class ImageView;
-using InternalVkImage = vk::Image;
+
 class Image : public VkManaged
 {
 public:
@@ -47,7 +46,7 @@ public:
    * @param image
    * @return
    */
-  static RefCountedImage New( Graphics& graphics, vk::ImageCreateInfo createInfo, vk::Image externalImage );
+  static RefCountedImage NewFromExternal( Graphics& graphics, vk::ImageCreateInfo createInfo, vk::Image externalImage );
 
   /**
    * Destructor
@@ -64,7 +63,7 @@ public:
    * Returns VkImageLayout associated with the image
    * @return
    */
-  vk::ImageLayout GetVkImageLayout() const;
+  vk::ImageLayout GetImageLayout() const;
 
   /**
    * Returns width in pixels
@@ -94,31 +93,42 @@ public:
    * Returns pixel format
    * @return
    */
-  vk::Format GetVkFormat() const;
+  vk::Format GetFormat() const;
 
   /**
    * returns image type ( VkImageType)
    * @return
    */
-  vk::ImageType GetVkImageType() const;
+  vk::ImageType GetImageType() const;
 
   /**
    * Returns used image tiling mode
    * @return
    */
-  vk::ImageTiling GetVkImageTiling() const;
+  vk::ImageTiling GetImageTiling() const;
 
   /**
    *
    * @return
    */
-  vk::ImageUsageFlags  GetVkImageUsageFlags() const;
+  vk::ImageUsageFlags  GetUsageFlags() const;
 
   /**
-   * Binds image memory
-   * @param handle
+   * Assigns the specified image memory to the image
+   * @warning This method does NOT bind the memory. Use Graphics::BindImageMemory instead
+   * @param memory The device memory to be assigned to the image
    */
-  void BindMemory( const RefCountedGpuMemoryBlock& handle );
+  void AssignMemory( RefCountedGpuMemoryBlock memory );
+
+  const Image& ConstRef();
+
+  Image& Ref();
+
+  operator vk::Image*();
+
+  bool OnDestroy() override;
+
+private:
 
   /**
    * Creates new VkImage with given specification, it doesn't
@@ -126,16 +136,16 @@ public:
    * @param graphics
    * @param createInfo
    */
-  Image( Graphics& graphics, const vk::ImageCreateInfo& createInfo, vk::Image externalImage );
-
-  operator InternalVkImage() const
-  {
-    return GetVkHandle();
-  }
+  Image( Graphics& graphics, const vk::ImageCreateInfo& createInfo, vk::Image externalImage = nullptr );
 
 private:
-  struct Impl;
-  std::unique_ptr<Impl> mImpl;
+  Graphics*           mGraphics;
+  vk::ImageCreateInfo mCreateInfo;
+  vk::Image           mImage;
+  vk::ImageLayout     mImageLayout;
+
+  RefCountedGpuMemoryBlock   mDeviceMemory;
+  bool mIsExternal;
 };
 
 } // namespace Vulkan
index 9251922..8623896 100644 (file)
@@ -206,13 +206,14 @@ public:
 private:
   std::vector< RefCountedBuffer >         mBuffers;
   std::vector< RefCountedImage >          mImages;
+  //TODO: add storage for ImageViews
   std::vector< RefCountedShader >         mShaders;
   std::vector< RefCountedCommandPool >    mCommandPools;
   std::vector< RefCountedDescriptorPool > mDescriptorPools;
   std::vector< RefCountedFramebuffer >    mFramebuffers;
   std::vector< RefCountedSampler >        mSamplers;
 
-  std::vector< std::function<void()> >    mDiscardQueue;
+  std::vector< std::function< void() > >    mDiscardQueue;
 };
 
 } //namespace Vulkan
index 9c4a43f..578b3ab 100644 (file)
@@ -345,14 +345,14 @@ struct Swapchain::Impl
             .setInitialLayout( vk::ImageLayout::eUndefined )
             .setSamples( vk::SampleCountFlagBits::e1 );
 
-    // create depth stencil image
-    auto dsRefCountedImage = Image::New( mGraphics, imageCreateInfo);
+    auto dsRefCountedImage = mGraphics.CreateImage( imageCreateInfo );
 
-    auto memory = mGraphics.GetDeviceMemoryManager().GetDefaultAllocator().Allocate(
-            dsRefCountedImage, vk::MemoryPropertyFlagBits::eDeviceLocal );
+    auto memory = mGraphics
+            .GetDeviceMemoryManager()
+            .GetDefaultAllocator()
+            .Allocate( dsRefCountedImage, vk::MemoryPropertyFlagBits::eDeviceLocal );
 
-    //TODO: use the graphics class to bind memory. Maybe...
-    dsRefCountedImage->BindMemory( memory );
+    mGraphics.BindImageMemory( dsRefCountedImage, memory, 0 );
 
     // create imageview to be used within framebuffer
     auto dsImageViewRef = mGraphics.CreateImageView(dsRefCountedImage);
@@ -383,12 +383,12 @@ struct Swapchain::Impl
     // Create external Image reference
     // Note that despite we don't create VkImage, we still fill the createinfo structure
     // as this data will be used later
-    auto refCountedImage = Image::New( mGraphics, imageCreateInfo, image );
+    auto refCountedImage = Image::NewFromExternal( mGraphics, imageCreateInfo, image );
 
     // Create basic imageview ( all mipmaps, all layers )
-    RefCountedImageView iv = mGraphics.CreateImageView(refCountedImage);
+    auto refCountedImageView = mGraphics.CreateImageView(refCountedImage);
 
-    fbRef->SetAttachment( iv, Framebuffer::AttachmentType::COLOR, 0u );
+    fbRef->SetAttachment( refCountedImageView, Framebuffer::AttachmentType::COLOR, 0u );
 
     return fbRef;
   }
@@ -502,7 +502,7 @@ struct Swapchain::Impl
 
     for( auto&& imageView : attachments )
     {
-      barriers.emplace_back( barrier.setImage( *imageView->GetImage() ) );
+      barriers.emplace_back( barrier.setImage( imageView->GetImage()->GetVkHandle() ) );
     }
 
     cmdBuf->PipelineBarrier( vk::PipelineStageFlagBits::eBottomOfPipe,