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);
|
||||
|
||||
@@ -78,19 +78,19 @@ namespace Engine
|
||||
m_ToCubeShader = shaders.CreateFromFile(
|
||||
dir + "ibl_equirect_to_cube.comp.spv",
|
||||
vk::ShaderStageFlagBits::eCompute,
|
||||
{m_IblSetLayout}).Handle;
|
||||
{m_IblSetLayout});
|
||||
m_IrrShader = shaders.CreateFromFile(
|
||||
dir + "ibl_irradiance.comp.spv",
|
||||
vk::ShaderStageFlagBits::eCompute,
|
||||
{m_IblSetLayout}).Handle;
|
||||
{m_IblSetLayout});
|
||||
m_PrefShader = shaders.CreateFromFile(
|
||||
dir + "ibl_prefilter.comp.spv",
|
||||
vk::ShaderStageFlagBits::eCompute,
|
||||
{m_IblSetLayout}, sizeof(f32)).Handle;
|
||||
{m_IblSetLayout}, sizeof(f32));
|
||||
m_LutShader = shaders.CreateFromFile(
|
||||
dir + "ibl_brdf_lut.comp.spv",
|
||||
vk::ShaderStageFlagBits::eCompute,
|
||||
{m_LutSetLayout}).Handle;
|
||||
{m_LutSetLayout});
|
||||
|
||||
if (!m_ToCubeShader || !m_IrrShader || !m_PrefShader || !m_LutShader) {
|
||||
ENGINE_FATAL("IblGenerator: failed to create compute shaders");
|
||||
@@ -125,10 +125,7 @@ namespace Engine
|
||||
{
|
||||
const auto& vkDevice = m_Device.GetDevice();
|
||||
|
||||
for (const vk::ShaderEXT s : {m_ToCubeShader, m_IrrShader,
|
||||
m_PrefShader, m_LutShader}) {
|
||||
if (s) vkDevice.destroyShaderEXT(s);
|
||||
}
|
||||
// shader 随 ShaderRef 引用计数自动销毁,此处只清其余原生句柄
|
||||
vkDevice.destroySampler(m_EquirectSampler);
|
||||
vkDevice.destroyPipelineLayout(m_IblLayout);
|
||||
vkDevice.destroyPipelineLayout(m_IblLayoutPush);
|
||||
@@ -412,7 +409,7 @@ namespace Engine
|
||||
// 4c. ① equirect → env cube
|
||||
std::array<vk::ShaderStageFlagBits, 1> computeStage = {
|
||||
vk::ShaderStageFlagBits::eCompute};
|
||||
std::array<vk::ShaderEXT, 1> toCubeShaders = {m_ToCubeShader};
|
||||
std::array<vk::ShaderEXT, 1> toCubeShaders = {m_ToCubeShader.GetHandle()};
|
||||
m_Cmd.bindShadersEXT(computeStage, toCubeShaders);
|
||||
m_Cmd.bindDescriptorSets(vk::PipelineBindPoint::eCompute,
|
||||
m_IblLayout, 0, setToCube, {});
|
||||
@@ -434,7 +431,7 @@ namespace Engine
|
||||
vk::DependencyInfo{}.setImageMemoryBarriers(envToRead));
|
||||
|
||||
// 4d. ② irradiance(env → irr)
|
||||
std::array<vk::ShaderEXT, 1> irrShaders = {m_IrrShader};
|
||||
std::array<vk::ShaderEXT, 1> irrShaders = {m_IrrShader.GetHandle()};
|
||||
m_Cmd.bindShadersEXT(computeStage, irrShaders);
|
||||
m_Cmd.bindDescriptorSets(vk::PipelineBindPoint::eCompute,
|
||||
m_IblLayout, 0, setIrr, {});
|
||||
@@ -443,7 +440,7 @@ namespace Engine
|
||||
kFaceCount);
|
||||
|
||||
// 4e. ③ prefilter(env → pref,每 mip 一次 dispatch + push roughness)
|
||||
std::array<vk::ShaderEXT, 1> prefShaders = {m_PrefShader};
|
||||
std::array<vk::ShaderEXT, 1> prefShaders = {m_PrefShader.GetHandle()};
|
||||
m_Cmd.bindShadersEXT(computeStage, prefShaders);
|
||||
for (u32 m = 0; m < kPrefilterMips; ++m) {
|
||||
const u32 dim = kPrefilterFaceSize >> m;
|
||||
@@ -459,7 +456,7 @@ namespace Engine
|
||||
}
|
||||
|
||||
// 4f. ④ BRDF LUT(独立纯数学)
|
||||
std::array<vk::ShaderEXT, 1> lutShaders = {m_LutShader};
|
||||
std::array<vk::ShaderEXT, 1> lutShaders = {m_LutShader.GetHandle()};
|
||||
m_Cmd.bindShadersEXT(computeStage, lutShaders);
|
||||
m_Cmd.bindDescriptorSets(vk::PipelineBindPoint::eCompute,
|
||||
m_LutLayout, 0, setLut, {});
|
||||
|
||||
@@ -67,8 +67,8 @@ namespace Engine::Passes
|
||||
vk::ShaderStageFlagBits::eFragment
|
||||
};
|
||||
std::array<vk::ShaderEXT, 2> shaders = {
|
||||
m_Gpu.forwardVert,
|
||||
translucent ? m_Gpu.translucentFrag : m_Gpu.forwardFrag};
|
||||
m_Gpu.forwardVert.GetHandle(),
|
||||
(translucent ? m_Gpu.translucentFrag : m_Gpu.forwardFrag).GetHandle()};
|
||||
cmd.bindShadersEXT(stages, shaders);
|
||||
|
||||
// Set 0:本帧槽位的 UBO;Set 2:本帧槽位的阴影图
|
||||
|
||||
@@ -74,12 +74,12 @@ namespace Engine::Passes
|
||||
std::vector<vk::DescriptorSetLayout>{setLayout},
|
||||
static_cast<u32>(sizeof(FullscreenPush)));
|
||||
|
||||
vert = vertShader.Handle;
|
||||
tonemapFrag = tonemapF.Handle;
|
||||
extractFrag = extractF.Handle;
|
||||
blurFrag = blurF.Handle;
|
||||
diffFrag = diffF.Handle;
|
||||
taaFrag = taaF.Handle;
|
||||
vert = std::move(vertShader);
|
||||
tonemapFrag = std::move(tonemapF);
|
||||
extractFrag = std::move(extractF);
|
||||
blurFrag = std::move(blurF);
|
||||
diffFrag = std::move(diffF);
|
||||
taaFrag = std::move(taaF);
|
||||
|
||||
if (!vert || !tonemapFrag || !extractFrag || !blurFrag ||
|
||||
!diffFrag || !taaFrag) {
|
||||
@@ -91,13 +91,7 @@ namespace Engine::Passes
|
||||
{
|
||||
const auto& vkDevice = m_Device.GetDevice();
|
||||
|
||||
if (vert) vkDevice.destroyShaderEXT(vert);
|
||||
if (tonemapFrag) vkDevice.destroyShaderEXT(tonemapFrag);
|
||||
if (extractFrag) vkDevice.destroyShaderEXT(extractFrag);
|
||||
if (blurFrag) vkDevice.destroyShaderEXT(blurFrag);
|
||||
if (diffFrag) vkDevice.destroyShaderEXT(diffFrag);
|
||||
if (taaFrag) vkDevice.destroyShaderEXT(taaFrag);
|
||||
|
||||
// shader 随 ShaderRef 引用计数自动销毁,此处只清其余原生句柄
|
||||
vkDevice.destroySampler(sampler);
|
||||
vkDevice.destroyPipelineLayout(layout);
|
||||
vkDevice.destroyDescriptorSetLayout(setLayout);
|
||||
@@ -119,7 +113,7 @@ namespace Engine::Passes
|
||||
|
||||
void FullscreenGpu::RecordFullscreen(RG::RenderGraphContext& ctx,
|
||||
vk::ImageView view,
|
||||
vk::ShaderEXT frag,
|
||||
const ShaderManager::ShaderRef& frag,
|
||||
const vk::DescriptorSet& set,
|
||||
const FullscreenPush& push)
|
||||
{
|
||||
@@ -147,7 +141,7 @@ namespace Engine::Passes
|
||||
vk::ShaderStageFlagBits::eVertex,
|
||||
vk::ShaderStageFlagBits::eFragment
|
||||
};
|
||||
std::array<vk::ShaderEXT, 2> shaders = {vert, frag};
|
||||
std::array<vk::ShaderEXT, 2> shaders = {vert.GetHandle(), frag.GetHandle()};
|
||||
cmd.bindShadersEXT(stages, shaders);
|
||||
|
||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
||||
|
||||
@@ -67,8 +67,8 @@ namespace Engine::Passes
|
||||
vk::ShaderStageFlagBits::eFragment,
|
||||
std::vector<vk::DescriptorSetLayout>{gpu.uboSetLayout}, 0);
|
||||
|
||||
m_Vert = vert.Handle;
|
||||
m_Frag = frag.Handle;
|
||||
m_Vert = std::move(vert);
|
||||
m_Frag = std::move(frag);
|
||||
if (!m_Vert || !m_Frag) {
|
||||
ENGINE_FATAL("HitProxyPass: failed to create shader objects");
|
||||
}
|
||||
@@ -83,11 +83,8 @@ namespace Engine::Passes
|
||||
|
||||
HitProxyPass::~HitProxyPass()
|
||||
{
|
||||
const auto& vkDevice = m_Device.GetDevice();
|
||||
|
||||
if (m_Vert) vkDevice.destroyShaderEXT(m_Vert);
|
||||
if (m_Frag) vkDevice.destroyShaderEXT(m_Frag);
|
||||
vkDevice.destroyPipelineLayout(m_Layout);
|
||||
// shader 随 ShaderRef 引用计数自动销毁,此处只清其余原生句柄
|
||||
m_Device.GetDevice().destroyPipelineLayout(m_Layout);
|
||||
}
|
||||
|
||||
bool HitProxyPass::TakeResult(u32& outBits)
|
||||
@@ -143,7 +140,7 @@ namespace Engine::Passes
|
||||
const std::array<vk::ShaderStageFlagBits, 2> stages = {
|
||||
vk::ShaderStageFlagBits::eVertex,
|
||||
vk::ShaderStageFlagBits::eFragment};
|
||||
const std::array<vk::ShaderEXT, 2> shaders = {m_Vert, m_Frag};
|
||||
const std::array<vk::ShaderEXT, 2> shaders = {m_Vert.GetHandle(), m_Frag.GetHandle()};
|
||||
cmd.bindShadersEXT(stages, shaders);
|
||||
|
||||
// Set0 = uboSets(UBO + 实例矩阵 + 蒙皮 + 实体 id)
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <Engine/Renderer/Passes/OutlinePass.h>
|
||||
#include <Engine/Renderer/Passes/FullscreenGpu.h>
|
||||
#include <Engine/Vulkan/ShaderManager.h>
|
||||
#include <Engine/Vulkan/Device.h>
|
||||
#include <Engine/Core/FrameContext.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
@@ -18,11 +17,11 @@
|
||||
|
||||
namespace Engine::Passes
|
||||
{
|
||||
OutlinePass::OutlinePass(Device& device, FullscreenGpu& gpu, ShaderManager& shaders,
|
||||
OutlinePass::OutlinePass(FullscreenGpu& gpu, ShaderManager& shaders,
|
||||
FrameSceneData& frame,
|
||||
RG::TextureHandle mask, RG::TextureHandle present,
|
||||
const glm::vec3& color, f32 widthPx)
|
||||
: m_Device(device), m_Gpu(gpu), m_Frame(frame), m_Mask(mask), m_Present(present),
|
||||
: m_Gpu(gpu), m_Frame(frame), m_Mask(mask), m_Present(present),
|
||||
m_Color(color), m_WidthPx(widthPx) {
|
||||
m_Frag = shaders.CreateFromFile(
|
||||
"shaders/outline.frag.spv",
|
||||
@@ -36,12 +35,6 @@ namespace Engine::Passes
|
||||
}
|
||||
}
|
||||
|
||||
OutlinePass::~OutlinePass()
|
||||
{
|
||||
// VkShaderEXT 是 Device 子对象,必须在 vkDestroyDevice 前销毁
|
||||
if (m_Frag.Handle) m_Device.GetDevice().destroyShaderEXT(m_Frag.Handle);
|
||||
}
|
||||
|
||||
void OutlinePass::Register(RG::RenderGraph& rg)
|
||||
{
|
||||
rg.AddPass("Outline", [this](RG::RenderGraphContext& ctx) {
|
||||
@@ -66,7 +59,7 @@ namespace Engine::Passes
|
||||
std::array<vk::ShaderStageFlagBits, 2> stages = {
|
||||
vk::ShaderStageFlagBits::eVertex,
|
||||
vk::ShaderStageFlagBits::eFragment};
|
||||
std::array<vk::ShaderEXT, 2> shaders = {m_Gpu.vert, m_Frag.Handle};
|
||||
std::array<vk::ShaderEXT, 2> shaders = {m_Gpu.vert.GetHandle(), m_Frag.GetHandle()};
|
||||
cmd.bindShadersEXT(stages, shaders);
|
||||
|
||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
||||
|
||||
@@ -84,8 +84,8 @@ namespace Engine::Passes
|
||||
std::vector<vk::DescriptorSetLayout>{},
|
||||
sizeof(glm::mat4));
|
||||
|
||||
m_Vert = vert.Handle;
|
||||
m_Frag = frag.Handle;
|
||||
m_Vert = std::move(vert);
|
||||
m_Frag = std::move(frag);
|
||||
if (!m_Vert || !m_Frag) {
|
||||
ENGINE_FATAL("PhysicsDebugPass: failed to create shader objects");
|
||||
}
|
||||
@@ -93,11 +93,8 @@ namespace Engine::Passes
|
||||
|
||||
PhysicsDebugPass::~PhysicsDebugPass()
|
||||
{
|
||||
const auto& vkDevice = m_Device.GetDevice();
|
||||
|
||||
if (m_Vert) vkDevice.destroyShaderEXT(m_Vert);
|
||||
if (m_Frag) vkDevice.destroyShaderEXT(m_Frag);
|
||||
vkDevice.destroyPipelineLayout(m_Layout);
|
||||
// shader 随 ShaderRef 引用计数自动销毁,此处只清其余原生句柄
|
||||
m_Device.GetDevice().destroyPipelineLayout(m_Layout);
|
||||
}
|
||||
|
||||
void PhysicsDebugPass::PrepareFrame(u32 frameSlot,
|
||||
@@ -168,7 +165,7 @@ namespace Engine::Passes
|
||||
vk::ShaderStageFlagBits::eVertex,
|
||||
vk::ShaderStageFlagBits::eFragment
|
||||
};
|
||||
const std::array<vk::ShaderEXT, 2> shaders = {m_Vert, m_Frag};
|
||||
const std::array<vk::ShaderEXT, 2> shaders = {m_Vert.GetHandle(), m_Frag.GetHandle()};
|
||||
cmd.bindShadersEXT(stages, shaders);
|
||||
|
||||
// layout 的 push range 是 vertex|fragment(CreatePipelineLayout 默认),
|
||||
|
||||
@@ -113,11 +113,11 @@ namespace Engine::Passes
|
||||
std::vector<vk::DescriptorSetLayout>{uboSetLayout},
|
||||
sizeof(glm::mat4));
|
||||
|
||||
forwardVert = vert.Handle;
|
||||
forwardFrag = frag.Handle;
|
||||
translucentFrag = transFrag.Handle;
|
||||
shadowVert = shadowVertShader.Handle;
|
||||
shadowFrag = shadowFragShader.Handle;
|
||||
forwardVert = std::move(vert);
|
||||
forwardFrag = std::move(frag);
|
||||
translucentFrag = std::move(transFrag);
|
||||
shadowVert = std::move(shadowVertShader);
|
||||
shadowFrag = std::move(shadowFragShader);
|
||||
|
||||
if (!forwardVert || !forwardFrag || !translucentFrag ||
|
||||
!shadowVert || !shadowFrag) {
|
||||
@@ -190,12 +190,7 @@ namespace Engine::Passes
|
||||
{
|
||||
const auto& vkDevice = m_Device.GetDevice();
|
||||
|
||||
if (forwardVert) vkDevice.destroyShaderEXT(forwardVert);
|
||||
if (forwardFrag) vkDevice.destroyShaderEXT(forwardFrag);
|
||||
if (translucentFrag) vkDevice.destroyShaderEXT(translucentFrag);
|
||||
if (shadowVert) vkDevice.destroyShaderEXT(shadowVert);
|
||||
if (shadowFrag) vkDevice.destroyShaderEXT(shadowFrag);
|
||||
|
||||
// shader 随 ShaderRef 引用计数自动销毁,此处只清其余原生句柄
|
||||
vkDevice.destroySampler(shadowSampler);
|
||||
vkDevice.destroyPipelineLayout(forwardLayout);
|
||||
vkDevice.destroyPipelineLayout(shadowLayout);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <Engine/Renderer/Passes/SelectionMaskPass.h>
|
||||
#include <Engine/Renderer/Passes/SceneGpu.h>
|
||||
#include <Engine/Vulkan/ShaderManager.h>
|
||||
#include <Engine/Vulkan/Device.h>
|
||||
#include <Engine/Renderer/Vertex.h>
|
||||
#include <Engine/Renderer/Mesh.h>
|
||||
|
||||
@@ -13,10 +12,10 @@
|
||||
|
||||
namespace Engine::Passes
|
||||
{
|
||||
SelectionMaskPass::SelectionMaskPass(Device& device, ShaderManager& shaders,
|
||||
SelectionMaskPass::SelectionMaskPass(ShaderManager& shaders,
|
||||
SceneGpu& gpu, FrameSceneData& frame,
|
||||
RG::TextureHandle mask)
|
||||
: m_Device(device), m_Gpu(gpu), m_Frame(frame), m_Mask(mask)
|
||||
: m_Gpu(gpu), m_Frame(frame), m_Mask(mask)
|
||||
{
|
||||
// 恒 1 片元;布局数组必须与 forwardVert 完全一致(shader object
|
||||
// 要求同程序各 shader 的 set layouts 逐项相同,VUID-08879),
|
||||
@@ -29,12 +28,6 @@ namespace Engine::Passes
|
||||
0);
|
||||
}
|
||||
|
||||
SelectionMaskPass::~SelectionMaskPass()
|
||||
{
|
||||
// VkShaderEXT 是 Device 子对象,必须在 vkDestroyDevice 前销毁
|
||||
if (m_Frag.Handle) m_Device.GetDevice().destroyShaderEXT(m_Frag.Handle);
|
||||
}
|
||||
|
||||
void SelectionMaskPass::Register(RG::RenderGraph& rg)
|
||||
{
|
||||
rg.AddPass("SelectionMask", [this](RG::RenderGraphContext& ctx) {
|
||||
@@ -66,8 +59,8 @@ namespace Engine::Passes
|
||||
std::array<vk::ShaderStageFlagBits, 2> stages = {
|
||||
vk::ShaderStageFlagBits::eVertex,
|
||||
vk::ShaderStageFlagBits::eFragment};
|
||||
std::array<vk::ShaderEXT, 2> shaders = {m_Gpu.forwardVert,
|
||||
m_Frag.Handle};
|
||||
std::array<vk::ShaderEXT, 2> shaders = {
|
||||
m_Gpu.forwardVert.GetHandle(), m_Frag.GetHandle()};
|
||||
cmd.bindShadersEXT(stages, shaders);
|
||||
|
||||
// Set0:本帧槽位 UBO + 实例/蒙皮 SSBO(Set1 材质、Set2
|
||||
|
||||
@@ -42,7 +42,8 @@ namespace Engine::Passes
|
||||
vk::ShaderStageFlagBits::eVertex,
|
||||
vk::ShaderStageFlagBits::eFragment
|
||||
};
|
||||
std::array<vk::ShaderEXT, 2> shaders = {m_Gpu.shadowVert, m_Gpu.shadowFrag};
|
||||
std::array<vk::ShaderEXT, 2> shaders = {
|
||||
m_Gpu.shadowVert.GetHandle(), m_Gpu.shadowFrag.GetHandle()};
|
||||
cmd.bindShadersEXT(stages, shaders);
|
||||
|
||||
// ---- 动态状态(depth-only)----
|
||||
|
||||
@@ -48,8 +48,8 @@ namespace Engine::Passes
|
||||
std::vector<vk::DescriptorSetLayout>{m_SetLayout},
|
||||
sizeof(glm::mat4));
|
||||
|
||||
m_Vert = vert.Handle;
|
||||
m_Frag = frag.Handle;
|
||||
m_Vert = std::move(vert);
|
||||
m_Frag = std::move(frag);
|
||||
if (!m_Vert || !m_Frag) {
|
||||
ENGINE_FATAL("SkyboxPass: failed to create shader objects");
|
||||
}
|
||||
@@ -69,8 +69,7 @@ namespace Engine::Passes
|
||||
{
|
||||
const auto& vkDevice = m_Device.GetDevice();
|
||||
|
||||
if (m_Vert) vkDevice.destroyShaderEXT(m_Vert);
|
||||
if (m_Frag) vkDevice.destroyShaderEXT(m_Frag);
|
||||
// shader 随 ShaderRef 引用计数自动销毁,此处只清其余原生句柄
|
||||
vkDevice.destroyPipelineLayout(m_Layout);
|
||||
vkDevice.destroyDescriptorSetLayout(m_SetLayout);
|
||||
}
|
||||
@@ -123,7 +122,7 @@ namespace Engine::Passes
|
||||
vk::ShaderStageFlagBits::eVertex,
|
||||
vk::ShaderStageFlagBits::eFragment
|
||||
};
|
||||
const std::array<vk::ShaderEXT, 2> shaders = {m_Vert, m_Frag};
|
||||
const std::array<vk::ShaderEXT, 2> shaders = {m_Vert.GetHandle(), m_Frag.GetHandle()};
|
||||
cmd.bindShadersEXT(stages, shaders);
|
||||
|
||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
||||
|
||||
@@ -423,7 +423,7 @@ namespace Engine
|
||||
// UE 透墙可见语义)→ Outline(叠加在 Tonemap 后的 PresentTarget
|
||||
// 上,恒定 LDR 描边色)
|
||||
m_Passes.push_back(CreateScope<Passes::SelectionMaskPass>(
|
||||
*m_Device, *m_ShaderManager, *m_SceneGpu, frame, m_SelectionMask));
|
||||
*m_ShaderManager, *m_SceneGpu, frame, m_SelectionMask));
|
||||
m_Passes.push_back(CreateScope<Passes::TAAPass>(
|
||||
*m_FullscreenGpu, frame, /*historyAlpha*/ 0.9f, m_HDRColor,
|
||||
m_Velocity, m_TAAColor));
|
||||
@@ -440,7 +440,7 @@ namespace Engine
|
||||
// 排在 Tonemap 前,会被 Tonemap 整帧覆盖(WAW 序 = 注册序)。
|
||||
// Blit/ImGui 之前——它们把 PresentTarget 送去 backbuffer/UI。
|
||||
m_Passes.push_back(CreateScope<Passes::OutlinePass>(
|
||||
*m_Device, *m_FullscreenGpu, *m_ShaderManager, frame,
|
||||
*m_FullscreenGpu, *m_ShaderManager, frame,
|
||||
m_SelectionMask, m_PresentTarget));
|
||||
// Direct 模式适配器:PresentTarget → backbuffer(Viewport 模式空转)。
|
||||
// 必须注册在 ImGui 之前:两者都写 backbuffer,WAW 边按声明序
|
||||
|
||||
@@ -8,105 +8,108 @@
|
||||
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
ShaderManager::ShaderManager(Device& device)
|
||||
: m_Device(device)
|
||||
{
|
||||
}
|
||||
|
||||
ShaderManager::~ShaderManager()
|
||||
{
|
||||
}
|
||||
|
||||
ShaderObject ShaderManager::CreateFromFile(const std::string& spvPath,
|
||||
const vk::ShaderStageFlagBits stage,
|
||||
const std::vector<vk::DescriptorSetLayout>& layouts,
|
||||
const u32 pushConstantSize)
|
||||
{
|
||||
const auto spirv = ReadSPIRV(spvPath);
|
||||
if (spirv.empty()) {
|
||||
ENGINE_ERROR("Failed to read SPIR-V: {}", spvPath);
|
||||
return { nullptr, stage };
|
||||
}
|
||||
return CreateFromSPIRV(spirv, stage, layouts, pushConstantSize);
|
||||
}
|
||||
|
||||
ShaderObject ShaderManager::CreateFromSPIRV(const std::vector<u32>& spirv,
|
||||
const vk::ShaderStageFlagBits stage,
|
||||
const std::vector<vk::DescriptorSetLayout>& layouts,
|
||||
const u32 pushConstantSize) const
|
||||
{
|
||||
vk::ShaderStageFlags nextStage = {};
|
||||
if (stage == vk::ShaderStageFlagBits::eVertex) {
|
||||
nextStage = vk::ShaderStageFlagBits::eFragment;
|
||||
}
|
||||
// compute 单阶段:无 nextStage(VUID-09183 只约束 graphics 链)
|
||||
|
||||
vk::ShaderCreateInfoEXT createInfo;
|
||||
createInfo.setStage(stage)
|
||||
.setNextStage(nextStage)
|
||||
.setCodeType(vk::ShaderCodeTypeEXT::eSpirv)
|
||||
.setCodeSize(spirv.size() * sizeof(u32))
|
||||
.setPCode(spirv.data())
|
||||
.setPName("main");
|
||||
|
||||
if (!layouts.empty()) {
|
||||
createInfo.setSetLayouts(layouts);
|
||||
// Entry 析构在 cpp:destroyShaderEXT 需要 Device 完整类型,
|
||||
// 持有方 TU 只有前置声明也不受影响
|
||||
ShaderManager::ShaderRef::Entry::~Entry()
|
||||
{
|
||||
if (handle && device) {
|
||||
device->GetDevice().destroyShaderEXT(handle);
|
||||
}
|
||||
}
|
||||
|
||||
std::array<vk::PushConstantRange, 1> pushRanges;
|
||||
if (pushConstantSize > 0) {
|
||||
// push range 是"程序级"声明:shader object 要求同一程序绑定的
|
||||
// 全部 shader(vert+frag)push range 定义完全一致(VUID-08878),
|
||||
// 因此统一按 vertex|fragment 声明;shader 实际读取哪些字节由
|
||||
// GLSL 的 push_constant block 决定,声明范围只是能力上限。
|
||||
// compute 无程序链,单独按 eCompute 声明(layout/push 调用点一致)
|
||||
pushRanges[0].setStageFlags(stage == vk::ShaderStageFlagBits::eCompute
|
||||
? vk::ShaderStageFlagBits::eCompute
|
||||
: vk::ShaderStageFlagBits::eVertex |
|
||||
vk::ShaderStageFlagBits::eFragment)
|
||||
.setOffset(0)
|
||||
.setSize(pushConstantSize);
|
||||
createInfo.setPushConstantRanges(pushRanges);
|
||||
ShaderManager::ShaderManager(Device& device)
|
||||
: m_Device(device)
|
||||
{
|
||||
}
|
||||
|
||||
vk::ShaderEXT shader;
|
||||
try {
|
||||
const 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 };
|
||||
ShaderManager::ShaderRef ShaderManager::CreateFromFile(const std::string& spvPath,
|
||||
const vk::ShaderStageFlagBits stage,
|
||||
const std::vector<vk::DescriptorSetLayout>& layouts,
|
||||
const u32 pushConstantSize)
|
||||
{
|
||||
const auto spirv = ReadSPIRV(spvPath);
|
||||
if (spirv.empty()) {
|
||||
ENGINE_ERROR("Failed to read SPIR-V: {}", spvPath);
|
||||
return {};
|
||||
}
|
||||
return CreateFromSPIRV(spirv, stage, layouts, pushConstantSize);
|
||||
}
|
||||
|
||||
return { shader, stage };
|
||||
}
|
||||
ShaderManager::ShaderRef ShaderManager::CreateFromSPIRV(const std::vector<u32>& spirv,
|
||||
const vk::ShaderStageFlagBits stage,
|
||||
const std::vector<vk::DescriptorSetLayout>& layouts,
|
||||
const u32 pushConstantSize) const
|
||||
{
|
||||
vk::ShaderStageFlags nextStage = {};
|
||||
if (stage == vk::ShaderStageFlagBits::eVertex) {
|
||||
nextStage = vk::ShaderStageFlagBits::eFragment;
|
||||
}
|
||||
// compute 单阶段:无 nextStage(VUID-09183 只约束 graphics 链)
|
||||
|
||||
void ShaderManager::Destroy(const ShaderObject& shader) const
|
||||
{
|
||||
if (shader.Handle) {
|
||||
m_Device.GetDevice().destroyShaderEXT(shader.Handle);
|
||||
}
|
||||
}
|
||||
vk::ShaderCreateInfoEXT createInfo;
|
||||
createInfo.setStage(stage)
|
||||
.setNextStage(nextStage)
|
||||
.setCodeType(vk::ShaderCodeTypeEXT::eSpirv)
|
||||
.setCodeSize(spirv.size() * sizeof(u32))
|
||||
.setPCode(spirv.data())
|
||||
.setPName("main");
|
||||
|
||||
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 {};
|
||||
if (!layouts.empty()) {
|
||||
createInfo.setSetLayouts(layouts);
|
||||
}
|
||||
|
||||
std::array<vk::PushConstantRange, 1> pushRanges;
|
||||
if (pushConstantSize > 0) {
|
||||
// push range 是"程序级"声明:shader object 要求同一程序绑定的
|
||||
// 全部 shader(vert+frag)push range 定义完全一致(VUID-08878),
|
||||
// 因此统一按 vertex|fragment 声明;shader 实际读取哪些字节由
|
||||
// GLSL 的 push_constant block 决定,声明范围只是能力上限。
|
||||
// compute 无程序链,单独按 eCompute 声明(layout/push 调用点一致)
|
||||
pushRanges[0].setStageFlags(stage == vk::ShaderStageFlagBits::eCompute
|
||||
? vk::ShaderStageFlagBits::eCompute
|
||||
: vk::ShaderStageFlagBits::eVertex |
|
||||
vk::ShaderStageFlagBits::eFragment)
|
||||
.setOffset(0)
|
||||
.setSize(pushConstantSize);
|
||||
createInfo.setPushConstantRanges(pushRanges);
|
||||
}
|
||||
|
||||
vk::ShaderEXT shader;
|
||||
try {
|
||||
const 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 {};
|
||||
}
|
||||
|
||||
auto entry = std::make_shared<ShaderRef::Entry>();
|
||||
entry->handle = shader;
|
||||
entry->stage = stage;
|
||||
entry->device = &m_Device;
|
||||
return ShaderRef(std::move(entry));
|
||||
}
|
||||
|
||||
const 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();
|
||||
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 {};
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
const 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