mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 13:18:31 +09:00
- 55d2af9b claimed - in its message, in MagmaPipeArms.h, in VertexInputStateFactory.cpp and
in MG_IntegrationTest/CMakeLists.txt - that the AbaControlHandles lane defeats the
GENERATION in {slot, gen}. It does not, and no lane of that shape can. Magma's mint has no
death notification (nothing in MG_Backend/DirectVulkan consumes NotifyStateObjectDestroyed)
and returns a slot only through OnFrameBoundary's age sweep, kSweepInterval 256 /
kRetireAgeBoundaries 1024; HandleRecycleScenario issues five frame boundaries, so the
replacement VAO acquires against an empty free list and gets a BRAND-NEW slot at Gen 1
(measured: redVao slot=2 gen=1, greenVao slot=3 gen=1). The knob-off FRESH verdict there is
decided by the SLOT alone, and deleting ++m_entries[index].Gen leaves all 32 HandleRecycle
entries green - re-measured this round.
- What the lane does defeat is the object identity that SELECTS the slot, which IS the key the
handle arm ships, and that is what the three code sites now say. The two requirements are
mutually exclusive for the pixel-visible memo: a genuine slot reuse needs >= 1024 idle
boundaries after the dead object's last draw, which necessarily puts the two draws in
different frames, and ResolvedVertexBindings - the only memo carrying a GPU slice rather
than a layout - declines across frames by design.
- So the generation is covered where it IS expressible. MG_Test/Pipe/MagmaPipeIdentityTest.cpp
drives the mint's real retire -> reuse (1280 boundaries, with a keep-alive object holding the
first allocatable slot so the reuse is not the slot the control aliases onto) and asserts
four things: the retired slot comes back with Gen+1; with the knob OFF a memo stamped at
{slot, gen=N} is NOT served at {slot, gen=N+1}; with the knob ON it IS, out of one uncleared
and unclaimed entry; and a live object keeps its slot, its generation and its memo across two
sweeps, so the generation cannot be "fixed" by bumping it on every acquisition.
- The claim rule itself moves into MagmaPipeArms.h as MagmaPipeClaimSlotMemos so the suite
exercises production code rather than a copy of it. VertexInputStateFactory::MemosFor is now
one call to it and is otherwise unchanged, on both the knob-on and the knob-off path.
- Load-bearing, measured: with ++m_entries[index].Gen commented out, ctest -L unit in
build-push goes 1563/1566 - three of the four new cases red, one of them naming the inherited
0xDEAD payload out of the same slot - while ctest -R HandleRecycle stays 32/32. Restored, all
four pass in build-push and build-verify and skip visibly in the pull build, so the ctest name
sets stay identical (G2).
1167 lines
62 KiB
CMake
1167 lines
62 KiB
CMake
cmake_minimum_required(VERSION 3.24)
|
|
|
|
# MobileGL headless GPU integration tests.
|
|
#
|
|
# These are not unit tests: each scenario brings up a real EGL context on a
|
|
# pbuffer, renders real frames through a real backend and asserts on
|
|
# glReadPixels output. They need a GPU, so the module is OFF by default
|
|
# (MOBILEGL_BUILD_INTEGRATION_TEST) and every scenario skips cleanly - never
|
|
# fails, never hangs - on a machine without one. "Cleanly" is not a hope: the
|
|
# harness runs the whole bring-up in a forked child first, because MobileGL
|
|
# ABORTS rather than returning an error on an unusable platform (HeadlessGL.cpp).
|
|
#
|
|
# A clean skip is also indistinguishable from a pass, so set
|
|
# MOBILEGL_ITEST_REQUIRE_GPU wherever the machine is supposed to have a GPU.
|
|
#
|
|
# Backend selection is latched at initialization from MOBILEGL_BACKEND_TYPE, so
|
|
# one process is one backend: the same binary is registered twice, once per
|
|
# backend, under the `integration-gpu` label.
|
|
|
|
message(STATUS "Generating build files for MobileGL Integration Test...")
|
|
|
|
set(CMAKE_CXX_STANDARD 23)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
|
|
set(MGL_ITEST_ROOT ${CMAKE_CURRENT_LIST_DIR}/../..)
|
|
|
|
# Desktop links the static implementation directly. Android runs the same
|
|
# executable from adb shell and links the shipping shared library instead.
|
|
if (ANDROID)
|
|
set(MGL_ITEST_MOBILEGL_TARGET MobileGL)
|
|
elseif (TARGET MobileGL_s)
|
|
set(MGL_ITEST_MOBILEGL_TARGET MobileGL_s)
|
|
else()
|
|
message(STATUS "No MobileGL library target is available; skipping the integration test module")
|
|
return()
|
|
endif()
|
|
|
|
# MG_Test already pulls googletest in when MOBILEGL_BUILD_TEST is ON. Stand on
|
|
# our own feet when it is not, so this module can be built by itself.
|
|
if (NOT TARGET GTest::gtest)
|
|
include(FetchContent)
|
|
FetchContent_Declare(
|
|
googletest
|
|
GIT_REPOSITORY https://github.com/google/googletest.git
|
|
GIT_TAG v1.17.0
|
|
)
|
|
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
|
FetchContent_MakeAvailable(googletest)
|
|
endif()
|
|
|
|
add_executable(MobileGLIntegrationTest
|
|
Main.cpp
|
|
Harness/HeadlessGL.cpp
|
|
Harness/BackendCapsPeek.cpp
|
|
Scenarios/OrientationScenario.cpp
|
|
Scenarios/CrossFrameBufferScenario.cpp
|
|
Scenarios/ResidentIndexScenario.cpp
|
|
Scenarios/MultiDrawScenario.cpp
|
|
Scenarios/DrawParametersScenario.cpp
|
|
Scenarios/AsyncCompileScenario.cpp
|
|
Scenarios/XfbAfterClipDistanceScenario.cpp
|
|
Scenarios/UnwrittenPositionOutputScenario.cpp
|
|
Scenarios/SampleMaskScopeScenario.cpp
|
|
Scenarios/SampledSetStalenessScenario.cpp
|
|
Scenarios/ThreeChannelAttachmentScenario.cpp
|
|
Scenarios/SnormAttachmentScenario.cpp
|
|
Scenarios/PipelineFailureScenario.cpp
|
|
Scenarios/AdvertisedLimitsScenario.cpp
|
|
Scenarios/PixelStoreSweepScenario.cpp
|
|
Scenarios/PrimitiveRestartScenario.cpp
|
|
Scenarios/FragCoordOriginScenario.cpp
|
|
Scenarios/ClearThenReadPixelsScenario.cpp
|
|
Scenarios/SampleVariablesScenario.cpp
|
|
Scenarios/DepthStencilReadbackScenario.cpp
|
|
Scenarios/DepthStencilReadbackMatrixScenario.cpp
|
|
Scenarios/DepthStencilReadbackAttachmentShapeScenario.cpp
|
|
Scenarios/ClipDistanceScenario.cpp
|
|
Scenarios/ViewportArrayScenario.cpp
|
|
Scenarios/SsboArrayLengthScenario.cpp
|
|
Scenarios/DoublePrecisionScenario.cpp
|
|
Scenarios/UniformInitializerScenario.cpp
|
|
Scenarios/SwizzleAccessRoutineScenario.cpp
|
|
Scenarios/IterationRPFirstReductionScenario.cpp
|
|
Scenarios/IterationRPProgram203Scenario.cpp
|
|
Scenarios/IterationRPScratchFixScenario.cpp
|
|
Scenarios/ProgramPipelineScenario.cpp
|
|
Scenarios/ImageLoadStoreSsoScenario.cpp
|
|
Scenarios/ImageTargetKindScenario.cpp
|
|
Scenarios/ImageFormatQualifierScenario.cpp
|
|
Scenarios/NonCoreImageFormatScenario.cpp
|
|
Scenarios/ImageSizeAfterRespecScenario.cpp
|
|
Scenarios/SsboDeclarationFormScenario.cpp
|
|
Scenarios/Glsl420DeclarationScenario.cpp
|
|
Scenarios/IoBlockNameCollisionScenario.cpp
|
|
Scenarios/UnlocatedIoBlockScenario.cpp
|
|
Scenarios/TessellationDrawModeScenario.cpp
|
|
Scenarios/GeometryDrawModeScenario.cpp
|
|
Scenarios/PostLinkAttachScenario.cpp
|
|
Scenarios/FormatlessImageBakeScenario.cpp
|
|
Scenarios/FragmentOutputArrayIndexScenario.cpp
|
|
Scenarios/BufferTextureScenario.cpp
|
|
Scenarios/VertexAttribBindingScenario.cpp
|
|
Scenarios/XfbCaptureBufferReuseScenario.cpp
|
|
Scenarios/XfbPrimitiveQueryScenario.cpp
|
|
Scenarios/PrimitivesGeneratedNoXfbScenario.cpp
|
|
Scenarios/XfbRepeatedCaptureScenario.cpp
|
|
Scenarios/TessellationXfbCaptureScenario.cpp
|
|
Scenarios/PointSizeDemotionScenario.cpp
|
|
Scenarios/VertexArrayEnableDisableScenario.cpp
|
|
Scenarios/CopyImageLevelRangeScenario.cpp
|
|
Scenarios/CopyImageLayeredScenario.cpp
|
|
Scenarios/CopyImagePacked16Scenario.cpp
|
|
Scenarios/TextureViewScenario.cpp
|
|
Scenarios/PackedWordReadbackScenario.cpp
|
|
Scenarios/LayeredAttachmentBarrierScenario.cpp
|
|
Scenarios/LayeredAttachmentShapeScenario.cpp
|
|
Scenarios/LayeredTextureReadbackScenario.cpp
|
|
Scenarios/AtomicCounterScenario.cpp
|
|
Scenarios/LargeArenaAdoptionScenario.cpp
|
|
Scenarios/SsboArrayDynamicIndexScenario.cpp
|
|
Scenarios/StorageBufferRegrowScenario.cpp
|
|
Scenarios/SpirvShaderBinaryScenario.cpp
|
|
Scenarios/RelinkStageSetScenario.cpp
|
|
Scenarios/GuiBatchScenario.cpp
|
|
Scenarios/UnboundImageDescriptorScenario.cpp
|
|
Scenarios/IntegerBorderColorScenario.cpp
|
|
Scenarios/ClearTexImageUndefinedLevelZeroScenario.cpp
|
|
Scenarios/RenderbufferBlendFormatScenario.cpp
|
|
Scenarios/DualSourceBlendScenario.cpp
|
|
Scenarios/PipeVerifyArmingScenario.cpp
|
|
Scenarios/PoisonOmissionScenario.cpp
|
|
Scenarios/HandleRecycleScenario.cpp
|
|
Scenarios/CsoContentAddressingScenario.cpp
|
|
)
|
|
|
|
target_include_directories(MobileGLIntegrationTest PRIVATE
|
|
${MGL_ITEST_ROOT}/include
|
|
${MGL_ITEST_ROOT}/MobileGL
|
|
)
|
|
|
|
# gtest, not gtest_main: Main.cpp installs the harness banner itself.
|
|
target_link_libraries(MobileGLIntegrationTest PRIVATE
|
|
GTest::gtest
|
|
${MGL_ITEST_MOBILEGL_TARGET}
|
|
)
|
|
|
|
if (ANDROID)
|
|
find_library(MGL_ITEST_ANDROID_LIBRARY android REQUIRED)
|
|
find_library(MGL_ITEST_LOG_LIBRARY log REQUIRED)
|
|
find_library(MGL_ITEST_MEDIANDK_LIBRARY mediandk REQUIRED)
|
|
target_link_libraries(MobileGLIntegrationTest PRIVATE
|
|
${MGL_ITEST_ANDROID_LIBRARY}
|
|
${MGL_ITEST_LOG_LIBRARY}
|
|
${MGL_ITEST_MEDIANDK_LIBRARY}
|
|
)
|
|
endif()
|
|
|
|
if (MSVC)
|
|
# Same reason as MG_Test/Backend/DirectVulkan: the GLES headers declare gl*
|
|
# as dllimport on Windows, so the in-library GL entry-point definitions only
|
|
# resolve if the whole static library is part of the link.
|
|
target_link_options(MobileGLIntegrationTest PRIVATE /WHOLEARCHIVE:MobileGL_s)
|
|
endif()
|
|
target_compile_definitions(MobileGLIntegrationTest PRIVATE -DNOMINMAX)
|
|
|
|
if (ANDROID)
|
|
return()
|
|
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
|
|
# a GPU test. Pin the vendor/ICD json the same way MG_Benchmark's
|
|
# run_driver_bench.sh does.
|
|
#
|
|
# Leaving these empty is not a neutral default, it is the failure mode: an
|
|
# unpinned libEGL lands on llvmpipe and the suite goes green having tested a
|
|
# software rasteriser. So they are DETECTED here rather than defaulted to empty,
|
|
# and an empty result is a loud warning.
|
|
#
|
|
# mgl_itest_find_driver_json(<outVar> <description> <glob> [<glob>...])
|
|
# Picks the first json a real hardware vendor owns, in preference order, and
|
|
# never picks a software rasteriser (llvmpipe / lavapipe / swrast) - landing on
|
|
# one of those silently is the exact accident this pinning exists to prevent.
|
|
function(mgl_itest_find_driver_json outVar)
|
|
set(candidates "")
|
|
foreach(pattern IN LISTS ARGN)
|
|
file(GLOB matches "${pattern}")
|
|
list(APPEND candidates ${matches})
|
|
endforeach()
|
|
list(SORT candidates)
|
|
# Vendors ship an i686 json beside the x86_64 one and it sorts first. Pinning
|
|
# the wrong word size is worse than not pinning at all - the loader finds no
|
|
# driver and the whole suite skips - so drop the mismatched ones outright.
|
|
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
list(FILTER candidates EXCLUDE REGEX "i686|i386")
|
|
else()
|
|
list(FILTER candidates EXCLUDE REGEX "x86_64|aarch64")
|
|
endif()
|
|
set(software "")
|
|
foreach(vendor IN ITEMS nvidia amdgpu amd radeon intel_hasvk intel broadcom freedreno panfrost)
|
|
foreach(candidate IN LISTS candidates)
|
|
get_filename_component(leaf "${candidate}" NAME)
|
|
string(TOLOWER "${leaf}" leaf)
|
|
if (leaf MATCHES "${vendor}")
|
|
set(${outVar} "${candidate}" PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
endforeach()
|
|
endforeach()
|
|
# Nothing recognised as hardware. Report the first non-software entry if there
|
|
# is one; otherwise report nothing, so the warning below fires.
|
|
foreach(candidate IN LISTS candidates)
|
|
get_filename_component(leaf "${candidate}" NAME)
|
|
string(TOLOWER "${leaf}" leaf)
|
|
if (NOT leaf MATCHES "lvp|llvmpipe|lavapipe|swrast|softpipe")
|
|
set(${outVar} "${candidate}" PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
set(software "${candidate}")
|
|
endforeach()
|
|
set(${outVar} "" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
set(MGL_ITEST_DETECTED_EGL_VENDOR "")
|
|
set(MGL_ITEST_DETECTED_VK_ICD "")
|
|
if (UNIX AND NOT APPLE AND NOT ANDROID)
|
|
mgl_itest_find_driver_json(MGL_ITEST_DETECTED_EGL_VENDOR
|
|
"/usr/share/glvnd/egl_vendor.d/*.json"
|
|
"/etc/glvnd/egl_vendor.d/*.json")
|
|
mgl_itest_find_driver_json(MGL_ITEST_DETECTED_VK_ICD
|
|
"/usr/share/vulkan/icd.d/*.json"
|
|
"/etc/vulkan/icd.d/*.json")
|
|
endif()
|
|
|
|
set(MOBILEGL_ITEST_EGL_VENDOR "${MGL_ITEST_DETECTED_EGL_VENDOR}" CACHE FILEPATH
|
|
"glvnd EGL vendor json to pin for the integration tests (empty: leave the loader alone)")
|
|
set(MOBILEGL_ITEST_VK_ICD "${MGL_ITEST_DETECTED_VK_ICD}" CACHE FILEPATH
|
|
"Vulkan ICD json to pin for the DirectVulkan integration tests (empty: leave the loader alone)")
|
|
|
|
if (MOBILEGL_ITEST_EGL_VENDOR)
|
|
message(STATUS "Integration tests: pinning EGL vendor ${MOBILEGL_ITEST_EGL_VENDOR}")
|
|
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. "
|
|
"Set -DMOBILEGL_ITEST_EGL_VENDOR=/usr/share/glvnd/egl_vendor.d/<vendor>.json.")
|
|
endif()
|
|
if (MOBILEGL_ITEST_VK_ICD)
|
|
message(STATUS "Integration tests: pinning Vulkan ICD ${MOBILEGL_ITEST_VK_ICD}")
|
|
else()
|
|
message(WARNING
|
|
"Integration tests: no Vulkan ICD json found or configured (MOBILEGL_ITEST_VK_ICD is empty). "
|
|
"DirectVulkan would then load whichever ICD the loader enumerates first, quite possibly lavapipe. "
|
|
"Set -DMOBILEGL_ITEST_VK_ICD=/usr/share/vulkan/icd.d/<vendor>.json.")
|
|
endif()
|
|
|
|
# Turns "no usable GPU" from a clean skip into a failure - see ScenarioFixture.h.
|
|
# Without it the integration-gpu label is unfalsifiable: a run that skipped every
|
|
# scenario and a run that passed every scenario are the same green in ctest.
|
|
option(MOBILEGL_ITEST_REQUIRE_GPU
|
|
"Fail (rather than skip) the integration scenarios when the headless harness is unusable" OFF)
|
|
|
|
# No EGL_PLATFORM knob here on purpose. The harness pins EGL_PLATFORM=surfaceless
|
|
# itself before its first EGL call (HeadlessGL.cpp, EnsureHeadlessPlatform) so a
|
|
# developer's machine and a CI runner take the SAME path whether or not a window
|
|
# system happens to be running. This used to inject "x11", which is how the lane
|
|
# came up green on a workstation with WSLg and died on a runner with no X server.
|
|
#
|
|
# A build-system knob would not just be redundant, it would be a trap: `set(...
|
|
# CACHE ...)` does not rewrite an existing cache, so every build directory
|
|
# configured before this change would keep injecting EGL_PLATFORM=x11 and go on
|
|
# binding to a window system - silently, and only on the machines that have one.
|
|
# Someone reproducing a platform-specific bug sets EGL_PLATFORM in their own
|
|
# environment, which the harness still honours.
|
|
|
|
set(MGL_ITEST_COMMON_ENV "")
|
|
if (MOBILEGL_ITEST_EGL_VENDOR)
|
|
list(APPEND MGL_ITEST_COMMON_ENV "__EGL_VENDOR_LIBRARY_FILENAMES=${MOBILEGL_ITEST_EGL_VENDOR}")
|
|
endif()
|
|
unset(MOBILEGL_ITEST_EGL_PLATFORM CACHE) # see above: an old cache must not resurrect x11
|
|
if (MOBILEGL_ITEST_REQUIRE_GPU)
|
|
list(APPEND MGL_ITEST_COMMON_ENV "MOBILEGL_ITEST_REQUIRE_GPU=1")
|
|
endif()
|
|
|
|
set(MGL_ITEST_VULKAN_ENV ${MGL_ITEST_COMMON_ENV})
|
|
if (MOBILEGL_ITEST_VK_ICD)
|
|
list(APPEND MGL_ITEST_VULKAN_ENV "VK_ICD_FILENAMES=${MOBILEGL_ITEST_VK_ICD}")
|
|
# The three iterationRP repairs are tri-state quirks that default to device
|
|
# auto-detection, and lavapipe is not on any auto list - so on lavapipe the
|
|
# iterationRP scenarios run unrepaired and Program 203 misses its golden
|
|
# output. CI's integration-gpu job exports these three by hand; pinning them
|
|
# to the ICD instead means a local `ctest -L integration-gpu` measures the
|
|
# same thing the gate does, with no environment to remember.
|
|
if (MOBILEGL_ITEST_VK_ICD MATCHES "lvp_icd|lavapipe")
|
|
message(STATUS "Integration tests: lavapipe ICD - forcing the iterationRP repairs on")
|
|
list(APPEND MGL_ITEST_VULKAN_ENV
|
|
"MOBILEGL_MAGMA_FIX_ITERATIONRP_SUBGROUP_SCRATCH=1"
|
|
"MOBILEGL_MAGMA_DERIVE_NUM_SUBGROUPS=1"
|
|
"MOBILEGL_MAGMA_ITERATIONRP_FIX_BARRIER=1")
|
|
endif()
|
|
endif()
|
|
|
|
# The ENVIRONMENT test property is itself a `;`-list, and gtest_discover_tests
|
|
# forwards PROPERTIES as a flat list - so a plain `;`-joined value arrives as
|
|
# four separate arguments and everything after the first is silently read as
|
|
# another property name. Escaping the separators keeps the whole thing one list
|
|
# element until set_tests_properties expands it back. Without this only
|
|
# MOBILEGL_BACKEND_TYPE reaches the test and the vendor/ICD pinning is lost.
|
|
function(mgl_itest_join_environment outVar)
|
|
set(joined "")
|
|
foreach(entry IN LISTS ARGN)
|
|
if (joined)
|
|
string(APPEND joined "\\;${entry}")
|
|
else()
|
|
set(joined "${entry}")
|
|
endif()
|
|
endforeach()
|
|
set(${outVar} "${joined}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# --- what THIS TREE implements, answered by the build rather than by a person ----------
|
|
#
|
|
# Two P2 entries assert something that only EXISTS once another P2 package has landed:
|
|
# HandleRecycleScenario's Handles arm needs a backend keyed on {slot, gen} (packages C and D),
|
|
# its AbaControl arm needs a consumer for MOBILEGL_PIPE_HANDLE_ABA_CONTROL (package D), and
|
|
# CsoContentAddressingScenario needs the client-side tracker that mints CSOs at all (package B).
|
|
# The gates package is written and merged FIRST, against the P2 contract commit, precisely so
|
|
# that the AbaControl red is on the record before either backend is touched - so for a while
|
|
# those entries have nothing to assert.
|
|
#
|
|
# The honest report for that is a SKIP naming what is missing, never a deleted registration and
|
|
# never a green that means "the thing I test does not exist yet". What decides the skip is
|
|
# THIS block, so that nobody has to remember to remove a hand-written guard:
|
|
#
|
|
# * two of the three answers are pure EXISTENCE checks, through file(GLOB CONFIGURE_DEPENDS).
|
|
# Ninja re-evaluates such a glob before every build and reconfigures only when the RESULT
|
|
# changes, so these cost nothing until the file appears - and then they arm themselves.
|
|
# * the third has to read a file's CONTENTS, because package D re-keys inside an existing
|
|
# source rather than adding one. VertexInputStateFactory.cpp is the one file both of D's
|
|
# answers live in (ComputeHash's buffer key is what the re-key changes AND what the ABA
|
|
# knob reverts), it is small, and it is watched by name - so an edit to it reconfigures and
|
|
# an edit anywhere else in the backend does not.
|
|
#
|
|
# Every verdict is printed at configure time: a marker that silently answered "no" for a tree
|
|
# that does implement the thing would turn a real gate into a permanent skip.
|
|
set(MGL_ITEST_CAPABILITY_ENV "")
|
|
|
|
# Whether the library under test compiled the push arm. Passed in rather than inferred, because
|
|
# the two CSO counters and the cso[] bracket of the stats line are #if MOBILEGL_PIPE_PUSH: in a
|
|
# pull build there is no CSO to mint and no channel to read, so the control has nothing to say -
|
|
# and "nothing to say" must be a SKIP that names the reason, not an assertion failure about a
|
|
# missing bracket.
|
|
#
|
|
# The lanes themselves are registered in BOTH builds even so. `ctest -L integration-gpu` has to
|
|
# be name-for-name identical between the pull build and the push build (P2 gate G2), and a lane
|
|
# that exists in only one of them breaks that comparison for every future package - a much worse
|
|
# outcome than four entries that skip.
|
|
if (MOBILEGL_PIPE_PUSH)
|
|
list(APPEND MGL_ITEST_CAPABILITY_ENV "MGITEST_PIPE_PUSH_BUILD=1")
|
|
endif()
|
|
|
|
# THE THREE MARKERS BELOW ANSWER A QUESTION ABOUT THE SOURCE TREE, so each is only a true
|
|
# statement about THIS LIBRARY while this build compiles the arm the source implements - and all
|
|
# three arms are `#if MOBILEGL_PIPE_PUSH`. A pull build has no {slot, gen} key (the slot tables
|
|
# and the re-keyed memos are push-only) and no Features.PipeHandleAbaControl at all (Config.h
|
|
# declares the field inside `#if MOBILEGL_PIPE_PUSH` and ConfigLoader parses it in the same arm).
|
|
# A source-only probe would therefore arm the PULL build's lanes the moment packages C and D
|
|
# land: the AbaControl lane would go hard red on a gate G2 requires green (the guards it means to
|
|
# defeat are still in force, so the scenario's "expect the stale pixels" assertion fails), and the
|
|
# Handles lane would report green against a library that contains no re-key at all - the
|
|
# "test that cannot fail" this scenario exists to avoid.
|
|
#
|
|
# So the whole block sits under the same `if (MOBILEGL_PIPE_PUSH)` as MGITEST_PIPE_PUSH_BUILD, and
|
|
# HandleRecycleScenario re-checks that marker before either arm asserts, so a hand-forced
|
|
# environment cannot arm an arm this build does not have either.
|
|
#
|
|
# ALL FOUR MARKERS ARE CONTENT PROBES, AND NONE OF THEM NAMES A FILE. A probe for a filename asks
|
|
# the wrong question: the owning package chooses its own file layout, so the moment it moves the
|
|
# code the probe answers "no" forever and the arm skips with a reason that has become false - a
|
|
# test quietly measuring nothing, which is the one outcome this whole scenario exists to prevent.
|
|
# The CSO probe was rewritten for exactly that reason once already; the magma probe still read one
|
|
# hard-coded .cpp, and package D already keeps one of its two Features.PipeHandleAbaControl
|
|
# consumers in a different file of the same directory (Renderer/VulkanRenderer.cpp), so it was one
|
|
# refactor away from a permanent AbaControl skip. So all four now ask "does any source in the
|
|
# directory the owning package owns name this symbol?", which is the thing each arm actually needs.
|
|
#
|
|
# Staleness cannot creep in from either side: the GLOB is CONFIGURE_DEPENDS (a file added or
|
|
# removed re-runs it) and every file it finds is appended to CMAKE_CONFIGURE_DEPENDS (an edit to
|
|
# one re-runs it).
|
|
function(mgl_itest_probe_for_symbol outVar directory symbolRegex)
|
|
file(GLOB_RECURSE mglItestProbeSources CONFIGURE_DEPENDS
|
|
"${directory}/*.h" "${directory}/*.hpp" "${directory}/*.cpp" "${directory}/*.c")
|
|
set(mglItestProbeHit "")
|
|
foreach(mglItestProbeSource IN LISTS mglItestProbeSources)
|
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${mglItestProbeSource}")
|
|
file(STRINGS "${mglItestProbeSource}" mglItestProbeLines REGEX "${symbolRegex}")
|
|
if (mglItestProbeLines AND NOT mglItestProbeHit)
|
|
set(mglItestProbeHit "${mglItestProbeSource}")
|
|
endif()
|
|
endforeach()
|
|
set(${outVar} "${mglItestProbeHit}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
if (MOBILEGL_PIPE_PUSH)
|
|
# DirectGLES' Track H arm, probed by the subsystem bit it is gated on rather than by
|
|
# SlotTables.h existing: the bit is declared in the contract (MG_Pipe/MGPipe.h:77) and the
|
|
# backend has to name it to honour MOBILEGL_PIPE_PUSH's default mask, whatever files package C
|
|
# spreads the slot tables across.
|
|
mgl_itest_probe_for_symbol(MGL_ITEST_ESPRYT_SLOTS
|
|
"${MGL_ITEST_ROOT}/MobileGL/MG_Backend/DirectGLES" "kMGPipeSubsystemEsprytSlots")
|
|
if (MGL_ITEST_ESPRYT_SLOTS)
|
|
message(STATUS "Integration tests: DirectGLES is keyed on {slot, gen} (${MGL_ITEST_ESPRYT_SLOTS})")
|
|
list(APPEND MGL_ITEST_CAPABILITY_ENV "MGITEST_HANDLE_REKEY_DirectGLES=1")
|
|
else()
|
|
message(STATUS "Integration tests: no DirectGLES source names kMGPipeSubsystemEsprytSlots - "
|
|
"HandleRecycle.Handles will SKIP on it")
|
|
endif()
|
|
|
|
# The CSO counters' EMITTER. The tracker package may implement the tracker and the cache
|
|
# header-only - today it does (MG_Impl/Pipe/{Tracker,CsoCache}.h, no Tracker.cpp) - so what is
|
|
# looked for is what the control actually reads: a source emitting the two counters.
|
|
mgl_itest_probe_for_symbol(MGL_ITEST_CSO_EMITTER
|
|
"${MGL_ITEST_ROOT}/MobileGL/MG_Impl/Pipe" "RenderStateCso(Mints|Binds)")
|
|
if (MGL_ITEST_CSO_EMITTER)
|
|
message(STATUS "Integration tests: the CSO counters have an emitter (${MGL_ITEST_CSO_EMITTER})")
|
|
list(APPEND MGL_ITEST_CAPABILITY_ENV "MGITEST_PIPE_TRACKER_PRESENT=1")
|
|
else()
|
|
message(STATUS "Integration tests: no MG_Impl/Pipe source emits RenderStateCsoMints/Binds - "
|
|
"CsoContentAddressing will SKIP")
|
|
endif()
|
|
|
|
# DirectVulkan's Track H arm, and the ABA knob's consumer. Both over the whole backend
|
|
# directory: the re-key is subsystem 4's bit wherever package D reads it, and the knob has a
|
|
# consumer if ANY DirectVulkan source reverts a guard on it - today two do, in two files.
|
|
mgl_itest_probe_for_symbol(MGL_ITEST_MAGMA_REKEY
|
|
"${MGL_ITEST_ROOT}/MobileGL/MG_Backend/DirectVulkan" "kMGPipeSubsystemMagmaVertexInput")
|
|
if (MGL_ITEST_MAGMA_REKEY)
|
|
message(STATUS "Integration tests: DirectVulkan's vertex input is keyed on {slot, gen} "
|
|
"(${MGL_ITEST_MAGMA_REKEY})")
|
|
list(APPEND MGL_ITEST_CAPABILITY_ENV "MGITEST_HANDLE_REKEY_DirectVulkan=1")
|
|
else()
|
|
message(STATUS "Integration tests: no DirectVulkan source names kMGPipeSubsystemMagmaVertexInput - "
|
|
"HandleRecycle.Handles will SKIP on it")
|
|
endif()
|
|
|
|
mgl_itest_probe_for_symbol(MGL_ITEST_MAGMA_ABA
|
|
"${MGL_ITEST_ROOT}/MobileGL/MG_Backend/DirectVulkan" "PipeHandleAbaControl")
|
|
if (MGL_ITEST_MAGMA_ABA)
|
|
message(STATUS "Integration tests: MOBILEGL_PIPE_HANDLE_ABA_CONTROL has a consumer "
|
|
"(${MGL_ITEST_MAGMA_ABA})")
|
|
list(APPEND MGL_ITEST_CAPABILITY_ENV "MGITEST_HANDLE_ABA_IMPLEMENTED=1")
|
|
else()
|
|
message(STATUS "Integration tests: no DirectVulkan source names PipeHandleAbaControl - "
|
|
"HandleRecycle.AbaControl will SKIP")
|
|
endif()
|
|
else()
|
|
message(STATUS "Integration tests: pull build - HandleRecycle.{Handles,AbaControl} and "
|
|
"CsoContentAddressing stay registered (G2) and SKIP: every arm they assert is "
|
|
"compiled only under MOBILEGL_PIPE_PUSH")
|
|
endif()
|
|
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" ${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" ${MGL_ITEST_VULKAN_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_ASYNC_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_ASYNC_SHADER_COMPILE=1" ${MGL_ITEST_VULKAN_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_FORCED_DS_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_ESPRYT_FORCE_DS_READBACK_EMULATION=1" ${MGL_ITEST_COMMON_ENV})
|
|
|
|
# The shader-compiler configurations AsyncCompileScenario needs, and the one
|
|
# ViewportArrayScenario's negative control needs.
|
|
#
|
|
# These used to be poked into MG_Config::Features from inside the test bodies. They
|
|
# cannot be any more - on Android this module links the SHIPPING libMobileGL.so, which
|
|
# exports nothing internal - and they should not have been anyway: half of what each of
|
|
# them decides is latched before the first GL call (the compile pool and its threads;
|
|
# the advertised extension list, which a backend builds once from the configuration in
|
|
# force at its first use), so an in-process write could only ever have moved the other
|
|
# half. Every one of them is a whole-process property, and a whole-process property is
|
|
# spelled with an environment variable and a ctest entry of its own.
|
|
#
|
|
# Note the shape of every list here: it APPENDS to MGL_ITEST_COMMON_ENV /
|
|
# MGL_ITEST_VULKAN_ENV rather than standing alone. A ctest ENVIRONMENT property REPLACES
|
|
# the job environment rather than adding to it, so an entry that lists only its mode
|
|
# variable would silently lose the EGL vendor and Vulkan ICD pinning and run against
|
|
# whatever the loader found first.
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_ASYNC_ON_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_ASYNC_SHADER_COMPILE=1" ${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_ASYNC_OFF_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_ASYNC_SHADER_COMPILE=0" ${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_ASYNC_ON_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_ASYNC_SHADER_COMPILE=1" ${MGL_ITEST_VULKAN_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_ASYNC_OFF_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_ASYNC_SHADER_COMPILE=0" ${MGL_ITEST_VULKAN_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_OPTIMISTIC_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_ASYNC_SHADER_COMPILE=1"
|
|
"MOBILEGL_ASYNC_OPTIMISTIC_SHADER_STATUS=1" ${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_OPTIMISTIC_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_ASYNC_SHADER_COMPILE=1"
|
|
"MOBILEGL_ASYNC_OPTIMISTIC_SHADER_STATUS=1" ${MGL_ITEST_VULKAN_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_NO_VIEWPORT_EMULATION_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_ESPRYT_FORCE_VIEWPORT_ARRAY_EMULATION=0" ${MGL_ITEST_COMMON_ENV})
|
|
# MOBILEGL_LOG_FILE_PATH alongside the pin, because the arming assertion needs somewhere to
|
|
# read the library's own report from. The strip's arming signal is a latched MGLOG_I and there
|
|
# is no other way for a test process to learn that it fired - MG_Config is not reachable from
|
|
# this module on Android, where it links the shipping library. The path is per-lane so nothing
|
|
# else appends to it, and the case only trusts the bytes written after it started.
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_UNLOCATED_IO_BLOCKS_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_ESPRYT_UNLOCATED_IO_BLOCKS=1"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/unlocated-io-blocks.log"
|
|
${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_WIDENED_PACKED16_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_ESPRYT_WIDEN_PACKED16_STORAGE=1" ${MGL_ITEST_COMMON_ENV})
|
|
# Same shape as the UnlocatedIoBlocks entry: the log path is where the reroute's latched
|
|
# MGLOG_I lands, and the arming case only trusts the bytes written after it started.
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_PRIMGEN_REROUTE_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_MAGMA_PRIMGEN_QUERY_REROUTE=1"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/primgen-query-reroute.log"
|
|
${MGL_ITEST_VULKAN_ENV})
|
|
# The point-size demotion pinned on, per backend, with a per-lane log file for the arming
|
|
# assertion - the same MOBILEGL_LOG_FILE_PATH reasoning as the UnlocatedIoBlocks lane above.
|
|
# Two lanes because the demotion runs in the SHARED phase-B chain and each backend then
|
|
# consumes it differently (Espryt respells the driver-side capture request, Magma binds the
|
|
# SPIR-V Xfb decorations to the carrier).
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_POINT_SIZE_DEMOTION_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_POINT_SIZE_DEMOTION=1"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/point-size-demotion-gles.log"
|
|
${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_POINT_SIZE_DEMOTION_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_POINT_SIZE_DEMOTION=1"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/point-size-demotion-vulkan.log"
|
|
${MGL_ITEST_VULKAN_ENV})
|
|
|
|
# TIMEOUT on every entry: a GPU test that wedges must fail the run, not hang it.
|
|
set(MGL_ITEST_TIMEOUT 120)
|
|
|
|
include(GoogleTest)
|
|
|
|
# Discovery runs `--gtest_list_tests`, which does not construct the harness and
|
|
# so needs no GPU. One registration per backend; TEST_PREFIX keeps the two sets
|
|
# of ctest names apart.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES."
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_ENVIRONMENT}"
|
|
)
|
|
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan."
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_ENVIRONMENT}"
|
|
)
|
|
|
|
# A third registration, of ONE scenario, with asynchronous shader compilation
|
|
# pinned on. Not a second code path in the renderer: a second ALLOCATION pattern.
|
|
# The async pipeline's job objects change which of the freed blocks the capture
|
|
# phase is handed, and that is what decides whether the destroyed-VAO address is
|
|
# reached at all - on the ablated (pre-fix) tree async=1 reproduced 3 runs out of
|
|
# 3 where the ambient default reproduced 2 of 3. Pinning it here means the
|
|
# high-signal configuration runs whatever the shipped default becomes, instead of
|
|
# the suite quietly weakening the day that default flips. It must be process-wide
|
|
# (the ENVIRONMENT property), not an in-process scope: the compile pool and its
|
|
# threads are stood up at initialization, and their allocations are half the
|
|
# point. DirectVulkan only - the memo this pins is DirectVulkan's.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.AsyncCompile."
|
|
TEST_FILTER "XfbAfterClipDistanceScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_ASYNC_ENVIRONMENT}"
|
|
)
|
|
|
|
# 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
|
|
# 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
|
|
# emulation is DirectGLES's.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.ForcedDepthStencilEmulation."
|
|
TEST_FILTER "DepthStencilReadback*Scenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_FORCED_DS_ENVIRONMENT}"
|
|
)
|
|
|
|
# UnlocatedIoBlockScenario with the interface-block location strip PINNED ON, for the same
|
|
# reason the depth/stencil entry above pins its emulation: without it this scenario is
|
|
# UNFALSIFIABLE on the machines this suite runs on. llvmpipe carries a located interface block
|
|
# correctly, so the driver POST that arms the strip on Mali answers "healthy" here and the
|
|
# emulation never runs - the ambient registration would be exercising the un-stripped path
|
|
# twice and calling it coverage. With the variable set, the blocks really are emitted with no
|
|
# location and the assertion is about the spelling the device gets.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.UnlocatedIoBlocks."
|
|
TEST_FILTER "UnlocatedIoBlockScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_UNLOCATED_IO_BLOCKS_ENVIRONMENT}"
|
|
)
|
|
|
|
# AsyncCompileScenario, with asynchronous compilation PINNED ON per backend.
|
|
#
|
|
# Not a duplicate of what the two ambient registrations already run: they run whatever
|
|
# MobileGL's built-in default happens to be, and the day that default flips they would
|
|
# stop covering the asynchronous path without anything going red. These entries are the
|
|
# ones that keep the asynchronous half tested no matter what ships. They are also the
|
|
# only place ExtensionStringMatchesTheConfiguration can assert that the extension IS
|
|
# advertised - the case derives its expectation from this variable and nothing else, and
|
|
# skips where it is unset, precisely so that it is not asserting the implementation
|
|
# against itself.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.AsyncOn."
|
|
TEST_FILTER "AsyncCompileScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_ASYNC_ON_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.AsyncOn."
|
|
TEST_FILTER "AsyncCompileScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_ASYNC_ON_ENVIRONMENT}"
|
|
)
|
|
|
|
# The other side of the same switch: asynchronous compilation OFF, so
|
|
# GL_KHR_parallel_shader_compile must be WITHDRAWN from both spellings of the extension
|
|
# list and GL_MAX_SHADER_COMPILER_THREADS_KHR must read 0. Only that one case is
|
|
# registered here because it is the only one that has anything to say in this
|
|
# configuration - the other four exist to observe worker-built artifacts, and there are
|
|
# none - so registering the whole scenario would buy four guaranteed skips per backend.
|
|
# Together with the AsyncOn. entries above, one ctest run still covers both flag states,
|
|
# which is what the in-process forcing used to be for.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.AsyncOff."
|
|
TEST_FILTER "AsyncCompileScenario.ExtensionStringMatchesTheConfiguration"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_ASYNC_OFF_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.AsyncOff."
|
|
TEST_FILTER "AsyncCompileScenario.ExtensionStringMatchesTheConfiguration"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_ASYNC_OFF_ENVIRONMENT}"
|
|
)
|
|
|
|
# The optimistic-status quirk's end-to-end shape. Its own entries and not part of the
|
|
# AsyncOn. ones because the quirk is not neutral for the rest of the scenario: with it in
|
|
# force glGetShaderiv(GL_COMPILE_STATUS) deliberately answers without joining, which is
|
|
# exactly what CompletionStatusPollingThenForcedJoin asserts must NOT happen. Off by
|
|
# default and never advertised, so - unlike asynchronous compilation, which announces
|
|
# itself through the extension string - the variable is the only thing that can tell the
|
|
# case it is in force.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.OptimisticShaderStatus."
|
|
TEST_FILTER "AsyncCompileScenario.IrisShapedTwoPhaseBatchRendersCorrectly"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_OPTIMISTIC_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.OptimisticShaderStatus."
|
|
TEST_FILTER "AsyncCompileScenario.IrisShapedTwoPhaseBatchRendersCorrectly"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_OPTIMISTIC_ENVIRONMENT}"
|
|
)
|
|
|
|
# The negative control for the DirectGLES gl_ViewportIndex emulation, in a process that
|
|
# has it switched off. One case, because it is the only one the switch may touch: with
|
|
# the emulation off the three positive cases in the same fixture describe behaviour the
|
|
# backend does not have, so a whole-scenario registration would be three guaranteed reds.
|
|
# DirectGLES only - the flag steers nothing on DirectVulkan, which routes natively.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.NoViewportArrayEmulation."
|
|
TEST_FILTER "ViewportArrayScenario.WithoutTheEmulationEveryIndexCollapsesOntoViewportZero"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_NO_VIEWPORT_EMULATION_ENVIRONMENT}"
|
|
)
|
|
|
|
# PrimitivesGeneratedNoXfbScenario again, with the GL_PRIMITIVES_GENERATED statistics
|
|
# reroute PINNED ON. The ambient DirectVulkan registration runs the same cases under the
|
|
# bring-up probe's Auto verdict, so between the two entries both accounting paths answer
|
|
# the same GL questions and must produce the same numbers - the "two pools must agree"
|
|
# gate this machine can hold that the affected device cannot. The pinned entry is also
|
|
# the only one whose arming case runs: it asserts the renderer's latched MGLOG_I, so a
|
|
# silently-disarmed reroute (an inverted override mapping, a lost gate) fails here
|
|
# instead of leaving every equality case vacuously green. DirectVulkan only - the flag
|
|
# steers nothing on DirectGLES.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.PrimGenReroute."
|
|
TEST_FILTER "PrimitivesGeneratedNoXfbScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_PRIMGEN_REROUTE_ENVIRONMENT}"
|
|
)
|
|
|
|
# The packed16 copy scenarios again, with the 8-bit storage widening PINNED ON. The ambient
|
|
# registrations above cover the narrow storage - on every CI driver the widening's POST
|
|
# probe finds no field-order mirror, so Auto keeps the native 16-bit path - which means the
|
|
# storage every AFFECTED device will actually run would otherwise execute nowhere at all:
|
|
# no CI driver has the Mali bug that arms it. This lane is what proves the widened storage
|
|
# is client-invisible (same packed words in and out on every leg the 18 failing CTS bodies
|
|
# used, the renderbuffer one included). DirectGLES only - the flag steers nothing on
|
|
# DirectVulkan, which has always stored these formats widened.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.WidenedPacked16."
|
|
TEST_FILTER "CopyImagePacked16Scenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_WIDENED_PACKED16_ENVIRONMENT}"
|
|
)
|
|
|
|
# PointSizeDemotionScenario with the demotion PINNED ON, per backend, for the reason every
|
|
# pinned lane above exists: llvmpipe and lavapipe both HOST gl_PointSize in tessellation and
|
|
# geometry stages, so the ambient registrations run these captures through the built-in and
|
|
# the demotion - the path every affected Mali device actually takes - would execute nowhere.
|
|
# The ambient runs stay the negative control: same scenario, same CPU-computed bytes, native
|
|
# path. Both backends, because the demotion is shared phase-B work with two different
|
|
# consumers (the ESSL capture respelling vs the SPIR-V Xfb carrier binding).
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.PointSizeDemotion."
|
|
TEST_FILTER "PointSizeDemotionScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_POINT_SIZE_DEMOTION_ENVIRONMENT}"
|
|
)
|
|
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.PointSizeDemotion."
|
|
TEST_FILTER "PointSizeDemotionScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_POINT_SIZE_DEMOTION_ENVIRONMENT}"
|
|
)
|
|
|
|
# --- the third CI mode: MOBILEGL_PIPE_VERIFY -----------------------------------
|
|
#
|
|
# ARCHITECTURE.md 13.2-(2) asks for a THIRD build mode next to pull and push: two state models in
|
|
# one address space, compared field by field at every verb boundary and again at every accessor
|
|
# read, 5-10x slower and never shipped. These entries are that mode's lane. They exist only when
|
|
# the library was configured with -DMOBILEGL_PIPE_VERIFY=ON, which is deliberate and is half of
|
|
# what makes the lane falsifiable: `ctest -L integration-verify --no-tests=error` in a build that
|
|
# forgot the option matches NO tests and fails, instead of reporting a green run of nothing.
|
|
#
|
|
# The other half is PipeVerifyArmingScenario.Armed, which asserts the library's own arming line -
|
|
# because MOBILEGL_PIPE_VERIFY=1 in the environment of a library that never compiled the
|
|
# comparator in is a silent no-op that looks exactly like a clean pass.
|
|
#
|
|
# Three things about the ENVIRONMENT properties below, each of which has already gone wrong once
|
|
# in this file:
|
|
# * every list APPENDS ${MGL_ITEST_COMMON_ENV} / ${MGL_ITEST_VULKAN_ENV}. A ctest ENVIRONMENT
|
|
# entry overrides the job environment for the names it lists, so an entry that named only its
|
|
# own knobs would lose the EGL vendor and Vulkan ICD pinning and run against whichever driver
|
|
# the loader found first.
|
|
# * the ambient Verify. entries name NEITHER MOBILEGL_PIPE_VERIFY_CORRUPT NOR
|
|
# MOBILEGL_PIPE_POISON_OMIT. That is what lets CI's two always-on negative-control steps
|
|
# export those knobs in the JOB environment and have them reach the test processes; a
|
|
# property entry of the same name would silently win and the controls would prove nothing.
|
|
# * MOBILEGL_LOG_FILE_PATH is per lane, and "per lane" is the exact limit of what it proves. It
|
|
# is the only channel a test process has for reading the library's own report (MG_Config is not
|
|
# reachable from this module), but the log is opened fopen(path, "w"), so every process in a
|
|
# lane TRUNCATES it: after an ambient lane of 400-odd entries the file holds the LAST process
|
|
# and nothing else. Reading it is therefore only sound in a filtered, one-entry lane - which is
|
|
# why the arming case has a lane and a log of its own below, and why neither this file nor CI
|
|
# may read the ambient logs as evidence about the entries that ran before the last one. The
|
|
# ambient path is kept for post-mortems (and to keep library chatter out of ctest's capture).
|
|
# --- G8: the handle ABA, three always-on arms -----------------------------------------
|
|
#
|
|
# ALWAYS ON, in every build mode, which is deliberate: the Legacy arm asserts today's
|
|
# lifetimeId + weak_ptr guards and is meaningful in a pull build, and `ctest -R HandleRecycle`
|
|
# has to name the same entries whichever build directory it is pointed at (P2 brief G8 runs it
|
|
# against build-verify; D.3 part 1 runs it again as part of the interface-purity gate).
|
|
#
|
|
# One lane per arm, and each lane names MGITEST_HANDLE_ARM: the arm is not a property of the
|
|
# test body, it is the (MOBILEGL_PIPE_PUSH, MOBILEGL_PIPE_LEGACY_MEMOS, MOBILEGL_PIPE_HANDLE_ABA_CONTROL)
|
|
# triple the process was launched with, and the scenario skips in the ambient entries because
|
|
# none of that is configured there.
|
|
#
|
|
# Every list APPENDS the common/Vulkan environment for the reason spelled out above the verify
|
|
# block: a ctest ENVIRONMENT property REPLACES the job environment for the names it lists, so an
|
|
# entry naming only its own knobs would lose the EGL vendor and Vulkan ICD pinning.
|
|
#
|
|
# The AbaControl arm is DirectVulkan only. The knob defeats the object-identity half of
|
|
# DirectVulkan's vertex-input memo keys (VertexInputStateFactory::ComputeHash, its per-VAO memo
|
|
# table, and LookupVaoDrawMemo); it steers nothing on DirectGLES, and a lane that configured it
|
|
# there would be a permanent skip claiming to be a control.
|
|
#
|
|
# It gets TWO lanes, because there are two arms and the control has to reach the one P2 SHIPS.
|
|
# `AbaControl` is D18's lane verbatim (MOBILEGL_PIPE_PUSH=0, the pre-handle arm) and defeats the
|
|
# lifetime-id/address guards; `AbaControlHandles` runs the handle arm (MOBILEGL_PIPE_LEGACY_MEMOS=0,
|
|
# the default push mask) and defeats the object identity that SELECTS THE SLOT - the key the handle
|
|
# arm ships. With only the first lane the control says nothing at all about the re-key: the handle
|
|
# arm is not executed under MOBILEGL_PIPE_PUSH=0, so every guard it would have to defeat is in
|
|
# another branch.
|
|
#
|
|
# NEITHER lane exercises the GENERATION half of {slot, gen}, and no lane of this shape can. Magma's
|
|
# mint has no death notification and returns a slot only through its age sweep (256/1024 boundaries,
|
|
# MagmaPipeArms.h), so the five frame boundaries this scenario issues always hand the replacement a
|
|
# brand-new slot at Gen 1; a real reuse needs >= 1024 idle boundaries, which puts the two draws in
|
|
# different frames - where the only pixel-visible memo declines by design. The generation is covered
|
|
# by the unit suite MG_Test/Pipe/MagmaPipeIdentityTest.cpp instead, which drives a real
|
|
# retire -> reuse; MagmaPipeAbaControlDefeatsIdentity carries the measurement.
|
|
#
|
|
# The two PUSH-ONLY knobs of those arms are set only in a push build, and the lane NAMES are
|
|
# unaffected by that (an ENVIRONMENT property is not part of a test's name, so G2 still sees the
|
|
# same list in both builds). MOBILEGL_PIPE_LEGACY_MEMOS=0 says "never enter the legacy arm"; in a
|
|
# pull build the legacy arm is the ONLY arm and every Track-H subsystem bit is clear, which is
|
|
# precisely D14's startup Fatal{PipeLegacyMemosDisabled} condition - so a lane that set it there
|
|
# would abort the process before the scenario could report its skip. MOBILEGL_PIPE_HANDLE_ABA_CONTROL
|
|
# has no field to parse into in a pull build at all (Config.h declares it under #if MOBILEGL_PIPE_PUSH).
|
|
# A lane that needs an arm pins EVERY knob that selects it. A ctest ENVIRONMENT property overrides
|
|
# only the variables it names; the rest leak in from the job. The five-part gate's all-pull control
|
|
# arm runs `MOBILEGL_PIPE_PUSH=0 ctest -L integration-gpu` over the whole label, and without the
|
|
# explicit bitmask below that leaked PUSH=0 turned this lane's LEGACY_MEMOS=0 into D14's armless
|
|
# combination: the bring-up aborted, on purpose, and the lane went red for a reason that was never
|
|
# about handles. The mask is the P2 default (kMGPipeSubsystemsMigratedAtP2), not a hand-picked bit,
|
|
# so the lane keeps measuring the shape that ships.
|
|
if (MOBILEGL_PIPE_PUSH)
|
|
set(MGL_ITEST_HANDLES_ARM_KNOBS "MOBILEGL_PIPE_LEGACY_MEMOS=0" "MOBILEGL_PIPE_PUSH=0x7f")
|
|
set(MGL_ITEST_ABA_ARM_KNOBS "MOBILEGL_PIPE_HANDLE_ABA_CONTROL=1")
|
|
else()
|
|
set(MGL_ITEST_HANDLES_ARM_KNOBS "")
|
|
set(MGL_ITEST_ABA_ARM_KNOBS "")
|
|
endif()
|
|
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_HANDLE_HANDLES_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MGITEST_HANDLE_ARM=handles" ${MGL_ITEST_HANDLES_ARM_KNOBS}
|
|
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_HANDLE_HANDLES_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MGITEST_HANDLE_ARM=handles" ${MGL_ITEST_HANDLES_ARM_KNOBS}
|
|
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_VULKAN_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_HANDLE_LEGACY_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MGITEST_HANDLE_ARM=legacy" "MOBILEGL_PIPE_PUSH=0"
|
|
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_HANDLE_LEGACY_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MGITEST_HANDLE_ARM=legacy" "MOBILEGL_PIPE_PUSH=0"
|
|
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_VULKAN_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_HANDLE_ABA_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MGITEST_HANDLE_ARM=aba" "MOBILEGL_PIPE_PUSH=0"
|
|
${MGL_ITEST_ABA_ARM_KNOBS}
|
|
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_VULKAN_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_HANDLE_ABA_HANDLES_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MGITEST_HANDLE_ARM=aba"
|
|
${MGL_ITEST_HANDLES_ARM_KNOBS} ${MGL_ITEST_ABA_ARM_KNOBS}
|
|
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_VULKAN_ENV})
|
|
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.HandleRecycle.Handles."
|
|
TEST_FILTER "HandleRecycleScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_HANDLE_HANDLES_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.HandleRecycle.Handles."
|
|
TEST_FILTER "HandleRecycleScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_HANDLE_HANDLES_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.HandleRecycle.Legacy."
|
|
TEST_FILTER "HandleRecycleScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_HANDLE_LEGACY_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.HandleRecycle.Legacy."
|
|
TEST_FILTER "HandleRecycleScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_HANDLE_LEGACY_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.HandleRecycle.AbaControl."
|
|
TEST_FILTER "HandleRecycleScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_HANDLE_ABA_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.HandleRecycle.AbaControlHandles."
|
|
TEST_FILTER "HandleRecycleScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_HANDLE_ABA_HANDLES_ENVIRONMENT}"
|
|
)
|
|
|
|
# --- G12: the CSO content-addressing negative control ---------------------------------
|
|
#
|
|
# PUSH BUILDS ONLY, and that is the honest scope rather than a convenience: the two counters the
|
|
# control reads (CallClass::RenderStateCsoMints / RenderStateCsoBinds) and the `cso[...]` bracket
|
|
# of the summary line are both `#if MOBILEGL_PIPE_PUSH` (PipeStats.h, PipeStats.cpp), so in a pull
|
|
# build there is no channel to read and an entry here would be a permanent skip.
|
|
#
|
|
# Each arm gets a LOG PATH OF ITS OWN. The library opens its log fopen(path, "w") - every process
|
|
# in a lane truncates it - and these two cases READ that log, so a shared path would have them
|
|
# reading a neighbour's bring-up under `ctest -j 4`. Same rule as the arming lane below.
|
|
#
|
|
# MOBILEGL_PIPE_STATS_PERIOD=1 makes one summary line per eglSwapBuffers, which is what lets the
|
|
# workload be bracketed by two swaps and read back as a window covering exactly itself.
|
|
#
|
|
# Registered in EVERY build, including the pull build where there is no CSO at all, so that
|
|
# `ctest -L integration-gpu` stays name-for-name identical between pull and push (gate G2). In a
|
|
# pull build MGITEST_PIPE_PUSH_BUILD is absent and both cases skip saying so.
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_CSO_ON_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MGITEST_CSO_LANE=content-addressed"
|
|
"MOBILEGL_PIPE_PUSH=0x7f" "MOBILEGL_PIPE_STATS=1" "MOBILEGL_PIPE_STATS_PERIOD=1"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/cso-content-addressed-DirectGLES.log"
|
|
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_CSO_OFF_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MGITEST_CSO_LANE=no-content-addressing"
|
|
"MOBILEGL_PIPE_PUSH=0x800000000000007f" "MOBILEGL_PIPE_STATS=1" "MOBILEGL_PIPE_STATS_PERIOD=1"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/cso-no-content-addressing-DirectGLES.log"
|
|
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_CSO_ON_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MGITEST_CSO_LANE=content-addressed"
|
|
"MOBILEGL_PIPE_PUSH=0x7f" "MOBILEGL_PIPE_STATS=1" "MOBILEGL_PIPE_STATS_PERIOD=1"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/cso-content-addressed-DirectVulkan.log"
|
|
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_VULKAN_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_CSO_OFF_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MGITEST_CSO_LANE=no-content-addressing"
|
|
"MOBILEGL_PIPE_PUSH=0x800000000000007f" "MOBILEGL_PIPE_STATS=1" "MOBILEGL_PIPE_STATS_PERIOD=1"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/cso-no-content-addressing-DirectVulkan.log"
|
|
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_VULKAN_ENV})
|
|
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.CsoContentAddressing.On."
|
|
TEST_FILTER "CsoContentAddressingScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_CSO_ON_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.CsoContentAddressing.Off."
|
|
TEST_FILTER "CsoContentAddressingScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_CSO_OFF_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.CsoContentAddressing.On."
|
|
TEST_FILTER "CsoContentAddressingScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_CSO_ON_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.CsoContentAddressing.Off."
|
|
TEST_FILTER "CsoContentAddressingScenario.*"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS integration-gpu
|
|
TIMEOUT ${MGL_ITEST_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_CSO_OFF_ENVIRONMENT}"
|
|
)
|
|
|
|
if (MOBILEGL_PIPE_VERIFY)
|
|
# 900s, not the ambient 120: the comparator re-reads every field of the fill mask at the verb
|
|
# boundary and again at every accessor read, which the design budgets at 5-10x.
|
|
set(MGL_ITEST_VERIFY_TIMEOUT 900)
|
|
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_VERIFY_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_PIPE_VERIFY=1"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-DirectGLES.log"
|
|
${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_VERIFY_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_PIPE_VERIFY=1"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-DirectVulkan.log"
|
|
${MGL_ITEST_VULKAN_ENV})
|
|
|
|
# The arming assertion's own lane, one case per backend, with a log path nothing else writes to.
|
|
#
|
|
# PipeVerifyArmingScenario.Armed reads the library's log, and the log is a per-LANE resource: it
|
|
# is opened fopen(path, "w"), so every process in a lane truncates it. In the ambient Verify.
|
|
# lane that is 400-odd processes on one path, run `-j 4` in CI, and a whole-file read there
|
|
# races a neighbour's bring-up. Every other log-reading scenario in this file (UnlocatedIoBlocks,
|
|
# the primgen reroute, the point-size demotion) is registered exactly like this for the same
|
|
# reason. MGITEST_PIPE_ARMING_LANE is a harness marker - the library never reads it - and it is
|
|
# what makes the case skip in the ambient lane instead of racing there.
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_VERIFY_ARMING_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_PIPE_VERIFY=1" "MGITEST_PIPE_ARMING_LANE=1"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-arming-DirectGLES.log"
|
|
${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_VERIFY_ARMING_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_PIPE_VERIFY=1" "MGITEST_PIPE_ARMING_LANE=1"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-arming-DirectVulkan.log"
|
|
${MGL_ITEST_VULKAN_ENV})
|
|
|
|
# Negative control A (G4). MOBILEGL_PIPE_VERIFY_FATAL=0 so the process SURVIVES its own
|
|
# divergence and the case can read the report back out of the log; the CI step that exports
|
|
# the same corruption against the ambient lane, where FATAL keeps its default of 1, asserts
|
|
# the other half - that a divergence aborts and reds the entry.
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_VERIFY_CORRUPT_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_PIPE_VERIFY=1"
|
|
"MOBILEGL_PIPE_VERIFY_CORRUPT=GetRenderStateParameters" "MOBILEGL_PIPE_VERIFY_FATAL=0"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-corrupt-DirectGLES.log"
|
|
${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_VERIFY_CORRUPT_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_PIPE_VERIFY=1"
|
|
"MOBILEGL_PIPE_VERIFY_CORRUPT=GetRenderStateParameters" "MOBILEGL_PIPE_VERIFY_FATAL=0"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-corrupt-DirectVulkan.log"
|
|
${MGL_ITEST_VULKAN_ENV})
|
|
|
|
# Negative control B (G5). The omission skips the STAMP of one field for one verb while still
|
|
# copying its value, which is indistinguishable from a fill row nobody wrote; the scenario
|
|
# forks, so the resulting std::abort() is a datum in waitpid() rather than a dead lane.
|
|
mgl_itest_join_environment(MGL_ITEST_GLES_POISON_OMIT_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_PIPE_VERIFY=1"
|
|
"MOBILEGL_PIPE_POISON_OMIT=GenerateMipmap:GetActiveTextureUnit"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-poison-omit-DirectGLES.log"
|
|
${MGL_ITEST_COMMON_ENV})
|
|
mgl_itest_join_environment(MGL_ITEST_VULKAN_POISON_OMIT_ENVIRONMENT
|
|
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_PIPE_VERIFY=1"
|
|
"MOBILEGL_PIPE_POISON_OMIT=GenerateMipmap:GetActiveTextureUnit"
|
|
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-poison-omit-DirectVulkan.log"
|
|
${MGL_ITEST_VULKAN_ENV})
|
|
|
|
# The whole suite again, per backend, with the comparator armed. Same scenarios, same
|
|
# assertions, but every backend read of frontend state is now checked against a snapshot taken
|
|
# from the live context at the verb boundary - which is what "the 742 integration entries
|
|
# prove push equals pull" means. Labelled integration-gpu as well so a verify build's
|
|
# `ctest -L integration-gpu` still describes the whole registration set.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.Verify."
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS "integration-gpu\;integration-verify"
|
|
TIMEOUT ${MGL_ITEST_VERIFY_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_VERIFY_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.Verify."
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS "integration-gpu\;integration-verify"
|
|
TIMEOUT ${MGL_ITEST_VERIFY_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_VERIFY_ENVIRONMENT}"
|
|
)
|
|
|
|
# The arming assertion, one entry per backend. This is the entry that fails a lane whose library
|
|
# never armed: it runs the same library and the same MOBILEGL_PIPE_VERIFY=1 as the ambient
|
|
# entries above, but unlike them it cannot be green against a library with no comparator
|
|
# compiled in. Its log is its own, so `-j 4` cannot make it flake.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.VerifyArming."
|
|
TEST_FILTER "PipeVerifyArmingScenario.Armed"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS "integration-gpu\;integration-verify"
|
|
TIMEOUT ${MGL_ITEST_VERIFY_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_VERIFY_ARMING_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.VerifyArming."
|
|
TEST_FILTER "PipeVerifyArmingScenario.Armed"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS "integration-gpu\;integration-verify"
|
|
TIMEOUT ${MGL_ITEST_VERIFY_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_VERIFY_ARMING_ENVIRONMENT}"
|
|
)
|
|
|
|
# One case each: the knobs are process-wide, so a corrupted or poisoned process cannot also be
|
|
# running the ambient assertions. These four entries are the ones that assert the RED - they
|
|
# pass when the comparator and the poison report, and go red when either stops.
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.VerifyCorrupted."
|
|
TEST_FILTER "PipeVerifyArmingScenario.CorruptedFieldIsReported"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS "integration-gpu\;integration-verify"
|
|
TIMEOUT ${MGL_ITEST_VERIFY_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_VERIFY_CORRUPT_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.VerifyCorrupted."
|
|
TEST_FILTER "PipeVerifyArmingScenario.CorruptedFieldIsReported"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS "integration-gpu\;integration-verify"
|
|
TIMEOUT ${MGL_ITEST_VERIFY_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_VERIFY_CORRUPT_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectGLES.PoisonOmitted."
|
|
TEST_FILTER "PoisonOmissionScenario.OmittedFieldAbortsOnThatVerb"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS "integration-gpu\;integration-verify"
|
|
TIMEOUT ${MGL_ITEST_VERIFY_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_GLES_POISON_OMIT_ENVIRONMENT}"
|
|
)
|
|
gtest_discover_tests(MobileGLIntegrationTest
|
|
TEST_PREFIX "DirectVulkan.PoisonOmitted."
|
|
TEST_FILTER "PoisonOmissionScenario.OmittedFieldAbortsOnThatVerb"
|
|
DISCOVERY_TIMEOUT 30
|
|
PROPERTIES
|
|
LABELS "integration-gpu\;integration-verify"
|
|
TIMEOUT ${MGL_ITEST_VERIFY_TIMEOUT}
|
|
ENVIRONMENT "${MGL_ITEST_VULKAN_POISON_OMIT_ENVIRONMENT}"
|
|
)
|
|
endif()
|