vulkan游戏引擎的renderer下的backend

1.vulkan_backend.h

#pragma once

#include "renderer/renderer_backend.h"

#include "resources/resource_types.h"

b8 vulkan_renderer_backend_initialize(renderer_backend* backend,const char* application_name,struct platform_state* plat_state);

void vulkan_renderer_backend_shutdown(renderer_backend* backend);

void vulkan_renderer_backend_on_resized(renderer_backend* backend,u16 width,u16 height);

b8 vulkan_renderer_backend_begin_frame(renderer_backend*backend,f32 delta_time);

void vulkan_renderer_update_global_state(mat4 projection,mat4 view,vec3 view_position,vec4 ambient_colour,i32 mode);

b8 vulkan_renderer_backend_end_frame(renderer_backend* backend,f32 delta_time);

void vulkan_backend_update_object(mat4 model);

void vulkan_renderer_create_texture(

const char* name,

b8 auto_release,

i32 width,

i32 height,

i32 channel_count,

const u8* pixels,

b8 has_transparency,

texture* out_texture

);

void vulkan_renderer_destroy_texture(texture* texture);

2.vulkan_backend.c

#include "vulkan_backend.h"

#include "vulkan_swapchain.h"

#include "vulkan_renderpass.h"

#include "vulkan_command_buffer.h"

#include "vulkan_framebuffer.h"

#include "vulkan_fence.h"

#include "vulkan_utils.h"

#include "vulkan_types.inl"

#include "core/logger.h"

#include "containers/darray.h"

#include "core/kstring.h"

#include "vulkan_platform.h"

#include "core/kmemory.h"

#include "core/application.h"

#include "platform/platform.h"

#include "vulkan_device.h"

#include "vulkan_platform.h"

#include "shaders/vulkan_object_shader.h"

#include "math/math_types.h"

#include "vulkan_buffer.h"

//static vulkan context

static vulkan_context context;

static u32 cached_framebuffer_width = 0;

static u32 cached_framebuffer_height = 0;

static vulkan_context context;

VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback(

VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,

VkDebugUtilsMessageTypeFlagsEXT message_types,

const VkDebugUtilsMessengerCallbackDataEXT* callback_data,

void* user_data

);

i32 find_memory_index(u32 type_filter,u32 property_flags);

b8 create_buffers(vulkan_context* context);

void create_command_buffers(renderer_backend* backend);

void regenerate_framebuffers(renderer_backend* backend,vulkan_swapchain* swapchain,vulkan_renderpass* renderpass);

b8 recreate_swapchain(renderer_backend* backend);

void upload_data_range(vulkan_context* context,VkCommandPool pool,VkFence fence,VkQueue queue,vulkan_buffer* buffer,u64 offset,u64 size,void* data)

{

VkBufferUsageFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;

vulkan_buffer staging;

vulkan_buffer_create(context,size,VK_BUFFER_USAGE_TRANSFER_SRC_BIT,flags,true,&staging);

vulkan_buffer_load_data(context,&staging,0,size,0,data);

vulkan_buffer_copy_to(context,pool,fence,queue,staging.handle,0,buffer->handle,offset,size);

vulkan_buffer_destroy(context,&staging);

}

b8 vulkan_renderer_backend_initialize(renderer_backend* backend,const char* application_name,struct platform_state* plat_state)

{

context.find_memory_index = find_memory_index;

context.allocator = 0;

application_get_framebuffer_size(&cached_framebuffer_width,&cached_framebuffer_height);

context.framebuffer_width = (cached_framebuffer_width != 0)? cached_framebuffer_width : 800;

context.framebuffer_height = (cached_framebuffer_height != 0) ? cached_framebuffer_height : 600;

cached_framebuffer_width = 0;

cached_framebuffer_height = 0;

//Setup vulkan instance

VkApplicationInfo app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO};

app_info.apiVersion = VK_API_VERSION_1_2;

app_info.pApplicationName = application_name;

app_info.applicationVersion = VK_MAKE_VERSION(1,0,0);

app_info.pEngineName = "Apophis Engine";

