blob: 77127965721040baadde68baa30043e2ab85cd5f [file] [log] [blame]
dyen8a145fb72016-03-31 00:37:511// 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 "gpu/vulkan/vulkan_device_queue.h"
6
Piotr Tworek252e35222020-04-30 13:28:427#include <cstring>
dyen5bd6d4f2016-03-31 15:25:458#include <unordered_set>
Peng Huangbcf31dc2019-03-12 00:35:409#include <utility>
dyen8a145fb72016-03-31 00:37:5110#include <vector>
11
Peng Huang60108c22020-05-04 16:25:2412#include "base/strings/stringprintf.h"
Peng Huangea21d6f2020-05-14 18:22:2213#include "gpu/config/gpu_info.h" // nogncheck
Peng Huang386c31c2019-11-13 20:38:2314#include "gpu/config/vulkan_info.h"
dyen8a145fb72016-03-31 00:37:5115#include "gpu/vulkan/vulkan_command_pool.h"
Peng Huang60108c22020-05-04 16:25:2416#include "gpu/vulkan/vulkan_crash_keys.h"
Eric Karlf9ec4a502019-04-11 18:29:5217#include "gpu/vulkan/vulkan_fence_helper.h"
Chris Blumeb9adeda82018-06-08 00:23:5318#include "gpu/vulkan/vulkan_function_pointers.h"
Peng Huang60108c22020-05-04 16:25:2419#include "gpu/vulkan/vulkan_util.h"
dyen8a145fb72016-03-31 00:37:5120
dyen8a145fb72016-03-31 00:37:5121namespace gpu {
22
Emircan Uysalerd41c9bf2019-08-08 20:38:3323VulkanDeviceQueue::VulkanDeviceQueue(VkInstance vk_instance,
24 bool enforce_protected_memory)
25 : vk_instance_(vk_instance),
26 enforce_protected_memory_(enforce_protected_memory) {}
dyen8a145fb72016-03-31 00:37:5127
28VulkanDeviceQueue::~VulkanDeviceQueue() {
29 DCHECK_EQ(static_cast<VkPhysicalDevice>(VK_NULL_HANDLE), vk_physical_device_);
30 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), vk_device_);
31 DCHECK_EQ(static_cast<VkQueue>(VK_NULL_HANDLE), vk_queue_);
32}
33
Michael Spang7509e6d2018-05-16 17:08:2834bool VulkanDeviceQueue::Initialize(
35 uint32_t options,
Peng Huangea21d6f2020-05-14 18:22:2236 const GPUInfo* gpu_info,
Peng Huangc2d69cc2019-10-07 23:02:2537 const VulkanInfo& info,
Michael Spang4e46bc22018-06-21 23:07:5138 const std::vector<const char*>& required_extensions,
Peng Huang576415de2020-03-02 20:04:3239 const std::vector<const char*>& optional_extensions,
Emircan Uysalerd41c9bf2019-08-08 20:38:3340 bool allow_protected_memory,
Sergey Ulanove82b1002019-07-22 22:23:3941 const GetPresentationSupportCallback& get_presentation_support) {
Peng Huangbcf31dc2019-03-12 00:35:4042 DCHECK_EQ(static_cast<VkPhysicalDevice>(VK_NULL_HANDLE), vk_physical_device_);
43 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), owned_vk_device_);
44 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), vk_device_);
45 DCHECK_EQ(static_cast<VkQueue>(VK_NULL_HANDLE), vk_queue_);
Emircan Uysalerd41c9bf2019-08-08 20:38:3346 DCHECK(!enforce_protected_memory_ || allow_protected_memory);
Peng Huangbcf31dc2019-03-12 00:35:4047
suyambu.rmf2fbf532017-12-04 08:38:1548 if (VK_NULL_HANDLE == vk_instance_)
dyen8a145fb72016-03-31 00:37:5149 return false;
50
dyen5bd6d4f2016-03-31 15:25:4551 VkResult result = VK_SUCCESS;
dyen8a145fb72016-03-31 00:37:5152
dyen8a145fb72016-03-31 00:37:5153 VkQueueFlags queue_flags = 0;
54 if (options & DeviceQueueOption::GRAPHICS_QUEUE_FLAG)
55 queue_flags |= VK_QUEUE_GRAPHICS_BIT;
56
Peng Huangea21d6f2020-05-14 18:22:2257 // We prefer to use discrete GPU, integrated GPU is the second, and then
58 // others.
59 static constexpr int kDeviceTypeScores[] = {
60 0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
61 3, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
62 4, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
63 2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
64 1, // VK_PHYSICAL_DEVICE_TYPE_CPU
65 };
66 static_assert(VK_PHYSICAL_DEVICE_TYPE_OTHER == 0, "");
67 static_assert(VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU == 1, "");
68 static_assert(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU == 2, "");
69 static_assert(VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU == 3, "");
70 static_assert(VK_PHYSICAL_DEVICE_TYPE_CPU == 4, "");
71
dyen8a145fb72016-03-31 00:37:5172 int device_index = -1;
73 int queue_index = -1;
Peng Huangea21d6f2020-05-14 18:22:2274 int device_score = -1;
Peng Huangc2d69cc2019-10-07 23:02:2575 for (size_t i = 0; i < info.physical_devices.size(); ++i) {
76 const auto& device_info = info.physical_devices[i];
Peng Huangea21d6f2020-05-14 18:22:2277 const auto& device_properties = device_info.properties;
Peng Huangc2d69cc2019-10-07 23:02:2578 const VkPhysicalDevice& device = device_info.device;
79 for (size_t n = 0; n < device_info.queue_families.size(); ++n) {
80 if ((device_info.queue_families[n].queueFlags & queue_flags) !=
81 queue_flags)
82 continue;
dyen8a145fb72016-03-31 00:37:5183
Peng Huangc2d69cc2019-10-07 23:02:2584 if (options & DeviceQueueOption::PRESENTATION_SUPPORT_QUEUE_FLAG &&
85 !get_presentation_support.Run(device, device_info.queue_families,
86 n)) {
87 continue;
dyen8a145fb72016-03-31 00:37:5188 }
89
Peng Huangea21d6f2020-05-14 18:22:2290 // If gpu_info is provided, the device should match it.
91 if (gpu_info && (device_properties.vendorID != gpu_info->gpu.vendor_id ||
92 device_properties.deviceID != gpu_info->gpu.device_id)) {
93 continue;
94 }
95
96 if (device_properties.deviceType < 0 ||
97 device_properties.deviceType > VK_PHYSICAL_DEVICE_TYPE_CPU) {
98 DLOG(ERROR) << "Unsupported device type: "
99 << device_properties.deviceType;
100 continue;
101 }
102
103 if (kDeviceTypeScores[device_properties.deviceType] > device_score) {
104 device_index = i;
105 queue_index = static_cast<int>(n);
106 device_score = kDeviceTypeScores[device_properties.deviceType];
107 }
108
109 // Use the device, if it matches gpu_info.
110 if (gpu_info)
111 break;
112
113 // If the device is a discrete GPU, we will use it. Otherwise go through
114 // all the devices and find the device with the highest score.
115 if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
116 break;
dyen8a145fb72016-03-31 00:37:51117 }
118 }
119
Peng Huangea21d6f2020-05-14 18:22:22120 if (device_index == -1) {
121 DLOG(ERROR) << "Cannot find capable device.";
dyen8a145fb72016-03-31 00:37:51122 return false;
Peng Huang50f53ae82020-03-20 19:52:13123 }
dyen8a145fb72016-03-31 00:37:51124
Peng Huangc2d69cc2019-10-07 23:02:25125 const auto& physical_device_info = info.physical_devices[device_index];
126 vk_physical_device_ = physical_device_info.device;
127 vk_physical_device_properties_ = physical_device_info.properties;
dyen8a145fb72016-03-31 00:37:51128 vk_queue_index_ = queue_index;
129
130 float queue_priority = 0.0f;
131 VkDeviceQueueCreateInfo queue_create_info = {};
132 queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
133 queue_create_info.queueFamilyIndex = queue_index;
134 queue_create_info.queueCount = 1;
135 queue_create_info.pQueuePriorities = &queue_priority;
Emircan Uysalerd41c9bf2019-08-08 20:38:33136 queue_create_info.flags =
137 allow_protected_memory ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0;
dyen8a145fb72016-03-31 00:37:51138
Michael Spang4e46bc22018-06-21 23:07:51139 std::vector<const char*> enabled_extensions;
Peng Huang576415de2020-03-02 20:04:32140 for (const char* extension : required_extensions) {
141 const auto it =
142 std::find_if(physical_device_info.extensions.begin(),
143 physical_device_info.extensions.end(),
144 [extension](const VkExtensionProperties& p) {
145 return std::strcmp(extension, p.extensionName) == 0;
146 });
147 if (it == physical_device_info.extensions.end()) {
148 // On Fuchsia, some device extensions are provided by layers.
149 // TODO(penghuang): checking extensions against layer device extensions
150 // too.
151#if !defined(OS_FUCHSIA)
152 DLOG(ERROR) << "Required Vulkan extension " << extension
153 << " is not supported.";
154 return false;
155#endif
156 }
157 enabled_extensions.push_back(extension);
158 }
159
160 for (const char* extension : optional_extensions) {
161 const auto it =
162 std::find_if(physical_device_info.extensions.begin(),
163 physical_device_info.extensions.end(),
164 [extension](const VkExtensionProperties& p) {
165 return std::strcmp(extension, p.extensionName) == 0;
166 });
167 if (it == physical_device_info.extensions.end()) {
168 DLOG(ERROR) << "Optional Vulkan extension " << extension
169 << " is not supported.";
170 } else {
171 enabled_extensions.push_back(extension);
172 }
173 }
Michael Spang4e46bc22018-06-21 23:07:51174
Peng Huang60108c22020-05-04 16:25:24175 if (vk_physical_device_properties_.apiVersion < info.used_api_version) {
176 LOG(ERROR) << "Physical device doesn't support version."
177 << info.used_api_version;
178 return false;
179 }
180
181 crash_keys::vulkan_device_api_version.Set(
182 VkVersionToString(vk_physical_device_properties_.apiVersion));
183 crash_keys::vulkan_device_driver_version.Set(base::StringPrintf(
184 "0x%08x", vk_physical_device_properties_.driverVersion));
185 crash_keys::vulkan_device_vendor_id.Set(
186 base::StringPrintf("0x%04x", vk_physical_device_properties_.vendorID));
187 crash_keys::vulkan_device_id.Set(
188 base::StringPrintf("0x%04x", vk_physical_device_properties_.deviceID));
189 static const char* kDeviceTypeNames[] = {
190 "other", "integrated", "discrete", "virtual", "cpu",
191 };
192 uint32_t gpu_type = vk_physical_device_properties_.deviceType;
193 if (gpu_type >= base::size(kDeviceTypeNames))
194 gpu_type = 0;
195 crash_keys::vulkan_device_type.Set(kDeviceTypeNames[gpu_type]);
196 crash_keys::vulkan_device_name.Set(vk_physical_device_properties_.deviceName);
Peng Huangc2d69cc2019-10-07 23:02:25197
198 // Disable all physical device features by default.
199 enabled_device_features_2_ = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
Emircan Uysalerd41c9bf2019-08-08 20:38:33200
Sergey Ulanov6ff66f22019-08-14 00:38:39201 // Android and Fuchsia need YCbCr sampler support.
202#if defined(OS_ANDROID) || defined(OS_FUCHSIA)
Peng Huangc2d69cc2019-10-07 23:02:25203 if (!physical_device_info.feature_sampler_ycbcr_conversion) {
Sergey Ulanov6ff66f22019-08-14 00:38:39204 LOG(ERROR) << "samplerYcbcrConversion is not supported.";
Vikas Sonib08bd9b2019-06-13 05:49:47205 return false;
206 }
Peng Huangc2d69cc2019-10-07 23:02:25207 sampler_ycbcr_conversion_features_ = {
208 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES};
209 sampler_ycbcr_conversion_features_.samplerYcbcrConversion = VK_TRUE;
Vikas Sonib08bd9b2019-06-13 05:49:47210
Sergey Ulanov6ff66f22019-08-14 00:38:39211 // Add VkPhysicalDeviceSamplerYcbcrConversionFeatures struct to pNext chain
212 // of VkPhysicalDeviceFeatures2 to enable YCbCr sampler support.
213 sampler_ycbcr_conversion_features_.pNext = enabled_device_features_2_.pNext;
214 enabled_device_features_2_.pNext = &sampler_ycbcr_conversion_features_;
215#endif // defined(OS_ANDROID) || defined(OS_FUCHSIA)
Emircan Uysalerd41c9bf2019-08-08 20:38:33216
217 if (allow_protected_memory) {
Peng Huangc2d69cc2019-10-07 23:02:25218 if (!physical_device_info.feature_protected_memory) {
Emircan Uysalerd41c9bf2019-08-08 20:38:33219 DLOG(ERROR) << "Protected memory is not supported";
220 return false;
221 }
Peng Huangc2d69cc2019-10-07 23:02:25222 protected_memory_features_ = {
223 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES};
224 protected_memory_features_.protectedMemory = VK_TRUE;
Emircan Uysalerd41c9bf2019-08-08 20:38:33225
Sergey Ulanov6ff66f22019-08-14 00:38:39226 // Add VkPhysicalDeviceProtectedMemoryFeatures struct to pNext chain
227 // of VkPhysicalDeviceFeatures2 to enable YCbCr sampler support.
228 protected_memory_features_.pNext = enabled_device_features_2_.pNext;
229 enabled_device_features_2_.pNext = &protected_memory_features_;
Emircan Uysalerd41c9bf2019-08-08 20:38:33230 }
Sergey Ulanov6ff66f22019-08-14 00:38:39231
Peng Huangc2d69cc2019-10-07 23:02:25232 VkDeviceCreateInfo device_create_info = {
233 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
Vikas Sonib08bd9b2019-06-13 05:49:47234 device_create_info.pNext = enabled_device_features_2_.pNext;
dyen8a145fb72016-03-31 00:37:51235 device_create_info.queueCreateInfoCount = 1;
236 device_create_info.pQueueCreateInfos = &queue_create_info;
Michael Spang4e46bc22018-06-21 23:07:51237 device_create_info.enabledExtensionCount = enabled_extensions.size();
238 device_create_info.ppEnabledExtensionNames = enabled_extensions.data();
Vikas Sonib08bd9b2019-06-13 05:49:47239 device_create_info.pEnabledFeatures = &enabled_device_features_2_.features;
dyen8a145fb72016-03-31 00:37:51240
Chris Blumef0fb42f2018-06-28 19:35:25241 result = vkCreateDevice(vk_physical_device_, &device_create_info, nullptr,
Peng Huangbcf31dc2019-03-12 00:35:40242 &owned_vk_device_);
Peng Huang50f53ae82020-03-20 19:52:13243 if (VK_SUCCESS != result) {
244 DLOG(ERROR) << "vkCreateDevice failed. result:" << result;
dyen8a145fb72016-03-31 00:37:51245 return false;
Peng Huang50f53ae82020-03-20 19:52:13246 }
dyen8a145fb72016-03-31 00:37:51247
Michael Spang4e46bc22018-06-21 23:07:51248 enabled_extensions_ = gfx::ExtensionSet(std::begin(enabled_extensions),
249 std::end(enabled_extensions));
250
Michael Spang5086fb92019-06-11 21:13:59251 if (!gpu::GetVulkanFunctionPointers()->BindDeviceFunctionPointers(
Peng Huang60108c22020-05-04 16:25:24252 owned_vk_device_, info.used_api_version, enabled_extensions_)) {
Michael Spang5086fb92019-06-11 21:13:59253 vkDestroyDevice(owned_vk_device_, nullptr);
254 owned_vk_device_ = VK_NULL_HANDLE;
255 return false;
256 }
257
258 vk_device_ = owned_vk_device_;
Michael Spang4e46bc22018-06-21 23:07:51259
Emircan Uysalerac88d872019-09-25 03:13:59260 if (allow_protected_memory) {
261 VkDeviceQueueInfo2 queue_info2 = {};
262 queue_info2.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2;
263 queue_info2.flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
264 queue_info2.queueFamilyIndex = queue_index;
265 queue_info2.queueIndex = 0;
266 vkGetDeviceQueue2(vk_device_, &queue_info2, &vk_queue_);
267 } else {
268 vkGetDeviceQueue(vk_device_, queue_index, 0, &vk_queue_);
269 }
dyen8a145fb72016-03-31 00:37:51270
Peng Huang992a8552020-05-04 18:05:30271 vma::CreateAllocator(vk_physical_device_, vk_device_, vk_instance_,
272 &vma_allocator_);
Eric Karlf9ec4a502019-04-11 18:29:52273 cleanup_helper_ = std::make_unique<VulkanFenceHelper>(this);
274
Emircan Uysalerd41c9bf2019-08-08 20:38:33275 allow_protected_memory_ = allow_protected_memory;
dyen8a145fb72016-03-31 00:37:51276 return true;
277}
278
Shouqun Liu80cd8a82019-06-17 18:15:19279bool VulkanDeviceQueue::InitializeForWebView(
Peng Huangbcf31dc2019-03-12 00:35:40280 VkPhysicalDevice vk_physical_device,
281 VkDevice vk_device,
282 VkQueue vk_queue,
283 uint32_t vk_queue_index,
284 gfx::ExtensionSet enabled_extensions) {
285 DCHECK_EQ(static_cast<VkPhysicalDevice>(VK_NULL_HANDLE), vk_physical_device_);
286 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), owned_vk_device_);
287 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), vk_device_);
288 DCHECK_EQ(static_cast<VkQueue>(VK_NULL_HANDLE), vk_queue_);
dyen8a145fb72016-03-31 00:37:51289
Peng Huangbcf31dc2019-03-12 00:35:40290 vk_physical_device_ = vk_physical_device;
291 vk_device_ = vk_device;
292 vk_queue_ = vk_queue;
293 vk_queue_index_ = vk_queue_index;
294 enabled_extensions_ = std::move(enabled_extensions);
Eric Karlf9ec4a502019-04-11 18:29:52295
296 cleanup_helper_ = std::make_unique<VulkanFenceHelper>(this);
Peng Huangbcf31dc2019-03-12 00:35:40297 return true;
298}
299
300void VulkanDeviceQueue::Destroy() {
Michael Spang5086fb92019-06-11 21:13:59301 if (cleanup_helper_) {
302 cleanup_helper_->Destroy();
303 cleanup_helper_.reset();
304 }
Eric Karlf9ec4a502019-04-11 18:29:52305
Peng Huang992a8552020-05-04 18:05:30306 if (vma_allocator_ != VK_NULL_HANDLE) {
307 vma::DestroyAllocator(vma_allocator_);
308 vma_allocator_ = VK_NULL_HANDLE;
309 }
310
Peng Huangbcf31dc2019-03-12 00:35:40311 if (VK_NULL_HANDLE != owned_vk_device_) {
312 vkDestroyDevice(owned_vk_device_, nullptr);
313 owned_vk_device_ = VK_NULL_HANDLE;
314 }
315 vk_device_ = VK_NULL_HANDLE;
dyen8a145fb72016-03-31 00:37:51316 vk_queue_ = VK_NULL_HANDLE;
317 vk_queue_index_ = 0;
dyen8a145fb72016-03-31 00:37:51318 vk_physical_device_ = VK_NULL_HANDLE;
319}
320
mostynb6682b1c42016-04-19 10:17:30321std::unique_ptr<VulkanCommandPool> VulkanDeviceQueue::CreateCommandPool() {
322 std::unique_ptr<VulkanCommandPool> command_pool(new VulkanCommandPool(this));
Emircan Uysalerd41c9bf2019-08-08 20:38:33323 if (!command_pool->Initialize(enforce_protected_memory_))
dyen8a145fb72016-03-31 00:37:51324 return nullptr;
325
326 return command_pool;
327}
328
Peng Huangea21d6f2020-05-14 18:22:22329} // namespace gpu