mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-17 00:28:31 +09:00
[Test] (MG_IntegrationTest): assert which persistent-map arm the scenario landed in through a peek at IsBackendPersistentMapped, not by inferring it from the push byte counter - "the push was never wired" and "the store was adopted" are different defects with different owners and the counter reads the same for both
This commit is contained in:
@@ -56,6 +56,7 @@ add_executable(MobileGLIntegrationTest
|
||||
Harness/PipeApplyPeek.cpp
|
||||
Harness/P4aSeamPeek.cpp
|
||||
Harness/P4aFinalFixPeek.cpp
|
||||
Harness/PersistentMapPeek.cpp
|
||||
Scenarios/OrientationScenario.cpp
|
||||
Scenarios/CrossFrameBufferScenario.cpp
|
||||
Scenarios/ResidentIndexScenario.cpp
|
||||
@@ -1798,6 +1799,27 @@ endif()
|
||||
# half is the sharp one and it is layout-independent in the way the house rule demands - the
|
||||
# owning packages have to DELETE those aborts to implement anything, whatever files they
|
||||
# choose to put the implementation in. Both halves are printed at configure time.
|
||||
# Package b1's client-side persistent-map tracker, which is what Harness/PersistentMapPeek.cpp
|
||||
# asks the membership question of (b1-v1.md 4.1 item 2). TWO halves, and both are needed:
|
||||
# MOBILEGL_BUILD_DISAGGREGATED because a build that never compiled MG_Remote cannot LINK the call,
|
||||
# and the content probe because b1 may not have landed it yet. __has_include in the peek would
|
||||
# answer yes in a pull build - the header is in the source tree of every build - and turn a
|
||||
# healthy pull build into a link error, which is why this decision is made here.
|
||||
if (MOBILEGL_BUILD_DISAGGREGATED)
|
||||
mgl_itest_probe_for_symbol(MGL_ITEST_PERSISTENT_MAP_TRACKER
|
||||
"${MGL_ITEST_ROOT}/MobileGL/MG_Remote/Client" "IsLivePersistentMap")
|
||||
if (MGL_ITEST_PERSISTENT_MAP_TRACKER)
|
||||
message(STATUS "Integration tests: package b1's persistent-map tracker is present "
|
||||
"(${MGL_ITEST_PERSISTENT_MAP_TRACKER}) - PersistentCoherentMapScenario's "
|
||||
"membership assertion is live")
|
||||
target_compile_definitions(MobileGLIntegrationTest PRIVATE -DMGITEST_PERSISTENT_MAP_TRACKER=1)
|
||||
else()
|
||||
message(STATUS "Integration tests: no source under MobileGL/MG_Remote/Client names "
|
||||
"IsLivePersistentMap - package b1's tracker has not landed, so "
|
||||
"PersistentCoherentMapScenario's membership assertion SKIPS")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
mgl_itest_probe_for_symbol(MGL_ITEST_REMOTE_CLIENT_SIGNATURES
|
||||
"${MGL_ITEST_ROOT}/MobileGL/MG_Remote/Client"
|
||||
"kRemoteEmitSlotCount|RemoteEmitTable|CapsMirror")
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
// MobileGL - MobileGL/MG_IntegrationTest/Harness/PersistentMapPeek.cpp
|
||||
// Copyright (c) 2026 MobileGL-Dev
|
||||
// Licensed under the GNU Lesser General Public License v3.0:
|
||||
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
// End of Source File Header
|
||||
|
||||
#include "PersistentMapPeek.h"
|
||||
|
||||
#if !defined(__ANDROID__)
|
||||
#include <MG_State/GLState/BufferState/BufferObject.h>
|
||||
#include <MG_State/GLState/Core.h>
|
||||
#define MGITEST_PERSISTENT_MAP_PEEK_LIVE 1
|
||||
#endif
|
||||
|
||||
// MGITEST_PERSISTENT_MAP_TRACKER is defined by MG_IntegrationTest/CMakeLists.txt, and only when
|
||||
// BOTH halves are true: the build compiled MG_Remote (so the symbol can link) AND some source
|
||||
// under MG_Remote/Client names IsLivePersistentMap (so package b1 landed it). __has_include is
|
||||
// NOT enough on its own - the header exists in the source tree of every build, including the pull
|
||||
// build that never compiles MG_Remote, so keying on it would turn a healthy pull build into a
|
||||
// link error.
|
||||
#if defined(MGITEST_PERSISTENT_MAP_PEEK_LIVE) && defined(MGITEST_PERSISTENT_MAP_TRACKER)
|
||||
#include <MG_Remote/Client/PersistentMapTracker.h>
|
||||
#define MGITEST_PERSISTENT_MAP_TRACKER_LIVE 1
|
||||
#endif
|
||||
|
||||
namespace MGITest {
|
||||
|
||||
bool PersistentMapPeekAvailable() {
|
||||
#if defined(MGITEST_PERSISTENT_MAP_PEEK_LIVE)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PersistentMapTrackerAvailable() {
|
||||
#if defined(MGITEST_PERSISTENT_MAP_TRACKER_LIVE)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(MGITEST_PERSISTENT_MAP_PEEK_LIVE)
|
||||
namespace {
|
||||
// The frontend object behind a GL buffer name, or null. GetBufferObject mints on demand
|
||||
// for a name that was generated and never bound, which is harmless here: a scenario only
|
||||
// ever asks about a buffer it has already defined and mapped, and a null store answers
|
||||
// "not adopted", which is the same answer an un-mapped buffer would give.
|
||||
MobileGL::MG_State::GLState::BufferObject* FrontendBuffer(unsigned int bufferName) {
|
||||
if (bufferName == 0) return nullptr;
|
||||
auto& context = MobileGL::MG_State::pGLContext;
|
||||
if (!context) return nullptr;
|
||||
const auto& buffer = context->GetBufferObject(static_cast<MobileGL::Uint>(bufferName));
|
||||
return buffer.get();
|
||||
}
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
bool PeekBufferIsAdoptedPersistentMap(unsigned int bufferName, bool* outAdopted) {
|
||||
#if defined(MGITEST_PERSISTENT_MAP_PEEK_LIVE)
|
||||
if (outAdopted == nullptr) return false;
|
||||
MobileGL::MG_State::GLState::BufferObject* buffer = FrontendBuffer(bufferName);
|
||||
if (buffer == nullptr) return false;
|
||||
*outAdopted = static_cast<bool>(buffer->IsBackendPersistentMapped());
|
||||
return true;
|
||||
#else
|
||||
(void)bufferName;
|
||||
(void)outAdopted;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PeekBufferIsLivePersistentMap(unsigned int bufferName, bool* outLive) {
|
||||
#if defined(MGITEST_PERSISTENT_MAP_TRACKER_LIVE)
|
||||
if (outLive == nullptr) return false;
|
||||
MobileGL::MG_State::GLState::BufferObject* buffer = FrontendBuffer(bufferName);
|
||||
if (buffer == nullptr) return false;
|
||||
*outLive = static_cast<bool>(
|
||||
MobileGL::MG_Remote::Client::PersistentMapTracker::IsLivePersistentMap(*buffer));
|
||||
return true;
|
||||
#else
|
||||
(void)bufferName;
|
||||
(void)outLive;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace MGITest
|
||||
@@ -0,0 +1,61 @@
|
||||
// MobileGL - MobileGL/MG_IntegrationTest/Harness/PersistentMapPeek.h
|
||||
// Copyright (c) 2026 MobileGL-Dev
|
||||
// Licensed under the GNU Lesser General Public License v3.0:
|
||||
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
// End of Source File Header
|
||||
//
|
||||
// WHICH ARM A PERSISTENT|WRITE|COHERENT MAP LANDED IN, read from a scenario.
|
||||
//
|
||||
// It exists for exit gate E3's first assertion, and package b1 (b1-v1.md 4.1) names the
|
||||
// spelling: `IsBackendPersistentMapped()` must be FALSE, i.e. the store was NOT adopted and the
|
||||
// CPU shadow is still the source of truth, i.e. the emulated arm. The question has no answer in
|
||||
// the GL API at all - both arms map, both arms take the application's writes, both arms draw the
|
||||
// same pixels - so a scenario with no peek is a scenario that silently tests whichever arm the
|
||||
// driver and the build happened to choose. `MOBILEGL_DISABLE_LARGE_BUFFER_ADOPTION` does not
|
||||
// separate them either: it is read only inside TryAdoptLargeStorage, and a scenario-sized buffer
|
||||
// never reaches the 16 MiB threshold that calls it.
|
||||
//
|
||||
// A separate translation unit for BackendCapsPeek.h's reason, verbatim: the scenario sources
|
||||
// include the GL headers with prototypes and MobileGL's umbrella header is not meant to meet them
|
||||
// in one file.
|
||||
//
|
||||
// Every entry point returns FALSE, touching nothing, where the state is out of reach - on Android
|
||||
// this module links the shipping libMobileGL.so built -fvisibility=hidden, so no internal symbol
|
||||
// resolves, and the tracker half additionally needs a build that compiled MG_Remote/Client. A
|
||||
// caller that gets false must SKIP rather than pass: "could not look" is not "it was emulated".
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace MGITest {
|
||||
|
||||
// True when the peek can answer at all in this build. A scenario asks this first so that its
|
||||
// skip message can name WHY it could not look.
|
||||
bool PersistentMapPeekAvailable();
|
||||
|
||||
// BufferObject::IsBackendPersistentMapped() for the buffer with this GL name.
|
||||
//
|
||||
// returns false -> could not look (no peek in this build, no current context, or no such
|
||||
// buffer). *outAdopted is untouched.
|
||||
// returns true -> *outAdopted is true on the ADOPTED arm (the resource owner minted
|
||||
// host-visible coherent storage and the shadow was released) and false on
|
||||
// the EMULATED arm (the owner declined; the shadow is the truth and the
|
||||
// client has to push blocks). R-6 pins the split arm at emulated.
|
||||
bool PeekBufferIsAdoptedPersistentMap(unsigned int bufferName, bool* outAdopted);
|
||||
|
||||
// True when this build compiled package b1's client-side persistent-map tracker, so the
|
||||
// membership predicate below means something. CMake answers it, by probing MG_Remote/Client
|
||||
// for the symbol: a build that never compiled MG_Remote cannot link the call, so the decision
|
||||
// has to be made before the compiler sees it rather than by __has_include.
|
||||
bool PersistentMapTrackerAvailable();
|
||||
|
||||
// MG_Remote::Client::PersistentMapTracker::IsLivePersistentMap() for this buffer - b1-v1.md
|
||||
// 4.1 item 2. The membership set is meant to be exactly the early-out chain of
|
||||
// SyncPersistentMappedRange; asking it here is what makes a drift between the two fail in a
|
||||
// named test rather than silently stop the push.
|
||||
//
|
||||
// Same contract as above: false means "could not look".
|
||||
bool PeekBufferIsLivePersistentMap(unsigned int bufferName, bool* outLive);
|
||||
|
||||
} // namespace MGITest
|
||||
@@ -55,6 +55,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "../Harness/HeadlessGL.h"
|
||||
#include "../Harness/PersistentMapPeek.h"
|
||||
#include "../Harness/PipeStatsWindow.h"
|
||||
#include "../Harness/ScenarioFixture.h"
|
||||
#include "../Harness/SplitLane.h"
|
||||
@@ -107,6 +108,14 @@ void main() { oColor = vec4(vColor, 1.0); }
|
||||
|
||||
constexpr GLsizeiptr kQuadBytes = GLsizeiptr(sizeof(Vertex) * 6);
|
||||
constexpr GLbitfield kCoherentFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
|
||||
// b1-v1.md 4.1 item 7, asserted rather than commented. GL_MAP_FLUSH_EXPLICIT_BIT would
|
||||
// take this buffer OUT of the client's live-persistent-map set on purpose - the
|
||||
// application announces its own writes through resource_flush_range and the push ships
|
||||
// nothing - so a flag added here would turn every assertion below into a statement about
|
||||
// a different mechanism, and it would still draw the right pixels under monolith.
|
||||
static_assert((kCoherentFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0,
|
||||
"this scenario is about the PUSH, which is defined only for a persistent "
|
||||
"write map that is NOT FLUSH_EXPLICIT (BufferObject.cpp:645-661)");
|
||||
|
||||
// The ctest entry that reads the summary line sets this and nothing else does; the case
|
||||
// skips everywhere else rather than racing for the lane's log (PipeStatsWindow.h).
|
||||
@@ -191,10 +200,82 @@ void main() { oColor = vec4(vColor, 1.0); }
|
||||
}
|
||||
m_vbo = store.vbo;
|
||||
m_map = store.map;
|
||||
// b1-v1.md 4.1 item 1, IMMEDIATELY AFTER THE MAP and before anything else can
|
||||
// change the answer. This is the assertion that decides whether the rest of the
|
||||
// scenario means anything.
|
||||
AssertOrRecordArm(m_vbo, "immediately after the map");
|
||||
if (IsSkipped() || HasFatalFailure()) return;
|
||||
AssertMembership(m_vbo, "immediately after the map");
|
||||
if (IsSkipped() || HasFatalFailure()) return;
|
||||
DescribeAttributes();
|
||||
ASSERT_EQ(FirstGLError(), 0u) << "configuring the VAO over the coherently mapped store";
|
||||
}
|
||||
|
||||
// WHICH ARM. b1-v1.md 4.1 items 1 and 5: IsBackendPersistentMapped() false is the
|
||||
// emulated arm - the resource owner DECLINED, the CPU shadow is still the truth, and
|
||||
// the client has to push the mapping's dirty blocks. True is the adopted arm, where
|
||||
// MGPipeApplyMapPersistent handed back a pointer and the shadow was released.
|
||||
//
|
||||
// Under inproc BOTH ARMS RENDER CORRECTLY, because an adopted store's address really
|
||||
// is valid in this process - which is exactly why exit gate E3(d) has to be checked
|
||||
// and cannot be inferred from pixels. Under spawn the adopted arm would be a wild
|
||||
// pointer, so this one assertion is what makes E3 mean the same thing in P5 and P6.
|
||||
//
|
||||
// The lane DECLARES the arm it expects (MGITEST_PERSISTENT_MAP_ARM); a lane that
|
||||
// declares none RECORDS it, because which arm AcquireMemoryRange takes for a
|
||||
// sub-16-MiB map is a property of the driver - llvmpipe mints, a device may decline -
|
||||
// and a monolith lane that pinned one would be red on hardware for no defect.
|
||||
void AssertOrRecordArm(unsigned int vbo, const char* when) {
|
||||
const std::string declared = SplitLane::DeclaredPersistentMapArm();
|
||||
if (!PersistentMapPeekAvailable()) {
|
||||
if (!declared.empty()) {
|
||||
GTEST_SKIP() << "this lane declares the " << declared
|
||||
<< " arm but Harness/PersistentMapPeek cannot look in this "
|
||||
"build (on Android this module links the shipping "
|
||||
"libMobileGL.so, built -fvisibility=hidden, so no internal "
|
||||
"symbol resolves). 'Could not look' is not 'it was "
|
||||
<< declared << "'.";
|
||||
}
|
||||
RecordProperty("persistent_map_arm", "unknown");
|
||||
return;
|
||||
}
|
||||
bool adopted = false;
|
||||
ASSERT_TRUE(PeekBufferIsAdoptedPersistentMap(vbo, &adopted))
|
||||
<< "no frontend BufferObject behind GL buffer " << vbo << " " << when;
|
||||
const char* arm = adopted ? "adopted" : "emulated";
|
||||
RecordProperty("persistent_map_arm", arm);
|
||||
if (declared.empty()) return;
|
||||
ASSERT_EQ(declared, std::string(arm))
|
||||
<< "the lane declared the " << declared << " arm and IsBackendPersistentMapped() "
|
||||
<< when << " says " << arm
|
||||
<< ". R-6 pins the split arm at adopt tier T2 = declined = emulated, and the two "
|
||||
"arms are completely different code paths: adopted means the CPU shadow was "
|
||||
"released and the application writes straight into storage the resource owner "
|
||||
"minted, emulated means the shadow is the truth and every validate point has "
|
||||
"to push blocks. Under inproc both render correctly, so pixels cannot tell "
|
||||
"them apart - this is exit gate E3(d) and it is the only thing that can.";
|
||||
}
|
||||
|
||||
// b1-v1.md 4.1 item 2: the client's live-persistent-map set is meant to be exactly
|
||||
// SyncPersistentMappedRange's early-out chain. A drift between the two stops the push
|
||||
// silently; asking here makes it a named failure instead.
|
||||
void AssertMembership(unsigned int vbo, const char* when) {
|
||||
if (!PersistentMapTrackerAvailable()) {
|
||||
RecordProperty("persistent_map_membership", "unavailable");
|
||||
return;
|
||||
}
|
||||
bool live = false;
|
||||
ASSERT_TRUE(PeekBufferIsLivePersistentMap(vbo, &live))
|
||||
<< "the tracker is compiled in but could not answer for GL buffer " << vbo << " " << when;
|
||||
EXPECT_TRUE(live)
|
||||
<< "a PERSISTENT|WRITE|COHERENT map that is not FLUSH_EXPLICIT is a member of "
|
||||
"the client's live-persistent-map set by construction, and it is not one "
|
||||
<< when
|
||||
<< ". The set is supposed to BE SyncPersistentMappedRange's early-out chain; if "
|
||||
"they have drifted, the push stops shipping this buffer's blocks and nothing "
|
||||
"else says so.";
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
if (!Ready()) return;
|
||||
glBindVertexArray(0);
|
||||
@@ -270,6 +351,11 @@ void main() { oColor = vec4(vColor, 1.0); }
|
||||
"the SECOND write through the same mapping, announced by nothing: "
|
||||
"this is exit gate E3(b), and a 'push on the next explicit buffer "
|
||||
"operation' implementation reads back the FIRST write's colour here"));
|
||||
// E3(d) again, AFTER the draws: b1-v1.md 4.1 item 5 asks that the arm hold across the
|
||||
// whole scenario, not only at the map. A late adoption - the owner declining once and
|
||||
// minting on a later validate point - would leave the first assertion true and this one
|
||||
// false, and would be invisible in every pixel this case reads.
|
||||
AssertOrRecordArm(m_vbo, "after both writes and both draws");
|
||||
Gl().EndFrame();
|
||||
}
|
||||
|
||||
@@ -291,6 +377,7 @@ void main() { oColor = vec4(vColor, 1.0); }
|
||||
EXPECT_EQ(FirstGLError(), 0u);
|
||||
EXPECT_TRUE(WholeSurfaceIs(second, "red",
|
||||
"frame 1's write through the SAME mapping, after a Present"));
|
||||
AssertOrRecordArm(m_vbo, "after a frame boundary and two draws");
|
||||
Gl().EndFrame();
|
||||
}
|
||||
|
||||
@@ -321,6 +408,10 @@ void main() { oColor = vec4(vColor, 1.0); }
|
||||
if (!store.refusal.empty()) {
|
||||
GTEST_SKIP() << store.refusal;
|
||||
}
|
||||
AssertOrRecordArm(store.vbo, "immediately after the counted window's map");
|
||||
if (IsSkipped() || HasFatalFailure()) return;
|
||||
AssertMembership(store.vbo, "immediately after the counted window's map");
|
||||
if (IsSkipped() || HasFatalFailure()) return;
|
||||
glBindVertexArray(m_vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, store.vbo);
|
||||
DescribeAttributes();
|
||||
@@ -358,56 +449,38 @@ void main() { oColor = vec4(vColor, 1.0); }
|
||||
"monolith arm's' checkable by one process. It reported: "
|
||||
<< window.line;
|
||||
|
||||
// The arm. pmap is bytes PUSHED because a persistently mapped range had to be published,
|
||||
// and a push happens if and only if the acquisition was DECLINED - so pmap > 0 is the
|
||||
// emulated arm and pmap == 0 is the adopted one.
|
||||
// E3(c)'s second half: the bytes the push actually shipped. `pmap` is bytes PUSHED because
|
||||
// a persistently mapped range had to be published, so on the emulated arm a window with
|
||||
// four writes and four draws through a live coherent mapping cannot be zero.
|
||||
//
|
||||
// THE ARM ITSELF IS NOT DERIVED FROM THIS NUMBER. It is asserted from
|
||||
// IsBackendPersistentMapped() at the map and again after the draws (b1-v1.md 4.1 items 1
|
||||
// and 5), which is the direct observable; pmap is the CONSEQUENCE and is checked as a
|
||||
// cross-check. Deriving the arm from pmap would have made "the push was never wired" and
|
||||
// "the store was adopted" the same reading, and they are different defects with different
|
||||
// owners.
|
||||
const double pushedBytes = PipeStatsWindow::CounterAsDoubleOrAbsent(window, "pmap");
|
||||
ASSERT_GE(pushedBytes, 0.0) << "the summary line carries no pmap= field: " << window.line;
|
||||
const char* observedArm = (pushedBytes > 0.0) ? "emulated" : "adopted";
|
||||
RecordProperty("persistent_map_arm", observedArm);
|
||||
RecordProperty("persistent_map_push_bytes_per_frame", std::to_string(pushedBytes).c_str());
|
||||
RecordProperty("map_persistent_roundtrips", std::to_string(roundtrips).c_str());
|
||||
|
||||
const std::string declared = SplitLane::DeclaredPersistentMapArm();
|
||||
if (declared.empty()) {
|
||||
// SUCCEED, not GTEST_SKIP. The mpr assertion above is this lane's real claim and it
|
||||
// has already been made; the arm is the half it cannot assert, because WHICH arm
|
||||
// AcquireMemoryRange takes for a sub-16-MiB map is a property of the driver (llvmpipe
|
||||
// mints, a device may decline) and a monolith lane that pinned one would be red on
|
||||
// hardware for a reason that is not a defect. A skip here would have thrown away the
|
||||
// mpr result with it - and mpr is the number the split lane is compared against.
|
||||
SUCCEED() << "this lane declares no MGITEST_PERSISTENT_MAP_ARM, so the arm is RECORDED "
|
||||
"and not asserted, and the assertion this lane does make - one coherent "
|
||||
"map costs one acquisition attempt - passed. Observed arm: "
|
||||
<< observedArm << " (pmap=" << pushedBytes << ", mpr=" << roundtrips << "). "
|
||||
<< window.line;
|
||||
glBindVertexArray(0);
|
||||
unsigned int recordedVbo = store.vbo;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, recordedVbo);
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glDeleteBuffers(1, &recordedVbo);
|
||||
return;
|
||||
}
|
||||
EXPECT_EQ(declared, std::string(observedArm))
|
||||
<< "the lane declared the " << declared << " arm and the library took the " << observedArm
|
||||
<< " one (pmap=" << pushedBytes
|
||||
<< "). R-6 pins the split lane at T2 = emulated, and the two arms are completely "
|
||||
"different code paths: adopted means MGPipeApplyMapPersistent handed back a pointer "
|
||||
"and the CPU shadow was released, emulated means it declined and the client has to "
|
||||
"push blocks. Under inproc an ADOPTED store still renders correctly - the address is "
|
||||
"real in this process - so pixels cannot tell them apart and this counter is the "
|
||||
"only thing that can. That is exit gate E3(d) in the only spelling a black-box "
|
||||
"scenario has. Line: "
|
||||
<< window.line;
|
||||
if (declared == "emulated") {
|
||||
if (SplitLane::DeclaredPersistentMapArm() == "emulated") {
|
||||
EXPECT_GT(pushedBytes, 0.0)
|
||||
<< "the emulated arm pushes the mapping's dirty blocks at every validate point, so "
|
||||
"a window with four writes and four draws through a live coherent mapping cannot "
|
||||
"have pushed zero bytes. Zero here with MOBILEGL_IPC_PERSISTENT_BLOCK_KB at its "
|
||||
"default is the push never being wired; zero with it set to 0 is exit gate "
|
||||
"E3(a)'s negative control working as intended. Line: "
|
||||
"a window with "
|
||||
<< kDrawsInTheWindow
|
||||
<< " writes and as many draws through a live coherent mapping cannot have pushed "
|
||||
"zero bytes. Zero here with MOBILEGL_IPC_PERSISTENT_BLOCK_KB at its default "
|
||||
"means the push is not reaching this buffer - which is a DIFFERENT defect from "
|
||||
"the store having been adopted, and the arm assertion above has already ruled "
|
||||
"that one out. Zero with the knob set to 0 is exit gate E3(a)'s negative control "
|
||||
"working as intended. Line: "
|
||||
<< window.line;
|
||||
} else {
|
||||
// Recorded, not asserted: on this arm the number is whatever the driver's adoption
|
||||
// decision makes it, and it is the figure MEASUREMENTS wants beside the split one.
|
||||
RecordProperty("persistent_map_push_note",
|
||||
"recorded only - this lane declares no emulated arm");
|
||||
}
|
||||
|
||||
unsigned int vbo = store.vbo;
|
||||
|
||||
Reference in New Issue
Block a user