Implemented the ResourceCache class.
[platform/core/uifw/dali-core.git] / dali / graphics / vulkan / vulkan-graphics.cpp
index 1ad1ff2..a898475 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali/graphics/vulkan/vulkan-queue.h>
 #include <dali/graphics/vulkan/vulkan-surface.h>
 #include <dali/integration-api/graphics/vulkan/vk-surface-factory.h>
-#include <dali/graphics/vulkan/vulkan-device-memory-manager.h>
+#include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.h>
+
+#include <dali/graphics/vulkan/vulkan-buffer.h>
+#include <dali/graphics/vulkan/vulkan-image.h>
+#include <dali/graphics/vulkan/vulkan-pipeline.h>
+#include <dali/graphics/vulkan/vulkan-shader.h>
+#include <dali/graphics/vulkan/vulkan-descriptor-set.h>
+#include <dali/graphics/vulkan/vulkan-framebuffer.h>
+#include <dali/graphics/vulkan/api/vulkan-api-controller.h>
+#include <dali/graphics/vulkan/vulkan-pipeline-cache.h>
+
+#include <dali/graphics-api/graphics-api-controller.h>
 
 #ifndef VK_KHR_XLIB_SURFACE_EXTENSION_NAME
 #define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface"
 #endif
 
+#ifndef VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
+#define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface"
+#endif
+
 #ifndef VK_KHR_XCB_SURFACE_EXTENSION_NAME
 #define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface"
 #endif
