1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/viz/common/gpu/vulkan_in_process_context_provider.h"
6 
7 #include "gpu/vulkan/buildflags.h"
8 #include "gpu/vulkan/vulkan_device_queue.h"
9 #include "gpu/vulkan/vulkan_fence_helper.h"
10 #include "gpu/vulkan/vulkan_function_pointers.h"
11 #include "gpu/vulkan/vulkan_implementation.h"
12 #include "gpu/vulkan/vulkan_instance.h"
13 #include "third_party/skia/include/gpu/GrContext.h"
14 #include "third_party/skia/include/gpu/vk/GrVkExtensions.h"
15 
16 namespace viz {
17 
18 scoped_refptr<VulkanInProcessContextProvider>
Create(gpu::VulkanImplementation * vulkan_implementation,const GrContextOptions & options)19 VulkanInProcessContextProvider::Create(
20     gpu::VulkanImplementation* vulkan_implementation,
21     const GrContextOptions& options) {
22   scoped_refptr<VulkanInProcessContextProvider> context_provider(
23       new VulkanInProcessContextProvider(vulkan_implementation));
24   if (!context_provider->Initialize(options))
25     return nullptr;
26   return context_provider;
27 }
28 
VulkanInProcessContextProvider(gpu::VulkanImplementation * vulkan_implementation)29 VulkanInProcessContextProvider::VulkanInProcessContextProvider(
30     gpu::VulkanImplementation* vulkan_implementation)
31     : vulkan_implementation_(vulkan_implementation) {}
32 
~VulkanInProcessContextProvider()33 VulkanInProcessContextProvider::~VulkanInProcessContextProvider() {
34   Destroy();
35 }
36 
Initialize(const GrContextOptions & context_options)37 bool VulkanInProcessContextProvider::Initialize(
38     const GrContextOptions& context_options) {
39   DCHECK(!device_queue_);
40 
41   const auto& instance_extensions = vulkan_implementation_->GetVulkanInstance()
42                                         ->vulkan_info()
43                                         .enabled_instance_extensions;
44 
45   uint32_t flags = gpu::VulkanDeviceQueue::GRAPHICS_QUEUE_FLAG;
46   constexpr base::StringPiece surface_extension_name(
47       VK_KHR_SURFACE_EXTENSION_NAME);
48   for (const auto* extension : instance_extensions) {
49     if (surface_extension_name == extension) {
50       flags |= gpu::VulkanDeviceQueue::PRESENTATION_SUPPORT_QUEUE_FLAG;
51       break;
52     }
53   }
54 
55   device_queue_ = gpu::CreateVulkanDeviceQueue(vulkan_implementation_, flags);
56   if (!device_queue_)
57     return false;
58 
59   GrVkBackendContext backend_context;
60   backend_context.fInstance = device_queue_->GetVulkanInstance();
61   backend_context.fPhysicalDevice = device_queue_->GetVulkanPhysicalDevice();
62   backend_context.fDevice = device_queue_->GetVulkanDevice();
63   backend_context.fQueue = device_queue_->GetVulkanQueue();
64   backend_context.fGraphicsQueueIndex = device_queue_->GetVulkanQueueIndex();
65   backend_context.fMaxAPIVersion = vulkan_implementation_->GetVulkanInstance()
66                                        ->vulkan_info()
67                                        .used_api_version;
68 
69   GrVkGetProc get_proc = [](const char* proc_name, VkInstance instance,
70                             VkDevice device) {
71     return device ? vkGetDeviceProcAddr(device, proc_name)
72                   : vkGetInstanceProcAddr(instance, proc_name);
73   };
74 
75   std::vector<const char*> device_extensions;
76   device_extensions.reserve(device_queue_->enabled_extensions().size());
77   for (const auto& extension : device_queue_->enabled_extensions())
78     device_extensions.push_back(extension.data());
79   GrVkExtensions gr_extensions;
80   gr_extensions.init(get_proc,
81                      vulkan_implementation_->GetVulkanInstance()->vk_instance(),
82                      device_queue_->GetVulkanPhysicalDevice(),
83                      instance_extensions.size(), instance_extensions.data(),
84                      device_extensions.size(), device_extensions.data());
85   backend_context.fVkExtensions = &gr_extensions;
86   backend_context.fDeviceFeatures2 =
87       &device_queue_->enabled_device_features_2();
88   backend_context.fGetProc = get_proc;
89   backend_context.fProtectedContext =
90       vulkan_implementation_->enforce_protected_memory() ? GrProtected::kYes
91                                                          : GrProtected::kNo;
92 
93   gr_context_ = GrContext::MakeVulkan(backend_context, context_options);
94 
95   return gr_context_ != nullptr;
96 }
97 
Destroy()98 void VulkanInProcessContextProvider::Destroy() {
99   if (device_queue_) {
100     // Destroy |fence_helper| will wait idle on the device queue, and then run
101     // all enqueued cleanup tasks.
102     auto* fence_helper = device_queue_->GetFenceHelper();
103     fence_helper->Destroy();
104   }
105 
106   if (gr_context_) {
107     // releaseResourcesAndAbandonContext() will wait on GPU to finish all works,
108     // execute pending flush done callbacks and release all resources.
109     gr_context_->releaseResourcesAndAbandonContext();
110     gr_context_.reset();
111   }
112 
113   if (device_queue_) {
114     device_queue_->Destroy();
115     device_queue_.reset();
116   }
117 }
118 
119 gpu::VulkanImplementation*
GetVulkanImplementation()120 VulkanInProcessContextProvider::GetVulkanImplementation() {
121   return vulkan_implementation_;
122 }
123 
GetDeviceQueue()124 gpu::VulkanDeviceQueue* VulkanInProcessContextProvider::GetDeviceQueue() {
125   return device_queue_.get();
126 }
127 
GetGrContext()128 GrContext* VulkanInProcessContextProvider::GetGrContext() {
129   return gr_context_.get();
130 }
131 
132 GrVkSecondaryCBDrawContext*
GetGrSecondaryCBDrawContext()133 VulkanInProcessContextProvider::GetGrSecondaryCBDrawContext() {
134   return nullptr;
135 }
136 
EnqueueSecondaryCBSemaphores(std::vector<VkSemaphore> semaphores)137 void VulkanInProcessContextProvider::EnqueueSecondaryCBSemaphores(
138     std::vector<VkSemaphore> semaphores) {
139   NOTREACHED();
140 }
141 
EnqueueSecondaryCBPostSubmitTask(base::OnceClosure closure)142 void VulkanInProcessContextProvider::EnqueueSecondaryCBPostSubmitTask(
143     base::OnceClosure closure) {
144   NOTREACHED();
145 }
146 
147 }  // namespace viz
148