vulkan游戏引擎的renderer下的vulkan缓冲区实现

1.vulkan_buffer.h

#pragma once

#include "vulkan_types.inl"

b8 vulkan_buffer_create(

vulkan_context* context,

u64 size,

VkBufferUsageFlagBits usage,

u32 memory_property_flags,

b8 bind_on_create,

vulkan_buffer* out_buffer

);

void vulkan_buffer_destroy(vulkan_context* context,vulkan_buffer* buffer);

b8 vulkan_buffer_resize(

vulkan_context* context,

u64 new_size,

vulkan_buffer* buffer,

VkQueue queue,

VkCommandPool pool

);

void vulkan_buffer_bind(vulkan_context* context,vulkan_buffer* buffer,u64 offset);

void* vulkan_buffer_lock_memory(vulkan_context* context,vulkan_buffer* buffer,u64 offset,u64 size,u32 flags);

void vulkan_buffer_unlock_memory(vulkan_context* context, vulkan_buffer* buffer);

void vulkan_buffer_load_data(vulkan_context* context,vulkan_buffer* buffer,u64 offset,u64 size,u32 flags,const void* data);

void vulkan_buffer_copy_to(

vulkan_context* context,

VkCommandPool pool,

VkFence fence,

VkQueue queue,

VkBuffer source,

u64 source_offset,

VkBuffer dest,

u64 dest_offset,

u64 size

);

2.vulkan_buffer.c

#include "vulkan_buffer.h"

#include "vulkan_device.h"

#include "vulkan_command_buffer.h"

#include "vulkan_types.inl"

#include "vulkan_utils.h"

#include "core/logger.h"

#include "core/kmemory.h"

b8 vulkan_buffer_create(

vulkan_context* context,

u64 size,

VkBufferUsageFlagBits usage,

u32 memory_property_flags,

b8 bind_on_create,

vulkan_buffer* out_buffer

)

{

kzero_memory(out_buffer,sizeof(vulkan_buffer));

out_buffer->total_size = size;

out_buffer->usage = usage;

out_buffer->memory_property_flags = memory_property_flags;

VkBufferCreateInfo buffer_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};

buffer_info.size = size;

buffer_info.usage = usage;

buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

VK_CHECK(vkCreateBuffer(context->device.logical_device,&buffer_info,context->allocator,&out_buffer->handle));

//Gather memory requirements

VkMemoryRequirements requirements;

vkGetBufferMemoryRequirements(context->device.logical_device,out_buffer->handle,&requirements);

out_buffer->memory_index = context->find_memory_index(requirements.memoryTypeBits,out_buffer->memory_property_flags);

if(out_buffer->memory_index == -1)

{

KERROR("Unable to create vulkan buffer because the reuqired memory type index was not found.");

return false;

}

//Allocacte memory info

VkMemoryAllocateInfo allocate_info = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};

allocate_info.allocationSize = requirements.size;

allocate_info.memoryTypeIndex = (u32)out_buffer->memory_index;

//Allocate the memory

VkResult result = vkAllocateMemory(

context->device.logical_device,

&allocate_info,

context->allocator,

&out_buffer->memory

);

if(result != VK_SUCCESS)

{

KERROR("Unable to create vulkan buffer because the required memory allocation failed.Error: %i",result);

return false;

}

if(bind_on_create)

{

vulkan_buffer_bind(context,out_buffer,0);

}

return true;

}

void vulkan_buffer_destroy(vulkan_context* context,vulkan_buffer* buffer)

{

if(buffer->memory)

{

vkFreeMemory(context->device.logical_device,buffer->memory,context->allocator);

buffer->memory = 0;

}

if(buffer->handle)

{

vkDestroyBuffer(context->device.logical_device,buffer->handle,context->allocator);

buffer->handle = 0;

}

buffer->total_size= 0;

buffer->usage = 0;

buffer->is_locked = false;

}

b8 vulkan_buffer_resize(

vulkan_context* context,

u64 new_size,

vulkan_buffer* buffer,

VkQueue queue,

VkCommandPool pool

)

{

//Create new buffer

VkBufferCreateInfo buffer_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};

buffer_info.size = new_size;

buffer_info.usage = buffer->usage;

buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

VkBuffer new_buffer;

VK_CHECK(vkCreateBuffer(context->device.logical_device,&buffer_info,context->allocator,&new_buffer));

//Gather memory requirements

VkMemoryRequirements requirements;

vkGetBufferMemoryRequirements(context->device.logical_device,new_buffer,&requirements);

//Allocaate memory info

VkMemoryAllocateInfo allocate_info = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};

