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,95 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/20.
|
||||
//
|
||||
|
||||
|
||||
#include <Engine/Vulkan/ShaderManager.h>
|
||||
#include <Engine/Vulkan/Device.h>
|
||||
#include <Engine/Core/Log.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
ShaderManager::ShaderManager(Device& device)
|
||||
: m_Device(device)
|
||||
{
|
||||
}
|
||||
|
||||
ShaderManager::~ShaderManager()
|
||||
{
|
||||
}
|
||||
|
||||
ShaderObject ShaderManager::CreateFromFile(const std::string& spvPath,
|
||||
vk::ShaderStageFlagBits stage,
|
||||
vk::DescriptorSetLayout layout)
|
||||
{
|
||||
auto spirv = ReadSPIRV(spvPath);
|
||||
if (spirv.empty()) {
|
||||
ENGINE_ERROR("Failed to read SPIR-V: {}", spvPath);
|
||||
return { nullptr, stage };
|
||||
}
|
||||
return CreateFromSPIRV(spirv, stage, layout);
|
||||
}
|
||||
|
||||
ShaderObject ShaderManager::CreateFromSPIRV(const std::vector<u32>& spirv,
|
||||
vk::ShaderStageFlagBits stage,
|
||||
vk::DescriptorSetLayout layout)
|
||||
{
|
||||
// 下一个阶段:顶点 → 片段
|
||||
vk::ShaderStageFlags nextStage = {};
|
||||
if (stage == vk::ShaderStageFlagBits::eVertex) {
|
||||
nextStage = vk::ShaderStageFlagBits::eFragment;
|
||||
}
|
||||
|
||||
vk::ShaderCreateInfoEXT createInfo;
|
||||
createInfo.setStage(stage)
|
||||
.setNextStage(nextStage)
|
||||
.setCodeType(vk::ShaderCodeTypeEXT::eSpirv)
|
||||
.setCodeSize(spirv.size() * sizeof(u32))
|
||||
.setPCode(spirv.data())
|
||||
.setPName("main");
|
||||
|
||||
// 有布局就传进去
|
||||
if (layout) {
|
||||
createInfo.setSetLayouts(layout);
|
||||
}
|
||||
|
||||
vk::ShaderEXT shader;
|
||||
try {
|
||||
auto result = m_Device.GetDevice().createShadersEXT(createInfo);
|
||||
shader = result.value[0];
|
||||
}
|
||||
catch (const vk::SystemError& e) {
|
||||
ENGINE_ERROR("Failed to create shader object: {}", e.what());
|
||||
return { nullptr, stage };
|
||||
}
|
||||
|
||||
return { shader, stage };
|
||||
}
|
||||
|
||||
void ShaderManager::Destroy(const ShaderObject& shader)
|
||||
{
|
||||
if (shader.Handle) {
|
||||
m_Device.GetDevice().destroyShaderEXT(shader.Handle);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<u32> ShaderManager::ReadSPIRV(const std::string& path)
|
||||
{
|
||||
std::ifstream file(path, std::ios::binary | std::ios::ate);
|
||||
if (!file) {
|
||||
ENGINE_ERROR("Failed to open: {}", path);
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t size = file.tellg();
|
||||
std::vector<u32> buffer(size / sizeof(u32));
|
||||
file.seekg(0);
|
||||
file.read(reinterpret_cast<char*>(buffer.data()), size);
|
||||
file.close();
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
} // namespace Engine
|
||||
Reference in New Issue
Block a user