blob: 5d172abe6858885d407385b77f4feac371f5e540 [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
Hans Wennborgeb1475dc2020-06-19 11:11:0212#include "base/logging.h"
Peng Huang60108c22020-05-04 16:25:2413#include "base/strings/stringprintf.h"
Peng Huangea21d6f2020-05-14 18:22:2214#include "gpu/config/gpu_info.h" // nogncheck
Peng Huang386c31c2019-11-13 20:38:2315#include "gpu/config/vulkan_info.h"
dyen8a145fb72016-03-31 00:37:5116#include "gpu/vulkan/vulkan_command_pool.h"
Peng Huang60108c22020-05-04 16:25:2417#include "gpu/vulkan/vulkan_crash_keys.h"
Eric Karlf9ec4a502019-04-11 18:29:5218#include "gpu/vulkan/vulkan_fence_helper.h"
Chris Blumeb9adeda82018-06-08 00:23:5319#include "gpu/vulkan/vulkan_function_pointers.h"
Peng Huang60108c22020-05-04 16:25:2420#include "gpu/vulkan/vulkan_util.h"
dyen8a145fb72016-03-31 00:37:5121
dyen8a145fb72016-03-31 00:37:5122namespace gpu {
23
Emircan Uysalerd41c9bf2019-08-08 20:38:3324VulkanDeviceQueue::VulkanDeviceQueue(VkInstance vk_instance,
25 bool enforce_protected_memory)
26 : vk_instance_(vk_instance),
27 enforce_protected_memory_(enforce_protected_memory) {}
dyen8a145fb72016-03-31 00:37:5128
29VulkanDeviceQueue::~VulkanDeviceQueue() {
30 DCHECK_EQ(static_cast<VkPhysicalDevice>(VK_NULL_HANDLE), vk_physical_device_);
31 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), vk_device_);
32 DCHECK_EQ(static_cast<VkQueue>(VK_NULL_HANDLE), vk_queue_);
33}
34
Michael Spang7509e6d2018-05-16 17:08:2835bool VulkanDeviceQueue::Initialize(
36 uint32_t options,
Peng Huangea21d6f2020-05-14 18:22:2237 const GPUInfo* gpu_info,
Peng Huangc2d69cc2019-10-07 23:02:2538 const VulkanInfo& info,
Michael Spang4e46bc22018-06-21 23:07:5139 const std::vector<const char*>& required_extensions,
Peng Huang576415de2020-03-02 20:04:3240 const std::vector<const char*>& optional_extensions,
Emircan Uysalerd41c9bf2019-08-08 20:38:3341 bool allow_protected_memory,
David Reveman0bacc1d82020-12-16 21:38:2242 const GetPresentationSupportCallback& get_presentation_support,
43 uint32_t heap_memory_limit) {
Peng Huangbcf31dc2019-03-12 00:35:4044 DCHECK_EQ(static_cast<VkPhysicalDevice>(VK_NULL_HANDLE), vk_physical_device_);
45 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), owned_vk_device_);
46 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), vk_device_);
47 DCHECK_EQ(static_cast<VkQueue>(VK_NULL_HANDLE), vk_queue_);
Emircan Uysalerd41c9bf2019-08-08 20:38:3348 DCHECK(!enforce_protected_memory_ || allow_protected_memory);
Peng Huangbcf31dc2019-03-12 00:35:4049
suyambu.rmf2fbf532017-12-04 08:38:1550 if (VK_NULL_HANDLE == vk_instance_)
dyen8a145fb72016-03-31 00:37:5151 return false;
52
dyen5bd6d4f2016-03-31 15:25:4553 VkResult result = VK_SUCCESS;
dyen8a145fb72016-03-31 00:37:5154
dyen8a145fb72016-03-31 00:37:5155 VkQueueFlags queue_flags = 0;
56 if (options & DeviceQueueOption::GRAPHICS_QUEUE_FLAG)
57 queue_flags |= VK_QUEUE_GRAPHICS_BIT;
58
Peng Huangea21d6f2020-05-14 18:22:2259 // We prefer to use discrete GPU, integrated GPU is the second, and then
60 // others.
61 static constexpr int kDeviceTypeScores[] = {
62 0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
63 3, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
64 4, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
65 2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
66 1, // VK_PHYSICAL_DEVICE_TYPE_CPU
67 };
68 static_assert(VK_PHYSICAL_DEVICE_TYPE_OTHER == 0, "");
69 static_assert(VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU == 1, "");
70 static_assert(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU == 2, "");
71 static_assert(VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU == 3, "");
72 static_assert(VK_PHYSICAL_DEVICE_TYPE_CPU == 4, "");
73
dyen8a145fb72016-03-31 00:37:5174 int device_index = -1;
75 int queue_index = -1;
Peng Huangea21d6f2020-05-14 18:22:2276 int device_score = -1;
Peng Huangc2d69cc2019-10-07 23:02:2577 for (size_t i = 0; i < info.physical_devices.size(); ++i) {
78 const auto& device_info = info.physical_devices[i];
Peng Huangea21d6f2020-05-14 18:22:2279 const auto& device_properties = device_info.properties;
Peng Huange8610052020-06-06 00:21:5580 if (device_properties.apiVersion < info.used_api_version)
81 continue;
82
Peng Huang5ba08e92020-12-23 00:44:2683 // If gpu_info is provided, the device should match it.
84 if (gpu_info && (device_properties.vendorID != gpu_info->gpu.vendor_id ||
85 device_properties.deviceID != gpu_info->gpu.device_id)) {
86 continue;
87 }
88
89 if (device_properties.deviceType < 0 ||
90 device_properties.deviceType > VK_PHYSICAL_DEVICE_TYPE_CPU) {
91 DLOG(ERROR) << "Unsupported device type: "
92 << device_properties.deviceType;
93 continue;
94 }
95
Peng Huangc2d69cc2019-10-07 23:02:2596 const VkPhysicalDevice& device = device_info.device;
Peng Huang5ba08e92020-12-23 00:44:2697 bool found = false;
Peng Huangc2d69cc2019-10-07 23:02:2598 for (size_t n = 0; n < device_info.queue_families.size(); ++n) {
99 if ((device_info.queue_families[n].queueFlags & queue_flags) !=
Peng Huang5ba08e92020-12-23 00:44:26100 queue_flags) {
Peng Huangc2d69cc2019-10-07 23:02:25101 continue;
Peng Huang5ba08e92020-12-23 00:44:26102 }
dyen8a145fb72016-03-31 00:37:51103
Peng Huangc2d69cc2019-10-07 23:02:25104 if (options & DeviceQueueOption::PRESENTATION_SUPPORT_QUEUE_FLAG &&
105 !get_presentation_support.Run(device, device_info.queue_families,
106 n)) {
107 continue;
dyen8a145fb72016-03-31 00:37:51108 }
109
Peng Huangea21d6f2020-05-14 18:22:22110 if (kDeviceTypeScores[device_properties.deviceType] > device_score) {
111 device_index = i;
112 queue_index = static_cast<int>(n);
113 device_score = kDeviceTypeScores[device_properties.deviceType];
Peng Huang5ba08e92020-12-23 00:44:26114 found = true;
115 break;
Peng Huangea21d6f2020-05-14 18:22:22116 }
dyen8a145fb72016-03-31 00:37:51117 }
Peng Huang5ba08e92020-12-23 00:44:26118
119 if (!found)
120 continue;
121
122 // Use the device, if it matches gpu_info.
123 if (gpu_info)
124 break;
125
126 // If the device is a discrete GPU, we will use it. Otherwise go through
127 // all the devices and find the device with the highest score.
128 if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
129 break;
dyen8a145fb72016-03-31 00:37:51130 }
131
Peng Huangea21d6f2020-05-14 18:22:22132 if (device_index == -1) {
133 DLOG(ERROR) << "Cannot find capable device.";
dyen8a145fb72016-03-31 00:37:51134 return false;
Peng Huang50f53ae82020-03-20 19:52:13135 }
dyen8a145fb72016-03-31 00:37:51136
Peng Huangc2d69cc2019-10-07 23:02:25137 const auto& physical_device_info = info.physical_devices[device_index];
138 vk_physical_device_ = physical_device_info.device;
139 vk_physical_device_properties_ = physical_device_info.properties;
Peng Huangcc7ddc42020-11-26 22:39:16140 vk_physical_device_driver_properties_ =
141 physical_device_info.driver_properties;
dyen8a145fb72016-03-31 00:37:51142 vk_queue_index_ = queue_index;
143
144 float queue_priority = 0.0f;
145 VkDeviceQueueCreateInfo queue_create_info = {};
146 queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
147 queue_create_info.queueFamilyIndex = queue_index;
148 queue_create_info.queueCount = 1;
149 queue_create_info.pQueuePriorities = &queue_priority;
Emircan Uysalerd41c9bf2019-08-08 20:38:33150 queue_create_info.flags =
151 allow_protected_memory ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0;
dyen8a145fb72016-03-31 00:37:51152
Michael Spang4e46bc22018-06-21 23:07:51153 std::vector<const char*> enabled_extensions;
Peng Huang576415de2020-03-02 20:04:32154 for (const char* extension : required_extensions) {
155 const auto it =
156 std::find_if(physical_device_info.extensions.begin(),
157 physical_device_info.extensions.end(),
158 [extension](const VkExtensionProperties& p) {
159 return std::strcmp(extension, p.extensionName) == 0;
160 });
161 if (it == physical_device_info.extensions.end()) {
162 // On Fuchsia, some device extensions are provided by layers.
163 // TODO(penghuang): checking extensions against layer device extensions
164 // too.
165#if !defined(OS_FUCHSIA)
166 DLOG(ERROR) << "Required Vulkan extension " << extension
167 << " is not supported.";
168 return false;
169#endif
170 }
171 enabled_extensions.push_back(extension);
172 }
173
174 for (const char* extension : optional_extensions) {
175 const auto it =
176 std::find_if(physical_device_info.extensions.begin(),
177 physical_device_info.extensions.end(),
178 [extension](const VkExtensionProperties& p) {
179 return std::strcmp(extension, p.extensionName) == 0;
180 });
181 if (it == physical_device_info.extensions.end()) {
182 DLOG(ERROR) << "Optional Vulkan extension " << extension
183 << " is not supported.";
184 } else {
185 enabled_extensions.push_back(extension);
186 }
187 }
Michael Spang4e46bc22018-06-21 23:07:51188
Peng Huang60108c22020-05-04 16:25:24189 crash_keys::vulkan_device_api_version.Set(
190 VkVersionToString(vk_physical_device_properties_.apiVersion));
191 crash_keys::vulkan_device_driver_version.Set(base::StringPrintf(
192 "0x%08x", vk_physical_device_properties_.driverVersion));
193 crash_keys::vulkan_device_vendor_id.Set(
194 base::StringPrintf("0x%04x", vk_physical_device_properties_.vendorID));
195 crash_keys::vulkan_device_id.Set(
196 base::StringPrintf("0x%04x", vk_physical_device_properties_.deviceID));
197 static const char* kDeviceTypeNames[] = {
198 "other", "integrated", "discrete", "virtual", "cpu",
199 };
200 uint32_t gpu_type = vk_physical_device_properties_.deviceType;
201 if (gpu_type >= base::size(kDeviceTypeNames))
202 gpu_type = 0;
203 crash_keys::vulkan_device_type.Set(kDeviceTypeNames[gpu_type]);
204 crash_keys::vulkan_device_name.Set(vk_physical_device_properties_.deviceName);
Peng Huangc2d69cc2019-10-07 23:02:25205
206 // Disable all physical device features by default.
207 enabled_device_features_2_ = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
Emircan Uysalerd41c9bf2019-08-08 20:38:33208
Sergey Ulanov6ff66f22019-08-14 00:38:39209 // Android and Fuchsia need YCbCr sampler support.
210#if defined(OS_ANDROID) || defined(OS_FUCHSIA)
Peng Huangc2d69cc2019-10-07 23:02:25211 if (!physical_device_info.feature_sampler_ycbcr_conversion) {
Sergey Ulanov6ff66f22019-08-14 00:38:39212 LOG(ERROR) << "samplerYcbcrConversion is not supported.";
Vikas Sonib08bd9b2019-06-13 05:49:47213 return false;
214 }
Peng Huangc2d69cc2019-10-07 23:02:25215 sampler_ycbcr_conversion_features_ = {
216 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES};
217 sampler_ycbcr_conversion_features_.samplerYcbcrConversion = VK_TRUE;
Vikas Sonib08bd9b2019-06-13 05:49:47218
Sergey Ulanov6ff66f22019-08-14 00:38:39219 // Add VkPhysicalDeviceSamplerYcbcrConversionFeatures struct to pNext chain
220 // of VkPhysicalDeviceFeatures2 to enable YCbCr sampler support.
221 sampler_ycbcr_conversion_features_.pNext = enabled_device_features_2_.pNext;
222 enabled_device_features_2_.pNext = &sampler_ycbcr_conversion_features_;
223#endif // defined(OS_ANDROID) || defined(OS_FUCHSIA)
Emircan Uysalerd41c9bf2019-08-08 20:38:33224
225 if (allow_protected_memory) {
Peng Huangc2d69cc2019-10-07 23:02:25226 if (!physical_device_info.feature_protected_memory) {
Emircan Uysalerd41c9bf2019-08-08 20:38:33227 DLOG(ERROR) << "Protected memory is not supported";
228 return false;
229 }
Peng Huangc2d69cc2019-10-07 23:02:25230 protected_memory_features_ = {
231 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES};
232 protected_memory_features_.protectedMemory = VK_TRUE;
Emircan Uysalerd41c9bf2019-08-08 20:38:33233
Sergey Ulanov6ff66f22019-08-14 00:38:39234 // Add VkPhysicalDeviceProtectedMemoryFeatures struct to pNext chain
235 // of VkPhysicalDeviceFeatures2 to enable YCbCr sampler support.
236 protected_memory_features_.pNext = enabled_device_features_2_.pNext;
237 enabled_device_features_2_.pNext = &protected_memory_features_;
Emircan Uysalerd41c9bf2019-08-08 20:38:33238 }
Sergey Ulanov6ff66f22019-08-14 00:38:39239
Peng Huangc2d69cc2019-10-07 23:02:25240 VkDeviceCreateInfo device_create_info = {
241 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
Vikas Sonib08bd9b2019-06-13 05:49:47242 device_create_info.pNext = enabled_device_features_2_.pNext;
dyen8a145fb72016-03-31 00:37:51243 device_create_info.queueCreateInfoCount = 1;
244 device_create_info.pQueueCreateInfos = &queue_create_info;
Michael Spang4e46bc22018-06-21 23:07:51245 device_create_info.enabledExtensionCount = enabled_extensions.size();
246 device_create_info.ppEnabledExtensionNames = enabled_extensions.data();
Vikas Sonib08bd9b2019-06-13 05:49:47247 device_create_info.pEnabledFeatures = &enabled_device_features_2_.features;
dyen8a145fb72016-03-31 00:37:51248
Chris Blumef0fb42f2018-06-28 19:35:25249 result = vkCreateDevice(vk_physical_device_, &device_create_info, nullptr,
Peng Huangbcf31dc2019-03-12 00:35:40250 &owned_vk_device_);
Peng Huang50f53ae82020-03-20 19:52:13251 if (VK_SUCCESS != result) {
252 DLOG(ERROR) << "vkCreateDevice failed. result:" << result;
dyen8a145fb72016-03-31 00:37:51253 return false;
Peng Huang50f53ae82020-03-20 19:52:13254 }
dyen8a145fb72016-03-31 00:37:51255
Michael Spang4e46bc22018-06-21 23:07:51256 enabled_extensions_ = gfx::ExtensionSet(std::begin(enabled_extensions),
257 std::end(enabled_extensions));
258
Michael Spang5086fb92019-06-11 21:13:59259 if (!gpu::GetVulkanFunctionPointers()->BindDeviceFunctionPointers(
Peng Huang60108c22020-05-04 16:25:24260 owned_vk_device_, info.used_api_version, enabled_extensions_)) {
Michael Spang5086fb92019-06-11 21:13:59261 vkDestroyDevice(owned_vk_device_, nullptr);
262 owned_vk_device_ = VK_NULL_HANDLE;
263 return false;
264 }
265
266 vk_device_ = owned_vk_device_;
Michael Spang4e46bc22018-06-21 23:07:51267
Emircan Uysalerac88d872019-09-25 03:13:59268 if (allow_protected_memory) {
269 VkDeviceQueueInfo2 queue_info2 = {};
270 queue_info2.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2;
271 queue_info2.flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
272 queue_info2.queueFamilyIndex = queue_index;
273 queue_info2.queueIndex = 0;
274 vkGetDeviceQueue2(vk_device_, &queue_info2, &vk_queue_);
275 } else {
276 vkGetDeviceQueue(vk_device_, queue_index, 0, &vk_queue_);
277 }
dyen8a145fb72016-03-31 00:37:51278
David Reveman0bacc1d82020-12-16 21:38:22279 std::vector<VkDeviceSize> heap_size_limit(
280 VK_MAX_MEMORY_HEAPS,
281 heap_memory_limit ? heap_memory_limit : VK_WHOLE_SIZE);
Peng Huang992a8552020-05-04 18:05:30282 vma::CreateAllocator(vk_physical_device_, vk_device_, vk_instance_,
David Reveman0bacc1d82020-12-16 21:38:22283 heap_size_limit.data(), &vma_allocator_);
Eric Karlf9ec4a502019-04-11 18:29:52284 cleanup_helper_ = std::make_unique<VulkanFenceHelper>(this);
285
Emircan Uysalerd41c9bf2019-08-08 20:38:33286 allow_protected_memory_ = allow_protected_memory;
dyen8a145fb72016-03-31 00:37:51287 return true;
288}
289
Shouqun Liu80cd8a82019-06-17 18:15:19290bool VulkanDeviceQueue::InitializeForWebView(
Peng Huangbcf31dc2019-03-12 00:35:40291 VkPhysicalDevice vk_physical_device,
292 VkDevice vk_device,
293 VkQueue vk_queue,
294 uint32_t vk_queue_index,
295 gfx::ExtensionSet enabled_extensions) {
296 DCHECK_EQ(static_cast<VkPhysicalDevice>(VK_NULL_HANDLE), vk_physical_device_);
297 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), owned_vk_device_);
298 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), vk_device_);
299 DCHECK_EQ(static_cast<VkQueue>(VK_NULL_HANDLE), vk_queue_);
dyen8a145fb72016-03-31 00:37:51300
Peng Huangbcf31dc2019-03-12 00:35:40301 vk_physical_device_ = vk_physical_device;
302 vk_device_ = vk_device;
303 vk_queue_ = vk_queue;
304 vk_queue_index_ = vk_queue_index;
305 enabled_extensions_ = std::move(enabled_extensions);
Eric Karlf9ec4a502019-04-11 18:29:52306
David Reveman0bacc1d82020-12-16 21:38:22307 vma::CreateAllocator(vk_physical_device_, vk_device_, vk_instance_, nullptr,
Vasiliy Telezhnikov5d6e8d142020-07-22 22:15:50308 &vma_allocator_);
309
Eric Karlf9ec4a502019-04-11 18:29:52310 cleanup_helper_ = std::make_unique<VulkanFenceHelper>(this);
Peng Huangbcf31dc2019-03-12 00:35:40311 return true;
312}
313
314void VulkanDeviceQueue::Destroy() {
Michael Spang5086fb92019-06-11 21:13:59315 if (cleanup_helper_) {
316 cleanup_helper_->Destroy();
317 cleanup_helper_.reset();
318 }
Eric Karlf9ec4a502019-04-11 18:29:52319
Peng Huang992a8552020-05-04 18:05:30320 if (vma_allocator_ != VK_NULL_HANDLE) {
321 vma::DestroyAllocator(vma_allocator_);
322 vma_allocator_ = VK_NULL_HANDLE;
323 }
324
Peng Huangbcf31dc2019-03-12 00:35:40325 if (VK_NULL_HANDLE != owned_vk_device_) {
326 vkDestroyDevice(owned_vk_device_, nullptr);
327 owned_vk_device_ = VK_NULL_HANDLE;
328 }
329 vk_device_ = VK_NULL_HANDLE;
dyen8a145fb72016-03-31 00:37:51330 vk_queue_ = VK_NULL_HANDLE;
331 vk_queue_index_ = 0;
dyen8a145fb72016-03-31 00:37:51332 vk_physical_device_ = VK_NULL_HANDLE;
333}
334
mostynb6682b1c42016-04-19 10:17:30335std::unique_ptr<VulkanCommandPool> VulkanDeviceQueue::CreateCommandPool() {
336 std::unique_ptr<VulkanCommandPool> command_pool(new VulkanCommandPool(this));
Emircan Uysalerd41c9bf2019-08-08 20:38:33337 if (!command_pool->Initialize(enforce_protected_memory_))
dyen8a145fb72016-03-31 00:37:51338 return nullptr;
339
340 return command_pool;
341}
342
Peng Huangea21d6f2020-05-14 18:22:22343} // namespace gpu