mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Feat] (Pipe): land the P1 contract - PipeInputsSwitch.h with MGB_CTX, the 63-field PipeInputs block with type-identical accessors, FillPoints.def and its G5b generator, the MOBILEGL_PIPE_PUSH/VERIFY options and the three verify knobs; pull build unchanged
- MG_Pipe/PipeInputsSwitch.h is the strangler switch (ARCHITECTURE.md 9.2): MGB_CTX is the
live GLContext in the pull build and &gPipeInputs under MOBILEGL_PIPE_PUSH, so the pull
arm's pGLContext spelling stays outside MG_Backend/ and purity gate C's grep.
- MG_Backend/MGPipe/PipeInputs.h holds one struct with every accessor a backend reads (63:
the 61 Coverage.def rows plus GetBoundTransformFeedbackLifetimeId and
HasOpenTransformFeedbackSpan), each keeping its GLContext name, parameters and return
type so the site conversion is type-neutral; V fields are copied values, O fields are
SharedPtr copies or pointers into the context, the seven F fields forward to the live
context from MG_Impl/Pipe/PipeFill.cpp and are the only sticky ones (Coverage.def's
MGP_COVERAGE_STICKY_LIST argues each: argument-keyed lookups and reverse-channel writes,
never a version or generation counter).
- MG_Pipe/FillPoints.def is the verb table: one row per GLFunctionsTable function pointer in
declaration order (69), nine classes and the may-read field rows; gen_pipe.py parses the
struct and refuses a row set that is not exactly its member set, then emits
generated/PipeFillPoints.inc (verb enum, class tables, per-class field masks with the
sticky fields OR'ed in). MGP_FILL(Verb) in MG_Impl/Pipe/PipeFill.h is the fill point;
MGPipeFillForVerb only bumps the serial, records the verb and stamps the sticky fields
here - the per-class copies land in the next commit, the fill points in MG_Impl after.
- MOBILEGL_PIPE_POISON is derived once in PipeInputs.h from MOBILEGL_PIPE_PUSH and the DEBUG
level, MOBILEGL_BUILD_DISAGGREGATED or MOBILEGL_PIPE_VERIFY (the tree has no
MOBILEGL_DEBUG); under it every accessor is a read-side freshness check that aborts with
Fatal{UnmigratedPipeInput, "Field@Verb"}.
- CMake: MOBILEGL_PIPE_PUSH and MOBILEGL_PIPE_VERIFY options (VERIFY forces PUSH on), the two
new sources appended only under PUSH, the compile definitions; Config.h/ConfigLoader.cpp
gain PipeVerifyFatal / PipeVerifyCorrupt / PipePoisonOmit under #if MOBILEGL_PIPE_PUSH so
the pull build's FeaturesTable does not change size.
- Pull build proof: symbol_report.py against the 087685d1 baseline reports 0 added / 0
removed / 0 resized / 0 renamed and a .text delta of 0; ctest -N names unchanged; gen_pipe
--check clean; unit tests green in the pull, push and verify builds.
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
// MobileGL - MobileGL/MG_Impl/Pipe/PipeFill.cpp
|
||||
// Copyright (c) 2025-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
|
||||
|
||||
// The client side of the PipeInputs block (ARCHITECTURE.md 9.2 phase A): the only place in
|
||||
// the push arm that reads MG_State::pGLContext. Holds the per-verb filler, the F-class
|
||||
// forwarders and IsLive. Compiled only under MOBILEGL_PIPE_PUSH (CMakeLists.txt appends it
|
||||
// to SOURCE_FILES there).
|
||||
//
|
||||
// Contract commit (P1 c1): the filler bumps the verb serial, records the verb and the
|
||||
// context identity, and stamps the seven sticky fields once; the per-class field copies and
|
||||
// stamps land in c2, the verify snapshot and comparator in c4.
|
||||
#include <MG_State/GLState/Core.h>
|
||||
#include <MG_Backend/MGPipe/PipeInputs.h>
|
||||
#include <Config.h>
|
||||
|
||||
namespace MobileGL::MG_Pipe {
|
||||
namespace {
|
||||
MG_State::GLState::GLContext* LiveContext() { return MG_State::pGLContext.get(); }
|
||||
|
||||
template <class T>
|
||||
const SharedPtr<T>& NullShared() {
|
||||
static const SharedPtr<T> null;
|
||||
return null;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// ---- liveness ----
|
||||
Bool PipeInputs::IsLive() const { return LiveContext() != nullptr; }
|
||||
|
||||
// ---- the seven F-class forwarders ----
|
||||
SizeT PipeInputs::GetBufferBindingPointCount(BufferTarget target) const {
|
||||
const auto* ctx = LiveContext();
|
||||
return ctx != nullptr ? ctx->GetBufferBindingPointCount(target) : 0;
|
||||
}
|
||||
|
||||
const SharedPtr<PipeInputs::ProgramObject>& PipeInputs::GetProgramObject(Uint index) {
|
||||
auto* ctx = LiveContext();
|
||||
return ctx != nullptr ? ctx->GetProgramObject(index) : NullShared<ProgramObject>();
|
||||
}
|
||||
|
||||
const SharedPtr<PipeInputs::ITextureObject>& PipeInputs::GetTextureObject(Uint index) {
|
||||
auto* ctx = LiveContext();
|
||||
return ctx != nullptr ? ctx->GetTextureObject(index) : NullShared<ITextureObject>();
|
||||
}
|
||||
|
||||
Bool PipeInputs::HasOpenTransformFeedbackSpan(Uint64 lifetimeId) const {
|
||||
const auto* ctx = LiveContext();
|
||||
return ctx != nullptr && ctx->HasOpenTransformFeedbackSpan(lifetimeId);
|
||||
}
|
||||
|
||||
void PipeInputs::InvalidateCompileEnv() {
|
||||
if (auto* ctx = LiveContext()) ctx->InvalidateCompileEnv();
|
||||
}
|
||||
|
||||
Bool PipeInputs::ValidateProgramName(Uint index) const {
|
||||
const auto* ctx = LiveContext();
|
||||
return ctx != nullptr && ctx->ValidateProgramName(index);
|
||||
}
|
||||
|
||||
void PipeInputs::RecordError(ErrorCode code, UniquePtr<ErrorInfo> info) {
|
||||
auto* ctx = LiveContext();
|
||||
if (ctx == nullptr) {
|
||||
MGLOG_E_ONCE("PipeInputs::RecordError: no live context, dropping error %d", static_cast<int>(code));
|
||||
return;
|
||||
}
|
||||
ctx->RecordError(code, Move(info));
|
||||
}
|
||||
|
||||
// ---- the filler ----
|
||||
void MGPipeFillForVerb(MGPipeVerb verb) {
|
||||
PipeInputs& inputs = gPipeInputs;
|
||||
#if MOBILEGL_PIPE_POISON
|
||||
// Starts at 1, so FilledGen == 0 means "never filled".
|
||||
++inputs.m_filled.CurrentVerbSerial;
|
||||
#endif
|
||||
inputs.m_currentVerb = verb;
|
||||
auto* ctx = LiveContext();
|
||||
if (ctx == nullptr) {
|
||||
inputs.m_live = false;
|
||||
inputs.m_contextIdentity = nullptr;
|
||||
return;
|
||||
}
|
||||
inputs.m_live = true;
|
||||
inputs.m_contextIdentity = ctx;
|
||||
#if MOBILEGL_PIPE_POISON
|
||||
// The sticky (forwarded) fields are stamped once by the first fill that sees a live
|
||||
// context and stay fresh through the Sticky -> FilledGen != 0 branch of
|
||||
// MGPipeInputFieldIsFresh.
|
||||
for (SizeT i = 0; i < kMGPipeInputFieldCount; ++i) {
|
||||
if (kMGPipeInputFieldSticky[i] && inputs.m_filled.FilledGen[i] == 0) inputs.m_filled.FilledGen[i] = 1;
|
||||
}
|
||||
#endif
|
||||
// c2: copy and stamp every field in kMGPipeClassFieldMask[kMGPipeVerbClass[verb]].
|
||||
}
|
||||
} // namespace MobileGL::MG_Pipe
|
||||
@@ -0,0 +1,27 @@
|
||||
// MobileGL - MobileGL/MG_Impl/Pipe/PipeFill.h
|
||||
// Copyright (c) 2025-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
|
||||
|
||||
#pragma once
|
||||
// The fill point (ARCHITECTURE.md 9.2, P1 brief D7). MG_Impl spells MGP_FILL(Verb); as the
|
||||
// statement immediately before every call through gBackendFunctionsTable.GL - after every
|
||||
// early return the call is behind, inside the loop body for a call made in a loop - so the
|
||||
// frontend fills the PipeInputs block for exactly the verbs that reach a backend. In the
|
||||
// pull build the macro is ((void)0) and the pull build is byte-identical to a tree without
|
||||
// it.
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
#include <MG_Pipe/MGPipe.h>
|
||||
namespace MobileGL::MG_Pipe {
|
||||
// PipeFill.cpp. Bumps the per-verb serial, records the verb, and (from c2 on) copies
|
||||
// every field in the verb class's may-read mask out of the live GLContext, stamping each
|
||||
// with the new serial.
|
||||
void MGPipeFillForVerb(MGPipeVerb verb);
|
||||
} // namespace MobileGL::MG_Pipe
|
||||
#define MGP_FILL(Verb) ::MobileGL::MG_Pipe::MGPipeFillForVerb(::MobileGL::MG_Pipe::MGPipeVerb::Verb)
|
||||
#else
|
||||
#define MGP_FILL(Verb) ((void)0)
|
||||
#endif
|
||||
Reference in New Issue
Block a user