Files
OpenVulkano/openVulkanoCpp/Shader/ShaderCompiler.cpp
2024-07-16 11:08:00 +03:00

102 lines
3.2 KiB
C++

#include "ShaderCompiler.hpp"
namespace OpenVulkano
{
Unique<void*> ShaderCompiler::CompileGLSLToSpirv(const std::string& absPath, const std::string& incPath,
const std::string& entryPoint, shaderc_shader_kind shaderStage,
bool bHaveIncludes)
{
Array<char> file = Utils::ReadFile(absPath, false, true);
#if defined(_DEBUG)
printf("Compiling shader: %s\n", absPath.c_str());
printf("%s\n", file.Data() + 1);
#endif
shaderc::Compiler shaderCompiler;
shaderc::CompileOptions options;
if (bHaveIncludes) options.SetIncluder(std::make_unique<ShaderIncluder>(incPath));
options.SetSourceLanguage(shaderc_source_language_glsl);
options.SetSuppressWarnings();
shaderc::PreprocessedSourceCompilationResult preResult =
shaderCompiler.PreprocessGlsl(file.Data(), shaderStage, entryPoint.c_str(), options);
if (preResult.GetCompilationStatus() != shaderc_compilation_status_success)
{
throw std::runtime_error("Failed to preprocess shader: " + preResult.GetErrorMessage());
return nullptr;
}
shaderc::CompilationResult result =
shaderCompiler.CompileGlslToSpv(static_cast<const char*>(preResult.begin()), shaderStage, "", options);
if (result.GetCompilationStatus() != shaderc_compilation_status_success)
{
throw std::runtime_error("Failed to compile shader: " + result.GetErrorMessage());
return nullptr;
}
Unique<void*> spirv = std::make_unique<void*>((void*) result.begin());
return spirv;
}
ShaderIncluder::ShaderIncluder(const std::string& path)
{
// TODO : Add the path to your include folder
m_includes.push_back(path);
}
shaderc_include_result* ShaderIncluder::GetInclude(const char* requested_source, shaderc_include_type type,
const char* requesting_source, uint64_t include_depth)
{
const char* includePath = GetActualPath(requested_source);
const char* content = RecordInclude(includePath);
shaderc_include_result* result = new shaderc_include_result();
result->content = content;
result->content_length = strlen(content);
result->source_name = includePath;
result->source_name_length = strlen(includePath);
result->user_data = nullptr;
return result;
}
void ShaderIncluder::ReleaseInclude(shaderc_include_result* data) { delete data; }
std::string ShaderIncluder::ResolveInclude(const std::string requestedSource)
{
// Check if the file exists in the include paths
for (const std::string& includePath: m_includes)
{
std::string path = includePath + requestedSource;
// TODO: Need to check if the folder exists
return path;
}
return "";
}
const char* ShaderIncluder::RecordInclude(const std::string& requestedSource)
{
Array<char> data = Utils::ReadFile(requestedSource);
char* result = new char[data.Size() + 1];
strcpy_s(result, data.Size(), data.Data());
return result;
}
const char* ShaderIncluder::GetActualPath(const std::string& requestedSource)
{
std::string includePath = ResolveInclude(requestedSource);
char* result = new char[includePath.size() + 1];
strcpy_s(result, includePath.size(), includePath.c_str());
return result;
}
}