diff --git a/CMakeLists.txt b/CMakeLists.txt index 58945d7f..ac485d65 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,7 @@ set(SOURCE_FILES MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp + MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.cpp MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp diff --git a/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp index 5f37118c..73be7323 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp @@ -1,6 +1,8 @@ #include "ShaderObject.h" +#include #include #include +#include #include namespace MobileGL { @@ -16,6 +18,7 @@ namespace MobileGL { void ShaderObject::Compile() { using namespace MG_Util::ShaderTranspiler; + MG_Util::ShaderTranspiler::PreprocessShaderSource(m_stage, m_source); // Compile for OpenGL here, so that we can do validation and link // like a real OpenGL driver at linking stage diff --git a/MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.cpp b/MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.cpp new file mode 100644 index 00000000..116b3368 --- /dev/null +++ b/MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.cpp @@ -0,0 +1,45 @@ +#include "ShaderSourceProcessor.h" + +namespace MobileGL { + namespace MG_Util { + namespace ShaderTranspiler { + void PreprocessShaderSource(ShaderStage stage, String& source) { + ShaderProfile profile = ShaderProfile::Core; + SizeT versionPos = source.find("#version"); + + if (versionPos != String::npos) { + SizeT lineEnd = source.find('\n', versionPos); + String versionLine = source.substr(versionPos, lineEnd - versionPos); + + if (versionLine.find("ES") != String::npos) + profile = ShaderProfile::ES; + else if (versionLine.find("compatibility") != String::npos) + profile = ShaderProfile::Compatibility; + else + profile = ShaderProfile::Core; + } else { + profile = ShaderProfile::Core; + source.insert(0, "#version 460 core\n"); + return; + } + + SizeT firstLineEnd = source.find('\n'); + + if (profile != ShaderProfile::ES) { + constexpr const char* versionDirectiveCore = "#version 460 core\n"; + constexpr const char* versionDirectiveCompat = "#version 460 compatibility\n"; + + const char* replacement = + (profile == ShaderProfile::Compatibility) ? versionDirectiveCompat : versionDirectiveCore; + + if (firstLineEnd != std::string::npos) { + source.replace(0, firstLineEnd + 1, replacement); + } else { + source = replacement; + } + } + } + + } // namespace ShaderTranspiler + } // namespace MG_Util +} // namespace MobileGL diff --git a/MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.h b/MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.h new file mode 100644 index 00000000..a248ec70 --- /dev/null +++ b/MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include + +namespace MobileGL { + enum class ShaderProfile { + Core, + Compatibility, + ES, + }; + + namespace MG_Util { + namespace ShaderTranspiler { + void PreprocessShaderSource(ShaderStage stage, String& source); + } // namespace ShaderTranspiler + } // namespace MG_Util +} // namespace MobileGL \ No newline at end of file