1 #ifndef HALIDE_RUNTIME_VULKAN_CONTEXT_H
2 #define HALIDE_RUNTIME_VULKAN_CONTEXT_H
52 : user_context(user_context) {
55 reinterpret_cast<halide_vulkan_memory_allocator **
>(&
allocator),
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";
86 VkInstance instance =
nullptr;
87 VkDevice device =
nullptr;
88 VkPhysicalDevice physical_device =
nullptr;
92 vk_get_requested_layers(user_context, requested_layers);
95 int status = vk_create_instance(user_context, requested_layers, &instance, alloc_callbacks);
97 debug(user_context) <<
" no valid vulkan runtime was found ...\n";
107 status = vk_select_device_for_context(user_context, &instance, &device, &physical_device, &queue_family_index);
109 debug(user_context) <<
" no valid vulkan device was found ...\n";
116 debug(user_context) <<
" querying for device properties ...\n";
120 debug(user_context) <<
" found device compute capability v" << *major <<
"." << *minor <<
" ...\n";
122 vk_destroy_instance(user_context, instance, alloc_callbacks);
128 debug(user_context) <<
" vk_create_instance (user_context: " << user_context <<
")\n";
131 vk_get_required_instance_extensions(user_context, required_instance_extensions);
134 vk_get_supported_instance_extensions(user_context, supported_instance_extensions);
136 bool valid_instance = vk_validate_required_extension_support(user_context, required_instance_extensions, supported_instance_extensions);
139 debug(user_context) <<
" found " << (
uint32_t)required_instance_extensions.
size() <<
" required extensions for instance!\n";
140 for (
int n = 0; n < (int)required_instance_extensions.
size(); ++n) {
141 debug(user_context) <<
" extension: " << required_instance_extensions[n] <<
"\n";
147 if (supported_instance_extensions.
contains(
"VK_KHR_portability_enumeration") &&
148 supported_instance_extensions.
contains(
"VK_MVK_macos_surface")) {
150 required_instance_extensions.
append(user_context,
"VK_KHR_portability_enumeration");
168 (
uint32_t)required_instance_extensions.
size(), required_instance_extensions.
data()
173 debug(user_context) <<
"Vulkan: vkCreateInstance failed with return code: " << vk_get_error_name(result) <<
"\n";
180 int vk_destroy_instance(
void *user_context, VkInstance instance,
const VkAllocationCallbacks *alloc_callbacks) {
181 debug(user_context) <<
" vk_destroy_instance (user_context: " << user_context <<
")\n";
186 int vk_select_device_for_context(
void *user_context,
187 VkInstance *instance, VkDevice *device,
188 VkPhysicalDevice *physical_device,
194 debug(user_context) <<
"Vulkan: vkEnumeratePhysicalDevices failed with return code: " << vk_get_error_name(result) <<
"\n";
197 if (device_count == 0) {
198 debug(user_context) <<
"Vulkan: No devices found.\n";
204 device_query_storage_config.
entry_size =
sizeof(VkPhysicalDevice);
205 BlockStorage device_query_storage(user_context, device_query_storage_config);
206 device_query_storage.resize(user_context, device_count);
208 VkPhysicalDevice chosen_device =
nullptr;
209 VkPhysicalDevice *avail_devices = (VkPhysicalDevice *)(device_query_storage.data());
210 if (avail_devices ==
nullptr) {
211 debug(user_context) <<
"Vulkan: Out of system memory!\n";
216 debug(user_context) <<
"Vulkan: vkEnumeratePhysicalDevices failed with return code: " << vk_get_error_name(result) <<
"\n";
225 for (
uint32_t i = 0; (chosen_device ==
nullptr) && (i < device_count); i++) {
228 debug(user_context) <<
"Vulkan: Checking device #" << i <<
"='" << properties.
deviceName <<
"'\n";
230 int matching_device = 0;
231 if ((dev_type !=
nullptr) && (*dev_type !=
'\0')) {
251 if (matching_device) {
253 uint32_t queue_properties_count = 0;
255 if (queue_properties_count < 1) {
261 queue_properties_storage_config.
entry_size =
sizeof(VkPhysicalDevice);
262 BlockStorage queue_properties_storage(user_context, queue_properties_storage_config);
263 queue_properties_storage.resize(user_context, queue_properties_count);
267 for (
uint32_t j = 0; (chosen_device ==
nullptr) && (j < queue_properties_count); j++) {
268 if (queue_properties[j].queueCount > 0 &&
270 chosen_device = avail_devices[i];
273 debug(user_context) <<
"Vulkan: Found matching compute device '" << properties.
deviceName <<
"'\n";
279 if (chosen_device ==
nullptr) {
281 chosen_device = avail_devices[0];
284 debug(user_context) <<
"Vulkan: Defaulting to first compute device '" << properties.
deviceName <<
"'\n";
287 *queue_family_index = queue_family;
288 *physical_device = chosen_device;
292 int vk_create_device(
void *user_context,
const StringTable &requested_layers, VkInstance *instance, VkDevice *device, VkQueue *queue,
294 debug(user_context) <<
" vk_create_device (user_context=" << user_context <<
")\n";
296 debug(user_context) <<
" checking for required device extensions ...\n";
298 vk_get_required_device_extensions(user_context, required_device_extensions);
300 debug(user_context) <<
" checking for optional device extensions ...\n";
302 vk_get_optional_device_extensions(user_context, optional_device_extensions);
304 debug(user_context) <<
" validating supported device extensions ...\n";
306 vk_get_supported_device_extensions(user_context, *physical_device, supported_device_extensions);
308 bool valid_device = vk_validate_required_extension_support(user_context, required_device_extensions, supported_device_extensions);
310 debug(user_context) <<
"Vulkan: Unable to validate required extension support!\n";
314 debug(user_context) <<
" found " << (
uint32_t)required_device_extensions.
size() <<
" required extensions for device!\n";
315 for (
uint32_t n = 0; n < required_device_extensions.
size(); ++n) {
316 debug(user_context) <<
" required extension: " << required_device_extensions[n] <<
"\n";
320 debug(user_context) <<
" checking for " << (
uint32_t)optional_device_extensions.
size() <<
" optional extensions for device ...\n";
321 for (
uint32_t n = 0; n < optional_device_extensions.
size(); ++n) {
322 if (supported_device_extensions.
contains(optional_device_extensions[n])) {
323 debug(user_context) <<
" optional extension: " << optional_device_extensions[n] <<
"\n";
324 required_device_extensions.
append(user_context, optional_device_extensions[n]);
328 float queue_priority = 1.0f;
340 debug(user_context) <<
" querying for device properties ...\n";
344 bool has_capability_v11 = (major_version >= 1) && (minor_version >= 1);
345 bool has_capability_v12 = (major_version >= 1) && (minor_version >= 2);
346 debug(user_context) <<
" found device compute capability v" << major_version <<
"." << minor_version <<
" ...\n";
350 void *extended_features_ptr =
nullptr;
351 void *standard_features_ptr =
nullptr;
353 debug(user_context) <<
" querying for device features...\n";
355 debug(user_context) <<
" shader float64 support: " << (device_features.
shaderFloat64 ?
"true" :
"false") <<
"...\n";
356 debug(user_context) <<
" shader int64 support: " << (device_features.
shaderInt64 ?
"true" :
"false") <<
"...\n";
357 debug(user_context) <<
" shader int16 support: " << (device_features.
shaderInt16 ?
"true" :
"false") <<
"...\n";
371 (has_capability_v12 ? &storage_8bit_ext :
nullptr),
376 &storage_16bit_ext, device_features};
387 debug(user_context) <<
" querying for extended device features...\n";
389 debug(user_context) <<
" shader int8 support: " << (shader_f16_i8_ext.
shaderInt8 ?
"true" :
"false") <<
"...\n";
390 debug(user_context) <<
" shader float16 support: " << (shader_f16_i8_ext.
shaderFloat16 ?
"true" :
"false") <<
"...\n";
391 if (has_capability_v12) {
392 debug(user_context) <<
" storage buffer 8bit access support: " << (storage_8bit_ext.
storageBuffer8BitAccess ?
"true" :
"false") <<
"...\n";
393 debug(user_context) <<
" storage buffer 16bit access support: " << (storage_16bit_ext.
storageBuffer16BitAccess ?
"true" :
"false") <<
"...\n";
395 extended_features_ptr = (
void *)(&device_features_ext);
397 standard_features_ptr = &device_features;
402 extended_features_ptr,
405 &device_queue_create_info,
407 (
uint32_t)required_device_extensions.
size(), required_device_extensions.
data(),
413 debug(user_context) <<
"Vulkan: vkCreateDevice failed with return code: " << vk_get_error_name(result) <<
"\n";
423 VkInstance *instance, VkDevice *device, VkPhysicalDevice *physical_device,
424 VkCommandPool *command_pool, VkQueue *queue,
uint32_t *queue_family_index) {
426 debug(user_context) <<
" vk_create_context (user_context: " << user_context <<
")\n";
429 uint32_t requested_layer_count = vk_get_requested_layers(user_context, requested_layers);
430 debug(user_context) <<
" requested " << requested_layer_count <<
" layers for instance!\n";
431 for (
int n = 0; n < (int)requested_layer_count; ++n) {
432 debug(user_context) <<
" layer: " << requested_layers[n] <<
"\n";
436 int error_code = vk_create_instance(user_context, requested_layers, instance, alloc_callbacks);
438 error(user_context) <<
"Vulkan: Failed to create instance for context!\n";
446 error_code = vk_select_device_for_context(user_context, instance, device, physical_device, queue_family_index);
448 error(user_context) <<
"Vulkan: Failed to select device for context!\n";
452 error_code = vk_create_device(user_context, requested_layers, instance, device, queue, physical_device, queue_family_index, alloc_callbacks);
454 error(user_context) <<
"Vulkan: Failed to create device for context!\n";
458 *allocator = vk_create_memory_allocator(user_context, *device, *physical_device, alloc_callbacks);
459 if (*allocator ==
nullptr) {
460 error(user_context) <<
"Vulkan: Failed to create memory allocator for device!\n";
464 error_code = vk_create_command_pool(user_context, *allocator, *queue_family_index, command_pool);
466 error(user_context) <<
"Vulkan: Failed to create command pool for context!\n";
#define HALIDE_VERSION_MINOR
#define HALIDE_VERSION_PATCH
#define HALIDE_VERSION_MAJOR
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_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
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)
const char ** data() const
bool contains(const char *str) const
VulkanMemoryAllocator * allocator
uint32_t queue_family_index
HALIDE_ALWAYS_INLINE VulkanContext(void *user_context)
VkCommandPool command_pool
VkPhysicalDevice physical_device
HALIDE_ALWAYS_INLINE const VkAllocationCallbacks * allocation_callbacks()
HALIDE_ALWAYS_INLINE ~VulkanContext()
halide_error_code_t error
Vulkan Memory Allocator class interface for managing large memory requests stored as contiguous block...
#define VK_API_VERSION_1_3
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *pName)
void(VKAPI_PTR * PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR *pFeatures)
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)
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 void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties)
#define VK_API_VERSION_MINOR(version)
@ VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR
@ VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
@ VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
@ VK_PHYSICAL_DEVICE_TYPE_CPU
@ VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices)
#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR
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
#define VK_API_VERSION_MAJOR(version)
VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice)
@ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
@ VK_STRUCTURE_TYPE_APPLICATION_INFO
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR
@ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
@ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR
volatile ScopedSpinLock::AtomicFlag WEAK thread_lock
VkQueue WEAK cached_queue
VkInstance WEAK cached_instance
VkCommandPool WEAK cached_command_pool
uint32_t WEAK cached_queue_family_index
VkPhysicalDevice WEAK cached_physical_device
halide_vulkan_memory_allocator *WEAK cached_allocator
VkDevice WEAK cached_device
void WEAK vk_load_vulkan_functions(VkInstance instance)
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)
VkBool32 storageBuffer16BitAccess
VkBool32 storageBuffer8BitAccess
VkPhysicalDeviceType deviceType
char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]