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);

}

相关推荐
90后小陈老师2 小时前
Unity教学 项目2 2D闯关游戏
游戏·unity·游戏引擎
噗噗夹的TA之旅3 小时前
Unity Shader 学习20:URP LitForwardPass PBR 解析
学习·unity·游戏引擎·图形渲染·技术美术
nnsix3 小时前
Unity ReferenceFinder插件 多选资源查找bug解决
unity·游戏引擎·bug
gzroy4 小时前
Unity Shader Graph实现全息瞄准器
unity·游戏引擎
90后小陈老师7 小时前
Unity教学 基础介绍
unity·游戏引擎
90后小陈老师7 小时前
Unity教学 项目3 3D坦克大战
3d·unity·游戏引擎
秦奈9 小时前
Unity复习学习随笔(五):Unity基础
学习·unity·游戏引擎
nnsix10 小时前
Unity ReferenceFinder插件 窗口中选择资源时 同步选择Assets下的资源
java·unity·游戏引擎
ۓ明哲ڪ12 小时前
Unity功能——关闭脚本自动编译(Unity2021.3)
unity·游戏引擎
90后小陈老师12 小时前
Unity教学 项目4 3D求生枪手
3d·unity·游戏引擎