Windows下vulkan开发流程
1、枚举实例扩展属性:
vkEnumerateInstanceExtensionProperties [0/17]VK_KHR_device_group_creation
vkEnumerateInstanceExtensionProperties [1/17]VK_KHR_display
vkEnumerateInstanceExtensionProperties [2/17]VK_KHR_external_fence_capabilities
vkEnumerateInstanceExtensionProperties [3/17]VK_KHR_external_memory_capabilities
vkEnumerateInstanceExtensionProperties [4/17]VK_KHR_external_semaphore_capabilities
vkEnumerateInstanceExtensionProperties [5/17]VK_KHR_get_display_properties2
vkEnumerateInstanceExtensionProperties [6/17]VK_KHR_get_physical_device_properties2
vkEnumerateInstanceExtensionProperties [7/17]VK_KHR_get_surface_capabilities2
vkEnumerateInstanceExtensionProperties [8/17]VK_KHR_surface
vkEnumerateInstanceExtensionProperties [9/17]VK_KHR_surface_protected_capabilities
vkEnumerateInstanceExtensionProperties [10/17]VK_KHR_win32_surface
vkEnumerateInstanceExtensionProperties [11/17]VK_EXT_debug_report
vkEnumerateInstanceExtensionProperties [12/17]VK_EXT_debug_utils
vkEnumerateInstanceExtensionProperties [13/17]VK_EXT_direct_mode_display
vkEnumerateInstanceExtensionProperties [14/17]VK_EXT_swapchain_colorspace
vkEnumerateInstanceExtensionProperties [15/17]VK_NV_external_memory_capabilities
vkEnumerateInstanceExtensionProperties [16/17]VK_KHR_portability_enumeration
2、通过实例信息结构VkInstanceCreateInfo创建一个实例
err = vkCreateInstance(&inst_info, NULL, &demo->inst);
失败日志ICD:
Cannot find a compatible Vulkan installable client driver (ICD).
3、枚举物理设备即显卡GPU
(1)、查询GPU数量
err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL);
(2)、获取GPU设备句柄
VkPhysicalDevice *physical_devices = malloc(sizeof(VkPhysicalDevice) * gpu_count);
err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, physical_devices);
遍历获取显卡属性:
vkGetPhysicalDeviceProperties(physical_devices[i], &physicalDeviceProperties);
比如集成显卡与独立显卡:
Intel(R) UHD Graphics
NVIDIA GeForce RTX 3060 Laptop GPU
4、枚举选择的GPU扩展属性
Selected GPU 1: NVIDIA GeForce RTX 3060 Laptop GPU, type: DiscreteGpu
GPU根据接入系统的方式分为集成型GPU(Integrated GPU,iGPU)和离散型GPU(Discrete GPU ,dGPU)两种
typedef enum VkPhysicalDeviceType {
VK_PHYSICAL_DEVICE_TYPE_OTHER = 0,
VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1,
VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2,
VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3,
VK_PHYSICAL_DEVICE_TYPE_CPU = 4,
VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF
} VkPhysicalDeviceType;
176个:
err = vkEnumerateDeviceExtensionProperties(demo->gpu, NULL, &device_extension_count, NULL);
vkGetPhysicalDeviceProperties(demo->gpu, &demo->gpu_props);
/* Call with NULL data to get count */
vkGetPhysicalDeviceQueueFamilyProperties(demo->gpu, &demo->queue_family_count, NULL);
assert(demo->queue_family_count >= 1);
demo->queue_props = (VkQueueFamilyProperties *)malloc(demo->queue_family_count * sizeof(VkQueueFamilyProperties));
vkGetPhysicalDeviceQueueFamilyProperties(demo->gpu, &demo->queue_family_count, demo->queue_props);
显卡特性:
VkPhysicalDeviceFeatures physDevFeatures;
vkGetPhysicalDeviceFeatures(demo->gpu, &physDevFeatures);
5、创建Windows窗口
demo_create_window(&demo
6、创建交换链SwapChain
demo_init_vk_swapchain
(1)、err = vkCreateWin32SurfaceKHR(demo->inst, &createInfo, NULL, &demo->surface);
(2)、 // Iterate over each queue to learn whether it supports presenting:
VkBool32 *supportsPresent = (VkBool32 *)malloc(demo->queue_family_count * sizeof(VkBool32));
for (uint32_t i = 0; i < demo->queue_family_count; i++) {
demo->fpGetPhysicalDeviceSurfaceSupportKHR(demo->gpu, i, demo->surface, &supportsPresent[i]);
}
(3)、搜索队列
// Search for a graphics and a present queue in the array of queue
// families, try to find one that supports both
uint32_t graphicsQueueFamilyIndex = UINT32_MAX;
uint32_t presentQueueFamilyIndex = UINT32_MAX;
for (uint32_t i = 0; i < demo->queue_family_count; i++) {
if ((demo->queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
if (graphicsQueueFamilyIndex == UINT32_MAX) {
graphicsQueueFamilyIndex = i;
}
if (supportsPresent[i] == VK_TRUE) {
graphicsQueueFamilyIndex = i;
presentQueueFamilyIndex = i;
break;
}
}
}
(4)、
err = vkCreateDevice(demo->gpu, &device, NULL, &demo->device);
vkGetDeviceQueue(demo->device, demo->graphics_queue_family_index, 0, &demo->graphics_queue);
err = demo->fpGetPhysicalDeviceSurfaceFormatsKHR(demo->gpu, demo->surface, &formatCount, NULL);
(5)、创建信号量同步显示
// Create semaphores to synchronize acquiring presentable buffers before
// rendering and waiting for drawing to be complete before presenting
VkSemaphoreCreateInfo semaphoreCreateInfo = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = NULL,
.flags = 0,
};
// 创建围栏
err = vkCreateFence(demo->device, &fence_ci, NULL, &demo->fences[i]);
assert(!err);
err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo, NULL, &demo->image_acquired_semaphores[i]);
// Get Memory information and properties
vkGetPhysicalDeviceMemoryProperties(demo->gpu, &demo->memory_properties);
7、渲染前的准备 demo_prepare
err = vkCreateCommandPool(demo->device, &cmd_pool_info, NULL, &demo->cmd_pool);
err = vkAllocateCommandBuffers(demo->device, &cmd, &demo->cmd);
err = vkBeginCommandBuffer(demo->cmd, &cmd_buf_info);
demo_prepare_depth(demo);
demo_prepare_textures(demo);
demo_prepare_cube_data_buffers(demo);
demo_prepare_descriptor_layout(demo);
demo_prepare_render_pass(demo);
demo_prepare_pipeline(demo);
/* create image */
err = vkCreateImage(demo->device, &image, NULL, &demo->depth.image);
/* allocate memory */
err = vkAllocateMemory(demo->device, &demo->depth.mem_alloc, NULL, &demo->depth.mem);
/* bind memory */
err = vkBindImageMemory(demo->device, demo->depth.image, demo->depth.mem, 0);
/* create image view */
view.image = demo->depth.image;
err = vkCreateImageView(demo->device, &view, NULL, &demo->depth.view);
demo_prepare_descriptor_pool(demo);
demo_prepare_descriptor_set(demo);
demo_prepare_framebuffers(demo);
for (uint32_t i = 0; i < demo->swapchainImageCount; i++) {
demo->current_buffer = i;
demo_draw_build_cmd(demo, demo->swapchain_image_resources[i].cmd);
}
err = vkBeginCommandBuffer(cmd_buf, &cmd_buf_info);
vkCmdBeginRenderPass(cmd_buf, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
viewport.height = viewport_dimension;
viewport.width = viewport_dimension;
viewport.minDepth = (float)0.0f;
viewport.maxDepth = (float)1.0f;
vkCmdSetViewport(cmd_buf, 0, 1, &viewport);
err = vkEndCommandBuffer(cmd_buf);
vulkan都是提前把渲染命令准备好。
8、渲染
case WM_PAINT:
// The validation callback calls MessageBox which can generate paint
// events - don't make more Vulkan calls if we got here from the
// callback
if (!in_callback) {
demo_run(&demo);
}
#if defined(VK_USE_PLATFORM_WIN32_KHR)
static void demo_run(struct demo *demo) {
if (!demo->prepared) return;
demo_draw(demo);
demo->curFrame++;
if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount) {
PostQuitMessage(validation_error);
}
}
// Ensure no more than FRAME_LAG renderings are outstanding
vkWaitForFences(demo->device, 1, &demo->fences[demo->frame_index], VK_TRUE, UINT64_MAX);
vkResetFences(demo->device, 1, &demo->fences[demo->frame_index]);
demo->fpAcquireNextImageKHR(demo->device, demo->swapchain, UINT64_MAX,
demo->image_acquired_semaphores[demo->frame_index], VK_NULL_HANDLE, &demo->current_buffer);
err = vkQueueSubmit(demo->graphics_queue, 1, &submit_info, demo->fences[demo->frame_index]);
err = demo->fpQueuePresentKHR(demo->present_queue, &present);
9、窗口大小缩放,重新准备
static void demo_resize(struct demo *demo) {
uint32_t i;
// Don't react to resize until after first initialization.
if (!demo->prepared) {
if (demo->is_minimized) {
demo_prepare(demo);
}
return;
}
// In order to properly resize the window, we must re-create the swapchain
// AND redo the command buffers, etc.
//
// First, perform part of the demo_cleanup() function:
demo->prepared = false;
vkDeviceWaitIdle(demo->device);
for (i = 0; i < demo->swapchainImageCount; i++) {
vkDestroyFramebuffer(demo->device, demo->swapchain_image_resources[i].framebuffer, NULL);
}
vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL);
vkDestroyPipeline(demo->device, demo->pipeline, NULL);
vkDestroyPipelineCache(demo->device, demo->pipelineCache, NULL);
vkDestroyRenderPass(demo->device, demo->render_pass, NULL);
vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL);
vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL);
for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
vkDestroyImageView(demo->device, demo->textures[i].view, NULL);
vkDestroyImage(demo->device, demo->textures[i].image, NULL);
vkFreeMemory(demo->device, demo->textures[i].mem, NULL);
vkDestroySampler(demo->device, demo->textures[i].sampler, NULL);
}
vkDestroyImageView(demo->device, demo->depth.view, NULL);
vkDestroyImage(demo->device, demo->depth.image, NULL);
vkFreeMemory(demo->device, demo->depth.mem, NULL);
for (i = 0; i < demo->swapchainImageCount; i++) {
vkDestroyImageView(demo->device, demo->swapchain_image_resources[i].view, NULL);
vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->swapchain_image_resources[i].cmd);
vkDestroyBuffer(demo->device, demo->swapchain_image_resources[i].uniform_buffer, NULL);
vkUnmapMemory(demo->device, demo->swapchain_image_resources[i].uniform_memory);
vkFreeMemory(demo->device, demo->swapchain_image_resources[i].uniform_memory, NULL);
}
vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL);
demo->cmd_pool = VK_NULL_HANDLE;
if (demo->separate_present_queue) {
vkDestroyCommandPool(demo->device, demo->present_cmd_pool, NULL);
}
free(demo->swapchain_image_resources);
// Second, re-perform the demo_prepare() function, which will re-create the
// swapchain:
demo_prepare(demo);
}