#include #include #include #include #include #include #include #include #include #include #include VK_NAMESPACE_BEGIN VkPipelineCache CreatePipelineCache(VkDevice device,const VkPhysicalDeviceProperties &); Swapchain *CreateSwapchain(const GPUDeviceAttribute *attr,const VkExtent2D &acquire_extent); #ifdef _DEBUG DebugMaker *CreateDebugMaker(VkDevice); #endif//_DEBUG namespace { void SetDeviceExtension(CharPointerList *ext_list,const GPUPhysicalDevice *physical_device) { ext_list->Add(VK_KHR_SWAPCHAIN_EXTENSION_NAME); constexpr char *require_ext_list[]= { #ifdef _DEBUG VK_EXT_DEBUG_MARKER_EXTENSION_NAME, #endif//_DEBUG // VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, // VK_EXT_HDR_METADATA_EXTENSION_NAME, // VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME, // VK_AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME, // VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME, }; for(const char *ext_name:require_ext_list) if(physical_device->CheckExtensionSupport(ext_name)) ext_list->Add(ext_name); } void SetDeviceFeatures(VkPhysicalDeviceFeatures *features,const VkPhysicalDeviceFeatures &pdf) { #define FEATURE_COPY(name) features->name=pdf.name; FEATURE_COPY(geometryShader); FEATURE_COPY(multiDrawIndirect); FEATURE_COPY(imageCubeArray); FEATURE_COPY(samplerAnisotropy); #undef FEATURE_COPY } VkDevice CreateDevice(VkInstance instance,const GPUPhysicalDevice *physical_device,uint32_t graphics_family) { float queue_priorities[1]={0.0}; VkDeviceQueueCreateInfo queue_info; queue_info.sType=VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue_info.pNext=nullptr; queue_info.queueFamilyIndex=graphics_family; queue_info.queueCount=1; queue_info.pQueuePriorities=queue_priorities; queue_info.flags=0; //如果这里写VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT,会导致vkGetDeviceQueue调用崩溃 VkDeviceCreateInfo create_info={}; CharPointerList ext_list; VkPhysicalDeviceFeatures features={}; SetDeviceExtension(&ext_list,physical_device); SetDeviceFeatures(&features,physical_device->GetFeatures()); create_info.sType=VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; create_info.pNext=nullptr; create_info.queueCreateInfoCount=1; create_info.pQueueCreateInfos=&queue_info; create_info.enabledExtensionCount=ext_list.GetCount(); create_info.ppEnabledExtensionNames=ext_list.GetData(); create_info.enabledLayerCount=0; create_info.ppEnabledLayerNames=nullptr; create_info.pEnabledFeatures=&features; VkDevice device; if(vkCreateDevice(*physical_device,&create_info,nullptr,&device)==VK_SUCCESS) return device; return nullptr; } void GetDeviceQueue(GPUDeviceAttribute *attr) { vkGetDeviceQueue(attr->device,attr->graphics_family,0,&attr->graphics_queue); if(attr->graphics_family==attr->present_family) attr->present_queue=attr->graphics_queue; else vkGetDeviceQueue(attr->device,attr->present_family,0,&attr->present_queue); } VkCommandPool CreateCommandPool(VkDevice device,uint32_t graphics_family) { VkCommandPoolCreateInfo cmd_pool_info={}; cmd_pool_info.sType=VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; cmd_pool_info.pNext=nullptr; cmd_pool_info.queueFamilyIndex=graphics_family; cmd_pool_info.flags=VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; VkCommandPool cmd_pool; if(vkCreateCommandPool(device,&cmd_pool_info,nullptr,&cmd_pool)==VK_SUCCESS) return cmd_pool; return(VK_NULL_HANDLE); } ImageView *Create2DImageView(VkDevice device,VkFormat format,const VkExtent2D &ext,const uint32_t miplevel,VkImage img=VK_NULL_HANDLE) { VkExtent3D extent; copy(extent,ext); return CreateImageView(device,VK_IMAGE_VIEW_TYPE_2D,format,extent,miplevel,VK_IMAGE_ASPECT_COLOR_BIT,img); } ImageView *CreateDepthImageView(VkDevice device,VkFormat format,const VkExtent2D &ext,const uint32_t miplevel,VkImage img=VK_NULL_HANDLE) { VkExtent3D extent; copy(extent,ext,1); return CreateImageView(device,VK_IMAGE_VIEW_TYPE_2D,format,extent,miplevel,VK_IMAGE_ASPECT_DEPTH_BIT,img); } VkDescriptorPool CreateDescriptorPool(VkDevice device,uint32_t sets_count) { VkDescriptorPoolSize pool_size[]= { {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, sets_count}, {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sets_count}, {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, sets_count}, {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, sets_count} }; VkDescriptorPoolCreateInfo dp_create_info; dp_create_info.sType =VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; dp_create_info.pNext =nullptr; dp_create_info.flags =0; dp_create_info.maxSets =sets_count; dp_create_info.poolSizeCount=sizeof(pool_size)/sizeof(VkDescriptorPoolSize); dp_create_info.pPoolSizes =pool_size; VkDescriptorPool desc_pool; if(vkCreateDescriptorPool(device,&dp_create_info,nullptr,&desc_pool)!=VK_SUCCESS) return(VK_NULL_HANDLE); return desc_pool; } void DebugOut(const VkPhysicalDeviceFeatures &features) { #define OUTPUT_PHYSICAL_DEVICE_FEATURE(name) std::cout<(pdp.vendorID).c_str()<(pdp.deviceID).c_str()<(pdp.pipelineCacheUUID); std::cout<<"pipelineCahceUUID: "<GetProperties()); DebugOut(physical_device->GetFeatures()); } #endif//_DEBUG GPUDeviceAttribute *device_attr=new GPUDeviceAttribute(inst,physical_device,surface); AutoDelete auto_delete(device_attr); if(device_attr->graphics_family==ERROR_FAMILY_INDEX) return(nullptr); device_attr->device=CreateDevice(*inst,physical_device,device_attr->graphics_family); if(!device_attr->device) return(nullptr); #ifdef _DEBUG device_attr->debug_maker=CreateDebugMaker(device_attr->device); #endif//_DEBUG GetDeviceQueue(device_attr); device_attr->cmd_pool=CreateCommandPool(device_attr->device,device_attr->graphics_family); if(!device_attr->cmd_pool) return(nullptr); device_attr->desc_pool=CreateDescriptorPool(device_attr->device,1024); if(!device_attr->desc_pool) return(nullptr); device_attr->pipeline_cache=CreatePipelineCache(device_attr->device,physical_device->GetProperties()); if(!device_attr->pipeline_cache) return(nullptr); auto_delete.Discard(); return(new GPUDevice(device_attr)); } GPUDevice *CreateRenderDevice(VulkanInstance *inst,Window *win,const GPUPhysicalDevice *pd) { if(!inst) return(nullptr); if(!pd)pd=inst->GetDevice(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU); //先找独显 if(!pd)pd=inst->GetDevice(VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU); //再找集显 if(!pd)pd=inst->GetDevice(VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU); //最后找虚拟显卡 if(!pd) return(nullptr); VkSurfaceKHR surface=CreateVulkanSurface(*inst,win); if(!surface) return(nullptr); VkExtent2D extent; extent.width=win->GetWidth(); extent.height=win->GetHeight(); GPUDevice *device=CreateRenderDevice(inst,pd,surface,extent); if(!device) { vkDestroySurfaceKHR(*inst,surface,nullptr); return(nullptr); } return device; } VK_NAMESPACE_END