vulkan游戏引擎的核心device核心文件实现

1.vulkan_device.h

#pragma once

#include "vulkan_types.inl"

b8 vulkan_device_create(vulkan_context* context);

void vulkan_device_destroy(vulkan_context* context);

void vulkan_device_query_swapchain_support(

VkPhysicalDevice physical_device,

VkSurfaceKHR surface,

vulkan_swapchain_support_info* out_support_info

);

b8 vulkan_device_detect_depth_format(vulkan_device* device);

2.vulkan_device.c

#include "vulkan_device.h"

#include "core/logger.h"

#include "core/kstring.h"

#include "core/kmemory.h"

#include "containers/darray.h"

#include "vulkan_types.inl"

#include "vulkan_backend.h"

#include "vulkan_swapchain.h"

typedef struct vulkan_physical_device_requirements{

b8 graphics;

b8 present;

b8 compute;

b8 transfer;

//darray

const char** device_extension_names;

b8 sampler_anisotropy;

b8 discrete_gpu;

}vulkan_physical_device_requirements;

typedef struct vulkan_physical_device_queue_family_info

{

u32 graphics_family_index;

u32 present_family_index;

u32 compute_family_index;

u32 transfer_family_index;

}vulkan_physical_device_queue_family_info;

b8 select_physical_device(vulkan_context* context);

static b8 physical_device_meets_requirements(

//vulkan_context* context,

VkPhysicalDevice device,

VkSurfaceKHR surface,

const VkPhysicalDeviceProperties* properties,

const VkPhysicalDeviceFeatures* features,

const vulkan_physical_device_requirements* requirements,

vulkan_physical_device_queue_family_info* out_queue_family_info,

vulkan_swapchain_support_info* out_swapchain_support

);

b8 vulkan_device_create(vulkan_context* context)

{

if(!select_physical_device(context))

{

return false;

}

KINFO("Creating logical device...");

b8 present_shares_graphics_queue = context->device.graphics_queue_index == context->device.present_queue_index;

b8 transfer_shares_graphics_queue = context->device.graphics_queue_index == context->device.transfer_queue_index;

//b8 present_must_share_graphics = false;

u32 index_count = 1;

if(!present_shares_graphics_queue)

{

index_count++;

}

if(!transfer_shares_graphics_queue)

{

index_count++;

}

u32 indices[32];

u8 index = 0;

indices[index++] = context->device.graphics_queue_index;

if(!present_shares_graphics_queue)

{

indices[index++] = context->device.present_queue_index;

}

if(!transfer_shares_graphics_queue)

{

indices[index++] = context->device.transfer_queue_index;

}

VkDeviceQueueCreateInfo queue_create_infos[32];

for(u32 i = 0;i <index_count;++i)

{

queue_create_infos[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;

queue_create_infos[i].queueFamilyIndex = indices[i];

queue_create_infos[i].queueCount = 1;

if(indices[i] == context->device.graphics_queue_index)

{

queue_create_infos[i].queueCount = 2;

}

queue_create_infos[i].flags = 0;

queue_create_infos[i].pNext = 0;

f32 queue_priority = 1.0f;

queue_create_infos[i].pQueuePriorities = &queue_priority;

}

//shoule be config driven

VkPhysicalDeviceFeatures device_features = {};

device_features.samplerAnisotropy = VK_TRUE;

VkDeviceCreateInfo device_create_info = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};

device_create_info.queueCreateInfoCount = index_count;

device_create_info.pQueueCreateInfos = queue_create_infos;

device_create_info.pEnabledFeatures = &device_features;

device_create_info.enabledExtensionCount = 1;

const char* extension_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME;

device_create_info.ppEnabledExtensionNames = &extension_names;

device_create_info.enabledLayerCount = 0;

device_create_info.ppEnabledLayerNames = 0;

//没有实现

//Create the device

VK_CHECK(vkCreateDevice(

context->device.physical_device,

&device_create_info,

context->allocator,

&context->device.logical_device

));

KINFO("Logical device created.");

vkGetDeviceQueue(

context->device.logical_device,

context->device.graphics_queue_index,

0,

&context->device.graphics_queue

);

vkGetDeviceQueue(

context->device.logical_device,

context->device.present_queue_index,

0,

&context->device.present_queue

);

vkGetDeviceQueue(

context->device.logical_device,

context->device.transfer_queue_index,

0,

&context->device.transfer_queue);

KINFO("Queues obtained.");

//Create command pool for graphics queue.

VkCommandPoolCreateInfo pool_create_info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};

pool_create_info.queueFamilyIndex = context->device.graphics_queue_index;

pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;

