mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 21:28:32 +09:00
- Plan B section 4 makes the frontend/backend boundary explicit and gives the backend its
own state machine. This is the P0 deliverable of section 11: the whole catalogue exists
from day one, placeholders included, because the wire opcode is a call's position in
PipeCalls.def and record numbering must never churn.
- MG_Pipe/PipeCalls.def is the single source of truth: 68 unique calls as
X(Name, Payload, Class, Flags). Its header reconciles that number with the plan's
headline counts (section 4.4, appendix A), which double count - "CSO 15" names
bind_sampler_states and set_sampler_views that the "set_* 17" list also names, "screen
14" tabulates the query family that section 4.3 assigns to the context, and the
"transfer 12" row enumerates 11 calls. Each reconciliation is written down next to the
count rather than resolved silently.
- MGPipeHandles.h: the 8-byte {slot, gen} pair, dense per-kind slots, the reserved null
and default-framebuffer handles, and the ShaderCso composite band (sections 4.2, 5.6.3).
The two generations are documented as strictly separate, with the interface rule that no
call may require the client to know MGGen.
- MGPipeTypes.h: every payload of section 4.5 as a flat POD with explicit padding, a
trivial-copyability assertion and an exact sizeof assertion, because the wire records are
memcpy'd and a field silently changing width is a protocol break no test would see.
MGPCaps embeds DynamicBackendParameters by inclusion so a caps field added there needs no
second edit here; its assertion is stated as a composition because that struct still
carries SizeT. ResidualValueBlock is pinned at MGL_RESIDUAL_BLOCK_SIZE 1248, the ratchet
that only ever goes down and reaches static_assert(... == 0) in P13 (section 6.3).
- MGPipeHostSpan.h keeps the one shape that changes with the transport isolated behind one
predictable branch, with the kFromServerIndexMirror sentinel D-B7 needs.
- MGPipeCallbacks.h names the reverse channel as ten callbacks plus the forward terminator
in the context table, replacing 95 poke sites across 17 methods (section 7.1).
- scripts/gen_pipe.py runs G1-G7 off those .def files. G1 asserts each table is EXACTLY its
call count of function pointers; G3 pads every wire record to the stream's 8-byte
granularity and checks size >= sizeof && size <= remaining && size % 8 == 0 before
dispatch, fatally; G4 compares field by field (padding excluded, floats by bits) because
a comparator with false positives is one nobody reads - DirectGLES.cpp says the same
thing about its own memcmp of RenderStateParameters; G5 turns the accessor list into
per-verb poison generations rather than a written-once bitmap, which is the only version
that can see a field left over from the previous draw (section 6.2.2); G6 joins the 477
read points of the vendored backend_read_inventory.md against Coverage.def and reports
0 UNMAPPED (299 to a call, 167 signatures that become handle parameters, 6 reverse
channel, 5 client-resolved); G7 pins the pipeline subset BY MEMBER NAME from what
VulkanRenderer::ComputePipelineStateHash hashes today, computing no offsets in python.
- The generated files are committed so the build never depends on python; CI regenerates
and diffs them.
62 lines
3.3 KiB
C++
62 lines
3.3 KiB
C++
// MobileGL - MobileGL/MG_Pipe/MGPipeCallbacks.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 "MGPipeHandles.h"
|
|
#include "MGPipeTypes.h"
|
|
|
|
// The backend -> frontend reverse channel, named (plan B section 7.1).
|
|
//
|
|
// Today this traffic is 95 call sites across 17 methods poked directly into frontend
|
|
// objects. gallium has no vocabulary for shadow writeback, GPU-write notification, texture
|
|
// re-send requests or default-framebuffer geometry, because in Mesa the state tracker and
|
|
// the driver share an address space. Naming them as ten callbacks plus one forward
|
|
// terminator (MGPipeContext::ResourceSubDataComplete) is the deliberate deviation (D8).
|
|
//
|
|
// Installed at context creation. In a monolith these are direct calls; under split they are
|
|
// records on the reverse channel, and their ORDER is a correctness requirement rather than
|
|
// an optimization (section 7.4).
|
|
namespace MobileGL::MG_Pipe {
|
|
struct MGPipeCallbacks {
|
|
// A driver-detected GL error that only the server could have seen.
|
|
void (*OnGlError)(Uint32 code);
|
|
// Ranges of a resource the GPU wrote; retires MarkGpuWritten.
|
|
void (*OnGpuWritten)(MGPipeHandle res, Uint rangeCount, const MGPRange* ranges);
|
|
void (*OnBufferWriteback)(MGPipeHandle res, Uint64 offset, MGPBlobRef bytes);
|
|
void (*OnTextureWriteback)(MGPipeHandle res, const MGPBox* box, MGPBlobRef bytes);
|
|
// The one new stall class in this design (D-B6): the server recast a texture and
|
|
// needs its texels back. The client answers with zero or more ResourceSubData
|
|
// records terminated by ResourceSubDataComplete carrying the same pullSerial.
|
|
void (*OnTexturePullRequest)(MGPipeHandle res, Uint16 target, Uint16 firstLevel, Uint16 levelCount,
|
|
Uint64 pullSerial);
|
|
// SHAPE ONLY, never bytes: the client owns the CPU shadow and allocates the levels
|
|
// itself.
|
|
void (*OnMipLevelsGenerated)(MGPipeHandle res, Uint16 base, Uint16 count);
|
|
// Retires the layering inversion where the swapchain writes into MG_Impl's
|
|
// pDefaultFramebufferInfo.
|
|
void (*OnSurfaceChanged)(const MGPSurfaceInfo* info);
|
|
void (*OnCapsInvalidated)();
|
|
// <= WARN is lossy, >= ERROR is lossless and rate limited.
|
|
void (*OnLog)(Uint8 level, const char* text);
|
|
// The XFB scatter is a read-modify-write of the CLIENT's shadow, so the server
|
|
// hands back the packed scratch and the client scatters (section 7.2.1).
|
|
void (*OnXfbScatterReady)(MGPipeHandle scratch, Uint64 packedStride, Uint64 vertices);
|
|
};
|
|
|
|
// Ten, and the count is asserted so an eleventh cannot be added without touching the
|
|
// transport's reverse-channel record table.
|
|
inline constexpr SizeT kMGPipeCallbackCount = 10;
|
|
static_assert(sizeof(MGPipeCallbacks) == kMGPipeCallbackCount * sizeof(void (*)()),
|
|
"MGPipeCallbacks gained or lost a callback");
|
|
|
|
// Null-initialized: a backend that installs nothing sends nothing.
|
|
inline MGPipeCallbacks gMGPipeCallbacks{};
|
|
} // namespace MobileGL::MG_Pipe
|