app_info.engineVersion = VK_MAKE_VERSION(1,0,0);

VkInstanceCreateInfo create_info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};

create_info.pApplicationInfo = &app_info;

create_info.enabledExtensionCount= 0;

create_info.ppEnabledExtensionNames = 0;

create_info.enabledLayerCount = 0;

create_info.ppEnabledLayerNames = 0;

//Obtain a list of required extensions

const char** required_extensions = darray_create(const char*);

darray_push(required_extensions,&VK_KHR_SURFACE_EXTENSION_NAME);

platform_get_required_extension_names(&required_extensions);

#if defined(_DEBUG)

darray_push(required_extensions,&VK_EXT_DEBUG_UTILS_EXTENSION_NAME);

KDEBUG("Required extensions");

u32 length = darray_length(required_extensions);

for (u32 i = 0; i < length; ++i) {

KDEBUG(required_extensions[i]);

}

#endif

create_info.enabledExtensionCount = darray_length(required_extensions);

create_info.ppEnabledExtensionNames = required_extensions;

const char** required_validation_layer_names = 0;

u32 required_validation_layer_count = 0;

#if defined(_DEBUG)

KINFO("Validation layers enabled. Enumerating...");

required_validation_layer_names = darray_create(const char*);

darray_push(required_validation_layer_names,&"VK_LAYER_KHRONOS_validation");

required_validation_layer_count = darray_length(required_validation_layer_names);

u32 available_layer_count = 0;

VK_CHECK(vkEnumerateInstanceLayerProperties(&available_layer_count, 0));

VkLayerProperties* available_layers = darray_reserve(VkLayerProperties, available_layer_count);

VK_CHECK(vkEnumerateInstanceLayerProperties(&available_layer_count, available_layers));

// Verify all required layers are available.

for (u32 i = 0; i < required_validation_layer_count; ++i) {

b8 found = false;

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

if (strings_equal(required_validation_layer_names[i], available_layers[j].layerName)) {

found = true;

KINFO("Found validation layer: %s...", required_validation_layer_names[i]);

break;

}

}

if (!found) {

KFATAL("Required validation layer is missing: %s", required_validation_layer_names[i]);

return false;

}

}

// Clean up.

//darray_destroy(available_extensions);

//darray_destroy(available_layers);

KINFO("All required validation layers are present.");

#endif

create_info.enabledLayerCount = required_validation_layer_count;

create_info.ppEnabledLayerNames = required_validation_layer_names;

//Validation layers

VK_CHECK(vkCreateInstance(&create_info,context.allocator,&context.instance));

KINFO("Vulkan Instance created!");

//Debugger

#if defined(_DEBUG)

KDEBUG("Creating Vulkan debugger...");

u32 log_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |

VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |

VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;

VkDebugUtilsMessengerCreateInfoEXT debug_create_info = {VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};

debug_create_info.messageSeverity = log_severity;

debug_create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT

| VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;

debug_create_info.pfnUserCallback = vk_debug_callback;

//debug_create_info.pUserData = 0;

PFN_vkCreateDebugUtilsMessengerEXT func =

