mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Feat] (MG_Impl, MG_Backend): GL_ARB_timer_query on both backends
Implements GL timer queries end to end: a frontend query registry (modeled on the sync module - mutex-guarded objects wrapping opaque backend handles behind optional function pointers) serving glGenQueries/glBeginQuery/glEndQuery(GL_TIME_ELAPSED)/glQueryCounter (GL_TIMESTAMP)/glGetQueryObject*/glGetQueryiv with GL 3.3 error semantics and a graceful zero-result fallback when a backend cannot time. DirectGLES backs spans with GL_EXT_disjoint_timer_query (context- generation-stamped handles, bounded result waits). DirectVulkan gets a VkTimerQueryManager: per-frame-in-flight timestamp query pools reset at command-buffer begin (outside render passes), records harvested by frame serial before their pool recycles, elapsed = masked tick delta x timestampPeriod; handles are stamped with a renderer generation that also now guards fence syncs across renderer recreation. GL_QUERY_ COUNTER_BITS reports 0 unless the live backend can actually time (dynamic IsTimerQuerySupported hook), and a failed blocking read keeps the handle alive so the real value stays reachable once the frame submits. GL_ARB_timer_query is advertised only when the device supports timing and MOBILEGL_DISABLE_TIMERQUERY is unset - LWJGL keys Minecraft's F3 'GPU: x%' line off exactly that extension string; verified on device (Adreno 830) on both backends. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,21 +8,21 @@
|
||||
|
||||
#include "Loader.h"
|
||||
#include "MG_Util/Types.h"
|
||||
#include <Config.h>
|
||||
#if defined(MOBILEGL_IOS)
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
namespace MobileGL::MG_Util::BackendLoader {
|
||||
static Bool UseRetraceAngle() {
|
||||
const char* value = std::getenv("MOBILEGL_RETRACE_USE_ANGLE");
|
||||
return value != nullptr && std::strcmp(value, "1") == 0;
|
||||
return MG_Config::Features.RetraceUseAngle;
|
||||
}
|
||||
|
||||
static Vector<String> AngleLibNames(const char* name) {
|
||||
const char* angleDir = std::getenv("MOBILEGL_RETRACE_ANGLE_DIR");
|
||||
if (angleDir != nullptr && angleDir[0] != '\0') {
|
||||
const String& angleDir = MG_Config::Features.RetraceAngleDir;
|
||||
if (!angleDir.empty()) {
|
||||
String path = angleDir;
|
||||
if (!path.empty() && path.back() != '/') {
|
||||
if (path.back() != '/') {
|
||||
path += "/";
|
||||
}
|
||||
path += name;
|
||||
@@ -450,6 +450,8 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
INIT_GLES_FUNC(glBufferStorageEXT)
|
||||
INIT_GLES_FUNC(glGetQueryObjectivEXT)
|
||||
INIT_GLES_FUNC(glGetQueryObjecti64vEXT)
|
||||
INIT_GLES_FUNC(glQueryCounterEXT)
|
||||
INIT_GLES_FUNC(glGetQueryObjectui64vEXT)
|
||||
INIT_GLES_FUNC(glBindFragDataLocationEXT)
|
||||
INIT_GLES_FUNC(glMapBufferOES)
|
||||
INIT_GLES_FUNC(glMultiDrawArraysIndirectEXT)
|
||||
@@ -726,6 +728,9 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
if (std::strcmp(extension, "GL_EXT_base_instance") == 0) {
|
||||
caps.SupportsBaseInstance = true;
|
||||
}
|
||||
if (std::strcmp(extension, "GL_EXT_disjoint_timer_query") == 0) {
|
||||
caps.SupportsDisjointTimerQuery = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -911,6 +916,18 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
MGLOG_I(" Indirect draw gl_InstanceID includes baseInstance: %s",
|
||||
caps.IndirectDrawInstanceIdIncludesBaseInstance ? "true" : "false");
|
||||
|
||||
caps.IsAngleRenderer = caps.GLESRendererString.find("ANGLE") != String::npos;
|
||||
caps.IsAngleLlvmpipeRenderer =
|
||||
caps.IsAngleRenderer && caps.GLESRendererString.find("llvmpipe") != String::npos;
|
||||
caps.AvoidSamplerMipmapMinFilter =
|
||||
caps.IsAngleLlvmpipeRenderer && MG_Config::Features.AvoidAngleLlvmpipeSamplerMipmapMinFilter;
|
||||
MGLOG_I(" GL_EXT_disjoint_timer_query supported: %s",
|
||||
caps.SupportsDisjointTimerQuery ? "true" : "false");
|
||||
MGLOG_I(" ANGLE renderer: %s", caps.IsAngleRenderer ? "true" : "false");
|
||||
MGLOG_I(" ANGLE llvmpipe renderer: %s", caps.IsAngleLlvmpipeRenderer ? "true" : "false");
|
||||
MGLOG_I(" Avoid sampler mipmap min filter: %s",
|
||||
caps.AvoidSamplerMipmapMinFilter ? "true" : "false");
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace MobileGL::MG_Util::BackendLoader
|
||||
|
||||
@@ -611,6 +611,8 @@ namespace MobileGL {
|
||||
GLbitfield flags)
|
||||
GL_FUNC_TYPEDEF(void, glGetQueryObjectivEXT, GLuint id, GLenum pname, GLint* params)
|
||||
GL_FUNC_TYPEDEF(void, glGetQueryObjecti64vEXT, GLuint id, GLenum pname, GLint64* params)
|
||||
GL_FUNC_TYPEDEF(void, glQueryCounterEXT, GLuint id, GLenum target)
|
||||
GL_FUNC_TYPEDEF(void, glGetQueryObjectui64vEXT, GLuint id, GLenum pname, GLuint64* params)
|
||||
GL_FUNC_TYPEDEF(void, glBindFragDataLocationEXT, GLuint program, GLuint colorNumber, const GLchar* name)
|
||||
GL_FUNC_TYPEDEF(void*, glMapBufferOES, GLenum target, GLenum access)
|
||||
|
||||
@@ -1000,6 +1002,8 @@ namespace MobileGL {
|
||||
GL_FUNC_DECL(glBufferStorageEXT)
|
||||
GL_FUNC_DECL(glGetQueryObjectivEXT)
|
||||
GL_FUNC_DECL(glGetQueryObjecti64vEXT)
|
||||
GL_FUNC_DECL(glQueryCounterEXT)
|
||||
GL_FUNC_DECL(glGetQueryObjectui64vEXT)
|
||||
GL_FUNC_DECL(glBindFragDataLocationEXT)
|
||||
GL_FUNC_DECL(glMapBufferOES)
|
||||
|
||||
@@ -1019,6 +1023,16 @@ namespace MobileGL {
|
||||
Bool SupportsPersistentMapping = false;
|
||||
Bool SupportsNorm16Texture = false;
|
||||
Bool SupportsBaseInstance = false;
|
||||
// GL_EXT_disjoint_timer_query is present in the extension string.
|
||||
Bool SupportsDisjointTimerQuery = false;
|
||||
// GL_RENDERER contains "ANGLE".
|
||||
Bool IsAngleRenderer = false;
|
||||
// GL_RENDERER contains both "ANGLE" and "llvmpipe".
|
||||
Bool IsAngleLlvmpipeRenderer = false;
|
||||
// IsAngleLlvmpipeRenderer combined with the
|
||||
// MOBILEGL_ANGLE_LLVMPIPE_AVOID_SAMPLER_MIPMAP_MIN_FILTER feature toggle:
|
||||
// sampler min filters should drop their mipmap component.
|
||||
Bool AvoidSamplerMipmapMinFilter = false;
|
||||
// True when indirect draws leak the command's baseInstance word ("reserved,
|
||||
// must be zero" in unextended ES) into gl_InstanceID. Conforming ES drivers
|
||||
// keep gl_InstanceID zero-based; ANGLE's Vulkan backend hands the command
|
||||
|
||||
Reference in New Issue
Block a user