void checkDeviceLayerPresent(VkPhysicalDevice physicalDevice, const char* layerName) { uint32_t layerCount = 0; std::vector<VkLayerProperties> layers; vkEnumerateDeviceLayerProperties(physicalDevice, &layerCount, NULL); layers.resize(layerCount); vkEnumerateDeviceLayerProperties(physicalDevice, &layerCount, layers.data()); for (auto& layer : layers) { if (!strcmp(layerName, layer.layerName)) { return; } } cerr << "ERROR: cannot find layer: " << layerName << endl; exit(1); }
/* * Return list of PhysicalDevice layers */ std::vector<VkLayerProperties> PhysicalDevice::layers() const { std::vector<VkLayerProperties> layer_props; VkResult err; do { uint32_t layer_count = 0; err = vkEnumerateDeviceLayerProperties(handle(), &layer_count, NULL); if (err == VK_SUCCESS) { layer_props.reserve(layer_count); err = vkEnumerateDeviceLayerProperties(handle(), &layer_count, layer_props.data()); } } while (err == VK_INCOMPLETE); assert(err == VK_SUCCESS); return layer_props; }
VkResult VulkanContext::GetDeviceLayerProperties() { /* * It's possible, though very rare, that the number of * instance layers could change. For example, installing something * could include new layers that the loader would pick up * between the initial query for the count and the * request for VkLayerProperties. The loader indicates that * by returning a VK_INCOMPLETE status and will update the * the count parameter. * The count parameter will be updated with the number of * entries loaded into the data pointer - in case the number * of layers went down or is smaller than the size given. */ uint32_t device_layer_count; std::vector<VkLayerProperties> vk_props; VkResult res; do { res = vkEnumerateDeviceLayerProperties(physical_devices_[physical_device_], &device_layer_count, nullptr); if (res != VK_SUCCESS) return res; if (device_layer_count == 0) return VK_SUCCESS; vk_props.resize(device_layer_count); res = vkEnumerateDeviceLayerProperties(physical_devices_[physical_device_], &device_layer_count, vk_props.data()); } while (res == VK_INCOMPLETE); // Gather the list of extensions for each device layer. for (uint32_t i = 0; i < device_layer_count; i++) { LayerProperties layer_props; layer_props.properties = vk_props[i]; res = GetDeviceLayerExtensionList(layer_props.properties.layerName, layer_props.extensions); if (res != VK_SUCCESS) return res; device_layer_properties_.push_back(layer_props); } return res; }
TEST(EnumerateDeviceLayerProperties, PropertyCountLessThanAvailable) { VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_SUCCESS); uint32_t physicalCount = 0; result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); for(uint32_t p = 0; p < physicalCount; ++p) { uint32_t count = 0u; result = vkEnumerateDeviceLayerProperties(physical[p], &count, nullptr); ASSERT_EQ(result, VK_SUCCESS); // We need atleast two for the test to be relevant. if(count < 2u) { continue; } std::unique_ptr<VkLayerProperties[]> properties(new VkLayerProperties[count]); count = 1; result = vkEnumerateDeviceLayerProperties(physical[p], &count, properties.get()); ASSERT_EQ(result, VK_INCOMPLETE); } vkDestroyInstance(instance, nullptr); }
// Devices void Renderer::_InitDevice() { { uint32_t gpu_count = 0; // Read number of GPU's vkEnumeratePhysicalDevices(_instance, &gpu_count, nullptr); std::vector<VkPhysicalDevice> gpu_list(gpu_count); // Populate list vkEnumeratePhysicalDevices(_instance, &gpu_count, gpu_list.data()); _gpu = gpu_list[0]; // Get the first available list vkGetPhysicalDeviceProperties(_gpu, &_gpu_properties); vkGetPhysicalDeviceMemoryProperties(_gpu, &_gpu_memory_properties); } { uint32_t family_count = 0; // Read number of GPU queue family properties vkGetPhysicalDeviceQueueFamilyProperties(_gpu, &family_count, nullptr); std::vector<VkQueueFamilyProperties> family_property_list(family_count); // Populate list vkGetPhysicalDeviceQueueFamilyProperties(_gpu, &family_count, family_property_list.data()); // Find the graphics family bool found = false; for (uint32_t i = 0; i < family_count; ++i) { if (family_property_list[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { found = true; _graphics_family_index = i; } } if (!found) { assert(0 && "Vulkan ERROR: Queue family supporting graphics not found."); std::exit(-1); } } // Instance Layers { uint32_t layer_count = 0; // Read the number of layers vkEnumerateInstanceLayerProperties(&layer_count, nullptr); std::vector<VkLayerProperties> layer_property_list(layer_count); // Populate list vkEnumerateInstanceLayerProperties(&layer_count, layer_property_list.data()); #if BUILD_ENABLE_VULKAN_RUNTIME_DEBUG std::cout << "Instance layers: \n"; for (auto &i : layer_property_list) { std::cout << " " << i.layerName << "\t\t | " << i.description << std::endl; } std::cout << std::endl; #endif } // Instance Extensions { uint32_t extension_count = 0; // Read the number of extensions vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr); std::vector<VkExtensionProperties> extension_property_list(extension_count); // Populate list vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_property_list.data()); #if BUILD_ENABLE_VULKAN_RUNTIME_DEBUG std::cout << "Instance extensions: \n"; for (auto &i : extension_property_list) { std::cout << " " << i.extensionName << "\t\t | " << i.specVersion << std::endl; } std::cout << std::endl; #endif } // Device Layers { uint32_t layer_count = 0; // Read the number of layers vkEnumerateDeviceLayerProperties(_gpu, &layer_count, nullptr); std::vector<VkLayerProperties> layer_property_list(layer_count); // Populate list vkEnumerateDeviceLayerProperties(_gpu, &layer_count, layer_property_list.data()); #if BUILD_ENABLE_VULKAN_RUNTIME_DEBUG std::cout << "Device layers: \n"; for (auto &i : layer_property_list) { std::cout << " " << i.layerName << "\t\t | " << i.description << std::endl; } std::cout << std::endl; #endif } // Device Extensions { uint32_t extension_count = 0; // Read the number of extensions vkEnumerateDeviceExtensionProperties(_gpu, nullptr, &extension_count, nullptr); std::vector<VkExtensionProperties> extension_property_list(extension_count); // Populate list vkEnumerateDeviceExtensionProperties(_gpu, nullptr, &extension_count, extension_property_list.data()); #if BUILD_ENABLE_VULKAN_RUNTIME_DEBUG std::cout << "Device extensions: \n"; for (auto &i : extension_property_list) { std::cout << " " << i.extensionName << "\t\t | " << i.specVersion << std::endl; } std::cout << std::endl; #endif } float queue_priorities[] {1.0f}; VkDeviceQueueCreateInfo device_queue_create_info {}; device_queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; device_queue_create_info.queueFamilyIndex = _graphics_family_index; device_queue_create_info.queueCount = 1; device_queue_create_info.pQueuePriorities = queue_priorities; VkDeviceCreateInfo device_create_info = {}; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_create_info.queueCreateInfoCount = 1; device_create_info.pQueueCreateInfos = &device_queue_create_info; device_create_info.enabledLayerCount = (uint32_t) _device_layer_list.size(); device_create_info.ppEnabledLayerNames = _device_layer_list.data(); device_create_info.enabledExtensionCount = (uint32_t) _device_extension_list.size(); device_create_info.ppEnabledExtensionNames = _device_extension_list.data(); ErrorCheck(vkCreateDevice(_gpu, &device_create_info, nullptr, &_device)); vkGetDeviceQueue(_device, _graphics_family_index, 0, &_queue); }
int main(int argc, char** argv) { g_validationLayers = std::vector<const char*> { "VK_LAYER_LUNARG_mem_tracker", "VK_LAYER_GOOGLE_unique_objects", }; // Init GLFW { // Handle GLFW errors glfwSetErrorCallback([](int error, const char* description) { std::cout << "GLFW error: " << error << " - " << description << std::endl; }); // Initialize GLFW if (!glfwInit()) error("Cannot initialize GLFW."); // Check Vulkan support if (!glfwVulkanSupported()) error("Cannot find compatible Vulkan client driver."); } // Get Validation layers { uint32_t numInstanceLayers = 0; // Get numInstanceLayers if (vkEnumerateInstanceLayerProperties(&numInstanceLayers, nullptr)) error("Vulkan: Could not enumerate instance layer properties."); if (numInstanceLayers > 0) { std::vector<VkLayerProperties> instanceLayers(numInstanceLayers); if (vkEnumerateInstanceLayerProperties(&numInstanceLayers, instanceLayers.data())) error("Vulkan: Could not enumerate instance layer properties."); // Print layers: std::cout << "Validation layers: " << std::endl; for (int i = 0; i < numInstanceLayers; ++i) { std::cout << "\t" << instanceLayers[i].layerName << std::endl; std::cout << "\t\t" << instanceLayers[i].description << std::endl; std::cout << std::endl; } std::cout << std::endl; } else std::cout << "No validation layers found!" << std::endl; // TODO: Check Layers } // Check instance extensions { int numRequiredExtensions; const char** requiredExtensions; // Get required extensions from GLFW { requiredExtensions = glfwGetRequiredInstanceExtensions((int*)&numRequiredExtensions); if (numRequiredExtensions > 0) { // Write to global g_extensions for (int i = 0; i < numRequiredExtensions; ++i) g_extensions.push_back(requiredExtensions[i]); // Print std::cout << "Required Instance Extensions(GLFW):" << std::endl; for (int i = 0; i < numRequiredExtensions; ++i) { std::cout << "\t" << requiredExtensions[i] << std::endl; } std::cout << std::endl; } // TODO: Check extensions } // Get Instance extensions { VkResult err; uint32_t numInstanceExtensions; err = vkEnumerateInstanceExtensionProperties(nullptr, &numInstanceExtensions, nullptr); if (numInstanceExtensions > 0) { std::vector<VkExtensionProperties> instanceExtensions(numInstanceExtensions); err = vkEnumerateInstanceExtensionProperties(NULL, &numInstanceExtensions, instanceExtensions.data()); // Print std::cout << "Instance Extensions: " << std::endl; for (int i = 0; i < numInstanceExtensions; ++i) { std::cout << "\t" <<instanceExtensions[i].extensionName << std::endl; std::cout << "\t\t" << instanceExtensions[i].specVersion << std::endl; std::cout << std::endl; } std::cout << std::endl; } // TODO: Check instance extensions(with required instance extensions) } } // Create Vulkan Instance { VkApplicationInfo app; { app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app.pNext = nullptr; app.pApplicationName = "Vulkan test 1"; app.applicationVersion = 0; app.pEngineName = "Vulkan test 1"; app.engineVersion = 0; app.apiVersion = VK_API_VERSION; } VkInstanceCreateInfo instanceInfo; { instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instanceInfo.pNext = nullptr; instanceInfo.pApplicationInfo = &app; instanceInfo.enabledLayerCount = g_validationLayers.size(); instanceInfo.ppEnabledLayerNames = g_validationLayers.data(); instanceInfo.enabledExtensionCount = g_extensions.size(); instanceInfo.ppEnabledExtensionNames = g_extensions.data(); } // TODO: Aligned allocators VkAllocationCallbacks allocator; { allocator.pUserData = nullptr; allocator.pfnAllocation = [](void* pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)->void* { return malloc(size); }; allocator.pfnFree = [](void* pUserData, void* pMemory) { free(pMemory); }; allocator.pfnReallocation = [](void* pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) { free(pOriginal); return malloc(size); }; allocator.pfnInternalAllocation = nullptr; allocator.pfnInternalFree = nullptr; allocator.pfnReallocation = nullptr; } // Create vulkan instance VkResult vkError = vkCreateInstance(&instanceInfo, &allocator, &g_vkInstance); // Handle errors switch (vkError) { case VK_ERROR_INCOMPATIBLE_DRIVER: error("Drivers do not support vulkan. Drivers could be outdated."); break; case VK_ERROR_EXTENSION_NOT_PRESENT: error("Cannot find specified extension."); break; case VK_SUCCESS: // Succes! (prevent default from catching success as error) std::cout << "Vulkan instance created!" << std::endl; break; default: error("Could not create vulkan Instance. Drivers could be outdated."); break; } } // Look for GPU device { uint32_t numGPUs; VkResult vkError = vkEnumeratePhysicalDevices(g_vkInstance, &numGPUs, nullptr); if (numGPUs < 0) error("vkEnumeratePhysicalDevices could not find any GPU devices."); if (vkError) error("vkEnumeratePhysicalDevices could not enumerate GPU devices."); if (numGPUs > 0) { std::vector<VkPhysicalDevice> physicalDevices(numGPUs); if (vkEnumeratePhysicalDevices(g_vkInstance, &numGPUs, physicalDevices.data())) error("vkEnumeratePhysicalDevices could not enumerate GPU devices."); g_vkGPU = physicalDevices[0]; std::cout << numGPUs << " GPUs found!" << std::endl; } } // Get queue properties { uint32_t numQueues; vkGetPhysicalDeviceProperties(g_vkGPU, &g_vkGPUProperties); vkGetPhysicalDeviceQueueFamilyProperties(g_vkGPU, &numQueues, nullptr); if (numQueues == 0) error("vkGetPhysicalDeviceQueueFamilyProperties could not find any queues."); g_vkQueueProperties = std::vector<VkQueueFamilyProperties>(numQueues); vkGetPhysicalDeviceQueueFamilyProperties(g_vkGPU, &numQueues, g_vkQueueProperties.data()); } // Look for device layers (Unecessary code that does nothing) { uint32_t numDeviceLayers; if (vkEnumerateDeviceLayerProperties(g_vkGPU, &numDeviceLayers, nullptr)) error("vkEnumerateDeviceLayerProperties failed!"); if (numDeviceLayers > 0) { std::vector<VkLayerProperties> deviceLayers(numDeviceLayers); if (vkEnumerateDeviceLayerProperties(g_vkGPU, &numDeviceLayers, deviceLayers.data())) error("vkEnumerateDeviceLayerProperties failed!"); // TODO: Check device layers. } } // Look for device extensions (swapchain extension) { uint32_t numDeviceExtensions; bool extensionSwapChainFound = false; if (vkEnumerateDeviceExtensionProperties(g_vkGPU, nullptr, &numDeviceExtensions, nullptr)) error("vkEnumerateDeviceExtensionProperties failed!"); if (numDeviceExtensions > 0) { std::vector<VkExtensionProperties> deviceExtensions(numDeviceExtensions); if (vkEnumerateDeviceExtensionProperties(g_vkGPU, nullptr, &numDeviceExtensions, deviceExtensions.data())) error("vkEnumerateDeviceExtensionProperties failed!"); // Search for swapchain extension for (VkExtensionProperties extension : deviceExtensions) { if (!strcmp(extension.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) extensionSwapChainFound = true; } // Print std::cout << std::endl << "Extensions:" << std::endl; for (VkExtensionProperties extension : deviceExtensions) { std::cout << extension.extensionName << "(" << extension.specVersion << ")" << std::endl; } std::cout << std::endl; } if (!extensionSwapChainFound) error("Failed to find the " VK_KHR_SWAPCHAIN_EXTENSION_NAME " extension!"); } // TODO: Validate // Get instance function adresses { GET_INSTANCE_PROC_ADDR(g_vkInstance, GetPhysicalDeviceSurfaceCapabilitiesKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, GetPhysicalDeviceSurfaceFormatsKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, GetPhysicalDeviceSurfacePresentModesKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, GetPhysicalDeviceSurfaceSupportKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, CreateSwapchainKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, DestroySwapchainKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, GetSwapchainImagesKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, AcquireNextImageKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, QueuePresentKHR); } // Create window { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); g_window = glfwCreateWindow(g_width, g_height, "Vulkan test", NULL, NULL); if (!g_window) error("Could not create window!"); glfwSetWindowRefreshCallback(g_window, [](GLFWwindow* window) { // TODO: draw(); }); glfwSetFramebufferSizeCallback(g_window, [](GLFWwindow* window, int width, int height) { g_width = width; g_height = height; // TODO: resize(); }); } // Init swapchain { glfwCreateWindowSurface(g_vkInstance, g_window, nullptr, &g_vkSurface); std::vector<VkBool32> supportsPresent(g_vkQueueProperties.size()); for (uint32_t i = 0; i < g_vkQueueProperties.size(); ++i) g_vkFPGetPhysicalDeviceSurfaceSupportKHR(g_vkGPU, i, g_vkSurface, &supportsPresent[i]); uint32_t graphicsQueueNodeIndex = UINT32_MAX; uint32_t presentQueueNodeIndex = UINT32_MAX; for (uint32_t i = 0; i < g_vkQueueProperties.size(); ++i) { if (graphicsQueueNodeIndex == UINT32_MAX) { graphicsQueueNodeIndex = i; } if (supportsPresent[i] == VK_TRUE) { graphicsQueueNodeIndex = i; presentQueueNodeIndex = i; break; } } //if (presentQueueNodeIndex == UINT32_MAX) { // for (uint32_t i = 0; i < g_vkQueueProperties.size(); ++i) { // if (supportsPresent[i] == VK_TRUE) { // presentQueueNodeIndex = i; // } // } //} if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX) error("Could not find a graphics and a present queue."); if (graphicsQueueNodeIndex != presentQueueNodeIndex) error("Could not find a common graphics and present queue."); g_vkGraphicsQueueNodeIndex = graphicsQueueNodeIndex; //TODO: init device { float queuePriotities = 0.f; VkDeviceQueueCreateInfo queue; { queue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue.pNext = NULL; queue.queueFamilyIndex = g_vkGraphicsQueueNodeIndex; queue.queueCount = 1; queue.pQueuePriorities = &queuePriotities; } } //vkGetDeviceQueue(g_vkDevice, g_vkGraphicsQueueNodeIndex, 0, g_vkQueue); } std::cin.get(); return 0; }
int main() { //Настроем вывод. setlocale(LC_ALL, "Russian"); //Подготовим данные приложения VkApplicationInfo app_info; memset(&app_info, 0, sizeof(app_info)); app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.pApplicationName = app_name; #ifdef VK_API_VERSION_1_0 app_info.apiVersion = VK_API_VERSION_1_0; #else app_info.apiVersion = VK_API_VERSION; #endif app_info.applicationVersion = VK_MAKE_VERSION(0, 1, 25); VkResult res; //заранее подготовим переменную для результата, она нам понадобится несколько раз. //Данные экземпляра VkInstanceCreateInfo instance_info; memset(&instance_info, 0, sizeof(instance_info)); instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instance_info.pApplicationInfo = &app_info; uint32_t available_instance_layer_count = 0; //узнаём кол-во установленных слоёв. res = vkEnumerateInstanceLayerProperties(&available_instance_layer_count, nullptr); if (res != VK_SUCCESS) { std::wcout << "Не удалось получить кол-во слоёв.\n"; return -1; } //настраиваем массив std::vector<VkLayerProperties> available_instance_layers(available_instance_layer_count); //Получаем слои res = vkEnumerateInstanceLayerProperties(&available_instance_layer_count, available_instance_layers.data()); if (available_instance_layer_count) { //А теперь выводим на экран. std::wcout << L"\n\nСлои экземпляра:\n"; for (uint32_t i = 0; i < available_instance_layer_count; i++) { VkLayerProperties &properties = available_instance_layers[i]; std::cout << properties.layerName << (strlen(properties.layerName) < 24 ? "\t" : "") << (strlen(properties.layerName) < 32 ? "\t" : "") << "\t|" << properties.description << "\n"; } } std::cout << "\n\n"; std::vector<const char *> instance_layers; instance_layers.push_back("VK_LAYER_LUNARG_standard_validation"); //И затем отправим их в стурктуру с информацией. instance_info.enabledLayerCount = instance_layers.size(); instance_info.ppEnabledLayerNames = instance_layers.data(); //Кол-во расширений. uint32_t available_instance_extension_count = 0; //Забираем кол-во расширений. res = vkEnumerateInstanceExtensionProperties(NULL, &available_instance_extension_count, nullptr); if (res != VK_SUCCESS) //Проверка { std::wcout << "Не удалось получить кол-во расширений.\n"; return -1; } //настраиваем массив std::vector<VkExtensionProperties> available_instance_extensions(available_instance_extension_count); //Получаем расширения res = vkEnumerateInstanceExtensionProperties(NULL, &available_instance_extension_count, available_instance_extensions.data()); if (available_instance_extension_count) { //Вывод на экран. std::wcout << L"\n\nРасширения экземпляра:\n"; for (uint32_t i = 0; i < available_instance_extensions.size(); i++) { VkExtensionProperties &properties = available_instance_extensions[i]; std::cout << properties.extensionName << "\n"; } std::cout << "\n\n"; } //Настройка расширений std::vector<const char *> instance_extensions; instance_extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); instance_info.enabledExtensionCount = instance_extensions.size(); instance_info.ppEnabledExtensionNames = instance_extensions.data(); VkInstance instance = VK_NULL_HANDLE; res = vkCreateInstance(&instance_info, NULL, &instance); if (res != VK_SUCCESS) //С проверками особо заморачиваться не будем. { std::wcerr << L"Что-то не так...\n"; return -1; } else std::wcout << L"Экземпляр Vulkan создан.\n"; //Создадим указатели на функции таким образом. PFN_vkCreateDebugReportCallbackEXT fvkCreateDebugReportCallbackEXT = NULL; PFN_vkDestroyDebugReportCallbackEXT fvkDestroyDebugReportCallbackEXT = NULL; //И получим их. fvkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"); fvkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT"); /* Отлично, мы получили эти функции! Теперь, нам нужно подготовить информацию для callback'ов, а также * оставить хэндл, который мы конечно же потом уничтожим. */ //Структура, которую мы должны заполнить VkDebugReportCallbackCreateInfoEXT debug_report_callback_info; memset(&debug_report_callback_info, 0, sizeof(debug_report_callback_info)); debug_report_callback_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; debug_report_callback_info.flags = VK_DEBUG_REPORT_DEBUG_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT; // Настало время прикрепить наш прототип здесь: debug_report_callback_info.pfnCallback = DebugReportCallback; VkDebugReportCallbackEXT debug_report_callback = VK_NULL_HANDLE; //И наконец-таки привзяываем наш Callback: res = fvkCreateDebugReportCallbackEXT(instance, &debug_report_callback_info, NULL, &debug_report_callback); if (res != VK_SUCCESS) { std::wcerr << L"Не удалось создать debug-report callback.\n"; return -1; } std::vector<VkPhysicalDevice> gpu_list; //здесь будем хранить физические устройства. uint32_t gpu_count; //кол-во девайсов //получаем колв-о девайсов и сразу проверяем на удачу. if (vkEnumeratePhysicalDevices(instance, &gpu_count, VK_NULL_HANDLE) != VK_SUCCESS) { std::wcerr << L"Посчитать физические устройства не удалось :(\n"; return -1; } gpu_list.resize(gpu_count); //заранее изменим размер под самый оптимальный. //Забираем физические девайсы if (vkEnumeratePhysicalDevices(instance, &gpu_count, gpu_list.data()) != VK_SUCCESS) { std::wcerr << L"Заполучить твои физические устройства не удалось, но я приду за ними в следующий раз!\n"; return -1; } //Выбираем видеокарту VkPhysicalDevice gpu = gpu_list[0]; //Теперь, семейства. uint32_t family_count = 0; //кол-во семейтсв vkGetPhysicalDeviceQueueFamilyProperties(gpu, &family_count, nullptr); std::vector<VkQueueFamilyProperties> family_properties_list(family_count); vkGetPhysicalDeviceQueueFamilyProperties(gpu, &family_count, family_properties_list.data()); //Листаем семейтсва и получаем нужное. uint32_t valid_family_index = (uint32_t) -1; //значение -1 будем использовать как "не найдено, 404". for (uint32_t i = 0; i < family_count; i++) //листаем все семейства. { VkQueueFamilyProperties &properties = family_properties_list[i]; if (properties.queueFlags & VK_QUEUE_GRAPHICS_BIT) { if (valid_family_index == (uint32_t) -1) valid_family_index = i; } } //И если наш индекс всё ещё не перезаписан, то.. if (valid_family_index == (uint32_t) -1) return -1; //Описываем очереди. VkDeviceQueueCreateInfo device_queue_info; memset(&device_queue_info, 0, sizeof(device_queue_info)); device_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; float device_queue_priority[] = {1.0f}; device_queue_info.queueCount = 1; device_queue_info.queueFamilyIndex = valid_family_index; device_queue_info.pQueuePriorities = device_queue_priority; VkDeviceCreateInfo device_info; memset(&device_info, 0, sizeof(device_info)); device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_info.queueCreateInfoCount = 1; device_info.pQueueCreateInfos = &device_queue_info; uint32_t available_device_layer_count = 0; res = vkEnumerateDeviceLayerProperties(gpu, &available_device_layer_count, VK_NULL_HANDLE); if (res != VK_SUCCESS) { std::wcout << "Не удалось получить кол-во слоёв.\n"; return -1; } //настраиваем массив std::vector<VkLayerProperties> available_device_layers(available_device_layer_count); res = vkEnumerateDeviceLayerProperties(gpu, &available_device_layer_count, available_device_layers.data()); if (res != VK_SUCCESS) { std::wcout << "Не удалось получить слои.\n"; return -1; } if (available_device_layer_count) { //А теперь выводим на экран. std::wcout << L"\n\nСлои устройства:\n"; for (uint32_t i = 0; i < available_device_layer_count; i++) { //Сделаем красивый вывод для имени и описания слоя. VkLayerProperties &properties = available_device_layers[i]; std::cout << properties.layerName << (strlen(properties.layerName) < 24 ? "\t" : "") << (strlen(properties.layerName) < 32 ? "\t" : "") << "\t|" << properties.description << "\n"; } } std::cout << "\n\n"; //Кол-во расширений. uint32_t available_device_extension_count = 0; //Забираем кол-во расширений. res = vkEnumerateDeviceExtensionProperties(gpu, NULL, &available_device_extension_count, VK_NULL_HANDLE); if (res != VK_SUCCESS) //Проверка { std::wcout << "Не удалось получить кол-во расширений.\n"; return -1; } //настраиваем массив std::vector<VkExtensionProperties> available_device_extensions(available_device_extension_count); //Получаем расширения res = vkEnumerateDeviceExtensionProperties(gpu, NULL, &available_device_extension_count, available_device_extensions.data()); if (available_device_extension_count) { //Вывод на экран. std::wcout << L"\n\nРасширения устройства:\n"; for (uint32_t i = 0; i < available_device_extensions.size(); i++) { VkExtensionProperties &properties = available_device_extensions[i]; std::cout << properties.extensionName << "\n"; } std::cout << "\n\n"; } std::vector<const char *> device_layers = instance_layers; //Расширения и слои device_info.enabledLayerCount = device_layers.size(); device_info.ppEnabledLayerNames = device_layers.data(); //А расширения устройства оставим и на сей раз пустым. std::vector<const char *> device_extensions; device_info.enabledExtensionCount = device_extensions.size(); device_info.ppEnabledExtensionNames = device_extensions.data(); VkDevice device = VK_NULL_HANDLE; if (vkCreateDevice(gpu, &device_info, NULL, &device) != VK_SUCCESS) return -1; vkDestroyDevice(device, NULL); fvkDestroyDebugReportCallbackEXT(instance, debug_report_callback, NULL); vkDestroyInstance(instance, NULL); std::wcout << L"Пожарено!\n"; return 0; }
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; } }