[Vulkan] Cleanup after removing rendering backend
[platform/core/uifw/dali-core.git] / dali / graphics / vulkan / vulkan-graphics.cpp
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // INTERNAL INCLUDES
19 #include <dali/graphics/vulkan/vulkan-graphics.h>
20 #include <dali/graphics/vulkan/vulkan-command-pool.h>
21 #include <dali/graphics/vulkan/vulkan-queue.h>
22 #include <dali/graphics/vulkan/vulkan-surface.h>
23 #include <dali/integration-api/graphics/vulkan/vk-surface-factory.h>
24 #include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.h>
25
26 #include <dali/graphics/vulkan/vulkan-buffer.h>
27 #include <dali/graphics/vulkan/vulkan-image.h>
28 #include <dali/graphics/vulkan/vulkan-pipeline.h>
29 #include <dali/graphics/vulkan/vulkan-shader.h>
30 #include <dali/graphics/vulkan/vulkan-descriptor-set.h>
31 #include <dali/graphics/vulkan/vulkan-framebuffer.h>
32 #include <dali/graphics/vulkan/api/vulkan-api-controller.h>
33 #include <dali/graphics/vulkan/vulkan-pipeline-cache.h>
34
35 #include <dali/graphics-api/graphics-api-controller.h>
36
37 #ifndef VK_KHR_XLIB_SURFACE_EXTENSION_NAME
38 #define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface"
39 #endif
40
41 #ifndef VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
42 #define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface"
43 #endif
44
45 #ifndef VK_KHR_XCB_SURFACE_EXTENSION_NAME
46 #define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface"
47 #endif
48
49 namespace Dali
50 {
51 namespace Graphics
52 {
53 using VkSurfaceFactory = Dali::Integration::Graphics::Vulkan::VkSurfaceFactory;
54 namespace Vulkan
55 {
56
57 const auto VALIDATION_LAYERS = std::vector< const char* >{
58
59   //"VK_LAYER_LUNARG_screenshot",           // screenshot
60   //"VK_LAYER_RENDERDOC_Capture",
61   //"VK_LAYER_LUNARG_parameter_validation", // parameter
62   //"VK_LAYER_LUNARG_vktrace",              // vktrace ( requires vktrace connection )
63   //"VK_LAYER_LUNARG_monitor",             // monitor
64   "VK_LAYER_LUNARG_swapchain",           // swapchain
65   "VK_LAYER_GOOGLE_threading",           // threading
66   "VK_LAYER_LUNARG_api_dump",            // api
67   "VK_LAYER_LUNARG_object_tracker",      // objects
68   "VK_LAYER_LUNARG_core_validation",     // core
69   "VK_LAYER_GOOGLE_unique_objects",      // unique objects
70   "VK_LAYER_GOOGLE_unique_objects",      // unique objects
71   "VK_LAYER_LUNARG_standard_validation", // standard
72 };
73
74 Graphics::Graphics() = default;
75 Graphics::~Graphics() = default;
76
77 Platform Graphics::GetDefaultPlatform() const
78 {
79 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
80   mPlatform = Platform::WAYLAND;
81 #elif VK_USE_PLATFORM_XCB_KHR
82   mPlatform = Platform::XCB;
83 #elif VK_USE_PLATFORM_XLIB_KHR
84   mPlatform =  Platform::XLIB;
85 #else
86   return mPlatform;
87 #endif
88 }
89
90 Dali::Graphics::API::Controller& Graphics::GetController()
91 {
92   if(!mGfxController)
93   {
94     mGfxController = Dali::Graphics::VulkanAPI::Controller::New(*this);
95   }
96
97   return *mGfxController.get();
98 }
99
100 std::vector<const char*> Graphics::PrepareDefaultInstanceExtensions()
101 {
102   auto extensions = vk::enumerateInstanceExtensionProperties();
103
104   std::string extensionName;
105
106   bool xlibAvailable    { false };
107   bool xcbAvailable     { false };
108   bool waylandAvailable { false };
109
110   for( auto&& ext : extensions.value )
111   {
112     extensionName = ext.extensionName;
113     if( extensionName == VK_KHR_XCB_SURFACE_EXTENSION_NAME )
114     {
115       xcbAvailable = true;
116     }
117     else if( extensionName == VK_KHR_XLIB_SURFACE_EXTENSION_NAME )
118     {
119       xlibAvailable = true;
120     }
121     else if( extensionName == VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME )
122     {
123       waylandAvailable = true;
124     }
125   }
126
127   std::vector<const char*> retval;
128
129   // depending on the platform validate extensions
130   auto platform = GetDefaultPlatform();
131
132   if( platform != Platform::UNDEFINED )
133   {
134     if (platform == Platform::XCB && xcbAvailable)
135     {
136       retval.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
137     }
138     else if (platform == Platform::XLIB && xlibAvailable)
139     {
140       retval.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
141     }
142     else if (platform == Platform::WAYLAND && waylandAvailable)
143     {
144       retval.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
145     }
146   }
147   else // try to determine the platform based on available extensions
148   {
149     if (xcbAvailable)
150     {
151       mPlatform = Platform::XCB;
152       retval.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
153     }
154     else if (xlibAvailable)
155     {
156       mPlatform = Platform::XLIB;
157       retval.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
158     }
159     else if (waylandAvailable)
160     {
161       mPlatform = Platform::WAYLAND;
162       retval.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
163     }
164     else
165     {
166       // can't determine the platform!
167       mPlatform = Platform::UNDEFINED;
168     }
169   }
170
171   // other essential extensions
172   retval.push_back( VK_KHR_SURFACE_EXTENSION_NAME );
173   retval.push_back( VK_EXT_DEBUG_REPORT_EXTENSION_NAME );
174
175   return retval;
176 }
177
178 void Graphics::Create()
179 {
180
181   auto extensions = PrepareDefaultInstanceExtensions();
182
183   auto layers = vk::enumerateInstanceLayerProperties();
184   std::vector<const char*> validationLayers;
185   for( auto&& reqLayer : VALIDATION_LAYERS )
186   {
187     for( auto&& prop : layers.value )
188     {
189       std::cout << prop.layerName << std::endl;
190       if( std::string(prop.layerName) == reqLayer )
191       {
192         validationLayers.push_back(reqLayer);
193       }
194     }
195   }
196
197   CreateInstance(extensions, validationLayers);
198   PreparePhysicalDevice();
199 }
200
201 void Graphics::CreateInstance( const std::vector<const char*>& extensions, const std::vector<const char*>& validationLayers )
202 {
203   auto info = vk::InstanceCreateInfo{};
204
205   info.setEnabledExtensionCount(U32(extensions.size()))
206       .setPpEnabledExtensionNames(extensions.data())
207       .setEnabledLayerCount(U32(validationLayers.size()))
208       //.setEnabledLayerCount(0)
209       .setPpEnabledLayerNames(validationLayers.data());
210
211   mInstance = VkAssert(vk::createInstance(info, *mAllocator));
212 }
213
214 void Graphics::DestroyInstance()
215 {
216   if(mInstance)
217   {
218     mInstance.destroy(*mAllocator);
219     mInstance = nullptr;
220   }
221 }
222
223
224 void Graphics::PreparePhysicalDevice()
225 {
226   auto devices = VkAssert(mInstance.enumeratePhysicalDevices());
227   assert(devices.size() > 0 && "No Vulkan supported device found!");
228
229   // if only one, pick first
230   mPhysicalDevice = nullptr;
231   if(devices.size() == 1)
232   {
233     mPhysicalDevice = devices[0];
234   }
235   else // otherwise look for one which is a graphics device
236   {
237     for(auto& device : devices)
238     {
239       auto properties =device.getProperties();
240       if(properties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu ||
241          properties.deviceType == vk::PhysicalDeviceType::eIntegratedGpu)
242       {
243         mPhysicalDevice = device;
244         break;
245       }
246     }
247   }
248
249   assert(mPhysicalDevice && "No suitable Physical Device found!");
250
251   GetPhysicalDeviceProperties();
252
253   GetQueueFamilyProperties();
254
255   mDeviceMemoryManager = GpuMemoryManager::New( *this );
256 }
257
258 void Graphics::GetPhysicalDeviceProperties()
259 {
260   // store data on heap to keep object smaller
261   mPhysicalDeviceProperties =
262     MakeUnique<vk::PhysicalDeviceProperties>(mPhysicalDevice.getProperties());
263   mPhysicalDeviceMemoryProperties =
264     MakeUnique<vk::PhysicalDeviceMemoryProperties>(mPhysicalDevice.getMemoryProperties());
265   mPhysicalDeviceFeatures =
266     MakeUnique<vk::PhysicalDeviceFeatures>(mPhysicalDevice.getFeatures());
267 }
268
269 void Graphics::GetQueueFamilyProperties()
270 {
271   mQueueFamilyProperties = mPhysicalDevice.getQueueFamilyProperties();
272 }
273
274 FBID Graphics::CreateSurface(std::unique_ptr< SurfaceFactory > surfaceFactory)
275 {
276   // create surface from the factory
277   auto surfaceRef = Surface::New( *this, std::move(surfaceFactory) );
278
279   if( surfaceRef->Create() )
280   {
281
282     // map surface to FBID
283     auto fbid = ++mBaseFBID;
284     mSurfaceFBIDMap[fbid] = SwapchainSurfacePair{ SwapchainRef{}, surfaceRef };
285     return fbid;
286   }
287   return -1;
288 }
289
290 SwapchainRef Graphics::CreateSwapchainForSurface( SurfaceRef surface )
291 {
292   auto swapchain = Swapchain::New( *this,
293                                    GetGraphicsQueue(0u),
294                                    surface, 4, 0 );
295
296   // store swapchain in the correct pair
297   for( auto&& val : mSurfaceFBIDMap )
298   {
299     if( val.second.surface == surface )
300     {
301       val.second.swapchain = swapchain;
302       break;
303     }
304   }
305
306   return swapchain;
307 }
308
309 SwapchainRef Graphics::GetSwapchainForSurface( SurfaceRef surface )
310 {
311   for( auto&& val : mSurfaceFBIDMap )
312   {
313     if( val.second.surface == surface )
314     {
315       return val.second
316                 .swapchain;
317     }
318   }
319   return SwapchainRef();
320 }
321
322 SwapchainRef Graphics::GetSwapchainForFBID( FBID surfaceId )
323 {
324   if(surfaceId == 0)
325   {
326     return mSurfaceFBIDMap.begin()->second.swapchain;
327   }
328   return mSurfaceFBIDMap[surfaceId].swapchain;
329 }
330
331 std::vector< vk::DeviceQueueCreateInfo > Graphics::GetQueueCreateInfos()
332 {
333   // surface is needed in order to find a family that supports presentation to this surface
334   // fixme: assuming all surfaces will be compatible with the queue family
335   assert(!mSurfaceFBIDMap.empty() &&
336          "At least one surface has to be created before creating VkDevice!");
337
338   auto queueInfos = std::vector< vk::DeviceQueueCreateInfo >{};
339
340   constexpr uint8_t MAX_QUEUE_TYPES = 3;
341   // find suitable family for each type of queue
342   uint32_t familyIndexType[MAX_QUEUE_TYPES];
343   std::fill(&familyIndexType[0], &familyIndexType[MAX_QUEUE_TYPES], -1u);
344
345   // Graphics
346   auto& graphicsFamily = familyIndexType[0];
347
348   // Transfer
349   auto& transferFamily = familyIndexType[1];
350
351   // Transfer
352   auto& presentFamily = familyIndexType[2];
353
354   auto queueFamilyIndex = 0u;
355   for(auto& prop : mQueueFamilyProperties)
356   {
357     if((prop.queueFlags & vk::QueueFlagBits::eGraphics) && graphicsFamily == -1u)
358     {
359       graphicsFamily = queueFamilyIndex;
360     }
361     if((prop.queueFlags & vk::QueueFlagBits::eTransfer) && transferFamily == -1u)
362     {
363       transferFamily = queueFamilyIndex;
364     }
365     if(mPhysicalDevice.getSurfaceSupportKHR(queueFamilyIndex, mSurfaceFBIDMap.begin()->second.surface->GetSurfaceKHR())
366            .value &&
367        presentFamily == -1u)
368     {
369       presentFamily = queueFamilyIndex;
370     }
371     ++queueFamilyIndex;
372   }
373
374   assert(graphicsFamily != -1u && "No queue family that supports graphics operations!");
375   assert(transferFamily != -1u && "No queue family that supports transfer operations!");
376   assert(presentFamily != -1u && "No queue family that supports present operations!");
377
378   // todo: we may require that the family must be same for all types of operations, it makes
379   // easier to handle synchronisation related issues.
380
381   // sort queues
382   std::sort(&familyIndexType[0], &familyIndexType[MAX_QUEUE_TYPES]);
383
384   // allocate all queues from graphics family
385   uint32_t prevQueueFamilyIndex = -1u;
386
387   for(auto i = 0u; i < MAX_QUEUE_TYPES; ++i)
388   {
389     auto& familyIndex = familyIndexType[i];
390     if(prevQueueFamilyIndex == familyIndex)
391     {
392       continue;
393     }
394
395     auto& queueCount = mQueueFamilyProperties[familyIndex].queueCount;
396
397     // fill queue create info for the family.
398     // note the priorities are not being set as local pointer will out of scope, this
399     // will be fixed by the caller function
400     auto info = vk::DeviceQueueCreateInfo{}
401                     .setPQueuePriorities(nullptr)
402                     .setQueueCount(queueCount)
403                     .setQueueFamilyIndex(familyIndex);
404     queueInfos.push_back(info);
405     prevQueueFamilyIndex = familyIndex;
406   }
407
408   return queueInfos;
409 }
410
411 void Graphics::CreateDevice()
412 {
413   auto queueInfos = GetQueueCreateInfos();
414   {
415     auto maxQueueCountPerFamily = 0u;
416     for( auto&& info : queueInfos )
417     {
418       maxQueueCountPerFamily = std::max( info.queueCount, maxQueueCountPerFamily );
419     }
420
421     auto priorities = std::vector<float>( maxQueueCountPerFamily );
422     std::fill( priorities.begin(), priorities.end(), 1.0f );
423
424     for( auto& info : queueInfos )
425     {
426       info.setPQueuePriorities( priorities.data() );
427     }
428
429     auto extensions = std::vector< const char* >{VK_KHR_SWAPCHAIN_EXTENSION_NAME};
430
431     auto info = vk::DeviceCreateInfo{};
432     info.setEnabledExtensionCount(U32(extensions.size()))
433         .setPpEnabledExtensionNames(extensions.data())
434         .setPEnabledFeatures(&(*mPhysicalDeviceFeatures))
435         .setPQueueCreateInfos(queueInfos.data())
436         .setQueueCreateInfoCount(U32(queueInfos.size()));
437
438     mDevice = VkAssert(mPhysicalDevice.createDevice(info, *mAllocator));
439   }
440
441   // create Queue objects
442   for(auto& queueInfo : queueInfos)
443   {
444     for(auto i = 0u; i < queueInfo.queueCount; ++i)
445     {
446       auto queue = mDevice.getQueue(queueInfo.queueFamilyIndex, i);
447
448       // based on family push queue instance into right array
449       auto flags = mQueueFamilyProperties[queueInfo.queueFamilyIndex].queueFlags;
450       if(flags & vk::QueueFlagBits::eGraphics)
451       {
452         mGraphicsQueues.emplace_back(
453           MakeUnique<Queue>(*this, queue, queueInfo.queueFamilyIndex, i, flags));
454       }
455       if(flags & vk::QueueFlagBits::eTransfer)
456       {
457         mTransferQueues.emplace_back(
458           MakeUnique<Queue>(*this, queue, queueInfo.queueFamilyIndex, i, flags));
459       }
460       if(flags & vk::QueueFlagBits::eCompute)
461       {
462         mComputeQueues.emplace_back(
463           MakeUnique<Queue>(*this, queue, queueInfo.queueFamilyIndex, i, flags));
464       }
465
466       // todo: present queue
467     }
468   }
469
470   mPipelineDatabase = std::make_unique<PipelineCache>( *this );
471 }
472
473 vk::Device Graphics::GetDevice() const
474 {
475   return mDevice;
476 }
477
478 vk::PhysicalDevice Graphics::GetPhysicalDevice() const
479 {
480   return mPhysicalDevice;
481 }
482
483 vk::Instance Graphics::GetInstance() const
484 {
485   return mInstance;
486 }
487
488 const vk::AllocationCallbacks& Graphics::GetAllocator() const
489 {
490   return *mAllocator;
491 }
492
493 Queue& Graphics::GetGraphicsQueue(uint32_t index) const
494 {
495   // todo: at the moment each type of queue may use only one, indices greater than 0 are invalid
496   // this will change in the future
497   assert(index == 0u && "Each type of queue may use only one, indices greater than 0 are invalid!");
498
499   return *mGraphicsQueues[0].get(); // will be mGraphicsQueues[index]
500 }
501
502 Queue& Graphics::GetTransferQueue(uint32_t index) const
503 {
504   // todo: at the moment each type of queue may use only one, indices greater than 0 are invalid
505   // this will change in the future
506   assert(index == 0u && "Each type of queue may use only one, indices greater than 0 are invalid!");
507
508   return *mTransferQueues[0].get(); // will be mGraphicsQueues[index]
509 }
510
511 Queue& Graphics::GetComputeQueue(uint32_t index) const
512 {
513   // todo: at the moment each type of queue may use only one, indices greater than 0 are invalid
514   // this will change in the future
515   assert(index == 0u && "Each type of queue may use only one, indices greater than 0 are invalid!");
516
517   return *mComputeQueues[0].get(); // will be mGraphicsQueues[index]
518 }
519
520 Queue& Graphics::GetPresentQueue() const
521 {
522   // fixme: should be a dedicated presentation queue
523   return GetGraphicsQueue(0);
524 }
525
526 Handle< CommandPool > Graphics::CreateCommandPool(const vk::CommandPoolCreateInfo& info)
527 {
528   auto cmdpool = CommandPool::New( *this, vk::CommandPoolCreateInfo{}.
529                                                                        setQueueFamilyIndex( 0u ).
530                                                                        setFlags( vk::CommandPoolCreateFlagBits::eResetCommandBuffer ) );
531   return cmdpool;
532 }
533
534 SurfaceRef Graphics::GetSurface( FBID surfaceId )
535 {
536   // TODO: FBID == 0 means default framebuffer, but there should be no
537   // such thing as default framebuffer.
538   if( surfaceId == 0 )
539   {
540     return mSurfaceFBIDMap.begin()->second.surface;
541   }
542   return mSurfaceFBIDMap[surfaceId].surface;
543 }
544
545 // TODO: all this stuff should go into some vulkan cache
546
547 void Graphics::AddBuffer( Handle<Buffer> buffer )
548 {
549   mBuffersCache.push_back( buffer );
550 }
551
552 void Graphics::AddImage( Handle<Image> image )
553 {
554   mImageCache.push_back( image );
555 }
556
557 void Graphics::AddPipeline( Handle<Pipeline> pipeline )
558 {
559   mPipelineCache.push_back( pipeline );
560 }
561
562 void Graphics::AddShader( Handle<Shader> shader )
563 {
564   mShaderCache.push_back( shader );
565 }
566
567 void Graphics::AddCommandPool( Handle<CommandPool> pool )
568 {
569   mCommandPoolCache.push_back( pool );
570 }
571
572 void Graphics::AddDescriptorPool( Handle<DescriptorPool> pool )
573 {
574   mDescriptorPoolCache.push_back( pool );
575 }
576
577 void Graphics::AddFramebuffer( Handle<Framebuffer> framebuffer )
578 {
579   mFramebufferCache.push_back( framebuffer );
580 }
581
582 void Graphics::RemoveBuffer( Buffer& buffer )
583 {
584   auto index = 0u;
585   for( auto&& iter : mBuffersCache )
586   {
587     if( &*iter == &buffer )
588     {
589       iter.Reset();
590       mBuffersCache.erase( mBuffersCache.begin()+index );
591       return;
592     }
593   }
594 }
595
596 void Graphics::RemoveShader( Shader& shader )
597 {
598   auto index = 0u;
599   for( auto&& iter : mShaderCache )
600   {
601     if( &*iter == &shader )
602     {
603       iter.Reset();
604       mShaderCache.erase( mShaderCache.begin()+index );
605       return;
606     }
607     ++index;
608   }
609 }
610
611 void Graphics::RemoveCommandPool( CommandPool& commandPool )
612 {
613   NotImplemented();
614 }
615
616 void Graphics::RemoveDescriptorPool( std::unique_ptr<DescriptorPool> pool )
617 {
618   NotImplemented();
619 }
620
621 ShaderRef Graphics::FindShader( vk::ShaderModule shaderModule )
622 {
623   for( auto&& iter : mShaderCache )
624   {
625     if( iter->GetVkShaderModule() == shaderModule )
626     {
627       return Handle<Shader>(&*iter);
628     }
629   }
630   return Handle<Shader>();
631 }
632
633 ImageRef Graphics::FindImage( vk::Image image )
634 {
635   for( auto&& iter : mImageCache )
636   {
637     if( iter->GetVkImage() == image )
638     {
639       return ImageRef(&*iter);
640     }
641   }
642   return ImageRef();
643 }
644
645
646
647 } // namespace Vulkan
648 } // namespace Graphics
649 } // namespace Dali