- ShaderObject 值类型 → ShaderRef(shared_ptr 语义,UE TShaderRef 对标):拷贝共享所有权,最后一个引用析构时自动销毁 VkShaderEXT, 持有方零清理代码——"新 pass 忘销毁"整类 bug 被机制消灭 - 删除公开 Destroy 与全部持有方手工 destroyShaderEXT(8 处); 各类析构只清 sampler/layout/set 等其余原生句柄 - RecordFullscreen 参数收窄为 const ShaderRef&(裸 handle 无法 再被误传);bind 点统一 GetHandle() - Outline/SelectionMask 撤掉上一轮补的 Device&(不再需要) - 验证:5s 探针自动退出 → exit 0、无 VUID-05137 泄漏、无 SIGSEGV
89 lines
2.9 KiB
C++
89 lines
2.9 KiB
C++
//
|
||
// Created by atdunbg on 2026/9/20.
|
||
//
|
||
// ShaderManager:shader object(VK_EXT_shader_object)创建工厂。
|
||
//
|
||
// 生命周期模型(UE FShaderResource / TShaderRef 语义):Create* 返回
|
||
// 引用计数句柄 ShaderRef,拷贝 = 共享所有权,最后一个引用析构时自动
|
||
// 销毁 VkShaderEXT——持有方零清理代码,"新 pass 忘销毁"整类 bug 被
|
||
// 机制消灭(曾因手工管理漏销毁退出时报 VUID-05137 泄漏)。
|
||
//
|
||
// 唯一约束:ShaderRef 不得比 Device 活得久(引擎内所有持有方都在
|
||
// Renderer 子树内、先于 Device 析构,天然满足;勿存进静态/长寿命容器)。
|
||
//
|
||
|
||
#ifndef HELLOVULKAN_SHADERMANAGER_H
|
||
#define HELLOVULKAN_SHADERMANAGER_H
|
||
|
||
|
||
#pragma once
|
||
|
||
#include <Engine/Core/Types.h>
|
||
#include <vulkan/vulkan.hpp>
|
||
#include <memory>
|
||
#include <string>
|
||
#include <vector>
|
||
|
||
namespace Engine {
|
||
|
||
class Device;
|
||
|
||
class ShaderManager {
|
||
public:
|
||
// ---- 引用计数句柄 ----
|
||
// 空句柄(创建失败)可用 operator bool 判定,此时 GetHandle()
|
||
// 返回空 handle(bind 前由调用方判空跳过)
|
||
class ShaderRef {
|
||
public:
|
||
ShaderRef() = default;
|
||
|
||
explicit operator bool() const { return m_Entry != nullptr; }
|
||
|
||
vk::ShaderEXT GetHandle() const {
|
||
return m_Entry ? m_Entry->handle : vk::ShaderEXT{};
|
||
}
|
||
|
||
vk::ShaderStageFlagBits GetStage() const { return m_Entry->stage; }
|
||
|
||
private:
|
||
friend class ShaderManager;
|
||
|
||
struct Entry {
|
||
vk::ShaderEXT handle{};
|
||
vk::ShaderStageFlagBits stage{};
|
||
Device* device = nullptr;
|
||
~Entry(); // cpp 定义:销毁 VkShaderEXT(需 Device 完整类型)
|
||
};
|
||
|
||
explicit ShaderRef(std::shared_ptr<Entry> e)
|
||
: m_Entry(std::move(e)) {}
|
||
|
||
std::shared_ptr<Entry> m_Entry;
|
||
};
|
||
|
||
explicit ShaderManager(Device& device);
|
||
~ShaderManager() = default; // shader 随引用计数自动释放
|
||
|
||
ShaderManager(const ShaderManager&) = delete;
|
||
ShaderManager& operator=(const ShaderManager&) = delete;
|
||
|
||
ShaderRef CreateFromFile(const std::string& spvPath,
|
||
vk::ShaderStageFlagBits stage,
|
||
const std::vector<vk::DescriptorSetLayout>& layouts = {},
|
||
u32 pushConstantSize = 0);
|
||
|
||
ShaderRef CreateFromSPIRV(const std::vector<u32>& spirv,
|
||
vk::ShaderStageFlagBits stage,
|
||
const std::vector<vk::DescriptorSetLayout>& layouts = {},
|
||
u32 pushConstantSize = 0) const;
|
||
|
||
private:
|
||
static std::vector<u32> ReadSPIRV(const std::string& path);
|
||
|
||
Device& m_Device;
|
||
};
|
||
|
||
} // namespace Engine
|
||
|
||
#endif //HELLOVULKAN_SHADERMANAGER_H
|