101 lines
3.1 KiB
C++
101 lines
3.1 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;
|
|
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;
|
|
}
|
|
}
|