[Fix] (MG_Impl/GLImpl): validate compute program queries [skip ci]

This commit is contained in:
2026-07-02 19:04:23 +08:00
parent ac66ea7790
commit 2e14b44349
2 changed files with 45 additions and 5 deletions
@@ -453,12 +453,12 @@ namespace MobileGL::MG_Impl::GLImpl {
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
break;
case GL_COMPUTE_WORK_GROUP_SIZE: { // GL >= 4.3
if (!programObject->GetLinkStatus()) {
if (!programObject->GetLinkStatus() || programObject->GetShaderIndexByStage(ShaderStage::Compute) < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::to_string(program) +
" is not a program object that has been linked."));
" is not a linked program object with a compute shader."));
return;
}
params[0] = static_cast<GLint>(programObject->GetComputeLocalSize(0));
@@ -62,6 +62,40 @@ namespace {
return glType;
}
}
static bool ComputeShaderDeclaresLocalSize(const MobileGL::String& source) {
bool inLineComment = false;
bool inBlockComment = false;
for (MobileGL::SizeT i = 0; i < source.length(); ++i) {
if (inLineComment) {
inLineComment = source[i] != '\n';
continue;
}
if (inBlockComment) {
if (source[i] == '*' && i + 1 < source.length() && source[i + 1] == '/') {
inBlockComment = false;
++i;
}
continue;
}
if (source[i] == '/' && i + 1 < source.length()) {
if (source[i + 1] == '/') {
inLineComment = true;
++i;
continue;
}
if (source[i + 1] == '*') {
inBlockComment = true;
++i;
continue;
}
}
if (source.compare(i, 11, "local_size_") == 0) {
return true;
}
}
return false;
}
}
namespace MobileGL::MG_State::GLState {
@@ -170,9 +204,6 @@ namespace MobileGL::MG_State::GLState {
}
m_detachedShaders.clear();
Vector<GLenum> shaderTypes(m_shaders.size());
Vector<SharedPtr<glslang::TShader>> shaders(m_shaders.size());
if (addDefaultFSIfMissingForRenderingPipelineProgram) {
AddDefaultFragmentShaderIfMissing();
}
@@ -187,6 +218,9 @@ namespace MobileGL::MG_State::GLState {
return a->GetShaderStage() < b->GetShaderStage();
});
Vector<GLenum> shaderTypes(m_shaders.size());
Vector<SharedPtr<glslang::TShader>> shaders(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,
@@ -201,6 +235,12 @@ namespace MobileGL::MG_State::GLState {
m_externalIndex, i, m_infoLog.c_str());
return;
}
if (m_shaders[i]->GetShaderStage() == ShaderStage::Compute &&
!ComputeShaderDeclaresLocalSize(m_shaders[i]->GetShaderSource())) {
m_infoLog = "Compute shader is missing a local_size layout declaration.";
MGLOG_E("ProgramObject %u: Link failed - %s", m_externalIndex, m_infoLog.c_str());
return;
}
shaders[i] = m_shaders[i]->GetCompiledShader();
MGLOG_D("ProgramObject %u: shader[%zu] compiled shader ptr %p, src len %zu", m_externalIndex, i,
shaders[i].get(), m_shaders[i]->GetShaderSource().length());