mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 18:13:23 +09:00
[Feat] (P13 W3b): subsystem bits 0-13 are fixed on and refused by name at startup, the legacy-memo and texel-retain knobs are gone
This commit is contained in:
+4
-9
@@ -370,6 +370,10 @@ namespace MobileGL::MG_Config {
|
||||
// 1<<63 NOT a subsystem, a BEHAVIOUR: turn OFF client-side content addressing of
|
||||
// CSOs, so every pipeline-version change mints a fresh CSO and the map is
|
||||
// never probed. The negative control the CSO design is measured against.
|
||||
// P13 W3b (ID-P13-3): bits 0-13 are FIXED ON. Their pre-handle arms are gone, so a mask
|
||||
// that clears one is refused by name at startup (Fatal{PipeSubsystemsFixedOn},
|
||||
// ConfigLoader.cpp); bit 63 is the one switch left. Everything above about "refused,
|
||||
// runs its legacy arm" describes code that is unreachable since then and goes in W6.
|
||||
Uint64 PipePush = 0;
|
||||
// MOBILEGL_PIPE_VERIFY: per-draw, per-FIELD shadow comparison of the pushed state
|
||||
// against a snapshot taken from GLContext the old way, printing the first field
|
||||
@@ -410,15 +414,6 @@ namespace MobileGL::MG_Config {
|
||||
// MOBILEGL_PIPE_STATS: dump the boundary counters (bytes, calls, roundtrips,
|
||||
// texture pulls, upload shapes, residual-block bytes, index mirror bytes).
|
||||
Bool PipeStats = false;
|
||||
// MOBILEGL_PIPE_LEGACY_MEMOS: keep the pre-handle registries and TwinLookupMemos
|
||||
// alive so the first handle waves have a real old-versus-new arm to be compared
|
||||
// against. ON by default for the whole migration window, deleted with the pull
|
||||
// path itself.
|
||||
Bool PipeLegacyMemos = true;
|
||||
// MOBILEGL_PIPE_TEXEL_RETAIN_MB: LRU budget for texels retained against a
|
||||
// server-initiated texture re-send. Default 0, i.e. OFF: MipmapStorage already
|
||||
// holds a complete CPU shadow, so this cache buys latency, never correctness.
|
||||
Uint32 PipeTexelRetainMb = 0;
|
||||
// MOBILEGL_PIPE_INDEX_MIRROR_MB: budget for the server-side index host mirror,
|
||||
// which is what lets primitive-restart rewriting and multi-draw flattening stay on
|
||||
// the server without shipping index bytes per draw. Over budget it degrades to
|
||||
|
||||
@@ -390,6 +390,21 @@ namespace MobileGL::MG_ConfigLoader {
|
||||
// kMGPipeSubsystemsMigratedAtP3a (0x1ff) is the phase-by-phase control - P4a's four
|
||||
// subsystems off, everything P3a landed still on.
|
||||
features.PipePush = QueryEnvUint64("MOBILEGL_PIPE_PUSH", MG_Pipe::kMGPipeSubsystemsMigratedAtP5e);
|
||||
// P13 W3b (ID-P13-3): bits 0-13 are fixed on. The arms a cleared bit used to select
|
||||
// (the pre-handle memos, the pull build's frontend reads) are gone, so a cleared bit has
|
||||
// nothing to run; it is refused here, by name, before any backend is brought up, rather
|
||||
// than discovered as an armless subsystem at its first draw. Bit 63 (CSO content
|
||||
// addressing off) stays a switch.
|
||||
if ((features.PipePush & MG_Pipe::kMGPipeSubsystemsMigratedAtP5e) !=
|
||||
MG_Pipe::kMGPipeSubsystemsMigratedAtP5e) {
|
||||
MGLOG_F("MGPipe: Fatal{PipeSubsystemsFixedOn, \"MOBILEGL_PIPE_PUSH=0x%llx clears subsystem "
|
||||
"bit(s) 0x%llx; bits 0-13 are fixed on since P13 - only bit 63 may be set or "
|
||||
"cleared\"}",
|
||||
static_cast<unsigned long long>(features.PipePush),
|
||||
static_cast<unsigned long long>(MG_Pipe::kMGPipeSubsystemsMigratedAtP5e &
|
||||
~features.PipePush));
|
||||
std::abort();
|
||||
}
|
||||
features.PipeVerify = QueryEnvFlag("MOBILEGL_PIPE_VERIFY");
|
||||
// Defaults ON: read as a tri-state so only an explicitly falsy value turns it off.
|
||||
features.PipeVerifyFatal =
|
||||
@@ -398,12 +413,6 @@ namespace MobileGL::MG_ConfigLoader {
|
||||
QueryEnvVariable("MOBILEGL_PIPE_POISON_OMIT", features.PipePoisonOmit, "");
|
||||
features.PipeHandleAbaControl = QueryEnvFlag("MOBILEGL_PIPE_HANDLE_ABA_CONTROL");
|
||||
features.PipeStats = QueryEnvFlag("MOBILEGL_PIPE_STATS");
|
||||
// Defaults ON, so the flag has to be read as a tri-state rather than as a plain
|
||||
// truthy check: unset must keep the memos, and only an explicitly falsy value may
|
||||
// drop them.
|
||||
features.PipeLegacyMemos =
|
||||
QueryEnvQuirkOverride("MOBILEGL_PIPE_LEGACY_MEMOS") != MG_Config::QuirkOverride::ForceOff;
|
||||
features.PipeTexelRetainMb = QueryEnvUint32("MOBILEGL_PIPE_TEXEL_RETAIN_MB", 0, 0, 4096);
|
||||
features.PipeIndexMirrorMb = QueryEnvUint32("MOBILEGL_PIPE_INDEX_MIRROR_MB", 64, 0, 4096);
|
||||
features.PipeStatsPeriod = QueryEnvUint32("MOBILEGL_PIPE_STATS_PERIOD", 120, 1, 1000000);
|
||||
QueryEnvVariable("MOBILEGL_PIPE_STATS_FILE", features.PipeStatsFile, "");
|
||||
|
||||
@@ -476,7 +476,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
EsprytSlotArmVerdict CurrentEsprytSlotArmVerdict() {
|
||||
return ClassifyEsprytSlotArm(
|
||||
(MG_Config::Features.PipePush & MG_Pipe::kMGPipeSubsystemEsprytSlots) != 0,
|
||||
MG_Config::Features.PipeLegacyMemos);
|
||||
/*legacyMemosEnabled=*/true);
|
||||
}
|
||||
|
||||
void DiagnoseEsprytSlotArm() {
|
||||
@@ -3317,7 +3317,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// and NoArm is unreachable for it. Said out loud rather than assumed, because the
|
||||
// knob is still answered below.
|
||||
const PipeSubsystemArmVerdict verdict =
|
||||
ClassifyPipeSubsystemArm(bitSet, MG_Config::Features.PipeLegacyMemos,
|
||||
ClassifyPipeSubsystemArm(bitSet, /*legacyMemosEnabled=*/true,
|
||||
/*legacyArmSurvivesLegacyMemos=*/true);
|
||||
// Unreachable for this family by the argument above, and stated as a stop anyway:
|
||||
// the two P3a families answer an armless verdict the same way, and an unreachable
|
||||
@@ -3326,11 +3326,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
StopOnArmlessPipeSubsystem("MOBILEGL_PIPE_PUSH leaves kMGPipeSubsystemResources "
|
||||
"(bit 7) clear and the pre-handle buffer arm is gone");
|
||||
}
|
||||
if (verdict == PipeSubsystemArmVerdict::Legacy && !MG_Config::Features.PipeLegacyMemos) {
|
||||
MGLOG_W("MGPipe: MOBILEGL_PIPE_PUSH leaves kMGPipeSubsystemResources (bit 7) clear while "
|
||||
"MOBILEGL_PIPE_LEGACY_MEMOS=0 asks for the pre-handle arms to be gone; the buffer "
|
||||
"ops table is compiled unconditionally, so the LEGACY arm is what this process runs");
|
||||
}
|
||||
const Bool enabled = verdict == PipeSubsystemArmVerdict::Handles;
|
||||
MGLOG_D("MGPipe: Espryt resource family runs the %s arm", enabled ? "handle" : "legacy");
|
||||
return enabled;
|
||||
@@ -3363,7 +3358,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// Unlike the buffer family, this one's legacy arm IS conditional: the pre-handle
|
||||
// SyncToBackend body and the twin memos it reads are inside MOBILEGL_PIPE_LEGACY_MEMOS.
|
||||
const PipeSubsystemArmVerdict verdict =
|
||||
ClassifyPipeSubsystemArm(bitSet, MG_Config::Features.PipeLegacyMemos,
|
||||
ClassifyPipeSubsystemArm(bitSet, /*legacyMemosEnabled=*/true,
|
||||
/*legacyArmSurvivesLegacyMemos=*/false);
|
||||
if (verdict != PipeSubsystemArmVerdict::Handles &&
|
||||
(verdict == PipeSubsystemArmVerdict::NoArm || !kLegacyVaoArmCompiled)) {
|
||||
@@ -4942,7 +4937,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
}
|
||||
const BufferImpl::PipeSubsystemArmVerdict verdict = BufferImpl::ClassifyPipeSubsystemArm(
|
||||
bitSet && !refused, MG_Config::Features.PipeLegacyMemos,
|
||||
bitSet && !refused, /*legacyMemosEnabled=*/true,
|
||||
/*legacyArmSurvivesLegacyMemos=*/false);
|
||||
if (verdict == BufferImpl::PipeSubsystemArmVerdict::NoArm) {
|
||||
BufferImpl::StopOnArmlessPipeSubsystem(
|
||||
@@ -4986,7 +4981,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
"kMGPipeSubsystemTextureResources (bit 10)");
|
||||
}
|
||||
const BufferImpl::PipeSubsystemArmVerdict verdict = BufferImpl::ClassifyPipeSubsystemArm(
|
||||
bitSet && !refused, MG_Config::Features.PipeLegacyMemos,
|
||||
bitSet && !refused, /*legacyMemosEnabled=*/true,
|
||||
/*legacyArmSurvivesLegacyMemos=*/false);
|
||||
if (verdict == BufferImpl::PipeSubsystemArmVerdict::NoArm) {
|
||||
BufferImpl::StopOnArmlessPipeSubsystem(
|
||||
@@ -5022,7 +5017,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
"kMGPipeSubsystemSamplers (bit 11)");
|
||||
}
|
||||
const BufferImpl::PipeSubsystemArmVerdict verdict = BufferImpl::ClassifyPipeSubsystemArm(
|
||||
bitSet && !refused, MG_Config::Features.PipeLegacyMemos,
|
||||
bitSet && !refused, /*legacyMemosEnabled=*/true,
|
||||
/*legacyArmSurvivesLegacyMemos=*/false);
|
||||
if (verdict == BufferImpl::PipeSubsystemArmVerdict::NoArm) {
|
||||
BufferImpl::StopOnArmlessPipeSubsystem(
|
||||
@@ -5053,7 +5048,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// specialises on (D-H5) are read from state this backend already holds.
|
||||
const Bool bitSet = (MG_Config::Features.PipePush & MG_Pipe::kMGPipeSubsystemPrograms) != 0;
|
||||
const BufferImpl::PipeSubsystemArmVerdict verdict = BufferImpl::ClassifyPipeSubsystemArm(
|
||||
bitSet, MG_Config::Features.PipeLegacyMemos, /*legacyArmSurvivesLegacyMemos=*/false);
|
||||
bitSet, /*legacyMemosEnabled=*/true, /*legacyArmSurvivesLegacyMemos=*/false);
|
||||
if (verdict == BufferImpl::PipeSubsystemArmVerdict::NoArm) {
|
||||
BufferImpl::StopOnArmlessPipeSubsystem(
|
||||
"MOBILEGL_PIPE_PUSH leaves kMGPipeSubsystemPrograms (bit 12) clear and "
|
||||
|
||||
@@ -79,8 +79,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// there is a correct answer (the state hash) where for bits 5/6 there is none - but it no
|
||||
// longer does it SILENTLY: the combination is named once, at startup, right here.
|
||||
inline void MagmaPipeValidateSubsystemConfiguration() {
|
||||
if (!MG_Config::Features.PipeLegacyMemos &&
|
||||
!MagmaPipeSubsystemOn(MG_Pipe::kMGPipeSubsystemRenderState)) {
|
||||
if (!MagmaPipeSubsystemOn(MG_Pipe::kMGPipeSubsystemRenderState)) {
|
||||
MGLOG_W("MGPipe: MOBILEGL_PIPE_LEGACY_MEMOS=0 with kMGPipeSubsystemRenderState (bit 0 "
|
||||
"of MOBILEGL_PIPE_PUSH) clear - Magma's pipeline memo has no CSO handle to key "
|
||||
"on, so every draw whose pipeline-state version moved runs the pre-handle STATE "
|
||||
|
||||
@@ -83,7 +83,8 @@
|
||||
X(ClientTablesUninstalled, ProtocolCorruption, "the applier ran before the client installed its tables") \
|
||||
X(NoClientSession, ProtocolCorruption, "a path that needs the client session ran without one") \
|
||||
X(UnnamedIdentity, ProtocolCorruption, "a per-context memo was consulted with a null context identity") \
|
||||
X(PipeLegacyMemosDisabled, ProtocolCorruption, "a subsystem bit is clear and this build compiles no legacy arm to fall back to") \
|
||||
X(PipeLegacyMemosDisabled, ProtocolCorruption, "a subsystem bit is clear and this build compiles no legacy arm to fall back to (unreachable since P13 W3b fixed bits 0-13 on)") \
|
||||
X(PipeSubsystemsFixedOn, ProtocolCorruption, "MOBILEGL_PIPE_PUSH cleared one of subsystem bits 0-13, which P13 fixed on") \
|
||||
X(PipeVerifyBadKnob, ProtocolCorruption, "a MOBILEGL_PIPE_VERIFY/POISON knob named a verb or field that does not exist") \
|
||||
X(PipeVerifyDiffer, ProtocolCorruption, "the verify comparator found a pushed field differing from the live one") \
|
||||
X(UnexpectedMapAccept, ProtocolCorruption, "a persistent-map accept arrived where the protocol permits none") \
|
||||
|
||||
@@ -184,19 +184,9 @@ TEST(SubsystemDepsTest, TheClientNeverEmitsAFamilyTheTableRefuses) {
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
TEST(SubsystemDepsTest, TheServerConsumerGateNeverArmsAFamilyTheTableRefuses) {
|
||||
using namespace MobileGL::MG_Backend::DirectGLES;
|
||||
// THE RESOLVERS SURVIVE A SWEEP ONLY BECAUSE LEGACY MEMOS ARE ON. Each of them ends in
|
||||
// ClassifyPipeSubsystemArm, and a verdict of NoArm calls StopOnArmlessPipeSubsystem
|
||||
// (Managers.cpp:2928-2938), which aborts the process - that is the intended behaviour for a
|
||||
// configuration with neither the handle arm nor the legacy arm, and it would turn this
|
||||
// mask sweep into a crash rather than a failure. MOBILEGL_PIPE_LEGACY_MEMOS defaults ON
|
||||
// (Config.h:399) and nothing in the unit lane clears it, so the legacy arm always survives
|
||||
// and every resolver returns rather than stopping. Asserted rather than assumed, because the
|
||||
// day that default flips this file would abort with no explanation.
|
||||
ASSERT_TRUE(MG_Config::Features.PipeLegacyMemos)
|
||||
<< "MOBILEGL_PIPE_LEGACY_MEMOS is clear, so a resolver whose handle arm this sweep "
|
||||
"deliberately refuses has NO arm left and StopOnArmlessPipeSubsystem will abort the "
|
||||
"process instead of returning false. Run this case with the legacy memos on, or teach "
|
||||
"it to skip the masks that leave a family armless.";
|
||||
// THE RESOLVERS SURVIVE A SWEEP because a refused family takes the (unreachable since P13 W3b)
|
||||
// legacy verdict and returns false instead of stopping; ConfigLoader refuses any such mask at
|
||||
// startup, so this sweep exercises the resolvers' own logic, not a reachable configuration.
|
||||
struct Resolver {
|
||||
const char* Name;
|
||||
Uint64 Family;
|
||||
@@ -234,8 +224,6 @@ TEST(SubsystemDepsTest, TheServerConsumerGateNeverArmsAFamilyTheTableRefuses) {
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
TEST(SubsystemDepsTest, TheTwoDocumentedRefusalLanesStillRefuseAndTheFullMaskStillArms) {
|
||||
using namespace MobileGL::MG_Backend::DirectGLES;
|
||||
ASSERT_TRUE(MG_Config::Features.PipeLegacyMemos)
|
||||
<< "see the sweep above: a refused family with the legacy arm also off aborts the process";
|
||||
{
|
||||
PushMaskScope scope(kMGPipeSubsystemsMigratedAtP5e);
|
||||
EXPECT_TRUE(ResolveTextureResourceSubsystemArm())
|
||||
|
||||
@@ -3694,29 +3694,6 @@ namespace {
|
||||
std::string m_previous;
|
||||
};
|
||||
|
||||
// Sets the two knobs into the combination that leaves no twin-table arm at all -
|
||||
// kMGPipeSubsystemEsprytSlots clear and PipeLegacyMemos false, which is what
|
||||
// MOBILEGL_PIPE_PUSH=0 MOBILEGL_PIPE_LEGACY_MEMOS=0 in the environment produces - and
|
||||
// restores MG_Config::Features on every exit path.
|
||||
struct ScopedArmlessKnobPair {
|
||||
ScopedArmlessKnobPair():
|
||||
m_savedPush(MobileGL::MG_Config::Features.PipePush),
|
||||
m_savedLegacy(MobileGL::MG_Config::Features.PipeLegacyMemos) {
|
||||
MobileGL::MG_Config::Features.PipePush =
|
||||
m_savedPush & ~MobileGL::MG_Pipe::kMGPipeSubsystemEsprytSlots;
|
||||
MobileGL::MG_Config::Features.PipeLegacyMemos = false;
|
||||
}
|
||||
~ScopedArmlessKnobPair() {
|
||||
MobileGL::MG_Config::Features.PipePush = m_savedPush;
|
||||
MobileGL::MG_Config::Features.PipeLegacyMemos = m_savedLegacy;
|
||||
}
|
||||
ScopedArmlessKnobPair(const ScopedArmlessKnobPair&) = delete;
|
||||
ScopedArmlessKnobPair& operator=(const ScopedArmlessKnobPair&) = delete;
|
||||
|
||||
private:
|
||||
MobileGL::Uint64 m_savedPush;
|
||||
MobileGL::Bool m_savedLegacy;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// The property the whole slice exists for. The pre-P2 registry keyed twins on the frontend heap
|
||||
@@ -4642,115 +4619,6 @@ TEST(DirectGLESSlotTable, ASavedCopyOfARealRegistryDropsTheTwinOnTheSameNotice)
|
||||
EXPECT_FALSE(registry.DestroyByLifetimeId(0)) << "sanity: a null id frees nothing";
|
||||
}
|
||||
|
||||
// The gate on MAJOR 1 of the round-3 review. Commit d89fb684 raised
|
||||
// Fatal{PipeLegacyMemosDisabled} from inside InitDisplayAndContext(), i.e. from inside EGL
|
||||
// bring-up - and the integration harness pre-flights EGL bring-up in a FORKED CHILD, converting
|
||||
// any child that dies on a signal into "no usable GPU/display/ICD" and SKIPPING every scenario.
|
||||
// So `MOBILEGL_PIPE_PUSH=0 MOBILEGL_PIPE_LEGACY_MEMOS=0 ctest -L integration-gpu -R DirectGLES`
|
||||
// reported 100% tests passed while running nothing at all, on the exact pair of env vars the
|
||||
// D14/D18 A/B is driven with. ROADMAP.md:7 forbids a gate that cannot go red for the reason it
|
||||
// exists, and a lane that goes green by skipping is the worst version of that.
|
||||
//
|
||||
// The split this case pins: bring-up DIAGNOSES (and returns), first twin lookup STOPS. It
|
||||
// checks the message and not only the signal, because an operator who is handed a bare
|
||||
// "Subprocess aborted" has been told nothing about which two knobs they set.
|
||||
TEST(DirectGLESSlotTable, AnArmlessKnobCombinationStopsInsteadOfSkippingTheLane) {
|
||||
GTEST_SKIP() << "this build compiles no legacy twin registry, so no knob combination can "
|
||||
"leave the process without an arm";
|
||||
}
|
||||
|
||||
// The two guards the armless cases stand on, pinned on their own: whatever an operator had in
|
||||
// MOBILEGL_LOG_FILE_PATH - a path, or nothing - and whatever MG_Config::Features held are back,
|
||||
// byte for byte, once the guards go out of scope, with or without a failure inside. Before
|
||||
// this the armless case unset the variable for every later case in the binary and restored
|
||||
// the config only on its success path (the round-4 review's minor 5).
|
||||
TEST(DirectGLESSlotTable, TheArmlessCasesLeaveTheLogPathAndTheConfigAsTheyFoundThem) {
|
||||
using namespace MobileGL;
|
||||
|
||||
const Uint64 push = MG_Config::Features.PipePush;
|
||||
const Bool legacy = MG_Config::Features.PipeLegacyMemos;
|
||||
std::string previousPath;
|
||||
const bool hadPreviousPath = std::getenv("MOBILEGL_LOG_FILE_PATH") != nullptr;
|
||||
if (hadPreviousPath) previousPath = std::getenv("MOBILEGL_LOG_FILE_PATH");
|
||||
|
||||
// With an operator path in place...
|
||||
const std::filesystem::path operatorPath = UniqueScratchLogPath("mobilegl-espryt-operator");
|
||||
SetEnvVar("MOBILEGL_LOG_FILE_PATH", operatorPath.string().c_str());
|
||||
{
|
||||
const ScopedArmlessKnobPair knobs;
|
||||
const ScopedLogFileRedirect redirect(UniqueScratchLogPath("mobilegl-espryt-guard"));
|
||||
EXPECT_EQ(MG_Config::Features.PipePush & MG_Pipe::kMGPipeSubsystemEsprytSlots, 0ull);
|
||||
EXPECT_FALSE(MG_Config::Features.PipeLegacyMemos);
|
||||
EXPECT_STRNE(std::getenv("MOBILEGL_LOG_FILE_PATH"), operatorPath.string().c_str());
|
||||
}
|
||||
ASSERT_NE(std::getenv("MOBILEGL_LOG_FILE_PATH"), nullptr) << "the operator's log path was unset";
|
||||
EXPECT_STREQ(std::getenv("MOBILEGL_LOG_FILE_PATH"), operatorPath.string().c_str());
|
||||
EXPECT_EQ(MG_Config::Features.PipePush, push);
|
||||
EXPECT_EQ(MG_Config::Features.PipeLegacyMemos, legacy);
|
||||
|
||||
// ...and with none.
|
||||
UnsetEnvVar("MOBILEGL_LOG_FILE_PATH");
|
||||
{
|
||||
const ScopedLogFileRedirect redirect(UniqueScratchLogPath("mobilegl-espryt-guard"));
|
||||
EXPECT_NE(std::getenv("MOBILEGL_LOG_FILE_PATH"), nullptr);
|
||||
}
|
||||
EXPECT_EQ(std::getenv("MOBILEGL_LOG_FILE_PATH"), nullptr)
|
||||
<< "a log path was left behind where the operator had none";
|
||||
|
||||
if (hadPreviousPath) {
|
||||
SetEnvVar("MOBILEGL_LOG_FILE_PATH", previousPath.c_str());
|
||||
}
|
||||
std::error_code ignored;
|
||||
std::filesystem::remove(operatorPath, ignored);
|
||||
}
|
||||
|
||||
// The round-4 review's minor 4: the case above pins the two FUNCTIONS, and nothing failed if
|
||||
// InitDisplayAndContext() (DirectGLES.cpp) was edited back to call the stopping one - which is
|
||||
// exactly the regression that produced the round-3 major. This pins the CALL SITE, by running
|
||||
// the real bring-up entry point under the armless pair.
|
||||
//
|
||||
// No display is needed: InitDisplayAndContext's twin-arm call is its first statement after
|
||||
// the context teardown, ahead of eglGetDisplay, so an EGL table whose eglGetDisplay answers
|
||||
// EGL_NO_DISPLAY takes bring-up through that call and straight back out with `false`. The
|
||||
// child must then EXIT with the code below. If the site stops again it dies of SIGABRT
|
||||
// instead, and the death test fails - naming both knobs - rather than skipping: in the
|
||||
// integration harness that same abort is what turned into a green lane that ran nothing.
|
||||
//
|
||||
// Not skipped in a build without the legacy arm either: there the verdict is Handles and
|
||||
// bring-up has nothing to diagnose, but it must still return, and this says so.
|
||||
TEST(DirectGLESSlotTable, EglBringUpUnderTheArmlessKnobPairReturnsInsteadOfStopping) {
|
||||
#if defined(_WIN32)
|
||||
GTEST_SKIP() << "needs a forked death test";
|
||||
#else
|
||||
using namespace MobileGL;
|
||||
|
||||
constexpr int kBringUpReturnedFalse = 0x51;
|
||||
constexpr int kBringUpReturnedTrue = 0x52;
|
||||
|
||||
// The redirect is set up in the PARENT: the child inherits the environment and writes the
|
||||
// file, the parent reads it once the child has gone, and the guard restores the operator's
|
||||
// log path either way.
|
||||
const ScopedLogFileRedirect log(UniqueScratchLogPath("mobilegl-espryt-armless-bringup"));
|
||||
|
||||
EXPECT_EXIT(
|
||||
{
|
||||
const ScopedArmlessKnobPair knobs;
|
||||
MG_External::EGLFunctionsTable egl{};
|
||||
egl.eglGetDisplay = +[](EGLNativeDisplayType) -> EGLDisplay { return EGL_NO_DISPLAY; };
|
||||
MG_Backend::DirectGLES::SetEGLFuncsTable(egl);
|
||||
const Bool ok = MG_Backend::DirectGLES::InitPbufferSurface(1, 1);
|
||||
MG_Util::Debug::Close();
|
||||
std::exit(ok ? kBringUpReturnedTrue : kBringUpReturnedFalse);
|
||||
},
|
||||
::testing::ExitedWithCode(kBringUpReturnedFalse), "")
|
||||
<< "EGL bring-up under MOBILEGL_PIPE_PUSH with kMGPipeSubsystemEsprytSlots clear and "
|
||||
"MOBILEGL_PIPE_LEGACY_MEMOS=0 did not RETURN: InitDisplayAndContext() is stopping "
|
||||
"on the armless knob pair again instead of diagnosing it, and the integration "
|
||||
"harness's forked pre-flight turns that stop into a lane that skips every scenario";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// P3a REWORK C-1's gate, and the case that would have caught it.
|
||||
//
|
||||
// A persistently mapped buffer whose store was NOT adopted - under the 16 MiB threshold, or
|
||||
|
||||
@@ -80,8 +80,8 @@ int main() {
|
||||
ExpectSplit(";;A=1;;B=2;;", {"A=1", "B=2"});
|
||||
ExpectSplit(";", {});
|
||||
// The values the plan's knobs actually carry: a path, a size, a comma list.
|
||||
ExpectSplit("MOBILEGL_PIPE_TEXEL_RETAIN_MB=64;MOBILEGL_LOG_FILE_PATH=/sdcard/MG/a.log",
|
||||
{"MOBILEGL_PIPE_TEXEL_RETAIN_MB=64", "MOBILEGL_LOG_FILE_PATH=/sdcard/MG/a.log"});
|
||||
ExpectSplit("MOBILEGL_PIPE_INDEX_MIRROR_MB=64;MOBILEGL_LOG_FILE_PATH=/sdcard/MG/a.log",
|
||||
{"MOBILEGL_PIPE_INDEX_MIRROR_MB=64", "MOBILEGL_LOG_FILE_PATH=/sdcard/MG/a.log"});
|
||||
|
||||
// Classification.
|
||||
ExpectParse("MOBILEGL_PIPE_PUSH=1", EnvOverrideAction::Set, "MOBILEGL_PIPE_PUSH", "1");
|
||||
|
||||
Reference in New Issue
Block a user