@@ -39,40 +54,158 @@ using VkSurfaceFactory = Dali::Integration::Graphics::Vulkan::VkSurfaceFactory;
 namespace Vulkan
 {
 
-Graphics::Graphics() = default;
+const auto VALIDATION_LAYERS = std::vector< const char* >{
+
+  //"VK_LAYER_LUNARG_screenshot",           // screenshot
+  //"VK_LAYER_RENDERDOC_Capture",
+  //"VK_LAYER_LUNARG_parameter_validation", // parameter
+  //"VK_LAYER_LUNARG_vktrace",              // vktrace ( requires vktrace connection )
+  //"VK_LAYER_LUNARG_monitor",             // monitor
+  "VK_LAYER_LUNARG_swapchain",           // swapchain
+  "VK_LAYER_GOOGLE_threading",           // threading
+  "VK_LAYER_LUNARG_api_dump",            // api
+  "VK_LAYER_LUNARG_object_tracker",      // objects
+  "VK_LAYER_LUNARG_core_validation",     // core
+  "VK_LAYER_GOOGLE_unique_objects",      // unique objects
+  "VK_LAYER_GOOGLE_unique_objects",      // unique objects
+  "VK_LAYER_LUNARG_standard_validation", // standard
+};
 
+Graphics::Graphics() = default;
 Graphics::~Graphics() = default;
 
+Platform Graphics::GetDefaultPlatform() const
+{
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+  mPlatform = Platform::WAYLAND;
+#elif VK_USE_PLATFORM_XCB_KHR
+  mPlatform = Platform::XCB;
+#elif VK_USE_PLATFORM_XLIB_KHR
+  mPlatform =  Platform::XLIB;
+#else
+  return mPlatform;
+#endif
+}
+
+Dali::Graphics::API::Controller& Graphics::GetController()
+{
+  if(!mGfxController)
+  {
+    mGfxController = Dali::Graphics::VulkanAPI::Controller::New(*this);
+  }
+
+  return *mGfxController;
+}
+
+std::vector<const char*> Graphics::PrepareDefaultInstanceExtensions()
+{
+  auto extensions = vk::enumerateInstanceExtensionProperties();
+
+  std::string extensionName;
+
+  bool xlibAvailable    { false };
+  bool xcbAvailable     { false };
+  bool waylandAvailable { false };
+
+  for( auto&& ext : extensions.value )
+  {
+    extensionName = ext.extensionName;
+    if( extensionName == VK_KHR_XCB_SURFACE_EXTENSION_NAME )
+    {
+      xcbAvailable = true;
+    }
+    else if( extensionName == VK_KHR_XLIB_SURFACE_EXTENSION_NAME )
+    {
+      xlibAvailable = true;
+    }
+    else if( extensionName == VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME )
+    {
+      waylandAvailable = true;
+    }
+  }
+
+  std::vector<const char*> retval;
+
+  // depending on the platform validate extensions
+  auto platform = GetDefaultPlatform();
+
+  if( platform != Platform::UNDEFINED )
+  {
+    if (platform == Platform::XCB && xcbAvailable)
+    {
+      retval.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
+    }
+    else if (platform == Platform::XLIB && xlibAvailable)
+    {
+      retval.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
+    }
+    else if (platform == Platform::WAYLAND && waylandAvailable)
+    {
+      retval.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
+    }
+  }
+  else // try to determine the platform based on available extensions
+  {
+    if (xcbAvailable)
+    {
+      mPlatform = Platform::XCB;
+      retval.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
+    }
+    else if (xlibAvailable)
+    {
+      mPlatform = Platform::XLIB;
+      retval.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
+    }
+    else if (waylandAvailable)
+    {
+      mPlatform = Platform::WAYLAND;
+      retval.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
+    }
+    else
+    {
+      // can't determine the platform!
+      mPlatform = Platform::UNDEFINED;
+    }
+  }
+
+  // other essential extensions
+  retval.push_back( VK_KHR_SURFACE_EXTENSION_NAME );
+  retval.push_back( VK_EXT_DEBUG_REPORT_EXTENSION_NAME );
+
+  return retval;
+}
+
 void Graphics::Create()
 {
-  CreateInstance();
+
+  auto extensions = PrepareDefaultInstanceExtensions();
+
+  auto layers = vk::enumerateInstanceLayerProperties();
+  std::vector<const char*> validationLayers;
+  for( auto&& reqLayer : VALIDATION_LAYERS )
+  {
+    for( auto&& prop : layers.value )
+    {
+      std::cout << prop.layerName << std::endl;
+      if( std::string(prop.layerName) == reqLayer )
+      {
+        validationLayers.push_back(reqLayer);
+      }
+    }
+  }
+
+  CreateInstance(extensions, validationLayers);
   PreparePhysicalDevice();
 }
 
-void Graphics::CreateInstance()
+void Graphics::CreateInstance( const std::vector<const char*>& extensions, const std::vector<const char*>& validationLayers )
 {
   auto info = vk::InstanceCreateInfo{};
-  auto extensions =
-      std::vector< const char* >{VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
-                                 VK_KHR_XLIB_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME };
-
-  const auto validationLayers = std::vector< const char* >{
-      //"VK_LAYER_LUNARG_screenshot",           // screenshot
-      "VK_LAYER_LUNARG_parameter_validation", // parameter
-      //"VK_LAYER_LUNARG_vktrace",              // vktrace ( requires vktrace connection )
-      "VK_LAYER_LUNARG_monitor",             // monitor
-      "VK_LAYER_LUNARG_swapchain",           // swapchain
-      "VK_LAYER_GOOGLE_threading",           // threading
-      "VK_LAYER_LUNARG_api_dump",            // api
-      "VK_LAYER_LUNARG_object_tracker",      // objects
-      "VK_LAYER_LUNARG_core_validation",     // core
-      "VK_LAYER_GOOGLE_unique_objects",      // unique objects
-      "VK_LAYER_LUNARG_standard_validation", // standard
-  };
 
   info.setEnabledExtensionCount(U32(extensions.size()))
       .setPpEnabledExtensionNames(extensions.data())
       .setEnabledLayerCount(U32(validationLayers.size()))
+      //.setEnabledLayerCount(0)
       .setPpEnabledLayerNames(validationLayers.data());
 
   mInstance = VkAssert(vk::createInstance(info, *mAllocator));
@@ -87,8 +220,7 @@ void Graphics::DestroyInstance()
   }
 }
 
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wframe-larger-than="
+
 void Graphics::PreparePhysicalDevice()
 {
   auto devices = VkAssert(mInstance.enumeratePhysicalDevices());
@@ -120,12 +252,9 @@ void Graphics::PreparePhysicalDevice()
 
   GetQueueFamilyProperties();
 
-  mDeviceMemoryManager = MakeUnique<DeviceMemoryManager>( *this );
+  mDeviceMemoryManager = GpuMemoryManager::New( *this );
 }
