48 VkDebugUtilsMessengerEXT
messenger = VK_NULL_HANDLE;
55 reinterpret_cast<halide_vulkan_memory_allocator **
>(&
allocator),
82int vk_find_compute_capability(
void *
user_context,
int *major,
int *minor) {
85 VkInstance instance = VK_NULL_HANDLE;
86 VkDevice device = VK_NULL_HANDLE;
87 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
102 if (vkCreateInstance ==
nullptr) {
104 if (vkCreateInstance ==
nullptr) {
105 debug(
user_context) <<
" no valid vulkan loader library was found ...\n";
112 vk_get_requested_layers(
user_context, requested_layers);
116 int status = vk_create_instance(
user_context, requested_layers, &instance, alloc_callbacks);
118 debug(
user_context) <<
" no valid vulkan runtime was found ...\n";
123 status = vk_select_device_for_context(
user_context, &instance, &device, &physical_device, &queue_family_index);
125 debug(
user_context) <<
" no valid vulkan device was found ...\n";
130 VkPhysicalDeviceProperties device_properties = {0};
131 debug(
user_context) <<
" querying for device properties ...\n";
132 vkGetPhysicalDeviceProperties(physical_device, &device_properties);
133 *major = VK_API_VERSION_MAJOR(device_properties.apiVersion);
134 *minor = VK_API_VERSION_MINOR(device_properties.apiVersion);
135 debug(
user_context) <<
" found device compute capability v" << *major <<
"." << *minor <<
" ...\n";
137 vk_destroy_instance(
user_context, instance, alloc_callbacks);
142int vk_create_instance(
void *
user_context,
const StringTable &requested_layers, VkInstance *instance,
const VkAllocationCallbacks *alloc_callbacks) {
146 vk_get_required_instance_extensions(
user_context, required_instance_extensions);
149 vk_get_optional_instance_extensions(
user_context, optional_instance_extensions);
152 vk_get_supported_instance_extensions(
user_context, supported_instance_extensions);
154 bool valid_instance = vk_validate_required_extension_support(
user_context, required_instance_extensions, supported_instance_extensions);
157 debug(
user_context) <<
" found " << (
uint32_t)required_instance_extensions.
size() <<
" required extensions for instance!\n";
158 for (
int n = 0; n < (int)required_instance_extensions.
size(); ++n) {
159 debug(
user_context) <<
" extension: " << required_instance_extensions[n] <<
"\n";
163 debug(
user_context) <<
" checking for " << (
uint32_t)optional_instance_extensions.
size() <<
" optional extensions for instance ...\n";
164 for (
uint32_t n = 0; n < optional_instance_extensions.
size(); ++n) {
165 if (supported_instance_extensions.
contains(optional_instance_extensions[n])) {
166 debug(
user_context) <<
" optional extension: " << optional_instance_extensions[n] <<
"\n";
174 if (supported_instance_extensions.
contains(
"VK_KHR_portability_enumeration") &&
175 supported_instance_extensions.
contains(
"VK_MVK_macos_surface")) {
176 create_flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
180 VkApplicationInfo app_info = {
181 VK_STRUCTURE_TYPE_APPLICATION_INFO,
184 VK_MAKE_API_VERSION(0, 1, 0, 0),
189 VkInstanceCreateInfo create_info = {
190 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
195 (
uint32_t)required_instance_extensions.
size(), required_instance_extensions.
data()
198 VkResult result = vkCreateInstance(&create_info, alloc_callbacks, instance);
199 if (result != VK_SUCCESS) {
200 debug(
user_context) <<
"Vulkan: vkCreateInstance failed with return code: " << vk_get_error_name(result) <<
"\n";
205 if (vkCreateDevice ==
nullptr) {
206 error(
user_context) <<
"Vulkan: Failed to resolve instance API methods to create device!\n";
213int vk_destroy_instance(
void *
user_context, VkInstance instance,
const VkAllocationCallbacks *alloc_callbacks) {
214 debug(
user_context) <<
" vk_destroy_instance (user_context: " <<
user_context <<
", device: " << (
void *)instance <<
", alloc_callbacks: " << (
void *)alloc_callbacks <<
")\n";
215 vkDestroyInstance(instance, alloc_callbacks);
221 VkInstance *instance, VkDevice *device,
222 VkPhysicalDevice *physical_device,
226 VkResult result = vkEnumeratePhysicalDevices(*instance, &device_count,
nullptr);
227 if ((result != VK_SUCCESS) && (result != VK_INCOMPLETE)) {
228 debug(
user_context) <<
"Vulkan: vkEnumeratePhysicalDevices failed with return code: " << vk_get_error_name(result) <<
"\n";
231 if (device_count == 0) {
238 device_query_storage_config.
entry_size =
sizeof(VkPhysicalDevice);
240 device_query_storage.resize(
user_context, device_count);
242 VkPhysicalDevice chosen_device = VK_NULL_HANDLE;
243 VkPhysicalDevice *avail_devices = (VkPhysicalDevice *)(device_query_storage.data());
244 if (avail_devices ==
nullptr) {
245 debug(
user_context) <<
"Vulkan: Out of system memory!\n";
248 result = vkEnumeratePhysicalDevices(*instance, &device_count, avail_devices);
249 if ((result != VK_SUCCESS) && (result != VK_INCOMPLETE)) {
250 debug(
user_context) <<
"Vulkan: vkEnumeratePhysicalDevices failed with return code: " << vk_get_error_name(result) <<
"\n";
259 for (
uint32_t i = 0; (chosen_device == VK_NULL_HANDLE) && (i < device_count); i++) {
260 VkPhysicalDeviceProperties properties;
261 vkGetPhysicalDeviceProperties(avail_devices[i], &properties);
262 debug(
user_context) <<
"Vulkan: Checking device #" << i <<
"='" << properties.deviceName <<
"'\n";
264 int matching_device = 0;
265 if ((dev_type !=
nullptr) && (*dev_type !=
'\0')) {
266 if (
strstr(dev_type,
"cpu") && (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)) {
268 }
else if (
strstr(dev_type,
"integrated-gpu") && ((properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU))) {
270 }
else if (
strstr(dev_type,
"discrete-gpu") && ((properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU))) {
272 }
else if (
strstr(dev_type,
"virtual-gpu") && (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU)) {
274 }
else if (
strstr(dev_type,
"gpu") && ((properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) || (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU))) {
279 if ((properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) ||
280 (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)) {
285 if (matching_device) {
287 uint32_t queue_properties_count = 0;
288 vkGetPhysicalDeviceQueueFamilyProperties(avail_devices[i], &queue_properties_count,
nullptr);
289 if (queue_properties_count < 1) {
295 queue_properties_storage_config.
entry_size =
sizeof(VkPhysicalDevice);
297 queue_properties_storage.resize(
user_context, queue_properties_count);
299 VkQueueFamilyProperties *queue_properties = (VkQueueFamilyProperties *)(queue_properties_storage.data());
300 vkGetPhysicalDeviceQueueFamilyProperties(avail_devices[i], &queue_properties_count, queue_properties);
301 for (
uint32_t j = 0; (chosen_device ==
nullptr) && (j < queue_properties_count); j++) {
302 if (queue_properties[j].queueCount > 0 &&
303 queue_properties[j].queueFlags & VK_QUEUE_COMPUTE_BIT) {
304 chosen_device = avail_devices[i];
307 debug(
user_context) <<
"Vulkan: Found matching compute device '" << properties.deviceName <<
"'\n";
313 if (chosen_device ==
nullptr) {
315 chosen_device = avail_devices[0];
316 VkPhysicalDeviceProperties properties;
317 vkGetPhysicalDeviceProperties(chosen_device, &properties);
318 debug(
user_context) <<
"Vulkan: Defaulting to first compute device '" << properties.deviceName <<
"'\n";
321 *queue_family_index = queue_family;
322 *physical_device = chosen_device;
326int vk_create_device(
void *
user_context,
const StringTable &requested_layers, VkInstance *instance, VkDevice *device, VkQueue *queue,
327 VkPhysicalDevice *physical_device,
uint32_t *queue_family_index,
const VkAllocationCallbacks *alloc_callbacks) {
330 debug(
user_context) <<
" checking for required device extensions ...\n";
332 vk_get_required_device_extensions(
user_context, required_device_extensions);
334 debug(
user_context) <<
" checking for optional device extensions ...\n";
336 vk_get_optional_device_extensions(
user_context, optional_device_extensions);
338 debug(
user_context) <<
" validating supported device extensions ...\n";
340 vk_get_supported_device_extensions(
user_context, *physical_device, supported_device_extensions);
342 bool valid_device = vk_validate_required_extension_support(
user_context, required_device_extensions, supported_device_extensions);
344 debug(
user_context) <<
"Vulkan: Unable to validate required extension support!\n";
348 debug(
user_context) <<
" found " << (
uint32_t)required_device_extensions.
size() <<
" required extensions for device!\n";
349 for (
uint32_t n = 0; n < required_device_extensions.
size(); ++n) {
350 debug(
user_context) <<
" required extension: " << required_device_extensions[n] <<
"\n";
354 debug(
user_context) <<
" checking for " << (
uint32_t)optional_device_extensions.
size() <<
" optional extensions for device ...\n";
355 for (
uint32_t n = 0; n < optional_device_extensions.
size(); ++n) {
356 if (supported_device_extensions.
contains(optional_device_extensions[n])) {
357 debug(
user_context) <<
" optional extension: " << optional_device_extensions[n] <<
"\n";
362 float queue_priority = 1.0f;
363 VkDeviceQueueCreateInfo device_queue_create_info = {
364 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
373 VkPhysicalDeviceProperties device_properties = {0};
374 debug(
user_context) <<
" querying for device properties ...\n";
375 vkGetPhysicalDeviceProperties(*physical_device, &device_properties);
376 uint32_t major_version = VK_API_VERSION_MAJOR(device_properties.apiVersion);
377 uint32_t minor_version = VK_API_VERSION_MINOR(device_properties.apiVersion);
378 bool has_capability_v11 = (major_version >= 1) && (minor_version >= 1);
379 bool has_capability_v12 = (major_version >= 1) && (minor_version >= 2);
380 debug(
user_context) <<
" found device compute capability v" << major_version <<
"." << minor_version <<
" ...\n";
383 VkPhysicalDeviceFeatures device_features = {};
384 void *extended_features_ptr =
nullptr;
385 void *standard_features_ptr =
nullptr;
387 debug(
user_context) <<
" querying for device features...\n";
388 vkGetPhysicalDeviceFeatures(*physical_device, &device_features);
389 debug(
user_context) <<
" shader float64 support: " << (device_features.shaderFloat64 ?
"true" :
"false") <<
"...\n";
390 debug(
user_context) <<
" shader int64 support: " << (device_features.shaderInt64 ?
"true" :
"false") <<
"...\n";
391 debug(
user_context) <<
" shader int16 support: " << (device_features.shaderInt16 ?
"true" :
"false") <<
"...\n";
396 VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_f16_i8_ext = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR,
397 nullptr, VK_FALSE, VK_FALSE};
400 VkPhysicalDevice8BitStorageFeaturesKHR storage_8bit_ext = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR,
401 &shader_f16_i8_ext, VK_FALSE, VK_FALSE, VK_FALSE};
404 VkPhysicalDevice16BitStorageFeaturesKHR storage_16bit_ext = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR,
405 (has_capability_v12 ? &storage_8bit_ext :
nullptr),
406 VK_FALSE, VK_FALSE, VK_FALSE, VK_FALSE};
408 VkPhysicalDeviceFeatures2KHR device_features_ext = {
409 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR,
410 &storage_16bit_ext, device_features};
413 PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(*instance,
"vkGetPhysicalDeviceFeatures2KHR");
414 if (!vkGetPhysicalDeviceFeatures2KHR) {
415 vkGetPhysicalDeviceFeatures2KHR = (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(*instance,
"vkGetPhysicalDeviceFeatures2");
419 if (vkGetPhysicalDeviceFeatures2KHR && has_capability_v11) {
421 debug(
user_context) <<
" querying for extended device features...\n";
422 vkGetPhysicalDeviceFeatures2KHR(*physical_device, &device_features_ext);
423 debug(
user_context) <<
" shader int8 support: " << (shader_f16_i8_ext.shaderInt8 ?
"true" :
"false") <<
"...\n";
424 debug(
user_context) <<
" shader float16 support: " << (shader_f16_i8_ext.shaderFloat16 ?
"true" :
"false") <<
"...\n";
425 if (has_capability_v12) {
426 debug(
user_context) <<
" storage buffer 8bit access support: " << (storage_8bit_ext.storageBuffer8BitAccess ?
"true" :
"false") <<
"...\n";
427 debug(
user_context) <<
" storage buffer 16bit access support: " << (storage_16bit_ext.storageBuffer16BitAccess ?
"true" :
"false") <<
"...\n";
429 extended_features_ptr = (
void *)(&device_features_ext);
431 standard_features_ptr = &device_features;
434 VkDeviceCreateInfo device_create_info = {
435 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
436 extended_features_ptr,
439 &device_queue_create_info,
441 (
uint32_t)required_device_extensions.
size(), required_device_extensions.
data(),
442 (VkPhysicalDeviceFeatures *)standard_features_ptr,
445 VkResult result = vkCreateDevice(*physical_device, &device_create_info, alloc_callbacks, device);
446 if (result != VK_SUCCESS) {
447 debug(
user_context) <<
"Vulkan: vkCreateDevice failed with return code: " << vk_get_error_name(result) <<
"\n";
452 if (vkAllocateMemory ==
nullptr) {
453 error(
user_context) <<
"Vulkan: Failed to resolve device API methods for driver!\n";
457 vkGetDeviceQueue(*device, *queue_family_index, 0, queue);
461int vk_destroy_device(
void *
user_context, VkDevice device,
const VkAllocationCallbacks *alloc_callbacks) {
462 debug(
user_context) <<
" vk_destroy_device (user_context: " <<
user_context <<
", device: " << (
void *)device <<
", alloc_callbacks: " << (
void *)alloc_callbacks <<
")\n";
463 vkDestroyDevice(device, alloc_callbacks);
470 VkInstance *instance, VkDevice *device, VkPhysicalDevice *physical_device,
471 VkQueue *queue,
uint32_t *queue_family_index, VkDebugUtilsMessengerEXT *messenger) {
475 if (vkCreateInstance ==
nullptr) {
477 if (vkCreateInstance ==
nullptr) {
478 error(
user_context) <<
"Vulkan: Failed to resolve loader library methods to create instance!\n";
485 debug(
user_context) <<
" requested " << requested_layer_count <<
" layers for instance!\n";
486 for (
int n = 0; n < (int)requested_layer_count; ++n) {
487 debug(
user_context) <<
" layer: " << requested_layers[n] <<
"\n";
493 error(
user_context) <<
"Vulkan: Failed to create instance for context!\n";
497 error_code = vk_select_device_for_context(
user_context, instance, device, physical_device, queue_family_index);
499 error(
user_context) <<
"Vulkan: Failed to select device for context!\n";
503 error_code = vk_create_device(
user_context, requested_layers, instance, device, queue, physical_device, queue_family_index, alloc_callbacks);
505 error(
user_context) <<
"Vulkan: Failed to create device for context!\n";
511 error(
user_context) <<
"Vulkan: Failed to create memory allocator for device!\n";
522 VkInstance instance, VkDevice device, VkPhysicalDevice physical_device,
523 VkQueue queue, VkDebugUtilsMessengerEXT messenger) {
526 <<
"vk_destroy_context (user_context: " <<
user_context <<
")\n";
528 if (vkCreateInstance ==
nullptr) {
532 if (queue != VK_NULL_HANDLE) {
533 VkResult result = vkQueueWaitIdle(queue);
534 if (result != VK_SUCCESS) {
535 error(
user_context) <<
"Vulkan: vkQueueWaitIdle returned " << vk_get_error_name(result) <<
"\n";
539 if (device != VK_NULL_HANDLE) {
540 VkResult result = vkDeviceWaitIdle(device);
541 if (result != VK_SUCCESS) {
542 error(
user_context) <<
"Vulkan: vkDeviceWaitIdle returned " << vk_get_error_name(result) <<
"\n";
554 if (device != VK_NULL_HANDLE) {
555 vk_destroy_device(
user_context, device, alloc_callbacks);
557 if (instance != VK_NULL_HANDLE) {
558 vk_destroy_instance(
user_context, instance, alloc_callbacks);
565VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_utils_messenger_callback(
566 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
567 VkDebugUtilsMessageTypeFlagsEXT message_type,
568 const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
570 if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
571 print(user_data) <<
"Vulkan [WARNING]: (user_context=" << user_data <<
", "
572 <<
"id=" << callback_data->messageIdNumber <<
", "
573 <<
"name:" << callback_data->pMessageIdName <<
") "
574 << callback_data->pMessage <<
"\n";
575 }
else if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
576 print(user_data) <<
"Vulkan [ERROR]: (user_context=" << user_data <<
", "
577 <<
"id=" << callback_data->messageIdNumber <<
", "
578 <<
"name:" << callback_data->pMessageIdName <<
") "
579 << callback_data->pMessage <<
"\n";
582 debug(user_data) <<
"Vulkan [DEBUG]: (user_context=" << user_data <<
", "
583 <<
"id=" << callback_data->messageIdNumber <<
", "
584 <<
"name:" << callback_data->pMessageIdName <<
") "
585 << callback_data->pMessage <<
"\n";
591 PFN_vkCreateDebugUtilsMessengerEXT func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance,
"vkCreateDebugUtilsMessengerEXT");
592 if (func !=
nullptr) {
593 debug(
user_context) <<
"Vulkan: Registering Debug Utils Messenger ... \n";
594 VkDebugUtilsMessengerCreateInfoEXT create_info{};
595 create_info.flags = 0;
596 create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
597 create_info.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;
598 create_info.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;
599 create_info.pfnUserCallback = vk_debug_utils_messenger_callback;
603 debug(
user_context) <<
"Vulkan: Debug Utils Messenger extension unavailable!\n";
604 return VK_ERROR_EXTENSION_NOT_PRESENT;
609 PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance,
"vkDestroyDebugUtilsMessengerEXT");
610 if (func !=
nullptr) {
611 debug(
user_context) <<
"Vulkan: Destroying Debug Utils Messenger ...\n";