• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 // @lint-ignore-every CLANGTIDY clang-diagnostic-missing-field-initializers
10 
11 #include <executorch/backends/vulkan/runtime/vk_api/Device.h>
12 
13 #include <executorch/backends/vulkan/runtime/vk_api/Exception.h>
14 
15 #include <bitset>
16 #include <cstring>
17 
18 namespace vkcompute {
19 namespace vkapi {
20 
PhysicalDevice(VkPhysicalDevice physical_device_handle)21 PhysicalDevice::PhysicalDevice(VkPhysicalDevice physical_device_handle)
22     : handle(physical_device_handle),
23       properties{},
24       memory_properties{},
25 #ifdef VK_KHR_16bit_storage
26       shader_16bit_storage{
27           VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES},
28 #endif /* VK_KHR_16bit_storage */
29 #ifdef VK_KHR_8bit_storage
30       shader_8bit_storage{
31           VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES},
32 #endif /* VK_KHR_8bit_storage */
33 #ifdef VK_KHR_shader_float16_int8
34       shader_float16_int8_types{
35           VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR},
36 #endif /* VK_KHR_shader_float16_int8 */
37       extension_features{nullptr},
38       queue_families{},
39       num_compute_queues(0),
40       supports_int16_shader_types(false),
41       has_unified_memory(false),
42       has_timestamps(properties.limits.timestampComputeAndGraphics),
43       timestamp_period(properties.limits.timestampPeriod) {
44   // Extract physical device properties
45   vkGetPhysicalDeviceProperties(handle, &properties);
46   vkGetPhysicalDeviceMemoryProperties(handle, &memory_properties);
47 
48   VkPhysicalDeviceFeatures2 features2{
49       VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
50 
51   // Create linked list to query availability of extensions
52 
53 #ifdef VK_KHR_16bit_storage
54   extension_features = &shader_16bit_storage;
55   features2.pNext = &shader_16bit_storage;
56 #elif defined(VK_KHR_8bit_storage)
57   extension_features = &shader_8bit_storage;
58   features2.pNext = &shader_8bit_storage;
59 #elif defined(VK_KHR_shader_float16_int8)
60   extension_features = &shader_float16_int8_types;
61   features2.pNext = &shader_float16_int8_types;
62 #endif /* VK_KHR_16bit_storage */
63 
64 #if defined(VK_KHR_16bit_storage) && defined(VK_KHR_8bit_storage)
65   shader_16bit_storage.pNext = &shader_8bit_storage;
66 #elif defined(VK_KHR_16bit_storage) && defined(VK_KHR_shader_float16_int8)
67   shader_16bit_storage.pNext = &shader_float16_int8_types;
68 #elif defined(VK_KHR_16bit_storage)
69   shader_16bit_storage.pNext = nullptr;
70 #endif
71 
72 #if defined(VK_KHR_8bit_storage) && defined(VK_KHR_shader_float16_int8)
73   shader_8bit_storage.pNext = &shader_float16_int8_types;
74 #elif defined(VK_KHR_8bit_storage)
75   shader_8bit_storage.pNext = nullptr;
76 #endif
77 
78 #ifdef VK_KHR_shader_float16_int8
79   shader_float16_int8_types.pNext = nullptr;
80 #endif
81 
82   vkGetPhysicalDeviceFeatures2(handle, &features2);
83 
84   if (features2.features.shaderInt16 == VK_TRUE) {
85     supports_int16_shader_types = true;
86   }
87 
88   // Check if there are any memory types have both the HOST_VISIBLE and the
89   // DEVICE_LOCAL property flags
90   const VkMemoryPropertyFlags unified_memory_flags =
91       VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
92   for (size_t i = 0; i < memory_properties.memoryTypeCount; ++i) {
93     if (memory_properties.memoryTypes[i].propertyFlags | unified_memory_flags) {
94       has_unified_memory = true;
95       break;
96     }
97   }
98 
99   uint32_t queue_family_count = 0;
100   vkGetPhysicalDeviceQueueFamilyProperties(
101       handle, &queue_family_count, nullptr);
102 
103   queue_families.resize(queue_family_count);
104   vkGetPhysicalDeviceQueueFamilyProperties(
105       handle, &queue_family_count, queue_families.data());
106 
107   // Find the total number of compute queues
108   for (const VkQueueFamilyProperties& p : queue_families) {
109     // Check if this family has compute capability
110     if (p.queueFlags & VK_QUEUE_COMPUTE_BIT) {
111       num_compute_queues += p.queueCount;
112     }
113   }
114 }
115 
116 //
117 // DeviceHandle
118 //
119 
DeviceHandle(VkDevice device)120 DeviceHandle::DeviceHandle(VkDevice device) : handle(device) {}
121 
~DeviceHandle()122 DeviceHandle::~DeviceHandle() {
123   if (handle == VK_NULL_HANDLE) {
124     return;
125   }
126   vkDestroyDevice(handle, nullptr);
127 }
128 
129 //
130 // Utils
131 //
132 
find_requested_device_extensions(VkPhysicalDevice physical_device,std::vector<const char * > & enabled_extensions,const std::vector<const char * > & requested_extensions)133 void find_requested_device_extensions(
134     VkPhysicalDevice physical_device,
135     std::vector<const char*>& enabled_extensions,
136     const std::vector<const char*>& requested_extensions) {
137   uint32_t device_extension_properties_count = 0;
138   VK_CHECK(vkEnumerateDeviceExtensionProperties(
139       physical_device, nullptr, &device_extension_properties_count, nullptr));
140   std::vector<VkExtensionProperties> device_extension_properties(
141       device_extension_properties_count);
142   VK_CHECK(vkEnumerateDeviceExtensionProperties(
143       physical_device,
144       nullptr,
145       &device_extension_properties_count,
146       device_extension_properties.data()));
147 
148   std::vector<const char*> enabled_device_extensions;
149 
150   for (const auto& requested_extension : requested_extensions) {
151     for (const auto& extension : device_extension_properties) {
152       if (strcmp(requested_extension, extension.extensionName) == 0) {
153         enabled_extensions.push_back(requested_extension);
154         break;
155       }
156     }
157   }
158 }
159 
get_device_type_str(const VkPhysicalDeviceType type)160 std::string get_device_type_str(const VkPhysicalDeviceType type) {
161   switch (type) {
162     case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
163       return "INTEGRATED_GPU";
164     case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
165       return "DISCRETE_GPU";
166     case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
167       return "VIRTUAL_GPU";
168     case VK_PHYSICAL_DEVICE_TYPE_CPU:
169       return "CPU";
170     default:
171       return "UNKNOWN";
172   }
173 }
174 
get_memory_properties_str(const VkMemoryPropertyFlags flags)175 std::string get_memory_properties_str(const VkMemoryPropertyFlags flags) {
176   std::bitset<10> values(flags);
177   std::stringstream ss("|");
178   if (values[0]) {
179     ss << " DEVICE_LOCAL |";
180   }
181   if (values[1]) {
182     ss << " HOST_VISIBLE |";
183   }
184   if (values[2]) {
185     ss << " HOST_COHERENT |";
186   }
187   if (values[3]) {
188     ss << " HOST_CACHED |";
189   }
190   if (values[4]) {
191     ss << " LAZILY_ALLOCATED |";
192   }
193 
194   return ss.str();
195 }
196 
get_queue_family_properties_str(const VkQueueFlags flags)197 std::string get_queue_family_properties_str(const VkQueueFlags flags) {
198   std::bitset<10> values(flags);
199   std::stringstream ss("|");
200   if (values[0]) {
201     ss << " GRAPHICS |";
202   }
203   if (values[1]) {
204     ss << " COMPUTE |";
205   }
206   if (values[2]) {
207     ss << " TRANSFER |";
208   }
209 
210   return ss.str();
211 }
212 
213 } // namespace vkapi
214 } // namespace vkcompute
215