74 lines
2.8 KiB
C++
74 lines
2.8 KiB
C++
#include "ShaderCompiler.hpp"
|
|
|
|
#include "Base/Logger.hpp"
|
|
|
|
#include <filesystem>
|
|
|
|
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);
|
|
|
|
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 preprocessing shader. Reason: " + preResult.GetErrorMessage());
|
|
}
|
|
|
|
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 compiling shader. Reason: " + result.GetErrorMessage());
|
|
}
|
|
|
|
Unique<void*> spirv = std::make_unique<void*>((void*) result.begin());
|
|
return spirv;
|
|
}
|
|
|
|
ShaderIncluder::ShaderIncluder(const std::string& path) : m_includePath(path) {}
|
|
|
|
shaderc_include_result* ShaderIncluder::GetInclude(const char* requestedSource, shaderc_include_type type,
|
|
const char* requestingSource, uint64_t includeDepth)
|
|
{
|
|
IncludeData* includeData = new IncludeData();
|
|
includeData->m_fullPath = ResolveInclude(requestedSource);
|
|
includeData->m_content = Utils::ReadFile(includeData->m_fullPath, false, false); // using nullTerminate as true causes crash in here. Needed to use as false.
|
|
|
|
shaderc_include_result* result = &includeData->result;
|
|
result->content = includeData->m_content.Data();
|
|
result->content_length = includeData->m_content.Size();
|
|
result->source_name = includeData->m_fullPath.data();
|
|
result->source_name_length = includeData->m_fullPath.size();
|
|
result->user_data = includeData;
|
|
|
|
return result;
|
|
}
|
|
|
|
void ShaderIncluder::ReleaseInclude(shaderc_include_result* data)
|
|
{
|
|
delete static_cast<IncludeData*>(data->user_data);
|
|
}
|
|
|
|
std::string ShaderIncluder::ResolveInclude(const std::string& requestedSource) const
|
|
{
|
|
// Check if the file exists in the include path
|
|
std::string path = m_includePath + requestedSource;
|
|
if (std::filesystem::exists(path)) return path;
|
|
else throw std::runtime_error("Failed to resolve include '" + requestedSource + "'!");
|
|
}
|
|
}
|