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