Files
Seele/src/Engine/Graphics/Vulkan/VulkanShader.cpp
T
2021-10-15 23:12:29 +02:00

107 lines
3.1 KiB
C++

#include "VulkanShader.h"
#include "VulkanGraphics.h"
#include "VulkanDescriptorSets.h"
#include "slang.h"
#include "stdlib.h"
using namespace slang;
using namespace Seele;
using namespace Seele::Vulkan;
Shader::Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage)
: graphics(graphics)
, type(shaderType)
, stage(stage)
{
}
Shader::~Shader()
{
if(module != VK_NULL_HANDLE)
{
vkDestroyShaderModule(graphics->getDevice(), module, nullptr);
}
}
Map<uint32, PDescriptorLayout> Shader::getDescriptorLayouts()
{
return descriptorSets;
}
uint32 Seele::Vulkan::Shader::getShaderHash() const
{
return hash;
}
static SlangStage getStageFromShaderType(ShaderType type)
{
switch (type)
{
case ShaderType::VERTEX:
return SLANG_STAGE_VERTEX;
case ShaderType::CONTROL:
return SLANG_STAGE_HULL;
case ShaderType::EVALUATION:
return SLANG_STAGE_DOMAIN;
case ShaderType::GEOMETRY:
return SLANG_STAGE_GEOMETRY;
case ShaderType::FRAGMENT:
return SLANG_STAGE_PIXEL;
default:
return SLANG_STAGE_NONE;
}
}
void Shader::create(const ShaderCreateInfo& createInfo)
{
entryPointName = createInfo.entryPoint;
static SlangSession* session = spCreateSession(nullptr);
SlangCompileRequest* request = spCreateCompileRequest(session);
int targetIndex = spAddCodeGenTarget(request, SLANG_SPIRV);
spSetTargetProfile(request, targetIndex, spFindProfile(session, "glsl_vk"));
spSetDumpIntermediates(request, true);
int translationUnitIndex = spAddTranslationUnit(request, SLANG_SOURCE_LANGUAGE_SLANG, "");
for(auto code : createInfo.shaderCode)
{
spAddTranslationUnitSourceString(
request,
translationUnitIndex,
entryPointName.c_str(),
code.data()
);
}
for(auto define : createInfo.defines)
{
spAddPreprocessorDefine(request, define.key, define.value);
}
spAddSearchPath(request, "shaders/lib/");
spAddSearchPath(request, "shaders/generated/");
spSetGlobalGenericArgs(request, (int)createInfo.typeParameter.size(), createInfo.typeParameter.data());
int entryPointIndex = spAddEntryPoint(request, translationUnitIndex, entryPointName.c_str(), getStageFromShaderType(type));
if(spCompile(request))
{
char const* diagnostics = spGetDiagnosticOutput(request);
std::cout << "Compile error for shader " << createInfo.name << std::endl;
std::cout << diagnostics << std::endl;
return;
}
size_t dataSize = 0;
const uint32* data = reinterpret_cast<const uint32*>(spGetEntryPointCode(request, entryPointIndex, &dataSize));
VkShaderModuleCreateInfo moduleInfo;
moduleInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
moduleInfo.pNext = nullptr;
moduleInfo.flags = 0;
moduleInfo.codeSize = dataSize;
moduleInfo.pCode = data;
VK_CHECK(vkCreateShaderModule(graphics->getDevice(), &moduleInfo, nullptr, &module));
boost::crc_32_type result;
result.process_bytes(entryPointName.data(), entryPointName.size());
result.process_bytes(data, dataSize);
hash = result.checksum();
}