mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Docs] (.github/workflows, MG_Backend/DirectGLES, MG_Backend/DirectVulkan, MG_Benchmark/Driver, MG_Impl/EGLImpl, MG_Impl/Pipe, MG_IntegrationTest, MG_IntegrationTest/Harness, MG_IntegrationTest/Scenarios, MG_Pipe, MG_State/GLState, MG_Test, MG_Test/Pipe, MG_Test/Program, MG_Test/SelfTest, MG_Test/ShaderTranspiler, MG_Test/Swapchain, MG_Test/Wire, MG_Util/Async, MG_Util/BackendLoaders, MG_Util/SelfTest, MG_Util/ShaderTranspiler, MobileGL, scripts/ci, tools/spikes, tools/trace_replay): name drivers and techniques instead of external projects
This commit is contained in:
@@ -452,7 +452,7 @@ jobs:
|
||||
# Second, filtered pass: with the range-invalidating map flush disabled,
|
||||
# the buffer scenarios run on the upload ring's staged-copy tier - which
|
||||
# the default pass never reaches (the map tier absorbs every flush on
|
||||
# Mesa), so without this the Mali fallback tier would have zero CI
|
||||
# the CI drivers), so without this the Mali fallback tier would have zero CI
|
||||
# coverage. The flag is NOT baked into the ctest ENVIRONMENT properties,
|
||||
# so an inline env reaches the test processes (unlike the ICD pin above).
|
||||
if [ "${{ secrets.ACTIONS_STEP_DEBUG }}" = "true" ]; then
|
||||
|
||||
+2
-2
@@ -283,7 +283,7 @@ namespace MobileGL::MG_Config {
|
||||
Bool DisableLargeBufferAdoption = false;
|
||||
// MOBILEGL_ESPRYT_FORCE_DS_READBACK_EMULATION: make DirectGLES skip the native ES
|
||||
// depth/stencil reads and always go through the shader-sampling emulation. Core GL
|
||||
// ES has no depth or stencil readback, but some drivers accept it anyway (Mesa does,
|
||||
// ES has no depth or stencil readback, but some drivers accept it anyway (llvmpipe does,
|
||||
// Adreno does not), which means the emulation is dead code on exactly the stack the
|
||||
// headless suite runs on. This forces it live so the scenarios and the CTS can
|
||||
// exercise the path, and gives the device an A/B lever over the same choice.
|
||||
@@ -378,7 +378,7 @@ namespace MobileGL::MG_Config {
|
||||
// MOBILEGL_MAGMA_PRIMGEN_QUERY_REROUTE: DirectVulkan's GL_PRIMITIVES_GENERATED
|
||||
// reroute for draws made while transform feedback is INACTIVE. The stream query
|
||||
// (VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT primitivesNeeded) is defined to count
|
||||
// them, but a Mali driver - and Mesa lavapipe - answers 0 unless a capture span is
|
||||
// them, but a Mali driver - and lavapipe - answers 0 unless a capture span is
|
||||
// open, which is exactly the shape the CTS uses to measure the tessellator, so ~29
|
||||
// tessellation tests per tree size a capture buffer from the 0 and die on the
|
||||
// zero-length map. Auto defers to a device probe at renderer bring-up
|
||||
|
||||
@@ -10153,7 +10153,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// was never anything but the frontend's way of naming the texture, and the record
|
||||
// names it now.
|
||||
backendTexture->Bind(backendTarget, TextureImpl::TempTextureUnit);
|
||||
// ANGLE/Mesa may validate the currently bound FBO while generating mipmaps, so the
|
||||
// ANGLE and some other drivers may validate the currently bound FBO while generating mipmaps, so the
|
||||
// source texture is detached from every framebuffer that attaches it - by handle,
|
||||
// over the applier's own framebuffer records.
|
||||
ScopedDetachedTextureFramebufferAttachments detachedAttachments(mipRes);
|
||||
@@ -10726,7 +10726,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// all. GL_DEPTH_COMPONENT, GL_STENCIL_INDEX and GL_DEPTH_STENCIL are simply not
|
||||
// accepted formats there, and the optional extensions that add them (GL_NV_read_depth,
|
||||
// GL_NV_read_stencil, GL_NV_read_depth_stencil) are absent on both the Adreno device
|
||||
// and Mesa's ES. Every native attempt therefore failed with a GL error and wrote
|
||||
// and llvmpipe's ES. Every native attempt therefore failed with a GL error and wrote
|
||||
// NOTHING, so the caller kept whatever its buffer already held - which is how the CTS
|
||||
// reports "expected DEPTH[0.25] but got DEPTH[0.2]": 0.2 is the poison value the test
|
||||
// itself put there.
|
||||
|
||||
@@ -837,7 +837,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// case). Written only under the mutex; read lock-free.
|
||||
std::atomic<Bool> g_hasDeferredBufferReleases{false};
|
||||
|
||||
// --- Buffer-storage pool (Mesa-style BO recycle) -------------------------
|
||||
// --- Buffer-storage pool (buffer-object recycling) -----------------------
|
||||
// Recycle idle GL buffer ids of an EXACT byte size instead of glDeleteBuffers
|
||||
// (which triggers the kgsl_sharedmem_free -> mmu_unmap -> smmu/power/bandwidth
|
||||
// cascade that dominated per-frame driver cost). An id retired during frame N
|
||||
@@ -11962,7 +11962,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
//
|
||||
// A driver that HAS GL_NV_image_formats still needs part of this. SPIRV-Cross throws
|
||||
// for its is_desktop_only_format set when it targets ESSL rather than printing a
|
||||
// token, and the throw loses the stage however willing the driver was - Mesa
|
||||
// token, and the throw loses the stage however willing the driver was - llvmpipe
|
||||
// advertises the extension and `layout(r8ui) uimage2D` lost its whole program there
|
||||
// until the widening ran for it too. So the driver bit decides HOW MUCH is widened,
|
||||
// never WHETHER.
|
||||
@@ -11996,7 +11996,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// reaches SPIRV-Cross intact and comes out as ESSL a strict driver rejects
|
||||
// outright ("array indexes for fragment outputs must be constant integral
|
||||
// expressions"), linking no program and silently no-oping every draw that
|
||||
// uses it. Mesa accepts it, ANGLE does not - which is the whole of the
|
||||
// uses it. llvmpipe accepts it, ANGLE does not - which is the whole of the
|
||||
// improved-transparency-minecraft-26.3 failure. Fold or lower the index here,
|
||||
// on the ESSL path only: the same module is legal for DirectVulkan.
|
||||
Vector<unsigned int> outputIndexSpirv;
|
||||
@@ -12012,7 +12012,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// dynamically-uniform expression, GLSL ES keeps the ES 3.1
|
||||
// constant-expression rule for both, and the drivers enforce it - Qualcomm
|
||||
// ("indexing into an SSBO array using a non-constant expression is not
|
||||
// permitted"), Mesa ("image arrays indexed with non-constant expressions are
|
||||
// permitted"), llvmpipe ("image arrays indexed with non-constant expressions are
|
||||
// forbidden in GLSL ES") - losing the stage, the program, and every draw or
|
||||
// dispatch that used it, while the frontend keeps reporting the link glslang
|
||||
// performed. Fold or lower the index here, on the ESSL path only: the same
|
||||
@@ -12158,7 +12158,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
// `readonly writeonly` together says the buffer variable can only be asked its
|
||||
// .length(), which the frontend has already enforced - so the pair is inert, and
|
||||
// printing it is not. Mesa's ES compiler refuses a block spelled that way and the
|
||||
// printing it is not. llvmpipe's ES compiler refuses a block spelled that way and the
|
||||
// stage never reaches the program.
|
||||
spvcSession.RelaxReadWriteExclusiveStorageBuffers();
|
||||
|
||||
@@ -13327,8 +13327,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// installs the new executable - but only "for all shader stages where the program
|
||||
// is active", and a stage the previous link did not produce is not active for
|
||||
// anything. So a relink that ADDS a stage is precisely the case the promise does
|
||||
// not cover. Verified with no MobileGL in the process (bare EGL + GLES 3.2, Mesa
|
||||
// 26.1.4 llvmpipe): vertex+fragment linked, used and drawn renders; a geometry
|
||||
// not cover. Verified with no MobileGL in the process (bare EGL + GLES 3.2,
|
||||
// llvmpipe 26.1.4): vertex+fragment linked, used and drawn renders; a geometry
|
||||
// shader attached and relinked reports LINK_STATUS true with an empty info log,
|
||||
// and the next draw renders NOTHING and raises no error - while the same draw
|
||||
// after a fresh glUseProgram of the same name renders again.
|
||||
|
||||
@@ -3273,7 +3273,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// P4a (D-F2/D-F3): the SIXTH Espryt twin table, and the only one of the six whose kind
|
||||
// has no frontend object at all. MobileGL has no sampler-view class: GL binds a texture
|
||||
// to a unit and the sampler uniform's type, the mipmap-completeness predicates and
|
||||
// IsUndefinedDefaultTexture decide what the shader sees. Gallium's one-view-per-slot IS
|
||||
// IsUndefinedDefaultTexture decide what the shader sees. Binding one sampler view per slot IS
|
||||
// that resolved form, the resolution moves to the CLIENT (ARCHITECTURE.md §5.5), and
|
||||
// create_sampler_view carries the restrictions the resolution had to read.
|
||||
//
|
||||
|
||||
@@ -390,7 +390,7 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl {
|
||||
// driver entries it saves. mc_sodium_multidraw (132 batches x 32 sub-draws),
|
||||
// ns/op, median of three:
|
||||
//
|
||||
// NVIDIA ES 3.2 Mesa llvmpipe ES 3.2
|
||||
// NVIDIA ES 3.2 llvmpipe ES 3.2
|
||||
// ext n/a 19300
|
||||
// basevertex 2500 25200
|
||||
// multiindirect 5700 27600
|
||||
|
||||
@@ -191,7 +191,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// behind the native probe), so a driver that does render to a three-channel image keeps
|
||||
// allocating it byte for byte.
|
||||
//
|
||||
// Do NOT read that as "nothing changes off-device". Measured on Mesa 26.1.6 llvmpipe
|
||||
// Do NOT read that as "nothing changes off-device". Measured on llvmpipe 26.1.6
|
||||
// (the headless CI driver), an ES 3.2 GL_TEXTURE_2D colour attachment is COMPLETE for
|
||||
// GL_RGB8 and GL_RGB16F but INCOMPLETE_ATTACHMENT for GL_RGB8_SNORM, GL_SRGB8 and every
|
||||
// RGB integer format, and UNSUPPORTED for GL_RGB32F. Those eight formats therefore DO
|
||||
@@ -328,7 +328,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// A driver WITH GL_NV_image_formats can spell the narrow format - but only for the
|
||||
// formats SPIRV-Cross will actually print. It throws for its is_desktop_only_format
|
||||
// set instead of emitting a token, and the throw loses the stage whatever the driver
|
||||
// would have accepted: on Mesa, which advertises the extension, `layout(r8ui)
|
||||
// would have accepted: on llvmpipe, which advertises the extension, `layout(r8ui)
|
||||
// uimage2D` still lost its whole program until the widening ran for it too.
|
||||
if (g_GLESCapabilities.SupportsExtendedImageFormats &&
|
||||
MG_Util::ShaderTranspiler::ShaderCompiler::SpirvCrossCanPrintEsslImageFormat(requested)) {
|
||||
@@ -1787,7 +1787,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// KHR-GL43.shading_language_420pack.binding_images_texture_type_* went from 6
|
||||
// image uniforms to 30 and the link failed outright with "Error: Image Image
|
||||
// location or component exceeds max allowed." on an Adreno 830, where Mali and
|
||||
// Mesa both accept the same text.
|
||||
// llvmpipe both accept the same text.
|
||||
//
|
||||
// Nothing downstream reads these names: the two passes that key on the GL uniform
|
||||
// name (RebindImageUniformsToFrontendUnits, BakeImageFormatQualifiers) both run
|
||||
|
||||
@@ -352,7 +352,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// That rewrite needs every k in the emitted text to be a LITERAL, and it is:
|
||||
// LegalizeResourceArrayIndexingForEssl has already folded or lowered every dynamic
|
||||
// image-array subscript in the module, because ESSL forbids one outright ("image arrays
|
||||
// indexed with non-constant expressions are forbidden in GLSL ES", Mesa 26.1.4 at
|
||||
// indexed with non-constant expressions are forbidden in GLSL ES", llvmpipe 26.1.4 at
|
||||
// ES 3.2, on a raw GLES probe with no MobileGL in the loop). The earlier shape here -
|
||||
// widening the array to cover the whole span of units and routing each subscript through
|
||||
// a `const highp int` offset table - was written before that pass covered images, and
|
||||
@@ -510,7 +510,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// linker answered "Error: Image Image location or component exceeds max allowed. Error:
|
||||
// Linking failed." - which, the frontend having already published LINK_STATUS = TRUE from
|
||||
// glslang's link, surfaced only as every draw silently doing nothing and the images
|
||||
// reading back zero. Mali and Mesa link the same text, so nothing but a device gate
|
||||
// reading back zero. Mali and a desktop GLES driver link the same text, so nothing but a device gate
|
||||
// catches this.
|
||||
//
|
||||
// A declaration SPIRV-Cross already tagged `readonly` or `writeonly` needs no qualifier
|
||||
|
||||
@@ -1531,7 +1531,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
case 0x1010u: // Imagination
|
||||
m_dynamicParameters.GpuVendor = GpuVendorKind::ImgTec;
|
||||
break;
|
||||
case 0x10005u: // Mesa software (lavapipe)
|
||||
case 0x10005u: // software (lavapipe)
|
||||
case 0x1AE0u: // Google (SwiftShader)
|
||||
m_dynamicParameters.GpuVendor = GpuVendorKind::Software;
|
||||
break;
|
||||
|
||||
@@ -1350,7 +1350,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Uint32 m_xfbQueryOpenSlot = 0;
|
||||
// GL_PRIMITIVES_GENERATED reroute for draws made while transform feedback is
|
||||
// INACTIVE. The stream pool's primitivesNeeded is defined to count those draws
|
||||
// too, but a Mali driver (and Mesa lavapipe) answers 0 unless a capture span
|
||||
// too, but a Mali driver (and lavapipe) answers 0 unless a capture span
|
||||
// is open (the CTS's tessellator-measuring shape). Where the bring-up probe
|
||||
// finds that defect with a working control - or
|
||||
// MOBILEGL_MAGMA_PRIMGEN_QUERY_REROUTE forces it - such draws accumulate the
|
||||
|
||||
@@ -1047,7 +1047,7 @@
|
||||
// otherwise - so `glBlitFramebuffer(0, h, w, 0, 0, 0, w, h, COLOR|DEPTH)` out of a
|
||||
// multisample framebuffer blitted its COLOUR correctly (the colour arm has handled a
|
||||
// flip since P5f and now handles a scale too) and then died on its DEPTH. GL 4.6 core
|
||||
// 18.3.1 asks for identical DIMENSIONS, not identical corners - Mesa compares absolute
|
||||
// 18.3.1 asks for identical DIMENSIONS, not identical corners - a conforming check compares absolute
|
||||
// spans - so a flip is a legal blit that has to produce a mirrored picture.
|
||||
//
|
||||
// Spans are therefore signed and everything downstream works off the min corner.
|
||||
|
||||
@@ -336,7 +336,7 @@ static int boot_egl(void) {
|
||||
/* The default display first: it is the one a windowed app would get, and
|
||||
* on a desktop it is the one that reaches the real GPU - which is the
|
||||
* driver this bench exists to measure. It does need a window system,
|
||||
* though; Mesa's default platform is X11, so with no $DISPLAY (CI, a
|
||||
* though; desktop EGL usually defaults to the X11 platform, so with no $DISPLAY (CI, a
|
||||
* build server, ssh without forwarding) eglInitialize fails. Fall back to
|
||||
* EGL_MESA_platform_surfaceless rather than give up: every case draws into
|
||||
* the FBO built by build_resources(), so no window is needed for any of
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# Pin the vendor libraries explicitly. A bare libEGL.so.1 on a glvnd system
|
||||
# picks whatever vendor eglGetDisplay(EGL_DEFAULT_DISPLAY) resolves first,
|
||||
# which is Mesa/llvmpipe here - a software rasteriser silently replacing the
|
||||
# which is llvmpipe here - a software rasteriser silently replacing the
|
||||
# GPU under a benchmark. Override MGL_EGL_VENDOR / MGL_VK_ICD to test another
|
||||
# driver.
|
||||
set -eu
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace MobileGL::MG_Impl::EGLImpl::Wayland {
|
||||
inline constexpr EGLenum kPlatformWayland = 0x31D8;
|
||||
|
||||
// Whether a display is a Wayland one: asked for as EGL_PLATFORM_WAYLAND, or (eglGetDisplay with
|
||||
// no platform) a native display that is a wl_display - recognised the way Mesa does, by its
|
||||
// no platform) a native display that is a wl_display - recognised the way EGL loaders usually do, by its
|
||||
// first word being libwayland-client's wl_display_interface (or, for an application with its
|
||||
// own copy of libwayland, an interface named "wl_display").
|
||||
Bool IsWaylandDisplay(Uint64 nativeDisplay, EGLenum platform);
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// before reusing the handle. ARCHITECTURE.md 4.1 says content addressing on an
|
||||
// xxHash; a bare 64-bit equality would let a collision alias two different render
|
||||
// states onto one CSO, which is silent wrong pixels with no gate that can see it.
|
||||
// Mesa's cso_cache memcmps for the same reason. The memcmp only ever runs on a
|
||||
// pipeline-version change, i.e. never in the steady state.
|
||||
// Hashed constant-state caches confirm a hit with a full-key memcmp for the same reason.
|
||||
// The memcmp only ever runs on a pipeline-version change, i.e. never in the steady state.
|
||||
// 3. miss -> mint a slot, emit create_render_state with every pipeline chunk, then bind.
|
||||
//
|
||||
// CAPACITY 64 (ROADMAP.md P2). 64 x (8 + 8 + 396 + 8) = about 26 KB per context. ROADMAP.md
|
||||
|
||||
@@ -617,7 +617,7 @@ namespace MobileGL::MG_Pipe {
|
||||
// ---------------------------------------------------------------------------------
|
||||
//
|
||||
// GL binds one texture per unit PER TARGET; which one the shader actually samples depends
|
||||
// on the sampler uniform's TYPE. Gallium's one-view-per-slot is the resolved form, so the
|
||||
// on the sampler uniform's TYPE. One sampler view per slot is the resolved form, so the
|
||||
// resolution moves to the client and the record carries the answer rather than the inputs.
|
||||
//
|
||||
// This is DirectGLES' SamplerUniformTextureTarget, moved to the side of the boundary that
|
||||
|
||||
@@ -241,7 +241,7 @@ endif()
|
||||
|
||||
# --- ctest wiring --------------------------------------------------------
|
||||
# A bare libEGL on a glvnd box resolves to whatever vendor comes first, which is
|
||||
# usually Mesa/llvmpipe - a software rasteriser silently replacing the GPU under
|
||||
# usually llvmpipe - a software rasteriser silently replacing the GPU under
|
||||
# a GPU test. Pin the vendor/ICD json the same way MG_Benchmark's
|
||||
# run_driver_bench.sh does.
|
||||
#
|
||||
@@ -316,7 +316,7 @@ else()
|
||||
message(WARNING
|
||||
"Integration tests: no EGL vendor json found or configured (MOBILEGL_ITEST_EGL_VENDOR is empty). "
|
||||
"An unpinned libEGL on a glvnd system resolves to whichever vendor comes first, which is usually "
|
||||
"Mesa/llvmpipe - the scenarios would then go green against a software rasteriser instead of the GPU. "
|
||||
"llvmpipe - the scenarios would then go green against a software rasteriser instead of the GPU. "
|
||||
"Set -DMOBILEGL_ITEST_EGL_VENDOR=/usr/share/glvnd/egl_vendor.d/<vendor>.json.")
|
||||
endif()
|
||||
if (MOBILEGL_ITEST_VK_ICD)
|
||||
@@ -905,7 +905,7 @@ gtest_discover_tests(MobileGLIntegrationTest
|
||||
# A fourth registration, of the depth/stencil readback scenarios, with the ES
|
||||
# shader-sampling emulation forced on. Not paranoia - without it these scenarios are
|
||||
# UNFALSIFIABLE on the machines this suite runs on: OpenGL ES has no depth or stencil
|
||||
# readback in core, but Mesa accepts the reads anyway, so on llvmpipe every one of them
|
||||
# readback in core, but llvmpipe accepts the reads anyway, so every one of them
|
||||
# goes green through a native path that the Adreno device does not have. Deleting the
|
||||
# entire emulation left all of them passing. With the flag the native spellings are off
|
||||
# the table and only the path the device actually takes remains. DirectGLES only - the
|
||||
@@ -2680,7 +2680,7 @@ if (MOBILEGL_BUILD_DISAGGREGATED)
|
||||
#
|
||||
# Without it this scenario is UNFALSIFIABLE on the machines this suite runs on, and the
|
||||
# ambient DirectGLES.ForcedDepthStencilEmulation. lane says why: OpenGL ES has no depth or
|
||||
# stencil readback in core, but Mesa accepts the reads anyway, so on llvmpipe every case goes
|
||||
# stencil readback in core, but llvmpipe accepts the reads anyway, so every case goes
|
||||
# green through a native path the Adreno device does not have - deleting the whole emulation
|
||||
# left all of them passing. A split arm that inherited the ambient default would be measuring
|
||||
# the same non-path three more times. So the pin is MIRRORED here, which is what the plan's
|
||||
|
||||
@@ -167,10 +167,10 @@ namespace MGITest {
|
||||
// not a CI accommodation - it is what keeps a developer's run and a CI run
|
||||
// the same run. The lane was wired up green on a workstation and immediately
|
||||
// died on the runner precisely because the workstation had a DISPLAY (WSLg)
|
||||
// and took Mesa's x11 platform, while the runner has none; that divergence
|
||||
// and took the x11 EGL platform, while the runner has none; that divergence
|
||||
// is the bug, and pinning the platform here is the fix for it.
|
||||
//
|
||||
// Mesa selects its EGL platform from EGL_PLATFORM at loader time, so this
|
||||
// The desktop EGL library selects its platform from EGL_PLATFORM at loader time, so this
|
||||
// has to run before the first EGL call in the process (see EnsureHeadless
|
||||
// callers). surfaceless is the platform with no window-system dependency at
|
||||
// all; the surface this file then creates is still a pbuffer, which every
|
||||
|
||||
@@ -180,7 +180,7 @@ void main() { fragColor = vec4(0.0, 1.0, 0.0, 1.0); }
|
||||
// forwarded at all.
|
||||
// - Vulkan has no such state: every clip distance a shader declares is active,
|
||||
// always. DirectVulkan therefore clips by a disabled distance.
|
||||
// - Mesa's llvmpipe ES driver behaves like Vulkan here.
|
||||
// - llvmpipe's ES driver behaves like Vulkan here.
|
||||
//
|
||||
// Emulating GL's semantics on those two would mean forcing the disabled slots to a
|
||||
// non-negative value inside the shader, which makes the enable mask part of the
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
//
|
||||
// On DirectGLES none of this exists natively - ES has no depth or stencil readback in
|
||||
// core - so every assertion here is really an assertion about the shader-sampling
|
||||
// emulation. The catch is that some ES drivers accept the reads anyway (Mesa does,
|
||||
// emulation. The catch is that some ES drivers accept the reads anyway (llvmpipe does,
|
||||
// Adreno does not), which would make the emulation dead code on the very stack the
|
||||
// headless suite runs on. That is what the second ctest registration is for: the same
|
||||
// scenarios run again with MOBILEGL_ESPRYT_FORCE_DS_READBACK_EMULATION=1, which takes the
|
||||
@@ -516,7 +516,7 @@ namespace MGITest {
|
||||
// P7 wave 2-B2 (review round): A MULTISAMPLE DEPTH RESOLVE THAT FLIPS, AND ONE THAT SCALES.
|
||||
//
|
||||
// GL 4.6 core 18.3.1 asks a multisample blit for identical rectangle DIMENSIONS, not for
|
||||
// identical corners - Mesa compares absolute spans - so `glBlitFramebuffer(0, h, w, 0, ...)`
|
||||
// identical corners - a conforming check compares absolute spans - so `glBlitFramebuffer(0, h, w, 0, ...)`
|
||||
// out of a multisample framebuffer is legal and owes a mirrored picture, while a blit whose
|
||||
// sizes differ is INVALID_OPERATION and owes nothing. The wire arm used to end the SESSION
|
||||
// on both: `Magma:multisample-depth-resolve-region` covered the reversed rectangle and the
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace MGITest {
|
||||
protected:
|
||||
// Both backends now answer these reads. DirectGLES has no native ES path for
|
||||
// either aspect (GL_NV_read_depth / GL_NV_read_stencil are optional and absent on
|
||||
// both the Adreno device and Mesa's ES), so it stages the attachment into a
|
||||
// both the Adreno device and llvmpipe's ES), so it stages the attachment into a
|
||||
// scratch depth texture and samples it into a colour target; the assertions below
|
||||
// are the same either way, which is the point.
|
||||
bool BackendReadsDepthStencil() const { return true; }
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// capability absent - src0, written straight through
|
||||
//
|
||||
// What each CI lane actually reaches: lavapipe has dualSrcBlend, so the DirectVulkan lane runs the
|
||||
// whole sequence and measures the blend. Mesa's GLES front end on llvmpipe has no
|
||||
// whole sequence and measures the blend. The GLES front end on llvmpipe has no
|
||||
// GL_EXT_blend_func_extended, so the ESSL stage carrying `layout(index = 1)` never compiles and the
|
||||
// program renders nothing - the DirectGLES lane therefore SKIPS on the capability probe in SetUp
|
||||
// rather than measuring a picture the driver never produced. The DECLINE arm itself - the path this
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// KHR-GL43.stencil_texturing.functional is where it surfaced: its compute half writes through a
|
||||
// format-less `uimage2D` bound to an R8UI texture, and returned zeros for every texel.
|
||||
//
|
||||
// DISCRIMINATING ONLY WHERE THE DRIVER ADVERTISES GL_NV_image_formats - Mesa does, which is what
|
||||
// DISCRIMINATING ONLY WHERE THE DRIVER ADVERTISES GL_NV_image_formats - llvmpipe does, which is what
|
||||
// the software lanes run and where this was found. On Adreno 830 and both Malis the extension is
|
||||
// absent, the old code already armed the widening, and these cases pass before and after; they
|
||||
// are kept running there as a guard against the opposite mistake.
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
// ProgramUtilTest, LoopDerivedFragmentOutputIndexFoldsToConstantIndices and its
|
||||
// genuinely-dynamic sibling) prove the SPIR-V comes out with constant indices, validates, and
|
||||
// decompiles to ESSL with only literal indices. What they cannot prove is that a real driver
|
||||
// then ACCEPTS and RUNS it - and acceptance is the whole failure mode, because Mesa accepts the
|
||||
// then ACCEPTS and RUNS it - and acceptance is the whole failure mode, because the desktop CI drivers accept the
|
||||
// illegal form too. Only a live glCompileShader/glLinkProgram followed by a draw can tell the two
|
||||
// apart, and only reading the pixels back can tell "linked" from "wrote the right attachment".
|
||||
//
|
||||
|
||||
@@ -211,7 +211,7 @@ void main()
|
||||
// r32ui program for the rgba32ui texture, and the second half would come back seeded.
|
||||
//
|
||||
// What the SOFTWARE lanes cannot falsify: with the key disabled this case still passes on
|
||||
// Mesa, because the reused r32ui declaration writes the red channel of an RGBA32UI image
|
||||
// llvmpipe, because the reused r32ui declaration writes the red channel of an RGBA32UI image
|
||||
// anyway - a format-class mismatch GL leaves undefined and that driver happens to absorb.
|
||||
// FirstBindAfterLinkRebuilds below is the case that fails there, because the reused
|
||||
// program was built with no format at all and never compiled. Both are kept: this one is
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
// EVERY CASE HERE IS PHRASED IN THOSE GL RULES AND NOTHING ELSE, which is what makes it a
|
||||
// falsifiable net rather than a restatement of the implementation. Magma needs none of the
|
||||
// machinery (Vulkan takes the declared format natively), a driver that DOES advertise
|
||||
// GL_NV_image_formats - Mesa's, which is what the software lanes run - keeps the narrow format and
|
||||
// GL_NV_image_formats - llvmpipe, which is what the software lanes run - keeps the narrow format and
|
||||
// widens nothing, and all of them must produce the same numbers. A widening that forgot to mask a
|
||||
// store, or masked it with the wrong constants, or widened the storage without widening the bind,
|
||||
// fails these on the device while the software lanes stay green.
|
||||
@@ -1003,7 +1003,7 @@ void main()
|
||||
// 3 were written past the end of the application's buffer.
|
||||
//
|
||||
// This runs on every backend, and on a driver that CAN spell rg32f for an imageBuffer
|
||||
// (Mesa's, which the software lanes use) nothing is split at all - which is the other half
|
||||
// (llvmpipe, which the software lanes use) nothing is split at all - which is the other half
|
||||
// of the claim: the arming has to agree with the shader, so a split that fired where the
|
||||
// driver needed none would double every subscript and fail here just as loudly.
|
||||
TEST_F(NonCoreImageFormatScenario, BufferImageAddressesTheApplicationsOwnTexels) {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
//
|
||||
// Every case uploads a level, lets the GPU clear it, writes one 2x2 box, and reads the level back:
|
||||
// the clear outside the box, the write inside. The formats are picked by what they cost the ES
|
||||
// upload, which is per driver - on Mesa llvmpipe GL_SRGB8, GL_RGB8_SNORM and GL_RGB8UI are stored
|
||||
// upload, which is per driver - on llvmpipe GL_SRGB8, GL_RGB8_SNORM and GL_RGB8UI are stored
|
||||
// four-channel (see ThreeChannelAttachmentScenario) while GL_RGB16F is native; ES has no renderable
|
||||
// three-channel format at all, so on a phone all four are converted. GL_RGBA8 is the control that
|
||||
// never converts. A format a backend cannot attach is skipped, not failed.
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//
|
||||
// DirectVulkan serves the query from the transform-feedback stream query's
|
||||
// primitivesNeeded, which VK_EXT_transform_feedback defines to count whether or
|
||||
// not a capture span is open. Both the Mali-G1-Ultra driver AND Mesa lavapipe
|
||||
// not a capture span is open. Both the Mali-G1-Ultra driver AND lavapipe
|
||||
// disagree with that definition: with no vkCmdBeginTransformFeedbackEXT recorded,
|
||||
// the pair reads back 0. Where the bring-up probe measures that defect with a
|
||||
// working control - or MOBILEGL_MAGMA_PRIMGEN_QUERY_REROUTE=1 pins it on - the
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// until the program stops being current, so GL_CURRENT_PROGRAM still names it. GuiBatchScenario
|
||||
// then replays AcceleratedRendering's save / switch / restore: it reads GL_CURRENT_PROGRAM, makes
|
||||
// its compute program current - which is what finally deletes the old one - and restores the
|
||||
// saved name, which no longer exists. GL_INVALID_VALUE, from MobileGL and from native Mesa alike:
|
||||
// saved name, which no longer exists. GL_INVALID_VALUE, from MobileGL and from a native driver alike:
|
||||
// the implementation is right and the fixture's "clean slate" was not.
|
||||
//
|
||||
// The two cases below run in declaration order in ONE process (the
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
// worse outcome, so the round trip below is pinned tightly enough to fail on a half-float substitute
|
||||
// (tolerance two SNORM steps, half-float error six).
|
||||
//
|
||||
// WHAT THIS GATE CAN AND CANNOT SEE. Both CI drivers (Mesa llvmpipe) and Adreno expose
|
||||
// WHAT THIS GATE CAN AND CANNOT SEE. Both CI drivers (llvmpipe) and Adreno expose
|
||||
// GL_EXT_render_snorm, so they take the NATIVE path here and the substitution stays dead. That is
|
||||
// precisely why the assertions are written as invariants of the format rather than of the fallback:
|
||||
// "a signed-normalized colour attachment is complete and round-trips its channel values" has to
|
||||
|
||||
@@ -69,7 +69,7 @@ void main() {
|
||||
// GL 4.6 core 4.10 lets a buffer variable be declared readonly AND writeonly at once:
|
||||
// it can then be neither read nor written, and `.length()` is the only thing left that
|
||||
// may be asked of it. The pair is inert - and printing it into ESSL is not, because
|
||||
// SPIRV-Cross hoists the qualifiers every member shares onto the BLOCK and Mesa's ES
|
||||
// SPIRV-Cross hoists the qualifiers every member shares onto the BLOCK and llvmpipe's ES
|
||||
// compiler refuses that spelling ("Interface block sets both readonly and writeonly").
|
||||
// Lifted from KHR-GL43.shader_storage_buffer_object.basic-readonly-writeonly.
|
||||
constexpr const char* kReadonlyWriteonlyComputeSource = R"(#version 430 core
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// actually PRODUCES that caveat. Only a live glCheckFramebufferStatus can, and the answer is
|
||||
// per-driver, not per-platform:
|
||||
//
|
||||
// Mesa llvmpipe (the headless CI driver), ES 3.2, GL_TEXTURE_2D colour attachment:
|
||||
// llvmpipe (the headless CI driver), ES 3.2, GL_TEXTURE_2D colour attachment:
|
||||
// COMPLETE GL_RGB8, GL_RGB16F, GL_R11F_G11F_B10F, every RGBA*
|
||||
// INCOMPLETE_ATTACHMENT GL_RGB8_SNORM, GL_SRGB8, every RGB integer format
|
||||
// UNSUPPORTED GL_RGB32F
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#
|
||||
# Pin the vendor libraries explicitly, for the same reason
|
||||
# MG_Benchmark/Driver/run_driver_bench.sh does: a bare libEGL on a glvnd system
|
||||
# resolves to whatever vendor comes first, which is usually Mesa/llvmpipe - a
|
||||
# resolves to whatever vendor comes first, which is usually llvmpipe - a
|
||||
# software rasteriser silently replacing the GPU under a GPU test. Override
|
||||
# MGL_EGL_VENDOR / MGL_VK_ICD to test another driver.
|
||||
#
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// The MGPipe boundary (plan B section 4).
|
||||
//
|
||||
// The two interface tables are FUNCTION-POINTER STRUCTS, not virtual bases. Three reasons
|
||||
// out of this repository rather than out of gallium: the boundary already is a
|
||||
// out of this repository rather than out of other driver interfaces: the boundary already is a
|
||||
// function-pointer struct sitting on one hook point in MG_Backend/Init.cpp; a nullptr entry
|
||||
// already means "not implemented, frontend falls back", which is exactly what a
|
||||
// not-yet-migrated subsystem needs to say while it keeps pulling; and MG_Test already
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
// The backend -> frontend reverse channel, named (plan B section 7.1).
|
||||
//
|
||||
// Today this traffic is 95 call sites across 17 methods poked directly into frontend
|
||||
// objects. gallium has no vocabulary for shadow writeback, GPU-write notification or
|
||||
// default-framebuffer geometry, because in Mesa the state tracker and the driver share an
|
||||
// objects. An in-process driver interface has no vocabulary for shadow writeback, GPU-write notification or
|
||||
// default-framebuffer geometry, because in such a design the state tracker and the driver share an
|
||||
// address space. Naming them as callbacks is the deliberate deviation (D8).
|
||||
//
|
||||
// SEVEN, NOT THE TEN PLAN B WROTE. Three went, each because nothing produces it.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
//
|
||||
// A handle is a {slot, gen} pair minted by the CLIENT and never by the server: no create_*
|
||||
// call in the catalogue returns a server-cast handle, which is the deliberate deviation
|
||||
// from gallium (D1) that lets the whole catalogue be remoted with ZERO creation round
|
||||
// from driver-minted handles (D1) that lets the whole catalogue be remoted with ZERO creation round
|
||||
// trips.
|
||||
//
|
||||
// Slots are dense and allocated PER KIND, so the server's object table is an array rather
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
virtual ~BackendBufferResource() = default;
|
||||
};
|
||||
|
||||
// Mesa pipe_resource analogue for a GL buffer's storage. It owns the buffer's
|
||||
// The storage resource behind a GL buffer object. It owns the buffer's
|
||||
// bytes and its backend GPU resource, and abstracts WHERE the authoritative
|
||||
// bytes live so no caller has to branch on the mode:
|
||||
//
|
||||
|
||||
@@ -954,7 +954,7 @@ namespace {
|
||||
|
||||
// ARCHITECTURE's third merge rule: the client emits the PROGRAM-RESOLVED set. A unit the
|
||||
// shader does not sample carries no view, whatever is bound to it - which is exactly the
|
||||
// gallium one-view-per-slot resolved form, and exactly what DirectGLES arrives at by
|
||||
// one-view-per-slot resolved form, and exactly what DirectGLES arrives at by
|
||||
// asking the program which of a unit's aliased bindings is the sampled one.
|
||||
TEST(SamplerEmit, OnlyTheProgramResolvedUnitsAreEmitted) {
|
||||
EmitterScope scope;
|
||||
|
||||
@@ -3010,7 +3010,7 @@ void main() {
|
||||
// (GLSL ES 3.00 4.3.6). SPIRV-Cross carries the dynamic index straight into the ESSL, a strict
|
||||
// driver rejects the shader, the program links nothing, and every draw using it silently draws
|
||||
// nothing - which is what empties the translucent layer of improved-transparency-minecraft-26.3
|
||||
// on the Android DirectGLES (ANGLE) lane while Mesa, being lenient, renders it correctly.
|
||||
// on the Android DirectGLES (ANGLE) lane while llvmpipe, being lenient, renders it correctly.
|
||||
namespace {
|
||||
Vector<Uint32> CompileFragmentToRawSpirv(const String& source) {
|
||||
using namespace MG_Util::ShaderTranspiler;
|
||||
|
||||
@@ -4051,7 +4051,7 @@ TEST(DirectGLESSlotTable, EverySwitchedOverKindResolvesItsTwinThroughTheHandleAr
|
||||
// P4a: the EIGHTH table and the SIXTH kind - the sampler view, which is the only kind in
|
||||
// the phase with no frontend object at all. MobileGL has no sampler-view class: GL binds a
|
||||
// texture to a unit and the sampler uniform's type plus the two completeness predicates
|
||||
// decide what the shader sees, gallium's one-view-per-slot IS that resolved form, and the
|
||||
// decide what the shader sees, a one-view-per-slot model IS that resolved form, and the
|
||||
// resolution moves to the CLIENT (D-F3). So this table is handle-keyed only, like the
|
||||
// buffer resource table above, and its twin owns no driver id whatsoever - what it holds is
|
||||
// the server's memo of one resolved view plus the raw-depth-fetch substitution decision,
|
||||
|
||||
@@ -971,7 +971,7 @@ TEST(DriverBugProbes, ImageCoherencyResidualIsDetectedAndQuantified) {
|
||||
ExpectProbeReleasedEverything();
|
||||
}
|
||||
|
||||
// The reason the subject is the STRONGEST shape and not the one MobileGL emits. Mesa llvmpipe
|
||||
// The reason the subject is the STRONGEST shape and not the one MobileGL emits. llvmpipe
|
||||
// misses every texel with `coherent` + memoryBarrierImage() and none once the pair is also
|
||||
// `volatile` - a defect MobileGL could fix by emitting a different shape, which is not what
|
||||
// UNFIXABLE means and does not belong in this section.
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// characterised is written down here as a fake measurement so the mapping cannot
|
||||
// drift without a red:
|
||||
// - a conforming driver (stream counts everywhere),
|
||||
// - Mesa lavapipe as measured 2026-08: stream silent everywhere, the dedicated
|
||||
// - lavapipe as measured 2026-08: stream silent everywhere, the dedicated
|
||||
// VK_EXT_primitives_generated_query exact everywhere (discard included), and
|
||||
// the statistics control exact on the plain shape but dead under rasterizer
|
||||
// discard (llvmpipe's discard short-circuit),
|
||||
@@ -113,7 +113,7 @@ TEST(PrimitivesGeneratedNoXfbVerdictTest, HealthNeedsNeitherTessellationNorACont
|
||||
PrimitivesGeneratedNoXfbVerdict::StreamCounts);
|
||||
}
|
||||
|
||||
// Mesa lavapipe as measured (2026-08): stream silent for every capture-less
|
||||
// lavapipe as measured (2026-08): stream silent for every capture-less
|
||||
// draw, the dedicated primitives-generated query exact on every shape (discard
|
||||
// included), the statistics control dead under discard. The dedicated query must
|
||||
// win - it is the only substitute that covers the CTS shape there.
|
||||
|
||||
@@ -273,7 +273,7 @@ void main() {
|
||||
// The IMAGE half, and the case that has always been broken independently of any per-element
|
||||
// unit remapping: a plain CONSECUTIVE image array subscripted by a loop variable. This is
|
||||
// KHR-GL42.shader_image_load_store.advanced-sso-simple's own fragment shader shape, and a raw
|
||||
// GLES probe on Mesa 26.1.4 at ES 3.2 refuses the ESSL it produces with "image arrays indexed
|
||||
// GLES probe on llvmpipe 26.1.4 at ES 3.2 refuses the ESSL it produces with "image arrays indexed
|
||||
// with non-constant expressions are forbidden in GLSL ES". Foldable: after unrolling every
|
||||
// subscript is a literal.
|
||||
constexpr const char* kLoopIndexedImageArray = R"(#version 450 core
|
||||
|
||||
@@ -847,7 +847,7 @@ TEST(WidenImageFormats, WidenedModulesEmitEsslNamingTheCoreCarrier) {
|
||||
}
|
||||
}
|
||||
|
||||
// The narrow mode, for a driver that HAS GL_NV_image_formats - Mesa, which every software lane
|
||||
// The narrow mode, for a driver that HAS GL_NV_image_formats - llvmpipe, which every software lane
|
||||
// runs on. There the driver can spell rg32f, so widening it would spend two to four times the
|
||||
// texture memory to change nothing; but SPIRV-Cross STILL throws for r8ui rather than printing it,
|
||||
// and the throw loses the stage whatever the driver would have accepted. So the extension narrows
|
||||
|
||||
@@ -15,7 +15,7 @@ using MobileGL::MG_Backend::DirectVulkan::SwapchainObject;
|
||||
|
||||
namespace {
|
||||
// What each surface reports. Android's loader exposes MAILBOX and FIFO (plus the shared
|
||||
// modes with VK_KHR_shared_presentable_image) but never IMMEDIATE; Mesa's X11 WSI has
|
||||
// modes with VK_KHR_shared_presentable_image) but never IMMEDIATE; a desktop X11 WSI has
|
||||
// all four classic modes.
|
||||
const Vector<VkPresentModeKHR> kAndroidModes{
|
||||
VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR,
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace {
|
||||
// THE HARNESS'S HEADLESS PIN (HeadlessGL.cpp, EnsureHeadlessPlatform), for the servers this test
|
||||
// starts itself: both the `--serve` supervisor (SupervisorEnvironment copies this process's
|
||||
// environment) and the LaunchServer child inherit it, and each peer brings a pbuffer context up
|
||||
// on that server. Without it Mesa takes its build-time x11 platform: on a WSLg workstation that
|
||||
// on that server. Without it the host EGL takes its build-time x11 platform: on a WSLg workstation that
|
||||
// binds the window system and goes green, on a runner with no DISPLAY InitPbufferSurface fails
|
||||
// and every case reds before the ring ever fills. An operator's explicit EGL_PLATFORM still
|
||||
// wins, as in the harness and in tcp_server_fixture.py.
|
||||
|
||||
@@ -1589,7 +1589,7 @@ namespace {
|
||||
// Welcome, the applied record and the clean reap of the next session - has been evaluated
|
||||
// by now, and a GTEST_SKIP after a failed EXPECT still reports the case FAILED; so on such a
|
||||
// host "Skipped" means "latched and served, render half not run". The CI unit job
|
||||
// (.github/workflows/test.yml `test`) installs libegl1, whose Recommends brings the Mesa
|
||||
// (.github/workflows/test.yml `test`) installs libegl1, whose Recommends brings the distribution's EGL
|
||||
// vendor library on an Ubuntu runner; a runner without it shows these rows as Skipped and
|
||||
// PresentFrameSerialZero (which needs a context to reach its site) as skipped outright.
|
||||
if (b.egl == 0) {
|
||||
|
||||
@@ -1541,7 +1541,7 @@ TEST(ServerLoopTest, TheSevenFormatCapabilityReadsAnswerFromTheServersBackendNot
|
||||
}
|
||||
|
||||
// =====================================================================================
|
||||
// The EGL fixture: the SERVER's real DirectGLES backend, a real headless context (mesa
|
||||
// The EGL fixture: the SERVER's real DirectGLES backend, a real headless context (EGL
|
||||
// surfaceless, llvmpipe) on the apply thread, driven only through v1's twelve forwarders
|
||||
// =====================================================================================
|
||||
//
|
||||
@@ -1563,7 +1563,7 @@ TEST(ServerLoopTest, TheSevenFormatCapabilityReadsAnswerFromTheServersBackendNot
|
||||
// counting 1, review v2 item 10).
|
||||
//
|
||||
// NO USABLE EGL IS A SKIP, UNLESS MOBILEGL_ITEST_REQUIRE_GPU SAYS OTHERWISE - the integration
|
||||
// harness's own rule (ScenarioFixture.h): a developer box without mesa should not fail a run it could
|
||||
// harness's own rule (ScenarioFixture.h): a developer box without headless EGL should not fail a run it could
|
||||
// not perform, but a lane that relies on these cases sets the variable, and then an unusable EGL is
|
||||
// a FAILURE naming the step, never a green that ran nothing (review v2 N-1's lesson).
|
||||
#if !defined(_WIN32)
|
||||
@@ -1588,7 +1588,7 @@ namespace {
|
||||
}
|
||||
|
||||
// The integration harness's headless pin (HeadlessGL.cpp, EnsureHeadlessPlatform), for the same
|
||||
// reason: mesa's surfaceless platform needs no display, and glvnd has to be told which vendor to
|
||||
// reason: the EGL surfaceless platform needs no display, and glvnd has to be told which vendor to
|
||||
// load. The vendor json is the one MG_IntegrationTest/CMakeLists.txt pins by default; an operator
|
||||
// who set __EGL_VENDOR_LIBRARY_FILENAMES keeps theirs.
|
||||
void PinHeadlessEglEnvironment() {
|
||||
@@ -1654,7 +1654,7 @@ namespace {
|
||||
// THE SURFACE'S OWN CREATION is what binds natively (InitPbufferSurface -> MakeCurrent).
|
||||
if (!Server::ServerCreateEGLPbufferSurface(Surf(), 64, 64)) {
|
||||
return "ServerCreateEGLPbufferSurface - no usable headless EGL (EGL_PLATFORM=surfaceless, "
|
||||
"__EGL_VENDOR_LIBRARY_FILENAMES -> mesa/llvmpipe) on this box";
|
||||
"__EGL_VENDOR_LIBRARY_FILENAMES -> llvmpipe) on this box";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@ namespace {
|
||||
EXPECT_EQ(r.glxLoaded, 1);
|
||||
EXPECT_EQ(r.clientQueries, 1);
|
||||
|
||||
// Mesa's software-renderer selection must not disable MobileGL's EGL/GLX entry points.
|
||||
// Selecting the software renderer (LIBGL_ALWAYS_SOFTWARE) must not disable MobileGL's EGL/GLX entry points.
|
||||
const EntryReport software = RunEntryPoints(server.endpoint, logBase, true);
|
||||
EXPECT_EQ(software.vendorDisplay, 1);
|
||||
EXPECT_EQ(software.getDisplay, 1);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// time. Do not add one here.
|
||||
|
||||
namespace MobileGL::MG_Util::Async {
|
||||
// Stage 7: on by default. The gate behind the flip (2026-08-09, headless Mesa, both
|
||||
// Stage 7: on by default. The gate behind the flip (2026-08-09, headless llvmpipe and lavapipe, both
|
||||
// backends): GL30-40 mustpass + KHR-GL46.parallel_shader_compile at async=1 with the
|
||||
// extension advertised - 58,344 case-runs, 8 failures, and every one of the 8 also
|
||||
// fails standalone at async=0 and under the pre-P1 library, i.e. zero async-attributable
|
||||
|
||||
@@ -714,7 +714,7 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
eglLib = OpenLib({"libtinygl4angle.dylib"});
|
||||
#else
|
||||
// Versioned SONAME first. The unversioned "libEGL.so" is a development
|
||||
// symlink: it ships in libegl-dev/mesa-libEGL-devel, NOT in the runtime
|
||||
// symlink: it ships in the EGL development package (libegl-dev), NOT in the runtime
|
||||
// package, so a machine that can run GL perfectly well may not have it -
|
||||
// every stock Ubuntu/Debian runtime image, the GitHub Actions runners
|
||||
// included. Asking only for the unversioned name there makes dlopen fail,
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace MobileGL::MG_Util::SelfTest {
|
||||
"void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }\n";
|
||||
|
||||
// No gl_PointSize anywhere: writing it from a geometry shader needs
|
||||
// EXT/OES_geometry_point_size, which not every ES 3.2 driver exposes (Mesa's does not),
|
||||
// EXT/OES_geometry_point_size, which not every ES 3.2 driver exposes (some desktop drivers do not),
|
||||
// and a probe that fails to COMPILE reaches no verdict at all.
|
||||
const char* const kProbeGeometrySource =
|
||||
"#version 320 es\n"
|
||||
|
||||
@@ -309,7 +309,7 @@ namespace MobileGL::MG_Util::SelfTest {
|
||||
// "unfixable". Probing only the shape MobileGL emits today (`coherent` plus
|
||||
// memoryBarrierImage()) reports a bug on drivers where simply adding `volatile` makes the
|
||||
// read correct, which is a defect MobileGL could fix rather than one it cannot: measured on
|
||||
// Mesa llvmpipe, the emitted shape misses every texel while the `volatile` shape misses
|
||||
// llvmpipe, the emitted shape misses every texel while the `volatile` shape misses
|
||||
// none. Only a driver that fails even the strongest shape has no in-shader substitute left.
|
||||
//
|
||||
// The control is the same dependency split across TWO draws with a glMemoryBarrier and a
|
||||
|
||||
@@ -1986,7 +1986,7 @@ namespace MobileGL::MG_Util::SelfTest {
|
||||
constexpr const char* RowName = "Subgroup first-reduction witness";
|
||||
// FailOptional, not Fail. The witness reports whether the NATIVE subgroup
|
||||
// first-reduction works; when it does not, the renderer takes its non-subgroup
|
||||
// iteration path and draws the same image. Both an Adreno 830 and Mesa lavapipe
|
||||
// iteration path and draws the same image. Both an Adreno 830 and lavapipe
|
||||
// fail this row's topology check today while running the DirectVulkan backend
|
||||
// perfectly well, so a fatal verdict here would have the screen announce that a
|
||||
// backend the user is looking at through that very backend cannot run.
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace MobileGL::MG_Util::SelfTest {
|
||||
//
|
||||
// THE CONTROL DISCIPLINE (DriverBugProbes.h): the substitute slots are the
|
||||
// probe's controls, and the DISCARD dimension is measured separately because
|
||||
// it is a real fault line, not paranoia: Mesa llvmpipe short-circuits its
|
||||
// it is a real fault line, not paranoia: llvmpipe short-circuits its
|
||||
// clipping statistics under rasterizer discard (reading 0 there while counting
|
||||
// the identical undiscarded draw exactly) while its dedicated
|
||||
// primitives-generated query counts both - measured 2026-08, and the reason
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace MobileGL {
|
||||
// constant-expression rule for both and the drivers refuse the whole stage
|
||||
// ("indexing into an SSBO array using a non-constant expression is not
|
||||
// permitted" on Qualcomm, "image arrays indexed with non-constant expressions
|
||||
// are forbidden in GLSL ES" on Mesa), which loses the program while the
|
||||
// are forbidden in GLSL ES" on llvmpipe), which loses the program while the
|
||||
// frontend still reports GL_LINK_STATUS = TRUE. Same two halves as the
|
||||
// fragment-output legalization: fold the loop-derived indices, then lower
|
||||
// whatever is genuinely dynamic to a switch over the array's range. SAMPLER
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace MobileGL {
|
||||
// '[' : array indexes for fragment outputs must be constant integral expressions
|
||||
//
|
||||
// The program then links nothing and every draw that uses it is a silent no-op.
|
||||
// Mesa accepts the same source, which is why this only ever showed on the ANGLE
|
||||
// llvmpipe accepts the same source, which is why this only ever showed on the ANGLE
|
||||
// lane (see tools/trace_replay/README.md, improved-transparency-minecraft-26.3:
|
||||
// the whole translucent layer disappears because the OIT coefficient shader is
|
||||
// exactly this shape).
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace MobileGL {
|
||||
// Qualcomm, storage blocks:
|
||||
// '[' : indexing into an SSBO array using a non-constant expression is not
|
||||
// permitted
|
||||
// Mesa, images:
|
||||
// llvmpipe, images:
|
||||
// image arrays indexed with non-constant expressions are forbidden in GLSL ES
|
||||
//
|
||||
// glslang keeps the whole array as ONE SPIR-V variable, so SPIRV-Cross prints
|
||||
@@ -38,7 +38,7 @@ namespace MobileGL {
|
||||
// Verified on the device for the storage-block half: an Adreno 830 ES probe with no
|
||||
// MobileGL in the loop rejects the non-constant subscript with AND without
|
||||
// GL_EXT_gpu_shader5 (which the driver does advertise), and accepts a constant one.
|
||||
// Verified again for the image half on llvmpipe / Mesa 26.1.4 at ES 3.2, on a raw
|
||||
// Verified again for the image half on llvmpipe 26.1.4 at ES 3.2, on a raw
|
||||
// GLES probe: a scalar image and an array with literal subscripts both write the
|
||||
// units they name, and both a loop-variable subscript and a `const int[]` table
|
||||
// lookup are refused with the message above. So the ES 3.2 "dynamically uniform"
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace MobileGL {
|
||||
// (Flywheel's glMultiDrawElementsIndirect, glDrawElementsInstancedBaseInstance)
|
||||
// therefore feeds shaders an InstanceID offset by baseInstance. This pass rebases
|
||||
// every load of the InstanceIndex builtin to (InstanceIndex - BaseInstance), the
|
||||
// same lowering Zink/DXVK use, so the value seen by the shader matches GL's
|
||||
// same lowering other API-on-Vulkan translation layers use, so the value seen by the shader matches GL's
|
||||
// zero-based gl_InstanceID. Vulkan backend only - the DirectGLES transpile path
|
||||
// already receives a zero-based gl_InstanceID from SPIRV-Cross.
|
||||
class RebaseInstanceIndexPass : public spvtools::opt::Pass {
|
||||
|
||||
@@ -1060,7 +1060,7 @@ namespace MobileGL {
|
||||
// The raw texel through an OpCopyObject before anything reads it, which costs
|
||||
// nothing in SPIR-V and is load-bearing in the ESSL: SPIRV-Cross emits a copy
|
||||
// of a non-opaque value as a real `uvec4 _n = imageLoad(...);` statement,
|
||||
// where the read's own result is FORWARDED into whatever consumes it. Mesa's
|
||||
// where the read's own result is FORWARDED into whatever consumes it. The
|
||||
// llvmpipe compiler miscompiles the forwarded form - `vec4(imageLoad(img, c))`
|
||||
// written straight into an expression comes back as zeroes, and 0xFFFF comes
|
||||
// back as a NaN, while the identical arithmetic on a named uvec4 is correct.
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace MobileGL {
|
||||
// no ESSL route even on a driver that DOES advertise GL_NV_image_formats.
|
||||
// SPIRV-Cross's is_desktop_only_format set - r8ui, rg16f, r16i and fifteen others -
|
||||
// makes it THROW for an ESSL target rather than print a token, and the throw takes
|
||||
// the stage with it whatever the driver could have accepted. Mesa is exactly that
|
||||
// the stage with it whatever the driver could have accepted. llvmpipe is exactly that
|
||||
// case: it advertises the extension, so nothing else needs widening there, and
|
||||
// `layout(r8ui) uimage2D` still lost its whole program until this ran for it.
|
||||
//
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace MobileGL {
|
||||
// harmless: GLSL ES has no `index` layout qualifier in core, so the driver
|
||||
// answers "index layout qualifier requires EXT_blend_func_extended" and refuses
|
||||
// the stage. The program then links nothing and every draw with it renders
|
||||
// NOTHING - verified on Mesa 26.1.4 llvmpipe with no MobileGL in the process,
|
||||
// NOTHING - verified on llvmpipe 26.1.4 with no MobileGL in the process,
|
||||
// and it is why KHR-GL43.shader_atomic_counters.basic-program-query read back a
|
||||
// black render target.
|
||||
//
|
||||
@@ -163,9 +163,9 @@ namespace MobileGL {
|
||||
// dropping it cannot change what the shader does.
|
||||
//
|
||||
// Emitting it does change whether the shader EXISTS. SPIRV-Cross hoists the
|
||||
// qualifiers every member shares onto the block, and Mesa's ES compiler rejects
|
||||
// qualifiers every member shares onto the block, and llvmpipe's ES compiler rejects
|
||||
// that spelling outright ("Interface block sets both readonly and writeonly",
|
||||
// verified on Mesa 26.1.4 llvmpipe with no MobileGL in the process, against the
|
||||
// verified on llvmpipe 26.1.4 with no MobileGL in the process, against the
|
||||
// exact source this transpiler emitted). The stage then never compiles, the
|
||||
// program links without it, and every dispatch or draw is a silent no-op -
|
||||
// which is how KHR-GL43.shader_storage_buffer_object.basic-readonly-writeonly
|
||||
|
||||
@@ -347,7 +347,7 @@ class Supervisor(unittest.TestCase):
|
||||
Under inproc and spawn the server inherits the CLIENT's environment after
|
||||
HeadlessGL.cpp's EnsureHeadlessPlatform pinned EGL_PLATFORM=surfaceless and cleared
|
||||
DISPLAY/WAYLAND_DISPLAY. This supervisor is started by ctest from the job environment
|
||||
instead, so on a WSLg workstation it bound Mesa's build-time default x11 platform and went
|
||||
instead, so on a WSLg workstation it bound the host EGL's build-time default x11 platform and went
|
||||
green, and on a runner with no window system eglInitialize failed with "xcb_connect
|
||||
failed" for every session."""
|
||||
seen = self.started_server_environment(DISPLAY=':0', WAYLAND_DISPLAY='wayland-0', EGL_PLATFORM=None)
|
||||
|
||||
@@ -75,7 +75,7 @@ def start(args):
|
||||
env.pop(key, None)
|
||||
# The harness's headless pin (HeadlessGL.cpp, EnsureHeadlessPlatform), for the one server it
|
||||
# does not start. Under inproc and spawn the server inherits the client's environment AFTER the
|
||||
# pin; this supervisor inherits ctest's. Without it Mesa takes its build-time x11 platform: on a
|
||||
# pin; this supervisor inherits ctest's. Without it the host EGL takes its build-time x11 platform: on a
|
||||
# WSLg workstation that binds the window system and goes green, on a runner with no DISPLAY
|
||||
# eglInitialize fails ("xcb_connect failed") and every Tcp. case reds with "remote TCP bring-up
|
||||
# failed". An operator's explicit EGL_PLATFORM still wins, as it does in the harness.
|
||||
|
||||
@@ -1256,7 +1256,7 @@ static void glImportFdBuffer(GlCtx& g, int fd, uint64_t allocationSize, uint64_t
|
||||
if (eImport != GL_NO_ERROR) {
|
||||
// Deliberately NOT closed: EXT_memory_object_fd transfers ownership of
|
||||
// the fd to the implementation and does not say whether that still
|
||||
// happens when the import fails, and Mesa closes it either way. A
|
||||
// happens when the import fails, and llvmpipe closes it either way. A
|
||||
// double close would land on whatever fd the allocator handed out
|
||||
// next -- the socket, in this program. At most a handful of rungs
|
||||
// run, so leaking the dup is the cheap, safe side of that trade.
|
||||
|
||||
@@ -5,7 +5,7 @@ if(NOT UNIX)
|
||||
return()
|
||||
endif()
|
||||
|
||||
option(MOBILEGL_TRACE_SOFTWARE_RENDERING "Force Mesa software rendering for trace tests" ON)
|
||||
option(MOBILEGL_TRACE_SOFTWARE_RENDERING "Force host software rendering (llvmpipe) for trace tests" ON)
|
||||
|
||||
set(MOBILEGL_TRACE_ROOT "${CMAKE_CURRENT_LIST_DIR}")
|
||||
set(MOBILEGL_TRACE_SHARED_CPP_DIR "${CMAKE_SOURCE_DIR}/android-plugin/app/src/trace/cpp")
|
||||
|
||||
Reference in New Issue
Block a user