Line data Source code
1 : /**
2 : Copyright (c) 2020-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #include "XLVkInstance.h"
25 : #include "XLVkLoop.h"
26 : #include "XLCoreDevice.h"
27 :
28 : #if MODULE_XENOLITH_FONT
29 : #include "backend/vk/XLVkFontQueue.h"
30 : #endif
31 :
32 : #if MODULE_XENOLITH_BACKEND_VKGUI
33 : #include "XLVkGuiPlatform.h"
34 : #endif
35 :
36 : namespace STAPPLER_VERSIONIZED stappler::xenolith::vk {
37 :
38 42 : SPUNUSED static VkResult s_createDebugUtilsMessengerEXT(VkInstance instance, const PFN_vkGetInstanceProcAddr getInstanceProcAddr, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) {
39 42 : auto func = (PFN_vkCreateDebugUtilsMessengerEXT) getInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
40 42 : if (func != nullptr) {
41 42 : return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
42 : } else {
43 0 : return VK_ERROR_EXTENSION_NOT_PRESENT;
44 : }
45 : }
46 :
47 303450 : SPUNUSED static VKAPI_ATTR VkBool32 VKAPI_CALL s_debugMessageCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
48 : VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) {
49 303450 : if (pCallbackData->pMessageIdName && strcmp(pCallbackData->pMessageIdName, "VUID-VkSwapchainCreateInfoKHR-imageExtent-01274") == 0) {
50 : // this is normal for multithreaded engine
51 0 : messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
52 : }
53 303450 : if (pCallbackData->pMessageIdName && strcmp(pCallbackData->pMessageIdName, "Loader Message") == 0) {
54 303450 : if (messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
55 303408 : if (StringView(pCallbackData->pMessage).starts_with("Instance Extension: ")
56 303408 : || StringView(pCallbackData->pMessage).starts_with("Device Extension: ")) {
57 302652 : return VK_FALSE;
58 : }
59 756 : log::verbose("Vk-Validation-Verbose", "[", pCallbackData->pMessageIdName, "] ", pCallbackData->pMessage);
60 42 : } else if (messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
61 0 : log::info("Vk-Validation-Info", "[", pCallbackData->pMessageIdName, "] ", pCallbackData->pMessage);
62 42 : } else if (messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
63 42 : log::warn("Vk-Validation-Warning", "[", pCallbackData->pMessageIdName, "] ", pCallbackData->pMessage);
64 0 : } else if (messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
65 0 : log::error("Vk-Validation-Error", "[", pCallbackData->pMessageIdName, "] ", pCallbackData->pMessage);
66 : }
67 798 : return VK_FALSE;
68 : } else {
69 0 : if (messageSeverity < XL_VK_MIN_MESSAGE_SEVERITY) {
70 0 : return VK_FALSE;
71 : }
72 :
73 0 : if (messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
74 0 : if (StringView(pCallbackData->pMessage).starts_with("Device Extension: ")) {
75 0 : return VK_FALSE;
76 : }
77 0 : log::verbose("Vk-Validation-Verbose", "[",
78 0 : pCallbackData->pMessageIdName ? pCallbackData->pMessageIdName : "(null)",
79 0 : "] ", pCallbackData->pMessage);
80 0 : } else if (messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
81 0 : log::info("Vk-Validation-Info", "[",
82 0 : pCallbackData->pMessageIdName ? pCallbackData->pMessageIdName : "(null)",
83 0 : "] ", pCallbackData->pMessage);
84 0 : } else if (messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
85 0 : log::warn("Vk-Validation-Warning", "[",
86 0 : pCallbackData->pMessageIdName ? pCallbackData->pMessageIdName : "(null)",
87 0 : "] ", pCallbackData->pMessage);
88 0 : } else if (messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
89 0 : log::error("Vk-Validation-Error", "[",
90 0 : pCallbackData->pMessageIdName ? pCallbackData->pMessageIdName : "(null)",
91 0 : "] ", pCallbackData->pMessage);
92 : }
93 0 : return VK_FALSE;
94 : }
95 : }
96 :
97 42 : Instance::Instance(VkInstance inst, const PFN_vkGetInstanceProcAddr getInstanceProcAddr, uint32_t targetVersion,
98 42 : Vector<StringView> &&optionals, Dso &&vulkanModule, TerminateCallback &&terminate, PresentSupportCallback &&present, bool validationEnabled, Rc<Ref> &&userdata)
99 42 : : core::Instance(move(vulkanModule), move(terminate), move(userdata)), InstanceTable(getInstanceProcAddr, inst), _instance(inst)
100 42 : , _version(targetVersion)
101 42 : , _optionals(move(optionals))
102 126 : , _checkPresentSupport(move(present)) {
103 42 : if (validationEnabled) {
104 42 : VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = { };
105 42 : debugCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
106 42 : debugCreateInfo.pNext = nullptr;
107 42 : debugCreateInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
108 42 : debugCreateInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
109 :
110 42 : debugCreateInfo.pfnUserCallback = s_debugMessageCallback;
111 42 : debugCreateInfo.pUserData = this;
112 :
113 42 : if (s_createDebugUtilsMessengerEXT(_instance, vkGetInstanceProcAddr, &debugCreateInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
114 0 : log::warn("Vk", "failed to set up debug messenger!");
115 : }
116 : }
117 :
118 42 : uint32_t deviceCount = 0;
119 42 : vkEnumeratePhysicalDevices(_instance, &deviceCount, nullptr);
120 :
121 42 : if (deviceCount) {
122 42 : Vector<VkPhysicalDevice> devices(deviceCount);
123 42 : vkEnumeratePhysicalDevices(_instance, &deviceCount, devices.data());
124 :
125 168 : for (auto &device : devices) {
126 126 : auto &it = _devices.emplace_back(getDeviceInfo(device));
127 :
128 252 : _availableDevices.emplace_back(core::DeviceProperties{
129 126 : String(it.properties.device10.properties.deviceName),
130 126 : it.properties.device10.properties.apiVersion,
131 126 : it.properties.device10.properties.driverVersion,
132 126 : it.supportsPresentation()
133 : });
134 : }
135 42 : }
136 42 : }
137 :
138 84 : Instance::~Instance() {
139 : if constexpr (s_enableValidationLayers) {
140 42 : if (debugMessenger != VK_NULL_HANDLE) {
141 42 : vkDestroyDebugUtilsMessengerEXT(_instance, debugMessenger, nullptr);
142 : }
143 : }
144 42 : vkDestroyInstance(_instance, nullptr);
145 84 : }
146 :
147 42 : Rc<core::Loop> Instance::makeLoop(core::LoopInfo &&info) const {
148 84 : return Rc<vk::Loop>::create(Rc<Instance>(const_cast<Instance *>(this)), move(info));
149 : }
150 :
151 42 : Rc<Device> Instance::makeDevice(const core::LoopInfo &info) const {
152 42 : auto data = info.platformData.cast<LoopData>().get();
153 42 : if (!data) {
154 0 : log::error("vk::Instance", "Fail to create device: loop platform data is not defined");
155 0 : return nullptr;
156 : }
157 :
158 42 : auto isDeviceSupported = [&] (const DeviceInfo &dev) {
159 42 : if (data->deviceSupportCallback) {
160 42 : if (!data->deviceSupportCallback(dev)) {
161 0 : return false;
162 : }
163 : } else {
164 0 : if (!dev.supportsPresentation()) {
165 0 : return false;
166 : }
167 : }
168 42 : return true;
169 42 : };
170 :
171 42 : auto getDeviceExtensions = [&] (const DeviceInfo &dev) {
172 42 : Vector<StringView> requiredExtensions;
173 42 : if (data->deviceExtensionsCallback) {
174 21 : requiredExtensions = data->deviceExtensionsCallback(dev);
175 : }
176 :
177 126 : for (auto &ext : s_requiredDeviceExtensions) {
178 84 : if (ext && !isPromotedExtension(dev.properties.device10.properties.apiVersion, StringView(ext))) {
179 0 : requiredExtensions.emplace_back(ext);
180 : }
181 : }
182 :
183 84 : for (auto &ext : dev.optionalExtensions) {
184 42 : requiredExtensions.emplace_back(ext);
185 : }
186 :
187 420 : for (auto &ext : dev.promotedExtensions) {
188 378 : if (!isPromotedExtension(dev.properties.device10.properties.apiVersion, ext)) {
189 0 : requiredExtensions.emplace_back(ext);
190 : }
191 : }
192 :
193 42 : return requiredExtensions;
194 0 : };
195 :
196 42 : auto isExtensionsSupported = [&] (const DeviceInfo &dev, const Vector<StringView> &requiredExtensions) {
197 42 : if (!requiredExtensions.empty()) {
198 42 : bool found = true;
199 105 : for (auto &req : requiredExtensions) {
200 63 : auto iit = std::find(dev.availableExtensions.begin(), dev.availableExtensions.end(), req);
201 63 : if (iit == dev.availableExtensions.end()) {
202 0 : found = false;
203 0 : break;
204 : }
205 : }
206 42 : if (!found) {
207 0 : return false;
208 : }
209 : }
210 42 : return true;
211 : };
212 :
213 42 : auto buildFeaturesList = [&] (const DeviceInfo &dev, DeviceInfo::Features &features) {
214 42 : if (data->deviceFeaturesCallback) {
215 0 : features = data->deviceFeaturesCallback(dev);
216 : }
217 :
218 42 : features.enableFromFeatures(DeviceInfo::Features::getRequired());
219 :
220 42 : if (!dev.features.canEnable(features, dev.properties.device10.properties.apiVersion)) {
221 0 : return false;
222 : }
223 :
224 42 : features.enableFromFeatures(DeviceInfo::Features::getOptional());
225 42 : features.disableFromFeatures(dev.features);
226 42 : features.flags = dev.features.flags;
227 42 : return true;
228 42 : };
229 :
230 42 : if (info.deviceIdx == DefaultDevice) {
231 42 : for (auto &it : _devices) {
232 42 : if (!isDeviceSupported(it)) {
233 0 : continue;
234 : }
235 :
236 42 : auto requiredExtensions = getDeviceExtensions(it);
237 42 : if (!isExtensionsSupported(it, requiredExtensions)) {
238 0 : continue;
239 : }
240 :
241 42 : DeviceInfo::Features targetFeatures;
242 42 : if (!buildFeaturesList(it, targetFeatures)) {
243 0 : continue;
244 : }
245 :
246 42 : if (it.features.canEnable(targetFeatures, it.properties.device10.properties.apiVersion)) {
247 84 : return Rc<vk::Device>::create(this, DeviceInfo(it), targetFeatures, requiredExtensions);
248 : }
249 42 : }
250 0 : } else if (info.deviceIdx < _devices.size()) {
251 0 : auto &dev = _devices[info.deviceIdx];
252 0 : if (!isDeviceSupported(dev)) {
253 0 : return nullptr;
254 : }
255 :
256 0 : auto requiredExtensions = getDeviceExtensions(dev);
257 0 : if (!isExtensionsSupported(dev, requiredExtensions)) {
258 0 : return nullptr;
259 : }
260 :
261 0 : DeviceInfo::Features targetFeatures;
262 0 : if (!buildFeaturesList(dev, targetFeatures)) {
263 0 : return nullptr;
264 : }
265 :
266 0 : if (dev.features.canEnable(targetFeatures, dev.properties.device10.properties.apiVersion)) {
267 0 : return Rc<vk::Device>::create(this, DeviceInfo(dev), targetFeatures, requiredExtensions);
268 : }
269 0 : }
270 0 : return nullptr;
271 : }
272 :
273 126 : static core::PresentMode getGlPresentMode(VkPresentModeKHR presentMode) {
274 126 : switch (presentMode) {
275 42 : case VK_PRESENT_MODE_IMMEDIATE_KHR: return core::PresentMode::Immediate; break;
276 0 : case VK_PRESENT_MODE_MAILBOX_KHR: return core::PresentMode::Mailbox; break;
277 42 : case VK_PRESENT_MODE_FIFO_KHR: return core::PresentMode::Fifo; break;
278 42 : case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return core::PresentMode::FifoRelaxed; break;
279 0 : default: return core::PresentMode::Unsupported; break;
280 : }
281 : }
282 :
283 42 : core::SurfaceInfo Instance::getSurfaceOptions(VkSurfaceKHR surface, VkPhysicalDevice device) const {
284 42 : core::SurfaceInfo ret;
285 :
286 42 : uint32_t formatCount = 0;
287 42 : vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
288 :
289 42 : uint32_t presentModeCount = 0;
290 42 : vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
291 :
292 42 : if (formatCount != 0) {
293 42 : Vector<VkSurfaceFormatKHR> formats; formats.resize(formatCount);
294 :
295 42 : vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, formats.data());
296 :
297 42 : ret.formats.reserve(formatCount);
298 126 : for (auto &it : formats) {
299 84 : ret.formats.emplace_back(core::ImageFormat(it.format), core::ColorSpace(it.colorSpace));
300 : }
301 42 : }
302 :
303 42 : if (presentModeCount != 0) {
304 42 : ret.presentModes.reserve(presentModeCount);
305 42 : Vector<VkPresentModeKHR> modes; modes.resize(presentModeCount);
306 :
307 42 : vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, modes.data());
308 :
309 168 : for (auto &it : modes) {
310 126 : ret.presentModes.emplace_back(getGlPresentMode(it));
311 : }
312 :
313 42 : std::sort(ret.presentModes.begin(), ret.presentModes.end(), [&] (core::PresentMode l, core::PresentMode r) {
314 168 : return toInt(l) > toInt(r);
315 : });
316 42 : }
317 :
318 : VkSurfaceCapabilitiesKHR caps;
319 42 : vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &caps);
320 :
321 42 : ret.minImageCount = caps.minImageCount;
322 42 : ret.maxImageCount = caps.maxImageCount;
323 42 : ret.currentExtent = Extent2(caps.currentExtent.width, caps.currentExtent.height);
324 42 : ret.minImageExtent = Extent2(caps.minImageExtent.width, caps.minImageExtent.height);
325 42 : ret.maxImageExtent = Extent2(caps.maxImageExtent.width, caps.maxImageExtent.height);
326 42 : ret.maxImageArrayLayers = caps.maxImageArrayLayers;
327 42 : ret.supportedTransforms = core::SurfaceTransformFlags(caps.supportedTransforms);
328 42 : ret.currentTransform = core::SurfaceTransformFlags(caps.currentTransform);
329 42 : ret.supportedCompositeAlpha = core::CompositeAlphaFlags(caps.supportedCompositeAlpha);
330 42 : ret.supportedUsageFlags = core::ImageUsage(caps.supportedUsageFlags);
331 84 : return ret;
332 0 : }
333 :
334 0 : VkExtent2D Instance::getSurfaceExtent(VkSurfaceKHR surface, VkPhysicalDevice device) const {
335 : VkSurfaceCapabilitiesKHR capabilities;
336 0 : vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &capabilities);
337 0 : return capabilities.currentExtent;
338 : }
339 :
340 42 : VkInstance Instance::getInstance() const {
341 42 : return _instance;
342 : }
343 :
344 : #if MODULE_XENOLITH_FONT
345 42 : Rc<core::Queue> Instance::makeFontQueue(StringView name) const {
346 84 : return Rc<FontQueue>::create(name);
347 : }
348 : #endif
349 :
350 : #if MODULE_XENOLITH_BACKEND_VKGUI
351 21 : Rc<xenolith::View> Instance::makeView(Application &loop, const core::Device &dev, ViewInfo &&info) const {
352 42 : return vk::platform::createView(loop, dev, move(info));
353 : }
354 : #endif
355 :
356 42 : void Instance::printDevicesInfo(std::ostream &out) const {
357 42 : out << "\n";
358 :
359 126 : auto getDeviceTypeString = [&] (VkPhysicalDeviceType type) -> const char * {
360 126 : switch (type) {
361 42 : case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return "Integrated GPU"; break;
362 42 : case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return "Discrete GPU"; break;
363 0 : case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return "Virtual GPU"; break;
364 42 : case VK_PHYSICAL_DEVICE_TYPE_CPU: return "CPU"; break;
365 0 : default: return "Other"; break;
366 : }
367 : return "Other";
368 : };
369 :
370 168 : for (auto &device : _devices) {
371 126 : out << "\tDevice: " << device.device << " " << getDeviceTypeString(device.properties.device10.properties.deviceType)
372 126 : << ": " << device.properties.device10.properties.deviceName
373 0 : << " (API: " << getVersionDescription(device.properties.device10.properties.apiVersion)
374 126 : << ", Driver: " << getVersionDescription(device.properties.device10.properties.driverVersion) << ")\n";
375 :
376 126 : uint32_t queueFamilyCount = 0;
377 126 : vkGetPhysicalDeviceQueueFamilyProperties(device.device, &queueFamilyCount, nullptr);
378 :
379 126 : Vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
380 126 : vkGetPhysicalDeviceQueueFamilyProperties(device.device, &queueFamilyCount, queueFamilies.data());
381 :
382 126 : int i = 0;
383 462 : for (const VkQueueFamilyProperties& queueFamily : queueFamilies) {
384 336 : bool empty = true;
385 336 : out << "\t\t[" << i << "] Queue family; Flags: ";
386 336 : if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
387 126 : if (!empty) { out << ", "; } else { empty = false; }
388 126 : out << "Graphics";
389 : }
390 336 : if (queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT) {
391 210 : if (!empty) { out << ", "; } else { empty = false; }
392 210 : out << "Compute";
393 : }
394 336 : if (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT) {
395 336 : if (!empty) { out << ", "; } else { empty = false; }
396 336 : out << "Transfer";
397 : }
398 336 : if (queueFamily.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) {
399 294 : if (!empty) { out << ", "; } else { empty = false; }
400 294 : out << "SparseBinding";
401 : }
402 336 : if (queueFamily.queueFlags & VK_QUEUE_PROTECTED_BIT) {
403 0 : if (!empty) { out << ", "; } else { empty = false; }
404 0 : out << "Protected";
405 : }
406 :
407 336 : VkBool32 presentSupport = _checkPresentSupport ? _checkPresentSupport(this, device.device, i) : false;
408 336 : if (presentSupport) {
409 105 : if (!empty) { out << ", "; } else { empty = false; }
410 105 : out << "Present";
411 : }
412 :
413 336 : out << "; Count: " << queueFamily.queueCount << "\n";
414 336 : i++;
415 : }
416 126 : out << device.description();
417 126 : }
418 42 : }
419 :
420 126 : void Instance::getDeviceFeatures(const VkPhysicalDevice &device, DeviceInfo::Features &features, ExtensionFlags flags, uint32_t api) const {
421 126 : void *next = nullptr;
422 : #ifdef VK_ENABLE_BETA_EXTENSIONS
423 : if ((flags & ExtensionFlags::Portability) != ExtensionFlags::None) {
424 : features.devicePortability.pNext = next;
425 : next = &features.devicePortability;
426 : }
427 : #endif
428 126 : features.flags = flags;
429 : #if VK_VERSION_1_3
430 126 : if (api >= VK_API_VERSION_1_3) {
431 126 : features.device13.pNext = next;
432 126 : features.device12.pNext = &features.device13;
433 126 : features.device11.pNext = &features.device12;
434 126 : features.device10.pNext = &features.device11;
435 :
436 126 : if (vkGetPhysicalDeviceFeatures2) {
437 126 : vkGetPhysicalDeviceFeatures2(device, &features.device10);
438 0 : } else if (vkGetPhysicalDeviceFeatures2KHR) {
439 0 : vkGetPhysicalDeviceFeatures2KHR(device, &features.device10);
440 : } else {
441 0 : vkGetPhysicalDeviceFeatures(device, &features.device10.features);
442 : }
443 :
444 126 : features.updateFrom13();
445 : } else
446 : #endif
447 0 : if (api >= VK_API_VERSION_1_2) {
448 0 : features.device12.pNext = next;
449 0 : features.device11.pNext = &features.device12;
450 0 : features.device10.pNext = &features.device11;
451 :
452 0 : if (vkGetPhysicalDeviceFeatures2) {
453 0 : vkGetPhysicalDeviceFeatures2(device, &features.device10);
454 0 : } else if (vkGetPhysicalDeviceFeatures2KHR) {
455 0 : vkGetPhysicalDeviceFeatures2KHR(device, &features.device10);
456 : } else {
457 0 : vkGetPhysicalDeviceFeatures(device, &features.device10.features);
458 : }
459 :
460 0 : features.updateFrom12();
461 : } else {
462 0 : if ((flags & ExtensionFlags::Storage16Bit) != ExtensionFlags::None) {
463 0 : features.device16bitStorage.pNext = next;
464 0 : next = &features.device16bitStorage;
465 : }
466 0 : if ((flags & ExtensionFlags::Storage8Bit) != ExtensionFlags::None) {
467 0 : features.device8bitStorage.pNext = next;
468 0 : next = &features.device8bitStorage;
469 : }
470 0 : if ((flags & ExtensionFlags::ShaderFloat16) != ExtensionFlags::None || (flags & ExtensionFlags::ShaderInt8) != ExtensionFlags::None) {
471 0 : features.deviceShaderFloat16Int8.pNext = next;
472 0 : next = &features.deviceShaderFloat16Int8;
473 : }
474 0 : if ((flags & ExtensionFlags::DescriptorIndexing) != ExtensionFlags::None) {
475 0 : features.deviceDescriptorIndexing.pNext = next;
476 0 : next = &features.deviceDescriptorIndexing;
477 : }
478 0 : if ((flags & ExtensionFlags::DeviceAddress) != ExtensionFlags::None) {
479 0 : features.deviceBufferDeviceAddress.pNext = next;
480 0 : next = &features.deviceBufferDeviceAddress;
481 : }
482 0 : features.device10.pNext = next;
483 :
484 0 : if (vkGetPhysicalDeviceFeatures2) {
485 0 : vkGetPhysicalDeviceFeatures2(device, &features.device10);
486 0 : } else if (vkGetPhysicalDeviceFeatures2KHR) {
487 0 : vkGetPhysicalDeviceFeatures2KHR(device, &features.device10);
488 : } else {
489 0 : vkGetPhysicalDeviceFeatures(device, &features.device10.features);
490 : }
491 :
492 0 : features.updateTo12(true);
493 : }
494 126 : }
495 :
496 126 : void Instance::getDeviceProperties(const VkPhysicalDevice &device, DeviceInfo::Properties &properties, ExtensionFlags flags, uint32_t api) const {
497 126 : void *next = nullptr;
498 : #ifdef VK_ENABLE_BETA_EXTENSIONS
499 : if ((flags & ExtensionFlags::Portability) != ExtensionFlags::None) {
500 : properties.devicePortability.pNext = next;
501 : next = &properties.devicePortability;
502 : }
503 : #endif
504 126 : if ((flags & ExtensionFlags::Maintenance3) != ExtensionFlags::None) {
505 126 : properties.deviceMaintenance3.pNext = next;
506 126 : next = &properties.deviceMaintenance3;
507 : }
508 126 : if ((flags & ExtensionFlags::DescriptorIndexing) != ExtensionFlags::None) {
509 126 : properties.deviceDescriptorIndexing.pNext = next;
510 126 : next = &properties.deviceDescriptorIndexing;
511 : }
512 :
513 126 : properties.device10.pNext = next;
514 :
515 126 : if (vkGetPhysicalDeviceProperties2) {
516 126 : vkGetPhysicalDeviceProperties2(device, &properties.device10);
517 0 : } else if (vkGetPhysicalDeviceProperties2KHR) {
518 0 : vkGetPhysicalDeviceProperties2KHR(device, &properties.device10);
519 : } else {
520 0 : vkGetPhysicalDeviceProperties(device, &properties.device10.properties);
521 : }
522 126 : }
523 :
524 126 : DeviceInfo Instance::getDeviceInfo(VkPhysicalDevice device) const {
525 126 : DeviceInfo ret;
526 126 : uint32_t graphicsFamily = maxOf<uint32_t>();
527 126 : uint32_t presentFamily = maxOf<uint32_t>();
528 126 : uint32_t transferFamily = maxOf<uint32_t>();
529 126 : uint32_t computeFamily = maxOf<uint32_t>();
530 :
531 126 : uint32_t queueFamilyCount = 0;
532 126 : vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
533 :
534 126 : Vector<DeviceInfo::QueueFamilyInfo> queueInfo(queueFamilyCount);
535 126 : Vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
536 :
537 126 : vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
538 :
539 126 : int i = 0;
540 462 : for (const VkQueueFamilyProperties &queueFamily : queueFamilies) {
541 336 : auto presentSupport = _checkPresentSupport ? _checkPresentSupport(this, device, i) : false;
542 :
543 336 : queueInfo[i].index = i;
544 336 : queueInfo[i].ops = getQueueOperations(queueFamily.queueFlags, presentSupport);
545 336 : queueInfo[i].count = queueFamily.queueCount;
546 336 : queueInfo[i].used = 0;
547 336 : queueInfo[i].minImageTransferGranularity = queueFamily.minImageTransferGranularity;
548 336 : queueInfo[i].presentSurfaceMask = presentSupport;
549 :
550 336 : if ((queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) && graphicsFamily == maxOf<uint32_t>()) {
551 126 : graphicsFamily = i;
552 : }
553 :
554 336 : if ((queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT) && transferFamily == maxOf<uint32_t>()) {
555 126 : transferFamily = i;
556 : }
557 :
558 336 : if ((queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT) && computeFamily == maxOf<uint32_t>()) {
559 126 : computeFamily = i;
560 : }
561 :
562 336 : if (presentSupport != 0 && presentFamily == maxOf<uint32_t>()) {
563 63 : presentFamily = i;
564 : }
565 :
566 336 : i ++;
567 : }
568 :
569 : // try to select different families for transfer and compute (for more concurrency)
570 126 : if (computeFamily == graphicsFamily) {
571 462 : for (auto &it : queueInfo) {
572 336 : if (it.index != graphicsFamily && ((it.ops & QueueOperations::Compute) != QueueOperations::None)) {
573 84 : computeFamily = it.index;
574 : }
575 : }
576 : }
577 :
578 126 : if (transferFamily == computeFamily || transferFamily == graphicsFamily) {
579 462 : for (auto &it : queueInfo) {
580 336 : if (it.index != graphicsFamily && it.index != computeFamily && ((it.ops & QueueOperations::Transfer) != QueueOperations::None)) {
581 126 : transferFamily = it.index;
582 : }
583 : }
584 126 : if (transferFamily == computeFamily || transferFamily == graphicsFamily) {
585 84 : if (queueInfo[computeFamily].count >= queueInfo[graphicsFamily].count) {
586 84 : transferFamily = computeFamily;
587 : } else {
588 0 : transferFamily = graphicsFamily;
589 : }
590 : }
591 : }
592 :
593 : // try to map present with graphics
594 126 : if (presentFamily != graphicsFamily) {
595 63 : if ((queueInfo[graphicsFamily].ops & QueueOperations::Present) != QueueOperations::None) {
596 0 : presentFamily = graphicsFamily;
597 : }
598 : }
599 :
600 : // fallback when Transfer or Compute is not defined
601 126 : if (transferFamily == maxOf<uint32_t>()) {
602 0 : transferFamily = graphicsFamily;
603 0 : queueInfo[transferFamily].ops |= QueueOperations::Transfer;
604 : }
605 :
606 126 : if (computeFamily == maxOf<uint32_t>()) {
607 0 : computeFamily = graphicsFamily;
608 : }
609 :
610 : uint32_t extensionCount;
611 126 : vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
612 :
613 126 : Vector<VkExtensionProperties> availableExtensions(extensionCount);
614 126 : vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
615 :
616 : // we need only API version for now
617 : VkPhysicalDeviceProperties deviceProperties;
618 126 : vkGetPhysicalDeviceProperties(device, &deviceProperties);
619 :
620 : // find required device extensions
621 126 : bool notFound = false;
622 252 : for (auto &extensionName : s_requiredDeviceExtensions) {
623 252 : if (!extensionName) {
624 126 : break;
625 : }
626 :
627 126 : if (isPromotedExtension(deviceProperties.apiVersion, extensionName)) {
628 126 : continue;
629 : }
630 :
631 0 : bool found = false;
632 0 : for (auto &extension : availableExtensions) {
633 0 : if (strcmp(extensionName, extension.extensionName) == 0) {
634 0 : found = true;
635 0 : break;
636 : }
637 : }
638 :
639 0 : if (!found) {
640 : if constexpr (s_printVkInfo) {
641 0 : log::verbose("Vk-Info", "Required device extension not found: %s", extensionName);
642 : }
643 0 : notFound = true;
644 0 : break;
645 : }
646 : }
647 :
648 126 : if (notFound) {
649 0 : ret.requiredExtensionsExists = false;
650 : } else {
651 126 : ret.requiredExtensionsExists = true;
652 : }
653 :
654 : // check for optionals
655 126 : ExtensionFlags extensionFlags = ExtensionFlags::None;
656 126 : Vector<StringView> enabledOptionals;
657 126 : Vector<StringView> promotedOptionals;
658 1386 : for (auto &extensionName : s_optionalDeviceExtensions) {
659 1386 : if (!extensionName) {
660 126 : break;
661 : }
662 :
663 1260 : checkIfExtensionAvailable(deviceProperties.apiVersion,
664 : extensionName, availableExtensions, enabledOptionals, promotedOptionals, extensionFlags);
665 : }
666 :
667 126 : ret.device = device;
668 126 : ret.graphicsFamily = queueInfo[graphicsFamily];
669 126 : ret.presentFamily = (presentFamily == maxOf<uint32_t>()) ? DeviceInfo::QueueFamilyInfo() : queueInfo[presentFamily];
670 126 : ret.transferFamily = queueInfo[transferFamily];
671 126 : ret.computeFamily = queueInfo[computeFamily];
672 126 : ret.optionalExtensions = move(enabledOptionals);
673 126 : ret.promotedExtensions = move(promotedOptionals);
674 :
675 126 : ret.availableExtensions.reserve(availableExtensions.size());
676 20412 : for (auto &it : availableExtensions) {
677 20286 : ret.availableExtensions.emplace_back(it.extensionName);
678 : }
679 :
680 126 : getDeviceProperties(device, ret.properties, extensionFlags, deviceProperties.apiVersion);
681 126 : getDeviceFeatures(device, ret.features, extensionFlags, deviceProperties.apiVersion);
682 :
683 126 : auto requiredFeatures = DeviceInfo::Features::getRequired();
684 126 : ret.requiredFeaturesExists = ret.features.canEnable(requiredFeatures, deviceProperties.apiVersion);
685 :
686 252 : return ret;
687 126 : }
688 :
689 : }
|