对于一台包含多个物理GPU的主机,Vulkan程序可以选择其中一块GPU作为它的运行平台。Vulkan程序枚举当前主机所有的GPU设备,并检查这些设备的特性是否符合特定要求,比如,要求是物理GPU,要求支持geometryShader等各种Shader。这些都可以检测出来。
今天的程序为了简洁,我把上节启动校验层给禁止了,这个禁还是很简单的,只要加一句:#define NDEBUG 0 就可以了。另外还加入了下面一些变量和类函数。
//定义一个物理设备(GPU) VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; //加入一个pickPhysicalDevice函数,它负责枚举主机所有GPU,并选择一个基于GPU的且支持geometryShader的设备作为物理渲染设备 void pickPhysicalDevice() { uint32_t deviceCount = 0; vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); if (deviceCount == 0) { throw std::runtime_error("failed to find GPUs with Vulkan support!"); } std::vector<VkPhysicalDevice> devices(deviceCount); vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); std::cout<<"GPU Devices:"<<deviceCount<<"\n"; VkPhysicalDeviceProperties DeviceProperties; VkPhysicalDeviceFeatures DeviceFeatures; for (const auto& device : devices) { vkGetPhysicalDeviceProperties(device,&DeviceProperties); vkGetPhysicalDeviceFeatures(device,&DeviceFeatures); if(DeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && DeviceFeatures.geometryShader){ std::cout<<"Device Name:"<<DeviceProperties.deviceName<<"\n"; physicalDevice = device; break; } } if (physicalDevice == VK_NULL_HANDLE) { throw std::runtime_error("failed to find a suitable GPU!"); } }
#define GLFW_INCLUDE_VULKAN #include <GLFW/glfw3.h> #include <string.h> #include <iostream> #include <vector> const uint32_t WIDTH = 800; const uint32_t HEIGHT = 600; const std::vector<const char*> validationLayers = { "VK_LAYER_KHRONOS_validation" }; #define NDEBUG 0 //是否启用校验层 #ifdef NDEBUG const bool enableValidationLayers = false; #else const bool enableValidationLayers = true; #endif VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) { auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); if (func != nullptr) { return func(instance, pCreateInfo, pAllocator, pDebugMessenger); } else { return VK_ERROR_EXTENSION_NOT_PRESENT; } } void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) { auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); if (func != nullptr) { func(instance, debugMessenger, pAllocator); } } class HelloTriangleApplication { public: void run() { initWindow(); initVulkan(); mainLoop(); cleanup(); } private: GLFWwindow* window; VkInstance instance; VkDebugUtilsMessengerEXT debugMessenger; VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; void initWindow() { glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan_01", nullptr, nullptr); } void initVulkan() { createInstance(); setupDebugMessenger(); pickPhysicalDevice(); } void mainLoop() { while (!glfwWindowShouldClose(window)) { glfwPollEvents(); } } void cleanup() { if (enableValidationLayers && !checkValidationLayerSupport()) { throw std::runtime_error("validation layers requested, but not available!"); } vkDestroyInstance(instance, nullptr); glfwDestroyWindow(window); glfwTerminate(); } void createInstance() { //检查校验层是否有效 if (enableValidationLayers && !checkValidationLayerSupport()) { throw std::runtime_error("validation layers requested, but not available!"); } //定义程序信息 VkApplicationInfo appInfo{}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "Hello Triangle"; appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.pEngineName = "No Engine"; appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.apiVersion = VK_API_VERSION_1_0; VkInstanceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.pApplicationInfo = &appInfo; //获取所需Vulkan的扩展 auto extensions = getRequiredExtensions(); createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size()); createInfo.ppEnabledExtensionNames = extensions.data(); createInfo.enabledLayerCount = 0; //校验层 VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size()); createInfo.ppEnabledLayerNames = validationLayers.data(); populateDebugMessengerCreateInfo(debugCreateInfo); createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo; //创建Vulkan实例 if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { throw std::runtime_error("failed to create instance!"); } } //返回GFLW所需扩展和启用校验层所需扩展 std::vector<const char*> getRequiredExtensions() { uint32_t glfwExtensionCount = 0; const char** glfwExtensions; glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); if (enableValidationLayers) { extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); } return extensions; } void showExtensions(){ uint32_t extensionCount = 0; vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); std::vector<VkExtensionProperties> extensions(extensionCount); vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); std::cout << "\n系统支持Vulkan扩展:\n"; for (const auto& extension : extensions) { std::cout << '\t' << extension.extensionName << '\n'; } } bool checkValidationLayerSupport() { uint32_t layerCount; vkEnumerateInstanceLayerProperties(&layerCount, nullptr); std::vector<VkLayerProperties> availableLayers(layerCount); vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); std::cout<<"本系统支持校验层数:"<<layerCount<<"\n"; int i=1; for (const auto& layerProperties : availableLayers) { std::cout<<"-------Validtion Layer "<<i++<<"---------\n"; std::cout<<"名称:"<<layerProperties.layerName<<"\n"; std::cout<<"描述:"<<layerProperties.description<<"\n\n"; } bool layerFound; for (const char* layerName : validationLayers) { bool layerFound = false; for (const auto& layerProperties : availableLayers) { if (strcmp(layerName, layerProperties.layerName) == 0) { layerFound = true; uint32_t propertyCount; vkEnumerateInstanceExtensionProperties(layerProperties.layerName,&propertyCount,NULL); std::vector<VkExtensionProperties> propertiesList; propertiesList.resize(propertyCount); vkEnumerateInstanceExtensionProperties(layerProperties.layerName,&propertyCount,propertiesList.data()); std::cout<<"所需扩展:\n"; for(auto ep:propertiesList){ if(enableValidationLayers==true){ std::cout<<"\t"<<ep.extensionName<<"\n"; } } break; } } if (!layerFound) { return false; } } return true; } //设置调试相关参数及回调函数 void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) { createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; //设置调试信息回调函数debugCallback createInfo.pfnUserCallback = debugCallback; } static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) { if(!enableValidationLayers) return VK_FALSE; std::string msg="Validation Layer "; switch(messageSeverity){ case 1: msg+="诊断信息:"; break; case 2: msg+="资源创建:"; break; case 3: msg+="警告信息:"; break; case 4: msg+="错误信息:"; break; } std::cerr << msg << pCallbackData->pMessage <<"\t"<<"\n\n"; return VK_FALSE; } void setupDebugMessenger() { if (!enableValidationLayers) return; VkDebugUtilsMessengerCreateInfoEXT createInfo; populateDebugMessengerCreateInfo(createInfo); if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) { throw std::runtime_error("failed to set up debug messenger!"); } } void pickPhysicalDevice() { uint32_t deviceCount = 0; vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); if (deviceCount == 0) { throw std::runtime_error("failed to find GPUs with Vulkan support!"); } std::vector<VkPhysicalDevice> devices(deviceCount); vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); std::cout<<"GPU Devices:"<<deviceCount<<"\n"; VkPhysicalDeviceProperties DeviceProperties; VkPhysicalDeviceFeatures DeviceFeatures; for (const auto& device : devices) { vkGetPhysicalDeviceProperties(device,&DeviceProperties); vkGetPhysicalDeviceFeatures(device,&DeviceFeatures); if(DeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && DeviceFeatures.geometryShader){ std::cout<<"Device Name:"<<DeviceProperties.deviceName<<"\n"; physicalDevice = device; break; } } if (physicalDevice == VK_NULL_HANDLE) { throw std::runtime_error("failed to find a suitable GPU!"); } } }; int main() { HelloTriangleApplication app; try { app.run(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }
运行结果,显示出主机包含GPU数量,和符合条件的GPU名称
GPU Devices:1 Device Name:GeForce GTX 1050 Ti
桂ICP备11003301号-1
公安备案号:45040302000027
Copyright @ 2021- 2022 By Sun zi chao
阅读统计: 1.93W 文章数量: 76 运行天数: 416天 返回cmnsoft