VK_CHECK(vkCreateCommandPool(

context->device.logical_device,

&pool_create_info,

context->allocator,

&context->device.graphics_command_pool

));

KINFO("Graphics command pool created.");

return true;

}

void vulkan_device_destroy(vulkan_context* context)

{

//Unset queues

context->device.graphics_queue = 0;

context->device.present_queue = 0;

context->device.transfer_queue = 0;

KINFO("Destroying command pools...");

vkDestroyCommandPool(

context->device.logical_device,

context->device.graphics_command_pool,

context->allocator

);

//Destroy logical device

KINFO("Destroying logical device...");

if(context->device.logical_device)

{

vkDestroyDevice(context->device.logical_device,context->allocator);

context->device.logical_device = 0;

}

//Physical devices are not destroyed

KINFO("Releasing physical device resources...");

context->device.physical_device = 0;

if(context->device.swapchain_support.formats)

{

kfree(

context->device.swapchain_support.formats,

sizeof(VkSurfaceFormatKHR)* context->device.swapchain_support.format_count,

MEMORY_TAG_RENDERER

);

context->device.swapchain_support.formats = 0;

context->device.swapchain_support.format_count = 0;

}

if(context->device.swapchain_support.present_modes)

{

kfree(

context->device.swapchain_support.present_modes,

sizeof(VkSurfaceFormatKHR)* context->device.swapchain_support.present_mode_count,

MEMORY_TAG_RENDERER

);

context->device.swapchain_support.present_modes = 0;

context->device.swapchain_support.present_mode_count = 0;

}

kzero_memory(

&context->device.swapchain_support.capabilities,

sizeof(context->device.swapchain_support.capabilities)

);

context->device.graphics_queue_index = -1;

context->device.present_queue_index = -1;

context->device.transfer_queue_index = -1;

}

void vulkan_device_query_swapchain_support(

VkPhysicalDevice physical_device,

VkSurfaceKHR surface,

vulkan_swapchain_support_info* out_support_info

){

//Surface capabilities

VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(

physical_device,

surface,

&out_support_info->capabilities

));

VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(

physical_device,

surface,

&out_support_info->format_count,

0

));

if(out_support_info->format_count !=0)

{

if(!out_support_info->formats)

{

out_support_info->formats = kallocate(sizeof(VkSurfaceFormatKHR)*out_support_info->format_count,MEMORY_TAG_RENDERER);

}

VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(

physical_device,

surface,

&out_support_info->format_count,

out_support_info->formats

));

if(out_support_info->format_count != 0)

{

if(!out_support_info->formats)

{

out_support_info->formats = kallocate(sizeof(VkSurfaceFormatKHR) * out_support_info->format_count,MEMORY_TAG_RENDERER);

}

VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(

physical_device,

surface,

&out_support_info->present_mode_count,

0

));

if(out_support_info->present_mode_count != 0)

{

if(!out_support_info->present_modes)

{

out_support_info->present_modes = kallocate(sizeof(VkPresentModeKHR)* out_support_info->present_mode_count,MEMORY_TAG_RENDERER);

}

VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(

physical_device,

surface,

&out_support_info->present_mode_count,

out_support_info->present_modes

));

}

}

}

VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(

physical_device,

surface,

&out_support_info->present_mode_count,

0

));

}

b8 vulkan_device_detect_depth_format(vulkan_device* device)

{

const u64 candidate_count = 3;

VkFormat candidates[3] = {

VK_FORMAT_D32_SFLOAT,

VK_FORMAT_D32_SFLOAT_S8_UINT,

VK_FORMAT_D24_UNORM_S8_UINT

};

u32 flags = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;

for (u64 i = 0;i<candidate_count;++i)

{

VkFormatProperties properties;

vkGetPhysicalDeviceFormatProperties(device->physical_device,candidates[i], &properties);

if((properties.linearTilingFeatures & flags) == flags)

{

device->depth_format = candidates[i];

return true;

}else if((properties.optimalTilingFeatures & flags) == flags)

{

device->depth_format = candidates[i];

return true;

}

}

return false;

}

b8 select_physical_device(vulkan_context* context)

