mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 05:08:31 +09:00
164 lines
9.0 KiB
C++
164 lines
9.0 KiB
C++
// MobileGL - MobileGL/MG_Pipe/MGPipe.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
|
|
#include <Includes.h>
|
|
|
|
#include "MGPipeCallbacks.h"
|
|
#include "MGPipeHandles.h"
|
|
#include "MGPipeHostSpan.h"
|
|
#include "MGPipeTypes.h"
|
|
|
|
// The MGPipe boundary (plan B section 4).
|
|
//
|
|
// The two interface tables are FUNCTION-POINTER STRUCTS, not virtual bases. Three reasons
|
|
// out of this repository rather than out of gallium: the boundary already is a
|
|
// function-pointer struct sitting on one hook point in MG_Backend/Init.cpp; a nullptr entry
|
|
// already means "not implemented, frontend falls back", which is exactly what a
|
|
// not-yet-migrated subsystem needs to say while it keeps pulling; and MG_Test already
|
|
// substitutes this table to mock a backend. The rare EGL and caps surface stays on
|
|
// pActiveBackendObject's virtual functions.
|
|
namespace MobileGL::MG_Pipe {
|
|
// Unscoped on purpose: PipeCalls.def spells these as bare tokens so the same file can
|
|
// be read by the C++ preprocessor and by scripts/gen_pipe.py.
|
|
enum MGPipeCallClass : Uint8 {
|
|
kScreen,
|
|
kCtxCso,
|
|
kCtxState,
|
|
kCtxObject,
|
|
kCtxVerb,
|
|
kCtxQuery,
|
|
kCallClassCount,
|
|
};
|
|
|
|
enum MGPipeCallFlags : Uint32 {
|
|
kNone = 0,
|
|
// The caller must not proceed until the server has acknowledged. Rare by design.
|
|
kNeedsAck = 1u << 0,
|
|
// Carries an MGPBlobRef.
|
|
kHasBlob = 1u << 1,
|
|
// Carries a variable-length array after the fixed payload.
|
|
kVarTail = 1u << 2,
|
|
// Carries an MGHostSpan - the one shape that changes with the transport.
|
|
kHostSpan = 1u << 3,
|
|
// Answers into an MGPReplySlot; never blocks.
|
|
kReplySlot = 1u << 4,
|
|
// May be null in a backend's table. A null entry is a real answer ("this backend
|
|
// does not implement it"), not an error: DirectVulkan deliberately leaves
|
|
// buffer_subdata_resident unregistered, and SetSwapInterval likewise.
|
|
kOptional = 1u << 5,
|
|
};
|
|
|
|
// The pipeline/dynamic split of RenderStateParameters, defined exactly once (section
|
|
// 4.5.2): MG_Pipe/MGPipeRenderStateSpans.{h,cpp}, which landed with P2 and computes
|
|
// every chunk boundary with offsetof. Include that header to use it; what stays here
|
|
// is the generated member list at the bottom of this file, which is what the chunk
|
|
// table was derived from.
|
|
|
|
// ---- MOBILEGL_PIPE_PUSH's runtime bitmask (Config.h Features.PipePush) ----
|
|
//
|
|
// One bit per SUBSYSTEM, so an A/B is per subsystem rather than all-or-nothing, and
|
|
// bit 63 for the one BEHAVIOUR the design has to be measured against. Bits are
|
|
// allocated in ROADMAP order and never reused: an operator's recorded 0x7f has to keep
|
|
// meaning what it meant.
|
|
//
|
|
// A clear subsystem bit means "keep pulling", which after P2 is only a valid control
|
|
// while MOBILEGL_PIPE_LEGACY_MEMOS compiles the pre-handle arm beside it.
|
|
inline constexpr Uint64 kMGPipeSubsystemRenderState = 1ull << 0;
|
|
inline constexpr Uint64 kMGPipeSubsystemPixelPack = 1ull << 1;
|
|
inline constexpr Uint64 kMGPipeSubsystemPatchState = 1ull << 2;
|
|
inline constexpr Uint64 kMGPipeSubsystemVertexAttribDefaults = 1ull << 3;
|
|
inline constexpr Uint64 kMGPipeSubsystemResidualValues = 1ull << 4;
|
|
inline constexpr Uint64 kMGPipeSubsystemEsprytSlots = 1ull << 5; // Track H, Espryt 0b
|
|
inline constexpr Uint64 kMGPipeSubsystemMagmaVertexInput = 1ull << 6; // Track H, Magma subsystem 4
|
|
// P3a's two. Resources is the seven BufferBackendOps hooks turned into the handle-shaped
|
|
// resource_* family; VertexInput is vertex elements, vertex buffers and the index buffer.
|
|
// They are separate bits because they are separate A/Bs: a buffer path that regressed and
|
|
// a vertex path that regressed are different findings, and clearing one must not disarm
|
|
// the other.
|
|
inline constexpr Uint64 kMGPipeSubsystemResources = 1ull << 7;
|
|
inline constexpr Uint64 kMGPipeSubsystemVertexInput = 1ull << 8;
|
|
// P4a's four. FOUR AND NOT ONE, for P3a's reason one level out: a framebuffer path that
|
|
// regressed, a texture path that regressed, a sampler path that regressed and a program
|
|
// path that regressed are four different findings, and clearing one must not disarm the
|
|
// other three.
|
|
//
|
|
// THREE OF THEM HAVE A DEPENDENCY and it is diagnosed at the first use, never half-run -
|
|
// one Resolve<Family>SubsystemArm per family beside the backend's existing
|
|
// ResolveResourceSubsystemArm, modelled on the bit-8-requires-bit-7 refusal it already
|
|
// ships, and lazy rather than at bring-up because a pre-flight child dying on a signal
|
|
// makes a whole lane SKIP green: bit 11 requires bit 10 because
|
|
// every MGPBoundView::Texture and MGPImageView::Res names a Texture handle and only bit 10
|
|
// puts one in the slot table; bit 9 requires bit 10 because MGPSurface::Res does; and bit
|
|
// 10 requires bit 7 because a buffer texture's BufferForTexBuffer names a Buffer handle.
|
|
// The mirror pairs (10 without 11, 10 without 9, 7 without 10) are all fine, and are
|
|
// stated as such because an unreachable branch that says something different is how the
|
|
// reachable one drifts. Bit 12 depends on nothing.
|
|
inline constexpr Uint64 kMGPipeSubsystemFramebuffer = 1ull << 9; // set_framebuffer_state
|
|
inline constexpr Uint64 kMGPipeSubsystemTextureResources = 1ull << 10; // texture + renderbuffer
|
|
// resource_*, set_texture_params
|
|
inline constexpr Uint64 kMGPipeSubsystemSamplers = 1ull << 11; // sampler CSO, sampler view,
|
|
// the three unit sets
|
|
inline constexpr Uint64 kMGPipeSubsystemPrograms = 1ull << 12; // shader CSO, draw/dispatch
|
|
// program, global constants
|
|
// bits 13..62 reserved for the later phases, allocated in ROADMAP order.
|
|
// 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. This is
|
|
// the negative control the whole CSO design is measured against (ROADMAP.md P2).
|
|
inline constexpr Uint64 kMGPipeBehaviourNoCsoContentAddressing = 1ull << 63;
|
|
// The default of a push build with the knob unset (ConfigLoader.cpp). Each phase's
|
|
// constant STAYS, because it is the A/B control for the phase after it: P3a's
|
|
// "everything P2 had and nothing of mine" arm is spelled MOBILEGL_PIPE_PUSH=0x7f.
|
|
inline constexpr Uint64 kMGPipeSubsystemsMigratedAtP2 = 0x7full; // bits 0..6
|
|
inline constexpr Uint64 kMGPipeSubsystemsMigratedAtP3a = 0x1ffull; // bits 0..8
|
|
// P4a's, and the two above are NOT edited: 0x1ff is P4a's T2 arm and its "everything P3a
|
|
// had and nothing of mine" control, exactly as 0x7f was P3a's.
|
|
inline constexpr Uint64 kMGPipeSubsystemsMigratedAtP4a = 0x1fffull; // bits 0..12
|
|
static_assert(kMGPipeSubsystemsMigratedAtP4a ==
|
|
(kMGPipeSubsystemsMigratedAtP3a | kMGPipeSubsystemFramebuffer |
|
|
kMGPipeSubsystemTextureResources | kMGPipeSubsystemSamplers |
|
|
kMGPipeSubsystemPrograms),
|
|
"the P4a phase constant and P4a's four subsystem bits have drifted");
|
|
|
|
// The catalogue itself. Only macros, so it is safe to expand inside the namespace, and
|
|
// consumers (the unit test, later the transport) get MGP_CALL_LIST from this header.
|
|
#include "PipeCalls.def"
|
|
|
|
// G1: the two interface tables. A null entry means "not implemented" (section 4.1).
|
|
#include "generated/PipeTables.inc"
|
|
|
|
// The installed tables. Zero-initialized, so an un-installed MGPipe is every entry
|
|
// null - which is precisely the pre-migration state.
|
|
inline MGPipeScreen gMGPipeScreen{};
|
|
inline MGPipeContext gMGPipeContext{};
|
|
|
|
// G2: monolith thunks. These are what MG_Impl call sites move onto, replacing
|
|
// gBackendFunctionsTable.GL.* one name at a time.
|
|
#include "generated/PipeThunks.inc"
|
|
|
|
// G3: wire records, their size assertions, and the applier's bounds precondition.
|
|
#include "generated/PipeWire.inc"
|
|
|
|
// G4: the MOBILEGL_PIPE_VERIFY field-wise comparators.
|
|
#include "generated/PipeVerify.inc"
|
|
|
|
// G5: PipeInputs field ids and the per-verb poison generations.
|
|
#include "generated/PipeFilled.inc"
|
|
|
|
// G5b: the verb enum (one per GLFunctionsTable entry), the verb classes and their
|
|
// may-read field masks - what MGPipeFillForVerb fills and what a poison build lets a
|
|
// verb read (FillPoints.def).
|
|
#include "generated/PipeFillPoints.inc"
|
|
|
|
// G6: the backend read inventory's coverage table.
|
|
#include "generated/PipeCoverage.inc"
|
|
|
|
// G7: the render-state pipeline subset, by member name.
|
|
#include "generated/PipeSpanTable.inc"
|
|
} // namespace MobileGL::MG_Pipe
|