[MG_Backend, MG_IntegrationTest] (P7): a real-probe negative control proves the depth-resolve measurement can see a broken render-pass arm on the host

This commit is contained in:
2026-09-23 15:20:17 -04:00
parent 33f3133920
commit 431bda67dc
8 changed files with 130 additions and 20 deletions
@@ -3452,6 +3452,34 @@ if (MOBILEGL_BUILD_DISAGGREGATED)
ENVIRONMENT "${mglItestMagmaWireEnvironment}\;MGITEST_MAGMA_DEPTH_RESOLVE_PROBE=bug\;MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/p7-${probeBugLog}${mglItestArmLogTag}.log")
endforeach()
endif()
# ---- P7 gate 5 (g5-msprobe critic): THE REAL PROBE'S NEGATIVE CONTROL ------------------
#
# The Bug entries above hand the arm choice a CANNED measurement, and MsResolve0 only pins
# lavapipe's clean answer, so no entry could see the REAL probe (WireDepthResolveProbe.cpp -
# its recording, readback and tally) stop detecting a render pass that writes nothing.
# MGITEST_MAGMA_DEPTH_RESOLVE_PROBE=elide-subject runs the real probe with its render-pass
# resolve left unrecorded - the subject's target keeps the sentinel, the Adreno 830's
# reading - while the shader control runs as always. The entry asserts the case's pixels,
# that the real measurement reports verdict=render-pass-resolve-broken with a reading whose
# render pass kept the sentinel beside a resolving control, and that the shader pass
# resolved and the render pass never did
# (DepthStencilReadbackMatrixScenario::ExpectTheResolveArmWhereTheLaneAsks).
#
# Split+spawn only, the server-side-knob reason above, named in spawn_lane_parity.py's
# MAGMA_SERVER_ENV_KNOB_NO_TCP.
#
# Red once (executed, reverted): EvaluateWireDepthResolveProbe answering Clean for every
# measurement fails both entries; the probe's subject tally counting every texel as
# resolved fails both entries while the four Bug entries stay green.
if(mglItestServerEnvKnobArm)
gtest_discover_tests(MobileGLIntegrationTest
TEST_PREFIX "DirectVulkan.${mglItestArm}.MsResolveElide."
TEST_FILTER "DepthStencilReadbackMatrixScenario.AResolvedMultisampleDepthReadsBackFromTheDestination"
DISCOVERY_TIMEOUT 30
PROPERTIES LABELS "${mglItestMagmaLabels}" TIMEOUT ${MGL_ITEST_TIMEOUT}
${mglItestArmProperties}
ENVIRONMENT "${mglItestMagmaWireEnvironment}\;MGITEST_MAGMA_DEPTH_RESOLVE_PROBE=elide-subject\;MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/p7-msresolveelide${mglItestArmLogTag}.log")
endif()
foreach(inPlaceCase CopyImageInPlaceAcrossLevelsAndLayers
CopyImageInPlaceOverlapDeclinesAndLeavesTheLevelAlone)
gtest_discover_tests(MobileGLIntegrationTest
@@ -244,6 +244,12 @@ namespace MGITest {
// place of running the probe: the shader pass must resolve, the render pass never;
// - MsResolve1. / MsFlip1. set MGITEST_MAGMA_FORCE_SHADER_DEPTH_RESOLVE=1, which drops
// the render-pass arm altogether: same assertion;
// - MsResolveElide. sets MGITEST_MAGMA_DEPTH_RESOLVE_PROBE=elide-subject, which runs the
// REAL probe with its render-pass resolve left unrecorded: the measurement itself (not
// a canned one) must report the defect - a reading whose render pass kept the sentinel
// in every texel while the shader control resolved all of them - and the shader pass
// must then resolve, the render pass never. The Bug entries cannot see the real
// probe's recording, readback or tally stop detecting the defect; this one does;
// - MsResolve0. on split and spawn sets MGITEST_EXPECT_DEPTH_RESOLVE_PROBE=clean - a
// marker only this function reads - and asserts the REAL probe ran on the lane's
// device (lavapipe), found the render pass clean, and that the render pass resolved.
@@ -256,13 +262,16 @@ namespace MGITest {
//
// Red once (executed, reverted): EvaluateWireDepthResolveProbe answering Clean for every
// measurement fails the four Bug entries here (the render-pass line is in the log and
// the verdict line says clean) while their pixels stay green.
// the verdict line says clean) while their pixels stay green. The two Elide entries go
// red under that too, and ALONE go red when the real probe's tally counts every subject
// texel as resolved (the canned Bug readings never pass through it).
static void ExpectTheResolveArmWhereTheLaneAsks(const char* what) {
const std::string probe = SplitLane::MarkerValue("MGITEST_MAGMA_DEPTH_RESOLVE_PROBE");
const bool forcedBug = probe == "bug";
const bool elidedSubject = probe == "elide-subject";
const bool renderPassDropped = SplitLane::MarkerIsOne("MGITEST_MAGMA_FORCE_SHADER_DEPTH_RESOLVE");
const bool measuredClean = SplitLane::MarkerValue("MGITEST_EXPECT_DEPTH_RESOLVE_PROBE") == "clean";
if (!forcedBug && !renderPassDropped && !measuredClean) return;
if (!forcedBug && !elidedSubject && !renderPassDropped && !measuredClean) return;
if (PipeStatsWindow::ServerLibraryLogPath().empty()) {
ADD_FAILURE() << what << ": the entry names the resolve arm (probe=" << probe
<< ", force-shader=" << renderPassDropped << ", expect-clean=" << measuredClean
@@ -277,7 +286,7 @@ namespace MGITest {
const bool renderPassResolved =
server.find("ResolveWireDepthStencil: resolved by the VK_KHR_depth_stencil_resolve render pass") !=
std::string::npos;
if (forcedBug || renderPassDropped) {
if (forcedBug || elidedSubject || renderPassDropped) {
EXPECT_TRUE(shaderResolved) << what << ": the server never resolved with the shader pass (probe="
<< probe << ", force-shader=" << renderPassDropped << ")";
EXPECT_FALSE(renderPassResolved)
@@ -288,6 +297,33 @@ namespace MGITest {
EXPECT_NE(server.find("verdict=render-pass-resolve-broken"), std::string::npos)
<< what << ": the forced `bug` measurement did not evaluate to the defect verdict";
}
if (elidedSubject) {
// The source phrase is the REAL measurement's (a canned one says "forced by"),
// and ArmWireDepthResolveOrder states it once per process.
EXPECT_NE(server.find("depth/stencil resolve probe (measured on this device with its render-pass "
"resolve elided by MGITEST_MAGMA_DEPTH_RESOLVE_PROBE=elide-subject) "
"verdict=render-pass-resolve-broken"),
std::string::npos)
<< what << ": the real probe, its render-pass resolve elided, did not report the defect";
// DescribeWireDepthResolveFormat's reading, one line per probed format: some
// format's render pass matched no texel and kept the sentinel in all 16, and its
// shader control resolved all 16.
bool sentinelKeptBesideAResolvedControl = false;
for (std::string::size_type at = server.find("depth/stencil resolve probe ");
at != std::string::npos && !sentinelKeptBesideAResolvedControl;
at = server.find("depth/stencil resolve probe ", at + 1)) {
const std::string::size_type end = server.find('\n', at);
const std::string line =
server.substr(at, end == std::string::npos ? std::string::npos : end - at);
sentinelKeptBesideAResolvedControl =
line.find(" x4: ") != std::string::npos &&
line.find("render pass 0/16 (first ") != std::string::npos &&
line.find("sentinel 16), shader control 16/16") != std::string::npos;
}
EXPECT_TRUE(sentinelKeptBesideAResolvedControl)
<< what << ": no real reading shows the elided render pass's sentinel kept beside a "
"shader control that resolved";
}
return;
}
EXPECT_NE(server.find("depth/stencil resolve probe (measured on this device) verdict=clean"),