103 lines
2.9 KiB
C++
103 lines
2.9 KiB
C++
//
|
|
// Created by atdunbg on 2026/9/20.
|
|
//
|
|
|
|
#include <Engine/Vulkan/ShaderManager.h>
|
|
#include <Engine/Vulkan/Device.h>
|
|
#include <Engine/Core/Log.h>
|
|
|
|
#include <array>
|
|
#include <fstream>
|
|
|
|
namespace Engine {
|
|
|
|
ShaderManager::ShaderManager(Device& device)
|
|
: m_Device(device)
|
|
{
|
|
}
|
|
|
|
ShaderManager::~ShaderManager()
|
|
{
|
|
}
|
|
|
|
ShaderObject ShaderManager::CreateFromFile(const std::string& spvPath,
|
|
vk::ShaderStageFlagBits stage,
|
|
const std::vector<vk::DescriptorSetLayout>& layouts,
|
|
u32 pushConstantSize)
|
|
{
|
|
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,
|
|
vk::ShaderStageFlagBits stage,
|
|
const std::vector<vk::DescriptorSetLayout>& layouts,
|
|
u32 pushConstantSize)
|
|
{
|
|
vk::ShaderStageFlags nextStage = {};
|
|
if (stage == vk::ShaderStageFlagBits::eVertex) {
|
|
nextStage = vk::ShaderStageFlagBits::eFragment;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
std::array<vk::PushConstantRange, 1> pushRanges;
|
|
if (pushConstantSize > 0) {
|
|
pushRanges[0].setStageFlags(vk::ShaderStageFlagBits::eVertex)
|
|
.setOffset(0)
|
|
.setSize(pushConstantSize);
|
|
createInfo.setPushConstantRanges(pushRanges);
|
|
}
|
|
|
|
vk::ShaderEXT shader;
|
|
try {
|
|
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 };
|
|
}
|
|
|
|
return { shader, stage };
|
|
}
|
|
|
|
void ShaderManager::Destroy(const ShaderObject& shader)
|
|
{
|
|
if (shader.Handle) {
|
|
m_Device.GetDevice().destroyShaderEXT(shader.Handle);
|
|
}
|
|
}
|
|
|
|
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 {};
|
|
}
|
|
|
|
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
|