allocate_info.allocationSize = requirements.size;

allocate_info.memoryTypeIndex = (u32)buffer->memory_index;

//Alocate the memory

VkDeviceMemory new_memory;

VkResult result = vkAllocateMemory(context->device.logical_device,&allocate_info,context->allocator,&new_memory);

if(result!=VK_SUCCESS)

{

KERROR("Unable to resize vulkan buffer because the required memory allocation failed. Error: %i",result);

return false;

}

//Bind

VK_CHECK(vkBindBufferMemory(context->device.logical_device,new_buffer,new_memory,0));

//copy over the data

vulkan_buffer_copy_to(context,pool,0,queue,buffer->handle,0,new_buffer,0,buffer->total_size);

vkDeviceWaitIdle(context->device.logical_device);

//Destroy the old

if(buffer->memory)

{

vkFreeMemory(context->device.logical_device,buffer->memory,context->allocator);

buffer->memory = 0;

}

if(buffer->handle)

{

vkDestroyBuffer(context->device.logical_device,buffer->handle,context->allocator);

buffer->handle = 0;

}

//Set new properties

buffer->total_size = new_size;

buffer->memory = new_memory;

buffer->handle = new_buffer;

return true;

}

void vulkan_buffer_bind(vulkan_context* context,vulkan_buffer* buffer,u64 offset)

{

VK_CHECK(vkBindBufferMemory(context->device.logical_device,buffer->handle,buffer->memory,offset));

}

void* vulkan_buffer_lock_memory(vulkan_context* context,vulkan_buffer* buffer,u64 offset,u64 size,u32 flags)

{

void* data;

VK_CHECK(vkMapMemory(context->device.logical_device,buffer->memory,offset,size,flags,&data));

return data;

}

void vulkan_buffer_unlock_memory(vulkan_context* context,vulkan_buffer* buffer)

{

vkUnmapMemory(context->device.logical_device,buffer->memory);

}

void vulkan_buffer_load_data(vulkan_context* context,vulkan_buffer* buffer,u64 offset,u64 size,u32 flags,const void* data)

{

void* data_ptr;

VK_CHECK(vkMapMemory(context->device.logical_device,buffer->memory,offset,size,flags,&data_ptr));

kcopy_memory(data_ptr,data,size);

vkUnmapMemory(context->device.logical_device,buffer->memory);

}

void vulkan_buffer_copy_to(

vulkan_context* context,

VkCommandPool pool,

VkFence fence,

VkQueue queue,

VkBuffer source,

u64 source_offset,

VkBuffer dest,

u64 dest_offset,

u64 size

)

{

vkQueueWaitIdle(queue);

vulkan_command_buffer temp_command_buffer;

vulkan_command_buffer_allocate_and_begin_single_use(context,pool,&temp_command_buffer);

VkBufferCopy copy_region;

copy_region.srcOffset = source_offset;

copy_region.dstOffset = dest_offset;

copy_region.size = size;

vkCmdCopyBuffer(temp_command_buffer.handle,source,dest,1,&copy_region);

vulkan_command_buffer_end_single_use(context,pool,&temp_command_buffer,queue);

}

相关推荐
陈随易2 小时前
在 VSCode 里,把项目一键部署到服务器
前端·后端·程序员
Highcharts.js2 小时前
教程:基于 React + Highcharts 构建一个单页应用程序、按需数据拉取与图表渲染
开发语言·前端·数据结构·react.js·前端框架·highcharts·页面应用
To_OC2 小时前
我被 useState 坑了两次之后,终于把它的脾气摸透了
前端·javascript·react.js
鱼樱前端2 小时前
我用 Claude Code 后,编码效率翻 3 倍。但更值钱的是别的。
前端·后端·ai编程
_lucas3 小时前
给知识库网站接入AI问答
前端·ai编程·全栈
头发还在的女程序员3 小时前
医院陪诊管理系统怎么选择?——2026 年选型避坑与架构参考
java·开发语言·陪诊系统·陪诊app·医院陪诊陪护
前端糕手4 小时前
前端面试题大全:JavaScript + Vue3 + React + TypeScript + 工程化 + 性能优化
前端
CodeStats4 小时前
【Spring事务】Spring事务注解 @Transactional 完整体系:从 MySQL 隔离级别到 MyBatis 原理详解
java·spring·mybatis·事务·transactional
我命由我123454 小时前
Android 开发问题:为 PDFView 设置一个带有黑色边框的背景 drawable,但边框没有生效
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
我不叫武5 小时前
一个用 Rust 写的离线编码查询桌面工具
前端