feat: 显存分配器迁移到 VMA(P1 路线第一项)
- vendored VulkanMemoryAllocator 子模块,唯一实现编译单元 VmaImpl.cpp - MemoryAllocator 重写为 VMA 后端:接口从"Allocate(reqs)+手绑"升级为 "创建即分配即绑定"(CreateBuffer/CreateImage/Destroy/Flush), VMA 要求资源与内存成对释放,约束成单一出口 - Buffer/Texture/RenderGraph 三处调用方迁移;staging 持久映射 + 按分配 精确 flush(原来按整块 flush) - 获得:TLSF 通用分配、DedicatedAllocation 自动启用、memory budget 感知、 内存别名基础(TAA/复用前置) - 编译零错误、validation 零警告、8 秒冒烟通过
This commit is contained in:
@@ -36,11 +36,6 @@ namespace Engine {
|
||||
vk::Buffer m_Buffer;
|
||||
vk::DeviceSize m_Size;
|
||||
|
||||
vk::DeviceMemory m_Memory;
|
||||
vk::DeviceSize m_Offset;
|
||||
|
||||
vk::DeviceSize m_BlockSize; // 所属内存块的总大小
|
||||
|
||||
MemoryAllocator::Allocation m_Allocation;
|
||||
MemoryAllocator& m_Allocator;
|
||||
|
||||
|
||||
@@ -1,68 +1,74 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/20.
|
||||
//
|
||||
// MemoryAllocator:显存分配器,VMA 后端。
|
||||
//
|
||||
// 2026-09-23 从手写 bump+free-list 块分配迁移到 VMA(VulkanMemoryAllocator):
|
||||
// - TLSF 式通用分配 + DedicatedAllocation 扩展自动启用
|
||||
// - 线性分配器(staging 类短命资源自动走线性算法)
|
||||
// - VK_EXT_memory_budget 感知(分配决策参考真实显存余量)
|
||||
// - 为后续内存别名(同一 VkDeviceMemory 多资源重绑)铺路
|
||||
//
|
||||
// 接口哲学:不再是"Allocate(reqs) + 手动 bind"——VMA 明确不推荐把分配与
|
||||
// 绑定拆开。创建即分配即绑定,销毁必须走 Destroy(资源与内存成对释放),
|
||||
// 这是本类存在的意义:把 VMA 的正确用法约束成一个出口。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_MEMORYALLOCATOR_H
|
||||
#define HELLOVULKAN_MEMORYALLOCATOR_H
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include "Engine/Core/Types.h"
|
||||
|
||||
// VMA 内部类型前向声明(实现在 VmaImpl.cpp,头文件不引入 vk_mem_alloc.h)
|
||||
struct VmaAllocator_T;
|
||||
struct VmaAllocation_T;
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Device;
|
||||
|
||||
class MemoryAllocator {
|
||||
public:
|
||||
MemoryAllocator(Device& device);
|
||||
explicit MemoryAllocator(Device& device);
|
||||
~MemoryAllocator();
|
||||
|
||||
MemoryAllocator(const MemoryAllocator&) = delete;
|
||||
MemoryAllocator& operator=(const MemoryAllocator&) = delete;
|
||||
|
||||
// 分配结果:资源句柄 + 分配句柄合一。
|
||||
// Buffer/Image 二选一有值;MappedPtr 仅 HOST_VISIBLE 非空(持久映射)。
|
||||
struct Allocation {
|
||||
vk::DeviceMemory Memory;
|
||||
vk::DeviceSize Offset;
|
||||
vk::DeviceSize Size;
|
||||
vk::Buffer Buffer{};
|
||||
vk::Image Image{};
|
||||
void* MappedPtr = nullptr;
|
||||
|
||||
// 内部用于 Free
|
||||
u32 BlockIndex = 0;
|
||||
u32 TypeIndex = 0;
|
||||
vk::DeviceSize Size = 0;
|
||||
bool Valid = false;
|
||||
|
||||
// VMA 内部句柄(上层不要碰)
|
||||
VmaAllocation_T* Handle = nullptr;
|
||||
};
|
||||
|
||||
Allocation Allocate(vk::MemoryRequirements reqs, vk::MemoryPropertyFlags props);
|
||||
void Free(const Allocation& alloc);
|
||||
// 创建 + 分配 + 绑定一步完成(VMA 惯用法)
|
||||
Allocation CreateBuffer(vk::DeviceSize size, vk::BufferUsageFlags usage,
|
||||
vk::MemoryPropertyFlags props);
|
||||
Allocation CreateImage(const vk::ImageCreateInfo& imageInfo,
|
||||
vk::MemoryPropertyFlags props);
|
||||
|
||||
// 销毁资源并释放分配(按 alloc.Buffer/Image 判断类型),随后 alloc 归零
|
||||
void Destroy(Allocation& alloc);
|
||||
|
||||
// HOST_VISIBLE 非 coherent 写入后冲刷(VMA 内部对 coherent 自动跳过)
|
||||
void Flush(const Allocation& alloc);
|
||||
|
||||
void PrintStats() const;
|
||||
|
||||
private:
|
||||
struct FreeRange {
|
||||
vk::DeviceSize Offset;
|
||||
vk::DeviceSize Size;
|
||||
};
|
||||
|
||||
struct Block {
|
||||
vk::DeviceMemory Memory;
|
||||
vk::DeviceSize Size;
|
||||
vk::DeviceSize Used = 0; // bump 分配用
|
||||
void* MappedPtr = nullptr;
|
||||
bool IsMapped = false;
|
||||
std::vector<FreeRange> FreeList; // 已释放的区域
|
||||
};
|
||||
|
||||
Device& m_Device;
|
||||
std::array<std::vector<Block>, VK_MAX_MEMORY_TYPES> m_Blocks;
|
||||
std::array<vk::DeviceSize, VK_MAX_MEMORY_TYPES> m_TotalAllocated{};
|
||||
|
||||
vk::DeviceSize GetBlockSize(vk::MemoryPropertyFlags props) const;
|
||||
VmaAllocator_T* m_Vma = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Engine
|
||||
|
||||
@@ -52,7 +52,6 @@ namespace Engine {
|
||||
Device& m_Device;
|
||||
vk::Image m_Image;
|
||||
vk::ImageView m_View;
|
||||
vk::DeviceMemory m_Memory;
|
||||
|
||||
vk::Sampler m_Sampler;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user