-#pragma GCC diagnostic pop
 
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wframe-larger-than="
 void Graphics::GetPhysicalDeviceProperties()
 {
   // store data on heap to keep object smaller
@@ -136,31 +265,69 @@ void Graphics::GetPhysicalDeviceProperties()
   mPhysicalDeviceFeatures =
     MakeUnique<vk::PhysicalDeviceFeatures>(mPhysicalDevice.getFeatures());
 }
-#pragma GCC diagnostic pop
 
 void Graphics::GetQueueFamilyProperties()
 {
-  mQueueFamilyProperties = std::move(mPhysicalDevice.getQueueFamilyProperties());
+  mQueueFamilyProperties = mPhysicalDevice.getQueueFamilyProperties();
 }
 
 FBID Graphics::CreateSurface(std::unique_ptr< SurfaceFactory > surfaceFactory)
 {
-  const auto vkFactory = dynamic_cast< const VkSurfaceFactory* >(surfaceFactory.get());
-  if(!vkFactory)
+  // create surface from the factory
+  auto surfaceRef = Surface::New( *this, std::move(surfaceFactory) );
+
+  if( surfaceRef->Create() )
   {
-    return FBID{0u};
+
+    // map surface to FBID
+    auto fbid = ++mBaseFBID;
+    mSurfaceFBIDMap[fbid] = SwapchainSurfacePair{ SwapchainRef{}, surfaceRef };
+    return fbid;
   }
+  return -1;
+}
 
-  auto surface = vkFactory->Create(mInstance, mAllocator.get(), mPhysicalDevice);
+SwapchainRef Graphics::CreateSwapchainForSurface( SurfaceRef surface )
+{
+  auto swapchain = Swapchain::New( *this,
+                                   GetGraphicsQueue(0u),
+                                   surface, 4, 0 );
 
-  // map surface to FBID
-  auto fbid             = ++mBaseFBID;
-  mSurfaceFBIDMap[fbid] = MakeUnique<Surface>(*this, surface, 3u);
-  return fbid;
+  // store swapchain in the correct pair
+  for( auto&& val : mSurfaceFBIDMap )
+  {
+    if( val.second.surface == surface )
+    {
+      val.second.swapchain = swapchain;
+      break;
+    }
+  }
+
+  return swapchain;
+}
+
+SwapchainRef Graphics::GetSwapchainForSurface( SurfaceRef surface )
+{
+  for( auto&& val : mSurfaceFBIDMap )
+  {
+    if( val.second.surface == surface )
+    {
+      return val.second
+                .swapchain;
+    }
+  }
+  return SwapchainRef();
+}
+
+SwapchainRef Graphics::GetSwapchainForFBID( FBID surfaceId )
+{
+  if(surfaceId == 0)
+  {
+    return mSurfaceFBIDMap.begin()->second.swapchain;
+  }
+  return mSurfaceFBIDMap[surfaceId].swapchain;
 }
 
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wframe-larger-than="
 std::vector< vk::DeviceQueueCreateInfo > Graphics::GetQueueCreateInfos()
 {
   // surface is needed in order to find a family that supports presentation to this surface
@@ -195,7 +362,7 @@ std::vector< vk::DeviceQueueCreateInfo > Graphics::GetQueueCreateInfos()
     {
       transferFamily = queueFamilyIndex;
     }
-    if(mPhysicalDevice.getSurfaceSupportKHR(queueFamilyIndex, mSurfaceFBIDMap.begin()->second.get()->GetSurfaceKHR())
+    if(mPhysicalDevice.getSurfaceSupportKHR(queueFamilyIndex, mSurfaceFBIDMap.begin()->second.surface->GetSurfaceKHR())
            .value &&
        presentFamily == -1u)
     {
@@ -240,10 +407,7 @@ std::vector< vk::DeviceQueueCreateInfo > Graphics::GetQueueCreateInfos()
 
   return queueInfos;
 }
-#pragma GCC diagnostic pop
 
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wframe-larger-than="
 void Graphics::CreateDevice()
 {
   auto queueInfos = GetQueueCreateInfos();
@@ -302,8 +466,9 @@ void Graphics::CreateDevice()
       // todo: present queue
     }
   }
+
+  mPipelineDatabase = std::make_unique<PipelineCache>( *this );
 }