{

u32 physical_device_count = 0;

VK_CHECK(vkEnumeratePhysicalDevices(context->instance,&physical_device_count,0));

if(physical_device_count == 0)

{

KFATAL("No devices which support vulkan were found.");

return false;

}

const u32 max_device_count = 32;

VkPhysicalDevice physical_devices[max_device_count];

VK_CHECK(vkEnumeratePhysicalDevices(context->instance,&physical_device_count,physical_devices));

for(u32 i = 0;i<physical_device_count;++i)

{

VkPhysicalDeviceProperties properties;

vkGetPhysicalDeviceProperties(physical_devices[i],&properties);

VkPhysicalDeviceFeatures features;

vkGetPhysicalDeviceFeatures(physical_devices[i],&features);

VkPhysicalDeviceMemoryProperties memory;

vkGetPhysicalDeviceMemoryProperties(physical_devices[i],&memory);

vulkan_physical_device_requirements requirements = {};

requirements.graphics = true;

requirements.present = true;

requirements.transfer = true;

requirements.sampler_anisotropy = true;

requirements.discrete_gpu = true;

requirements.device_extension_names = darray_create(const char*);

darray_push(requirements.device_extension_names,&VK_KHR_SWAPCHAIN_EXTENSION_NAME);

vulkan_physical_device_queue_family_info queue_info = {};

b8 result = physical_device_meets_requirements(

//context,

physical_devices[i],

context->surface,

&properties,

&features,

&requirements,

&queue_info,

&context->device.swapchain_support);

if(result)

{

KINFO("Selected device: '%s'.",properties.deviceName);

//GPU type

switch(properties.deviceType)

{

default:

case VK_PHYSICAL_DEVICE_TYPE_OTHER:

KINFO("GPU type is Unknown.");

break;

case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:

KINFO("GPU type is Integrated.");

break;

case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:

KINFO("GPU type is Descrete.");

break;

case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:

KINFO("GPU type is Virtual.");

break;

case VK_PHYSICAL_DEVICE_TYPE_CPU:

KINFO("GPU type is CPU.");

break;

}

KINFO(

"GPU Driver version: %d,%d,%d",

VK_VERSION_MAJOR(properties.driverVersion),

VK_VERSION_MINOR(properties.driverVersion),

VK_VERSION_PATCH(properties.driverVersion)

);

//Vulkan API version

KINFO(

"Vulkan API version: %d,%d,%d",

VK_VERSION_MAJOR(properties.apiVersion),

VK_VERSION_MINOR(properties.apiVersion),

VK_VERSION_PATCH(properties.apiVersion)

);

//Memory information

for(u32 j = 0;j <memory.memoryHeapCount;++j)

{

f32 memory_size_gib = (((f32)memory.memoryHeaps[j].size)/1024.0f/1024.0f/1024.0f);

if(memory.memoryHeaps[j].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)

{

KINFO("Local GPU memory: %.2f GiB",memory_size_gib);

}else

{

KINFO("Shared System memory: %.2f GiB",memory_size_gib);

}

}

context->device.physical_device = physical_devices[i];

context->device.graphics_queue_index = queue_info.graphics_family_index;

context->device.present_queue_index = queue_info.present_family_index;

context->device.transfer_queue_index = queue_info.transfer_family_index;

context->device.properties = properties;

context->device.features = features;

context->device.memory = memory;

break;

}

}

if(!context->device.physical_device)

{

KERROR("NO physical devices were found which meet the requirements.");

return false;

}

KINFO("Physical device selected.");

return true;

}

b8 physical_device_meets_requirements(

//vulkan_context* context,

VkPhysicalDevice device,

VkSurfaceKHR surface,

const VkPhysicalDeviceProperties* properties,

const VkPhysicalDeviceFeatures* features,

const vulkan_physical_device_requirements* requirements,

vulkan_physical_device_queue_family_info* out_queue_info,

vulkan_swapchain_support_info* out_swapchain_support

)

{

out_queue_info->graphics_family_index = -1;

out_queue_info->present_family_index = -1;

out_queue_info->compute_family_index = -1;

out_queue_info->transfer_family_index = -1;

if(requirements->discrete_gpu)

{

if(properties->deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)

{

KINFO("Device is not a discrete GPU,and one is required.Skipping.");

return false;

}

}

u32 queue_family_count = 0;

vkGetPhysicalDeviceQueueFamilyProperties(device,&queue_family_count,0);

VkQueueFamilyProperties queue_families[32];

vkGetPhysicalDeviceQueueFamilyProperties(device,&queue_family_count,queue_families);

KINFO("Graphics | Present | Compute | Transfer | Name");

u8 min_transfer_score = 255;

for(u32 i = 0;i <queue_family_count;++i)

{

u8 current_transfer_score = 0;

//Graphics queue

if(queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)

{

out_queue_info->graphics_family_index = i;

++current_transfer_score;

}

//Compute queue

if(queue_families[i].queueFlags & VK_QUEUE_COMPUTE_BIT)

{

out_queue_info->compute_family_index = i;

++current_transfer_score;

}

if(queue_families[i].queueFlags & VK_QUEUE_TRANSFER_BIT)

{

if(current_transfer_score <= min_transfer_score)

{

min_transfer_score = current_transfer_score;

out_queue_info->transfer_family_index = i;

}

}

VkBool32 supports_present = VK_FALSE;

VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(device,i,surface,&supports_present));

if(supports_present)

{

out_queue_info->present_family_index = i;

}

}

