diff --git a/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp b/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp index 395e77f7..b78095c4 100644 --- a/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp +++ b/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp @@ -922,8 +922,7 @@ namespace MG_GL::GL { } void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount, const GLint *basevertex) { - return; - // PrepareForDraw(); + PrepareForDraw(mode, (GLsizei *)count, type, (const void*&)indices[0]); auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO(); Diligent::IBuffer* pIndexBuffer = nullptr; diff --git a/MG/MG_GL/Implementations/GL/Program/GL_Program.cpp b/MG/MG_GL/Implementations/GL/Program/GL_Program.cpp index 0b9808fb..bd1e70c6 100644 --- a/MG/MG_GL/Implementations/GL/Program/GL_Program.cpp +++ b/MG/MG_GL/Implementations/GL/Program/GL_Program.cpp @@ -292,39 +292,78 @@ namespace MG_GL::GL { } MG_Global::unordered_map shaderSources; + MG_Global::unordered_map finalShaderSources; + for (GLuint shaderId : programObj.attachedShaders) { + auto it = MG_State_T::programState->shaders_.find(shaderId); + if (it != MG_State_T::programState->shaders_.end() && !it->second.markedForDeletion) { + shaderSources[it->first] = it->second.source; + MG_Util::Program::RenameGLSLBuiltinsForVulkan(shaderSources[it->first]); + } + } + + MG_Util::Program::GenerateDefaultUBOForGLSL_Multi(shaderSources, programInfo.uniformBufferNames); + for (GLuint shaderId : programObj.attachedShaders) { auto it = MG_State_T::programState->shaders_.find(shaderId); if (it != MG_State_T::programState->shaders_.end() && !it->second.markedForDeletion) { std::string shaderSource; if (it->second.type == GL_VERTEX_SHADER) { std::string infoLog; - auto spirv = - MG_Util::Program::CompileGLSLToSPIRV(it->second.type, - it->second.source, - infoLog); + + const char* fragmentShaderSource = nullptr; + for (GLuint otherShaderId : programObj.attachedShaders) { + if (otherShaderId != shaderId && MG_State_T::programState->shaders_[otherShaderId].type == GL_FRAGMENT_SHADER) { + fragmentShaderSource = shaderSources[otherShaderId].c_str(); + break; + } + } + auto spirv = MG_Util::Program::CompileGLSLToSPIRV(it->second.type, + shaderSources[shaderId], + infoLog, true, GL_FRAGMENT_SHADER, fragmentShaderSource); if (spirv.empty()) { - MG_Util::Debug::LogE("Failed to compile shader %u: %s", shaderId, + MG_Util::Debug::LogE("Failed to compile vertex shader %u: %s", shaderId, infoLog.c_str()); continue; } shaderSource = MG_Util::Program::BindInputLayoutLocationsForGLSL(spirv, - programObj.attribLocations); + programObj.attribLocations); + } else if (it->second.type == GL_FRAGMENT_SHADER) { + std::string infoLog; + + const char* vertexShaderSource = nullptr; + for (GLuint otherShaderId : programObj.attachedShaders) { + if (otherShaderId != shaderId && MG_State_T::programState->shaders_[otherShaderId].type == GL_VERTEX_SHADER) { + vertexShaderSource = shaderSources[otherShaderId].c_str(); + break; + } + } + + auto spirv = MG_Util::Program::CompileGLSLToSPIRV(it->second.type, + shaderSources[shaderId], + infoLog, true, + GL_VERTEX_SHADER, vertexShaderSource); + if (spirv.empty()) { + MG_Util::Debug::LogE("Failed to compile fragment shader %u to SPIRV: %s", shaderId, + infoLog.c_str()); + continue; + } + + shaderSource = MG_Util::Program::CompileSPIRVToGLSL(spirv, 450, false, true); } else { shaderSource = it->second.source; } - MG_Util::Program::RenameGLSLBuiltinsForVulkan(shaderSource); - shaderSources[it->first] = shaderSource; + finalShaderSources[it->first] = shaderSource; } } - - MG_Util::Program::GenerateDefaultUBOForGLSL_Multi(shaderSources, programInfo.uniformBufferNames); + + MG_Util::Debug::LogD("Shader sources after UBO generation for program %u:", program); - for (const auto& [shaderId, source] : shaderSources) { + for (const auto& [shaderId, source] : finalShaderSources) { MG_Util::Debug::LogD(" Program %u Shader %u:\n%s", program, shaderId, source.c_str()); } - size_t uboTotalSize = RecordUniformOffsets(programInfo, shaderSources); + size_t uboTotalSize = RecordUniformOffsets(programInfo, finalShaderSources); CreateDefaultUBO(programInfo, uboTotalSize); // Compile attached shaders @@ -333,7 +372,7 @@ namespace MG_GL::GL { // Compile only if not already compiled in Diligent if (MG_Diligent::g_ShaderMap.find(shaderId) == MG_Diligent::g_ShaderMap.end() || MG_Diligent::g_ShaderMap[shaderId] == nullptr) { GLenum shaderType = shaderObj.type; - std::string sourceStr = shaderSources[shaderId]; + std::string sourceStr = finalShaderSources[shaderId]; MG_Util::Debug::LogD("Shader ID: %u, type: %s\nConverted source:\n%s", shaderId, MG_Util::Debug::GLEnumToString(shaderType), sourceStr.c_str()); diff --git a/MG/MG_UTIL/Program/GLSLTool.cpp b/MG/MG_UTIL/Program/GLSLTool.cpp index d9552ed3..f105958c 100644 --- a/MG/MG_UTIL/Program/GLSLTool.cpp +++ b/MG/MG_UTIL/Program/GLSLTool.cpp @@ -672,7 +672,9 @@ namespace MG_Util::Program { } std::vector CompileGLSLToSPIRV(GLenum shaderType, const std::string &source, - std::string &infoLog, bool isVkGLSL) { + std::string &infoLog, bool isVkGLSL, GLenum additionalShaderType, + const std::string& additionalShaderSource + ) { using namespace glslang; TShader* shader = nullptr; @@ -682,12 +684,27 @@ namespace MG_Util::Program { return {}; } TProgram program; - program.addShader(shader); + + if (additionalShaderType == GL_VERTEX_SHADER) + program.addShader(shader); + if (additionalShaderType && !additionalShaderSource.empty()) { + TShader* additionalShader = nullptr; + std::string additionalInfoLog = CompileGLSLToTShader(additionalShaderType, additionalShaderSource, additionalShader, isVkGLSL); + if (!additionalInfoLog.empty()) { + infoLog = "Error: [glslang] Cannot compile additional " + GetShaderTypeName(additionalShaderType) + ":\n" + additionalInfoLog; + return {}; + } + program.addShader(additionalShader); + } + if (additionalShaderType != GL_VERTEX_SHADER) + program.addShader(shader); + if (!program.link(isVkGLSL ? EShMsgVulkanRules : EShMsgDefault)) { infoLog = "Error: [glslang] Cannot link the program of the single shader:\n" + std::to_string(program.getInfoLog()); return {}; } program.mapIO(); + std::vector spirv; SpvOptions spvOptions; @@ -999,7 +1016,7 @@ namespace MG_Util::Program { spvc_context_destroy(context); } - std::string CompileSPIRVToGLSL(std::vector spirv, uint glslVersion, bool isES) { + std::string CompileSPIRVToGLSL(std::vector spirv, uint glslVersion, bool isES, bool isVkGLSL) { spvc_context context = nullptr; spvc_parsed_ir ir = nullptr; spvc_compiler compiler_glsl = nullptr; @@ -1018,12 +1035,15 @@ namespace MG_Util::Program { spvc_compiler_create_shader_resources(compiler_glsl, &resources); spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &list, &count); spvc_compiler_create_compiler_options(compiler_glsl, &options); + spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, glslVersion); spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, isES ? SPVC_TRUE : SPVC_FALSE); + spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_VULKAN_SEMANTICS, isVkGLSL ? SPVC_TRUE : SPVC_FALSE); spvc_compiler_install_compiler_options(compiler_glsl, options); spvc_compiler_compile(compiler_glsl, &result); if (!result) { + MG_Util::Debug::LogE("Failed to compile the shader to GLSL: %s", spvc_context_get_last_error_string(context)); return{}; } diff --git a/MG/MG_UTIL/Program/GLSLTool.h b/MG/MG_UTIL/Program/GLSLTool.h index dbe625ae..3fd11a65 100644 --- a/MG/MG_UTIL/Program/GLSLTool.h +++ b/MG/MG_UTIL/Program/GLSLTool.h @@ -174,12 +174,13 @@ namespace MG_Util::Program { } std::vector CompileGLSLToSPIRV(GLenum shaderType, const std::string& source, - std::string& infoLog, bool isVkGLSL = false); + std::string& infoLog, bool isVkGLSL = false, GLenum additionalShaderType = 0, + const std::string& additionalShaderSource = {}); std::string CompileGLSLToTShader(GLenum shaderType, const std::string& source, glslang::TShader *&shader, bool isVkGLSL = false); std::vector> CompileMultipleShadersToSPIRV(const ProgramState& state, ProgramObject& prog, std::string& infoLog); void ReflectSPIRVUniforms(const std::vector>& allSpirv, ProgramObject& prog, std::string& infoLog); - std::string CompileSPIRVToGLSL(std::vector spirv, uint glslVersion, bool isES); + std::string CompileSPIRVToGLSL(std::vector spirv, uint glslVersion, bool isES, bool isVkGLSL = false); std::pair GenerateDefaultUBOForGLSL(const std::pair& glslSources); void GenerateDefaultUBOForGLSL_Multi(