[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:
2026-09-06 01:35:45 -04:00
parent 087685d19b
commit bf86b1ede6
15 changed files with 1834 additions and 30 deletions
+28 -3
View File
@@ -31,11 +31,13 @@
X(GetBlendColor, SetDynamicState) \
X(GetBlendEquationIndexed, CreateRenderState) \
X(GetBlendFuncIndexed, CreateRenderState) \
/* dead: no backend reads it since D21; kept for inventory row 594 */ \
X(GetBoundTransformFeedbackName, SetStreamOutputTargets) \
X(GetBoundVertexArray, BindVertexElements) \
/* Polymorphic over BufferTarget: its rows split across set_vertex_buffers, */ \
/* set_index_buffer, set_indirect_buffers and set_shader_buffers once the */ \
/* inventory carries the target argument (P1). Named for the plan's explicit */ \
/* set_index_buffer, set_indirect_buffers and set_shader_buffers when the */ \
/* inventory is re-vendored carrying the target argument (deferred out of P1: */ \
/* the extractor lives in MobileGL-CS). Named for the plan's explicit */ \
/* replacement of the DrawIndirect/Parameter pair. */ \
X(GetBufferBindingSlot, SetIndirectBuffers) \
X(GetBufferBindingPoint, SetShaderBuffers) \
@@ -94,7 +96,30 @@
X(IsTransformFeedbackPaused, PauseStreamOutput) \
X(InvalidateCompileEnv, kClientResolved) \
X(ValidateProgramName, kClientResolved) \
X(RecordError, kReverseChannel)
X(RecordError, kReverseChannel) \
/* The D21 XFB counter-slot rekey's reads (VulkanRenderer.cpp); the calls they */ \
/* map to are GetTransformFeedbackGeneration's. */ \
X(GetBoundTransformFeedbackLifetimeId, SetStreamOutputTargets) \
X(HasOpenTransformFeedbackSpan, SetStreamOutputTargets)
// X(Accessor, Reason) - the STICKY fields (P1 brief D6): the only PipeInputs fields whose
// value is valid across verbs, so the poison's per-verb generation does not apply to them.
// Exactly the seven F-class (forwarded) accessors, and the argument for each is the same:
// it takes an argument that is not verb state - a GL name, a lifetime id, a target - i.e.
// it is a lookup or a reverse-channel write, not a state read; there is no value the
// filler could copy and no verb whose fill could make it stale; phase C replaces them
// with handle tables and callbacks. None of the version/generation accessors is sticky:
// those change under verbs and are precisely what the poison must protect. The verify
// lane's Fatal{UnmigratedPipeInput} is fixed by a FillPoints.def row, never by a row here.
// gen_pipe.py refuses a name that is not an accessor above.
#define MGP_COVERAGE_STICKY_LIST(X) \
X(GetBufferBindingPointCount, "keyed by target: a constexpr capacity table, not verb state") \
X(GetProgramObject, "keyed by GL name: an object lookup, not verb state") \
X(GetTextureObject, "keyed by GL name: an object lookup, not verb state") \
X(HasOpenTransformFeedbackSpan, "keyed by lifetime id: an object lookup, not verb state") \
X(ValidateProgramName, "keyed by GL name: a name-table lookup, not verb state") \
X(InvalidateCompileEnv, "reverse channel: a write into the frontend, not a state read") \
X(RecordError, "reverse channel: a write into the frontend, not a state read")
// X(DeltaKind, PipeCall) - for inventory rows with no accessor in the member column.
// Read by gen_pipe.py ONLY, never by the C++ preprocessor: the delta kinds are the
+267
View File
@@ -0,0 +1,267 @@
// MobileGL - MobileGL/MG_Pipe/FillPoints.def
// 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 per-verb fill points of the PipeInputs strangler (ARCHITECTURE.md 9.2, phase A; the
// P1 brief D7). Three hand-maintained lists, read by scripts/gen_pipe.py (G5b) into
// generated/PipeFillPoints.inc:
//
// MGP_FILL_VERB_LIST every verb the frontend calls through GLFunctionsTable, with its class
// MGP_FILL_CLASS_LIST the verb classes
// MGP_FILL_FIELD_LIST the may-read table: which PipeInputs fields a class of verb may read
//
// The verb set IS the function-pointer member set of MG_Backend::GLFunctionsTable
// (MG_Backend/BackendObject.h), in declaration order: gen_pipe.py parses that struct and
// refuses a row set that is not exactly its member set in that order, so the MGPipeVerb enum
// and the table cannot drift apart. MG_Impl spells MGP_FILL(Verb) immediately before every
// call through the table (83 statements over these 69 verbs); Present and SetSwapInterval go
// through BackendObject virtuals and read no frontend state, so they are not verbs here.
//
// The seven sticky fields (Coverage.def, MGP_COVERAGE_STICKY_LIST) are implicit in every
// class and are not listed. The verify lane is the oracle for this table: a
// Fatal{UnmigratedPipeInput, "Field@Verb"} found there is fixed by adding the (class, field)
// row, never by marking the field sticky.
//
// gen_pipe.py's block regexes end at a blank line: keep the empty line after each macro.
//
// clang-format off
// X(Verb, Class) - one row per function-pointer member of MG_Backend::GLFunctionsTable (BackendObject.h),
// in declaration order. gen_pipe.py parses that struct and refuses a row set that is not exactly its member set.
#define MGP_FILL_VERB_LIST(X) \
X(DrawArrays, kDraw) \
X(DrawElements, kDraw) \
X(DrawElementsBaseVertex, kDraw) \
X(MultiDrawArrays, kDraw) \
X(MultiDrawElements, kDraw) \
X(MultiDrawElementsBaseVertex, kDraw) \
X(MultiDrawElementsIndirect, kDraw) \
X(MultiDrawArraysIndirect, kDraw) \
X(MultiDrawElementsIndirectCount, kDraw) \
X(MultiDrawArraysIndirectCount, kDraw) \
X(DrawRangeElementsBaseVertex, kDraw) \
X(DrawRangeElements, kDraw) \
X(DrawElementsInstancedBaseVertexBaseInstance, kDraw) \
X(DrawElementsInstancedBaseVertex, kDraw) \
X(DrawElementsInstancedBaseInstance, kDraw) \
X(DrawElementsInstanced, kDraw) \
X(DrawArraysInstancedBaseInstance, kDraw) \
X(DrawArraysInstanced, kDraw) \
X(DrawElementsIndirect, kDraw) \
X(DrawArraysIndirect, kDraw) \
X(Clear, kClear) \
X(ClearBufferfi, kClear) \
X(ClearBufferfv, kClear) \
X(ClearBufferuiv, kClear) \
X(ClearBufferiv, kClear) \
X(ClearNamedFramebufferfv, kClear) \
X(ClearNamedFramebufferfi, kClear) \
X(ClearNamedFramebufferiv, kClear) \
X(ClearNamedFramebufferuiv, kClear) \
X(BlitFramebuffer, kBlitOrCopy) \
X(BlitNamedFramebuffer, kBlitOrCopy) \
X(CopyTexImage2D, kBlitOrCopy) \
X(CopyTexSubImage2D, kBlitOrCopy) \
X(CopyImageSubData, kBlitOrCopy) \
X(GenerateMipmap, kTextureOp) \
X(ReadPixels, kReadback) \
X(GetTexImage, kReadback) \
X(GetTextureImage, kReadback) \
X(DispatchCompute, kDispatch) \
X(DispatchComputeIndirect, kDispatch) \
X(MemoryBarrier, kQuery) \
X(MemoryBarrierByRegion, kQuery) \
X(BindImageTexture, kTextureOp) \
X(GetIntegeri_v, kQuery) \
X(ShaderStorageBlockBinding, kProgramOp) \
X(FenceSync, kQuery) \
X(ClientWaitSync, kQuery) \
X(WaitSync, kQuery) \
X(DeleteSync, kQuery) \
X(GetSyncStatus, kQuery) \
X(IsTimerQuerySupported, kQuery) \
X(BeginTimeElapsedQuery, kQuery) \
X(EndTimeElapsedQuery, kQuery) \
X(QueryCounterTimestamp, kQuery) \
X(IsQueryResultAvailable, kQuery) \
X(GetQueryResult64, kQuery) \
X(DeleteBackendQuery, kQuery) \
X(BeginOcclusionQuery, kQuery) \
X(EndOcclusionQuery, kQuery) \
X(BeginXfbPrimitivesQuery, kQuery) \
X(EndXfbPrimitivesQuery, kQuery) \
X(PatchParameteri, kQuery) \
X(BeginTransformFeedback, kXfbSpan) \
X(EndTransformFeedback, kXfbSpan) \
X(PauseTransformFeedback, kXfbSpan) \
X(ResumeTransformFeedback, kXfbSpan) \
X(BindTransformFeedback, kXfbSpan) \
X(DeleteTransformFeedback, kXfbSpan) \
X(GetGpuTimestampNs, kQuery)
// X(Class) - the nine verb classes (ARCHITECTURE.md:153 names eight; kProgramOp is split out because
// ShaderStorageBlockBinding is the one non-draw verb that syncs Espryt's render state and textures).
#define MGP_FILL_CLASS_LIST(X) \
X(kDraw) X(kDispatch) X(kClear) X(kBlitOrCopy) X(kTextureOp) X(kReadback) X(kXfbSpan) X(kProgramOp) X(kQuery)
// X(Class, Field) - the may-read table. A field named here is filled and stamped at every verb of the class;
// a read of a field NOT named here is Fatal{UnmigratedPipeInput, "Field@Verb"} in a poison build.
// Derived from the verified reachability of every backend read (both backends, union), P1 brief D7.
#define MGP_FILL_FIELD_LIST(X) \
/* kDraw: every draw entry of both backends */ \
X(kDraw, GetBoundVertexArray) \
X(kDraw, GetProgramForDraw) \
X(kDraw, GetBufferBindingSlot) \
X(kDraw, GetBufferBindingPoint) \
X(kDraw, GetTouchedBufferBindingPointCount) \
X(kDraw, GetTextureUnitObject) \
X(kDraw, GetTextureContextId) \
X(kDraw, GetTextureBindGeneration) \
X(kDraw, GetMaxTouchedTextureUnit) \
X(kDraw, GetSamplingResolutionGeneration) \
X(kDraw, GetImageTextureBinding) \
X(kDraw, GetCurrentVertexAttribute) \
X(kDraw, GetRenderStateParameters) \
X(kDraw, GetRenderStateParametersVersion) \
X(kDraw, GetPipelineStateVersion) \
X(kDraw, GetViewport) \
X(kDraw, GetViewportIndexed) \
X(kDraw, GetDepthRangeIndexed) \
X(kDraw, GetScissorBox) \
X(kDraw, IsCapabilityEnabled) \
X(kDraw, IsCapabilityEnabledIndexed) \
X(kDraw, GetBlendColor) \
X(kDraw, GetBlendFuncIndexed) \
X(kDraw, GetBlendEquationIndexed) \
X(kDraw, GetColorMaskIndexed) \
X(kDraw, GetLogicOp) \
X(kDraw, GetDepthFunc) \
X(kDraw, GetDepthMask) \
X(kDraw, GetStencilState) \
X(kDraw, GetCullFaceMode) \
X(kDraw, GetPolygonModeFront) \
X(kDraw, GetPolygonOffsetFactor) \
X(kDraw, GetPolygonOffsetUnits) \
X(kDraw, GetLineWidth) \
X(kDraw, GetMinSampleShadingValue) \
X(kDraw, GetProvokingVertexMode) \
X(kDraw, GetPatchVertices) \
X(kDraw, GetPatchDefaultOuterLevel) \
X(kDraw, GetPatchDefaultInnerLevel) \
X(kDraw, GetPrimitiveRestartIndex) \
X(kDraw, GetFramebufferBindingSlot) \
X(kDraw, IsTransformFeedbackActive) \
X(kDraw, IsTransformFeedbackPaused) \
X(kDraw, GetTransformFeedbackProgram) \
X(kDraw, GetTransformFeedbackGeneration) \
X(kDraw, GetBoundTransformFeedbackLifetimeId) \
X(kDraw, GetTransformFeedbackCapturedVertices) \
/* kDispatch: the patch fields are Espryt's SyncCurrentProgram -> */ \
/* AttachPassthroughTessControlStage (Managers.cpp) */ \
X(kDispatch, GetProgramForDispatch) \
X(kDispatch, GetBufferBindingSlot) \
X(kDispatch, GetBufferBindingPoint) \
X(kDispatch, GetTouchedBufferBindingPointCount) \
X(kDispatch, GetTextureUnitObject) \
X(kDispatch, GetTextureContextId) \
X(kDispatch, GetTextureBindGeneration) \
X(kDispatch, GetMaxTouchedTextureUnit) \
X(kDispatch, GetSamplingResolutionGeneration) \
X(kDispatch, GetImageTextureBinding) \
X(kDispatch, GetFramebufferBindingSlot) \
X(kDispatch, GetPatchVertices) \
X(kDispatch, GetPatchDefaultOuterLevel) \
X(kDispatch, GetPatchDefaultInnerLevel) \
/* kClear */ \
X(kClear, GetRenderStateParameters) \
X(kClear, GetRenderStateParametersVersion) \
X(kClear, GetViewport) \
X(kClear, IsCapabilityEnabled) \
X(kClear, GetFramebufferBindingSlot) \
X(kClear, GetClearColor) \
X(kClear, GetClearDepth) \
X(kClear, GetClearStencil) \
X(kClear, GetScissorBox) \
X(kClear, GetColorMaskIndexed) \
X(kClear, GetDepthMask) \
X(kClear, GetStencilState) \
X(kClear, GetTextureUnitObject) \
X(kClear, GetTextureContextId) \
X(kClear, GetSamplingResolutionGeneration) \
X(kClear, GetTextureBindGeneration) \
X(kClear, GetMaxTouchedTextureUnit) \
X(kClear, GetImageTextureBinding) \
/* kBlitOrCopy */ \
X(kBlitOrCopy, GetFramebufferBindingSlot) \
X(kBlitOrCopy, IsCapabilityEnabled) \
X(kBlitOrCopy, GetScissorBox) \
X(kBlitOrCopy, IsTransformFeedbackActive) \
X(kBlitOrCopy, IsTransformFeedbackPaused) \
X(kBlitOrCopy, GetRenderStateParameters) \
X(kBlitOrCopy, GetRenderStateParametersVersion) \
X(kBlitOrCopy, GetViewport) \
X(kBlitOrCopy, GetActiveTextureUnit) \
X(kBlitOrCopy, GetTextureUnitObject) \
X(kBlitOrCopy, GetTextureContextId) \
X(kBlitOrCopy, GetSamplingResolutionGeneration) \
X(kBlitOrCopy, GetTextureBindGeneration) \
X(kBlitOrCopy, GetMaxTouchedTextureUnit) \
X(kBlitOrCopy, GetImageTextureBinding) \
X(kBlitOrCopy, GetColorMaskIndexed) \
X(kBlitOrCopy, GetDepthMask) \
X(kBlitOrCopy, GetStencilState) \
/* kTextureOp */ \
X(kTextureOp, GetActiveTextureUnit) \
X(kTextureOp, GetTextureUnitObject) \
X(kTextureOp, GetImageTextureBinding) \
X(kTextureOp, GetTextureContextId) \
X(kTextureOp, GetSamplingResolutionGeneration) \
X(kTextureOp, GetTextureBindGeneration) \
X(kTextureOp, GetMaxTouchedTextureUnit) \
/* kReadback */ \
X(kReadback, GetPixelStoreParameters) \
X(kReadback, GetBufferBindingSlot) \
X(kReadback, GetFramebufferBindingSlot) \
X(kReadback, GetActiveTextureUnit) \
X(kReadback, GetTextureUnitObject) \
X(kReadback, GetClampReadColor) \
X(kReadback, IsCapabilityEnabled) \
X(kReadback, GetRenderStateParameters) \
X(kReadback, GetRenderStateParametersVersion) \
X(kReadback, GetViewport) \
X(kReadback, GetTextureContextId) \
X(kReadback, GetSamplingResolutionGeneration) \
X(kReadback, GetTextureBindGeneration) \
X(kReadback, GetMaxTouchedTextureUnit) \
X(kReadback, GetImageTextureBinding) \
/* kXfbSpan */ \
X(kXfbSpan, GetTransformFeedbackProgram) \
X(kXfbSpan, GetBufferBindingPoint) \
X(kXfbSpan, GetTouchedBufferBindingPointCount) \
X(kXfbSpan, GetTransformFeedbackCapturedVertices) \
X(kXfbSpan, IsTransformFeedbackActive) \
X(kXfbSpan, IsTransformFeedbackPaused) \
X(kXfbSpan, GetTransformFeedbackGeneration) \
X(kXfbSpan, GetBoundTransformFeedbackLifetimeId) \
/* kProgramOp: ShaderStorageBlockBinding syncs Espryt's render state and textures */ \
X(kProgramOp, GetRenderStateParameters) \
X(kProgramOp, GetRenderStateParametersVersion) \
X(kProgramOp, GetViewport) \
X(kProgramOp, IsCapabilityEnabled) \
X(kProgramOp, GetFramebufferBindingSlot) \
X(kProgramOp, GetTextureUnitObject) \
X(kProgramOp, GetTextureContextId) \
X(kProgramOp, GetSamplingResolutionGeneration) \
X(kProgramOp, GetTextureBindGeneration) \
X(kProgramOp, GetMaxTouchedTextureUnit) \
X(kProgramOp, GetImageTextureBinding) \
/* kQuery: Magma's transform feedback query end reads the paused counter */ \
/* (DirectVulkan.cpp); every other verb in the class reads nothing and */ \
/* its fill is a serial bump */ \
X(kQuery, GetTransformFeedbackPausedPrimitiveCounter)
// clang-format on
+5
View File
@@ -85,6 +85,11 @@ namespace MobileGL::MG_Pipe {
// 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"
+28
View File
@@ -0,0 +1,28 @@
// MobileGL - MobileGL/MG_Pipe/PipeInputsSwitch.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
#ifndef MOBILEGL_MG_PIPE_INPUTS_SWITCH_H // belt and braces: reachable as <MG_Pipe/..> and <..> (CMakeLists.txt:531,535)
#define MOBILEGL_MG_PIPE_INPUTS_SWITCH_H
// The strangler switch (ARCHITECTURE.md 9.2). Every backend read of frontend state is spelled
// MGB_CTX->Accessor(...). Pull arm: the live GLContext, so the pull build is the tree before P1
// token for token. Push arm: the PipeInputs block the frontend fills at every verb boundary.
// The pull arm is the ONLY place under MobileGL/ outside MG_State and MG_Impl that may spell
// pGLContext; purity gate C greps MG_Backend/ for that token.
#if MOBILEGL_PIPE_PUSH
#include <MG_Backend/MGPipe/PipeInputs.h>
#define MGB_CTX (&::MobileGL::MG_Pipe::gPipeInputs)
#define MGB_CTX_LIVE (::MobileGL::MG_Pipe::gPipeInputs.IsLive())
#define MGB_CTX_IDENTITY (::MobileGL::MG_Pipe::gPipeInputs.ContextIdentity())
#else
#include <MG_State/GLState/Core.h>
#define MGB_CTX (::MobileGL::MG_State::pGLContext)
#define MGB_CTX_LIVE (::MobileGL::MG_State::pGLContext != nullptr)
#define MGB_CTX_IDENTITY (static_cast<const void*>(::MobileGL::MG_State::pGLContext.get()))
#endif
#endif
@@ -0,0 +1,300 @@
// MobileGL - MobileGL/MG_Pipe/generated/PipeFillPoints.inc
// 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
// G5b: the verb enum, the verb classes and their may-read field masks.
//
// GENERATED by scripts/gen_pipe.py from FillPoints.def, Coverage.def and MG_Backend/BackendObject.h - DO NOT EDIT.
// Regenerate with `python3 scripts/gen_pipe.py`; CI runs it and diffs the result.
// This file is included from MG_Pipe/MGPipe.h inside namespace MobileGL::MG_Pipe.
// One verb per function-pointer member of MG_Backend::GLFunctionsTable, in declaration
// order, so the enum IS the table's member list. MG_Impl spells MGP_FILL(Verb) before every
// call through the table; MGPipeFillForVerb fills exactly the fields of the verb's class
// (plus the sticky fields, OR'ed into every mask) and stamps them with the new serial. A
// read of any other field is Fatal{UnmigratedPipeInput, "Field@Verb"} in a poison build.
enum class MGPipeVerb : Uint8 {
DrawArrays,
DrawElements,
DrawElementsBaseVertex,
MultiDrawArrays,
MultiDrawElements,
MultiDrawElementsBaseVertex,
MultiDrawElementsIndirect,
MultiDrawArraysIndirect,
MultiDrawElementsIndirectCount,
MultiDrawArraysIndirectCount,
DrawRangeElementsBaseVertex,
DrawRangeElements,
DrawElementsInstancedBaseVertexBaseInstance,
DrawElementsInstancedBaseVertex,
DrawElementsInstancedBaseInstance,
DrawElementsInstanced,
DrawArraysInstancedBaseInstance,
DrawArraysInstanced,
DrawElementsIndirect,
DrawArraysIndirect,
Clear,
ClearBufferfi,
ClearBufferfv,
ClearBufferuiv,
ClearBufferiv,
ClearNamedFramebufferfv,
ClearNamedFramebufferfi,
ClearNamedFramebufferiv,
ClearNamedFramebufferuiv,
BlitFramebuffer,
BlitNamedFramebuffer,
CopyTexImage2D,
CopyTexSubImage2D,
CopyImageSubData,
GenerateMipmap,
ReadPixels,
GetTexImage,
GetTextureImage,
DispatchCompute,
DispatchComputeIndirect,
MemoryBarrier,
MemoryBarrierByRegion,
BindImageTexture,
GetIntegeri_v,
ShaderStorageBlockBinding,
FenceSync,
ClientWaitSync,
WaitSync,
DeleteSync,
GetSyncStatus,
IsTimerQuerySupported,
BeginTimeElapsedQuery,
EndTimeElapsedQuery,
QueryCounterTimestamp,
IsQueryResultAvailable,
GetQueryResult64,
DeleteBackendQuery,
BeginOcclusionQuery,
EndOcclusionQuery,
BeginXfbPrimitivesQuery,
EndXfbPrimitivesQuery,
PatchParameteri,
BeginTransformFeedback,
EndTransformFeedback,
PauseTransformFeedback,
ResumeTransformFeedback,
BindTransformFeedback,
DeleteTransformFeedback,
GetGpuTimestampNs,
kVerbCount,
};
inline constexpr SizeT kMGPipeVerbCount = static_cast<SizeT>(MGPipeVerb::kVerbCount);
static_assert(kMGPipeVerbCount == 69, "the GLFunctionsTable verb set moved");
inline constexpr const char* kMGPipeVerbNames[kMGPipeVerbCount] = {
"DrawArrays",
"DrawElements",
"DrawElementsBaseVertex",
"MultiDrawArrays",
"MultiDrawElements",
"MultiDrawElementsBaseVertex",
"MultiDrawElementsIndirect",
"MultiDrawArraysIndirect",
"MultiDrawElementsIndirectCount",
"MultiDrawArraysIndirectCount",
"DrawRangeElementsBaseVertex",
"DrawRangeElements",
"DrawElementsInstancedBaseVertexBaseInstance",
"DrawElementsInstancedBaseVertex",
"DrawElementsInstancedBaseInstance",
"DrawElementsInstanced",
"DrawArraysInstancedBaseInstance",
"DrawArraysInstanced",
"DrawElementsIndirect",
"DrawArraysIndirect",
"Clear",
"ClearBufferfi",
"ClearBufferfv",
"ClearBufferuiv",
"ClearBufferiv",
"ClearNamedFramebufferfv",
"ClearNamedFramebufferfi",
"ClearNamedFramebufferiv",
"ClearNamedFramebufferuiv",
"BlitFramebuffer",
"BlitNamedFramebuffer",
"CopyTexImage2D",
"CopyTexSubImage2D",
"CopyImageSubData",
"GenerateMipmap",
"ReadPixels",
"GetTexImage",
"GetTextureImage",
"DispatchCompute",
"DispatchComputeIndirect",
"MemoryBarrier",
"MemoryBarrierByRegion",
"BindImageTexture",
"GetIntegeri_v",
"ShaderStorageBlockBinding",
"FenceSync",
"ClientWaitSync",
"WaitSync",
"DeleteSync",
"GetSyncStatus",
"IsTimerQuerySupported",
"BeginTimeElapsedQuery",
"EndTimeElapsedQuery",
"QueryCounterTimestamp",
"IsQueryResultAvailable",
"GetQueryResult64",
"DeleteBackendQuery",
"BeginOcclusionQuery",
"EndOcclusionQuery",
"BeginXfbPrimitivesQuery",
"EndXfbPrimitivesQuery",
"PatchParameteri",
"BeginTransformFeedback",
"EndTransformFeedback",
"PauseTransformFeedback",
"ResumeTransformFeedback",
"BindTransformFeedback",
"DeleteTransformFeedback",
"GetGpuTimestampNs",
};
enum class MGPipeVerbClass : Uint8 {
kDraw,
kDispatch,
kClear,
kBlitOrCopy,
kTextureOp,
kReadback,
kXfbSpan,
kProgramOp,
kQuery,
kClassCount,
};
inline constexpr SizeT kMGPipeVerbClassCount = static_cast<SizeT>(MGPipeVerbClass::kClassCount);
static_assert(kMGPipeVerbClassCount == 9, "the verb class set moved");
inline constexpr const char* kMGPipeVerbClassNames[kMGPipeVerbClassCount] = {
"kDraw",
"kDispatch",
"kClear",
"kBlitOrCopy",
"kTextureOp",
"kReadback",
"kXfbSpan",
"kProgramOp",
"kQuery",
};
inline constexpr MGPipeVerbClass kMGPipeVerbClass[kMGPipeVerbCount] = {
MGPipeVerbClass::kDraw, // DrawArrays
MGPipeVerbClass::kDraw, // DrawElements
MGPipeVerbClass::kDraw, // DrawElementsBaseVertex
MGPipeVerbClass::kDraw, // MultiDrawArrays
MGPipeVerbClass::kDraw, // MultiDrawElements
MGPipeVerbClass::kDraw, // MultiDrawElementsBaseVertex
MGPipeVerbClass::kDraw, // MultiDrawElementsIndirect
MGPipeVerbClass::kDraw, // MultiDrawArraysIndirect
MGPipeVerbClass::kDraw, // MultiDrawElementsIndirectCount
MGPipeVerbClass::kDraw, // MultiDrawArraysIndirectCount
MGPipeVerbClass::kDraw, // DrawRangeElementsBaseVertex
MGPipeVerbClass::kDraw, // DrawRangeElements
MGPipeVerbClass::kDraw, // DrawElementsInstancedBaseVertexBaseInstance
MGPipeVerbClass::kDraw, // DrawElementsInstancedBaseVertex
MGPipeVerbClass::kDraw, // DrawElementsInstancedBaseInstance
MGPipeVerbClass::kDraw, // DrawElementsInstanced
MGPipeVerbClass::kDraw, // DrawArraysInstancedBaseInstance
MGPipeVerbClass::kDraw, // DrawArraysInstanced
MGPipeVerbClass::kDraw, // DrawElementsIndirect
MGPipeVerbClass::kDraw, // DrawArraysIndirect
MGPipeVerbClass::kClear, // Clear
MGPipeVerbClass::kClear, // ClearBufferfi
MGPipeVerbClass::kClear, // ClearBufferfv
MGPipeVerbClass::kClear, // ClearBufferuiv
MGPipeVerbClass::kClear, // ClearBufferiv
MGPipeVerbClass::kClear, // ClearNamedFramebufferfv
MGPipeVerbClass::kClear, // ClearNamedFramebufferfi
MGPipeVerbClass::kClear, // ClearNamedFramebufferiv
MGPipeVerbClass::kClear, // ClearNamedFramebufferuiv
MGPipeVerbClass::kBlitOrCopy, // BlitFramebuffer
MGPipeVerbClass::kBlitOrCopy, // BlitNamedFramebuffer
MGPipeVerbClass::kBlitOrCopy, // CopyTexImage2D
MGPipeVerbClass::kBlitOrCopy, // CopyTexSubImage2D
MGPipeVerbClass::kBlitOrCopy, // CopyImageSubData
MGPipeVerbClass::kTextureOp, // GenerateMipmap
MGPipeVerbClass::kReadback, // ReadPixels
MGPipeVerbClass::kReadback, // GetTexImage
MGPipeVerbClass::kReadback, // GetTextureImage
MGPipeVerbClass::kDispatch, // DispatchCompute
MGPipeVerbClass::kDispatch, // DispatchComputeIndirect
MGPipeVerbClass::kQuery, // MemoryBarrier
MGPipeVerbClass::kQuery, // MemoryBarrierByRegion
MGPipeVerbClass::kTextureOp, // BindImageTexture
MGPipeVerbClass::kQuery, // GetIntegeri_v
MGPipeVerbClass::kProgramOp, // ShaderStorageBlockBinding
MGPipeVerbClass::kQuery, // FenceSync
MGPipeVerbClass::kQuery, // ClientWaitSync
MGPipeVerbClass::kQuery, // WaitSync
MGPipeVerbClass::kQuery, // DeleteSync
MGPipeVerbClass::kQuery, // GetSyncStatus
MGPipeVerbClass::kQuery, // IsTimerQuerySupported
MGPipeVerbClass::kQuery, // BeginTimeElapsedQuery
MGPipeVerbClass::kQuery, // EndTimeElapsedQuery
MGPipeVerbClass::kQuery, // QueryCounterTimestamp
MGPipeVerbClass::kQuery, // IsQueryResultAvailable
MGPipeVerbClass::kQuery, // GetQueryResult64
MGPipeVerbClass::kQuery, // DeleteBackendQuery
MGPipeVerbClass::kQuery, // BeginOcclusionQuery
MGPipeVerbClass::kQuery, // EndOcclusionQuery
MGPipeVerbClass::kQuery, // BeginXfbPrimitivesQuery
MGPipeVerbClass::kQuery, // EndXfbPrimitivesQuery
MGPipeVerbClass::kQuery, // PatchParameteri
MGPipeVerbClass::kXfbSpan, // BeginTransformFeedback
MGPipeVerbClass::kXfbSpan, // EndTransformFeedback
MGPipeVerbClass::kXfbSpan, // PauseTransformFeedback
MGPipeVerbClass::kXfbSpan, // ResumeTransformFeedback
MGPipeVerbClass::kXfbSpan, // BindTransformFeedback
MGPipeVerbClass::kXfbSpan, // DeleteTransformFeedback
MGPipeVerbClass::kQuery, // GetGpuTimestampNs
};
// One bit per MGPipeInputField. The 7 sticky fields are OR'ed into every class.
struct MGPipeFieldMask {
Uint64 Words[2];
};
inline constexpr Bool MGPipeFieldMaskHas(const MGPipeFieldMask& mask, MGPipeInputField field) {
const SizeT index = static_cast<SizeT>(field);
return (mask.Words[index / 64] >> (index % 64)) & 1u;
}
inline constexpr MGPipeFieldMask kMGPipeClassFieldMask[kMGPipeVerbClassCount] = {
// kDraw: 54 fields (47 own + 7 sticky)
{{0x7ffbfff7bfffc3eeull, 0x0000000000000000ull}},
// kDispatch: 21 fields (14 own + 7 sticky)
{{0x5c00f2281d3003c0ull, 0x0000000000000000ull}},
// kClear: 25 fields (18 own + 7 sticky)
{{0x5c50ffa001347900ull, 0x0000000000000000ull}},
// kBlitOrCopy: 25 fields (18 own + 7 sticky)
{{0x5f50ffa001344101ull, 0x0000000000000000ull}},
// kTextureOp: 14 fields (7 own + 7 sticky)
{{0x5c00f22001200101ull, 0x0000000000000000ull}},
// kReadback: 22 fields (15 own + 7 sticky)
{{0x5c50f3a041300541ull, 0x0000000000000000ull}},
// kXfbSpan: 15 fields (8 own + 7 sticky)
{{0x7f0b402000000380ull, 0x0000000000000000ull}},
// kProgramOp: 18 fields (11 own + 7 sticky)
{{0x5c50f3a001300100ull, 0x0000000000000000ull}},
// kQuery: 8 fields (1 own + 7 sticky)
{{0x5c04402000000100ull, 0x0000000000000000ull}},
};
static_assert(kMGPipeInputFieldCount <= 2 * 64, "MGPipeFieldMask needs another word");
+21 -12
View File
@@ -22,8 +22,8 @@
// field stamps it with that serial, and reading a non-sticky field whose stamp is older is
// Fatal{UnmigratedPipeInput} (section 6.2.2).
//
// P0 is the skeleton: the enum, the tables and the assertion helper exist, PipeInputs
// itself lands in P1.
// PipeInputs itself is MG_Backend/MGPipe/PipeInputs.h (P1); the verb enum and the
// per-class fill masks are G5b, generated/PipeFillPoints.inc.
enum class MGPipeInputField : Uint16 {
GetActiveTextureUnit,
@@ -87,11 +87,13 @@ enum class MGPipeInputField : Uint16 {
InvalidateCompileEnv,
ValidateProgramName,
RecordError,
GetBoundTransformFeedbackLifetimeId,
HasOpenTransformFeedbackSpan,
kFieldCount,
};
inline constexpr SizeT kMGPipeInputFieldCount = static_cast<SizeT>(MGPipeInputField::kFieldCount);
static_assert(kMGPipeInputFieldCount == 61, "the PipeInputs field set moved");
static_assert(kMGPipeInputFieldCount == 63, "the PipeInputs field set moved");
inline constexpr const char* kMGPipeInputFieldNames[kMGPipeInputFieldCount] = {
"GetActiveTextureUnit",
@@ -155,11 +157,13 @@ inline constexpr const char* kMGPipeInputFieldNames[kMGPipeInputFieldCount] = {
"InvalidateCompileEnv",
"ValidateProgramName",
"RecordError",
"GetBoundTransformFeedbackLifetimeId",
"HasOpenTransformFeedbackSpan",
};
// Fields whose value is valid ACROSS verbs. Every entry is false in P0 and each
// true has to be argued for in P1 when the fillers land: a sticky field is a field
// the poison cannot protect.
// Fields whose value is valid ACROSS verbs: a sticky field is a field the poison
// cannot protect, so every true is argued for in Coverage.def's
// MGP_COVERAGE_STICKY_LIST (the seven forwarded, argument-keyed accessors).
inline constexpr Bool kMGPipeInputFieldSticky[kMGPipeInputFieldCount] = {
false, // GetActiveTextureUnit
false, // GetBlendColor
@@ -169,7 +173,7 @@ inline constexpr Bool kMGPipeInputFieldSticky[kMGPipeInputFieldCount] = {
false, // GetBoundVertexArray
false, // GetBufferBindingSlot
false, // GetBufferBindingPoint
false, // GetBufferBindingPointCount
true, // GetBufferBindingPointCount: keyed by target: a constexpr capacity table, not verb state
false, // GetTouchedBufferBindingPointCount
false, // GetClampReadColor
false, // GetClearColor
@@ -198,7 +202,7 @@ inline constexpr Bool kMGPipeInputFieldSticky[kMGPipeInputFieldCount] = {
false, // GetPrimitiveRestartIndex
false, // GetProgramForDispatch
false, // GetProgramForDraw
false, // GetProgramObject
true, // GetProgramObject: keyed by GL name: an object lookup, not verb state
false, // GetProvokingVertexMode
false, // GetRenderStateParameters
false, // GetRenderStateParametersVersion
@@ -207,7 +211,7 @@ inline constexpr Bool kMGPipeInputFieldSticky[kMGPipeInputFieldCount] = {
false, // GetStencilState
false, // GetTextureBindGeneration
false, // GetTextureContextId
false, // GetTextureObject
true, // GetTextureObject: keyed by GL name: an object lookup, not verb state
false, // GetTextureUnitObject
false, // GetTransformFeedbackCapturedVertices
false, // GetTransformFeedbackGeneration
@@ -219,10 +223,13 @@ inline constexpr Bool kMGPipeInputFieldSticky[kMGPipeInputFieldCount] = {
false, // IsCapabilityEnabledIndexed
false, // IsTransformFeedbackActive
false, // IsTransformFeedbackPaused
false, // InvalidateCompileEnv
false, // ValidateProgramName
false, // RecordError
true, // InvalidateCompileEnv: reverse channel: a write into the frontend, not a state read
true, // ValidateProgramName: keyed by GL name: a name-table lookup, not verb state
true, // RecordError: reverse channel: a write into the frontend, not a state read
false, // GetBoundTransformFeedbackLifetimeId
true, // HasOpenTransformFeedbackSpan: keyed by lifetime id: an object lookup, not verb state
};
inline constexpr SizeT kMGPipeInputStickyFieldCount = 7;
// Which call is expected to have filled a field by the time a verb reads it. Names
// come from Coverage.def, so this table and the coverage table cannot disagree.
@@ -288,6 +295,8 @@ inline constexpr const char* kMGPipeInputFieldFilledBy[kMGPipeInputFieldCount] =
"kClientResolved", // pseudo-call: not filled by a forward record
"kClientResolved", // pseudo-call: not filled by a forward record
"kReverseChannel", // pseudo-call: not filled by a forward record
"SetStreamOutputTargets",
"SetStreamOutputTargets",
};
struct MGPipeFilledState {