From b83977b906b1f1dcf91c1a205461874f8de269a7 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Sun, 9 Nov 2025 11:37:39 +0800 Subject: [PATCH] [Fix] (MG_State/ProgramState): Separate detach/remove shader in ProgramObject. Add more log. --- MobileGL/MG_Backend/DirectGLES/Managers.cpp | 3 +- .../GLState/ProgramState/ProgramObject.cpp | 225 +++++++++++++++--- .../GLState/ProgramState/ProgramObject.h | 20 +- 3 files changed, 203 insertions(+), 45 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index 1c521c3f..de8f4725 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -565,7 +565,8 @@ 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 for %u: %s", m_backendProgramId, log.data()); + MGLOG_E("Program %u linking failed for %u: %s", stateProgramObject->GetExternalIndex(), + m_backendProgramId, log.data()); } else { MGLOG_D("Program linked successfully. ID: %u", m_backendProgramId); } diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp index 90738de8..1f96071d 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -8,79 +8,143 @@ namespace MobileGL { namespace MG_State { namespace GLState { bool ProgramObject::ShaderIsAttached(SharedPtr shader) { + MGLOG_D("ProgramObject %u: ShaderIsAttached check for shader %p", m_externalIndex, shader.get()); auto it = std::find_if(m_shaders.begin(), m_shaders.end(), [shader](const SharedPtr& s) { return s.get() == shader.get(); }); - return it != m_shaders.end(); + bool attached = it != m_shaders.end(); + MGLOG_D("ProgramObject %u: ShaderIsAttached -> %s", m_externalIndex, attached ? "true" : "false"); + return attached; } bool ProgramObject::AttachShader(SharedPtr shader) { - if (ShaderIsAttached(shader)) return false; + MGLOG_D("ProgramObject %u: AttachShader called for shader %p", m_externalIndex, shader.get()); + if (ShaderIsAttached(shader)) { + MGLOG_D("ProgramObject %u: AttachShader - shader already attached, skipping", m_externalIndex); + return false; + } m_shaders.emplace_back(shader); + MGLOG_D("ProgramObject %u: AttachShader - attached successfully, total shaders now %zu", + m_externalIndex, m_shaders.size()); return true; } SizeT ProgramObject::DetachShader(SharedPtr shader) { + MGLOG_D("DetachShader called for shader %p from ProgramObject %u", shader.get(), m_externalIndex); + if (!ShaderIsAttached(shader)) { + MGLOG_D("Shader %p is not attached to ProgramObject %u, cannot detach.", shader.get(), + m_externalIndex); + return 0; + } + m_detachedShaders.push_back(shader); + MGLOG_D("Shader %p marked for detachment from ProgramObject %u", shader.get(), m_externalIndex); + return 1; + } + + SizeT ProgramObject::RemoveShader(SharedPtr shader) { + MGLOG_D("ProgramObject %u: RemoveShader called for shader %p", m_externalIndex, shader.get()); auto count = std::erase_if( m_shaders, [shader](const SharedPtr& s) { return s.get() == shader.get(); }); + MGLOG_D("ProgramObject %u: RemoveShader - removed %zu shader(s), remaining %zu", m_externalIndex, count, + m_shaders.size()); return count; } void ProgramObject::Link() { + MGLOG_D("ProgramObject %u: Link start, shaders to link: %zu", m_externalIndex, m_shaders.size()); + // Remove detached shaders first + for (const auto& detachedShader : m_detachedShaders) { + RemoveShader(detachedShader); + } + m_detachedShaders.clear(); + Vector shaderTypes(m_shaders.size()); Vector> shaders(m_shaders.size()); - MGLOG_D("%s: shaders to link: %d\n", __func__, m_shaders.size()); + for (SizeT i = 0; i < m_shaders.size(); i++) { shaderTypes[i] = MG_Util::ConvertShaderStageToGLEnum(m_shaders[i]->GetShaderStage()); + MGLOG_D("ProgramObject %u: Preparing shader[%zu] stage %s at %p", m_externalIndex, i, + MG_Util::ConvertGLEnumToString(shaderTypes[i]).c_str(), m_shaders[i].get()); + if (!m_shaders[i]->GetCompileStatus()) { - m_infoLog = std::format("Linking a {} with compilation error, linking will now terminate. Shader error log:\n{}\nShader src:\n{}", - MG_Util::ConvertGLEnumToString(shaderTypes[i]).c_str(), - m_shaders[i]->GetInfoLog().c_str(), m_shaders[i]->GetShaderSource().c_str()); + m_infoLog = + std::format("Linking a {} with compilation error, linking will now terminate. Shader error " + "log:\n{}\nShader src:\n{}", + MG_Util::ConvertGLEnumToString(shaderTypes[i]).c_str(), + m_shaders[i]->GetInfoLog().c_str(), m_shaders[i]->GetShaderSource().c_str()); m_linkStatus = false; - MGLOG_W("%s", m_infoLog.c_str()); + MGLOG_E("ProgramObject %u: Link failed - shader[%zu] compile status false. InfoLog:\n%s", + m_externalIndex, i, m_infoLog.c_str()); return; } shaders[i] = m_shaders[i]->GetCompiledShader(); - MGLOG_D("%s: \n%s", - MG_Util::ConvertGLEnumToString(shaderTypes[i]).c_str(), m_shaders[i]->GetShaderSource().c_str()); + MGLOG_D("ProgramObject %u: shader[%zu] compiled shader ptr %p, src len %zu", m_externalIndex, i, + shaders[i].get(), m_shaders[i]->GetShaderSource().length()); + MGLOG_D("ProgramObject %u: shader[%zu] source:\n%s", m_externalIndex, i, + m_shaders[i]->GetShaderSource().c_str()); } MG_Util::ShaderTranspiler::ProgramAttrib attrib{ .shaders = Move(shaders), }; + MGLOG_D("ProgramObject %u: Calling ShaderCompiler::LinkProgram", m_externalIndex); auto result = MG_Util::ShaderTranspiler::ShaderCompiler::LinkProgram(attrib); if (result) { m_linkStatus = true; m_program = result.value(); + MGLOG_D("ProgramObject %u: LinkProgram succeeded, TProgram ptr %p", m_externalIndex, + m_program.get()); } else { m_linkStatus = false; m_infoLog = result.error().log; - MGLOG_W("%s", m_infoLog.c_str()); + MGLOG_E("ProgramObject %u: LinkProgram failed. InfoLog:\n%s", m_externalIndex, m_infoLog.c_str()); } + MGLOG_D("ProgramObject %u: Starting reflection", m_externalIndex); DoReflection(); + MGLOG_D("ProgramObject %u: Reflection done (linkStatus=%d)", m_externalIndex, (int)m_linkStatus); + + MGLOG_D("ProgramObject %u: Starting binary generation", m_externalIndex); GenerateBinary(); + MGLOG_D("ProgramObject %u: Binary generation finished (generatedSpirv size=%zu)", m_externalIndex, + m_generatedSpirv.size()); } void ProgramObject::MarkAsDeleted() { + MGLOG_D("ProgramObject %u: MarkAsDeleted called (was %s)", m_externalIndex, + m_deleteStatus ? "deleted" : "not deleted"); m_deleteStatus = true; + MGLOG_D("ProgramObject %u: MarkAsDeleted - now marked deleted", m_externalIndex); } Vector>& ProgramObject::GetAttachedShaders() { + MGLOG_D("ProgramObject %u: GetAttachedShaders called, returning %zu shaders", m_externalIndex, + m_shaders.size()); return m_shaders; } void ProgramObject::DoReflection() { + if (!m_program) { + MGLOG_E("ProgramObject %u: DoReflection called but m_program is null", m_externalIndex); + m_linkStatus = false; + m_infoLog = "DoReflection failed: no program."; + return; + } + + MGLOG_D("ProgramObject %u: DoReflection - building reflection", m_externalIndex); if (!m_program->buildReflection()) { m_linkStatus = false; m_infoLog = "Build reflection failed."; + MGLOG_E("ProgramObject %u: DoReflection - buildReflection() returned false", m_externalIndex); return; } // ------------ Uniforms (GL Plain) ---------------- // Allocate uniform locations m_activeUniformCount = m_program->getNumUniformVariables(); + MGLOG_D("ProgramObject %u: Reflection - active uniform count = %d", m_externalIndex, + m_activeUniformCount); for (int i = 0; i < m_activeUniformCount; i++) { auto& uniform = m_program->getUniform(i); auto location = uniform.layoutLocation(); @@ -89,17 +153,23 @@ namespace MobileGL { } m_uniformNameMaxLength = std::max(m_uniformNameMaxLength, (Int)uniform.name.length()); m_uniformLocations[uniform.name] = location; + MGLOG_D("ProgramObject %u: Reflection - uniform[%d] name='%s' layoutLocation=%d", m_externalIndex, + i, uniform.name.c_str(), location); } + MGLOG_D("ProgramObject %u: Reflection - computed m_maxUniformLocation=%u m_uniformNameMaxLength=%d", + m_externalIndex, m_maxUniformLocation, m_uniformNameMaxLength); + if (m_maxUniformLocation + 1 < m_activeUniformCount) { + MGLOG_D("ProgramObject %u: Reflection - maxUniformLocation+1 (%u) < activeUniformCount (%d), " + "adjusting", + m_externalIndex, m_maxUniformLocation + 1, m_activeUniformCount); // This means we have fewer than enough gaps to fit // unallocated uniforms m_maxUniformLocation = m_activeUniformCount; } // i-th elements refers to uniform at layout(location = i, ...) - // Be aware, there could be gaps in between these vectors - // Locations can be not sequential m_uniformIndexInTProgram.resize(m_maxUniformLocation + 1, 4095); m_uniformSamplerOrImageUnitIndex.resize(m_maxUniformLocation + 1, -1); @@ -111,9 +181,13 @@ namespace MobileGL { auto location = uniform.layoutLocation(); if (m_uniformLocations[uniform.name] == 4095) { unallocatedUniformIndex.emplace_back(i); + MGLOG_D("ProgramObject %u: Reflection - uniform '%s' is unallocated, will assign later", + m_externalIndex, uniform.name.c_str()); continue; // will allocate unallocated uniforms later } m_uniformIndexInTProgram[location] = i; + MGLOG_D("ProgramObject %u: Reflection - assigned uniform '%s' to location %d (indexInTProgram=%d)", + m_externalIndex, uniform.name.c_str(), location, i); } SizeT locNeedle = 0; @@ -124,16 +198,24 @@ namespace MobileGL { // Found a vacant location at locNeedle m_uniformIndexInTProgram[locNeedle] = index; m_uniformLocations[uniform.name] = locNeedle; + MGLOG_D("ProgramObject %u: Reflection - assigned unallocated uniform '%s' to location %zu " + "(index %d)", + m_externalIndex, uniform.name.c_str(), locNeedle, index); + locNeedle++; break; } } int inCount = m_program->getNumPipeInputs(); + MGLOG_D("ProgramObject %u: Reflection - pipe input count (attributes) = %d", m_externalIndex, inCount); int maxLoc = -1; for (int i = 0; i < inCount; ++i) { int loc = m_program->getPipeInput(i).layoutLocation(); if (loc >= 0) maxLoc = std::max(maxLoc, loc); + MGLOG_D("ProgramObject %u: Reflection - pipe input[%d] name='%s' layoutLocation=%d glType=%u", + m_externalIndex, i, m_program->getPipeInput(i).name.c_str(), loc, + m_program->getPipeInput(i).glDefineType); } if (maxLoc < 0) { @@ -141,11 +223,13 @@ namespace MobileGL { } GLint maxAttribs = 16; // TODO: get from backend + MGLOG_D("ProgramObject %u: Reflection - computed maxLoc=%d, using maxAttribs=%d", m_externalIndex, + maxLoc, maxAttribs); if (maxLoc >= maxAttribs) { - MGLOG_W("ProgramObject::DoReflection - required attrib location %d >= GL_MAX_VERTEX_ATTRIBS (%d). " - "Clamping.", - maxLoc, maxAttribs); + MGLOG_W("ProgramObject %u: ProgramObject::DoReflection - required attrib location %d >= " + "GL_MAX_VERTEX_ATTRIBS (%d). Clamping.", + m_externalIndex, maxLoc, maxAttribs); maxLoc = maxAttribs - 1; } @@ -160,9 +244,12 @@ namespace MobileGL { if (location >= 0 && location < (int)m_attribs.size()) { m_attribs[location] = inVar.name; m_attribTypes[location] = inVar.glDefineType; + MGLOG_D("ProgramObject %u: Reflection - placed attrib '%s' at explicit location %d", + m_externalIndex, inVar.name.c_str(), location); } else if (location >= (int)m_attribs.size()) { - MGLOG_W("ProgramObject::DoReflection - attrib location %d >= attribs.size() (%zu). Ignoring.", - location, m_attribs.size()); + MGLOG_W("ProgramObject %u: ProgramObject::DoReflection - attrib location %d >= attribs.size() " + "(%zu). Ignoring.", + m_externalIndex, location, m_attribs.size()); continue; } else { bool placed = false; @@ -171,6 +258,8 @@ namespace MobileGL { m_attribs[idx] = inVar.name; m_attribTypes[idx] = inVar.glDefineType; placed = true; + MGLOG_D("ProgramObject %u: Reflection - placed attrib '%s' into free slot %zu", + m_externalIndex, inVar.name.c_str(), idx); break; } } @@ -178,44 +267,62 @@ namespace MobileGL { m_attribs.push_back(inVar.name); m_attribTypes.push_back(inVar.glDefineType); placed = true; + MGLOG_D("ProgramObject %u: Reflection - pushed attrib '%s' to new slot %zu", + m_externalIndex, inVar.name.c_str(), m_attribs.size() - 1); } if (!placed) { - MGLOG_W("ProgramObject::DoReflection - cannot place attrib '%s' (no free slot and at max " - "capacity). Ignoring.", - inVar.name.c_str()); + MGLOG_W("ProgramObject %u: ProgramObject::DoReflection - cannot place attrib '%s' (no free " + "slot and at max capacity). Ignoring.", + m_externalIndex, inVar.name.c_str()); } } } // Implement glBindAttribLocation semantics (explicit locations set by user) for (auto& [name, location] : m_explicitAttribLocations) { + MGLOG_D("ProgramObject %u: Reflection - explicit attrib location request: name='%s' location=%d", + m_externalIndex, name.c_str(), location); if (location < 0) continue; if (location >= (int)m_attribs.size()) { if (location >= maxAttribs) { - MGLOG_W("SetExplicitAttribLocation: requested location %d >= GL_MAX_VERTEX_ATTRIBS (%d). " - "Ignored for attribute '%s'.", - location, maxAttribs, name.c_str()); + MGLOG_W("ProgramObject %u: SetExplicitAttribLocation: requested location %d >= " + "GL_MAX_VERTEX_ATTRIBS (%d). Ignored for attribute '%s'.", + m_externalIndex, location, maxAttribs, name.c_str()); continue; } m_attribs.resize(location + 1); m_attribTypes.resize(location + 1); + MGLOG_D("ProgramObject %u: Reflection - resized attrib arrays to %zu to accommodate explicit " + "location %d", + m_externalIndex, m_attribs.size(), location); } if (m_attribs[location] != name) { auto it = std::find(m_attribs.begin(), m_attribs.end(), name); - if (it == m_attribs.end()) continue; + if (it == m_attribs.end()) { + MGLOG_D("ProgramObject %u: Reflection - explicit attrib '%s' not found in current list, " + "skipping swap", + m_externalIndex, name.c_str()); + continue; + } auto idx = std::distance(m_attribs.begin(), it); std::swap(m_attribs[location], m_attribs[idx]); std::swap(m_attribTypes[location], m_attribTypes[idx]); + MGLOG_D("ProgramObject %u: Reflection - swapped attrib '%s' from idx %zu to explicit " + "location %d", + m_externalIndex, name.c_str(), idx, location); } for (SizeT idx = 0; idx < m_attribs.size(); ++idx) { m_attribLocation[m_attribs[idx]] = idx; + MGLOG_D("ProgramObject %u: Reflection - attribLocation['%s'] = %zu", m_externalIndex, + m_attribs[idx].c_str(), idx); } } // ---------- UBO ---------- int uboCount = m_program->getNumUniformBlocks(); + MGLOG_D("ProgramObject %u: Reflection - uniform block count (UBO) = %d", m_externalIndex, uboCount); m_uniformBlockBinding.resize(uboCount, -1); for (int i = 0; i < uboCount; i++) { auto& ubo = m_program->getUniformBlock(i); @@ -224,6 +331,8 @@ namespace MobileGL { // if there's binding defined in shader as layout(binding = ...), // retrieve it here m_uniformBlockBinding[i] = ubo.getBinding(); + MGLOG_D("ProgramObject %u: Reflection - UBO[%d] name='%s' size=%u binding=%d", m_externalIndex, i, + ubo.name.c_str(), ubo.size, ubo.getBinding()); } } @@ -234,6 +343,7 @@ namespace MobileGL { * here without the burden of error reporting. */ using namespace MG_Util::ShaderTranspiler; + MGLOG_D("ProgramObject %u: GenerateBinary - start", m_externalIndex); Vector> shaders(m_shaders.size()); Vector shaderTypes(m_shaders.size()); for (SizeT i = 0; i < m_shaders.size(); i++) { @@ -241,32 +351,58 @@ namespace MobileGL { shaderTypes[i] = shaderType; ShaderAttrib attrib{ .shaderType = shaderType, .sourceStr = m_shaders[i]->GetShaderSource(), .flags = 0}; + MGLOG_D("ProgramObject %u: GenerateBinary - compiling shader[%zu] type %u", m_externalIndex, i, + shaderType); auto res = ShaderCompiler::CompileShader(attrib); - assert(res); + if (!res) { + MGLOG_E("ProgramObject %u: GenerateBinary - CompileShader failed for shader[%zu], aborting " + "binary generation", + m_externalIndex, i); + assert(res); // keep original assert but log first + } shaders[i] = res.value(); + MGLOG_D("ProgramObject %u: GenerateBinary - compiled shader[%zu] -> TShader ptr %p", + m_externalIndex, i, shaders[i].get()); } ProgramAttrib attrib{ .shaders = Move(shaders), }; + MGLOG_D("ProgramObject %u: GenerateBinary - linking program for binary", m_externalIndex); auto programResult = ShaderCompiler::LinkProgram(attrib); + if (!programResult) { + MGLOG_E("ProgramObject %u: GenerateBinary - LinkProgram failed during binary generation", + m_externalIndex); + } assert(programResult); auto program = programResult.value(); + MGLOG_D("ProgramObject %u: GenerateBinary - got linked program object", m_externalIndex); ProgramBinaryAttrib binaryAttrib{ .shaderTypes = shaderTypes, .program = *program, }; + MGLOG_D("ProgramObject %u: GenerateBinary - requesting SPIR-V binary from program", m_externalIndex); auto binaryResult = ShaderCompiler::GetSpirvBinaryFromProgram(binaryAttrib); + if (!binaryResult) { + MGLOG_E("ProgramObject %u: GenerateBinary - GetSpirvBinaryFromProgram failed", m_externalIndex); + } assert(binaryResult); m_generatedSpirv = Move(binaryResult.value()); + MGLOG_D("ProgramObject %u: GenerateBinary - generated %zu SPIR-V modules", m_externalIndex, + m_generatedSpirv.size()); for (SizeT i = 0; i < m_generatedSpirv.size(); i++) { auto& spv = m_generatedSpirv[i]; auto shaderType = shaderTypes[i]; + MGLOG_D("ProgramObject %u: GenerateBinary - parsing SPIR-V meta data for module %zu " + "(shaderType=%u, wordCount=%zu)", + m_externalIndex, i, shaderType, spv.size()); SpvcSession session(spv); auto result = session.ParseMetaData(); if (result < 0) { + MGLOG_E("ProgramObject %u: GenerateBinary - SpvcSession::ParseMetaData failed for module %zu", + m_externalIndex, i); continue; } // auto srcResult = ShaderCompiler::DecompileShader(session); @@ -276,28 +412,55 @@ namespace MobileGL { auto& meta = session.GetMetadata(); auto size = meta.uboSize; + MGLOG_D("ProgramObject %u: GenerateBinary - SPIR-V meta: uboSize=%zu plainUniformCount=%zu " + "plainUniformOffsets=%zu", + m_externalIndex, meta.uboSize, meta.plainUniformMemberSizesInBytes.size(), + meta.plainUniformOffsetsInUBO.size()); m_uboScratch.resize(size); m_uniformOffsets.resize(m_maxUniformLocation + 1); for (const auto& [name, offset] : meta.plainUniformOffsetsInUBO) { - if (m_uniformLocations.find(name) != m_uniformLocations.end()) + if (m_uniformLocations.find(name) != m_uniformLocations.end()) { m_uniformOffsets[m_uniformLocations[name]] = offset; + MGLOG_D("ProgramObject %u: GenerateBinary - uniform '%s' offset=%u assigned to location %u", + m_externalIndex, name.c_str(), offset, m_uniformLocations[name]); + } else { + MGLOG_D("ProgramObject %u: GenerateBinary - uniform '%s' offset=%u but not found in " + "m_uniformLocations", + m_externalIndex, name.c_str(), offset); + } } m_uniformSizesInBytes.resize(m_maxUniformLocation + 1); for (const auto& [name, size] : meta.plainUniformMemberSizesInBytes) { - if (m_uniformLocations.find(name) != m_uniformLocations.end()) + if (m_uniformLocations.find(name) != m_uniformLocations.end()) { m_uniformSizesInBytes[m_uniformLocations[name]] = size; + MGLOG_D("ProgramObject %u: GenerateBinary - uniform '%s' size=%u assigned to location %u", + m_externalIndex, name.c_str(), size, m_uniformLocations[name]); + } else { + MGLOG_D("ProgramObject %u: GenerateBinary - uniform '%s' size=%u but not found in " + "m_uniformLocations", + m_externalIndex, name.c_str(), size); + } } - // assert(m_uniformOffsets.size() == GetUniformCount()); - // assert(m_uniformSizesInBytes.size() == GetUniformCount()); + // Only parse first module that contains uniform metadata + MGLOG_D("ProgramObject %u: GenerateBinary - finished parsing module %zu; breaking after first " + "valid metadata", + m_externalIndex, i); break; } } - void ProgramObject::WaitUntilGenerationCompleted() {} + void ProgramObject::WaitUntilGenerationCompleted() { + MGLOG_D("ProgramObject %u: WaitUntilGenerationCompleted called (no-op)", m_externalIndex); + // currently no-op, but keep log for debugging + } void ProgramObject::SetExplicitAttribLocation(Uint index, const char* name) { + MGLOG_D("ProgramObject %u: SetExplicitAttribLocation called name='%s' index=%u", m_externalIndex, name, + index); m_explicitAttribLocations[name] = index; + MGLOG_D("ProgramObject %u: SetExplicitAttribLocation - stored explicit location for '%s' -> %u", + m_externalIndex, name, index); } } // namespace GLState } // namespace MG_State -} // namespace MobileGL \ No newline at end of file +} // namespace MobileGL diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h index e1291d34..ccbba86b 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h @@ -13,6 +13,7 @@ namespace MobileGL { bool ShaderIsAttached(SharedPtr shader); bool AttachShader(SharedPtr shader); SizeT DetachShader(SharedPtr shader); + SizeT RemoveShader(SharedPtr shader); void Link(); void MarkAsDeleted(); @@ -77,35 +78,27 @@ namespace MobileGL { Int GetActiveUniformBlocksMaxNameLength() const { return m_uniformBlockNameMaxLength; } Uint GetUniformBlockIndex(const char* name) const { auto it = m_uniformBlockIndexByName.find(name); - if (it != m_uniformBlockIndexByName.end()) - return it->second; + if (it != m_uniformBlockIndexByName.end()) return it->second; return 0xFFFFFFFFu; // GL_INVALID_INDEX } Bool IsActiveUniformBlock(Uint index) const { - if (index >= GetActiveUniformBlocksCount()) - return false; + if (index >= GetActiveUniformBlocksCount()) return false; return true; } Uint GetUBOSizeAt(Uint index) const { - if (!IsActiveUniformBlock(index)) - return 0; + if (!IsActiveUniformBlock(index)) return 0; return m_program->getUniformBlock(index).size; } - const String& GetUniformBlockName(Uint index) const { auto& ubo = m_program->getUniformBlock(index); return ubo.name; } // Set by glUniformBlockBinding - void SetUniformBlockBinding(Uint index, Uint binding) { - m_uniformBlockBinding[index] = binding; - } + void SetUniformBlockBinding(Uint index, Uint binding) { m_uniformBlockBinding[index] = binding; } - Uint GetUniformBlockBinding(Uint index) const { - return m_uniformBlockBinding[index]; - } + Uint GetUniformBlockBinding(Uint index) const { return m_uniformBlockBinding[index]; } Vector>& GetGeneratedSpirv() { return m_generatedSpirv; } @@ -120,6 +113,7 @@ namespace MobileGL { const Uint m_externalIndex = 0; Vector> m_shaders; + Vector> m_detachedShaders; // Store detached shaders and remove on next link SharedPtr m_program;