diff --git a/.github/workflows/apk.yml b/.github/workflows/apk.yml index 43d49be8..a626d752 100644 --- a/.github/workflows/apk.yml +++ b/.github/workflows/apk.yml @@ -337,7 +337,7 @@ jobs: - name: Retrace and validate env: MOBILEGL_RETRACE_USE_ANGLE: ${{ matrix.backend.name == 'DirectGLES' && '1' || '0' }} - MOBILEGL_VULKAN_R11G11B10F_FALLBACK: ${{ matrix.backend.name == 'DirectVulkan' && '1' || '0' }} + MOBILEGL_MAGMA_R11G11B10F_FALLBACK: ${{ matrix.backend.name == 'DirectVulkan' && '1' || '0' }} run: | apk_file="$(find android-retrace-apks -name '${{ matrix.backend.apk }}' -print -quit)" extra_retrace_args=() diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 51cfb29f..0d330478 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -452,7 +452,7 @@ jobs: working-directory: build-retrace/tools/trace_replay run: | if [ '${{ matrix.backend }}' = 'DirectVulkan' ]; then - export MOBILEGL_VULKAN_R11G11B10F_FALLBACK=1 + export MOBILEGL_MAGMA_R11G11B10F_FALLBACK=1 fi ctest -V --no-tests=error -R '^MobileGLTraceReplay\.${{ matrix.case }}\.${{ matrix.backend }}$' diff --git a/MobileGL/Config.h b/MobileGL/Config.h index 55d4cf71..bd35da61 100644 --- a/MobileGL/Config.h +++ b/MobileGL/Config.h @@ -41,8 +41,10 @@ namespace MobileGL::MG_Config { String RetraceAngleDir; // MOBILEGL_DISABLE_SUBGROUP: force-disable Vulkan shader subgroup support. Bool DisableSubgroup = false; - // MOBILEGL_VULKAN_R11G11B10F_FALLBACK: use fallback format for R11G11B10F on Vulkan. + // MOBILEGL_MAGMA_R11G11B10F_FALLBACK: use fallback format for R11G11B10F on Vulkan. Bool VulkanR11G11B10FFallback = false; + // MOBILEGL_MAGMA_FRAMESINFLIGHT: requested Magma frames in flight, defaulting to 3. + Uint32 MagmaFramesInFlight = 3; // MOBILEGL_GLES_PRESENT_STATS: log present pixel statistics (DirectGLES backend). Bool GlesPresentStats = false; // MOBILEGL_ANGLE_LLVMPIPE_AVOID_SAMPLER_MIPMAP_MIN_FILTER: avoid mipmap min diff --git a/MobileGL/ConfigLoader.cpp b/MobileGL/ConfigLoader.cpp index 3b29fc79..84a5dfe5 100644 --- a/MobileGL/ConfigLoader.cpp +++ b/MobileGL/ConfigLoader.cpp @@ -8,6 +8,9 @@ #include "Config.h" +#include +#include + #ifndef _WIN32 extern char** environ; #endif @@ -83,13 +86,35 @@ namespace MobileGL::MG_ConfigLoader { return it != acceptedEnvVariablesMap->end() && IsTruthyValue(it->second); } + inline Uint32 QueryEnvUint32(const String& key, Uint32 defaultValue, Uint32 minValue, Uint32 maxValue) { + auto it = acceptedEnvVariablesMap->find(key); + if (it == acceptedEnvVariablesMap->end()) { + return defaultValue; + } + + const String& value = it->second; + char* parseEnd = nullptr; + errno = 0; + const unsigned long parsedValue = std::strtoul(value.c_str(), &parseEnd, 10); + if (parseEnd == value.c_str() || *parseEnd != '\0' || errno == ERANGE || parsedValue < minValue || + parsedValue > maxValue) { + MGLOG_W("Config: Ignoring invalid env variable %s='%s'; expected an integer in range [%u, %u], " + "using default %u", + key.c_str(), value.c_str(), minValue, maxValue, defaultValue); + return defaultValue; + } + + return static_cast(parsedValue); + } + inline void InitFeatures() { auto& features = MG_Config::Features; features.DisableTimerQuery = QueryEnvFlag("MOBILEGL_DISABLE_TIMERQUERY"); features.RetraceUseAngle = QueryEnvFlag("MOBILEGL_RETRACE_USE_ANGLE"); QueryEnvVariable("MOBILEGL_RETRACE_ANGLE_DIR", features.RetraceAngleDir, ""); features.DisableSubgroup = QueryEnvFlag("MOBILEGL_DISABLE_SUBGROUP"); - features.VulkanR11G11B10FFallback = QueryEnvFlag("MOBILEGL_VULKAN_R11G11B10F_FALLBACK"); + features.VulkanR11G11B10FFallback = QueryEnvFlag("MOBILEGL_MAGMA_R11G11B10F_FALLBACK"); + features.MagmaFramesInFlight = QueryEnvUint32("MOBILEGL_MAGMA_FRAMESINFLIGHT", 3, 1, 64); features.GlesPresentStats = QueryEnvFlag("MOBILEGL_GLES_PRESENT_STATS"); features.AvoidAngleLlvmpipeSamplerMipmapMinFilter = QueryEnvFlag("MOBILEGL_ANGLE_LLVMPIPE_AVOID_SAMPLER_MIPMAP_MIN_FILTER"); diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index 602c3de4..761956f0 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -1911,20 +1911,10 @@ void main() { // renderer init.) Existing logs already report the swapchain's min/actual image count; // this one adds the frames-in-flight decision itself. { - // Desired depth comes from the MOBILEGL_MAGMA_FRAMESINFLIGHT env var (so it can be - // tuned per device without a rebuild); if unset/invalid, fall back to the config value. - Uint32 requestedFramesInFlight = m_config.MaxFramesInFlight; - if (const char* framesEnv = std::getenv("MOBILEGL_MAGMA_FRAMESINFLIGHT")) { - char* parseEnd = nullptr; - const long parsedFrames = std::strtol(framesEnv, &parseEnd, 10); - if (parseEnd != framesEnv && *parseEnd == '\0' && parsedFrames >= 1 && parsedFrames <= 64) { - requestedFramesInFlight = static_cast(parsedFrames); - MGLOG_I("MaxFramesInFlight: MOBILEGL_MAGMA_FRAMESINFLIGHT=%ld requested", parsedFrames); - } else { - MGLOG_W("MaxFramesInFlight: ignoring invalid MOBILEGL_MAGMA_FRAMESINFLIGHT='%s'; " - "falling back to %u", framesEnv, requestedFramesInFlight); - } - } + // Desired depth comes from MOBILEGL_MAGMA_FRAMESINFLIGHT, parsed once by ConfigLoader + // with a default of 3 when the variable is unset or invalid. + Uint32 requestedFramesInFlight = MG_Config::Features.MagmaFramesInFlight; + MGLOG_I("MaxFramesInFlight: configured request=%u", requestedFramesInFlight); VkSurfaceCapabilitiesKHR surfaceCaps{}; const VkResult capsResult = vkGetPhysicalDeviceSurfaceCapabilitiesKHR( diff --git a/android-plugin/app/src/trace/cpp/trace_replay_core.cpp b/android-plugin/app/src/trace/cpp/trace_replay_core.cpp index 2dee477c..bb6df573 100644 --- a/android-plugin/app/src/trace/cpp/trace_replay_core.cpp +++ b/android-plugin/app/src/trace/cpp/trace_replay_core.cpp @@ -136,9 +136,9 @@ bool LoadMobileGL(const Request& request, std::string& error) { setenv("MOBILEGL_TRACE_SKIP_AUTODESTROY", "1", 1); setenv("MOBILEGL_TRACE_SURFACE", request.usePbuffer ? "pbuffer" : "window", 1); if (request.backend == "DirectVulkan") { - setenv("MOBILEGL_VULKAN_R11G11B10F_FALLBACK", "1", 1); + setenv("MOBILEGL_MAGMA_R11G11B10F_FALLBACK", "1", 1); } else { - unsetenv("MOBILEGL_VULKAN_R11G11B10F_FALLBACK"); + unsetenv("MOBILEGL_MAGMA_R11G11B10F_FALLBACK"); } if (UseAngleForRequest(request)) { setenv("MOBILEGL_RETRACE_USE_ANGLE", "1", 1); diff --git a/tools/trace_replay/run_macos_window_retrace_local.py b/tools/trace_replay/run_macos_window_retrace_local.py index bc7cc5a8..f5096ae8 100755 --- a/tools/trace_replay/run_macos_window_retrace_local.py +++ b/tools/trace_replay/run_macos_window_retrace_local.py @@ -363,7 +363,7 @@ def run_case(case, backend, replay_exe, mobilegl_library, vulkan_icd): ] env = os.environ.copy() env["MOBILEGL_BACKEND_TYPE"] = backend - env["MOBILEGL_VULKAN_R11G11B10F_FALLBACK"] = "1" + env["MOBILEGL_MAGMA_R11G11B10F_FALLBACK"] = "1" if vulkan_icd: env["VK_ICD_FILENAMES"] = vulkan_icd diff --git a/tools/trace_replay/skills/trace-fixture-authoring.md b/tools/trace_replay/skills/trace-fixture-authoring.md index 5c0f9db0..804869b0 100644 --- a/tools/trace_replay/skills/trace-fixture-authoring.md +++ b/tools/trace_replay/skills/trace-fixture-authoring.md @@ -376,7 +376,7 @@ or the install fails with `INSTALL_FAILED_UPDATE_INCOMPATIBLE`. Match the CI environment (`.github/workflows/apk.yml` matrix): the emulator boots with `--gpu software` + `MOBILEGL_RETRACE_USE_ANGLE=1` for `DirectGLES` -and `--gpu lavapipe` + `MOBILEGL_VULKAN_R11G11B10F_FALLBACK=1` for +and `--gpu lavapipe` + `MOBILEGL_MAGMA_R11G11B10F_FALLBACK=1` for `DirectVulkan`. The emulator's ANGLE-on-Vulkan GLES stack exercises genuinely different driver semantics than physical devices (e.g. indirect-draw `gl_InstanceID` handling), so treat AVD-only image mismatches as real signal,