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
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
#include <Engine/Core/Types.h>
|
||||
#include <Engine/Renderer/Cubemap.h> // DecodedEquirect(解码产物数据契约)
|
||||
#include <Engine/Vulkan/MemoryAllocator.h>
|
||||
#include <Engine/Vulkan/ShaderManager.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <string>
|
||||
@@ -36,7 +37,6 @@ namespace Engine {
|
||||
|
||||
class Device;
|
||||
class DescriptorManager;
|
||||
class ShaderManager;
|
||||
class Cubemap;
|
||||
|
||||
class IblGenerator {
|
||||
@@ -95,10 +95,11 @@ namespace Engine {
|
||||
vk::PipelineLayout m_IblLayoutPush;
|
||||
vk::PipelineLayout m_LutLayout;
|
||||
|
||||
vk::ShaderEXT m_ToCubeShader{};
|
||||
vk::ShaderEXT m_IrrShader{};
|
||||
vk::ShaderEXT m_PrefShader{};
|
||||
vk::ShaderEXT m_LutShader{};
|
||||
// compute shader(引用计数句柄,析构自动销毁)
|
||||
ShaderManager::ShaderRef m_ToCubeShader;
|
||||
ShaderManager::ShaderRef m_IrrShader;
|
||||
ShaderManager::ShaderRef m_PrefShader;
|
||||
ShaderManager::ShaderRef m_LutShader;
|
||||
|
||||
vk::Sampler m_EquirectSampler; // S=repeat(经度环绕)T=clamp
|
||||
vk::CommandPool m_Pool; // 持久复用,每次生成 reset
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
|
||||
#include <Engine/Core/Types.h>
|
||||
#include <Engine/RenderGraph/RenderGraph.h>
|
||||
#include <Engine/Vulkan/ShaderManager.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Device;
|
||||
class DescriptorManager;
|
||||
class ShaderManager;
|
||||
|
||||
namespace Passes {
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Engine {
|
||||
public:
|
||||
FullscreenGpu(Device& device, DescriptorManager& descriptors,
|
||||
ShaderManager& shaders);
|
||||
~FullscreenGpu();
|
||||
~FullscreenGpu(); // 只清 sampler/layout(shader 随引用自动销毁)
|
||||
|
||||
FullscreenGpu(const FullscreenGpu&) = delete;
|
||||
FullscreenGpu& operator=(const FullscreenGpu&) = delete;
|
||||
@@ -72,9 +72,10 @@ namespace Engine {
|
||||
vk::DescriptorSetLayout setLayout; // Set0 = {输入0, 输入1, 调试输入}
|
||||
vk::PipelineLayout layout; // push 16B(FullscreenPush)
|
||||
vk::Sampler sampler;
|
||||
vk::ShaderEXT vert{}, extractFrag{}, blurFrag{}, tonemapFrag{};
|
||||
vk::ShaderEXT diffFrag{}; // temporal_diff(帧历史调试)
|
||||
vk::ShaderEXT taaFrag{}; // taa(时域抗锯齿 resolve)
|
||||
// shader 引用计数句柄(析构自动销毁,零手工清理)
|
||||
ShaderManager::ShaderRef vert, extractFrag, blurFrag, tonemapFrag;
|
||||
ShaderManager::ShaderRef diffFrag; // temporal_diff(帧历史调试)
|
||||
ShaderManager::ShaderRef taaFrag; // taa(时域抗锯齿 resolve)
|
||||
|
||||
// 各 pass 自己持有 per-slot set;分配统一走这里
|
||||
vk::DescriptorSet AllocateSet();
|
||||
@@ -87,7 +88,8 @@ namespace Engine {
|
||||
// 全屏 pass 公共录制:动态状态/draw 全一致,仅附件 view、
|
||||
// 输入 set、push 值不同
|
||||
void RecordFullscreen(RG::RenderGraphContext& ctx, vk::ImageView view,
|
||||
vk::ShaderEXT frag, const vk::DescriptorSet& set,
|
||||
const ShaderManager::ShaderRef& frag,
|
||||
const vk::DescriptorSet& set,
|
||||
const FullscreenPush& push);
|
||||
|
||||
private:
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <Engine/Renderer/Passes/RenderPass.h>
|
||||
#include <Engine/Renderer/SceneTypes.h>
|
||||
#include <Engine/Vulkan/Buffer.h>
|
||||
#include <Engine/Vulkan/ShaderManager.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Engine {
|
||||
@@ -61,7 +62,7 @@ namespace Engine {
|
||||
RG::TextureHandle m_Depth;
|
||||
|
||||
vk::PipelineLayout m_Layout; // Set0 = uboSetLayout,无 push
|
||||
vk::ShaderEXT m_Vert{}, m_Frag{};
|
||||
ShaderManager::ShaderRef m_Vert, m_Frag; // 析构自动销毁
|
||||
|
||||
// 1×1 像素暂存(host visible,持久映射);拷贝录制时置位
|
||||
Scope<Buffer> m_Staging;
|
||||
|
||||
@@ -23,12 +23,11 @@ namespace Engine {
|
||||
class OutlinePass final : public RenderPass {
|
||||
public:
|
||||
// color:描边色(LDR);widthPx:描边宽度(物理像素)
|
||||
OutlinePass(Device& device, FullscreenGpu& gpu, ShaderManager& shaders,
|
||||
OutlinePass(FullscreenGpu& gpu, ShaderManager& shaders,
|
||||
FrameSceneData& frame,
|
||||
RG::TextureHandle mask, RG::TextureHandle present,
|
||||
const glm::vec3& color = glm::vec3(1.0f, 0.62f, 0.05f),
|
||||
f32 widthPx = 6.0f);
|
||||
~OutlinePass() override;
|
||||
|
||||
OutlinePass(const OutlinePass&) = delete;
|
||||
OutlinePass& operator=(const OutlinePass&) = delete;
|
||||
@@ -37,14 +36,13 @@ namespace Engine {
|
||||
void OnTargetsRebuilt(RG::RenderGraph& rg) override;
|
||||
|
||||
private:
|
||||
Device& m_Device;
|
||||
FullscreenGpu& m_Gpu;
|
||||
FrameSceneData& m_Frame;
|
||||
RG::TextureHandle m_Mask;
|
||||
RG::TextureHandle m_Present;
|
||||
glm::vec3 m_Color;
|
||||
f32 m_WidthPx;
|
||||
ShaderObject m_Frag{};
|
||||
ShaderManager::ShaderRef m_Frag; // 析构自动销毁
|
||||
std::vector<vk::DescriptorSet> m_Sets; // per-frame slot
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <Engine/Renderer/Passes/RenderPass.h>
|
||||
#include <Engine/Renderer/SceneTypes.h>
|
||||
#include <Engine/Vulkan/UniformBuffer.h>
|
||||
#include <Engine/Vulkan/ShaderManager.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Engine {
|
||||
@@ -64,7 +65,7 @@ namespace Engine {
|
||||
UniformBuffer& m_TriVB;
|
||||
|
||||
vk::PipelineLayout m_Layout; // 无描述符,push = viewProj 64B
|
||||
vk::ShaderEXT m_Vert{}, m_Frag{};
|
||||
ShaderManager::ShaderRef m_Vert, m_Frag; // 析构自动销毁
|
||||
|
||||
std::array<u32, kMaxFramesInFlight> m_LineCounts{};
|
||||
std::array<u32, kMaxFramesInFlight> m_TriCounts{};
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <Engine/Core/FrameContext.h>
|
||||
#include <Engine/Renderer/SceneTypes.h>
|
||||
#include <Engine/RenderGraph/RenderGraph.h>
|
||||
#include <Engine/Vulkan/ShaderManager.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
@@ -22,7 +23,6 @@ namespace Engine {
|
||||
|
||||
class Device;
|
||||
class DescriptorManager;
|
||||
class ShaderManager;
|
||||
class UniformBuffer;
|
||||
class Cubemap;
|
||||
class Buffer;
|
||||
@@ -40,7 +40,7 @@ namespace Engine {
|
||||
UniformBuffer& skinOffsetBuffer,
|
||||
UniformBuffer& skinPaletteBuffer,
|
||||
UniformBuffer& entityIdBuffer);
|
||||
~SceneGpu();
|
||||
~SceneGpu(); // 只清 sampler/layout/set(shader 随引用自动销毁)
|
||||
|
||||
SceneGpu(const SceneGpu&) = delete;
|
||||
SceneGpu& operator=(const SceneGpu&) = delete;
|
||||
@@ -76,10 +76,11 @@ namespace Engine {
|
||||
std::array<Scope<Buffer>, kMaxFramesInFlight> indirectCmdBuffers;
|
||||
std::array<Scope<Buffer>, kMaxFramesInFlight> indirectCountBuffers;
|
||||
|
||||
vk::ShaderEXT forwardVert{}, forwardFrag{};
|
||||
// shader 引用计数句柄(析构自动销毁,零手工清理)
|
||||
ShaderManager::ShaderRef forwardVert, forwardFrag;
|
||||
// 透明变体:同 simple_shader + gl_FragDepth=1.0(见 frag 注释)
|
||||
vk::ShaderEXT translucentFrag{};
|
||||
vk::ShaderEXT shadowVert{}, shadowFrag{};
|
||||
ShaderManager::ShaderRef translucentFrag;
|
||||
ShaderManager::ShaderRef shadowVert, shadowFrag;
|
||||
|
||||
// RG 重编译后重绑阴影图(物理镜像按槽位各一份)
|
||||
void BindShadowMaps(RG::RenderGraph& rg,
|
||||
|
||||
@@ -26,10 +26,9 @@ namespace Engine {
|
||||
|
||||
class SelectionMaskPass final : public RenderPass {
|
||||
public:
|
||||
SelectionMaskPass(Device& device, ShaderManager& shaders,
|
||||
SelectionMaskPass(ShaderManager& shaders,
|
||||
SceneGpu& gpu, FrameSceneData& frame,
|
||||
RG::TextureHandle mask);
|
||||
~SelectionMaskPass() override;
|
||||
|
||||
SelectionMaskPass(const SelectionMaskPass&) = delete;
|
||||
SelectionMaskPass& operator=(const SelectionMaskPass&) = delete;
|
||||
@@ -38,11 +37,10 @@ namespace Engine {
|
||||
void OnTargetsRebuilt(RG::RenderGraph& rg) override {}
|
||||
|
||||
private:
|
||||
Device& m_Device;
|
||||
SceneGpu& m_Gpu;
|
||||
FrameSceneData& m_Frame;
|
||||
RG::TextureHandle m_Mask;
|
||||
ShaderObject m_Frag{};
|
||||
ShaderManager::ShaderRef m_Frag; // 析构自动销毁
|
||||
};
|
||||
|
||||
} // namespace Passes
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <Engine/Core/FrameContext.h>
|
||||
#include <Engine/Renderer/Passes/RenderPass.h>
|
||||
#include <Engine/Renderer/SceneTypes.h>
|
||||
#include <Engine/Vulkan/ShaderManager.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Engine {
|
||||
@@ -52,7 +53,7 @@ namespace Engine {
|
||||
|
||||
vk::DescriptorSetLayout m_SetLayout; // Set0 = {samplerCube}
|
||||
vk::PipelineLayout m_Layout; // push = invVP 64B
|
||||
vk::ShaderEXT m_Vert{}, m_Frag{};
|
||||
ShaderManager::ShaderRef m_Vert, m_Frag; // 析构自动销毁
|
||||
std::array<vk::DescriptorSet, kMaxFramesInFlight> m_Sets{};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
//
|
||||
// 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
|
||||
@@ -10,6 +20,7 @@
|
||||
|
||||
#include <Engine/Core/Types.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -17,31 +28,54 @@ namespace Engine {
|
||||
|
||||
class Device;
|
||||
|
||||
struct ShaderObject {
|
||||
vk::ShaderEXT Handle;
|
||||
vk::ShaderStageFlagBits Stage;
|
||||
};
|
||||
|
||||
class ShaderManager {
|
||||
public:
|
||||
ShaderManager(Device& device);
|
||||
~ShaderManager();
|
||||
// ---- 引用计数句柄 ----
|
||||
// 空句柄(创建失败)可用 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;
|
||||
|
||||
// 改成接受 vector
|
||||
ShaderObject CreateFromFile(const std::string& spvPath,
|
||||
vk::ShaderStageFlagBits stage,
|
||||
const std::vector<vk::DescriptorSetLayout>& layouts = {},
|
||||
u32 pushConstantSize = 0);
|
||||
ShaderRef CreateFromFile(const std::string& spvPath,
|
||||
vk::ShaderStageFlagBits stage,
|
||||
const std::vector<vk::DescriptorSetLayout>& layouts = {},
|
||||
u32 pushConstantSize = 0);
|
||||
|
||||
ShaderObject CreateFromSPIRV(const std::vector<u32>& spirv,
|
||||
vk::ShaderStageFlagBits stage,
|
||||
const std::vector<vk::DescriptorSetLayout>& layouts = {},
|
||||
u32 pushConstantSize = 0) const;
|
||||
|
||||
void Destroy(const ShaderObject& shader) const;
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user