5.0 KiB
VulkanShader
命名空间: XCEngine::RHI
类型: class
头文件: XCEngine/RHI/Vulkan/VulkanShader.h
描述: Vulkan 后端里的 RHIShader 实现,负责把 SPIR-V 数据包装成 VkShaderModule,并解析 shader stage 与入口点。
概览
VulkanShader 的职责很聚焦:它不是完整的“着色器编译系统”,而是 Vulkan shader module 的持有者。
它主要处理三件事:
- 接收 SPIR-V 字节流或
.spv文件 - 从 SPIR-V 元数据或 target hint 推断
ShaderType - 创建并持有
VkShaderModule
真正负责把 GLSL 文本编译成 SPIR-V 的,是 VulkanShaderCompiler。也就是说,这个类更接近“已编译 shader 对象”,而不是“编译器前端”。
生命周期
典型顺序是:
- 由 VulkanDevice 创建
VulkanShader - 设备先把输入编译或整理为 SPIR-V
Compile()或CompileFromFile()创建VkShaderModule- pipeline state 在创建阶段引用该 shader
- 不再使用时
Shutdown()
析构函数会调用 Shutdown()。如果当前对象仍持有 VkShaderModule,Shutdown() 会调用 vkDestroyShaderModule() 释放原生资源。
当前实现的真实行为
输入格式
Compile(const void* sourceData, size_t sourceSize, ...)只接受 SPIR-V word 流CompileFromFile(...)也只接受二进制.spv文件- 如果输入不是 4 字节对齐的 SPIR-V payload,会直接失败
这点很重要:VulkanShader 本身不编译 GLSL/HLSL 文本。文本输入必须先经过 VulkanShaderCompiler。
stage 与入口点解析
InitializeFromSpirvWords() 的行为是:
- 先验证 SPIR-V magic number
0x07230203 - 优先从 SPIR-V
OpEntryPoint指令里解析执行模型和入口点 - 如果解析不到 stage,再退回
targetHint - 入口点优先级为:
entryPointHint> SPIR-V 模块里解析出的入口点 >"main"
这意味着当前实现对标准 SPIR-V 模块相当友好,也允许调用方在必要时通过 hint 补足信息。
Uniform 反射
GetUniformInfos()返回m_uniformInfosGetUniformInfo(name)只是在这个数组里线性查找- 但当前实现并没有完整的 Vulkan/SPIR-V 反射流程去填充这些 uniform 信息
因此从真实行为看,uniform 反射能力目前仍比较初级。不要把这个接口误解成已经等价于成熟商业引擎里的 shader reflection system。
线程语义
从源码看,VulkanShader 没有内部同步。更稳妥的约束是:
- 创建、销毁和编译由调用方串行控制
- 不要在多个线程上同时对同一个
VulkanShader实例重复Compile()
所有权与资源管理
VulkanShader持有VkShaderModuleSetDevice()只是写入设备句柄,不转移设备所有权GetNativeHandle()返回VkShaderModule
设计取向
把“文本编译”与“native module 持有”拆开,是比较合理的商业引擎设计:
- 编译步骤通常依赖外部工具链、缓存或导入流程
- runtime 持有对象则只需要稳定地包装 native handle
这样做的好处是职责清晰,后续更容易插入 shader cache、离线编译或 asset import 管线;代价是使用者必须理解 VulkanShader 和 VulkanShaderCompiler 不是同一个层次的东西。
如果对照 Unity,可以把 VulkanShader 理解成更接近 backend 内部的编译后着色器句柄,而不是 Unity ShaderLab 那种同时承载 authoring、编译和运行时绑定的统一概念。
当前限制
- 只直接接受 SPIR-V 输入
- 当前 uniform 反射信息基本没有真正建起来
- 不包含 GLSL/HLSL 文本编译逻辑
- 不负责 shader cache、变体管理或 asset 导入
主要公开方法
bool CompileFromFile(const wchar_t* filePath, const char* entryPoint, const char* target)bool Compile(const void* sourceData, size_t sourceSize, const char* entryPoint, const char* target)void Shutdown()ShaderType GetType() constbool IsValid() constvoid* GetNativeHandle()const std::vector<UniformInfo>& GetUniformInfos() constconst UniformInfo* GetUniformInfo(const char* name) constvoid SetDevice(VkDevice device)VkShaderModule GetShaderModule() constconst char* GetEntryPoint() const
相关测试与使用线索
tests/RHI/unit/test_shader.cpp覆盖了抽象 shader 创建、类型获取、native handle 与 shutdown 行为tests/RHI/unit/test_vulkan_graphics.cpp明确验证了从 SPIR-V、GLSL 源码和 GLSL 文件创建 Vulkan shader 的路径tests/RHI/unit/test_compute.cpp和tests/RHI/unit/test_command_list.cpp会把 compute shader 接入 pipeline 与 dispatch 流程