#include "ShaderCompiler.hpp" #include "Base/Logger.hpp" #include namespace OpenVulkano { Unique ShaderCompiler::CompileGLSLToSpirv(const std::string& absPath, const std::string& incPath, const std::string& entryPoint, shaderc_shader_kind shaderStage, bool bHaveIncludes) { Array file = Utils::ReadFile(absPath, false, true); shaderc::Compiler shaderCompiler; shaderc::CompileOptions options; if (bHaveIncludes) options.SetIncluder(std::make_unique(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(preResult.begin()), shaderStage, "", options); if (result.GetCompilationStatus() != shaderc_compilation_status_success) { throw std::runtime_error("Failed compiling shader. Reason: " + result.GetErrorMessage()); } Unique spirv = std::make_unique((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(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 + "'!"); } }