Halide  19.0.0
Halide compiler and libraries
vulkan_context.h
Go to the documentation of this file.
1 #ifndef HALIDE_RUNTIME_VULKAN_CONTEXT_H
2 #define HALIDE_RUNTIME_VULKAN_CONTEXT_H
3 
4 #include "printer.h"
5 #include "runtime_internal.h"
6 #include "scoped_spin_lock.h"
7 
8 #include "vulkan_extensions.h"
9 #include "vulkan_internal.h"
10 #include "vulkan_memory.h"
11 
12 // --------------------------------------------------------------------------
13 
14 namespace Halide {
15 namespace Runtime {
16 namespace Internal {
17 namespace Vulkan {
18 
19 // --------------------------------------------------------------------------
20 
21 // Vulkan Memory allocator for host-device allocations
22 halide_vulkan_memory_allocator *WEAK cached_allocator = nullptr;
23 
24 // Cached instance related handles for device resources
25 VkInstance WEAK cached_instance = nullptr;
26 VkDevice WEAK cached_device = nullptr;
27 VkCommandPool WEAK cached_command_pool = VkInvalidCommandPool;
28 VkQueue WEAK cached_queue = nullptr;
29 VkPhysicalDevice WEAK cached_physical_device = nullptr;
31 
32 // A Vulkan context/queue/synchronization lock defined in this module with weak linkage
34 
35 // --------------------------------------------------------------------------
36 
37 // Helper object to acquire and release the Vulkan context.
39  void *user_context;
40 
41 public:
43  VkInstance instance = nullptr;
44  VkDevice device = nullptr;
45  VkCommandPool command_pool = VkInvalidCommandPool;
46  VkPhysicalDevice physical_device = nullptr;
47  VkQueue queue = nullptr;
48  uint32_t queue_family_index = 0; // used for operations requiring queue family
50 
51  HALIDE_ALWAYS_INLINE explicit VulkanContext(void *user_context)
52  : user_context(user_context) {
53 
54  int result = halide_vulkan_acquire_context(user_context,
55  reinterpret_cast<halide_vulkan_memory_allocator **>(&allocator),
57  if (result != halide_error_code_success) {
60  }
61  halide_debug_assert(user_context, allocator != nullptr);
62  halide_debug_assert(user_context, instance != nullptr);
63  halide_debug_assert(user_context, device != nullptr);
64  halide_debug_assert(user_context, command_pool != 0);
65  halide_debug_assert(user_context, queue != nullptr);
66  halide_debug_assert(user_context, physical_device != nullptr);
67  }
68 
71  }
72 
73  // For now, this is always nullptr
75  return nullptr;
76  }
77 };
78 
79 // --------------------------------------------------------------------------
80 
81 namespace {
82 
83 int vk_find_compute_capability(void *user_context, int *major, int *minor) {
84  debug(user_context) << " vk_find_compute_capability (user_context: " << user_context << ")\n";
85 
86  VkInstance instance = nullptr;
87  VkDevice device = nullptr;
88  VkPhysicalDevice physical_device = nullptr;
89  uint32_t queue_family_index = 0;
90 
91  if (!lib_vulkan) {
92  // If the Vulkan loader can't be found, we want to return compute
93  // capability of (0, 0) ... this is not considered an error. So we
94  // should be very careful about looking for Vulkan without tripping
95  // any errors in the rest of this runtime.
96  void *sym = halide_vulkan_get_symbol(user_context, "vkCreateInstance");
97  if (!sym) {
98  *major = *minor = 0;
100  }
101  }
102 
103  if (vkCreateInstance == nullptr) {
104  vk_load_vulkan_loader_functions(user_context);
105  if (vkCreateInstance == nullptr) {
106  debug(user_context) << " no valid vulkan loader library was found ...\n";
107  *major = *minor = 0;
109  }
110  }
111 
112  StringTable requested_layers;
113  vk_get_requested_layers(user_context, requested_layers);
114 
115  // Attempt to find a suitable instance that can support the requested layers
116  const VkAllocationCallbacks *alloc_callbacks = halide_vulkan_get_allocation_callbacks(user_context);
117  int status = vk_create_instance(user_context, requested_layers, &instance, alloc_callbacks);
118  if (status != halide_error_code_success) {
119  debug(user_context) << " no valid vulkan runtime was found ...\n";
120  *major = *minor = 0;
121  return 0;
122  }
123 
124  if (vkCreateDevice == nullptr) {
125  vk_load_vulkan_functions(user_context, instance);
126  if (vkCreateDevice == nullptr) {
127  debug(user_context) << " no valid vulkan runtime was found ...\n";
128  *major = *minor = 0;
130  }
131  }
132 
133  status = vk_select_device_for_context(user_context, &instance, &device, &physical_device, &queue_family_index);
134  if (status != halide_error_code_success) {
135  debug(user_context) << " no valid vulkan device was found ...\n";
136  *major = *minor = 0;
137  return 0;
138  }
139 
140  VkPhysicalDeviceProperties device_properties = {0};
141  debug(user_context) << " querying for device properties ...\n";
142  vkGetPhysicalDeviceProperties(physical_device, &device_properties);
143  *major = VK_API_VERSION_MAJOR(device_properties.apiVersion);
144  *minor = VK_API_VERSION_MINOR(device_properties.apiVersion);
145  debug(user_context) << " found device compute capability v" << *major << "." << *minor << " ...\n";
146 
147  vk_destroy_instance(user_context, instance, alloc_callbacks);
148  return 0;
149 }
150 
151 // Initializes the instance (used by the default vk_create_context)
152 int vk_create_instance(void *user_context, const StringTable &requested_layers, VkInstance *instance, const VkAllocationCallbacks *alloc_callbacks) {
153  debug(user_context) << " vk_create_instance (user_context: " << user_context << ")\n";
154 
155  StringTable required_instance_extensions;
156  vk_get_required_instance_extensions(user_context, required_instance_extensions);
157 
158  StringTable supported_instance_extensions;
159  vk_get_supported_instance_extensions(user_context, supported_instance_extensions);
160 
161  bool valid_instance = vk_validate_required_extension_support(user_context, required_instance_extensions, supported_instance_extensions);
162  halide_abort_if_false(user_context, valid_instance);
163 
164  debug(user_context) << " found " << (uint32_t)required_instance_extensions.size() << " required extensions for instance!\n";
165  for (int n = 0; n < (int)required_instance_extensions.size(); ++n) {
166  debug(user_context) << " extension: " << required_instance_extensions[n] << "\n";
167  }
168 
169  // If we're running under Molten VK, we must enable the portability extension and create flags
170  // to allow non-physical devices that are emulated to appear in the device list.
171  uint32_t create_flags = 0;
172  if (supported_instance_extensions.contains("VK_KHR_portability_enumeration") &&
173  supported_instance_extensions.contains("VK_MVK_macos_surface")) {
175  required_instance_extensions.append(user_context, "VK_KHR_portability_enumeration");
176  }
177 
178  VkApplicationInfo app_info = {
179  VK_STRUCTURE_TYPE_APPLICATION_INFO, // struct type
180  nullptr, // Next
181  "Runtime", // application name
182  VK_MAKE_API_VERSION(0, 1, 0, 0), // app version
183  "Halide", // engine name
185  VK_API_VERSION_1_3}; // FIXME: only use the minimum capability necessary
186 
187  VkInstanceCreateInfo create_info = {
189  nullptr, // Next
190  create_flags, // Flags
191  &app_info, // ApplicationInfo
192  (uint32_t)requested_layers.size(), requested_layers.data(), // Layers
193  (uint32_t)required_instance_extensions.size(), required_instance_extensions.data() // Extensions
194  };
195 
196  VkResult result = vkCreateInstance(&create_info, alloc_callbacks, instance);
197  if (result != VK_SUCCESS) {
198  debug(user_context) << "Vulkan: vkCreateInstance failed with return code: " << vk_get_error_name(result) << "\n";
200  }
201 
203 }
204 
205 int vk_destroy_instance(void *user_context, VkInstance instance, const VkAllocationCallbacks *alloc_callbacks) {
206  debug(user_context) << " vk_destroy_instance (user_context: " << user_context << ")\n";
207  vkDestroyInstance(instance, alloc_callbacks);
209 }
210 
211 int vk_select_device_for_context(void *user_context,
212  VkInstance *instance, VkDevice *device,
213  VkPhysicalDevice *physical_device,
214  uint32_t *queue_family_index) {
215  // query for the number of physical devices available in this instance
216  uint32_t device_count = 0;
217  VkResult result = vkEnumeratePhysicalDevices(*instance, &device_count, nullptr);
218  if ((result != VK_SUCCESS) && (result != VK_INCOMPLETE)) {
219  debug(user_context) << "Vulkan: vkEnumeratePhysicalDevices failed with return code: " << vk_get_error_name(result) << "\n";
221  }
222  if (device_count == 0) {
223  debug(user_context) << "Vulkan: No devices found.\n";
225  }
226 
227  // allocate enough storage for the physical device query results
228  BlockStorage::Config device_query_storage_config;
229  device_query_storage_config.entry_size = sizeof(VkPhysicalDevice);
230  BlockStorage device_query_storage(user_context, device_query_storage_config);
231  device_query_storage.resize(user_context, device_count);
232 
233  VkPhysicalDevice chosen_device = nullptr;
234  VkPhysicalDevice *avail_devices = (VkPhysicalDevice *)(device_query_storage.data());
235  if (avail_devices == nullptr) {
236  debug(user_context) << "Vulkan: Out of system memory!\n";
238  }
239  result = vkEnumeratePhysicalDevices(*instance, &device_count, avail_devices);
240  if ((result != VK_SUCCESS) && (result != VK_INCOMPLETE)) {
241  debug(user_context) << "Vulkan: vkEnumeratePhysicalDevices failed with return code: " << vk_get_error_name(result) << "\n";
243  }
244 
245  // get the configurable device type to search for (e.g. 'cpu', 'gpu', 'integrated-gpu', 'discrete-gpu', ...)
246  const char *dev_type = halide_vulkan_get_device_type(user_context);
247 
248  // try to find a matching device that supports compute.
249  uint32_t queue_family = 0;
250  for (uint32_t i = 0; (chosen_device == nullptr) && (i < device_count); i++) {
251  VkPhysicalDeviceProperties properties;
252  vkGetPhysicalDeviceProperties(avail_devices[i], &properties);
253  debug(user_context) << "Vulkan: Checking device #" << i << "='" << properties.deviceName << "'\n";
254 
255  int matching_device = 0;
256  if ((dev_type != nullptr) && (*dev_type != '\0')) {
257  if (strstr(dev_type, "cpu") && (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)) {
258  matching_device = 1;
259  } else if (strstr(dev_type, "integrated-gpu") && ((properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU))) {
260  matching_device = 1;
261  } else if (strstr(dev_type, "discrete-gpu") && ((properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU))) {
262  matching_device = 1;
263  } else if (strstr(dev_type, "virtual-gpu") && (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU)) {
264  matching_device = 1;
265  } else if (strstr(dev_type, "gpu") && ((properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) || (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU))) {
266  matching_device = 1;
267  }
268  } else {
269  // use a non-virtual gpu device by default
272  matching_device = 1;
273  }
274  }
275 
276  if (matching_device) {
277  // get the number of supported queues for this physical device
278  uint32_t queue_properties_count = 0;
279  vkGetPhysicalDeviceQueueFamilyProperties(avail_devices[i], &queue_properties_count, nullptr);
280  if (queue_properties_count < 1) {
281  continue;
282  }
283 
284  // allocate enough storage for the queue properties query results
285  BlockStorage::Config queue_properties_storage_config;
286  queue_properties_storage_config.entry_size = sizeof(VkPhysicalDevice);
287  BlockStorage queue_properties_storage(user_context, queue_properties_storage_config);
288  queue_properties_storage.resize(user_context, queue_properties_count);
289 
290  VkQueueFamilyProperties *queue_properties = (VkQueueFamilyProperties *)(queue_properties_storage.data());
291  vkGetPhysicalDeviceQueueFamilyProperties(avail_devices[i], &queue_properties_count, queue_properties);
292  for (uint32_t j = 0; (chosen_device == nullptr) && (j < queue_properties_count); j++) {
293  if (queue_properties[j].queueCount > 0 &&
294  queue_properties[j].queueFlags & VK_QUEUE_COMPUTE_BIT) {
295  chosen_device = avail_devices[i];
296  queue_family = j;
297 
298  debug(user_context) << "Vulkan: Found matching compute device '" << properties.deviceName << "'\n";
299  }
300  }
301  }
302  }
303  // If nothing, just try the first one for now.
304  if (chosen_device == nullptr) {
305  queue_family = 0;
306  chosen_device = avail_devices[0];
307  VkPhysicalDeviceProperties properties;
308  vkGetPhysicalDeviceProperties(chosen_device, &properties);
309  debug(user_context) << "Vulkan: Defaulting to first compute device '" << properties.deviceName << "'\n";
310  }
311 
312  *queue_family_index = queue_family;
313  *physical_device = chosen_device;
315 }
316 
317 int vk_create_device(void *user_context, const StringTable &requested_layers, VkInstance *instance, VkDevice *device, VkQueue *queue,
318  VkPhysicalDevice *physical_device, uint32_t *queue_family_index, const VkAllocationCallbacks *alloc_callbacks) {
319  debug(user_context) << " vk_create_device (user_context=" << user_context << ")\n";
320 
321  debug(user_context) << " checking for required device extensions ...\n";
322  StringTable required_device_extensions;
323  vk_get_required_device_extensions(user_context, required_device_extensions);
324 
325  debug(user_context) << " checking for optional device extensions ...\n";
326  StringTable optional_device_extensions;
327  vk_get_optional_device_extensions(user_context, optional_device_extensions);
328 
329  debug(user_context) << " validating supported device extensions ...\n";
330  StringTable supported_device_extensions;
331  vk_get_supported_device_extensions(user_context, *physical_device, supported_device_extensions);
332 
333  bool valid_device = vk_validate_required_extension_support(user_context, required_device_extensions, supported_device_extensions);
334  if (!valid_device) {
335  debug(user_context) << "Vulkan: Unable to validate required extension support!\n";
337  }
338 
339  debug(user_context) << " found " << (uint32_t)required_device_extensions.size() << " required extensions for device!\n";
340  for (uint32_t n = 0; n < required_device_extensions.size(); ++n) {
341  debug(user_context) << " required extension: " << required_device_extensions[n] << "\n";
342  }
343 
344  // enable all available optional extensions
345  debug(user_context) << " checking for " << (uint32_t)optional_device_extensions.size() << " optional extensions for device ...\n";
346  for (uint32_t n = 0; n < optional_device_extensions.size(); ++n) {
347  if (supported_device_extensions.contains(optional_device_extensions[n])) {
348  debug(user_context) << " optional extension: " << optional_device_extensions[n] << "\n";
349  required_device_extensions.append(user_context, optional_device_extensions[n]);
350  }
351  }
352 
353  float queue_priority = 1.0f;
354  VkDeviceQueueCreateInfo device_queue_create_info = {
356  nullptr, // Next
357  0, // Flags
358  *queue_family_index,
359  1,
360  &queue_priority,
361  };
362 
363  // Get the API version to determine what device features are valid to search for
364  VkPhysicalDeviceProperties device_properties = {0};
365  debug(user_context) << " querying for device properties ...\n";
366  vkGetPhysicalDeviceProperties(*physical_device, &device_properties);
367  uint32_t major_version = VK_API_VERSION_MAJOR(device_properties.apiVersion);
368  uint32_t minor_version = VK_API_VERSION_MINOR(device_properties.apiVersion);
369  bool has_capability_v11 = (major_version >= 1) && (minor_version >= 1); // supports >= v1.1
370  bool has_capability_v12 = (major_version >= 1) && (minor_version >= 2); // supports >= v1.2
371  debug(user_context) << " found device compute capability v" << major_version << "." << minor_version << " ...\n";
372 
373  // Get the device features so that all supported features are enabled when device is created
374  VkPhysicalDeviceFeatures device_features = {};
375  void *extended_features_ptr = nullptr;
376  void *standard_features_ptr = nullptr;
377 
378  debug(user_context) << " querying for device features...\n";
379  vkGetPhysicalDeviceFeatures(*physical_device, &device_features);
380  debug(user_context) << " shader float64 support: " << (device_features.shaderFloat64 ? "true" : "false") << "...\n";
381  debug(user_context) << " shader int64 support: " << (device_features.shaderInt64 ? "true" : "false") << "...\n";
382  debug(user_context) << " shader int16 support: " << (device_features.shaderInt16 ? "true" : "false") << "...\n";
383 
384  // assemble the chain of features to query, but only add the ones that exist in the API version
385 
386  // note: requires v1.2+
388  nullptr, VK_FALSE, VK_FALSE};
389 
390  // note: requires v1.2+
392  &shader_f16_i8_ext, VK_FALSE, VK_FALSE, VK_FALSE};
393 
394  // note: requires v1.1+
396  (has_capability_v12 ? &storage_8bit_ext : nullptr),
398 
399  VkPhysicalDeviceFeatures2KHR device_features_ext = {
401  &storage_16bit_ext, device_features};
402 
403  // Look for extended device feature query method (KHR was removed when it was adopted into v1.1+)
407  }
408 
409  // If the instance runtime supports querying extended device features, request them
410  if (vkGetPhysicalDeviceFeatures2KHR && has_capability_v11) {
411 
412  debug(user_context) << " querying for extended device features...\n";
413  vkGetPhysicalDeviceFeatures2KHR(*physical_device, &device_features_ext);
414  debug(user_context) << " shader int8 support: " << (shader_f16_i8_ext.shaderInt8 ? "true" : "false") << "...\n";
415  debug(user_context) << " shader float16 support: " << (shader_f16_i8_ext.shaderFloat16 ? "true" : "false") << "...\n";
416  if (has_capability_v12) {
417  debug(user_context) << " storage buffer 8bit access support: " << (storage_8bit_ext.storageBuffer8BitAccess ? "true" : "false") << "...\n";
418  debug(user_context) << " storage buffer 16bit access support: " << (storage_16bit_ext.storageBuffer16BitAccess ? "true" : "false") << "...\n";
419  }
420  extended_features_ptr = (void *)(&device_features_ext); // pass extended features (which also contains the standard features)
421  } else {
422  standard_features_ptr = &device_features; // pass v1.0 standard features
423  }
424 
425  VkDeviceCreateInfo device_create_info = {
427  extended_features_ptr, // Extended struct ptr (used here for requesting chain of extended features)
428  0, // Flags
429  1, // Count of queues to create
430  &device_queue_create_info,
431  (uint32_t)requested_layers.size(), requested_layers.data(), // Layers
432  (uint32_t)required_device_extensions.size(), required_device_extensions.data(), // Enabled extensions
433  (VkPhysicalDeviceFeatures *)standard_features_ptr, // Requested device features
434  };
435 
436  VkResult result = vkCreateDevice(*physical_device, &device_create_info, alloc_callbacks, device);
437  if (result != VK_SUCCESS) {
438  debug(user_context) << "Vulkan: vkCreateDevice failed with return code: " << vk_get_error_name(result) << "\n";
440  }
441 
442  vkGetDeviceQueue(cached_device, *queue_family_index, 0, queue);
444 }
445 
446 // Initializes the context (used by the default implementation of halide_acquire_context)
447 int vk_create_context(void *user_context, VulkanMemoryAllocator **allocator,
448  VkInstance *instance, VkDevice *device, VkPhysicalDevice *physical_device,
449  VkCommandPool *command_pool, VkQueue *queue, uint32_t *queue_family_index) {
450 
451  debug(user_context) << " vk_create_context (user_context: " << user_context << ")\n";
452 
453  if (vkCreateInstance == nullptr) {
454  vk_load_vulkan_loader_functions(user_context);
455  if (vkCreateInstance == nullptr) {
456  error(user_context) << "Vulkan: Failed to resolve loader library methods to create instance!\n";
458  }
459  }
460 
461  StringTable requested_layers;
462  uint32_t requested_layer_count = vk_get_requested_layers(user_context, requested_layers);
463  debug(user_context) << " requested " << requested_layer_count << " layers for instance!\n";
464  for (int n = 0; n < (int)requested_layer_count; ++n) {
465  debug(user_context) << " layer: " << requested_layers[n] << "\n";
466  }
467 
468  const VkAllocationCallbacks *alloc_callbacks = halide_vulkan_get_allocation_callbacks(user_context);
469  int error_code = vk_create_instance(user_context, requested_layers, instance, alloc_callbacks);
470  if (error_code != halide_error_code_success) {
471  error(user_context) << "Vulkan: Failed to create instance for context!\n";
472  return error_code;
473  }
474 
475  if (vkCreateDevice == nullptr) {
476  vk_load_vulkan_functions(user_context, *instance);
477  if (vkCreateDevice == nullptr) {
478  error(user_context) << "Vulkan: Failed to resolve API library methods to create device!\n";
480  }
481  }
482 
483  error_code = vk_select_device_for_context(user_context, instance, device, physical_device, queue_family_index);
484  if (error_code != halide_error_code_success) {
485  error(user_context) << "Vulkan: Failed to select device for context!\n";
486  return error_code;
487  }
488 
489  error_code = vk_create_device(user_context, requested_layers, instance, device, queue, physical_device, queue_family_index, alloc_callbacks);
490  if (error_code != halide_error_code_success) {
491  error(user_context) << "Vulkan: Failed to create device for context!\n";
492  return error_code;
493  }
494 
495  *allocator = vk_create_memory_allocator(user_context, *device, *physical_device, alloc_callbacks);
496  if (*allocator == nullptr) {
497  error(user_context) << "Vulkan: Failed to create memory allocator for device!\n";
499  }
500 
501  error_code = vk_create_command_pool(user_context, *allocator, *queue_family_index, command_pool);
502  if (error_code != halide_error_code_success) {
503  error(user_context) << "Vulkan: Failed to create command pool for context!\n";
504  return error_code;
505  }
506 
508 }
509 
510 // Destroys the context and all associated resources (used by halide_vulkan_device_release)
511 // NOTE: This should be called inside an acquire_context/release_context scope
512 int vk_destroy_context(void *user_context, VulkanMemoryAllocator *allocator,
513  VkInstance instance, VkDevice device, VkPhysicalDevice physical_device,
514  VkCommandPool command_pool, VkQueue queue) {
515 
516  debug(user_context)
517  << "vk_destroy_context (user_context: " << user_context << ")\n";
518 
519  if (device != nullptr) {
520  vkDeviceWaitIdle(device);
521  }
522  if ((command_pool != VkInvalidCommandPool) && (allocator != nullptr)) {
523  vk_destroy_command_pool(user_context, allocator, command_pool);
524  vk_destroy_shader_modules(user_context, allocator);
525  vk_destroy_memory_allocator(user_context, allocator);
526  }
527  if (device != nullptr) {
528  vkDestroyDevice(device, nullptr);
529  }
530  if (instance != nullptr) {
531  vkDestroyInstance(instance, nullptr);
532  }
534 }
535 
536 // --------------------------------------------------------------------------
537 
538 } // namespace
539 } // namespace Vulkan
540 } // namespace Internal
541 } // namespace Runtime
542 } // namespace Halide
543 
544 #endif /// HALIDE_RUNTIME_VULKAN_CONTEXT_H
#define HALIDE_VERSION_MINOR
Definition: HalideRuntime.h:27
#define HALIDE_VERSION_PATCH
Definition: HalideRuntime.h:28
#define HALIDE_VERSION_MAJOR
Definition: HalideRuntime.h:26
int halide_error_no_device_interface(void *user_context)
halide_error_code_t
The error codes that may be returned by a Halide pipeline.
@ halide_error_code_symbol_not_found
A runtime symbol could not be loaded.
@ halide_error_code_device_interface_no_device
Buffer has a non-null device_interface but device is 0, which violates a Halide invariant.
@ halide_error_code_generic_error
An uncategorized error occurred.
@ halide_error_code_success
There was no error.
@ halide_error_code_out_of_memory
A call to halide_malloc returned NULL.
#define HALIDE_ALWAYS_INLINE
Definition: HalideRuntime.h:49
const char * halide_vulkan_get_device_type(void *user_context)
const struct VkAllocationCallbacks * halide_vulkan_get_allocation_callbacks(void *user_context)
int halide_vulkan_acquire_context(void *user_context, struct halide_vulkan_memory_allocator **allocator, struct VkInstance_T **instance, struct VkDevice_T **device, struct VkPhysicalDevice_T **physical_device, uint64_t *command_pool, struct VkQueue_T **queue, uint32_t *queue_family_index, bool create=true)
int halide_vulkan_release_context(void *user_context, struct VkInstance_T *instance, struct VkDevice_T *device, struct VkQueue_T *queue)
void append(void *user_context, const char *str, size_t length=0)
Definition: string_table.h:145
bool contains(const char *str) const
Definition: string_table.h:191
HALIDE_ALWAYS_INLINE VulkanContext(void *user_context)
HALIDE_ALWAYS_INLINE const VkAllocationCallbacks * allocation_callbacks()
Vulkan Memory Allocator class interface for managing large memory requests stored as contiguous block...
Definition: vulkan_memory.h:42
#define VK_API_VERSION_1_3
Definition: mini_vulkan.h:83
VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator)
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *pName)
void(VKAPI_PTR * PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR *pFeatures)
Definition: mini_vulkan.h:3860
VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue)
#define VK_MAKE_API_VERSION(variant, major, minor, patch)
Definition: mini_vulkan.h:78
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures)
VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance)
VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(VkDevice device)
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties)
#define VK_API_VERSION_MINOR(version)
Definition: mini_vulkan.h:76
@ VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR
Definition: mini_vulkan.h:1044
#define VK_FALSE
Definition: mini_vulkan.h:120
@ VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
Definition: mini_vulkan.h:608
@ VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
Definition: mini_vulkan.h:606
@ VK_PHYSICAL_DEVICE_TYPE_CPU
Definition: mini_vulkan.h:609
@ VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
Definition: mini_vulkan.h:607
VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices)
@ VK_QUEUE_COMPUTE_BIT
Definition: mini_vulkan.h:1111
#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR
Definition: mini_vulkan.h:6067
VkResult
Definition: mini_vulkan.h:138
@ VK_INCOMPLETE
Definition: mini_vulkan.h:144
@ VK_SUCCESS
Definition: mini_vulkan.h:139
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties *pQueueFamilyProperties)
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR *pFeatures)
VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator)
#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR
Definition: mini_vulkan.h:6057
#define VK_API_VERSION_MAJOR(version)
Definition: mini_vulkan.h:75
VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice)
@ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
Definition: mini_vulkan.h:175
@ VK_STRUCTURE_TYPE_APPLICATION_INFO
Definition: mini_vulkan.h:173
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR
Definition: mini_vulkan.h:250
@ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
Definition: mini_vulkan.h:174
@ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
Definition: mini_vulkan.h:176
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR
Definition: mini_vulkan.h:302
volatile ScopedSpinLock::AtomicFlag WEAK thread_lock
void WEAK vk_load_vulkan_loader_functions(void *user_context)
WEAK void * halide_vulkan_get_symbol(void *user_context, const char *name)
void WEAK vk_load_vulkan_functions(void *user_context, VkInstance instance)
VkCommandPool WEAK cached_command_pool
VkPhysicalDevice WEAK cached_physical_device
halide_vulkan_memory_allocator *WEAK cached_allocator
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
#define halide_debug_assert(user_context, cond)
halide_debug_assert() is like halide_assert(), but only expands into a check when DEBUG_RUNTIME is de...
const char * strstr(const char *, const char *)
unsigned __INT32_TYPE__ uint32_t
#define halide_abort_if_false(user_context, cond)
#define WEAK
VkPhysicalDeviceType deviceType
Definition: mini_vulkan.h:1658
char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]
Definition: mini_vulkan.h:1659