bool VulkanCommon::CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &selected_graphics_queue_family_index, uint32_t &selected_present_queue_family_index ) { uint32_t extensions_count = 0; if( (vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, nullptr ) != VK_SUCCESS) || (extensions_count == 0) ) { std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; return false; } std::vector<VkExtensionProperties> available_extensions( extensions_count ); if( vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, &available_extensions[0] ) != VK_SUCCESS ) { std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; return false; } std::vector<const char*> device_extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; for( size_t i = 0; i < device_extensions.size(); ++i ) { if( !CheckExtensionAvailability( device_extensions[i], available_extensions ) ) { std::cout << "Physical device " << physical_device << " doesn't support extension named \"" << device_extensions[i] << "\"!" << std::endl; return false; } } VkPhysicalDeviceProperties device_properties; VkPhysicalDeviceFeatures device_features; vkGetPhysicalDeviceProperties( physical_device, &device_properties ); vkGetPhysicalDeviceFeatures( physical_device, &device_features ); uint32_t major_version = VK_VERSION_MAJOR( device_properties.apiVersion ); if( (major_version < 1) && (device_properties.limits.maxImageDimension2D < 4096) ) { std::cout << "Physical device " << physical_device << " doesn't support required parameters!" << std::endl; return false; } uint32_t queue_families_count = 0; vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, nullptr ); if( queue_families_count == 0 ) { std::cout << "Physical device " << physical_device << " doesn't have any queue families!" << std::endl; return false; } std::vector<VkQueueFamilyProperties> queue_family_properties( queue_families_count ); std::vector<VkBool32> queue_present_support( queue_families_count ); vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, &queue_family_properties[0] ); uint32_t graphics_queue_family_index = UINT32_MAX; uint32_t present_queue_family_index = UINT32_MAX; for( uint32_t i = 0; i < queue_families_count; ++i ) { vkGetPhysicalDeviceSurfaceSupportKHR( physical_device, i, Vulkan.PresentationSurface, &queue_present_support[i] ); if( (queue_family_properties[i].queueCount > 0) && (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) ) { // Select first queue that supports graphics if( graphics_queue_family_index == UINT32_MAX ) { graphics_queue_family_index = i; } // If there is queue that supports both graphics and present - prefer it if( queue_present_support[i] ) { selected_graphics_queue_family_index = i; selected_present_queue_family_index = i; return true; } } } // We don't have queue that supports both graphics and present so we have to use separate queues for( uint32_t i = 0; i < queue_families_count; ++i ) { if( queue_present_support[i] ) { present_queue_family_index = i; break; } } // If this device doesn't support queues with graphics and present capabilities don't use it if( (graphics_queue_family_index == UINT32_MAX) || (present_queue_family_index == UINT32_MAX) ) { std::cout << "Could not find queue families with required properties on physical device " << physical_device << "!" << std::endl; return false; } selected_graphics_queue_family_index = graphics_queue_family_index; selected_present_queue_family_index = present_queue_family_index; return true; }
int vk_init(){ unsigned int i; unsigned int qi = 0; unsigned int qc = 0; VkResult res; VkApplicationInfo ainfo = {0}; VkInstanceCreateInfo iinfo = {0}; ainfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; ainfo.pApplicationName = "enaengine"; ainfo.pEngineName = "enaengine"; ainfo.apiVersion = VK_API_VERSION; iinfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; iinfo.pApplicationInfo = &ainfo; iinfo.enabledExtensionCount = NUMEXT; iinfo.ppEnabledExtensionNames = ext; // iinfo.enabledExtensionCount = glfw_extensions_count; // iinfo.ppEnabledExtensionNames = glfw_extensions; res = vkCreateInstance(&iinfo, NULL, &vkinstance); if(res){ //TODO ERROR return FALSE; } res = vkEnumeratePhysicalDevices(vkinstance, &vkdevices_count, 0); if(vkdevices_count < 1 || res){ //TODO ERROR return FALSE; } vkdevices = malloc(vkdevices_count * sizeof(VkPhysicalDevice)); res = vkEnumeratePhysicalDevices(vkinstance, &vkdevices_count, vkdevices); if(res){ //TODO ERROR return FALSE; } //find first dev with graphics capabilities for(i = 0; i < vkdevices_count; i++){ vkactivedevice = vkdevices[i]; qc = 0; vkGetPhysicalDeviceQueueFamilyProperties(vkactivedevice, &qc, NULL); if(!qc) continue; vkdevicesqp = malloc(qc * sizeof(VkQueueFamilyProperties)); vkGetPhysicalDeviceQueueFamilyProperties(vkactivedevice, &qc, vkdevicesqp); for(qi = 0; qi < qc; qi++){ if(vkdevicesqp[qi].queueFlags & VK_QUEUE_GRAPHICS_BIT) break; } if(qi != qc) break; if(vkdevicesqp) free(vkdevicesqp); vkdevicesqp = 0; } //didnt find one if(i == vkdevices_count){ return FALSE; } //create dev (finally) float qp[] = {0.0f}; VkDeviceQueueCreateInfo qci = {0}; qci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; qci.queueFamilyIndex = qi; qci.queueCount = 1; qci.pQueuePriorities = qp; VkDeviceCreateInfo dci = {0}; dci.queueCreateInfoCount = 1; dci.pQueueCreateInfos = &qci; dci.enabledExtensionCount = NUMEXT2; dci.ppEnabledExtensionNames = ext2; res = vkCreateDevice(vkactivedevice, &dci, 0, &vkdevice); if(res){ //TODO error return FALSE; } vkGetPhysicalDeviceProperties(vkactivedevice, &vkdeviceprop); vkGetPhysicalDeviceFeatures(vkactivedevice, &vkdevicefeat); return TRUE; }
VkPhysicalDeviceFeatures PhysicalDevice::features() const { VkPhysicalDeviceFeatures features; vkGetPhysicalDeviceFeatures(handle(), &features); return features; }
Error GrManagerImpl::initInstance(const GrManagerInitInfo& init) { // Create the instance // static Array<const char*, 8> LAYERS = {{"VK_LAYER_LUNARG_core_validation", "VK_LAYER_LUNARG_swapchain", "VK_LAYER_LUNARG_image", "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_GOOGLE_unique_objects", "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_standard_validation"}}; static Array<const char*, 2> EXTENSIONS = {{VK_KHR_SURFACE_EXTENSION_NAME, #if ANKI_OS == ANKI_OS_LINUX VK_KHR_XCB_SURFACE_EXTENSION_NAME #elif ANKI_OS == ANKI_OS_WINDOWS VK_KHR_WIN32_SURFACE_EXTENSION_NAME #else #error TODO #endif }}; VkApplicationInfo app = {}; app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app.pApplicationName = "unamed"; app.applicationVersion = 1; app.pEngineName = "AnKi 3D Engine"; app.engineVersion = (ANKI_VERSION_MAJOR << 1) | ANKI_VERSION_MINOR; app.apiVersion = VK_MAKE_VERSION(1, 0, 3); VkInstanceCreateInfo ci = {}; ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; ci.pApplicationInfo = &app; if(init.m_config->getNumber("debugContext")) { ANKI_LOGI("VK: Will enable debug layers"); ci.enabledLayerCount = LAYERS.getSize(); ci.ppEnabledLayerNames = &LAYERS[0]; } ci.enabledExtensionCount = EXTENSIONS.getSize(); ci.ppEnabledExtensionNames = &EXTENSIONS[0]; #if ANKI_GR_MANAGER_DEBUG_MEMMORY VkAllocationCallbacks allocCbs = {}; VkAllocationCallbacks* pallocCbs = &allocCbs; allocCbs.pUserData = this; allocCbs.pfnAllocation = allocateCallback; allocCbs.pfnReallocation = reallocateCallback; allocCbs.pfnFree = freeCallback; #else VkAllocationCallbacks* pallocCbs = nullptr; #endif ANKI_VK_CHECK(vkCreateInstance(&ci, pallocCbs, &m_instance)); // Create the physical device // uint32_t count = 0; ANKI_VK_CHECK(vkEnumeratePhysicalDevices(m_instance, &count, nullptr)); ANKI_LOGI("VK: Number of physical devices: %u", count); if(count < 1) { ANKI_LOGE("Wrong number of physical devices"); return ErrorCode::FUNCTION_FAILED; } count = 1; ANKI_VK_CHECK(vkEnumeratePhysicalDevices(m_instance, &count, &m_physicalDevice)); vkGetPhysicalDeviceProperties(m_physicalDevice, &m_devProps); // Find vendor switch(m_devProps.vendorID) { case 0x13B5: m_vendor = GpuVendor::ARM; break; case 0x10DE: m_vendor = GpuVendor::NVIDIA; break; case 0x1002: case 0x1022: m_vendor = GpuVendor::AMD; break; } ANKI_LOGI("GPU vendor is %s", &GPU_VENDOR_STR[m_vendor][0]); vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_devFeatures); return ErrorCode::NONE; }
bool select_device(std::vector<VkPhysicalDevice> &devices, VkPhysicalDevice &chosen_device) { bool suitable_dev_found = false; unsigned int best_score = 0; for (const auto& device : devices) { unsigned int score = 0; VkPhysicalDeviceProperties deviceProperties; VkPhysicalDeviceFeatures deviceFeatures; vkGetPhysicalDeviceProperties(device, &deviceProperties); vkGetPhysicalDeviceFeatures(device, &deviceFeatures); if(deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU){score+= 1000;} if(!deviceFeatures.geometryShader){score-= 1000000;} uint32_t queueFamilyCount = 0; vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount); vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data()); /*checks that all the needed queue families are supported */ bool graphics_found = false, present_found = false; int i = 0; for(const auto& queueFamily : queueFamilies) { if (!graphics_found && queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { graphics_found = true; graphics_queue_family_index = i; } VkBool32 presentSupport = false; vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); if (!present_found && queueFamily.queueCount > 0 && presentSupport) { present_found = true; present_queue_family_index = i; } if(present_found && graphics_found){break;}//if it finds both there is no point in keeping looking for queue families i++; } if(!(graphics_found && present_found)){continue;}//if it didn't find both cues go to next device /*checking for device specific extnsions support*/ uint32_t extensionCount; vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); std::vector<VkExtensionProperties> availableExtensions(extensionCount); vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data()); std::set<std::string> requiredExtensions(device_extensions.begin(), device_extensions.end()); for (const auto& extension : availableExtensions) { requiredExtensions.erase(extension.extensionName); } if(!requiredExtensions.empty()){continue;} /*checks that swap chains are supported*/ bool swapChainAdequate = false; SwapChainSupportDetails swapChainSupport = query_swap_chain_support(device); swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty(); if(score >= best_score) { chosen_device = device; suitable_dev_found = true; best_score = score; } if(!swapChainAdequate){continue;} } return suitable_dev_found; //if no device is found }