(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(context.instance,"vkCreateDebugUtilsMessengerEXT");

KASSERT_MSG(func,"Failed to create debug messenger!");

VK_CHECK(func(context.instance,&debug_create_info,context.allocator,&context.debug_messenger));

KDEBUG("Vulkan debugger created");

KDEBUG("Creating Vulkan surface...");

if(!platform_create_vulkan_surface(plat_state,&context))

{

KERROR("Failed to create platform surface!");

return false;

}

KDEBUG("Vulkan surface created.");

#endif

//Device creation

if(!vulkan_device_create(&context))

{

KERROR("Failed to create device.");

return false;

}

//Swapchain

vulkan_swapchain_create(

&context,

context.framebuffer_height,

context.framebuffer_width,

&context.swapchain);

vulkan_renderpass_create(

&context,

&context.main_renderpass,

0,0,context.framebuffer_width,context.framebuffer_height,

0.0f,0.0f,0.2f,1.0f,

1.0f,

0

);

//Swapchain framebuffers

context.swapchain.framebuffers = darray_reserve(vulkan_framebuffer,context.swapchain.image_count);

regenerate_framebuffers(backend,&context.swapchain,&context.main_renderpass);

//Create command buffers

create_command_buffers(backend);

//Create command buffers

context.image_available_semaphores = darray_reserve(VkSemaphore,context.swapchain.max_frames_in_flight);

context.queue_complete_semaphores = darray_reserve(VkSemaphore,context.swapchain.max_frames_in_flight);

context.in_flight_fences = darray_reserve(vulkan_fence,context.swapchain.max_frames_in_flight);

for(u8 i =0;i<context.swapchain.max_frames_in_flight;++i)

{

VkSemaphoreCreateInfo semaphore_create_info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};

vkCreateSemaphore(context.device.logical_device,&semaphore_create_info,context.allocator,&context.image_available_semaphores[i]);

vkCreateSemaphore(context.device.logical_device,&semaphore_create_info,context.allocator,&context.queue_complete_semaphores[i]);

vulkan_fence_create(&context,true,&context.in_flight_fences[i]);

}

//by list

context.images_in_flight = darray_reserve(vulkan_fence,context.swapchain.image_count);

for(u32 i = 0;i<context.swapchain.image_count;++i)

{

context.images_in_flight[i] = 0;

}

if(!vulkan_object_shader_create(&context,&context.object_shader))

{

KERROR("Error loading built-in basic_lighting shader.");

return false;

}

create_buffers(&context);

//TODO:compary test code

const u32 vert_count = 4;

vertex_3d verts[vert_count];

kzero_memory(verts,sizeof(vertex_3d)*vert_count);

const f32 f = 10.0f;

verts[0].position.x = 0.5 * f;

verts[0].position.y = -0.5*f;

verts[1].position.x = 0.5*f;

verts[1].position.y = 0.5*f;

verts[2].position.x = -0.5*f;

verts[2].position.y = 0.5*f;

verts[3].position.x = 0.5*f;

verts[3].position.y = -0.5*f;

const u32 index_count = 6;

u32 indices[index_count] = {0,1,2,0,3,1};

upload_data_range(&context,context.device.graphics_command_pool,0,context.device.graphics_queue,&context.object_vertex_buffer,0,sizeof(vertex_3d)*vert_count,verts);

upload_data_range(&context,context.device.graphics_command_pool,0,context.device.graphics_queue,&context.object_index_buffer,0,sizeof(u32)*index_count,indices);

KINFO("Vulkan renderer initialize successfully.");

return true;

}

void vulkan_renderer_backend_shutdown(renderer_backend* backend)

