LCOV - code coverage report
Current view: top level - source/renderer/backend/vulkan - DeviceSelection.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 1 312 0.3 %
Date: 2023-01-19 00:18:29 Functions: 2 17 11.8 %

          Line data    Source code
       1             : /* Copyright (C) 2023 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "precompiled.h"
      19             : 
      20             : #include "DeviceSelection.h"
      21             : 
      22             : #include "lib/code_annotation.h"
      23             : #include "lib/config2.h"
      24             : #include "renderer/backend/vulkan/Device.h"
      25             : #include "renderer/backend/vulkan/Utilities.h"
      26             : #include "scriptinterface/JSON.h"
      27             : #include "scriptinterface/Object.h"
      28             : #include "scriptinterface/ScriptInterface.h"
      29             : #include "scriptinterface/ScriptRequest.h"
      30             : 
      31             : #include <algorithm>
      32             : #include <limits>
      33             : #include <string>
      34             : #include <type_traits>
      35             : #include <vector>
      36             : 
      37             : namespace Renderer
      38             : {
      39             : 
      40             : namespace Backend
      41             : {
      42             : 
      43             : namespace Vulkan
      44             : {
      45             : 
      46             : namespace
      47             : {
      48             : 
      49           0 : std::vector<std::string> GetPhysicalDeviceExtensions(VkPhysicalDevice device)
      50             : {
      51           0 :     uint32_t extensionCount = 0;
      52           0 :     ENSURE_VK_SUCCESS(vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr));
      53           0 :     std::vector<VkExtensionProperties> extensions(extensionCount);
      54           0 :     ENSURE_VK_SUCCESS(vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, extensions.data()));
      55             : 
      56           0 :     std::vector<std::string> availableExtensions;
      57           0 :     availableExtensions.reserve(extensions.size());
      58           0 :     for (const VkExtensionProperties& extension : extensions)
      59           0 :         availableExtensions.emplace_back(extension.extensionName);
      60           0 :     std::sort(availableExtensions.begin(), availableExtensions.end());
      61           0 :     return availableExtensions;
      62             : }
      63             : 
      64           0 : uint32_t GetDeviceTypeScore(const VkPhysicalDeviceType deviceType)
      65             : {
      66           0 :     uint32_t score = 0;
      67             :     // We prefer discrete GPU over integrated, and integrated over others.
      68           0 :     switch (deviceType)
      69             :     {
      70           0 :     case VK_PHYSICAL_DEVICE_TYPE_OTHER:
      71           0 :         score = 1;
      72           0 :         break;
      73           0 :     case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
      74           0 :         score = 4;
      75           0 :         break;
      76           0 :     case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
      77           0 :         score = 5;
      78           0 :         break;
      79           0 :     case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
      80           0 :         score = 3;
      81           0 :         break;
      82           0 :     case VK_PHYSICAL_DEVICE_TYPE_CPU:
      83           0 :         score = 2;
      84           0 :         break;
      85           0 :     default:
      86           0 :         break;
      87             :     }
      88           0 :     return score;
      89             : }
      90             : 
      91           0 : VkDeviceSize GetDeviceTotalMemory(
      92             :     const VkPhysicalDeviceMemoryProperties& memoryProperties)
      93             : {
      94           0 :     VkDeviceSize totalMemory = 0;
      95           0 :     for (uint32_t heapIndex = 0; heapIndex < memoryProperties.memoryHeapCount; ++heapIndex)
      96           0 :         if (memoryProperties.memoryHeaps[heapIndex].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
      97           0 :             totalMemory += memoryProperties.memoryHeaps[heapIndex].size;
      98           0 :     return totalMemory;
      99             : }
     100             : 
     101           0 : VkDeviceSize GetHostTotalMemory(
     102             :     const VkPhysicalDeviceMemoryProperties& memoryProperties)
     103             : {
     104           0 :     VkDeviceSize totalMemory = 0;
     105           0 :     for (uint32_t heapIndex = 0; heapIndex < memoryProperties.memoryHeapCount; ++heapIndex)
     106           0 :         if ((memoryProperties.memoryHeaps[heapIndex].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) == 0)
     107           0 :             totalMemory += memoryProperties.memoryHeaps[heapIndex].size;
     108           0 :     return totalMemory;
     109             : }
     110             : 
     111             : // We don't support some types in JS, so wrap them to have in the report.
     112             : template<typename T, typename Tag = void>
     113             : struct ReportFormatHelper
     114             : {
     115             :     std::string operator()(const T&) const { return "unknown"; }
     116             : };
     117             : 
     118             : template<typename T>
     119             : struct ReportFormatHelper<T, typename std::enable_if_t<std::is_floating_point_v<T>>>
     120             : {
     121           0 :     float operator()(const T& value) const { return static_cast<float>(value); }
     122             : };
     123             : 
     124             : template<typename T>
     125             : struct ReportFormatHelper<T, typename std::enable_if_t<std::is_integral_v<T>>>
     126             : {
     127             :     static constexpr bool IsSigned = std::is_signed_v<T>;
     128             :     using ResultType = std::conditional_t<IsSigned, int32_t, uint32_t>;
     129           0 :     uint32_t operator()(const T& value) const
     130             :     {
     131           0 :         if (value > std::numeric_limits<ResultType>::max())
     132           0 :             return std::numeric_limits<ResultType>::max();
     133             :         if constexpr (IsSigned)
     134             :         {
     135             :             if (value < std::numeric_limits<ResultType>::min())
     136             :                 return std::numeric_limits<ResultType>::min();
     137             :         }
     138           0 :         return static_cast<ResultType>(value);
     139             :     }
     140             : };
     141             : 
     142             : template<typename T>
     143             : struct ReportFormatHelper<T, typename std::enable_if_t<std::is_enum_v<T>>>
     144             : {
     145             :     using HelperType = ReportFormatHelper<std::underlying_type_t<T>>;
     146             :     using ResultType = std::invoke_result_t<HelperType, std::underlying_type_t<T>>;
     147             :     ResultType operator()(const T& value) const
     148             :     {
     149             :         HelperType helper{};
     150             :         return helper(value);
     151             :     }
     152             : };
     153             : 
     154             : template<typename T>
     155             : struct ReportFormatHelper<T, typename std::enable_if_t<std::is_array_v<T>>>
     156             : {
     157             :     using HelperType = ReportFormatHelper<std::remove_extent_t<T>>;
     158             :     using ElementType = std::invoke_result_t<HelperType, std::remove_extent_t<T>>;
     159           0 :     std::vector<ElementType> operator()(const T& value) const
     160             :     {
     161           0 :         std::vector<ElementType> arr;
     162           0 :         arr.reserve(std::size(value));
     163             :         HelperType helper{};
     164           0 :         for (const auto& element : value)
     165           0 :             arr.emplace_back(helper(element));
     166           0 :         return arr;
     167             :     }
     168             : };
     169             : 
     170           0 : SAvailablePhysicalDevice MakeAvailablePhysicalDevice(
     171             :     const uint32_t physicalDeviceIndex, VkPhysicalDevice physicalDevice,
     172             :     VkSurfaceKHR surface, const std::vector<const char*>& requiredDeviceExtensions)
     173             : {
     174           0 :     SAvailablePhysicalDevice availablePhysicalDevice{};
     175             : 
     176           0 :     availablePhysicalDevice.index = physicalDeviceIndex;
     177           0 :     availablePhysicalDevice.device = physicalDevice;
     178           0 :     availablePhysicalDevice.hasOutputToSurfaceSupport = false;
     179           0 :     availablePhysicalDevice.extensions = GetPhysicalDeviceExtensions(availablePhysicalDevice.device);
     180           0 :     auto hasExtension = [&extensions = availablePhysicalDevice.extensions](const char* name) -> bool
     181           0 :     {
     182           0 :         return std::find(extensions.begin(), extensions.end(), name) != extensions.end();
     183           0 :     };
     184             : 
     185           0 :     availablePhysicalDevice.hasRequiredExtensions =
     186           0 :         std::all_of(requiredDeviceExtensions.begin(), requiredDeviceExtensions.end(), hasExtension);
     187             : 
     188           0 :     vkGetPhysicalDeviceMemoryProperties(
     189             :         availablePhysicalDevice.device, &availablePhysicalDevice.memoryProperties);
     190           0 :     availablePhysicalDevice.deviceTotalMemory =
     191           0 :         GetDeviceTotalMemory(availablePhysicalDevice.memoryProperties);
     192           0 :     availablePhysicalDevice.hostTotalMemory =
     193           0 :         GetHostTotalMemory(availablePhysicalDevice.memoryProperties);
     194             : 
     195           0 :     VkPhysicalDeviceDescriptorIndexingPropertiesEXT descriptorIndexingProperties{};
     196           0 :     descriptorIndexingProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT;
     197             : 
     198           0 :     VkPhysicalDeviceProperties2 deviesProperties2{};
     199           0 :     deviesProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
     200           0 :     deviesProperties2.pNext = &descriptorIndexingProperties;
     201           0 :     vkGetPhysicalDeviceProperties2(availablePhysicalDevice.device, &deviesProperties2);
     202           0 :     availablePhysicalDevice.properties = deviesProperties2.properties;
     203           0 :     availablePhysicalDevice.descriptorIndexingProperties = descriptorIndexingProperties;
     204             : 
     205           0 :     VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptorIndexingFeatures{};
     206           0 :     descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
     207             : 
     208           0 :     VkPhysicalDeviceFeatures2 deviceFeatures2{};
     209           0 :     deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
     210           0 :     deviceFeatures2.pNext = &descriptorIndexingFeatures;
     211           0 :     vkGetPhysicalDeviceFeatures2(availablePhysicalDevice.device, &deviceFeatures2);
     212           0 :     availablePhysicalDevice.features = deviceFeatures2.features;
     213           0 :     availablePhysicalDevice.descriptorIndexingFeatures = descriptorIndexingFeatures;
     214             : 
     215           0 :     uint32_t queueFamilyCount = 0;
     216           0 :     vkGetPhysicalDeviceQueueFamilyProperties(availablePhysicalDevice.device, &queueFamilyCount, nullptr);
     217           0 :     availablePhysicalDevice.queueFamilies.resize(queueFamilyCount);
     218           0 :     vkGetPhysicalDeviceQueueFamilyProperties(
     219             :         availablePhysicalDevice.device, &queueFamilyCount, availablePhysicalDevice.queueFamilies.data());
     220             : 
     221           0 :     availablePhysicalDevice.graphicsQueueFamilyIndex = availablePhysicalDevice.queueFamilies.size();
     222           0 :     availablePhysicalDevice.presentQueueFamilyIndex = availablePhysicalDevice.queueFamilies.size();
     223           0 :     for (size_t familyIdx = 0; familyIdx < availablePhysicalDevice.queueFamilies.size(); ++familyIdx)
     224             :     {
     225           0 :         const VkQueueFamilyProperties& queueFamily = availablePhysicalDevice.queueFamilies[familyIdx];
     226           0 :         if (surface != VK_NULL_HANDLE)
     227             :         {
     228           0 :             VkBool32 hasOutputToSurfaceSupport = false;
     229           0 :             ENSURE_VK_SUCCESS(vkGetPhysicalDeviceSurfaceSupportKHR(
     230             :                 availablePhysicalDevice.device, familyIdx, surface, &hasOutputToSurfaceSupport));
     231           0 :             availablePhysicalDevice.hasOutputToSurfaceSupport = hasOutputToSurfaceSupport;
     232           0 :             if ((queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) && hasOutputToSurfaceSupport)
     233             :             {
     234           0 :                 availablePhysicalDevice.graphicsQueueFamilyIndex = familyIdx;
     235           0 :                 availablePhysicalDevice.presentQueueFamilyIndex = familyIdx;
     236             :             }
     237             :         }
     238             :     }
     239             : 
     240           0 :     ENSURE_VK_SUCCESS(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
     241             :         availablePhysicalDevice.device, surface, &availablePhysicalDevice.surfaceCapabilities));
     242             : 
     243           0 :     uint32_t surfaceFormatCount = 0;
     244           0 :     ENSURE_VK_SUCCESS(vkGetPhysicalDeviceSurfaceFormatsKHR(
     245             :         availablePhysicalDevice.device, surface, &surfaceFormatCount, nullptr));
     246           0 :     if (surfaceFormatCount > 0)
     247             :     {
     248           0 :         availablePhysicalDevice.surfaceFormats.resize(surfaceFormatCount);
     249           0 :         ENSURE_VK_SUCCESS(vkGetPhysicalDeviceSurfaceFormatsKHR(
     250             :             availablePhysicalDevice.device, surface, &surfaceFormatCount, availablePhysicalDevice.surfaceFormats.data()));
     251             :     }
     252             : 
     253           0 :     uint32_t presentModeCount = 0;
     254           0 :     ENSURE_VK_SUCCESS(vkGetPhysicalDeviceSurfacePresentModesKHR(
     255             :         availablePhysicalDevice.device, surface, &presentModeCount, nullptr));
     256           0 :     if (presentModeCount > 0)
     257             :     {
     258           0 :         availablePhysicalDevice.presentModes.resize(presentModeCount);
     259           0 :         ENSURE_VK_SUCCESS(vkGetPhysicalDeviceSurfacePresentModesKHR(
     260             :             availablePhysicalDevice.device, surface, &presentModeCount, availablePhysicalDevice.presentModes.data()));
     261             :     }
     262             : 
     263           0 :     return availablePhysicalDevice;
     264             : }
     265             : 
     266             : } // anonymous namespace
     267             : 
     268           0 : std::vector<SAvailablePhysicalDevice> GetAvailablePhysicalDevices(
     269             :     VkInstance instance, VkSurfaceKHR surface,
     270             :     const std::vector<const char*>& requiredDeviceExtensions)
     271             : {
     272           0 :     uint32_t physicalDeviceCount = 0;
     273           0 :     ENSURE_VK_SUCCESS(vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr));
     274           0 :     if (physicalDeviceCount == 0)
     275           0 :         return {};
     276             : 
     277           0 :     std::vector<SAvailablePhysicalDevice> availablePhysicalDevices;
     278           0 :     availablePhysicalDevices.reserve(physicalDeviceCount);
     279             : 
     280           0 :     std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
     281           0 :     ENSURE_VK_SUCCESS(vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data()));
     282           0 :     for (uint32_t physicalDeviceIndex = 0; physicalDeviceIndex < physicalDeviceCount; ++physicalDeviceIndex)
     283             :     {
     284           0 :         availablePhysicalDevices.emplace_back(MakeAvailablePhysicalDevice(
     285           0 :             physicalDeviceIndex, physicalDevices[physicalDeviceIndex], surface, requiredDeviceExtensions));
     286             :     }
     287             : 
     288           0 :     return availablePhysicalDevices;
     289             : }
     290             : 
     291           0 : bool IsPhysicalDeviceUnsupported(const SAvailablePhysicalDevice& device)
     292             : {
     293           0 :     if (!device.hasRequiredExtensions)
     294           0 :         return true;
     295             :     // We can't draw something without graphics queue. And currently we don't
     296             :     // support separate queues for graphics and present.
     297           0 :     if (device.graphicsQueueFamilyIndex != device.presentQueueFamilyIndex)
     298           0 :         return true;
     299           0 :     if (device.graphicsQueueFamilyIndex == device.queueFamilies.size())
     300           0 :         return true;
     301           0 :     if (!device.hasOutputToSurfaceSupport)
     302           0 :         return true;
     303           0 :     if (device.properties.limits.maxBoundDescriptorSets < 4)
     304           0 :         return true;
     305             :     // It's guaranteed to have sRGB but we don't support it yet.
     306           0 :     return std::none_of(device.surfaceFormats.begin(), device.surfaceFormats.end(), IsSurfaceFormatSupported);
     307             : }
     308             : 
     309           0 : bool ComparePhysicalDevices(
     310             :     const SAvailablePhysicalDevice& device1,
     311             :     const SAvailablePhysicalDevice& device2)
     312             : {
     313           0 :     const uint32_t deviceTypeScore1 = GetDeviceTypeScore(device1.properties.deviceType);
     314           0 :     const uint32_t deviceTypeScore2 = GetDeviceTypeScore(device2.properties.deviceType);
     315           0 :     if (deviceTypeScore1 != deviceTypeScore2)
     316           0 :         return deviceTypeScore1 > deviceTypeScore2;
     317             :     // We use a total device memory amount to compare. We assume that more memory
     318             :     // means better performance as previous metrics are equal.
     319           0 :     return device1.deviceTotalMemory > device2.deviceTotalMemory;
     320             : }
     321             : 
     322           0 : bool IsSurfaceFormatSupported(
     323             :     const VkSurfaceFormatKHR& surfaceFormat)
     324             : {
     325             :     return
     326           0 :         surfaceFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR &&
     327           0 :         (surfaceFormat.format == VK_FORMAT_R8G8B8A8_UNORM ||
     328           0 :         surfaceFormat.format == VK_FORMAT_B8G8R8A8_UNORM);
     329             : }
     330             : 
     331           0 : void ReportAvailablePhysicalDevice(const SAvailablePhysicalDevice& device,
     332             :     const ScriptRequest& rq, JS::HandleValue settings)
     333             : {
     334           0 :     Script::SetProperty(rq, settings, "name", device.properties.deviceName);
     335           0 :     Script::SetProperty(rq, settings, "version",
     336           0 :         std::to_string(VK_API_VERSION_VARIANT(device.properties.apiVersion)) +
     337           0 :         "." + std::to_string(VK_API_VERSION_MAJOR(device.properties.apiVersion)) +
     338           0 :         "." + std::to_string(VK_API_VERSION_MINOR(device.properties.apiVersion)) +
     339           0 :         "." + std::to_string(VK_API_VERSION_PATCH(device.properties.apiVersion)));
     340           0 :     Script::SetProperty(rq, settings, "apiVersion", device.properties.apiVersion);
     341           0 :     Script::SetProperty(rq, settings, "driverVersion", device.properties.driverVersion);
     342           0 :     Script::SetProperty(rq, settings, "vendorID", device.properties.vendorID);
     343           0 :     Script::SetProperty(rq, settings, "deviceID", device.properties.deviceID);
     344           0 :     Script::SetProperty(rq, settings, "deviceType", static_cast<int32_t>(device.properties.deviceType));
     345           0 :     Script::SetProperty(rq, settings, "index", device.index);
     346             : 
     347           0 :     JS::RootedValue memory(rq.cx);
     348           0 :     Script::CreateObject(rq, &memory);
     349             : 
     350           0 :     JS::RootedValue memoryTypes(rq.cx);
     351           0 :     Script::CreateArray(rq, &memoryTypes, device.memoryProperties.memoryTypeCount);
     352           0 :     for (uint32_t memoryTypeIndex = 0; memoryTypeIndex < device.memoryProperties.memoryTypeCount; ++memoryTypeIndex)
     353             :     {
     354           0 :         const VkMemoryType& type = device.memoryProperties.memoryTypes[memoryTypeIndex];
     355           0 :         JS::RootedValue memoryType(rq.cx);
     356           0 :         Script::CreateObject(rq, &memoryType);
     357           0 :         Script::SetProperty(rq, memoryType, "propertyFlags", static_cast<uint32_t>(type.propertyFlags));
     358           0 :         Script::SetProperty(rq, memoryType, "heapIndex", type.heapIndex);
     359           0 :         Script::SetPropertyInt(rq, memoryTypes, memoryTypeIndex, memoryType);
     360             :     }
     361           0 :     JS::RootedValue memoryHeaps(rq.cx);
     362           0 :     Script::CreateArray(rq, &memoryHeaps, device.memoryProperties.memoryHeapCount);
     363           0 :     for (uint32_t memoryHeapIndex = 0; memoryHeapIndex < device.memoryProperties.memoryHeapCount; ++memoryHeapIndex)
     364             :     {
     365           0 :         const VkMemoryHeap& heap = device.memoryProperties.memoryHeaps[memoryHeapIndex];
     366           0 :         JS::RootedValue memoryHeap(rq.cx);
     367           0 :         Script::CreateObject(rq, &memoryHeap);
     368             :         // We can't serialize uint64_t in JS, so put data in KiB.
     369           0 :         Script::SetProperty(rq, memoryHeap, "size", static_cast<uint32_t>(heap.size / 1024));
     370           0 :         Script::SetProperty(rq, memoryHeap, "flags", static_cast<uint32_t>(heap.flags));
     371           0 :         Script::SetPropertyInt(rq, memoryHeaps, memoryHeapIndex, memoryHeap);
     372             :     }
     373             : 
     374           0 :     Script::SetProperty(rq, memory, "types", memoryTypes);
     375           0 :     Script::SetProperty(rq, memory, "heaps", memoryHeaps);
     376           0 :     Script::SetProperty(rq, settings, "memory", memory);
     377             : 
     378           0 :     JS::RootedValue constants(rq.cx);
     379           0 :     Script::CreateObject(rq, &constants);
     380             : 
     381           0 :     JS::RootedValue limitsConstants(rq.cx);
     382           0 :     Script::CreateObject(rq, &limitsConstants);
     383             : #define REPORT_LIMITS_CONSTANT(NAME) \
     384             :     do \
     385             :     { \
     386             :         const ReportFormatHelper<decltype(device.properties.limits.NAME)> helper{}; \
     387             :         Script::SetProperty(rq, limitsConstants, #NAME, helper(device.properties.limits.NAME)); \
     388             :     } while (0)
     389           0 :     REPORT_LIMITS_CONSTANT(maxImageDimension1D);
     390           0 :     REPORT_LIMITS_CONSTANT(maxImageDimension2D);
     391           0 :     REPORT_LIMITS_CONSTANT(maxImageDimension3D);
     392           0 :     REPORT_LIMITS_CONSTANT(maxImageDimensionCube);
     393           0 :     REPORT_LIMITS_CONSTANT(maxImageArrayLayers);
     394           0 :     REPORT_LIMITS_CONSTANT(maxUniformBufferRange);
     395           0 :     REPORT_LIMITS_CONSTANT(maxStorageBufferRange);
     396           0 :     REPORT_LIMITS_CONSTANT(maxPushConstantsSize);
     397           0 :     REPORT_LIMITS_CONSTANT(maxMemoryAllocationCount);
     398           0 :     REPORT_LIMITS_CONSTANT(maxSamplerAllocationCount);
     399           0 :     REPORT_LIMITS_CONSTANT(bufferImageGranularity);
     400           0 :     REPORT_LIMITS_CONSTANT(maxBoundDescriptorSets);
     401           0 :     REPORT_LIMITS_CONSTANT(maxPerStageDescriptorSamplers);
     402           0 :     REPORT_LIMITS_CONSTANT(maxPerStageDescriptorUniformBuffers);
     403           0 :     REPORT_LIMITS_CONSTANT(maxPerStageDescriptorStorageBuffers);
     404           0 :     REPORT_LIMITS_CONSTANT(maxPerStageDescriptorSampledImages);
     405           0 :     REPORT_LIMITS_CONSTANT(maxPerStageDescriptorStorageImages);
     406           0 :     REPORT_LIMITS_CONSTANT(maxPerStageDescriptorInputAttachments);
     407           0 :     REPORT_LIMITS_CONSTANT(maxPerStageResources);
     408           0 :     REPORT_LIMITS_CONSTANT(maxDescriptorSetSamplers);
     409           0 :     REPORT_LIMITS_CONSTANT(maxDescriptorSetUniformBuffers);
     410           0 :     REPORT_LIMITS_CONSTANT(maxDescriptorSetUniformBuffersDynamic);
     411           0 :     REPORT_LIMITS_CONSTANT(maxDescriptorSetStorageBuffers);
     412           0 :     REPORT_LIMITS_CONSTANT(maxDescriptorSetStorageBuffersDynamic);
     413           0 :     REPORT_LIMITS_CONSTANT(maxDescriptorSetSampledImages);
     414           0 :     REPORT_LIMITS_CONSTANT(maxDescriptorSetStorageImages);
     415           0 :     REPORT_LIMITS_CONSTANT(maxDescriptorSetInputAttachments);
     416           0 :     REPORT_LIMITS_CONSTANT(maxVertexInputAttributes);
     417           0 :     REPORT_LIMITS_CONSTANT(maxVertexInputBindings);
     418           0 :     REPORT_LIMITS_CONSTANT(maxVertexInputAttributeOffset);
     419           0 :     REPORT_LIMITS_CONSTANT(maxVertexInputBindingStride);
     420           0 :     REPORT_LIMITS_CONSTANT(maxComputeSharedMemorySize);
     421           0 :     REPORT_LIMITS_CONSTANT(maxComputeWorkGroupCount);
     422           0 :     REPORT_LIMITS_CONSTANT(maxComputeWorkGroupInvocations);
     423           0 :     REPORT_LIMITS_CONSTANT(maxComputeWorkGroupSize);
     424           0 :     REPORT_LIMITS_CONSTANT(maxDrawIndexedIndexValue);
     425           0 :     REPORT_LIMITS_CONSTANT(maxSamplerLodBias);
     426           0 :     REPORT_LIMITS_CONSTANT(maxSamplerAnisotropy);
     427           0 :     REPORT_LIMITS_CONSTANT(minMemoryMapAlignment);
     428           0 :     REPORT_LIMITS_CONSTANT(minTexelBufferOffsetAlignment);
     429           0 :     REPORT_LIMITS_CONSTANT(minUniformBufferOffsetAlignment);
     430           0 :     REPORT_LIMITS_CONSTANT(minStorageBufferOffsetAlignment);
     431           0 :     REPORT_LIMITS_CONSTANT(maxFramebufferWidth);
     432           0 :     REPORT_LIMITS_CONSTANT(maxFramebufferHeight);
     433           0 :     REPORT_LIMITS_CONSTANT(maxFramebufferLayers);
     434           0 :     REPORT_LIMITS_CONSTANT(framebufferColorSampleCounts);
     435           0 :     REPORT_LIMITS_CONSTANT(framebufferDepthSampleCounts);
     436           0 :     REPORT_LIMITS_CONSTANT(framebufferStencilSampleCounts);
     437           0 :     REPORT_LIMITS_CONSTANT(framebufferNoAttachmentsSampleCounts);
     438           0 :     REPORT_LIMITS_CONSTANT(maxColorAttachments);
     439           0 :     REPORT_LIMITS_CONSTANT(sampledImageColorSampleCounts);
     440           0 :     REPORT_LIMITS_CONSTANT(sampledImageDepthSampleCounts);
     441           0 :     REPORT_LIMITS_CONSTANT(sampledImageStencilSampleCounts);
     442           0 :     REPORT_LIMITS_CONSTANT(storageImageSampleCounts);
     443           0 :     REPORT_LIMITS_CONSTANT(optimalBufferCopyOffsetAlignment);
     444           0 :     REPORT_LIMITS_CONSTANT(optimalBufferCopyRowPitchAlignment);
     445             : #undef REPORT_LIMITS_CONSTANT
     446           0 :     Script::SetProperty(rq, constants, "limits", limitsConstants);
     447             : 
     448           0 :     JS::RootedValue descriptorIndexingConstants(rq.cx);
     449           0 :     Script::CreateObject(rq, &descriptorIndexingConstants);
     450             : #define REPORT_DESCRIPTOR_INDEXING_CONSTANT(NAME) \
     451             :     do \
     452             :     { \
     453             :         const ReportFormatHelper<decltype(device.descriptorIndexingProperties.NAME)> helper{}; \
     454             :         Script::SetProperty(rq, descriptorIndexingConstants, #NAME, helper(device.descriptorIndexingProperties.NAME)); \
     455             :     } while (0)
     456           0 :     REPORT_DESCRIPTOR_INDEXING_CONSTANT(maxUpdateAfterBindDescriptorsInAllPools);
     457           0 :     REPORT_DESCRIPTOR_INDEXING_CONSTANT(shaderSampledImageArrayNonUniformIndexingNative);
     458           0 :     REPORT_DESCRIPTOR_INDEXING_CONSTANT(maxPerStageDescriptorUpdateAfterBindSamplers);
     459           0 :     REPORT_DESCRIPTOR_INDEXING_CONSTANT(maxPerStageDescriptorUpdateAfterBindSampledImages);
     460           0 :     REPORT_DESCRIPTOR_INDEXING_CONSTANT(maxPerStageDescriptorUpdateAfterBindUniformBuffers);
     461           0 :     REPORT_DESCRIPTOR_INDEXING_CONSTANT(maxPerStageUpdateAfterBindResources);
     462           0 :     REPORT_DESCRIPTOR_INDEXING_CONSTANT(maxDescriptorSetUpdateAfterBindSamplers);
     463           0 :     REPORT_DESCRIPTOR_INDEXING_CONSTANT(maxDescriptorSetUpdateAfterBindSampledImages);
     464           0 :     REPORT_DESCRIPTOR_INDEXING_CONSTANT(maxDescriptorSetUpdateAfterBindUniformBuffers);
     465           0 :     REPORT_DESCRIPTOR_INDEXING_CONSTANT(maxDescriptorSetUpdateAfterBindUniformBuffersDynamic);
     466             : #undef REPORT_DESCRIPTOR_INDEXING_CONSTANT
     467           0 :     Script::SetProperty(rq, constants, "descriptor_indexing", descriptorIndexingConstants);
     468             : 
     469           0 :     Script::SetProperty(rq, settings, "constants", constants);
     470             : 
     471           0 :     JS::RootedValue features(rq.cx);
     472           0 :     Script::CreateObject(rq, &features);
     473             : #define REPORT_FEATURE(NAME) \
     474             :     Script::SetProperty(rq, features, #NAME, static_cast<bool>(device.features.NAME));
     475           0 :     REPORT_FEATURE(imageCubeArray);
     476           0 :     REPORT_FEATURE(geometryShader);
     477           0 :     REPORT_FEATURE(tessellationShader);
     478           0 :     REPORT_FEATURE(logicOp);
     479           0 :     REPORT_FEATURE(multiDrawIndirect);
     480           0 :     REPORT_FEATURE(depthClamp);
     481           0 :     REPORT_FEATURE(depthBiasClamp);
     482           0 :     REPORT_FEATURE(samplerAnisotropy);
     483           0 :     REPORT_FEATURE(textureCompressionETC2);
     484           0 :     REPORT_FEATURE(textureCompressionASTC_LDR);
     485           0 :     REPORT_FEATURE(textureCompressionBC);
     486           0 :     REPORT_FEATURE(pipelineStatisticsQuery);
     487             : #undef REPORT_FEATURE
     488             : 
     489             : #define REPORT_DESCRIPTOR_INDEXING_FEATURE(NAME) \
     490             :     Script::SetProperty(rq, features, #NAME, static_cast<bool>(device.descriptorIndexingFeatures.NAME));
     491           0 :     REPORT_DESCRIPTOR_INDEXING_FEATURE(shaderSampledImageArrayNonUniformIndexing);
     492           0 :     REPORT_DESCRIPTOR_INDEXING_FEATURE(descriptorBindingUniformBufferUpdateAfterBind);
     493           0 :     REPORT_DESCRIPTOR_INDEXING_FEATURE(descriptorBindingSampledImageUpdateAfterBind);
     494           0 :     REPORT_DESCRIPTOR_INDEXING_FEATURE(descriptorBindingPartiallyBound);
     495           0 :     REPORT_DESCRIPTOR_INDEXING_FEATURE(descriptorBindingUpdateUnusedWhilePending);
     496           0 :     REPORT_DESCRIPTOR_INDEXING_FEATURE(descriptorBindingPartiallyBound);
     497           0 :     REPORT_DESCRIPTOR_INDEXING_FEATURE(descriptorBindingVariableDescriptorCount);
     498           0 :     REPORT_DESCRIPTOR_INDEXING_FEATURE(runtimeDescriptorArray);
     499             : #undef REPORT_DESCRIPTOR_INDEXING_FEATURE
     500             : 
     501           0 :     Script::SetProperty(rq, settings, "features", features);
     502             : 
     503           0 :     JS::RootedValue presentModes(rq.cx);
     504           0 :     Script::CreateArray(rq, &presentModes, device.presentModes.size());
     505           0 :     for (size_t index = 0; index < device.presentModes.size(); ++index)
     506             :     {
     507           0 :         Script::SetPropertyInt(
     508           0 :             rq, presentModes, index, static_cast<uint32_t>(device.presentModes[index]));
     509             :     }
     510           0 :     Script::SetProperty(rq, settings, "present_modes", presentModes);
     511             : 
     512           0 :     JS::RootedValue surfaceFormats(rq.cx);
     513           0 :     Script::CreateArray(rq, &surfaceFormats, device.surfaceFormats.size());
     514           0 :     for (size_t index = 0; index < device.surfaceFormats.size(); ++index)
     515             :     {
     516           0 :         JS::RootedValue surfaceFormat(rq.cx);
     517           0 :         Script::CreateObject(rq, &surfaceFormat);
     518           0 :         Script::SetProperty(
     519           0 :             rq, surfaceFormat, "format", static_cast<uint32_t>(device.surfaceFormats[index].format));
     520           0 :         Script::SetProperty(
     521           0 :             rq, surfaceFormat, "color_space", static_cast<uint32_t>(device.surfaceFormats[index].colorSpace));
     522           0 :         Script::SetPropertyInt(rq, surfaceFormats, index, surfaceFormat);
     523             :     }
     524           0 :     Script::SetProperty(rq, settings, "surface_formats", surfaceFormats);
     525             : 
     526           0 :     JS::RootedValue surfaceCapabilities(rq.cx);
     527           0 :     Script::CreateObject(rq, &surfaceCapabilities);
     528             : #define REPORT_SURFACE_CAPABILITIES_CONSTANT(NAME) \
     529             :     do \
     530             :     { \
     531             :         const ReportFormatHelper<decltype(device.surfaceCapabilities.NAME)> helper{}; \
     532             :         Script::SetProperty(rq, surfaceCapabilities, #NAME, helper(device.surfaceCapabilities.NAME)); \
     533             :     } while (0)
     534           0 :     REPORT_SURFACE_CAPABILITIES_CONSTANT(minImageCount);
     535           0 :     REPORT_SURFACE_CAPABILITIES_CONSTANT(maxImageCount);
     536           0 :     REPORT_SURFACE_CAPABILITIES_CONSTANT(maxImageArrayLayers);
     537           0 :     REPORT_SURFACE_CAPABILITIES_CONSTANT(supportedTransforms);
     538           0 :     REPORT_SURFACE_CAPABILITIES_CONSTANT(supportedCompositeAlpha);
     539           0 :     REPORT_SURFACE_CAPABILITIES_CONSTANT(supportedUsageFlags);
     540             : #undef REPORT_SURFACE_CAPABILITIES_CONSTANT
     541           0 :     Script::SetProperty(rq, settings, "surface_capabilities", surfaceCapabilities);
     542           0 : }
     543             : 
     544             : } // namespace Vulkan
     545             : 
     546             : } // namespace Backend
     547             : 
     548           3 : } // namespace Renderer

Generated by: LCOV version 1.13