vulkan游戏引擎的renderer下的backend

发布于:2025-05-25 ⋅ 阅读:(18) ⋅ 点赞:(0)

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



 

    }


 


网站公告

今日签到

点亮在社区的每一天
去签到