{

vkDeviceWaitIdle(context.device.logical_device);

vulkan_buffer_destroy(&context,&context.object_vertex_buffer);

vulkan_buffer_destroy(&context,&context.object_index_buffer);

vulkan_object_shader_destroy(&context,&context.object_shader);

//Sync objects

for(u8 i = 0;i<context.swapchain.max_frames_in_flight;++i)

{

if(context.image_available_semaphores[i])

{

vkDestroySemaphore(

context.device.logical_device,

context.image_available_semaphores[i],

context.allocator

);

context.image_available_semaphores[i] = 0;

}

if(context.queue_complete_semaphores[i])

{

vkDestroySemaphore(

context.device.logical_device,

context.queue_complete_semaphores[i],

context.allocator

);

context.queue_complete_semaphores[i] = 0;

}

vulkan_fence_destroy(&context,&context.in_flight_fences[i]);

}

darray_destroy(context.image_available_semaphores);

context.image_available_semaphores = 0;

darray_destroy(context.queue_complete_semaphores);

context.queue_complete_semaphores = 0;

darray_destroy(context.in_flight_fences);

context.in_flight_fences = 0;

darray_destroy(context.images_in_flight);

context.images_in_flight = 0;

//Command buffers

for(u32 i = 0;i<context.swapchain.image_count;++i)

{

if(context.graphics_command_buffers[i].handle)

{

vulkan_command_buffer_free(

&context,

context.device.graphics_command_pool,

&context.graphics_command_buffers[i]

);

context.graphics_command_buffers[i].handle = 0;

}

}

darray_destroy(context.graphics_command_buffers);

context.graphics_command_buffers = 0;

vulkan_renderpass_destroy(&context,&context.main_renderpass);

vulkan_swapchain_destroy(&context,&context.swapchain);

KDEBUG("Destroying vulkan device...");

vulkan_device_destroy(&context);

KDEBUG("Destroying Vulkan surface...");

if(context.surface)

{

vkDestroySurfaceKHR(context.instance,context.surface,context.allocator);

context.surface = 0;

}

KDEBUG("Destroying Vulkan debugger...");

if(context.debug_messenger)

{

PFN_vkDestroyDebugUtilsMessengerEXT func =

(PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(context.instance,"vkDestroyDebugUtilsMessengerEXT");

func(context.instance,context.debug_messenger,context.allocator);

}

KDEBUG("Destroying Vulkan instance...");

vkDestroyInstance(context.instance,context.allocator);

}

void vulkan_renderer_backend_on_resized(renderer_backend* backend,u16 width,u16 height)

{

cached_framebuffer_width = width;

cached_framebuffer_height = height;

context.framebuffer_size_generation++;

KINFO("Vulkan renderer backend->resized: %i/%i/%ilu",width,height,context.framebuffer_size_generation);

}

b8 vulkan_renderer_backend_begin_frame(renderer_backend*backend,f32 delta_time)

{

vulkan_device* device = &context.device;

//Check if recreating swap chain add boot out

if(context.recreating_swapchain)

{

VkResult result = vkDeviceWaitIdle(device->logical_device);

if(!vulkan_result_is_success(result))

{

KERROR("vulkan_renderer_backend_begin_frame vkDeviceWaitIdle (1) failed: '%s",vulkan_result_string(result,true));

return false;

}

KINFO("Recreating swapchain,booting.");

return false;

}

//Check if the framebuffer

if(context.framebuffer_size_generation != context.framebuffer_size_last_generation)

{

VkResult result = vkDeviceWaitIdle(device->logical_device);

if(!vulkan_result_is_success(result))

{

KERROR("vulkan_renderer_backend_begin_frame vkDeviceWaitIdle (2) failed: '%s'",vulkan_result_string(result,true));

return false;

}

if(!recreate_swapchain(backend))

{

return false;

}

KINFO("Resized , booting");

return false;

}

if(!vulkan_fence_wait(

&context,

&context.in_flight_fences[context.current_frame],

UINT64_MAX

))

{

KWARN("In flight fence wait failure!");

return false;

}

if(

!vulkan_swapchain_acquire_next_image_index(

&context,

&context.swapchain,

UINT64_MAX,

context.image_available_semaphores[context.current_frame],

0,

&context.image_index

))

{

return false;

}

//Begin recording commands

vulkan_command_buffer* command_buffer = &context.graphics_command_buffers[context.image_index];

vulkan_command_buffer_reset(command_buffer);

vulkan_command_buffer_begin(command_buffer,false,false,false);

//Dynamic state

VkViewport viewport;

viewport.x = 0.0f;

viewport.y = (f32)context.framebuffer_height;

viewport.width = (f32)context.framebuffer_width;

viewport.height = -(f32)context.framebuffer_height;

viewport.minDepth = 0.0f;

viewport.maxDepth = 1.0f;

//Scissor

VkRect2D scissor;

scissor.offset.x = scissor.offset.y = 0;

scissor.extent.width = context.framebuffer_width;

scissor.extent.height = context.framebuffer_height;

vkCmdSetViewport(command_buffer->handle,0,1,&viewport);

vkCmdSetScissor(command_buffer->handle,0,1,&scissor);

context.main_renderpass.w = context.framebuffer_width;

context.main_renderpass.h = context.framebuffer_height;

//Begin the render pass/

vulkan_renderpass_begin(

command_buffer,

&context.main_renderpass,

context.swapchain.framebuffers[context.image_index].handle

);

//temporary test code

return true;

}

/*

void vulkan_renderer_update_global_state(mat4 projection,mat4 view,vec3 view_position,vec4 ambient_colour,i32 mode)

{

vulkan_command_buffer* command_buffer = &context.graphics_command_buffers[context.image_index];

vulkan_object_shader_use(&context,&context.object_shader);

context.object_shader.global_ubo.projection = projection;

context.object_shader.global_ubo.view = view;

//TODO: other ubo properties

vulkan_object_shader_update_global_state(&context,&context.object_shader);

vulkan_object_shader_use(&context,&context.object_shader);

VkDeviceSize offsets[1] = {0};

vkCmdBindVertexBuffers(command_buffer->handle,0,1,&context.object_vertex_buffer.handle,(VkDeviceSize*)offsets);

vkCmdBindIndexBuffer(command_buffer->handle,context.object_index_buffer.handle,0,VK_INDEX_TYPE_UINT32);

//Draw

vkCmdDrawIndexed(command_buffer->handle,6,1,0,0,0);

}

*/

void vulkan_renderer_update_global_state(mat4 projection, mat4 view, vec3 view_position, vec4 ambient_colour, i32 mode)

{

vulkan_command_buffer* command_buffer = &context.graphics_command_buffers[context.image_index];

vulkan_object_shader_use(&context, &context.object_shader);

context.object_shader.global_ubo.projection = projection;

context.object_shader.global_ubo.view = view;

//TODO: other ubo properties

vulkan_object_shader_update_global_state(&context, &context.object_shader);

}

b8 vulkan_renderer_backend_end_frame(renderer_backend* backend,f32 delta_time)

{

vulkan_command_buffer* command_buffer = &context.graphics_command_buffers[context.image_index];

//End renderpass

vulkan_renderpass_end(command_buffer,&context.main_renderpass);

vulkan_command_buffer_end(command_buffer);

//Make sure the previous frame is not using this image

if(context.images_in_flight[context.image_index] != VK_NULL_HANDLE)

{

vulkan_fence_wait(

&context,

context.images_in_flight[context.image_index],

UINT64_MAX);

}

context.images_in_flight[context.image_index] = &context.in_flight_fences[context.current_frame];

vulkan_fence_reset(&context,&context.in_flight_fences[context.current_frame]);

VkSubmitInfo submit_info = {VK_STRUCTURE_TYPE_SUBMIT_INFO};

//Command buffers to be executed

submit_info.commandBufferCount = 1;

submit_info.pCommandBuffers = &command_buffer->handle;

//The semaphores to be signaled when the queue is complete

submit_info.signalSemaphoreCount = 1;

submit_info.pSignalSemaphores = &context.queue_complete_semaphores[context.current_frame];

submit_info.waitSemaphoreCount = 1;

submit_info.pWaitSemaphores = &context.image_available_semaphores[context.current_frame];

VkPipelineStageFlags flags[1] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};

submit_info.pWaitDstStageMask=flags;

VkResult result = vkQueueSubmit(

context.device.graphics_queue,

1,

&submit_info,

context.in_flight_fences[context.current_frame].handle);

if(result!=VK_SUCCESS)

{

KERROR("vkQueueSubmit failed with result: %s",vulkan_result_string(result,true));

return false;

}

vulkan_command_buffer_update_submitted(command_buffer);

//Give the image back to the swapchain

vulkan_swapchain_present(

&context,

&context.swapchain,

context.device.graphics_queue,

context.device.present_queue,

context.queue_complete_semaphores[context.current_frame],

context.image_index

);

return true;

}

