void Renderer::checkDeviceProperties(VkPhysicalDevice gpu) { VkPhysicalDeviceProperties properties; VkPhysicalDeviceFeatures features; vkGetPhysicalDeviceProperties(gpu, &properties); vkGetPhysicalDeviceFeatures(gpu, &features); printf("%s\n", properties.deviceName); printf("Vulkan Version: %d.%d.%d\n", VK_VERSION_MAJOR(properties.apiVersion), VK_VERSION_MINOR(properties.apiVersion), VK_VERSION_PATCH(properties.apiVersion)); printf("Driver Version: %d.%d.%d\n\n", VK_VERSION_MAJOR(properties.driverVersion), VK_VERSION_MINOR(properties.driverVersion), VK_VERSION_PATCH(properties.driverVersion)); }
bool Tutorial01::CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &queue_family_index ) { 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 ); uint32_t minor_version = VK_VERSION_MINOR( device_properties.apiVersion ); uint32_t patch_version = VK_VERSION_PATCH( 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 ); vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, queue_family_properties.data() ); for( uint32_t i = 0; i < queue_families_count; ++i ) { if( (queue_family_properties[i].queueCount > 0) && (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) ) { queue_family_index = i; std::cout << "Selected device: " << device_properties.deviceName << std::endl; return true; } } std::cout << "Could not find queue family with required properties on physical device " << physical_device << "!" << std::endl; return false; }
void vulkan_choose_physical_device(ReaperRoot& root, VulkanBackend& backend, PhysicalDeviceInfo& physicalDeviceInfo) { uint32_t deviceCount = 0; Assert(vkEnumeratePhysicalDevices(backend.instance, &deviceCount, nullptr) == VK_SUCCESS); Assert(deviceCount > 0); log_debug(root, "vulkan: enumerating {} physical devices", deviceCount); std::vector<VkPhysicalDevice> availableDevices(deviceCount); Assert(vkEnumeratePhysicalDevices(backend.instance, &deviceCount, &availableDevices[0]) == VK_SUCCESS, "error occurred during physical devices enumeration"); uint32_t selected_queue_family_index = UINT32_MAX; uint32_t selected_present_queue_family_index = UINT32_MAX; // Duplicated two times TODO merge std::vector<const char*> extensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; VkPhysicalDevice chosenPhysicalDevice = VK_NULL_HANDLE; for (auto& device : availableDevices) { if (vulkan_check_physical_device(root.renderer->window, device, backend.presentInfo.surface, extensions, selected_queue_family_index, selected_present_queue_family_index)) { chosenPhysicalDevice = device; break; } } Assert(chosenPhysicalDevice != VK_NULL_HANDLE, "could not select physical device based on the chosen properties"); physicalDeviceInfo.graphicsQueueIndex = selected_queue_family_index; physicalDeviceInfo.presentQueueIndex = selected_present_queue_family_index; vkGetPhysicalDeviceMemoryProperties(chosenPhysicalDevice, &physicalDeviceInfo.memory); // re-fetch device infos TODO avoid VkPhysicalDeviceProperties physicalDeviceProperties; vkGetPhysicalDeviceProperties(chosenPhysicalDevice, &physicalDeviceProperties); log_info(root, "vulkan: selecting device '{}'", physicalDeviceProperties.deviceName); log_debug(root, "- type = {}", vulkan_physical_device_type_name(physicalDeviceProperties.deviceType)); uint32_t apiVersion = physicalDeviceProperties.apiVersion; uint32_t driverVersion = physicalDeviceProperties.driverVersion; log_debug(root, "- api version = {}.{}.{}", VK_VERSION_MAJOR(apiVersion), VK_VERSION_MINOR(apiVersion), VK_VERSION_PATCH(apiVersion)); log_debug(root, "- driver version = {}.{}.{}", VK_VERSION_MAJOR(driverVersion), VK_VERSION_MINOR(driverVersion), VK_VERSION_PATCH(driverVersion)); log_debug(root, "- memory type count = {}, memory heap count = {}", physicalDeviceInfo.memory.memoryTypeCount, physicalDeviceInfo.memory.memoryHeapCount); for (u32 i = 0; i < physicalDeviceInfo.memory.memoryHeapCount; ++i) { VkMemoryHeap& heap = physicalDeviceInfo.memory.memoryHeaps[i]; log_debug(root, "- heap {}: available size = {}, flags = {}", i, heap.size, heap.flags); } backend.physicalDevice = chosenPhysicalDevice; }
VkResult init_Vulkan(VkInstance& vk_instance, VkDevice* out_device, DrawCommandBuffer* out_draw_command_buffer, SwapChain* out_swap_chain) { if ((out_device == nullptr) || (out_swap_chain == nullptr)) { return VK_ERROR_INITIALIZATION_FAILED; } VkApplicationInfo app_info = {}; app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.pNext = nullptr; app_info.pApplicationName = "VT Test"; app_info.applicationVersion = 0x00000001; app_info.pEngineName = "Noengine"; app_info.engineVersion = 0x00; app_info.apiVersion = VK_MAKE_VERSION(1, 0, 2); std::vector<const char *> enabledExtensions = { VK_KHR_SURFACE_EXTENSION_NAME }; enabledExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); VkInstanceCreateInfo instance_info = {}; instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instance_info.pNext = nullptr; instance_info.flags = 0; instance_info.pApplicationInfo = &app_info; instance_info.enabledLayerCount = 0; instance_info.ppEnabledLayerNames = nullptr; instance_info.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size()); instance_info.ppEnabledExtensionNames = enabledExtensions.data(); VK_THROW(vkCreateInstance(&instance_info, nullptr, &vk_instance)); // Create Vulkan library instance out_swap_chain->instance = GetModuleHandle(NULL); out_swap_chain->window = setup_window(out_swap_chain->instance, 800, 600, "vk_test"); uint32_t gpu_count = 0; // Get number of available physical devices VK_THROW(vkEnumeratePhysicalDevices(vk_instance, &gpu_count, nullptr)); assert(gpu_count > 0); std::vector<VkPhysicalDevice> physicalDevices(gpu_count); // Enumerate devices VK_THROW(vkEnumeratePhysicalDevices(vk_instance, &gpu_count, physicalDevices.data())); bool surface_created = false; VkPhysicalDeviceProperties gpu_properties; VkPhysicalDeviceFeatures gpu_feature; for (uint32_t gidx = 0; gidx < gpu_count; ++gidx) { VkPhysicalDevice gpu = physicalDevices[gidx]; vkGetPhysicalDeviceProperties(gpu, &gpu_properties); std::cout << gidx << "Driver Version: " << gpu_properties.driverVersion << "\n"; std::cout << gidx << "Device Name: " << gpu_properties.deviceName << "\n"; std::cout << gidx << "Device Type: " << gpu_properties.deviceType << "\n"; std::cout << gidx << "API Version: " << VK_VERSION_MAJOR(gpu_properties.apiVersion) << "." << VK_VERSION_MINOR(gpu_properties.apiVersion) << "." << VK_VERSION_PATCH(gpu_properties.apiVersion) << "\n"; // we can choose a gpu based on the features here. vkGetPhysicalDeviceFeatures(gpu, &gpu_feature); VkResult err = create_surface(vk_instance, gpu, out_device, out_draw_command_buffer, out_swap_chain); if (err == VK_SUCCESS) { surface_created = true; break; } } if (!surface_created) { return VK_ERROR_INITIALIZATION_FAILED; } return VK_SUCCESS; }
bool initialize(android_app* app) { // Load Android vulkan and retrieve vulkan API function pointers if (!InitVulkan()) { LOGE("Vulkan is unavailable, install vulkan and re-start"); return false; } VkApplicationInfo appInfo = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pNext = nullptr, .apiVersion = VK_MAKE_VERSION(1, 0, 0), .applicationVersion = VK_MAKE_VERSION(1, 0, 0), .engineVersion = VK_MAKE_VERSION(1, 0, 0), .pApplicationName = "tutorial01_load_vulkan", .pEngineName = "tutorial", }; // prepare necessary extensions: Vulkan on Android need these to function std::vector<const char *> instanceExt, deviceExt; instanceExt.push_back("VK_KHR_surface"); instanceExt.push_back("VK_KHR_android_surface"); deviceExt.push_back("VK_KHR_swapchain"); // Create the Vulkan instance VkInstanceCreateInfo instanceCreateInfo { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pNext = nullptr, .pApplicationInfo = &appInfo, .enabledExtensionCount = static_cast<uint32_t>(instanceExt.size()), .ppEnabledExtensionNames = instanceExt.data(), .enabledLayerCount = 0, .ppEnabledLayerNames = nullptr, }; CALL_VK(vkCreateInstance(&instanceCreateInfo, nullptr, &tutorialInstance)); // if we create a surface, we need the surface extension VkAndroidSurfaceCreateInfoKHR createInfo { .sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, .pNext = nullptr, .flags = 0, .window = app->window }; CALL_VK(vkCreateAndroidSurfaceKHR(tutorialInstance, &createInfo, nullptr, &tutorialSurface)); // Find one GPU to use: // On Android, every GPU device is equal -- supporting graphics/compute/present // for this sample, we use the very first GPU device found on the system uint32_t gpuCount = 0; CALL_VK(vkEnumeratePhysicalDevices(tutorialInstance, &gpuCount, nullptr)); VkPhysicalDevice tmpGpus[gpuCount]; CALL_VK(vkEnumeratePhysicalDevices(tutorialInstance, &gpuCount, tmpGpus)); tutorialGpu = tmpGpus[0]; // Pick up the first GPU Device // check for vulkan info on this GPU device VkPhysicalDeviceProperties gpuProperties; vkGetPhysicalDeviceProperties(tutorialGpu, &gpuProperties); LOGI("Vulkan Physical Device Name: %s", gpuProperties.deviceName); LOGI("Vulkan Physical Device Info: apiVersion: %x \n\t driverVersion: %x", gpuProperties.apiVersion, gpuProperties.driverVersion); LOGI("API Version Supported: %d.%d.%d", VK_VERSION_MAJOR(gpuProperties.apiVersion), VK_VERSION_MINOR(gpuProperties.apiVersion), VK_VERSION_PATCH(gpuProperties.apiVersion)); VkSurfaceCapabilitiesKHR surfaceCapabilities; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(tutorialGpu, tutorialSurface, &surfaceCapabilities); LOGI("Vulkan Surface Capabilities:\n"); LOGI("\timage count: %u - %u\n", surfaceCapabilities.minImageCount, surfaceCapabilities.maxImageCount); LOGI("\tarray layers: %u\n", surfaceCapabilities.maxImageArrayLayers); LOGI("\timage size (now): %dx%d\n", surfaceCapabilities.currentExtent.width, surfaceCapabilities.currentExtent.height); LOGI("\timage size (extent): %dx%d - %dx%d\n", surfaceCapabilities.minImageExtent.width, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.width, surfaceCapabilities.maxImageExtent.height); LOGI("\tusage: %x\n", surfaceCapabilities.supportedUsageFlags); LOGI("\tcurrent transform: %u\n", surfaceCapabilities.currentTransform); LOGI("\tallowed transforms: %x\n", surfaceCapabilities.supportedTransforms); LOGI("\tcomposite alpha flags: %u\n", surfaceCapabilities.currentTransform); // Create a logical device from GPU we picked float priorities[] = { 1.0f, }; VkDeviceQueueCreateInfo queueCreateInfo { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, .pNext = nullptr, .flags = 0, .queueCount = 1, .queueFamilyIndex = 0, .pQueuePriorities = priorities, }; VkDeviceCreateInfo deviceCreateInfo { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = nullptr, .queueCreateInfoCount = 1, .pQueueCreateInfos = &queueCreateInfo, .enabledLayerCount = 0, .ppEnabledLayerNames = nullptr, .enabledExtensionCount = static_cast<uint32_t>(deviceExt.size()), .ppEnabledExtensionNames = deviceExt.data(), .pEnabledFeatures = nullptr, }; CALL_VK(vkCreateDevice(tutorialGpu, &deviceCreateInfo, nullptr, &tutorialDevice)); initialized_ = true; return 0; } void terminate() { vkDestroySurfaceKHR(tutorialInstance, tutorialSurface, nullptr); vkDestroyDevice(tutorialDevice, nullptr); vkDestroyInstance(tutorialInstance, nullptr); initialized_ = false; } // Process the next main command. void handle_cmd(android_app* app, int32_t cmd) { switch (cmd) { case APP_CMD_INIT_WINDOW: // The window is being shown, get it ready. initialize(app); break; case APP_CMD_TERM_WINDOW: // The window is being hidden or closed, clean it up. terminate(); break; default: LOGI("event not handled: %d", cmd); } }
void SetupDevice() { // Query how many devices are present in the system uint32_t deviceCount = 0; VkResult result; if( !vl.instance ) SetupInstance(); result = vkEnumeratePhysicalDevices( vl.instance, &deviceCount, NULL ); if( result != VK_SUCCESS ) { fprintf( stderr, "Failed to query the number of physical devices present: %d", result ); abort(); } // There has to be at least one device present if( deviceCount == 0 ) { fprintf( stderr, "Couldn't detect any device present with Vulkan support: %d", result ); abort(); } // Get the physical devices vl.physicalDevices = NewArray( VkPhysicalDevice, deviceCount ); result = vkEnumeratePhysicalDevices( vl.instance, &deviceCount, vl.physicalDevices ); if( result != VK_SUCCESS ) { fprintf( stderr, "Faied to enumerate physical devices present: %d", result ); abort(); } { // Enumerate all physical devices VkPhysicalDeviceProperties deviceProperties; uint32_t i; for( i = 0; i < deviceCount; i++ ) { memset( &deviceProperties, 0, sizeof deviceProperties ); vkGetPhysicalDeviceProperties( vl.physicalDevices[i], &deviceProperties ); lprintf( "Driver Version: %d", deviceProperties.driverVersion ); lprintf( "Device Name: %s", deviceProperties.deviceName ); lprintf( "Device Type: %d", deviceProperties.deviceType ); lprintf( "API Version: %d.%d.%d" // See note below regarding this: , VK_VERSION_MAJOR( deviceProperties.apiVersion ) , VK_VERSION_MINOR( deviceProperties.apiVersion ) , VK_VERSION_PATCH( deviceProperties.apiVersion ) ); { uint32_t queueFamilyCount = 0; uint32_t i , j; VkQueueFamilyProperties *familyProperties; vkGetPhysicalDeviceQueueFamilyProperties( vl.physicalDevices[i], &queueFamilyCount, NULL ); familyProperties = NewArray( VkQueueFamilyProperties, (queueFamilyCount) ); vkGetPhysicalDeviceQueueFamilyProperties( vl.physicalDevices[i], &queueFamilyCount, familyProperties ); // Print the families for( i = 0; i < deviceCount; i++ ) { for( j = 0; j < queueFamilyCount; j++ ) { printf( "Count of Queues: %d", familyProperties[j].queueCount ); printf( "Supported operationg on this queue:" ); if( familyProperties[j].queueFlags & VK_QUEUE_GRAPHICS_BIT ) lprintf( "\t\t Graphics" ); if( familyProperties[j].queueFlags & VK_QUEUE_COMPUTE_BIT ) lprintf( "\t\t Compute" ); if( familyProperties[j].queueFlags & VK_QUEUE_TRANSFER_BIT ) lprintf( "\t\t Transfer" ); if( familyProperties[j].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT ) lprintf( "\t\t Sparse Binding" ); } } } } } }
int sample_main(int argc, char *argv[]) { struct sample_info info = {}; init_global_layer_properties(info); // Android build not at 1.1 yet #ifndef ANDROID /* VULKAN_KEY_START */ // Keep track of the major/minor version we can actually use uint16_t using_major_version = 1; uint16_t using_minor_version = 0; std::string using_version_string = ""; // Set the desired version we want uint16_t desired_major_version = 1; uint16_t desired_minor_version = 1; uint32_t desired_version = VK_MAKE_VERSION(desired_major_version, desired_minor_version, 0); std::string desired_version_string = ""; desired_version_string += std::to_string(desired_major_version); desired_version_string += "."; desired_version_string += std::to_string(desired_minor_version); VkInstance instance = VK_NULL_HANDLE; std::vector<VkPhysicalDevice> physical_devices_desired; // Determine what API version is available uint32_t api_version; if (VK_SUCCESS == vkEnumerateInstanceVersion(&api_version)) { // Translate the version into major/minor for easier comparison uint32_t loader_major_version = VK_VERSION_MAJOR(api_version); uint32_t loader_minor_version = VK_VERSION_MINOR(api_version); std::cout << "Loader/Runtime support detected for Vulkan " << loader_major_version << "." << loader_minor_version << "\n"; // Check current version against what we want to run if (loader_major_version > desired_major_version || (loader_major_version == desired_major_version && loader_minor_version >= desired_minor_version)) { // Initialize the VkApplicationInfo structure with the version of the API we're intending to use VkApplicationInfo app_info = {}; app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.pNext = NULL; app_info.pApplicationName = APP_SHORT_NAME; app_info.applicationVersion = 1; app_info.pEngineName = APP_SHORT_NAME; app_info.engineVersion = 1; app_info.apiVersion = desired_version; // Initialize the VkInstanceCreateInfo structure VkInstanceCreateInfo inst_info = {}; inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; inst_info.pNext = NULL; inst_info.flags = 0; inst_info.pApplicationInfo = &app_info; inst_info.enabledExtensionCount = 0; inst_info.ppEnabledExtensionNames = NULL; inst_info.enabledLayerCount = 0; inst_info.ppEnabledLayerNames = NULL; // Attempt to create the instance if (VK_SUCCESS != vkCreateInstance(&inst_info, NULL, &instance)) { std::cout << "Unknown error creating " << desired_version_string << " Instance\n"; exit(-1); } // Get the list of physical devices uint32_t phys_dev_count = 1; if (VK_SUCCESS != vkEnumeratePhysicalDevices(instance, &phys_dev_count, NULL) || phys_dev_count == 0) { std::cout << "Failed searching for Vulkan physical devices\n"; exit(-1); } std::vector<VkPhysicalDevice> physical_devices; physical_devices.resize(phys_dev_count); if (VK_SUCCESS != vkEnumeratePhysicalDevices(instance, &phys_dev_count, physical_devices.data()) || phys_dev_count == 0) { std::cout << "Failed enumerating Vulkan physical devices\n"; exit(-1); } // Go through the list of physical devices and select only those that are capable of running the API version we want. for (uint32_t dev = 0; dev < physical_devices.size(); ++dev) { VkPhysicalDeviceProperties physical_device_props = {}; vkGetPhysicalDeviceProperties(physical_devices[dev], &physical_device_props); if (physical_device_props.apiVersion >= desired_version) { physical_devices_desired.push_back(physical_devices[dev]); } } // If we have something in the desired version physical device list, we're good if (physical_devices_desired.size() > 0) { using_major_version = desired_major_version; using_minor_version = desired_minor_version; } } } using_version_string += std::to_string(using_major_version); using_version_string += "."; using_version_string += std::to_string(using_minor_version); if (using_minor_version < desired_minor_version) { std::cout << "Determined that this system can only use Vulkan API version " << using_version_string << " instead of desired version " << desired_version_string << std::endl; } else { std::cout << "Determined that this system can run desired Vulkan API version " << desired_version_string << std::endl; } // Destroy the instance if it was created if (VK_NULL_HANDLE == instance) { vkDestroyInstance(instance, NULL); } #endif /* VULKAN_KEY_END */ return 0; }