From 5da6a0e05ebdc17fcec09b695326e66dbe21e7d5 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Sun, 26 Oct 2025 11:43:10 +0800 Subject: [PATCH] [Fix] (MG_Backend/DirectGLES): Actually compile shader and use. * TODO: remove junk code. --- MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 13 ++ MobileGL/MG_Backend/DirectGLES/Managers.cpp | 162 +++++++++++++++--- MobileGL/MG_Backend/DirectGLES/Managers.h | 4 + MobileGL/MG_Backend/DirectGLES/Utils.cpp | 4 +- MobileGL/MG_Backend/DirectGLES/Utils.h | 3 +- .../GLState/ProgramState/ProgramObject.h | 3 + .../ShaderTranspiler/ShaderCompiler.cpp | 4 +- 7 files changed, 168 insertions(+), 25 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 8d6baafc..2f5d08f0 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -1,4 +1,5 @@ #include "DirectGLES.h" +#include "MG_Util/ShaderTranspiler/Types.h" #include "Utils.h" #include "Managers.h" #include @@ -289,6 +290,18 @@ namespace MobileGL::MG_Backend::DirectGLES { const auto& backendProgramIt = PrgramImpl::g_backendProgramObjects.find(currentProgram); if (backendProgramIt != PrgramImpl::g_backendProgramObjects.end()) { backendProgramIt->second->Use(); + // UBO + MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, backendProgramIt->second->GetBackendGlobalUBOId()); + MG_External::GLES::glBufferSubData(GL_UNIFORM_BUFFER, 0, currentProgram->GetUBOSize(), + currentProgram->MapUBO()); + MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, 0); + + Uint bindingPoint; + MG_External::GLES::glGetUniformBlockIndex(backendProgramIt->second->GetBackendProgramId(), + MG_Util::ShaderTranspiler::GLOBAL_UBO_NAME); + + MG_External::GLES::glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, + backendProgramIt->second->GetBackendGlobalUBOId()); } else { MG_External::GLES::glUseProgram(0); } diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index 5fa2f15a..c65241b7 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -1,4 +1,7 @@ #include "Managers.h" +#include "MG_Backend/Backends.h" +#include "MG_State/GLState/ProgramState/ShaderObject.h" +#include "MG_Util/Types.h" #include "Utils.h" #include "DirectGLES.h" #include @@ -147,7 +150,7 @@ namespace MobileGL::MG_Backend::DirectGLES { return; } - MGLOG_D("Syncing VAO object with ID: %u to backend for state: %s", m_backendVAOId, stateVAOObject.get()); + MGLOG_D("Syncing VAO object with ID: %u to backend for state: 0x%p", m_backendVAOId, stateVAOObject.get()); BufferImpl::BackendBufferBindingProtector backendBufferBindingProtector(BufferImpl::TempBufferTarget); BackendVertexArrayBindingProtector backendVAOBindingProtector; @@ -222,7 +225,7 @@ namespace MobileGL::MG_Backend::DirectGLES { return; } - MGLOG_D("Syncing texture object with ID: %u to backend for state: %s", m_backendTextureId, + MGLOG_D("Syncing texture object with ID: %u to backend for state: 0x%p", m_backendTextureId, stateTextureObject.get()); GLenum target = MG_Util::ConvertTextureTargetToGLEnum(stateTextureObject->GetTarget()); @@ -340,7 +343,7 @@ namespace MobileGL::MG_Backend::DirectGLES { return; } - MGLOG_D("Syncing FBO object with ID: %u to backend for state: %s", m_backendFBOId, stateFBOObject.get()); + MGLOG_D("Syncing FBO object with ID: %u to backend for state: 0x%p", m_backendFBOId, stateFBOObject.get()); BackendFramebufferBindingProtector backendFBOBindingProtector(GL_FRAMEBUFFER); Bind(); @@ -352,9 +355,6 @@ namespace MobileGL::MG_Backend::DirectGLES { FramebufferAttachmentType attachmentType = static_cast(index); const auto& attachment = attachments[index]; if (!attachment.IsComplete()) { - MG_External::GLES::glFramebufferRenderbuffer( - GL_FRAMEBUFFER, MG_Util::ConvertFramebufferAttachmentTypeToGLEnum(attachmentType), - GL_RENDERBUFFER, 0); continue; } @@ -386,31 +386,50 @@ namespace MobileGL::MG_Backend::DirectGLES { g_backendShaderObjects; UnorderedMap, SharedPtr> g_backendProgramObjects; + BackendShaderObjectImpl::BackendShaderObjectImpl() { m_backendShaderId = MG_External::GLES::glCreateShader(GL_VERTEX_SHADER); if (m_backendShaderId == 0) { MGLOG_E("Failed to create shader object in backend."); + } else { + MGLOG_D("Created backend shader object with ID: %u", m_backendShaderId); } } + BackendShaderObjectImpl::~BackendShaderObjectImpl() { if (m_backendShaderId != 0) { + MGLOG_D("Deleting backend shader object with ID: %u", m_backendShaderId); MG_External::GLES::glDeleteShader(m_backendShaderId); } } + void BackendShaderObjectImpl::SyncToBackend(SharedPtr& stateShaderObject) { - if (!stateShaderObject || !stateShaderObject->GetCompileStatus()) { - MGLOG_E("Shader object is null or not compiled, skipping backend sync."); + if (!stateShaderObject) { + MGLOG_E("State shader object is null, skipping backend sync."); return; } - String source = stateShaderObject->GetShaderSource(); - source = removeLayoutBinding(source); - source = ProcessOutColorLocations(source); - source = ForceSupporterOutput(source); - GLenum shaderType = ConvertGLShaderTypeByMGLShaderStage(stateShaderObject->GetShaderStage()); + + if (!stateShaderObject->GetCompileStatus()) { + MGLOG_E("Shader object is not compiled, skipping backend sync. Shader: 0x%p", stateShaderObject.get()); + return; + } + + MGLOG_D("Syncing shader to backend. State shader: 0x%p, Backend ID: %u, Stage: %s", stateShaderObject.get(), + m_backendShaderId, + MG_Util::ConvertGLEnumToString( + MG_State::GLState::ConvertGLShaderTypeByMGLShaderStage(stateShaderObject->GetShaderStage())) + .c_str()); + + auto shaderTShader = stateShaderObject->GetCompiledShader(); + String source = ConvertTShaderToGLSL(shaderTShader, 320, true); // TODO: get real version const char* sourceCStr = source.c_str(); + MGLOG_D("Setting shader source for backend shader ID: %u", m_backendShaderId); MG_External::GLES::glShaderSource(m_backendShaderId, 1, &sourceCStr, nullptr); + + MGLOG_D("Compiling shader. Backend ID: %u", m_backendShaderId); MG_External::GLES::glCompileShader(m_backendShaderId); + GLint compileStatus; MG_External::GLES::glGetShaderiv(m_backendShaderId, GL_COMPILE_STATUS, &compileStatus); if (compileStatus != GL_TRUE) { @@ -418,47 +437,135 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_External::GLES::glGetShaderiv(m_backendShaderId, GL_INFO_LOG_LENGTH, &logLength); Vector log(logLength); MG_External::GLES::glGetShaderInfoLog(m_backendShaderId, logLength, nullptr, log.data()); - MGLOG_E("Shader compilation failed: %s", log.data()); + MGLOG_E("Shader compilation failed for backend ID %u: %s", m_backendShaderId, log.data()); + } else { + MGLOG_D("Shader compiled successfully. Backend ID: %u", m_backendShaderId); } + m_isInitialized = true; + MGLOG_D("Shader sync completed. Backend ID: %u", m_backendShaderId); } + BackendProgramObjectImpl::BackendProgramObjectImpl() { m_backendProgramId = MG_External::GLES::glCreateProgram(); if (m_backendProgramId == 0) { MGLOG_E("Failed to create program object in backend."); + } else { + MGLOG_D("Created backend program object with ID: %u", m_backendProgramId); } } + BackendProgramObjectImpl::~BackendProgramObjectImpl() { if (m_backendProgramId != 0) { + MGLOG_D("Deleting backend program object with ID: %u", m_backendProgramId); MG_External::GLES::glDeleteProgram(m_backendProgramId); } } + void BackendProgramObjectImpl::SyncToBackend(SharedPtr& stateProgramObject) { - if (!stateProgramObject || !stateProgramObject->GetLinkStatus()) { - MGLOG_E("Program object is null or not linked, skipping backend sync."); + if (!stateProgramObject) { + MGLOG_E("State program object is null, skipping backend sync."); return; } + + if (!stateProgramObject->GetLinkStatus()) { + MGLOG_E("Program object is not linked, skipping backend sync. Program: 0x%p", stateProgramObject.get()); + return; + } + + MGLOG_D("Syncing program to backend. State program: 0x%p, Backend ID: 0x%p", stateProgramObject.get(), + m_backendProgramId); + // Detach all existing shaders GLint attachedCount = 0; MG_External::GLES::glGetProgramiv(m_backendProgramId, GL_ATTACHED_SHADERS, &attachedCount); + MGLOG_D("Currently attached shaders count: %d", attachedCount); + if (attachedCount > 0) { Vector attachedShaders(attachedCount); GLsizei actualCount; MG_External::GLES::glGetAttachedShaders(m_backendProgramId, attachedCount, &actualCount, attachedShaders.data()); + MGLOG_D("Detaching %d existing shaders from program %u", actualCount, m_backendProgramId); + for (GLsizei i = 0; i < actualCount; ++i) { + MGLOG_D("Detaching shader ID: %u from program %u", attachedShaders[i], m_backendProgramId); MG_External::GLES::glDetachShader(m_backendProgramId, attachedShaders[i]); } } + // Attach current shaders - for (const auto& shader : stateProgramObject->GetAttachedShaders()) { - const auto& it = g_backendShaderObjects.find(shader); - if (it != g_backendShaderObjects.end() && it->second) { - MG_External::GLES::glAttachShader(m_backendProgramId, it->second->GetBackendShaderId()); + auto& attachedShaders = stateProgramObject->GetAttachedShaders(); + MGLOG_D("Attaching %zu shaders to program %u", attachedShaders.size(), m_backendProgramId); + auto& shaderSpirvs = stateProgramObject->GetGeneratedSpirv(); + + for (int index = 0; index < attachedShaders.size(); ++index) { + auto& shader = attachedShaders[index]; + GLenum glShaderType = MG_State::GLState::ConvertGLShaderTypeByMGLShaderStage(shader->GetShaderStage()); + GLuint backendShaderId = MG_External::GLES::glCreateShader(glShaderType); + + if (backendShaderId == 0) { + MGLOG_E("Failed to create backend shader for attachment."); + continue; } + String source; + auto& spirvCode = shaderSpirvs[index]; + + MG_Util::ShaderTranspiler::SpvcSession spvcSession(spirvCode); + + spvc_compiler_options options; + spvcSession.CreateOptions(&options); + + spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, 320); + spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, SPVC_TRUE); + spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_VULKAN_SEMANTICS, SPVC_FALSE); + + spvcSession.SetOptions(options); + + const char* result = nullptr; + spvcSession.Compile(&result); + + if (!result) { + MG_Util::ShaderTranspiler::ResultInfo r; + r.log += "Failed to compile the shader to GLSL: \n"; + r.log += spvcSession.GetLastErrorString(); + r.errc = -5; + MGLOG_E("%s", r.log.c_str()); + continue; + } + + source = result; + + source = RemoveLayoutBinding(source); + source = ProcessOutColorLocations(source); + source = ForceSupporterOutput(source); + + const char* sourceCStr = source.c_str(); + MGLOG_D("Setting shader source for backend shader ID: %u", backendShaderId); + MG_External::GLES::glShaderSource(backendShaderId, 1, &sourceCStr, nullptr); + MG_External::GLES::glCompileShader(backendShaderId); + + GLint compileStatus; + MG_External::GLES::glGetShaderiv(backendShaderId, GL_COMPILE_STATUS, &compileStatus); + if (compileStatus == GL_FALSE) { + GLint logLength; + MG_External::GLES::glGetShaderiv(backendShaderId, GL_INFO_LOG_LENGTH, &logLength); + Vector log(logLength); + MG_External::GLES::glGetShaderInfoLog(backendShaderId, logLength, nullptr, log.data()); + MGLOG_E("Shader compilation failed for backend ID %u: %s", backendShaderId, log.data()); + continue; + } + + MGLOG_D("Attaching shader ID: %u to program %u", backendShaderId, m_backendProgramId); + MG_External::GLES::glAttachShader(m_backendProgramId, backendShaderId); + + MGLOG_D("Processed shader source length: %zu", source.length()); } + // Link program + MGLOG_D("Linking program %u", m_backendProgramId); MG_External::GLES::glLinkProgram(m_backendProgramId); + GLint linkStatus; MG_External::GLES::glGetProgramiv(m_backendProgramId, GL_LINK_STATUS, &linkStatus); if (linkStatus != GL_TRUE) { @@ -466,11 +573,24 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_External::GLES::glGetProgramiv(m_backendProgramId, GL_INFO_LOG_LENGTH, &logLength); Vector log(logLength); MG_External::GLES::glGetProgramInfoLog(m_backendProgramId, logLength, nullptr, log.data()); - MGLOG_E("Program linking failed: %s", log.data()); + MGLOG_E("Program linking failed for %u: %s", m_backendProgramId, log.data()); + } else { + MGLOG_D("Program linked successfully. ID: %u", m_backendProgramId); } + + // Create global UBO + MG_External::GLES::glGenBuffers(1, &m_backendGlobalUBOId); + MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, m_backendGlobalUBOId); + MG_External::GLES::glBufferData(GL_UNIFORM_BUFFER, stateProgramObject->GetUBOSize(), nullptr, + GL_STREAM_DRAW); + MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, 0); + m_isInitialized = true; + MGLOG_D("Program sync completed. Backend ID: %u", m_backendProgramId); } + void BackendProgramObjectImpl::Use() { + MGLOG_D("Using program %u", m_backendProgramId); MG_External::GLES::glUseProgram(m_backendProgramId); } } // namespace PrgramImpl diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.h b/MobileGL/MG_Backend/DirectGLES/Managers.h index fd806ff5..57601437 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.h +++ b/MobileGL/MG_Backend/DirectGLES/Managers.h @@ -107,6 +107,7 @@ namespace MobileGL::MG_Backend::DirectGLES { Uint m_backendShaderId = 0; Bool m_isInitialized = false; }; + class BackendProgramObjectImpl { public: BackendProgramObjectImpl(); @@ -114,11 +115,14 @@ namespace MobileGL::MG_Backend::DirectGLES { void SyncToBackend(SharedPtr& stateProgramObject); void Use(); Uint GetBackendProgramId() const { return m_backendProgramId; } + Uint GetBackendGlobalUBOId() const { return m_backendGlobalUBOId; } private: Uint m_backendProgramId = 0; + Uint m_backendGlobalUBOId = 0; Bool m_isInitialized = false; }; + extern UnorderedMap, SharedPtr> g_backendShaderObjects; extern UnorderedMap, SharedPtr> diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.cpp b/MobileGL/MG_Backend/DirectGLES/Utils.cpp index faceb7c2..09c3c40f 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Utils.cpp @@ -294,6 +294,8 @@ namespace MobileGL::MG_Backend::DirectGLES { } // namespace FramebufferImpl namespace PrgramImpl { + String ConvertTShaderToGLSL(SharedPtr& shaderTShader, Uint glslVersion, Bool isES) {} + String ProcessOutColorLocations(const String& glslCode) { const static std::regex pattern(R"(\n(out highp vec4 outColor)(\d+);)"); const String replacement = "\nlayout(location=$2) $1$2;"; @@ -356,7 +358,7 @@ namespace MobileGL::MG_Backend::DirectGLES { return result; } - String removeLayoutBinding(const String& glslCode) { + String RemoveLayoutBinding(const String& glslCode) { static std::regex bindingRegex(R"(layout\s*\(\s*binding\s*=\s*\d+\s*\)\s*)"); String result = std::regex_replace(glslCode, bindingRegex, ""); static std::regex bindingRegex2(R"(layout\s*\(\s*binding\s*=\s*\d+\s*,)"); diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.h b/MobileGL/MG_Backend/DirectGLES/Utils.h index c086c4a0..22c50e21 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.h +++ b/MobileGL/MG_Backend/DirectGLES/Utils.h @@ -61,9 +61,10 @@ namespace MobileGL::MG_Backend::DirectGLES { } // namespace FramebufferImpl namespace PrgramImpl { + String ConvertTShaderToGLSL(SharedPtr& shaderTShader, Uint glslVersion, Bool isES); String ProcessOutColorLocations(const String& glslCode); String ForceSupporterOutput(const String& glslCode); - String removeLayoutBinding(const String& glslCode); + String RemoveLayoutBinding(const String& glslCode); } // namespace PrgramImpl namespace Utils { diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h index dcf265b2..20a6bb95 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h @@ -44,6 +44,7 @@ namespace MobileGL { GLenum GetAttribType(Uint index) const { return m_attribTypes[index]; } const String& GetAttribName(Uint index) const { return m_attribs[index]; } void* MapUBO() { return m_uboScratch.data(); } + Uint GetUBOSize() const { return static_cast(m_uboScratch.size()); } Bool GetDeleteStatus() const { return m_deleteStatus; } Bool GetLinkStatus() const { return m_linkStatus; } @@ -54,6 +55,8 @@ namespace MobileGL { Int GetActiveAttributesMaxLength() const { return m_attribInNameMaxLength; } Int GetActiveUniformBlocksMaxNameLength() const { return m_uniformBlockNameMaxLength; } + Vector>& GetGeneratedSpirv() { return m_generatedSpirv; } + private: void DoReflection(); void GenerateBinary(); diff --git a/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp b/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp index b66e1fff..c35a8780 100644 --- a/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp +++ b/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp @@ -142,11 +142,11 @@ namespace MobileGL { ((attrib.flags & ShaderCompileBits::EmitDiscardAsDemote) ? glslang::EShTargetSpv_1_6 : glslang::EShTargetSpv_1_5)); + tshader->setEnvInputVulkanRulesRelaxed(); // using EXT_vulkan_glsl_relaxed for gl_VertexID and + // gl_InstanceID? } tshader->setAutoMapLocations(true); tshader->setAutoMapBindings(true); - tshader->setEnvInputVulkanRulesRelaxed(); // using EXT_vulkan_glsl_relaxed for gl_VertexID and - // gl_InstanceID? tshader->setGlobalUniformBlockName(GLOBAL_UBO_NAME); if (!tshader->parse(&GetTBuiltInResourceInstance(), 460, ECoreProfile, /*forceDefaultVersionAndProfile: */ false,