Files
HelloVulkan/Engine/include/Engine/Vulkan/ShaderManager.h
T
atdunbg b0d5ed4550 refactor: ShaderManager 引用计数句柄——shader 生命周期自动化
- 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
2026-10-02 20:20:07 +08:00

89 lines
2.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// 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