void vulkan_backend_update_object(mat4 model)

{

vulkan_command_buffer* command_buffer = &context.graphics_command_buffers[context.image_index];

vulkan_object_shader_update_object(&context,&context.object_shader,model);

vulkan_object_shader_use(&context, &context.object_shader);

VkDeviceSize offsets[1] = {0};

vkCmdBindVertexBuffers(command_buffer->handle, 0, 1, &context.object_vertex_buffer.handle, offsets);

// 确保 context.object_index_buffer.handle 是有效的 VkBuffer 句柄

if (context.object_index_buffer.handle != VK_NULL_HANDLE) {

vkCmdBindIndexBuffer(command_buffer->handle, context.object_index_buffer.handle, 0, VK_INDEX_TYPE_UINT32);

} else {

KERROR("Invalid index buffer handle!");

return; // 或者根据需要进行错误处理

}

//Draw

vkCmdDrawIndexed(command_buffer->handle, 6, 1, 0, 0, 0);

}

VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback(

VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,

VkDebugUtilsMessageTypeFlagsEXT message_types,

const VkDebugUtilsMessengerCallbackDataEXT* callback_data,

void* user_data

)

{

switch(message_severity)

{

default:

case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:

KERROR(callback_data->pMessage);

break;

case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:

KWARN(callback_data->pMessage);

break;

case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:

KINFO(callback_data->pMessage);

break;

case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:

KTRACE(callback_data->pMessage);

break;

}

return VK_FALSE;

}