-#pragma GCC diagnostic pop
 
 vk::Device Graphics::GetDevice() const
 {
@@ -354,20 +519,131 @@ Queue& Graphics::GetComputeQueue(uint32_t index) const
 
 Queue& Graphics::GetPresentQueue() const
 {
-  return *mPresentQueue.get();
+  // fixme: should be a dedicated presentation queue
+  return GetGraphicsQueue(0);
 }
 
-std::unique_ptr< CommandPool > Graphics::CreateCommandPool(const vk::CommandPoolCreateInfo& info)
+Handle< CommandPool > Graphics::CreateCommandPool(const vk::CommandPoolCreateInfo& info)
 {
-  auto cmdpool = std::unique_ptr< CommandPool >(new CommandPool(*this, info));
+  auto cmdpool = CommandPool::New( *this, vk::CommandPoolCreateInfo{}.
+                                                                       setQueueFamilyIndex( 0u ).
+                                                                       setFlags( vk::CommandPoolCreateFlagBits::eResetCommandBuffer ) );
   return cmdpool;
 }
 
-Surface& Graphics::GetSurface( FBID surfaceId )
+SurfaceRef Graphics::GetSurface( FBID surfaceId )
+{
+  // TODO: FBID == 0 means default framebuffer, but there should be no
+  // such thing as default framebuffer.
+  if( surfaceId == 0 )
+  {
+    return mSurfaceFBIDMap.begin()->second.surface;
+  }
+  return mSurfaceFBIDMap[surfaceId].surface;
+}
+
+// TODO: all this stuff should go into some vulkan cache
+
+void Graphics::AddBuffer( Handle<Buffer> buffer )
+{
+  mBuffersCache.push_back( buffer );
+}
+
+void Graphics::AddImage( Handle<Image> image )
+{
+  mImageCache.push_back( image );
+}
+
+void Graphics::AddPipeline( Handle<Pipeline> pipeline )
+{
+  mPipelineCache.push_back( pipeline );
+}
+
+void Graphics::AddShader( Handle<Shader> shader )
+{
+  mShaderCache.push_back( shader );
+}
+
+void Graphics::AddCommandPool( Handle<CommandPool> pool )
+{
+  mCommandPoolCache.push_back( pool );
+}
+
+void Graphics::AddDescriptorPool( Handle<DescriptorPool> pool )
+{
+  mDescriptorPoolCache.push_back( pool );
+}
+
+void Graphics::AddFramebuffer( Handle<Framebuffer> framebuffer )
 {
-  return *mSurfaceFBIDMap[surfaceId].get();
+  mFramebufferCache.push_back( framebuffer );
 }
 
+void Graphics::RemoveBuffer( Buffer& buffer )
+{
+  auto index = 0u;
+  for( auto&& iter : mBuffersCache )
+  {
+    if( &*iter == &buffer )
+    {
+      iter.Reset();
+      mBuffersCache.erase( mBuffersCache.begin()+index );
+      return;
+    }
+  }
+}
+
+void Graphics::RemoveShader( Shader& shader )
+{
+  auto index = 0u;
+  for( auto&& iter : mShaderCache )
+  {
+    if( &*iter == &shader )
+    {
+      iter.Reset();
+      mShaderCache.erase( mShaderCache.begin()+index );
+      return;
+    }
+    ++index;
+  }
+}
+
+void Graphics::RemoveCommandPool( CommandPool& commandPool )
+{
+  NotImplemented();
+}
+
+void Graphics::RemoveDescriptorPool( std::unique_ptr<DescriptorPool> pool )
+{
+  NotImplemented();
+}
+
+ShaderRef Graphics::FindShader( vk::ShaderModule shaderModule )
+{
+  for( auto&& iter : mShaderCache )
+  {
+    if( iter->GetVkShaderModule() == shaderModule )
+    {
+      return Handle<Shader>(&*iter);
+    }
+  }
+  return Handle<Shader>();
+}
+
+ImageRef Graphics::FindImage( vk::Image image )
+{
+  for( auto&& iter : mImageCache )
+  {
+    if( iter->GetVkImage() == image )
+    {
+      return ImageRef(&*iter);
+    }
+  }
+  return ImageRef();
+}
+
+
+
 } // namespace Vulkan
 } // namespace Graphics
 } // namespace Dali