feat: 搭建 Vulkan 1.4 渲染器骨架,绘制旋转 3D 立方体
使用 Vulkan 1.4 现代路径初始化引擎骨架: - 用 Shader Object (VK_EXT_shader_object) 替代传统 VkPipeline - 用 Dynamic Rendering 替代 RenderPass/Framebuffer - 用 Synchronization2 管理 barrier 核心模块: - Window:GLFW 封装,GLFW_NO_API 模式,兼容 Wayland - Log:spdlog 封装 - Types:u32/u64/f32 类型别名 Vulkan 后端: - Device:Instance、PhysicalDevice、LogicalDevice、Queue 及 feature 查询 - Swapchain:Image、ImageView、DepthBuffer、Recreate - ShaderManager:SPIR-V 加载与 ShaderEXT 创建 - CommandManager:CommandPool 与主 CommandBuffer - SyncManager:per-frame Fence 与 ImageAvailable semaphore,per-image RenderFinished semaphore,2 frames in flight - MemoryAllocator:内存子分配器,256MB block,persistent mapping - Buffer:VertexBuffer、IndexBuffer、UniformBuffer 封装 - UniformBuffer:每帧上传 MVP 矩阵 - DescriptorManager:DescriptorSetLayout、DescriptorPool、DescriptorSet 及更新 Renderer: - 协调所有子系统 - 绘制每面不同颜色的旋转 3D 立方体 - 启用 depth test,MVP 矩阵由 GLM 计算 构建: - CMake 组织 Engine 静态库与 App 可执行文件 - glfw、glm、spdlog 通过 add_subdirectory 引入
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/20.
|
||||
//
|
||||
|
||||
#include <Engine/Vulkan/MemoryAllocator.h>
|
||||
#include <Engine/Vulkan/Device.h>
|
||||
#include <Engine/Core/Log.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
MemoryAllocator::MemoryAllocator(Device& device)
|
||||
: m_Device(device)
|
||||
{
|
||||
ENGINE_INFO("MemoryAllocator created");
|
||||
}
|
||||
|
||||
MemoryAllocator::~MemoryAllocator()
|
||||
{
|
||||
const auto& vkDevice = m_Device.GetDevice();
|
||||
|
||||
for (auto& blocks : m_Blocks) {
|
||||
for (auto& block : blocks) {
|
||||
if (block.IsMapped) {
|
||||
vkDevice.unmapMemory(block.Memory);
|
||||
}
|
||||
vkDevice.freeMemory(block.Memory);
|
||||
}
|
||||
blocks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
MemoryAllocator::Allocation MemoryAllocator::Allocate(
|
||||
vk::MemoryRequirements reqs, vk::MemoryPropertyFlags props)
|
||||
{
|
||||
uint32_t typeIndex = m_Device.FindMemoryType(reqs.memoryTypeBits, props);
|
||||
auto& blocks = m_Blocks[typeIndex];
|
||||
|
||||
// 先从已有块里找能放下的
|
||||
for (auto& block : blocks) {
|
||||
vk::DeviceSize alignedOffset =
|
||||
(block.Used + reqs.alignment - 1) & ~(reqs.alignment - 1);
|
||||
|
||||
if (alignedOffset + reqs.size <= block.Size) {
|
||||
Allocation alloc;
|
||||
alloc.Memory = block.Memory;
|
||||
alloc.Offset = alignedOffset;
|
||||
alloc.Size = reqs.size;
|
||||
alloc.MappedPtr = block.IsMapped
|
||||
? static_cast<char*>(block.MappedPtr) + alignedOffset
|
||||
: nullptr;
|
||||
|
||||
block.Used = alignedOffset + reqs.size;
|
||||
return alloc;
|
||||
}
|
||||
}
|
||||
|
||||
// 没有合适的块,创建新块
|
||||
vk::DeviceSize blockSize = std::max(m_DefaultBlockSize, reqs.size);
|
||||
|
||||
vk::MemoryAllocateInfo allocInfo;
|
||||
allocInfo.setAllocationSize(blockSize)
|
||||
.setMemoryTypeIndex(typeIndex);
|
||||
|
||||
Block block;
|
||||
block.Memory = m_Device.GetDevice().allocateMemory(allocInfo);
|
||||
block.Size = blockSize;
|
||||
block.Used = 0;
|
||||
|
||||
// HOST_VISIBLE 的块持久映射
|
||||
if (props & vk::MemoryPropertyFlagBits::eHostVisible) {
|
||||
block.MappedPtr = m_Device.GetDevice().mapMemory(
|
||||
block.Memory, 0, VK_WHOLE_SIZE);
|
||||
block.IsMapped = true;
|
||||
}
|
||||
|
||||
blocks.push_back(block);
|
||||
|
||||
// 从新块分配
|
||||
vk::DeviceSize alignedOffset = (reqs.alignment - 1) & ~(reqs.alignment - 1);
|
||||
|
||||
Allocation alloc;
|
||||
alloc.Memory = block.Memory;
|
||||
alloc.Offset = alignedOffset;
|
||||
alloc.Size = reqs.size;
|
||||
alloc.MappedPtr = block.IsMapped
|
||||
? static_cast<char*>(block.MappedPtr) + alignedOffset
|
||||
: nullptr;
|
||||
|
||||
blocks.back().Used = alignedOffset + reqs.size;
|
||||
|
||||
ENGINE_INFO("MemoryAllocator: new block of {} bytes (type {})",
|
||||
blockSize, typeIndex);
|
||||
|
||||
return alloc;
|
||||
}
|
||||
|
||||
} // namespace Engine
|
||||
Reference in New Issue
Block a user