i32 find_memory_index(u32 type_filter,u32 property_flags)

{

VkPhysicalDeviceMemoryProperties memory_properties;

vkGetPhysicalDeviceMemoryProperties(context.device.physical_device,&memory_properties);

for(u32 i = 0; i<memory_properties.memoryTypeCount;++i)

{

if(type_filter & (1<<i) && (memory_properties.memoryTypes[i].propertyFlags & property_flags) == property_flags)

{

return i;

}

}

KWARN("Unable to find suitable memory type!");

return -1;

}

void create_command_buffers(renderer_backend* backend)

{

if(!context.graphics_command_buffers)

{

context.graphics_command_buffers = darray_reserve(vulkan_command_buffer,context.swapchain.image_count);

for(u32 i = 0;i<context.swapchain.image_count;++i)

{

kzero_memory(&context.graphics_command_buffers[i],sizeof(vulkan_command_buffer));

}

}

for(u32 i = 0;i<context.swapchain.image_count;++i)

{

if(context.graphics_command_buffers[i].handle)

{

vulkan_command_buffer_free(

&context,

context.device.graphics_command_pool,

&context.graphics_command_buffers[i]

);

}

kzero_memory(&context.graphics_command_buffers[i],sizeof(vulkan_command_buffer));

vulkan_command_buffer_allocate(

&context,

context.device.graphics_command_pool,

true,

&context.graphics_command_buffers[i]

);

}

KDEBUG("Vulkan command buffers created");

}

void regenerate_framebuffers(renderer_backend* backend,vulkan_swapchain* swapchain,vulkan_renderpass* renderpass)

{

for(u32 i = 0;i<swapchain->image_count;++i)

{

//make this dynamic based on the currently configured attachemnts

u32 attachment_count =2;

VkImageView attachments[] = {

swapchain->views[i],

swapchain->depth_attachment.view

};

vulkan_framebuffer_create(

&context,

renderpass,

context.framebuffer_width,

context.framebuffer_height,

attachment_count,

attachments,

&context.swapchain.framebuffers[i]

);

}

}

b8 recreate_swapchain(renderer_backend* backend)

