mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-11 12:03:24 +09:00
- MGPipeBarriered(op, payload, applierState), IMPLEMENTED, not stubbed: the static wait-class column plus the two payload-derived escalations the contract names (an open XFB span, a draw carrying kDrawClientArrays). One function and two callers is the point - the emit table and the sink must reach the same answer or the client runs on while the server reads a value that has already moved. set_context_values now mirrors IsTransformFeedbackActive into the applier state as well, because a predicate that read it out of gPipeInputs would be reading the very block run-ahead stops filling. - MGPipeApplierCurrentRecordIsBarriered() with the writer beside it. It answers true by default and that IS the landed lockstep answer, not a stub: on a server without kCapRunAheadApply every record is barriered and CONTRACT-P5C's two exemption scopes keep working unchanged. - The sb applier fields (BoundShaderBuffers[3][84], the three windows, the writable masks and ShaderBuffersSerial) and the pg record fields (the three binding tails, Signature, BindingsSerial) with the two entry points MGPipeApplySetShaderBuffers / MGPipeApplySetProgramBindings declared and ABORTING BY NAME. - The by-handle backend seams in Managers.h with aborting bodies in one block: ResolveVaoTwin, ResolveTextureTwin, ResolveProgramTwin, SyncTextureToBackendByHandle, SyncMipmapsToBackendByHandle, and the FBO / RBO / program SyncToBackendByHandle overloads. Five packages sit on opposite sides of these calls - tx2 writes what fb calls, fb writes what tx2 needs, id rekeys the registries all three read - so the signature is fixed once here and each family replaces a body. Abort and not null: a resolver that answered null renders a blank draw and a sync that did nothing renders stale pixels, and both are green lanes. - Coverage.def's GetBufferBindingPoint -> SetShaderBuffers row with BOTH of its PipeFill.cpp switch arms and the pairing asserts, shape-only and inert. It lands with the contract package because PipeFill.cpp belongs to the contract package for the whole phase - an emitter enumerator whose dispatch arm lived in the family's worktree is the merge trap that file's own comment was written about. - FieldOwnership.def re-annotates the six object-class rows plus GetProgramForDispatch to "P5e (Espryt unbarriered), P7 (Magma)", and the strict-abort case follows the string, which IS the debt entry rather than decoration. kMGPipeMaxBufferBindingPoints is pinned against BufferState.h's 84 where both are visible. gen_pipe_field_ownership's refusal count is 8.
307 lines
23 KiB
Modula-2
307 lines
23 KiB
Modula-2
// MobileGL - MobileGL/MG_Pipe/Coverage.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 hand-maintained half of G6 (plan B section 4.7, gate 10.3-5): which MGPipe call
|
|
// answers each backend read point in scripts/data/backend_read_inventory.md (477 rows, 57
|
|
// files, generated from the backends by MobileGL-CS's extract_backend_read_inventory.py).
|
|
//
|
|
// gen_pipe.py joins the inventory's `member` column against MGP_COVERAGE_ACCESSOR_LIST and
|
|
// its `delta` column against MGP_COVERAGE_DELTA_LIST, then writes generated/PipeCoverage.inc
|
|
// with the per-accessor table and prints the coverage summary. Rows matching neither are
|
|
// UNMAPPED: allowed in P0 and merely counted, ZERO from P5 onward, when the gate becomes
|
|
// "regenerate and git diff --exit-code with 0 UNMAPPED".
|
|
//
|
|
// Three pseudo-calls stand for read points that do NOT become a forward call:
|
|
// kClientResolved - the frontend answers it itself; the server is never asked
|
|
// (section 4.4.6: "the server answers nothing the client can answer").
|
|
// kReverseChannel - it becomes one of the ten MGPipeCallbacks (section 7.1).
|
|
// kStructuralHandle - the row is a SIGNATURE carrying SharedPtr<MG_State...>, which
|
|
// becomes an MGPipeHandle parameter; there is no single call to name.
|
|
//
|
|
// clang-format off
|
|
|
|
// X(Accessor, PipeCall)
|
|
#define MGP_COVERAGE_ACCESSOR_LIST(X) \
|
|
X(GetActiveTextureUnit, SetSamplerViews) \
|
|
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, and P3a SPLITS it - not by re-vendoring the */ \
|
|
/* inventory (the extractor lives in MobileGL-CS and still does not carry the */ \
|
|
/* target argument), but by supplying the target from the EMISSION SITE, which */ \
|
|
/* knows it exactly. The split, target by target, in BufferTarget's OWN */ \
|
|
/* spelling (BufferObject.h:15-33) so the list cross-checks mechanically: */ \
|
|
/* Vertex, and the per-attribute buffer of a VAO -> set_vertex_buffers */ \
|
|
/* Index -> set_index_buffer */ \
|
|
/* DrawIndirect, Parameter -> set_indirect_buffers */ \
|
|
/* Uniform, ShaderStorage, AtomicCounter, */ \
|
|
/* TransformFeedback -> set_shader_buffers */ \
|
|
/* CopyRead, CopyWrite, PixelPack, PixelUnpack, */ \
|
|
/* Texture -> still pulled: the */ \
|
|
/* transfer and pixel-store targets have no call of their own yet; */ \
|
|
/* DispatchIndirect -> still pulled, and */ \
|
|
/* it is the one a reader most plausibly assumes set_indirect_buffers */ \
|
|
/* covers: BOTH backends read it (SyncBoundBuffer at every */ \
|
|
/* glDispatchComputeIndirect) and NO call carries it - MGPIndirectBuffers */ \
|
|
/* is the DrawIndirect + Parameter pair only - so the field stays the */ \
|
|
/* fill loop's for this target; */ \
|
|
/* Query -> still pulled: no */ \
|
|
/* backend reads it at all and no call names it. */ \
|
|
/* That is 15 of 15; a target missing from this list is a target a later */ \
|
|
/* phase would retire the pull for on the strength of a split that never */ \
|
|
/* covered it. */ \
|
|
/* THE ROW STAYS ONE ROW, and that is structural rather than a shortcut: this */ \
|
|
/* list IS the MGPipeInputField enum and the PipeInputs field set, and the */ \
|
|
/* field is ONE array (m_bufferBindingSlot[kBufferTargetCount]) that a second */ \
|
|
/* row of the same name could only duplicate. So the split lives here and in */ \
|
|
/* the emitters, and the row keeps naming set_indirect_buffers for the plan's */ \
|
|
/* explicit replacement of the DrawIndirect/Parameter pair. It is deliberately */ \
|
|
/* NOT in the EMITTED list below: seven targets above are still pulled, and a */ \
|
|
/* row there says "the whole field is supplied", which for this field would be */ \
|
|
/* the same half-truth GetPixelStoreParameters is kept out for. */ \
|
|
X(GetBufferBindingSlot, SetIndirectBuffers) \
|
|
X(GetBufferBindingPoint, SetShaderBuffers) \
|
|
X(GetBufferBindingPointCount, SetShaderBuffers) \
|
|
X(GetTouchedBufferBindingPointCount, SetShaderBuffers) \
|
|
X(GetClampReadColor, SetDynamicState) \
|
|
X(GetClearColor, SetDynamicState) \
|
|
X(GetClearDepth, SetDynamicState) \
|
|
X(GetClearStencil, SetDynamicState) \
|
|
X(GetColorMaskIndexed, CreateRenderState) \
|
|
X(GetCullFaceMode, CreateRenderState) \
|
|
X(GetCurrentVertexAttribute, SetVertexAttribDefaults) \
|
|
X(GetDepthFunc, CreateRenderState) \
|
|
X(GetDepthMask, CreateRenderState) \
|
|
X(GetDepthRangeIndexed, SetDynamicState) \
|
|
X(GetFramebufferBindingSlot, SetFramebufferState) \
|
|
X(GetImageTextureBinding, SetShaderImages) \
|
|
X(GetLineWidth, SetDynamicState) \
|
|
X(GetLogicOp, CreateRenderState) \
|
|
X(GetMaxTouchedTextureUnit, SetSamplerViews) \
|
|
X(GetMinSampleShadingValue, CreateRenderState) \
|
|
X(GetPatchDefaultInnerLevel, SetPatchState) \
|
|
X(GetPatchDefaultOuterLevel, SetPatchState) \
|
|
X(GetPatchVertices, SetPatchState) \
|
|
X(GetPipelineStateVersion, BindRenderState) \
|
|
X(GetPixelStoreParameters, SetPixelPackState) \
|
|
X(GetPolygonModeFront, CreateRenderState) \
|
|
X(GetPolygonOffsetFactor, SetDynamicState) \
|
|
X(GetPolygonOffsetUnits, SetDynamicState) \
|
|
X(GetPrimitiveRestartIndex, DrawVbo) \
|
|
X(GetProgramForDispatch, SetDispatchProgram) \
|
|
X(GetProgramForDraw, SetDrawProgram) \
|
|
X(GetProgramObject, CreateShaderState) \
|
|
/* ANSWERED by P2: it is in the pipeline half. SetProvokingVertexMode calls */ \
|
|
/* BumpVersions(), and the chunk table's rule is exactly that, so it rides */ \
|
|
/* pipeline chunk P4 - a strict superset of what ComputePipelineStateHash used */ \
|
|
/* to hash (MGPipeRenderStateSpans.cpp records the provenance). */ \
|
|
X(GetProvokingVertexMode, CreateRenderState) \
|
|
X(GetRenderStateParameters, CreateRenderState) \
|
|
X(GetRenderStateParametersVersion, BindRenderState) \
|
|
X(GetSamplingResolutionGeneration, SetSamplerViews) \
|
|
X(GetScissorBox, SetDynamicState) \
|
|
X(GetStencilState, CreateRenderState) \
|
|
X(GetTextureBindGeneration, SetSamplerViews) \
|
|
X(GetTextureContextId, SetSamplerViews) \
|
|
X(GetTextureObject, SetSamplerViews) \
|
|
X(GetTextureUnitObject, SetSamplerViews) \
|
|
X(GetTransformFeedbackCapturedVertices, DrawVbo) \
|
|
X(GetTransformFeedbackGeneration, SetStreamOutputTargets) \
|
|
X(GetTransformFeedbackPausedPrimitiveCounter, EndStreamOutput) \
|
|
X(GetTransformFeedbackProgram, SetStreamOutputTargets) \
|
|
X(GetViewport, SetDynamicState) \
|
|
X(GetViewportIndexed, SetDynamicState) \
|
|
X(IsCapabilityEnabled, CreateRenderState) \
|
|
X(IsCapabilityEnabledIndexed, CreateRenderState) \
|
|
X(IsTransformFeedbackActive, BeginStreamOutput) \
|
|
X(IsTransformFeedbackPaused, PauseStreamOutput) \
|
|
X(InvalidateCompileEnv, kClientResolved) \
|
|
X(ValidateProgramName, kClientResolved) \
|
|
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
|
|
// inventory's own free-text labels, not C tokens.
|
|
#define MGP_COVERAGE_DELTA_LIST(X) \
|
|
X(handle-ify (wire handle), kStructuralHandle) \
|
|
X(Buffer ops delta, ResourceRespecify)
|
|
|
|
// X(Accessor, PipeCall) - the EMITTED list (P2 brief D5): which P2 call now SUPPLIES this
|
|
// PipeInputs field, so the per-verb residual fill loop no longer has to pull it out of
|
|
// GLContext. gen_pipe.py turns it into kMGPipeFieldEmittedBy[] (generated/PipeFilled.inc);
|
|
// a field with no row here keeps going through the fill loop, which is what makes the
|
|
// MOBILEGL_PIPE_PUSH bitmask a true per-subsystem A/B rather than an all-or-nothing switch.
|
|
//
|
|
// Every name must be an accessor in MGP_COVERAGE_ACCESSOR_LIST and every call must be a
|
|
// real call in PipeCalls.def; gen_pipe.py refuses anything else.
|
|
//
|
|
// The one row whose call differs from the accessor list's is GetPrimitiveRestartIndex:
|
|
// coverage maps it onto draw_vbo because that is where a backend reads it, but the VALUE
|
|
// travels in dynamic chunk D6, so set_dynamic_state is what supplies it.
|
|
//
|
|
// GetPixelStoreParameters is DELIBERATELY ABSENT, and the reason is the shape of the field
|
|
// rather than of the call. The field is PipeInputs::m_pixelStore[2] - pack AND unpack - and
|
|
// set_pixel_pack_state carries the PACK half only, deliberately and permanently (D10,
|
|
// ARCHITECTURE.md 4.6 D5: nothing on the far side of the boundary reads unpack state). A row
|
|
// here says "this field is supplied, the fill loop may skip it", which would be a half-truth:
|
|
// the moment the render-state bitmask has its bit set, the unpack half would be written by
|
|
// nothing while its poison stamp said it was published, so neither the poison nor the verify
|
|
// comparator could see it. Until the field is split, the whole of it keeps going through the
|
|
// fill loop and the pack half is simply written twice.
|
|
//
|
|
// P3a ADDS ONE ROW, GetBoundVertexArray -> BindVertexElements, and it is the vertex-input
|
|
// family's only candidate: GetBufferBindingSlot is polymorphic over a target set P3a covers
|
|
// only part of (see its comment above) and GetCurrentVertexAttribute has been here since P2.
|
|
// The row is INERT until the vertex-input subsystem is wired - MG_Impl/Pipe/PipeFill.cpp's
|
|
// kMGPipeWiredSubsystems does not carry that bit at the contract commit, because the emitters
|
|
// beside it are still stubs - which is exactly the guard that lets a row land before the call
|
|
// that carries it exists.
|
|
//
|
|
// A NOTE FOR THE COMMIT THAT WIRES IT, because it is not visible from this file: the field is
|
|
// a shared pointer to the frontend VAO, and the vertex-input calls supply the CONFIGURATION
|
|
// (the applier's MGPipeVertexElementsRecord), not the object. So the row is shape-only in the
|
|
// same sense GetCurrentVertexAttribute's is, and it stays so until the backend's twin
|
|
// resolution reads the applier's BoundVertexElements instead of the object - at which point
|
|
// PipeFill.cpp's EmittedCallSuppliesTheWholeField arm is where that is decided, deliberately
|
|
// rather than silently by this row's presence.
|
|
//
|
|
// P4a ADDS SIX ROWS, and the same note applies to every one of them: each is SHAPE-ONLY, each
|
|
// lands in PipeFill.cpp's EmittedCallSuppliesTheWholeField FALSE arm, and the decision is
|
|
// taken THERE rather than inherited from a row's presence here. The rows and their calls:
|
|
//
|
|
// GetFramebufferBindingSlot -> SetFramebufferState GetProgramForDraw -> SetDrawProgram
|
|
// GetImageTextureBinding -> SetShaderImages GetProgramForDispatch -> SetDispatchProgram
|
|
// GetTextureUnitObject -> SetSamplerViews GetMaxTouchedTextureUnit -> SetSamplerViews
|
|
//
|
|
// Five of the six are the pointer-storage case GetBoundVertexArray already documents: the
|
|
// field is a BindingSlot<FramebufferObject>, an ImageTextureBinding, a TextureUnit or a
|
|
// SharedPtr<ProgramObject> - frontend heap references - and the calls carry eight-byte
|
|
// {slot, gen} handles and resolved descriptors. The applier has no way to produce a pointer
|
|
// and P4a deliberately does not give it one; skipping the pull would leave every one of those
|
|
// mirrors null on every draw of every push build. What retires those pulls is not a better
|
|
// applier, it is the phase where the backend stops reading a frontend object at all.
|
|
//
|
|
// THE SIXTH left that arm at P5c rv: GetMaxTouchedTextureUnit is a plain Int whose problem was
|
|
// never shape, it was the CARRIER - set_sampler_views' Count is the set's window, and the set
|
|
// is suppressed on an unchanged content hash while the high-water mark still moves on a
|
|
// redundant re-bind. set_context_values (CONTRACT-P5C.md §5.3) carries the mark as a VALUE of
|
|
// its own, whole-record suppressed, so the mark rides an unsuppressed field and the row is
|
|
// RECORD_SUPPLIED outright.
|
|
//
|
|
// P5c rv ADDS EIGHT ROWS, and they are the whole of the value-class debt that was left
|
|
// (CONTRACT-P5C.md §5.3): seven residual values no set_* call carried - the two texture-unit
|
|
// counters, the 15-target touched-count array and the five transform-feedback values - plus
|
|
// GetMaxTouchedTextureUnit re-homed from SetSamplerViews. All eight name SetContextValues, one
|
|
// POD emitted at validate when any covered value moved, hash-suppressed whole. The OBJECT rows
|
|
// (GetTextureUnitObject and its four P4a siblings above) stay BARRIER_PULLED with their
|
|
// retiring phases; the three texture shutters (below) take no row here either - they carry no
|
|
// wire value at all, the accessors answer the applier's own Serial.
|
|
//
|
|
// GetTextureContextId / GetTextureBindGeneration / GetSamplingResolutionGeneration stay out
|
|
// DELIBERATELY, and the reason is ownership rather than coverage: they are frontend SHUTTERS,
|
|
// and what replaces them server-side is the applier's own Serial - a different value with a
|
|
// different owner. A row here would claim the sets supply the generations, and the fill loop
|
|
// would skip two counters no record carries.
|
|
// And GetTextureObject / GetProgramObject are STICKY (see MGP_COVERAGE_STICKY_LIST): they are
|
|
// keyed by GL name, they are object lookups rather than verb state, and a forwarded field has
|
|
// no storage for an emitted call to supply.
|
|
//
|
|
// P5e ADDS ONE ROW, GetBufferBindingPoint -> SetShaderBuffers (MG_Remote/CONTRACT-P5E.md §5.6),
|
|
// and it is SHAPE-ONLY like P3a's and P4a's six: the field's storage is four raw bases into the
|
|
// frontend's Array<Array<BindingSlotRange1D, 84>, 4>, and set_shader_buffers carries RESOLVED
|
|
// {handle, offset, size} ranges per class. The applier has no way to produce a pointer and P5e
|
|
// deliberately does not give it one, so the row lands in PipeFill.cpp's
|
|
// EmittedCallSuppliesTheWholeField FALSE arm and the decision is taken THERE. What retires the
|
|
// pull is not a better applier, it is the four Espryt consumers reading the applier's
|
|
// BoundShaderBuffers instead of the frontend's binding points - at which point the
|
|
// FieldOwnership.def row flips to RECORD_SUPPLIED.
|
|
//
|
|
// THE ROW IS INERT AT THIS COMMIT for GetBoundVertexArray's reason one phase on: the emission
|
|
// and the fill skip both test kMGPipeWiredSubsystems, and the buffer-binding family's wired
|
|
// constant is 0 until the package that gives MG_Impl/Pipe/ShaderBufferEmit.h its body sets it.
|
|
// It lands here, with its two PipeFill.cpp switch arms, because this file and that one belong
|
|
// to the contract package for the whole phase - a family package that had to add an enumerator
|
|
// AND the arm that dispatches on it would be editing the one file the merge trap lives in.
|
|
#define MGP_COVERAGE_EMITTED_LIST(X) \
|
|
X(GetActiveTextureUnit, SetContextValues) \
|
|
X(GetBlendColor, SetDynamicState) \
|
|
X(GetBlendEquationIndexed, CreateRenderState) \
|
|
X(GetBlendFuncIndexed, CreateRenderState) \
|
|
X(GetBoundTransformFeedbackLifetimeId, SetContextValues) \
|
|
X(GetBoundVertexArray, BindVertexElements) \
|
|
X(GetBufferBindingPoint, SetShaderBuffers) \
|
|
X(GetClampReadColor, SetDynamicState) \
|
|
X(GetClearColor, SetDynamicState) \
|
|
X(GetClearDepth, SetDynamicState) \
|
|
X(GetClearStencil, SetDynamicState) \
|
|
X(GetColorMaskIndexed, CreateRenderState) \
|
|
X(GetCullFaceMode, CreateRenderState) \
|
|
X(GetCurrentVertexAttribute, SetVertexAttribDefaults) \
|
|
X(GetDepthFunc, CreateRenderState) \
|
|
X(GetDepthMask, CreateRenderState) \
|
|
X(GetDepthRangeIndexed, SetDynamicState) \
|
|
X(GetFramebufferBindingSlot, SetFramebufferState) \
|
|
X(GetImageTextureBinding, SetShaderImages) \
|
|
X(GetLineWidth, SetDynamicState) \
|
|
X(GetLogicOp, CreateRenderState) \
|
|
X(GetMaxTouchedTextureUnit, SetContextValues) \
|
|
X(GetMinSampleShadingValue, CreateRenderState) \
|
|
X(GetPatchDefaultInnerLevel, SetPatchState) \
|
|
X(GetPatchDefaultOuterLevel, SetPatchState) \
|
|
X(GetPatchVertices, SetPatchState) \
|
|
X(GetPipelineStateVersion, BindRenderState) \
|
|
X(GetPolygonModeFront, CreateRenderState) \
|
|
X(GetPolygonOffsetFactor, SetDynamicState) \
|
|
X(GetPolygonOffsetUnits, SetDynamicState) \
|
|
X(GetPrimitiveRestartIndex, SetDynamicState) \
|
|
X(GetProgramForDispatch, SetDispatchProgram) \
|
|
X(GetProgramForDraw, SetDrawProgram) \
|
|
X(GetProvokingVertexMode, CreateRenderState) \
|
|
X(GetRenderStateParameters, CreateRenderState) \
|
|
X(GetRenderStateParametersVersion, BindRenderState) \
|
|
X(GetScissorBox, SetDynamicState) \
|
|
X(GetStencilState, CreateRenderState) \
|
|
X(GetTextureUnitObject, SetSamplerViews) \
|
|
X(GetTouchedBufferBindingPointCount, SetContextValues) \
|
|
X(GetTransformFeedbackCapturedVertices, SetContextValues) \
|
|
X(GetTransformFeedbackGeneration, SetContextValues) \
|
|
X(GetViewport, SetDynamicState) \
|
|
X(GetViewportIndexed, SetDynamicState) \
|
|
X(IsCapabilityEnabled, CreateRenderState) \
|
|
X(IsCapabilityEnabledIndexed, CreateRenderState) \
|
|
X(IsTransformFeedbackActive, SetContextValues) \
|
|
X(IsTransformFeedbackPaused, SetContextValues)
|
|
|
|
// clang-format on
|