blob: 4d95330b5675b5177a118a059880f1b794e136f4 [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
dyen5bd6d4f2016-03-31 15:25:457#include <unordered_set>
Peng Huangbcf31dc2019-03-12 00:35:408#include <utility>
dyen8a145fb72016-03-31 00:37:519#include <vector>
10
Peng Huang386c31c2019-11-13 20:38:2311#include "gpu/config/vulkan_info.h"
dyen8a145fb72016-03-31 00:37:5112#include "gpu/vulkan/vulkan_command_pool.h"
Eric Karlf9ec4a502019-04-11 18:29:5213#include "gpu/vulkan/vulkan_fence_helper.h"
Chris Blumeb9adeda82018-06-08 00:23:5314#include "gpu/vulkan/vulkan_function_pointers.h"
dyen8a145fb72016-03-31 00:37:5115
dyen8a145fb72016-03-31 00:37:5116namespace gpu {
17
Emircan Uysalerd41c9bf2019-08-08 20:38:3318VulkanDeviceQueue::VulkanDeviceQueue(VkInstance vk_instance,
19 bool enforce_protected_memory)
20 : vk_instance_(vk_instance),
21 enforce_protected_memory_(enforce_protected_memory) {}
dyen8a145fb72016-03-31 00:37:5122
23VulkanDeviceQueue::~VulkanDeviceQueue() {
24 DCHECK_EQ(static_cast<VkPhysicalDevice>(VK_NULL_HANDLE), vk_physical_device_);
25 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), vk_device_);
26 DCHECK_EQ(static_cast<VkQueue>(VK_NULL_HANDLE), vk_queue_);
27}
28
Michael Spang7509e6d2018-05-16 17:08:2829bool VulkanDeviceQueue::Initialize(
30 uint32_t options,
Peng Huangc2d69cc2019-10-07 23:02:2531 const VulkanInfo& info,
Michael Spang4e46bc22018-06-21 23:07:5132 const std::vector<const char*>& required_extensions,
Peng Huang576415de2020-03-02 20:04:3233 const std::vector<const char*>& optional_extensions,
Emircan Uysalerd41c9bf2019-08-08 20:38:3334 bool allow_protected_memory,
Sergey Ulanove82b1002019-07-22 22:23:3935 const GetPresentationSupportCallback& get_presentation_support) {
Peng Huangbcf31dc2019-03-12 00:35:4036 DCHECK_EQ(static_cast<VkPhysicalDevice>(VK_NULL_HANDLE), vk_physical_device_);
37 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), owned_vk_device_);
38 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), vk_device_);
39 DCHECK_EQ(static_cast<VkQueue>(VK_NULL_HANDLE), vk_queue_);
Emircan Uysalerd41c9bf2019-08-08 20:38:3340 DCHECK(!enforce_protected_memory_ || allow_protected_memory);
Peng Huangbcf31dc2019-03-12 00:35:4041
suyambu.rmf2fbf532017-12-04 08:38:1542 if (VK_NULL_HANDLE == vk_instance_)
dyen8a145fb72016-03-31 00:37:5143 return false;
44
dyen5bd6d4f2016-03-31 15:25:4545 VkResult result = VK_SUCCESS;
dyen8a145fb72016-03-31 00:37:5146
dyen8a145fb72016-03-31 00:37:5147 VkQueueFlags queue_flags = 0;
48 if (options & DeviceQueueOption::GRAPHICS_QUEUE_FLAG)
49 queue_flags |= VK_QUEUE_GRAPHICS_BIT;
50
51 int device_index = -1;
52 int queue_index = -1;
Peng Huangc2d69cc2019-10-07 23:02:2553 for (size_t i = 0; i < info.physical_devices.size(); ++i) {
54 const auto& device_info = info.physical_devices[i];
55 const VkPhysicalDevice& device = device_info.device;
56 for (size_t n = 0; n < device_info.queue_families.size(); ++n) {
57 if ((device_info.queue_families[n].queueFlags & queue_flags) !=
58 queue_flags)
59 continue;
dyen8a145fb72016-03-31 00:37:5160
Peng Huangc2d69cc2019-10-07 23:02:2561 if (options & DeviceQueueOption::PRESENTATION_SUPPORT_QUEUE_FLAG &&
62 !get_presentation_support.Run(device, device_info.queue_families,
63 n)) {
64 continue;
dyen8a145fb72016-03-31 00:37:5165 }
66
Peng Huangc2d69cc2019-10-07 23:02:2567 queue_index = static_cast<int>(n);
68 break;
69 }
70 if (-1 != queue_index) {
71 device_index = static_cast<int>(i);
72 break;
dyen8a145fb72016-03-31 00:37:5173 }
74 }
75
Peng Huang50f53ae82020-03-20 19:52:1376 if (queue_index == -1) {
77 DLOG(ERROR) << "Cannot find capable device queue.";
dyen8a145fb72016-03-31 00:37:5178 return false;
Peng Huang50f53ae82020-03-20 19:52:1379 }
dyen8a145fb72016-03-31 00:37:5180
Peng Huangc2d69cc2019-10-07 23:02:2581 const auto& physical_device_info = info.physical_devices[device_index];
82 vk_physical_device_ = physical_device_info.device;
83 vk_physical_device_properties_ = physical_device_info.properties;
dyen8a145fb72016-03-31 00:37:5184 vk_queue_index_ = queue_index;
85
86 float queue_priority = 0.0f;
87 VkDeviceQueueCreateInfo queue_create_info = {};
88 queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
89 queue_create_info.queueFamilyIndex = queue_index;
90 queue_create_info.queueCount = 1;
91 queue_create_info.pQueuePriorities = &queue_priority;
Emircan Uysalerd41c9bf2019-08-08 20:38:3392 queue_create_info.flags =
93 allow_protected_memory ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0;
dyen8a145fb72016-03-31 00:37:5194
Michael Spang4e46bc22018-06-21 23:07:5195 std::vector<const char*> enabled_extensions;
Peng Huang576415de2020-03-02 20:04:3296 for (const char* extension : required_extensions) {
97 const auto it =
98 std::find_if(physical_device_info.extensions.begin(),
99 physical_device_info.extensions.end(),
100 [extension](const VkExtensionProperties& p) {
101 return std::strcmp(extension, p.extensionName) == 0;
102 });
103 if (it == physical_device_info.extensions.end()) {
104 // On Fuchsia, some device extensions are provided by layers.
105 // TODO(penghuang): checking extensions against layer device extensions
106 // too.
107#if !defined(OS_FUCHSIA)
108 DLOG(ERROR) << "Required Vulkan extension " << extension
109 << " is not supported.";
110 return false;
111#endif
112 }
113 enabled_extensions.push_back(extension);
114 }
115
116 for (const char* extension : optional_extensions) {
117 const auto it =
118 std::find_if(physical_device_info.extensions.begin(),
119 physical_device_info.extensions.end(),
120 [extension](const VkExtensionProperties& p) {
121 return std::strcmp(extension, p.extensionName) == 0;
122 });
123 if (it == physical_device_info.extensions.end()) {
124 DLOG(ERROR) << "Optional Vulkan extension " << extension
125 << " is not supported.";
126 } else {
127 enabled_extensions.push_back(extension);
128 }
129 }
Michael Spang4e46bc22018-06-21 23:07:51130
Peng Huangc2d69cc2019-10-07 23:02:25131 uint32_t device_api_version = std::min(
132 info.used_api_version, vk_physical_device_properties_.apiVersion);
133
134 // Disable all physical device features by default.
135 enabled_device_features_2_ = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
Emircan Uysalerd41c9bf2019-08-08 20:38:33136
Sergey Ulanov6ff66f22019-08-14 00:38:39137 // Android and Fuchsia need YCbCr sampler support.
138#if defined(OS_ANDROID) || defined(OS_FUCHSIA)
Peng Huangc2d69cc2019-10-07 23:02:25139 if (!physical_device_info.feature_sampler_ycbcr_conversion) {
Sergey Ulanov6ff66f22019-08-14 00:38:39140 LOG(ERROR) << "samplerYcbcrConversion is not supported.";
Vikas Sonib08bd9b2019-06-13 05:49:47141 return false;
142 }
Peng Huangc2d69cc2019-10-07 23:02:25143 sampler_ycbcr_conversion_features_ = {
144 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES};
145 sampler_ycbcr_conversion_features_.samplerYcbcrConversion = VK_TRUE;
Vikas Sonib08bd9b2019-06-13 05:49:47146
Sergey Ulanov6ff66f22019-08-14 00:38:39147 // Add VkPhysicalDeviceSamplerYcbcrConversionFeatures struct to pNext chain
148 // of VkPhysicalDeviceFeatures2 to enable YCbCr sampler support.
149 sampler_ycbcr_conversion_features_.pNext = enabled_device_features_2_.pNext;
150 enabled_device_features_2_.pNext = &sampler_ycbcr_conversion_features_;
151#endif // defined(OS_ANDROID) || defined(OS_FUCHSIA)
Emircan Uysalerd41c9bf2019-08-08 20:38:33152
153 if (allow_protected_memory) {
Peng Huangc2d69cc2019-10-07 23:02:25154 if (!physical_device_info.feature_protected_memory) {
Emircan Uysalerd41c9bf2019-08-08 20:38:33155 DLOG(ERROR) << "Protected memory is not supported";
156 return false;
157 }
Peng Huangc2d69cc2019-10-07 23:02:25158 protected_memory_features_ = {
159 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES};
160 protected_memory_features_.protectedMemory = VK_TRUE;
Emircan Uysalerd41c9bf2019-08-08 20:38:33161
Sergey Ulanov6ff66f22019-08-14 00:38:39162 // Add VkPhysicalDeviceProtectedMemoryFeatures struct to pNext chain
163 // of VkPhysicalDeviceFeatures2 to enable YCbCr sampler support.
164 protected_memory_features_.pNext = enabled_device_features_2_.pNext;
165 enabled_device_features_2_.pNext = &protected_memory_features_;
Emircan Uysalerd41c9bf2019-08-08 20:38:33166 }
Sergey Ulanov6ff66f22019-08-14 00:38:39167
Peng Huangc2d69cc2019-10-07 23:02:25168 VkDeviceCreateInfo device_create_info = {
169 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
Vikas Sonib08bd9b2019-06-13 05:49:47170 device_create_info.pNext = enabled_device_features_2_.pNext;
dyen8a145fb72016-03-31 00:37:51171 device_create_info.queueCreateInfoCount = 1;
172 device_create_info.pQueueCreateInfos = &queue_create_info;
Michael Spang4e46bc22018-06-21 23:07:51173 device_create_info.enabledExtensionCount = enabled_extensions.size();
174 device_create_info.ppEnabledExtensionNames = enabled_extensions.data();
Vikas Sonib08bd9b2019-06-13 05:49:47175 device_create_info.pEnabledFeatures = &enabled_device_features_2_.features;
dyen8a145fb72016-03-31 00:37:51176
Chris Blumef0fb42f2018-06-28 19:35:25177 result = vkCreateDevice(vk_physical_device_, &device_create_info, nullptr,
Peng Huangbcf31dc2019-03-12 00:35:40178 &owned_vk_device_);
Peng Huang50f53ae82020-03-20 19:52:13179 if (VK_SUCCESS != result) {
180 DLOG(ERROR) << "vkCreateDevice failed. result:" << result;
dyen8a145fb72016-03-31 00:37:51181 return false;
Peng Huang50f53ae82020-03-20 19:52:13182 }
dyen8a145fb72016-03-31 00:37:51183
Michael Spang4e46bc22018-06-21 23:07:51184 enabled_extensions_ = gfx::ExtensionSet(std::begin(enabled_extensions),
185 std::end(enabled_extensions));
186
Michael Spang5086fb92019-06-11 21:13:59187 if (!gpu::GetVulkanFunctionPointers()->BindDeviceFunctionPointers(
Sergey Ulanove82b1002019-07-22 22:23:39188 owned_vk_device_, device_api_version, enabled_extensions_)) {
Michael Spang5086fb92019-06-11 21:13:59189 vkDestroyDevice(owned_vk_device_, nullptr);
190 owned_vk_device_ = VK_NULL_HANDLE;
191 return false;
192 }
193
194 vk_device_ = owned_vk_device_;
Michael Spang4e46bc22018-06-21 23:07:51195
Emircan Uysalerac88d872019-09-25 03:13:59196 if (allow_protected_memory) {
197 VkDeviceQueueInfo2 queue_info2 = {};
198 queue_info2.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2;
199 queue_info2.flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
200 queue_info2.queueFamilyIndex = queue_index;
201 queue_info2.queueIndex = 0;
202 vkGetDeviceQueue2(vk_device_, &queue_info2, &vk_queue_);
203 } else {
204 vkGetDeviceQueue(vk_device_, queue_index, 0, &vk_queue_);
205 }
dyen8a145fb72016-03-31 00:37:51206
Eric Karlf9ec4a502019-04-11 18:29:52207 cleanup_helper_ = std::make_unique<VulkanFenceHelper>(this);
208
Emircan Uysalerd41c9bf2019-08-08 20:38:33209 allow_protected_memory_ = allow_protected_memory;
dyen8a145fb72016-03-31 00:37:51210 return true;
211}
212
Shouqun Liu80cd8a82019-06-17 18:15:19213bool VulkanDeviceQueue::InitializeForWebView(
Peng Huangbcf31dc2019-03-12 00:35:40214 VkPhysicalDevice vk_physical_device,
215 VkDevice vk_device,
216 VkQueue vk_queue,
217 uint32_t vk_queue_index,
218 gfx::ExtensionSet enabled_extensions) {
219 DCHECK_EQ(static_cast<VkPhysicalDevice>(VK_NULL_HANDLE), vk_physical_device_);
220 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), owned_vk_device_);
221 DCHECK_EQ(static_cast<VkDevice>(VK_NULL_HANDLE), vk_device_);
222 DCHECK_EQ(static_cast<VkQueue>(VK_NULL_HANDLE), vk_queue_);
dyen8a145fb72016-03-31 00:37:51223
Peng Huangbcf31dc2019-03-12 00:35:40224 vk_physical_device_ = vk_physical_device;
225 vk_device_ = vk_device;
226 vk_queue_ = vk_queue;
227 vk_queue_index_ = vk_queue_index;
228 enabled_extensions_ = std::move(enabled_extensions);
Eric Karlf9ec4a502019-04-11 18:29:52229
230 cleanup_helper_ = std::make_unique<VulkanFenceHelper>(this);
Peng Huangbcf31dc2019-03-12 00:35:40231 return true;
232}
233
234void VulkanDeviceQueue::Destroy() {
Michael Spang5086fb92019-06-11 21:13:59235 if (cleanup_helper_) {
236 cleanup_helper_->Destroy();
237 cleanup_helper_.reset();
238 }
Eric Karlf9ec4a502019-04-11 18:29:52239
Peng Huangbcf31dc2019-03-12 00:35:40240 if (VK_NULL_HANDLE != owned_vk_device_) {
241 vkDestroyDevice(owned_vk_device_, nullptr);
242 owned_vk_device_ = VK_NULL_HANDLE;
243 }
244 vk_device_ = VK_NULL_HANDLE;
dyen8a145fb72016-03-31 00:37:51245 vk_queue_ = VK_NULL_HANDLE;
246 vk_queue_index_ = 0;
dyen8a145fb72016-03-31 00:37:51247 vk_physical_device_ = VK_NULL_HANDLE;
248}
249
mostynb6682b1c42016-04-19 10:17:30250std::unique_ptr<VulkanCommandPool> VulkanDeviceQueue::CreateCommandPool() {
251 std::unique_ptr<VulkanCommandPool> command_pool(new VulkanCommandPool(this));
Emircan Uysalerd41c9bf2019-08-08 20:38:33252 if (!command_pool->Initialize(enforce_protected_memory_))
dyen8a145fb72016-03-31 00:37:51253 return nullptr;
254
255 return command_pool;
256}
257
Peng Huang50f53ae82020-03-20 19:52:13258} // namespace gpu