mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Fix] (Retrace): load ANGLE through LD_LIBRARY_PATH
This commit is contained in:
@@ -336,7 +336,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrace and validate
|
- name: Retrace and validate
|
||||||
env:
|
env:
|
||||||
MOBILEGL_RETRACE_USE_ANGLE: ${{ matrix.backend.name == 'DirectGLES' && '1' || '0' }}
|
MOBILEGL_USE_ANGLE: ${{ matrix.backend.name == 'DirectGLES' && '1' || '0' }}
|
||||||
MOBILEGL_MAGMA_R11G11B10F_FALLBACK: ${{ matrix.backend.name == 'DirectVulkan' && '1' || '0' }}
|
MOBILEGL_MAGMA_R11G11B10F_FALLBACK: ${{ matrix.backend.name == 'DirectVulkan' && '1' || '0' }}
|
||||||
run: |
|
run: |
|
||||||
apk_file="$(find android-retrace-apks -name '${{ matrix.backend.apk }}' -print -quit)"
|
apk_file="$(find android-retrace-apks -name '${{ matrix.backend.apk }}' -print -quit)"
|
||||||
|
|||||||
+2
-4
@@ -35,10 +35,8 @@ namespace MobileGL::MG_Config {
|
|||||||
struct FeaturesTable {
|
struct FeaturesTable {
|
||||||
// MOBILEGL_DISABLE_TIMERQUERY: do not advertise or use GPU timer queries.
|
// MOBILEGL_DISABLE_TIMERQUERY: do not advertise or use GPU timer queries.
|
||||||
Bool DisableTimerQuery = false;
|
Bool DisableTimerQuery = false;
|
||||||
// MOBILEGL_RETRACE_USE_ANGLE: load ANGLE EGL/GLES libraries for retrace runs.
|
// MOBILEGL_USE_ANGLE: load ANGLE EGL/GLES libraries.
|
||||||
Bool RetraceUseAngle = false;
|
Bool UseAngle = false;
|
||||||
// MOBILEGL_RETRACE_ANGLE_DIR: directory searched first for the ANGLE libraries.
|
|
||||||
String RetraceAngleDir;
|
|
||||||
// MOBILEGL_DISABLE_SUBGROUP: force-disable Vulkan shader subgroup support.
|
// MOBILEGL_DISABLE_SUBGROUP: force-disable Vulkan shader subgroup support.
|
||||||
Bool DisableSubgroup = false;
|
Bool DisableSubgroup = false;
|
||||||
// MOBILEGL_MAGMA_R11G11B10F_FALLBACK: use fallback format for R11G11B10F on Vulkan.
|
// MOBILEGL_MAGMA_R11G11B10F_FALLBACK: use fallback format for R11G11B10F on Vulkan.
|
||||||
|
|||||||
@@ -110,8 +110,7 @@ namespace MobileGL::MG_ConfigLoader {
|
|||||||
inline void InitFeatures() {
|
inline void InitFeatures() {
|
||||||
auto& features = MG_Config::Features;
|
auto& features = MG_Config::Features;
|
||||||
features.DisableTimerQuery = QueryEnvFlag("MOBILEGL_DISABLE_TIMERQUERY");
|
features.DisableTimerQuery = QueryEnvFlag("MOBILEGL_DISABLE_TIMERQUERY");
|
||||||
features.RetraceUseAngle = QueryEnvFlag("MOBILEGL_RETRACE_USE_ANGLE");
|
features.UseAngle = QueryEnvFlag("MOBILEGL_USE_ANGLE");
|
||||||
QueryEnvVariable("MOBILEGL_RETRACE_ANGLE_DIR", features.RetraceAngleDir, "");
|
|
||||||
features.DisableSubgroup = QueryEnvFlag("MOBILEGL_DISABLE_SUBGROUP");
|
features.DisableSubgroup = QueryEnvFlag("MOBILEGL_DISABLE_SUBGROUP");
|
||||||
features.MagmaR11G11B10FFallback = QueryEnvFlag("MOBILEGL_MAGMA_R11G11B10F_FALLBACK");
|
features.MagmaR11G11B10FFallback = QueryEnvFlag("MOBILEGL_MAGMA_R11G11B10F_FALLBACK");
|
||||||
features.MagmaFramesInFlight = QueryEnvUint32("MOBILEGL_MAGMA_FRAMESINFLIGHT", 3, 1, 64);
|
features.MagmaFramesInFlight = QueryEnvUint32("MOBILEGL_MAGMA_FRAMESINFLIGHT", 3, 1, 64);
|
||||||
|
|||||||
@@ -14,21 +14,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace MobileGL::MG_Util::BackendLoader {
|
namespace MobileGL::MG_Util::BackendLoader {
|
||||||
static Bool UseRetraceAngle() {
|
static Bool UseAngle() {
|
||||||
return MG_Config::Features.RetraceUseAngle;
|
return MG_Config::Features.UseAngle;
|
||||||
}
|
|
||||||
|
|
||||||
static Vector<String> AngleLibNames(const char* name) {
|
|
||||||
const String& angleDir = MG_Config::Features.RetraceAngleDir;
|
|
||||||
if (!angleDir.empty()) {
|
|
||||||
String path = angleDir;
|
|
||||||
if (path.back() != '/') {
|
|
||||||
path += "/";
|
|
||||||
}
|
|
||||||
path += name;
|
|
||||||
return {path, name};
|
|
||||||
}
|
|
||||||
return {name};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* OpenLib(const Vector<String>& names) {
|
static void* OpenLib(const Vector<String>& names) {
|
||||||
@@ -40,7 +27,7 @@ namespace MobileGL::MG_Util::BackendLoader {
|
|||||||
"/opt/vc/lib/", "/usr/local/lib/", "/usr/lib/", "/usr/lib/x86_64-linux-gnu/",
|
"/opt/vc/lib/", "/usr/local/lib/", "/usr/lib/", "/usr/lib/x86_64-linux-gnu/",
|
||||||
"/usr/lib64/", "/lib64/",
|
"/usr/lib64/", "/lib64/",
|
||||||
#endif
|
#endif
|
||||||
"" // We should put this to the end of the list to avoid breaking `LD_LIBRARY_PATH` usage
|
"" // Keep this last so the dynamic loader can use LD_LIBRARY_PATH.
|
||||||
};
|
};
|
||||||
|
|
||||||
void* lib = nullptr;
|
void* lib = nullptr;
|
||||||
@@ -473,13 +460,13 @@ namespace MobileGL::MG_Util::BackendLoader {
|
|||||||
|
|
||||||
void AcquireEGLFunctions(MG_External::EGLFunctionsTable& funcs) {
|
void AcquireEGLFunctions(MG_External::EGLFunctionsTable& funcs) {
|
||||||
void* eglLib = nullptr;
|
void* eglLib = nullptr;
|
||||||
if (UseRetraceAngle()) {
|
if (UseAngle()) {
|
||||||
void* glesLib = OpenLib(AngleLibNames("libGLESv2_angle.so"));
|
void* glesLib = OpenLib({"libGLESv2_angle.so"});
|
||||||
if (!glesLib) {
|
if (!glesLib) {
|
||||||
MGLOG_E("Failed to open ANGLE libGLESv2_angle.so");
|
MGLOG_E("Failed to open ANGLE libGLESv2_angle.so");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
eglLib = OpenLib(AngleLibNames("libEGL_angle.so"));
|
eglLib = OpenLib({"libEGL_angle.so"});
|
||||||
if (!eglLib) {
|
if (!eglLib) {
|
||||||
MGLOG_E("Failed to open ANGLE libEGL_angle.so");
|
MGLOG_E("Failed to open ANGLE libEGL_angle.so");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ Implementation notes:
|
|||||||
- `DirectGLES` and `DirectVulkan` replay on the Activity `SurfaceView` by default. DirectGLES can still use the old offscreen EGL pbuffer path by passing `use_pbuffer=true`.
|
- `DirectGLES` and `DirectVulkan` replay on the Activity `SurfaceView` by default. DirectGLES can still use the old offscreen EGL pbuffer path by passing `use_pbuffer=true`.
|
||||||
- Golden comparison is implemented in native C++ with libpng RGBA decode and SSIM validation. The Java Activity only passes arguments and displays the native result, so the replay/compare core is not tied to Android UI or Bitmap APIs and can be ported to Linux.
|
- Golden comparison is implemented in native C++ with libpng RGBA decode and SSIM validation. The Java Activity only passes arguments and displays the native result, so the replay/compare core is not tied to Android UI or Bitmap APIs and can be ported to Linux.
|
||||||
- The plugin profile still excludes `libtrace_replay_runner.so`; normal plugin APK behavior is preserved.
|
- The plugin profile still excludes `libtrace_replay_runner.so`; normal plugin APK behavior is preserved.
|
||||||
- Set `MOBILEGL_RETRACE_USE_ANGLE=1` when running `trace-replay-ci.sh` to pass `use_angle=true` for DirectGLES. Set `MOBILEGL_RETRACE_USE_PBUFFER=1` or pass `--use-pbuffer` to keep DirectGLES offscreen. The APK must include `libEGL_angle.so` and `libGLESv2_angle.so` under its x86_64 native libraries. The Activity passes Android's `nativeLibraryDir` to native code as `MOBILEGL_RETRACE_ANGLE_DIR`.
|
- Set `MOBILEGL_USE_ANGLE=1` when running `trace-replay-ci.sh` to pass `use_angle=true` for DirectGLES. Set `MOBILEGL_RETRACE_USE_PBUFFER=1` or pass `--use-pbuffer` to keep DirectGLES offscreen. The APK must include `libEGL_angle.so` and `libGLESv2_angle.so` under its x86_64 native libraries. The native runner prepends the ANGLE directory to `LD_LIBRARY_PATH` before loading MobileGL.
|
||||||
|
|
||||||
Example core-profile trace smoke command for a debug trace APK:
|
Example core-profile trace smoke command for a debug trace APK:
|
||||||
|
|
||||||
|
|||||||
@@ -88,10 +88,24 @@ bool UseAngleForRequest(const Request& request) {
|
|||||||
if (request.useAngle) {
|
if (request.useAngle) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const char* value = getenv("MOBILEGL_RETRACE_USE_ANGLE");
|
const char* value = getenv("MOBILEGL_USE_ANGLE");
|
||||||
return value != nullptr && strcmp(value, "1") == 0;
|
return value != nullptr && strcmp(value, "1") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrependLibraryPath(const std::string& directory) {
|
||||||
|
if (directory.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* current = getenv("LD_LIBRARY_PATH");
|
||||||
|
std::string value = directory;
|
||||||
|
if (current != nullptr && current[0] != '\0') {
|
||||||
|
value += ":";
|
||||||
|
value += current;
|
||||||
|
}
|
||||||
|
setenv("LD_LIBRARY_PATH", value.c_str(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
bool EnsureDirectory(const std::string& path) {
|
bool EnsureDirectory(const std::string& path) {
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -141,13 +155,12 @@ bool LoadMobileGL(const Request& request, std::string& error) {
|
|||||||
unsetenv("MOBILEGL_MAGMA_R11G11B10F_FALLBACK");
|
unsetenv("MOBILEGL_MAGMA_R11G11B10F_FALLBACK");
|
||||||
}
|
}
|
||||||
if (UseAngleForRequest(request)) {
|
if (UseAngleForRequest(request)) {
|
||||||
setenv("MOBILEGL_RETRACE_USE_ANGLE", "1", 1);
|
setenv("MOBILEGL_USE_ANGLE", "1", 1);
|
||||||
if (!request.angleLibraryDir.empty()) {
|
if (!request.angleLibraryDir.empty()) {
|
||||||
setenv("MOBILEGL_RETRACE_ANGLE_DIR", request.angleLibraryDir.c_str(), 1);
|
PrependLibraryPath(request.angleLibraryDir);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unsetenv("MOBILEGL_RETRACE_USE_ANGLE");
|
unsetenv("MOBILEGL_USE_ANGLE");
|
||||||
unsetenv("MOBILEGL_RETRACE_ANGLE_DIR");
|
|
||||||
}
|
}
|
||||||
if (request.avoidAngleLlvmpipeSamplerMipmapMinFilter) {
|
if (request.avoidAngleLlvmpipeSamplerMipmapMinFilter) {
|
||||||
setenv("MOBILEGL_AVOID_SAMPLER_MIPMAP_MIN_FILTER", "1", 1);
|
setenv("MOBILEGL_AVOID_SAMPLER_MIPMAP_MIN_FILTER", "1", 1);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Usage:
|
|||||||
[--avoid-angle-llvmpipe-sampler-mipmap-min-filter] \
|
[--avoid-angle-llvmpipe-sampler-mipmap-min-filter] \
|
||||||
--timeout-seconds N
|
--timeout-seconds N
|
||||||
|
|
||||||
Set MOBILEGL_RETRACE_USE_ANGLE=1 to run DirectGLES replay with packaged ANGLE
|
Set MOBILEGL_USE_ANGLE=1 to run DirectGLES replay with packaged ANGLE
|
||||||
instead of the device system GLES driver.
|
instead of the device system GLES driver.
|
||||||
Set MOBILEGL_RETRACE_USE_PBUFFER=1 or pass --use-pbuffer to run DirectGLES
|
Set MOBILEGL_RETRACE_USE_PBUFFER=1 or pass --use-pbuffer to run DirectGLES
|
||||||
against an offscreen EGL pbuffer instead of the Activity surface.
|
against an offscreen EGL pbuffer instead of the Activity surface.
|
||||||
@@ -245,7 +245,7 @@ run_retrace() {
|
|||||||
if [ -n "${alternate_golden_path}" ]; then
|
if [ -n "${alternate_golden_path}" ]; then
|
||||||
alternate_golden_app_path="${app_dir}/input/alternate-golden.png"
|
alternate_golden_app_path="${app_dir}/input/alternate-golden.png"
|
||||||
fi
|
fi
|
||||||
if [ "${MOBILEGL_RETRACE_USE_ANGLE:-}" = "1" ] && [ "${backend}" = "DirectGLES" ]; then
|
if [ "${MOBILEGL_USE_ANGLE:-}" = "1" ] && [ "${backend}" = "DirectGLES" ]; then
|
||||||
use_angle=1
|
use_angle=1
|
||||||
fi
|
fi
|
||||||
if [ "${MOBILEGL_RETRACE_USE_PBUFFER:-}" = "1" ] && [ "${backend}" = "DirectGLES" ]; then
|
if [ "${MOBILEGL_RETRACE_USE_PBUFFER:-}" = "1" ] && [ "${backend}" = "DirectGLES" ]; then
|
||||||
|
|||||||
@@ -172,9 +172,9 @@ def run_case(case, backend):
|
|||||||
env["PYTHON"] = "python"
|
env["PYTHON"] = "python"
|
||||||
env["MSYS2_ARG_CONV_EXCL"] = "/data/*"
|
env["MSYS2_ARG_CONV_EXCL"] = "/data/*"
|
||||||
if backend_info["use_angle"]:
|
if backend_info["use_angle"]:
|
||||||
env["MOBILEGL_RETRACE_USE_ANGLE"] = "1"
|
env["MOBILEGL_USE_ANGLE"] = "1"
|
||||||
else:
|
else:
|
||||||
env.pop("MOBILEGL_RETRACE_USE_ANGLE", None)
|
env.pop("MOBILEGL_USE_ANGLE", None)
|
||||||
result = subprocess.run(command, cwd=ROOT, env=env)
|
result = subprocess.run(command, cwd=ROOT, env=env)
|
||||||
copy_goldens(case, backend)
|
copy_goldens(case, backend)
|
||||||
return result.returncode
|
return result.returncode
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ device or emulator has a trace package from a different keystore, uninstall
|
|||||||
or the install fails with `INSTALL_FAILED_UPDATE_INCOMPATIBLE`.
|
or the install fails with `INSTALL_FAILED_UPDATE_INCOMPATIBLE`.
|
||||||
|
|
||||||
Match the CI environment (`.github/workflows/apk.yml` matrix): the emulator
|
Match the CI environment (`.github/workflows/apk.yml` matrix): the emulator
|
||||||
boots with `--gpu software` + `MOBILEGL_RETRACE_USE_ANGLE=1` for `DirectGLES`
|
boots with `--gpu software` + `MOBILEGL_USE_ANGLE=1` for `DirectGLES`
|
||||||
and `--gpu lavapipe` + `MOBILEGL_MAGMA_R11G11B10F_FALLBACK=1` for
|
and `--gpu lavapipe` + `MOBILEGL_MAGMA_R11G11B10F_FALLBACK=1` for
|
||||||
`DirectVulkan`. The emulator's ANGLE-on-Vulkan GLES stack exercises genuinely
|
`DirectVulkan`. The emulator's ANGLE-on-Vulkan GLES stack exercises genuinely
|
||||||
different driver semantics than physical devices (e.g. indirect-draw
|
different driver semantics than physical devices (e.g. indirect-draw
|
||||||
|
|||||||
Reference in New Issue
Block a user