KINFO(" %d| %d| %d| %d |%s",

out_queue_info->graphics_family_index != -1,

out_queue_info->present_family_index != -1,

out_queue_info->compute_family_index != -1,

out_queue_info->transfer_family_index != -1,

properties->deviceName

);

if (

(!requirements->graphics || (requirements->graphics && out_queue_info->graphics_family_index != -1)) &&

(!requirements->present || (requirements->present && out_queue_info->present_family_index != -1)) &&

(!requirements->compute || (requirements->compute && out_queue_info->compute_family_index != -1)) &&

(!requirements->transfer || (requirements->transfer && out_queue_info->transfer_family_index != -1))) {

KINFO("Device meets queue requirements.");

KTRACE("Graphics Family Index: %i", out_queue_info->graphics_family_index);

KTRACE("Present Family Index: %i", out_queue_info->present_family_index);

KTRACE("Transfer Family Index: %i", out_queue_info->transfer_family_index);

KTRACE("Compute Family Index: %i", out_queue_info->compute_family_index);

//Qure swapchain support

vulkan_device_query_swapchain_support(

device,

surface,

out_swapchain_support

);

if(out_swapchain_support->format_count < 1 || out_swapchain_support->present_mode_count < 1)

{

if(out_swapchain_support->formats)

{

kfree(out_swapchain_support->formats,sizeof(VkSurfaceFormatKHR) * out_swapchain_support->format_count,MEMORY_TAG_RENDERER);

}

if(out_swapchain_support->present_modes)

{

kfree(out_swapchain_support->present_modes,sizeof(VkPresentModeKHR)*out_swapchain_support->present_mode_count,MEMORY_TAG_RENDERER);

}

KINFO("Required swapchain support not present.skipping device");

return false;

}

//Device extensions

if(requirements->device_extension_names)

{

u32 available_extension_count = 0;

VkExtensionProperties* available_extensions = 0;

VK_CHECK(vkEnumerateDeviceExtensionProperties(

device,

0,

&available_extension_count,

0

));

if(available_extension_count != 0)

{

available_extensions = kallocate(sizeof(VkExtensionProperties)* available_extension_count,MEMORY_TAG_RENDERER);

VK_CHECK(vkEnumerateDeviceExtensionProperties(

device,

0,

&available_extension_count,

available_extensions

));

u32 required_extension_count = darray_length(requirements->device_extension_names);

for(u32 i = 0;i<required_extension_count;++i)

{

b8 found = false;

for(u32 j = 0;j<available_extension_count;++j){

if(strings_equal(requirements->device_extension_names[i],available_extensions[j].extensionName))

{

found =true;

break;

}

}

if(!found)

{

KINFO("Required extensions not found: '%s',skipping device.",requirements->device_extension_names[i]);

kfree(available_extensions,sizeof(VkExtensionProperties) * available_extension_count,MEMORY_TAG_RENDERER);

break;

}

}

}

kfree(available_extensions,sizeof(VkExtensionProperties)* available_extension_count,MEMORY_TAG_RENDERER);

}

// Sampler anisotropy

if (requirements->sampler_anisotropy && !features->samplerAnisotropy) {

KINFO("Device does not support samplerAnisotropy, skipping.");

return false;

}

// Device meets all requirements.

return true;

}

return false;

}

相关推荐
执 、2 小时前
SpringBoot定时监控数据库状态
java·数据库·ide·spring boot·后端
FmZero2 小时前
Redis使用规范
java·redis·mybatis
Small black human2 小时前
Spring-MyBatis的配置
java·spring·mybatis
睡觉z3 小时前
Haproxy搭建web群集
前端
codingandsleeping3 小时前
重读《你不知道的JavaScript》(上)- this
前端·javascript
Niloofar4 小时前
SpringBootWeb请求响应
java·maven
王有品5 小时前
Spring MVC 会话管理实践教程:HttpSession 深入应用
java·spring·mvc
武子康5 小时前
Java-49 深入浅出 Tomcat 手写 Tomcat 实现【02】HttpServlet Request RequestProcessor
java·开发语言·后端·学习·spring cloud·tomcat
若疆赤云online5 小时前
Minio使用https自签证书
java·网络协议·https
bulucc5 小时前
IntelliJ IDEA 安装及java环境搭建
java·ide·intellij-idea