添加多模型渲染,添加贴图渲染,添加平行光, 暂时不上传assets

This commit is contained in:
2026-09-21 14:07:20 +08:00
parent 381b7c0aa6
commit 7d628f8d8a
37 changed files with 9817 additions and 189 deletions
+1
View File
@@ -13,6 +13,7 @@ namespace Engine {
#define ENGINE_TRACE(...) ::spdlog::trace(__VA_ARGS__)
#define ENGINE_INFO(...) ::spdlog::info(__VA_ARGS__)
#define ENGINE_DEBUG(...) ::spdlog::debug(__VA_ARGS__)
#define ENGINE_WARN(...) ::spdlog::warn(__VA_ARGS__)
#define ENGINE_ERROR(...) ::spdlog::error(__VA_ARGS__)
#define ENGINE_FATAL(...) ::spdlog::critical(__VA_ARGS__)
+92
View File
@@ -0,0 +1,92 @@
//
// Created by atdunbg on 2026/9/21.
//
#ifndef HELLOVULKAN_STATS_H
#define HELLOVULKAN_STATS_H
#include <Engine/Core/Types.h>
#include <mutex>
namespace Engine
{
class Stats
{
public:
static Stats& Get();
// ---- Engine 自己管理的 GPU 内存 ----
void AddTexture(u64 bytes);
void RemoveTexture(u64 bytes);
void AddMesh(u64 vertexBytes, u64 indexBytes);
void RemoveMesh(u64 vertexBytes, u64 indexBytes);
void AddBuffer(u64 bytes);
void RemoveBuffer(u64 bytes);
void AddMemoryBlock(u64 bytes);
void RemoveMemoryBlock(u64 bytes);
void AddMemoryUsed(u64 bytes);
void RemoveMemoryUsed(u64 bytes);
// ---- 每帧统计 ----
void BeginFrame();
void EndFrame();
void AddAllocation(u64 bytes);
void AddDeallocation(u64 bytes);
// ---- 采样进程真实内存 ----
void SampleProcessMemory();
// ---- 打印 ----
void Print() const;
void PrintDetailed() const;
void PrintComparison() const;
private:
Stats() = default;
struct ProcessMemory
{
u64 VmSize = 0; // /proc/self/status VmSize
u64 Rss = 0; // /proc/self/status VmRSS
u64 Pss = 0; // smaps_rollup
u64 SharedClean = 0;
u64 PrivateDirty = 0;
u64 PrivateClean = 0;
};
ProcessMemory ReadProcessMemory() const;
mutable std::mutex m_Mutex;
// 资源计数
u64 m_TextureCount = 0;
u64 m_TextureBytes = 0;
u64 m_MeshCount = 0;
u64 m_MeshBytes = 0;
u64 m_BufferCount = 0;
u64 m_BufferBytes = 0;
// MemoryAllocator
u64 m_MemoryBlockBytes = 0;
u64 m_MemoryUsedBytes = 0;
// 每帧
u64 m_FrameAllocation = 0;
u64 m_FrameDeallocation = 0;
u64 m_TotalAllocation = 0;
u64 m_TotalDeallocation = 0;
// 进程快照
ProcessMemory m_ProcessMem{};
};
#define STATS Engine::Stats::Get()
} // namespace Engine
#endif //HELLOVULKAN_STATS_H
+15
View File
@@ -38,11 +38,26 @@ namespace Engine {
// 需要的 Vulkan 扩展(GLFW 提供)
static std::vector<const char*> GetRequiredExtensions();
// 窗口事件
void GetFramebufferSize(int& width, int& height) const;
bool WasResized() const { return m_FramebufferResized; }
void ResetResizedFlag() { m_FramebufferResized = false; }
// 输入事件系统
bool IsKeyPressed(int key) const;
void GetMouseDelta(float& dx, float& dy);
private:
GLFWwindow* m_Window = nullptr;
u32 m_Width;
u32 m_Height;
std::string m_Title;
bool m_FramebufferResized = false;
static void FramebufferResizeCallback(GLFWwindow* window, int width, int height);
};
} // namespace Engine
+39
View File
@@ -0,0 +1,39 @@
//
// Created by atdunbg on 2026/9/21.
//
#ifndef HELLOVULKAN_MATERIAL_H
#define HELLOVULKAN_MATERIAL_H
#include <Engine/Core/Types.h>
#include <vulkan/vulkan.hpp>
#include <string>
namespace Engine
{
class Device;
class DescriptorManager;
class Texture;
class Material
{
public:
Material(Device& device,
DescriptorManager& descriptorManager,
vk::DescriptorSetLayout layout,
Texture* texture);
~Material();
Material(const Material&) = delete;
Material& operator=(const Material&) = delete;
vk::DescriptorSet GetDescriptorSet() const { return m_DescriptorSet; }
Texture* GetTexture() const { return m_Texture; }
private:
Texture* m_Texture = nullptr;
vk::DescriptorSet m_DescriptorSet;
};
} // namespace Engine
#endif //HELLOVULKAN_MATERIAL_H
+49
View File
@@ -0,0 +1,49 @@
//
// Created by atdunbg on 2026/9/21.
//
#ifndef HELLOVULKAN_MESH_H
#define HELLOVULKAN_MESH_H
#include <Engine/Core/Types.h>
#include <Engine/Renderer/Vertex.h>
#include <vulkan/vulkan.hpp>
#include <vector>
namespace Engine
{
class Device;
class MemoryAllocator;
class Buffer;
class Material;
class Mesh
{
public:
Mesh(Device& device, MemoryAllocator& allocator,
const std::vector<Vertex>& vertices,
const std::vector<u32>& indices,
Scope<Material> material);
~Mesh();
Mesh(const Mesh&) = delete;
Mesh& operator=(const Mesh&) = delete;
void Draw(vk::CommandBuffer cmd) const;
Material* GetMaterial() const { return m_Material.get(); }
u32 GetIndexCount() const { return m_IndexCount; }
private:
Scope<Buffer> m_VertexBuffer;
Scope<Buffer> m_IndexBuffer;
Scope<Material> m_Material;
u32 m_IndexCount = 0;
u64 m_VertexBytes = 0;
u64 m_IndexBytes = 0;
};
} // namespace Engine
#endif //HELLOVULKAN_MESH_H
+64
View File
@@ -0,0 +1,64 @@
//
// Created by atdunbg on 2026/9/21.
//
#ifndef HELLOVULKAN_MODEL_H
#define HELLOVULKAN_MODEL_H
#pragma once
#include <Engine/Core/Types.h>
#include <Engine/Renderer/Mesh.h>
#include <vulkan/vulkan.hpp>
#include <string>
#include <unordered_map>
#include <vector>
struct aiNode;
struct aiMesh;
struct aiScene;
namespace Engine
{
class Device;
class MemoryAllocator;
class DescriptorManager;
class Texture;
class Model
{
public:
Model(Device& device, MemoryAllocator& allocator,
DescriptorManager& descriptorManager,
vk::DescriptorSetLayout textureLayout,
const std::string& path);
~Model();
Model(const Model&) = delete;
Model& operator=(const Model&) = delete;
const std::vector<Scope<Mesh>>& GetMeshes() const { return m_Meshes; }
private:
void LoadModel(const std::string& path);
void ProcessNode(aiNode* node, const aiScene* scene);
Scope<Mesh> ProcessMesh(aiMesh* mesh, const aiScene* scene);
Texture* GetOrLoadTexture(const std::string& path);
Device& m_Device;
MemoryAllocator& m_Allocator;
DescriptorManager& m_DescriptorManager;
vk::DescriptorSetLayout m_TextureLayout;
std::vector<Scope<Mesh>> m_Meshes;
std::string m_ModelPath;
// 纹理缓存:同一路径只加载一次
std::unordered_map<std::string, Scope<Texture>> m_TextureCache;
Scope<Texture> m_DefaultTexture;
};
} // namespace Engine
#endif //HELLOVULKAN_MODEL_H
+27 -4
View File
@@ -11,6 +11,11 @@
#include <vulkan/vulkan.hpp>
#include <chrono>
#include "Engine/Vulkan/Texture.h"
#include <glm/glm.hpp>
#include "Model.h"
namespace Engine {
class Window;
@@ -24,6 +29,11 @@ namespace Engine {
class Buffer;
class UniformBuffer;
struct Object {
glm::mat4 transform = glm::mat4(1.0f);
Model* model = nullptr;
};
class Renderer {
public:
Renderer(Window& window);
@@ -49,13 +59,16 @@ namespace Engine {
Scope<SyncManager> m_SyncManager;
Scope<CommandManager> m_CommandManager;
Scope<Buffer> m_VertexBuffer;
Scope<Buffer> m_IndexBuffer;
Scope<Model> m_Model;
std::vector<Object> m_Objects;
Scope<UniformBuffer> m_UniformBuffer;
vk::DescriptorSetLayout m_DescriptorSetLayout;
vk::PipelineLayout m_PipelineLayout;
vk::DescriptorSet m_DescriptorSet;
vk::DescriptorSetLayout m_UBOSetLayout;
vk::DescriptorSet m_UBODescriptorSet;
vk::DescriptorSetLayout m_TextureSetLayout;
vk::ShaderEXT m_VertShader;
vk::ShaderEXT m_FragShader;
@@ -66,6 +79,16 @@ namespace Engine {
static constexpr u32 kMaxFramesInFlight = 2;
u32 m_CurrentFrame = 0;
// 相机
glm::vec3 m_CameraPos = glm::vec3(0.0f, 0.0f, 7.0f);
f32 m_CameraYaw = -90.0f; // 朝向 -Z
f32 m_CameraPitch = 0.0f;
f32 m_CameraSpeed = 2.5f;
f32 m_MouseSensitivity = 0.1f;
f32 m_DeltaTime = 0.016f;
f32 m_LastFrameTime = 0.0f;
std::chrono::steady_clock::time_point m_StartTime;
};
+51
View File
@@ -0,0 +1,51 @@
//
// Created by atdunbg on 2026/9/21.
//
#ifndef HELLOVULKAN_VERTEX_H
#define HELLOVULKAN_VERTEX_H
#include <glm/glm.hpp>
#include <vulkan/vulkan.hpp>
namespace Engine {
struct Vertex {
glm::vec3 position;
glm::vec3 normal;
glm::vec2 uv;
static vk::VertexInputBindingDescription2EXT GetBindingDescription() {
vk::VertexInputBindingDescription2EXT binding;
binding.setBinding(0)
.setStride(sizeof(Vertex))
.setInputRate(vk::VertexInputRate::eVertex)
.setDivisor(1);
return binding;
}
static std::array<vk::VertexInputAttributeDescription2EXT, 3> GetAttributeDescriptions() {
std::array<vk::VertexInputAttributeDescription2EXT, 3> attrs;
attrs[0].setLocation(0)
.setBinding(0)
.setFormat(vk::Format::eR32G32B32Sfloat)
.setOffset(offsetof(Vertex, position));
attrs[1].setLocation(1)
.setBinding(0)
.setFormat(vk::Format::eR32G32B32Sfloat)
.setOffset(offsetof(Vertex, normal));
attrs[2].setLocation(2)
.setBinding(0)
.setFormat(vk::Format::eR32G32Sfloat)
.setOffset(offsetof(Vertex, uv));
return attrs;
}
};
} // namespace Engine
#endif //HELLOVULKAN_VERTEX_H
+5
View File
@@ -8,6 +8,8 @@
#include <vulkan/vulkan.hpp>
#include "MemoryAllocator.h"
namespace Engine {
class Device;
@@ -39,6 +41,9 @@ namespace Engine {
vk::DeviceSize m_BlockSize; // 所属内存块的总大小
MemoryAllocator::Allocation m_Allocation;
MemoryAllocator& m_Allocator;
void* m_MappedPtr = nullptr;
};
@@ -8,11 +8,18 @@
#include <Engine/Core/Types.h>
#include <vulkan/vulkan.hpp>
#include <vector>
namespace Engine {
class Device;
struct DescriptorBinding {
u32 Binding;
vk::DescriptorType Type;
vk::ShaderStageFlags Stages;
};
class DescriptorManager {
public:
DescriptorManager(Device& device);
@@ -21,18 +28,24 @@ namespace Engine {
DescriptorManager(const DescriptorManager&) = delete;
DescriptorManager& operator=(const DescriptorManager&) = delete;
// 创建一个描述符布局:一个 binding,类型是 Uniform Buffer
vk::DescriptorSetLayout CreateUniformBufferLayout(u32 binding);
vk::DescriptorSetLayout CreateLayout(const std::vector<DescriptorBinding>& bindings);
vk::PipelineLayout CreatePipelineLayout(vk::DescriptorSetLayout layout);
// 根据布局分配一个描述符集
vk::DescriptorSet AllocateDescriptorSet(vk::DescriptorSetLayout layout);
// 把 Buffer 绑到描述符集的某个 binding
void UpdateUniformBuffer(vk::DescriptorSet set, u32 binding,
vk::Buffer buffer, u64 size);
void UpdateTexture(vk::DescriptorSet set, u32 binding,
vk::Sampler sampler, vk::ImageView view);
// 单个 set layout 的旧接口(保留)
vk::PipelineLayout CreatePipelineLayout(vk::DescriptorSetLayout layout,
u32 pushConstantSize);
// 多 set layout 的新接口
vk::PipelineLayout CreatePipelineLayout(
const std::vector<vk::DescriptorSetLayout>& layouts,
u32 pushConstantSize);
private:
Device& m_Device;
@@ -43,4 +56,5 @@ namespace Engine {
} // namespace Engine
#endif //HELLOVULKAN_DESCRIPTORMANAGER_H
+23 -3
View File
@@ -6,10 +6,14 @@
#define HELLOVULKAN_MEMORYALLOCATOR_H
#pragma once
#include <vulkan/vulkan.hpp>
#include <array>
#include <vector>
#include "Engine/Core/Types.h"
namespace Engine {
class Device;
@@ -26,23 +30,39 @@ namespace Engine {
vk::DeviceMemory Memory;
vk::DeviceSize Offset;
vk::DeviceSize Size;
void* MappedPtr; // HOST_VISIBLE 时才有
void* MappedPtr = nullptr;
// 内部用于 Free
u32 BlockIndex = 0;
u32 TypeIndex = 0;
bool Valid = false;
};
Allocation Allocate(vk::MemoryRequirements reqs, vk::MemoryPropertyFlags props);
void Free(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;
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;
vk::DeviceSize m_DefaultBlockSize = 256ull * 1024 * 1024; // 256 MB
std::array<vk::DeviceSize, VK_MAX_MEMORY_TYPES> m_TotalAllocated{};
vk::DeviceSize GetBlockSize(vk::MemoryPropertyFlags props) const;
};
} // namespace Engine
+5 -3
View File
@@ -30,14 +30,16 @@ namespace Engine {
ShaderManager(const ShaderManager&) = delete;
ShaderManager& operator=(const ShaderManager&) = delete;
// layout 可选:为 nullptr 时不使用描述符
// 改成接受 vector
ShaderObject CreateFromFile(const std::string& spvPath,
vk::ShaderStageFlagBits stage,
vk::DescriptorSetLayout layout = nullptr);
const std::vector<vk::DescriptorSetLayout>& layouts = {},
u32 pushConstantSize = 0);
ShaderObject CreateFromSPIRV(const std::vector<u32>& spirv,
vk::ShaderStageFlagBits stage,
vk::DescriptorSetLayout layout = nullptr);
const std::vector<vk::DescriptorSetLayout>& layouts = {},
u32 pushConstantSize = 0);
void Destroy(const ShaderObject& shader);
+56
View File
@@ -0,0 +1,56 @@
//
// Created by atdunbg on 2026/9/20.
//
#ifndef HELLOVULKAN_TEXTURE_H
#define HELLOVULKAN_TEXTURE_H
#pragma once
#include <Engine/Core/Types.h>
#include <vulkan/vulkan.hpp>
#include <string>
#include "MemoryAllocator.h"
namespace Engine {
class Device;
class MemoryAllocator;
class Texture {
public:
Texture(Device& device, MemoryAllocator& allocator, const std::string& path);
~Texture();
Texture(const Texture&) = delete;
Texture& operator=(const Texture&) = delete;
vk::Image Get() const { return m_Image; }
vk::ImageView GetView() const { return m_View; }
u32 GetWidth() const { return m_Width; }
u32 GetHeight() const { return m_Height; }
vk::Sampler GetSampler() const { return m_Sampler; }
private:
Device& m_Device;
vk::Image m_Image;
vk::ImageView m_View;
vk::DeviceMemory m_Memory;
vk::Sampler m_Sampler;
u32 m_Width = 0;
u32 m_Height = 0;
u64 m_TextureBytes = 0;
MemoryAllocator::Allocation m_ImageAllocation;
MemoryAllocator& m_Allocator;
};
} // namespace Engine
#endif //HELLOVULKAN_TEXTURE_H