gboolean gst_vulkan_instance_open (GstVulkanInstance * instance, GError ** error) { VkExtensionProperties *instance_extensions; char *extension_names[64]; /* FIXME: make dynamic */ VkLayerProperties *instance_layers; uint32_t instance_extension_count = 0; uint32_t enabled_extension_count = 0; uint32_t instance_layer_count = 0; uint32_t enabled_layer_count = 0; gchar **enabled_layers; VkResult err; GST_OBJECT_LOCK (instance); if (instance->priv->opened) { GST_OBJECT_UNLOCK (instance); return TRUE; } /* Look for validation layers */ err = vkEnumerateInstanceLayerProperties (&instance_layer_count, NULL); if (gst_vulkan_error_to_g_error (err, error, "vKEnumerateInstanceLayerProperties") < 0) goto error; instance_layers = g_new0 (VkLayerProperties, instance_layer_count); err = vkEnumerateInstanceLayerProperties (&instance_layer_count, instance_layers); if (gst_vulkan_error_to_g_error (err, error, "vKEnumerateInstanceLayerProperties") < 0) { g_free (instance_layers); goto error; } /* TODO: allow outside selection */ _check_for_all_layers (G_N_ELEMENTS (instance_validation_layers), instance_validation_layers, instance_layer_count, instance_layers, &enabled_layer_count, &enabled_layers); g_free (instance_layers); err = vkEnumerateInstanceExtensionProperties (NULL, &instance_extension_count, NULL); if (gst_vulkan_error_to_g_error (err, error, "vkEnumerateInstanceExtensionProperties") < 0) { g_strfreev (enabled_layers); goto error; } GST_DEBUG_OBJECT (instance, "Found %u extensions", instance_extension_count); memset (extension_names, 0, sizeof (extension_names)); instance_extensions = g_new0 (VkExtensionProperties, instance_extension_count); err = vkEnumerateInstanceExtensionProperties (NULL, &instance_extension_count, instance_extensions); if (gst_vulkan_error_to_g_error (err, error, "vkEnumerateInstanceExtensionProperties") < 0) { g_strfreev (enabled_layers); g_free (instance_extensions); goto error; } { GstVulkanDisplayType display_type; gboolean swapchain_ext_found = FALSE; gboolean winsys_ext_found = FALSE; const gchar *winsys_ext_name; display_type = gst_vulkan_display_choose_type (instance); winsys_ext_name = gst_vulkan_display_type_to_extension_string (display_type); if (!winsys_ext_name) { GST_WARNING_OBJECT (instance, "No window system extension enabled"); winsys_ext_found = TRUE; /* Don't error out completely */ } /* TODO: allow outside selection */ for (uint32_t i = 0; i < instance_extension_count; i++) { GST_TRACE_OBJECT (instance, "checking instance extension %s", instance_extensions[i].extensionName); if (!g_strcmp0 (VK_KHR_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) { swapchain_ext_found = TRUE; extension_names[enabled_extension_count++] = (gchar *) VK_KHR_SURFACE_EXTENSION_NAME; } if (!g_strcmp0 (VK_EXT_DEBUG_REPORT_EXTENSION_NAME, instance_extensions[i].extensionName)) { extension_names[enabled_extension_count++] = (gchar *) VK_EXT_DEBUG_REPORT_EXTENSION_NAME; } if (!g_strcmp0 (winsys_ext_name, instance_extensions[i].extensionName)) { winsys_ext_found = TRUE; extension_names[enabled_extension_count++] = (gchar *) winsys_ext_name; } g_assert (enabled_extension_count < 64); } if (!swapchain_ext_found) { g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, "vkEnumerateInstanceExtensionProperties failed to find the required " "\"" VK_KHR_SURFACE_EXTENSION_NAME "\" extension"); g_strfreev (enabled_layers); g_free (instance_extensions); goto error; } if (!winsys_ext_found) { g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, "vkEnumerateInstanceExtensionProperties failed to find the required " "\"%s\" window system extension", winsys_ext_name); g_strfreev (enabled_layers); g_free (instance_extensions); goto error; } } { VkApplicationInfo app = { 0, }; VkInstanceCreateInfo inst_info = { 0, }; app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app.pNext = NULL; app.pApplicationName = APP_SHORT_NAME; app.applicationVersion = 0; app.pEngineName = APP_SHORT_NAME; app.engineVersion = 0; app.apiVersion = VK_API_VERSION_1_0; inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; inst_info.pNext = NULL; inst_info.pApplicationInfo = &app; #if 0 inst_info.enabledLayerCount = enabled_layer_count; inst_info.ppEnabledLayerNames = (const char *const *) enabled_layers; #else inst_info.enabledLayerCount = 0; inst_info.ppEnabledLayerNames = NULL; #endif inst_info.enabledExtensionCount = enabled_extension_count; inst_info.ppEnabledExtensionNames = (const char *const *) extension_names; err = vkCreateInstance (&inst_info, NULL, &instance->instance); if (gst_vulkan_error_to_g_error (err, error, "vkCreateInstance") < 0) { g_strfreev (enabled_layers); g_free (instance_extensions); goto error; } } g_free (instance_extensions); g_strfreev (enabled_layers); err = vkEnumeratePhysicalDevices (instance->instance, &instance->n_physical_devices, NULL); if (gst_vulkan_error_to_g_error (err, error, "vkEnumeratePhysicalDevices") < 0) goto error; g_assert (instance->n_physical_devices > 0); instance->physical_devices = g_new0 (VkPhysicalDevice, instance->n_physical_devices); err = vkEnumeratePhysicalDevices (instance->instance, &instance->n_physical_devices, instance->physical_devices); if (gst_vulkan_error_to_g_error (err, error, "vkEnumeratePhysicalDevices") < 0) goto error; instance->dbgCreateDebugReportCallback = (PFN_vkCreateDebugReportCallbackEXT) gst_vulkan_instance_get_proc_address (instance, "vkCreateDebugReportCallbackEXT"); if (!instance->dbgCreateDebugReportCallback) { g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, "Failed to retreive vkCreateDebugReportCallback"); goto error; } instance->dbgDestroyDebugReportCallback = (PFN_vkDestroyDebugReportCallbackEXT) gst_vulkan_instance_get_proc_address (instance, "vkDestroyDebugReportCallbackEXT"); if (!instance->dbgDestroyDebugReportCallback) { g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, "Failed to retreive vkDestroyDebugReportCallback"); goto error; } instance->dbgReportMessage = (PFN_vkDebugReportMessageEXT) gst_vulkan_instance_get_proc_address (instance, "vkDebugReportMessageEXT"); if (!instance->dbgReportMessage) { g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, "Failed to retreive vkDebugReportMessage"); goto error; } { VkDebugReportCallbackCreateInfoEXT info = { 0, }; info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; info.pNext = NULL; info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; info.pfnCallback = (PFN_vkDebugReportCallbackEXT) _gst_vk_debug_callback; info.pUserData = NULL; err = instance->dbgCreateDebugReportCallback (instance->instance, &info, NULL, &instance->msg_callback); if (gst_vulkan_error_to_g_error (err, error, "vkCreateDebugReportCallback") < 0) goto error; } instance->priv->opened = TRUE; GST_OBJECT_UNLOCK (instance); return TRUE; error: { GST_OBJECT_UNLOCK (instance); return FALSE; } }
gboolean gst_vulkan_device_open (GstVulkanDevice * device, GError ** error) { const char *extension_names[64]; uint32_t enabled_extension_count = 0; uint32_t device_extension_count = 0; VkExtensionProperties *device_extensions = NULL; uint32_t enabled_layer_count = 0; gchar **enabled_layers; uint32_t device_layer_count = 0; VkLayerProperties *device_layers; gboolean have_swapchain_ext; VkPhysicalDevice gpu; VkResult err; guint i; g_return_val_if_fail (GST_IS_VULKAN_DEVICE (device), FALSE); GST_OBJECT_LOCK (device); if (device->priv->opened) { GST_OBJECT_UNLOCK (device); return TRUE; } if (!_physical_device_info (device, error)) goto error; gpu = gst_vulkan_device_get_physical_device (device); /* Look for validation layers */ err = vkEnumerateDeviceLayerProperties (gpu, &device_layer_count, NULL); if (gst_vulkan_error_to_g_error (err, error, "vkEnumerateDeviceLayerProperties") < 0) goto error; device_layers = g_new0 (VkLayerProperties, device_layer_count); err = vkEnumerateDeviceLayerProperties (gpu, &device_layer_count, device_layers); if (gst_vulkan_error_to_g_error (err, error, "vkEnumerateDeviceLayerProperties") < 0) { g_free (device_layers); goto error; } _check_for_all_layers (G_N_ELEMENTS (device_validation_layers), device_validation_layers, device_layer_count, device_layers, &enabled_layer_count, &enabled_layers); g_free (device_layers); device_layers = NULL; err = vkEnumerateDeviceExtensionProperties (gpu, NULL, &device_extension_count, NULL); if (gst_vulkan_error_to_g_error (err, error, "vkEnumerateDeviceExtensionProperties") < 0) { g_strfreev (enabled_layers); goto error; } GST_DEBUG_OBJECT (device, "Found %u extensions", device_extension_count); have_swapchain_ext = 0; enabled_extension_count = 0; memset (extension_names, 0, sizeof (extension_names)); device_extensions = g_new0 (VkExtensionProperties, device_extension_count); err = vkEnumerateDeviceExtensionProperties (gpu, NULL, &device_extension_count, device_extensions); if (gst_vulkan_error_to_g_error (err, error, "vkEnumerateDeviceExtensionProperties") < 0) { g_strfreev (enabled_layers); g_free (device_extensions); goto error; } for (uint32_t i = 0; i < device_extension_count; i++) { GST_TRACE_OBJECT (device, "checking device extension %s", device_extensions[i].extensionName); if (!strcmp (VK_KHR_SWAPCHAIN_EXTENSION_NAME, device_extensions[i].extensionName)) { have_swapchain_ext = TRUE; extension_names[enabled_extension_count++] = (gchar *) VK_KHR_SWAPCHAIN_EXTENSION_NAME; } g_assert (enabled_extension_count < 64); } if (!have_swapchain_ext) { g_set_error_literal (error, GST_VULKAN_ERROR, VK_ERROR_EXTENSION_NOT_PRESENT, "Failed to find required extension, \"" VK_KHR_SWAPCHAIN_EXTENSION_NAME "\""); g_strfreev (enabled_layers); goto error; } g_free (device_extensions); vkGetPhysicalDeviceProperties (gpu, &device->gpu_props); vkGetPhysicalDeviceMemoryProperties (gpu, &device->memory_properties); vkGetPhysicalDeviceFeatures (gpu, &device->gpu_features); vkGetPhysicalDeviceQueueFamilyProperties (gpu, &device->n_queue_families, NULL); g_assert (device->n_queue_families >= 1); device->queue_family_props = g_new0 (VkQueueFamilyProperties, device->n_queue_families); vkGetPhysicalDeviceQueueFamilyProperties (gpu, &device->n_queue_families, device->queue_family_props); /* FIXME: allow overriding/selecting */ for (i = 0; i < device->n_queue_families; i++) { if (device->queue_family_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) break; } if (i >= device->n_queue_families) { g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, "Failed to find a compatible queue family"); g_strfreev (enabled_layers); goto error; } device->queue_family_id = i; device->n_queues = 1; { VkDeviceQueueCreateInfo queue_info = { 0, }; VkDeviceCreateInfo device_info = { 0, }; gfloat queue_priority = 0.5; queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue_info.pNext = NULL; queue_info.queueFamilyIndex = device->queue_family_id; queue_info.queueCount = device->n_queues; queue_info.pQueuePriorities = &queue_priority; device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_info.pNext = NULL; device_info.queueCreateInfoCount = 1; device_info.pQueueCreateInfos = &queue_info; device_info.enabledLayerCount = enabled_layer_count; device_info.ppEnabledLayerNames = (const char *const *) enabled_layers; device_info.enabledExtensionCount = enabled_extension_count; device_info.ppEnabledExtensionNames = (const char *const *) extension_names; device_info.pEnabledFeatures = NULL; err = vkCreateDevice (gpu, &device_info, NULL, &device->device); if (gst_vulkan_error_to_g_error (err, error, "vkCreateDevice") < 0) { g_strfreev (enabled_layers); goto error; } } g_strfreev (enabled_layers); { VkCommandPoolCreateInfo cmd_pool_info = { 0, }; cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; cmd_pool_info.pNext = NULL; cmd_pool_info.queueFamilyIndex = device->queue_family_id; cmd_pool_info.flags = 0; err = vkCreateCommandPool (device->device, &cmd_pool_info, NULL, &device->cmd_pool); if (gst_vulkan_error_to_g_error (err, error, "vkCreateCommandPool") < 0) goto error; } GST_OBJECT_UNLOCK (device); return TRUE; error: { GST_OBJECT_UNLOCK (device); return FALSE; } }