{

if(context.recreating_swapchain)

{

KDEBUG("recreating swapchain called when already recreating .Booting.");

return false;

}

if(context.framebuffer_width == 0 || context.framebuffer_height == 0)

{

KDEBUG("recreate_swapchain called when window is <1 in a dimension.Booting.");

return false;

}

//Marking

context.recreating_swapchain = true;

//Wait for any operations to complete

vkDeviceWaitIdle(context.device.logical_device);

for(u32 i = 0;i<context.swapchain.image_count;++i){

context.images_in_flight[i] = 0;

}

//Requery support

vulkan_device_query_swapchain_support(

context.device.physical_device,

context.surface,

&context.device.swapchain_support

);

vulkan_device_detect_depth_format(&context.device);

vulkan_swapchain_recreate(

&context,

cached_framebuffer_width,

cached_framebuffer_height,

&context.swapchain

);

//Sync the framebuffer size with the cached sizes

context.framebuffer_width = cached_framebuffer_width;

context.framebuffer_height = cached_framebuffer_height;

context.main_renderpass.w = context.framebuffer_width;

context.main_renderpass.h = context.framebuffer_height;

cached_framebuffer_width=0;

cached_framebuffer_height=0;

//Update framebuffer size geneartion

context.framebuffer_size_last_generation = context.framebuffer_size_generation;

//cleanup swapchain

for(u32 i = 0;i<context.swapchain.image_count;++i)

{

vulkan_command_buffer_free(&context,context.device.graphics_command_pool,&context.graphics_command_buffers[i]);

}

//Framebuffers

for(u32 i = 0;i <context.swapchain.image_count;++i)

{

vulkan_framebuffer_destroy(&context,&context.swapchain.framebuffers[i]);

}

context.main_renderpass.x = 0;

context.main_renderpass.y = 0;

context.main_renderpass.w = context.framebuffer_width;

context.main_renderpass.h = context.framebuffer_height;

regenerate_framebuffers(backend,&context.swapchain,&context.main_renderpass);

create_command_buffers(backend);

//Clear the recreating flag

context.recreating_swapchain = false;

return true;

}

b8 create_buffers(vulkan_context* context)

{

VkMemoryPropertyFlagBits memory_property_flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;

const u64 vertex_buffer_size = sizeof(vertex_3d)*1024*1024;

if(!vulkan_buffer_create(

context,

vertex_buffer_size,

VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,

memory_property_flags,

true,

&context->object_vertex_buffer

))

{

KERROR("Error creating vertex buffer.");

return false;

}

context->geometry_vertex_offset= 0;

const u64 index_buffer_size = sizeof(u32) * 1024 * 1204;

if(!vulkan_buffer_create(

context,

index_buffer_size,

VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,

memory_property_flags,

true,

&context->object_index_buffer

))

{

KERROR("Error creating index buffer.");

return false;

}

context->geometry_index_offset = 0;

return true;

}

void vulkan_renderer_create_texture(

const char* name,

b8 auto_release,

i32 width,

i32 height,

i32 channel_count,

const u8* pixels,

b8 has_transparency,

texture* out_texture

)

{

out_texture->width = width;

out_texture->height= height;

out_texture->channel_count = channel_count;

out_texture->generation = 0;

out_texture->internal_data = (vulkan_texture_data*)kallocate(sizeof(vulkan_texture_data),MEMORY_TAG_TEXTURE);

vulkan_texture_data* data = (vulkan_texture_data*)out_texture->internal_data;

VkDeviceSize image_size = width * height * channel_count;

//Assume bits a channel

VkFormat image_format = VK_FORMAT_R8G8B8A8_UNORM;

//Create a staging buffer and load data info it

VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;

VkMemoryPropertyFlags memory_prop_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;

vulkan_buffer staging;

vulkan_buffer_create(&context,image_size,usage,memory_prop_flags,true,&staging);

}

相关推荐
君莫愁。1 小时前
【Unity】使用InputSystem实现UI控件与键盘输入绑定以及如何快速制作虚拟摇杆
开发语言·unity·c#·游戏引擎·input system·输入系统
Magnum Lehar4 小时前
vulkan游戏引擎的renderer下的vulkan缓冲区实现
java·前端·游戏引擎
虾球xz4 小时前
游戏引擎学习第309天:用于重叠检测的网格划分
c++·学习·算法·游戏引擎
虾球xz8 小时前
游戏引擎学习第308天:调试循环检测
前端·c++·学习·算法·游戏引擎
一线灵8 小时前
跨平台游戏引擎 Axmol-2.6.0 发布
游戏引擎
虾球xz15 小时前
游戏引擎学习第298天:改进排序键 - 第1部分
人工智能·学习·游戏引擎
Magnum Lehar1 天前
vulkan游戏引擎的platform文件实现
游戏引擎
虾球xz1 天前
游戏引擎学习第307天:排序组可视化
c++·学习·算法·游戏引擎
虾球xz1 天前
游戏引擎学习第306天:图结构排序的调试
c++·学习·算法·游戏引擎