mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Refactor] (P13 W3b): strip the push/legacy-memo guards from MG_State, MG_Util and the config
This commit is contained in:
@@ -377,7 +377,6 @@ namespace MobileGL::MG_Config {
|
||||
// the semantic gate that replaces byte identity, and it catches the dangerous
|
||||
// direction - a dirty bit that fires too RARELY - which no purity gate can see.
|
||||
Bool PipeVerify = false;
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// The three knobs of the MOBILEGL_PIPE_VERIFY build (P1 brief D2). Compiled only
|
||||
// under MOBILEGL_PIPE_PUSH so the pull build's FeaturesTable does not change size.
|
||||
// MOBILEGL_PIPE_VERIFY_FATAL: the first divergence aborts (default). 0 logs and
|
||||
@@ -408,7 +407,6 @@ namespace MobileGL::MG_Config {
|
||||
// measurement and for what the control still leaves standing. Under
|
||||
// MOBILEGL_PIPE_PUSH only, so it cannot exist in a shipping pull build.
|
||||
Bool PipeHandleAbaControl = false;
|
||||
#endif
|
||||
// MOBILEGL_PIPE_STATS: dump the boundary counters (bytes, calls, roundtrips,
|
||||
// texture pulls, upload shapes, residual-block bytes, index mirror bytes).
|
||||
Bool PipeStats = false;
|
||||
|
||||
@@ -10,12 +10,10 @@
|
||||
#include <sys/system_properties.h>
|
||||
#endif
|
||||
#include "Config.h"
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// For kMGPipeSubsystemsMigratedAtP5e, the push build's PipePush default (the P2, P3a and P4a
|
||||
// constants beside it are the phase-by-phase controls, not the default). Push-only, so the
|
||||
// pull build's translation unit is unchanged.
|
||||
#include <MG_Pipe/MGPipe.h>
|
||||
#endif
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
@@ -386,27 +384,19 @@ namespace MobileGL::MG_ConfigLoader {
|
||||
// MGPipe. Nothing here needs adding to an allow-list: InitializeAcceptedEnvVariables
|
||||
// accepts every MOBILEGL_ / LIBGL_ prefixed variable in the environment, so a name
|
||||
// that starts with MOBILEGL_ is visible to these queries by construction.
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// A push build with the knob unset runs every subsystem migrated so far, so the
|
||||
// shipped path is the one the gates measure; MOBILEGL_PIPE_PUSH=0 in the
|
||||
// environment is the all-subsystems-pull control that reproduces P1 exactly, and
|
||||
// kMGPipeSubsystemsMigratedAtP3a (0x1ff) is the phase-by-phase control - P4a's four
|
||||
// subsystems off, everything P3a landed still on.
|
||||
features.PipePush = QueryEnvUint64("MOBILEGL_PIPE_PUSH", MG_Pipe::kMGPipeSubsystemsMigratedAtP5e);
|
||||
#else
|
||||
// Meaningless in a pull build: there is nothing to push. Config.h documents 0 as
|
||||
// "pull everything" and that stays literally true.
|
||||
features.PipePush = QueryEnvUint64("MOBILEGL_PIPE_PUSH", 0);
|
||||
#endif
|
||||
features.PipeVerify = QueryEnvFlag("MOBILEGL_PIPE_VERIFY");
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// Defaults ON: read as a tri-state so only an explicitly falsy value turns it off.
|
||||
features.PipeVerifyFatal =
|
||||
QueryEnvQuirkOverride("MOBILEGL_PIPE_VERIFY_FATAL") != MG_Config::QuirkOverride::ForceOff;
|
||||
QueryEnvVariable("MOBILEGL_PIPE_VERIFY_CORRUPT", features.PipeVerifyCorrupt, "");
|
||||
QueryEnvVariable("MOBILEGL_PIPE_POISON_OMIT", features.PipePoisonOmit, "");
|
||||
features.PipeHandleAbaControl = QueryEnvFlag("MOBILEGL_PIPE_HANDLE_ABA_CONTROL");
|
||||
#endif
|
||||
features.PipeStats = QueryEnvFlag("MOBILEGL_PIPE_STATS");
|
||||
// Defaults ON, so the flag has to be read as a tri-state rather than as a plain
|
||||
// truthy check: unset must keep the memos, and only an explicitly falsy value may
|
||||
|
||||
@@ -82,7 +82,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
BufferObject::BufferObject(Uint externalIndex)
|
||||
: m_externalIndex(externalIndex), m_size(0), m_usage(BufferUsage::StaticDraw), m_isMapped(false),
|
||||
m_mappingAccess(BufferMappingAccessBit::Null), m_mappedRange({0, 0}), m_ownsStagingData{} {
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P3a D-A2: a resource EXISTS before anything can name it, so resource_create is
|
||||
// emitted from the constructor and carries no storage - the store is defined lazily
|
||||
// by the first respecify and every backend already tolerates a resource with none.
|
||||
@@ -90,7 +89,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// set_vertex_buffers names this buffer by handle out of a different subsystem.
|
||||
MG_Pipe::MGPipeMintResourceHandle(*this);
|
||||
if (MG_Pipe::MGPipeResourceSubsystemEnabled()) MG_Pipe::MGPipeEmitResourceCreate(*this);
|
||||
#endif
|
||||
}
|
||||
|
||||
BufferObject::~BufferObject() {
|
||||
@@ -101,7 +99,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// for a buffer that was never a member.
|
||||
MG_Remote::Client::PersistentMapTracker::Instance().Forget(*this);
|
||||
#endif
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P3a D-L: the buffer's death crosses as resource_destroy, which is the catalogue
|
||||
// call for it - no seventh NotifyStateObjectDestroyed raiser is added, because that
|
||||
// header exists for kinds that have no such call. The emit-then-free ORDER is fixed
|
||||
@@ -112,7 +109,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// a pipe record to drop and no legacy backend object, and one constructed the other
|
||||
// way round has the opposite, so the create's answer is the only one that pairs.
|
||||
if (MG_Pipe::MGPipeEmitResourceDestroyAndFree(*this)) return;
|
||||
#endif
|
||||
if (m_resource.Backend() && g_bufferBackendOps && g_bufferBackendOps->OnDestroy) {
|
||||
g_bufferBackendOps->OnDestroy(m_resource.ReleaseBackend());
|
||||
}
|
||||
@@ -121,12 +117,10 @@ namespace MobileGL::MG_State::GLState {
|
||||
void BufferObject::NotifyRespecify() {
|
||||
++m_changeSerial;
|
||||
MGP_NOTE_AGGREGATE(BufferChange);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
if (MG_Pipe::MGPipeResourceSubsystemEnabled()) {
|
||||
MG_Pipe::MGPipeEmitResourceRespecify(*this);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (g_bufferBackendOps && g_bufferBackendOps->Respecify) {
|
||||
g_bufferBackendOps->Respecify(*this);
|
||||
}
|
||||
@@ -137,12 +131,10 @@ namespace MobileGL::MG_State::GLState {
|
||||
MGP_NOTE_AGGREGATE(BufferChange);
|
||||
if (size == 0) return;
|
||||
m_hasDefinedContent = true;
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
if (MG_Pipe::MGPipeResourceSubsystemEnabled()) {
|
||||
MG_Pipe::MGPipeEmitResourceSubData(*this, offset, size);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (g_bufferBackendOps && g_bufferBackendOps->SubData) {
|
||||
g_bufferBackendOps->SubData(*this, offset, size);
|
||||
}
|
||||
@@ -153,7 +145,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
MGP_NOTE_AGGREGATE(BufferChange);
|
||||
if (range.start >= range.end) return;
|
||||
m_hasDefinedContent = true;
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
if (MG_Pipe::MGPipeResourceSubsystemEnabled()) {
|
||||
static_assert(sizeof(appAccess.GetRaw()) <= sizeof(Uint32),
|
||||
"MGPFlushRange::AccessFlags is a Uint32 and carries the application's "
|
||||
@@ -162,7 +153,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
static_cast<Uint32>(appAccess.GetRaw()));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (g_bufferBackendOps && g_bufferBackendOps->FlushMappedRange) {
|
||||
g_bufferBackendOps->FlushMappedRange(*this, range, appAccess);
|
||||
}
|
||||
@@ -293,12 +283,10 @@ namespace MobileGL::MG_State::GLState {
|
||||
if (m_size < kLargeBufferAdoptBytes) return;
|
||||
if (m_resource.IsGpuResident()) return;
|
||||
if (m_isMapped) return;
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
if (MG_Pipe::MGPipeResourceSubsystemEnabled()) {
|
||||
if (void* base = MG_Pipe::MGPipeEmitMapPersistent(*this)) m_resource.AdoptPersistentMap(base);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
// R-6 IS "ALWAYS", AND THIS IS ITS SECOND DOOR. MGPipeApplyMapPersistent declines
|
||||
// every acquisition under split - but a split build whose backend registered no
|
||||
@@ -588,7 +576,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// phase only gives the client a conservative set, and a zero-range announcement stays
|
||||
// illegal until P8/P9 make it mean "fully narrowed - nothing is dirty".
|
||||
if (MG_Config::Transport != MG_Config::TransportMode::Monolith) {
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
if (m_size != 0 && MG_Pipe::MGPipeResourceSubsystemEnabled() && m_resource.IsGpuResident()) {
|
||||
// P11 B2: A T0 STORE IS READ WHERE IT IS. Under split a store is resident only
|
||||
// when T0 adopted it - its pages ARE the client's AHardwareBuffer - so no bytes
|
||||
@@ -631,7 +618,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// emission was synchronous and the writeback has already cleared the flag.
|
||||
MG_Remote::Client::AwaitBufferWriteback(*this);
|
||||
}
|
||||
#endif
|
||||
// A buffer with no readback route - no size, or a backend that registered no
|
||||
// resource ops - can never catch up, and retrying on every subsequent read would
|
||||
// only repeat the same no-op. That is the ONE case the monolith clear covers that
|
||||
@@ -645,7 +631,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// Cleared unconditionally: without a readback op the shadow can never catch up,
|
||||
// and retrying on every subsequent read would only repeat the same no-op.
|
||||
m_gpuWritePending = false;
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
if (m_size != 0 && MG_Pipe::MGPipeResourceSubsystemEnabled()) {
|
||||
// The answer comes back through the reverse channel's OnBufferWriteback, which
|
||||
// resolves this handle to this object and writes the shadow before the server
|
||||
@@ -655,7 +640,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
MG_Pipe::MGPipeEmitResourceReadback(*this);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (m_size == 0 || g_bufferBackendOps == nullptr || g_bufferBackendOps->ReadbackFromGpu == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -704,7 +688,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// NotifyContentWrite on a resident store only bumps the serial: the backend has no
|
||||
// separate copy to sync, so no transfer op runs.
|
||||
void BufferObject::LandBytesIntoResidentStore(SizeT offset, DataPtr bytes) {
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// buffer_subdata_resident stays NULLABLE and stays asymmetric: one backend
|
||||
// deliberately does not implement it, and the frontend checks the pipe table exactly
|
||||
// as it checks the op table it replaces, so a backend without it keeps the legacy
|
||||
@@ -727,7 +710,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
NotifyContentWrite(offset, bytes.size);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (bytes.size > 0 && g_bufferBackendOps && g_bufferBackendOps->ResidentSubData) {
|
||||
g_bufferBackendOps->ResidentSubData(*this, offset, bytes);
|
||||
m_hasDefinedContent = true;
|
||||
@@ -762,14 +744,10 @@ namespace MobileGL::MG_State::GLState {
|
||||
// fills in place anyway, so a whole-arena clear would allocate a whole arena
|
||||
// for nothing.
|
||||
if (m_resource.IsGpuResident() &&
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// The same question, asked of whichever table owns the family in this build.
|
||||
(MG_Pipe::MGPipeResourceSubsystemEnabled()
|
||||
? MG_Pipe::MGPipeResourceOpsHaveSubDataResident()
|
||||
: (g_bufferBackendOps && g_bufferBackendOps->ResidentSubData))
|
||||
#else
|
||||
g_bufferBackendOps && g_bufferBackendOps->ResidentSubData
|
||||
#endif
|
||||
) {
|
||||
Vector<Uint8> expanded(size);
|
||||
if (pattern.size == 1) {
|
||||
@@ -878,14 +856,12 @@ namespace MobileGL::MG_State::GLState {
|
||||
if (m_isMapped) {
|
||||
return false;
|
||||
}
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
if (m_size != 0 && MG_Pipe::MGPipeResourceSubsystemEnabled()) {
|
||||
void* pushedBase = MG_Pipe::MGPipeEmitMapPersistent(*this);
|
||||
if (pushedBase == nullptr) return false;
|
||||
m_resource.AdoptPersistentMap(pushedBase);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
// R-6's second door, as in TryAdoptLargeStorage above.
|
||||
if (MG_Config::Transport != MG_Config::TransportMode::Monolith) return false;
|
||||
@@ -943,7 +919,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// returning; AdoptPersistentMap then releases the shadow. Falls back to the
|
||||
// shadow when the backend declines (returns null). Only attempted once - the
|
||||
// storage is immutable and outlives unmap/remap.
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
if (!m_resource.IsGpuResident() && (access & BufferMappingAccessBit::Write) &&
|
||||
!(access & BufferMappingAccessBit::FlushExplicit) &&
|
||||
MG_Pipe::MGPipeResourceSubsystemEnabled()) {
|
||||
@@ -967,7 +942,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
}
|
||||
return m_resource.Bytes() + range.start;
|
||||
}
|
||||
#endif
|
||||
if (!m_resource.IsGpuResident() && (access & BufferMappingAccessBit::Write) &&
|
||||
!(access & BufferMappingAccessBit::FlushExplicit) &&
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
|
||||
@@ -40,7 +40,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
if (bindingPoint.GetBoundObject() == bufferObject) {
|
||||
bindingPoint.Bind(nullptr);
|
||||
bindingPoint.ClearRange();
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// An UNBIND, and the one writer of an indexed point that is not an
|
||||
// entry point (GL_Buffer.cpp's BindBuffer{Base,Range}_State and
|
||||
// Core.cpp's transform-feedback writers bump their own): without the
|
||||
@@ -51,7 +50,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// "BackendSlotTable.Generation"} (DeletedBoundBufferScenario).
|
||||
NoteBindPointChanged(BufferBindPointTargets[static_cast<SizeT>(
|
||||
&bindingPointArray - m_bufferBindPointTargets.data())]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// resets the deleting context's bindings, and other contexts keep their own).
|
||||
void UnbindBufferObject(const SharedPtr<BufferObject>& bufferObject);
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P2 brief D4: "did the contents of ANY buffer object move". One counter for every
|
||||
// BufferObject ++m_changeSerial site, which is what NEW_VERTEX_BUFFERS /
|
||||
// NEW_INDEX_BUFFER / NEW_CONST_BUFFERS / NEW_SHADER_BUFFERS / NEW_SO_TARGETS all
|
||||
@@ -102,13 +101,10 @@ namespace MobileGL::MG_State::GLState {
|
||||
if (it == BufferBindPointTargets.end()) return 0;
|
||||
return m_bindPointGeneration[std::distance(BufferBindPointTargets.begin(), it)];
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
Uint64 m_anyBufferChangeGeneration = 0;
|
||||
Array<Uint64, BufferBindPointTargets.size()> m_bindPointGeneration{};
|
||||
#endif
|
||||
Array<BindingSlot<BufferObject>, GlobalBufferTargets.size()> m_bindingSlots;
|
||||
// TODO: query the count somewhere globally?
|
||||
// For glBindBufferBase / glBindBufferRange
|
||||
|
||||
@@ -277,11 +277,9 @@ namespace MobileGL::MG_State {
|
||||
current.intValue[component] = static_cast<Int32>(value[component]);
|
||||
current.uintValue[component] = static_cast<Uint32>(value[component]);
|
||||
}
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// The two views above are CONVERSIONS, not bit copies, so which one was written
|
||||
// is part of the value; set_vertex_attrib_defaults carries it.
|
||||
m_currentVertexAttributeClasses[index] = kVertexAttribValueClassFloat;
|
||||
#endif
|
||||
MGP_NOTE_AGGREGATE(VertexAttribDefault);
|
||||
}
|
||||
|
||||
@@ -297,9 +295,7 @@ namespace MobileGL::MG_State {
|
||||
current.floatValue[component] = static_cast<Float>(value[component]);
|
||||
current.uintValue[component] = static_cast<Uint32>(value[component]);
|
||||
}
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
m_currentVertexAttributeClasses[index] = kVertexAttribValueClassInt;
|
||||
#endif
|
||||
MGP_NOTE_AGGREGATE(VertexAttribDefault);
|
||||
}
|
||||
|
||||
@@ -315,9 +311,7 @@ namespace MobileGL::MG_State {
|
||||
current.floatValue[component] = static_cast<Float>(value[component]);
|
||||
current.intValue[component] = static_cast<Int32>(value[component]);
|
||||
}
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
m_currentVertexAttributeClasses[index] = kVertexAttribValueClassUint;
|
||||
#endif
|
||||
MGP_NOTE_AGGREGATE(VertexAttribDefault);
|
||||
}
|
||||
|
||||
@@ -1427,13 +1421,11 @@ namespace MobileGL::MG_State {
|
||||
}
|
||||
|
||||
void GLContext::RestoreBoundTransformFeedbackState() {
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// The FOURTH writer of the transform-feedback binding points (a bind or a delete of
|
||||
// the bound transform-feedback object swaps the whole set in): it moves the generation
|
||||
// like the other three, so bit 17 cannot miss a swap whose two objects happen to carry
|
||||
// the same capture-span generation.
|
||||
NoteBufferBindPointChanged(BufferTarget::TransformFeedback);
|
||||
#endif
|
||||
const auto& object = m_transformFeedbackObjects[m_boundTransformFeedback];
|
||||
for (Uint i = 0; i < MAX_TRANSFORM_FEEDBACK_BUFFERS; ++i) {
|
||||
auto& point = m_bufferState.GetBindingPoint(BufferTarget::TransformFeedback, i);
|
||||
@@ -1638,7 +1630,6 @@ namespace MobileGL::MG_State {
|
||||
Bool hasExplicitRange) {
|
||||
if (bufferIndex >= MAX_TRANSFORM_FEEDBACK_BUFFERS) return;
|
||||
if (index == m_boundTransformFeedback) {
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P5e (sb): the THIRD writer of a transform-feedback binding point, and the one
|
||||
// a reader of GL_Buffer.cpp alone would miss - glTransformFeedbackBufferBase /
|
||||
// ...Range on the CURRENTLY BOUND object land here rather than in
|
||||
@@ -1648,7 +1639,6 @@ namespace MobileGL::MG_State {
|
||||
// POINT at all (it writes the named object's own table) and deliberately bumps
|
||||
// nothing.
|
||||
NoteBufferBindPointChanged(BufferTarget::TransformFeedback);
|
||||
#endif
|
||||
auto& point = m_bufferState.GetBindingPoint(BufferTarget::TransformFeedback, bufferIndex);
|
||||
point.Bind(buffer);
|
||||
if (buffer && hasExplicitRange) {
|
||||
|
||||
@@ -41,7 +41,6 @@ namespace MobileGL {
|
||||
#endif
|
||||
|
||||
namespace GLState {
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// MGPAttribValue::ValueClass' encoding (MG_Pipe/MGPipeTypes.h documents the order
|
||||
// "Float | Int | Uint | Double"). It lives here rather than in MG_Pipe because the
|
||||
// FRONTEND is the only thing that knows which of the three views below a value was
|
||||
@@ -50,7 +49,6 @@ namespace MobileGL {
|
||||
inline constexpr Uint32 kVertexAttribValueClassFloat = 0;
|
||||
inline constexpr Uint32 kVertexAttribValueClassInt = 1;
|
||||
inline constexpr Uint32 kVertexAttribValueClassUint = 2;
|
||||
#endif
|
||||
|
||||
struct CurrentVertexAttributeValue {
|
||||
Array<Float, 4> floatValue{0.f, 0.f, 0.f, 1.f};
|
||||
@@ -186,14 +184,12 @@ namespace MobileGL {
|
||||
m_textureState.NoteUnitTouched(unit, bindingChanged);
|
||||
}
|
||||
Int GetMaxTouchedTextureUnit() const { return m_textureState.GetMaxTouchedUnit(); }
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// The IMAGE-unit high-water mark, which is a different namespace from the
|
||||
// texture-unit one above - see TextureState::NoteImageUnitTouched for why it is a
|
||||
// second mark and why it only grows. Push builds only, so the pull build's
|
||||
// GLContext is untouched (G1).
|
||||
void NoteImageUnitTouched(Int unit) { m_textureState.NoteImageUnitTouched(unit); }
|
||||
Int GetMaxTouchedImageUnit() const { return m_textureState.GetMaxTouchedImageUnit(); }
|
||||
#endif
|
||||
// Monotonic counter bumped whenever a texture bind/unbind/delete changes which
|
||||
// texture is bound at a unit; lets a backend skip re-resolving an unchanged
|
||||
// per-draw sampled-texture set.
|
||||
@@ -268,7 +264,6 @@ namespace MobileGL {
|
||||
Uint GetBoundProgramPipelineName() const { return m_boundProgramPipeline; }
|
||||
const SharedPtr<ProgramPipelineObject>& GetBoundProgramPipeline() const;
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// ---- the aggregate generations (P2 brief D4) ----
|
||||
//
|
||||
// The bump points sit on OBJECTS - a VertexArrayObject, a TextureObject, a
|
||||
@@ -334,7 +329,6 @@ namespace MobileGL {
|
||||
? m_currentVertexAttributeClasses[index]
|
||||
: kVertexAttribValueClassFloat;
|
||||
}
|
||||
#endif
|
||||
|
||||
// RenderState
|
||||
Uint GetRenderStateParametersVersion() const;
|
||||
@@ -665,11 +659,9 @@ namespace MobileGL {
|
||||
Bool m_transformFeedbackPaused = false;
|
||||
GLenum m_transformFeedbackPrimitiveMode = GL_POINTS;
|
||||
SharedPtr<ProgramObject> m_transformFeedbackProgram;
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
Uint64 m_anyVertexAttribDefaultGeneration = 0;
|
||||
// Parallel to m_currentVertexAttributes; see GetCurrentVertexAttributeClass.
|
||||
Array<Uint32, VertexArrayObject::MAX_VERTEX_ATTRIBS> m_currentVertexAttributeClasses{};
|
||||
#endif
|
||||
Uint64 m_transformFeedbackGeneration = 0;
|
||||
// Source of the per-span ids above; never rolls back with an object switch.
|
||||
Uint64 m_transformFeedbackNextGeneration = 0;
|
||||
|
||||
@@ -23,7 +23,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
return s_nextFramebufferLifetimeId.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
FramebufferObject::~FramebufferObject() {
|
||||
// P4a D-I2: A FRAMEBUFFER HAS A HANDLE AND NO WIRE LIFETIME. PipeCalls.def carries
|
||||
// resource_destroy and five delete_* rows and NO framebuffer delete, because a
|
||||
@@ -42,7 +41,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// record's ContentHash.
|
||||
MG_Pipe::MGPipeEmitFramebufferDestroyAndFree(m_lifetimeId);
|
||||
}
|
||||
#endif
|
||||
|
||||
// FramebufferAttachmentObject
|
||||
FramebufferAttachmentObject::FramebufferAttachmentObject(
|
||||
|
||||
@@ -115,12 +115,10 @@ namespace MobileGL {
|
||||
Array<Uint16, static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>;
|
||||
|
||||
FramebufferObject(Uint externalIndex);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P2 step e2. Out of line, and declared only where there is a notice to raise:
|
||||
// in a pull build this class keeps its implicit destructor, which is what keeps
|
||||
// the pull build's symbol set byte-for-byte the pre-P2 one (G1).
|
||||
~FramebufferObject();
|
||||
#endif
|
||||
|
||||
void AttachTexture(FramebufferAttachmentType type, const SharedPtr<ITextureObject>& texture,
|
||||
TextureUploadTarget textureUploadTarget = TextureUploadTarget::Unknown, int level = 0,
|
||||
|
||||
@@ -38,19 +38,15 @@ namespace MobileGL::MG_State::GLState {
|
||||
SharedPtr<FramebufferObject> FindFramebufferObjectByLifetimeId(Uint64 lifetimeId) const;
|
||||
#endif
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P2 brief D4: "did the attachment set or the default geometry of ANY framebuffer
|
||||
// move". It does NOT cover a BIND - a bind writes a BindingSlot, not the object - so
|
||||
// MGPipeTracker pairs this counter with the bound draw framebuffer identity, which
|
||||
// is one extra load and keeps the bump points on the object where they belong.
|
||||
void NoteAttachmentChanged() { ++m_anyAttachmentGeneration; }
|
||||
Uint64 GetAnyAttachmentGeneration() const { return m_anyAttachmentGeneration; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
Uint64 m_anyAttachmentGeneration = 0;
|
||||
#endif
|
||||
UnorderedMap<Uint, SharedPtr<FramebufferObject>> m_framebufferObjects;
|
||||
IndexGenerator<Uint> m_indexGenerator;
|
||||
Array<BindingSlot<FramebufferObject>, static_cast<SizeT>(FramebufferTarget::FramebufferTargetCount)>
|
||||
|
||||
@@ -32,7 +32,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
|
||||
ProgramObject::~ProgramObject() {
|
||||
CancelLink();
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P2 step e2: ANNOUNCE the death instead of leaving the backend to discover it in a
|
||||
// garbage sweep. This is the last SharedPtr to this object dropping - not
|
||||
// glDeleteProgram, which only marks the name and leaves a still-bound object very much
|
||||
@@ -56,7 +55,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// a proven no-op, because the slot allocator refuses a slot that is not live at that
|
||||
// generation.
|
||||
MG_Pipe::MGPipeEmitShaderCsoDestroyAndFree(m_lifetimeId);
|
||||
#endif
|
||||
}
|
||||
|
||||
// EnsureLinkJoined() is defined inline in ProgramObject.h (see the comment there for
|
||||
|
||||
@@ -1115,7 +1115,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
return Artifacts();
|
||||
}
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// The phase-B twin of GetLinkReflection, and it exists for exactly one caller:
|
||||
// create_shader_state publishes the WHOLE SpirvArtifacts beside the whole
|
||||
// LinkArtifacts, because the archive the far side deserialises into is those two
|
||||
@@ -1130,7 +1129,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
const SpirvArtifacts& GetSpirvReflection() const {
|
||||
return Spirv();
|
||||
}
|
||||
#endif
|
||||
|
||||
static Bool IsValidUniformLocation(const LinkArtifacts& artifacts, Int location) {
|
||||
if (location < 0 || location > static_cast<Int>(artifacts.maxUniformLocation)) return false;
|
||||
|
||||
@@ -30,7 +30,6 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
RenderbufferObject::RenderbufferObject(Uint externalIndex) : m_externalIndex(externalIndex) {
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P4a D-D1: resource_create from the constructor, carrying no storage. A
|
||||
// renderbuffer is an INDEPENDENT class on the wire - it shares MGPResourceDesc's
|
||||
// shape with textures and buffers and nothing else - and its handle is minted
|
||||
@@ -42,10 +41,8 @@ namespace MobileGL {
|
||||
// PipeFill.cpp decides.
|
||||
MG_Pipe::MGPipeMintRenderbufferHandle(*this);
|
||||
MG_Pipe::MGPipeEmitRenderbufferResourceCreate(*this);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
RenderbufferObject::~RenderbufferObject() {
|
||||
// P4a D-I1, the fixed three-step order: the wire delete first (published-gated,
|
||||
// because a slot is not evidence of a record), then the death notice - the P2
|
||||
@@ -57,7 +54,6 @@ namespace MobileGL {
|
||||
// is deleted, not kept, for the reason ~TextureObjectBase states in full.
|
||||
MG_Pipe::MGPipeEmitRenderbufferDestroyAndFree(m_lifetimeId);
|
||||
}
|
||||
#endif
|
||||
|
||||
Uint RenderbufferObject::GetExternalIndex() const {
|
||||
return m_externalIndex;
|
||||
@@ -114,28 +110,21 @@ namespace MobileGL {
|
||||
void RenderbufferObject::SetInternalFormat(TextureInternalFormat format) {
|
||||
m_internalFormat = format;
|
||||
m_componentSizes = MG_Util::GetComponentSizesForInternalFormat(format);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipePublishDescriptor();
|
||||
#endif
|
||||
}
|
||||
|
||||
void RenderbufferObject::AllocateStorage(IntVec2 size) {
|
||||
m_width = size.x();
|
||||
m_height = size.y();
|
||||
m_allocated = true;
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipePublishDescriptor();
|
||||
#endif
|
||||
}
|
||||
|
||||
void RenderbufferObject::SetSamples(Int samples) {
|
||||
m_samples = samples;
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipePublishDescriptor();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// D-D2: THE RENDERBUFFER PUBLICATION HOLE, CLOSED BY EMISSION AND NOT BY A NEW
|
||||
// VERSION. These three setters bump no version and raise no notice, so
|
||||
// `glBindRenderbuffer; glRenderbufferStorage(newSize)` on an attached renderbuffer
|
||||
@@ -160,7 +149,6 @@ namespace MobileGL {
|
||||
MG_Pipe::MGPipeEmitRenderbufferResourceRespecify(*this);
|
||||
MGP_NOTE_AGGREGATE(FramebufferAttachment);
|
||||
}
|
||||
#endif
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -25,12 +25,10 @@ namespace MobileGL {
|
||||
using TargetEnum = RenderbufferTarget;
|
||||
|
||||
RenderbufferObject(Uint externalIndex);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P2 step e2. Out of line, and declared only where there is a notice to raise:
|
||||
// in a pull build this class stays trivially destructible, which is what keeps
|
||||
// the pull build's symbol set byte-for-byte the pre-P2 one (G1).
|
||||
~RenderbufferObject();
|
||||
#endif
|
||||
|
||||
Uint GetExternalIndex() const;
|
||||
void SetInternalFormat(TextureInternalFormat format);
|
||||
@@ -59,13 +57,11 @@ namespace MobileGL {
|
||||
|
||||
private:
|
||||
static Uint64 AllocateLifetimeId();
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P4a D-D2: resource_respecify, from every storage-defining setter. Non-virtual
|
||||
// and push-only, so the pull build's object layout is untouched (P4a's
|
||||
// admitted-resize set is EMPTY); defined in RenderbufferObject.cpp, which is the
|
||||
// one translation unit that includes the client emitter.
|
||||
void PipePublishDescriptor();
|
||||
#endif
|
||||
|
||||
Uint m_externalIndex = 0;
|
||||
const Uint64 m_lifetimeId = AllocateLifetimeId();
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace MobileGL {
|
||||
SamplerObject::SamplerObject(Uint externalIndex)
|
||||
: m_externalIndex(externalIndex), m_lifetimeId(AllocateLifetimeId()) {}
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
SamplerObject::~SamplerObject() {
|
||||
// P2 step e2: ANNOUNCE the death instead of leaving the backend to discover it in a
|
||||
// garbage sweep. This is the last SharedPtr to this object dropping - not the
|
||||
@@ -53,7 +52,6 @@ namespace MobileGL {
|
||||
// and exactly as before, is the notice.
|
||||
MG_Pipe::MGPipeEmitSamplerCsoDestroyAndFree(m_lifetimeId);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SamplerObject::BumpVersion() {
|
||||
++m_version;
|
||||
|
||||
@@ -16,12 +16,10 @@ namespace MobileGL {
|
||||
class SamplerObject {
|
||||
public:
|
||||
SamplerObject(Uint externalIndex);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P2 step e2. Out of line, and declared only where there is a notice to raise:
|
||||
// in a pull build this class keeps its implicit destructor, which is what keeps
|
||||
// the pull build's symbol set byte-for-byte the pre-P2 one (G1).
|
||||
~SamplerObject();
|
||||
#endif
|
||||
|
||||
void SetWrapS(SamplerWrapMode mode);
|
||||
void SetWrapT(SamplerWrapMode mode);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#pragma once
|
||||
#include <Includes.h>
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
#include <MG_Pipe/MGPipeHandles.h>
|
||||
|
||||
// P2 step e2, the frontend half: TELL the backend that a state object died, instead of
|
||||
@@ -59,4 +58,3 @@ namespace MobileGL::MG_State::GLState {
|
||||
}
|
||||
|
||||
} // namespace MobileGL::MG_State::GLState
|
||||
#endif // MOBILEGL_PIPE_PUSH
|
||||
|
||||
@@ -34,7 +34,6 @@ namespace MobileGL {
|
||||
return s_nextTextureLifetimeId.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
TextureObjectBase::~TextureObjectBase() {
|
||||
// P4a D-I1: BACKEND-NEUTRAL FROM DAY ONE, and the three-step order is fixed.
|
||||
//
|
||||
@@ -110,7 +109,6 @@ namespace MobileGL {
|
||||
MG_Pipe::MGPipeNoteTextureLevelDirty(*this, static_cast<Uint32>(uploadTarget),
|
||||
static_cast<Uint32>(mipmapLevel));
|
||||
}
|
||||
#endif
|
||||
|
||||
void TextureObjectBase::BumpShapeVersion() {
|
||||
++m_shapeVersion;
|
||||
@@ -142,7 +140,6 @@ namespace MobileGL {
|
||||
m_sampler->SetWrapT(SamplerWrapMode::ClampToEdge);
|
||||
m_sampler->SetWrapR(SamplerWrapMode::ClampToEdge);
|
||||
}
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P4a D-D1: A RESOURCE EXISTS BEFORE ANYTHING CAN NAME IT, so resource_create is
|
||||
// emitted from the constructor and carries no storage - the store is defined
|
||||
// lazily by the first respecify and every backend already tolerates a resource
|
||||
@@ -169,7 +166,6 @@ namespace MobileGL {
|
||||
(void)externalIndex;
|
||||
MG_Pipe::MGPipeMintTextureHandle(*this);
|
||||
MG_Pipe::MGPipeEmitTextureResourceCreate(*this);
|
||||
#endif
|
||||
}
|
||||
|
||||
TextureInternalFormat TextureObjectBase::GetFormat() const {
|
||||
@@ -217,14 +213,12 @@ namespace MobileGL {
|
||||
BumpShapeVersion();
|
||||
++m_textureParamsVersion;
|
||||
MGP_NOTE_AGGREGATE(TextureParams);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// The format is BOTH halves: a descriptor field the backend allocates from and a
|
||||
// parameter the swizzle / depth-stencil push reads, so both records move. It is
|
||||
// also the last statement of both glTexBuffer entry points, which is what
|
||||
// publishes a buffer texture's window without a call site in MG_Impl/GLImpl.
|
||||
PipePublishDescriptor();
|
||||
PipePublishParams();
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint TextureObjectBase::GetExternalIndex() const {
|
||||
@@ -251,9 +245,7 @@ namespace MobileGL {
|
||||
m_sampler->SetBorderColor(color);
|
||||
++m_textureParamsVersion;
|
||||
MGP_NOTE_AGGREGATE(TextureParams);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipePublishParams();
|
||||
#endif
|
||||
}
|
||||
|
||||
const IntVec4& TextureObjectBase::GetBorderColorI() const {
|
||||
@@ -269,9 +261,7 @@ namespace MobileGL {
|
||||
m_sampler->SetBorderColorI(color);
|
||||
++m_textureParamsVersion;
|
||||
MGP_NOTE_AGGREGATE(TextureParams);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipePublishParams();
|
||||
#endif
|
||||
}
|
||||
|
||||
const UintVec4& TextureObjectBase::GetBorderColorUI() const {
|
||||
@@ -287,9 +277,7 @@ namespace MobileGL {
|
||||
m_sampler->SetBorderColorUI(color);
|
||||
++m_textureParamsVersion;
|
||||
MGP_NOTE_AGGREGATE(TextureParams);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipePublishParams();
|
||||
#endif
|
||||
}
|
||||
|
||||
BorderColorForm TextureObjectBase::GetBorderColorForm() const {
|
||||
@@ -340,9 +328,7 @@ namespace MobileGL {
|
||||
}
|
||||
++m_textureParamsVersion;
|
||||
MGP_NOTE_AGGREGATE(TextureParams);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipePublishParams();
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetSwizzleParamRGBA(const Vec4<TextureSwizzleParam>& values) {
|
||||
@@ -351,9 +337,7 @@ namespace MobileGL {
|
||||
m_swizzleParams = values;
|
||||
++m_textureParamsVersion;
|
||||
MGP_NOTE_AGGREGATE(TextureParams);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipePublishParams();
|
||||
#endif
|
||||
}
|
||||
|
||||
const UintVec2& TextureObjectBase::GetLevelRange() const {
|
||||
@@ -373,12 +357,10 @@ namespace MobileGL {
|
||||
++m_textureParamsVersion;
|
||||
MGP_NOTE_AGGREGATE(TextureParams);
|
||||
BumpShapeVersion();
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// The level range is PARAMS, not a descriptor field: the record carries
|
||||
// BaseLevel / MaxLevel and the storage is untouched. The descriptor is deduped on
|
||||
// its own bytes, so the shape bump above costs nothing here.
|
||||
PipePublishParams();
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetMaxLevel(Uint maxLevel) {
|
||||
@@ -391,9 +373,7 @@ namespace MobileGL {
|
||||
++m_textureParamsVersion;
|
||||
MGP_NOTE_AGGREGATE(TextureParams);
|
||||
BumpShapeVersion();
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipePublishParams();
|
||||
#endif
|
||||
}
|
||||
|
||||
Bool TextureObjectBase::IsImmutable() const {
|
||||
@@ -414,14 +394,12 @@ namespace MobileGL {
|
||||
}
|
||||
++m_textureParamsVersion;
|
||||
MGP_NOTE_AGGREGATE(TextureParams);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// Immutable is a descriptor fact the backend reads - and NOT a request for an
|
||||
// acknowledgement: MGPipeResourceRespecifyNeedsAck names the buffer target
|
||||
// explicitly, because texture allocation is lazy in monolith and stays lazy in
|
||||
// split. The level clamp above is params.
|
||||
PipePublishDescriptor();
|
||||
PipePublishParams();
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint16 TextureObjectBase::GetTextureParamsVersion() const {
|
||||
@@ -460,9 +438,7 @@ namespace MobileGL {
|
||||
m_samples = samples;
|
||||
++m_textureParamsVersion;
|
||||
MGP_NOTE_AGGREGATE(TextureParams);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipePublishDescriptor();
|
||||
#endif
|
||||
}
|
||||
|
||||
Bool TextureObjectBase::HasFixedSampleLocations() const {
|
||||
@@ -473,9 +449,7 @@ namespace MobileGL {
|
||||
m_fixedSampleLocations = fixedSampleLocations;
|
||||
++m_textureParamsVersion;
|
||||
MGP_NOTE_AGGREGATE(TextureParams);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipePublishDescriptor();
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64 TextureObjectBase::GetLifetimeId() const {
|
||||
@@ -507,7 +481,6 @@ namespace MobileGL {
|
||||
MipmapInput input) {
|
||||
BumpShapeVersion();
|
||||
m_textureStorage.AllocateLevel(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, input);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// AFTER the allocation, never before: BumpShapeVersion runs first and a descriptor
|
||||
// built there would describe the level set this call is about to change. Every
|
||||
// storage-defining GL entry point - glTexImage*, glCompressedTexImage*,
|
||||
@@ -517,17 +490,14 @@ namespace MobileGL {
|
||||
// C-1): this call replaced ONE level's storage, and only that level's pending
|
||||
// upload may go with it.
|
||||
PipePublishLevelDescriptor(uploadTarget, mipmapLevel);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextureObjectWithOneMipmap::TruncateMipmapLevels(TextureUploadTarget uploadTarget, Uint levelCount) {
|
||||
BumpShapeVersion();
|
||||
m_textureStorage.TruncateToLevelCount(GetIndexOfTextureUploadTarget(uploadTarget), levelCount);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// The levels at and above the cut are gone; the ones below keep their pending
|
||||
// uploads (final review C-1).
|
||||
PipePublishTruncatedDescriptor(uploadTarget, levelCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextureObjectWithOneMipmap::UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
||||
@@ -546,11 +516,9 @@ namespace MobileGL {
|
||||
MGP_NOTE_AGGREGATE(TextureContent);
|
||||
}
|
||||
m_textureStorage.MarkDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, dirty);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// THE DRAIN LIST HAS NO CLEAN ARM (see TextureEmit.h): a level that goes clean
|
||||
// is collected at the next drain, whose first test is IsStorageDirty.
|
||||
if (dirty) PipeNoteLevelDirty(uploadTarget, mipmapLevel);
|
||||
#endif
|
||||
}
|
||||
|
||||
Bool TextureObjectWithOneMipmap::IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const {
|
||||
@@ -563,13 +531,11 @@ namespace MobileGL {
|
||||
MGP_NOTE_AGGREGATE(TextureContent);
|
||||
m_textureStorage.MarkDirtyRegion(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, offset,
|
||||
size);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// THE DRAIN LIST IS KEYED ON THE STORAGE OWNER FOR FREE: TextureObjectView
|
||||
// forwards this call to the OWNER's method after remapping the level and the
|
||||
// region, so an upload through a view and an upload through the owner arrive here
|
||||
// on the same object with the same owner-side coordinates.
|
||||
PipeNoteLevelDirty(uploadTarget, mipmapLevel);
|
||||
#endif
|
||||
}
|
||||
|
||||
MipmapDirtyRegion TextureObjectWithOneMipmap::GetStorageDirtyRegion(TextureUploadTarget uploadTarget,
|
||||
|
||||
@@ -117,15 +117,11 @@ namespace MobileGL::MG_State::GLState {
|
||||
class TextureObjectBase : public ITextureObject {
|
||||
public:
|
||||
TextureObjectBase(TextureTarget target, Uint externalIndex);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P2 step e2. Out of line, and declared only where there is a notice to raise: in a
|
||||
// pull build this stays the implicit `= default` the pre-P2 tree had, which is what
|
||||
// keeps the pull build's symbol set byte-for-byte the pre-P2 one (G1). Declared on the
|
||||
// BASE, so every concrete texture class - 2D, 3D, cube, buffer, view - announces once.
|
||||
virtual ~TextureObjectBase();
|
||||
#else
|
||||
virtual ~TextureObjectBase() = default;
|
||||
#endif
|
||||
|
||||
TextureInternalFormat GetFormat() const override;
|
||||
TextureTarget GetTarget() const override;
|
||||
@@ -190,12 +186,10 @@ namespace MobileGL::MG_State::GLState {
|
||||
m_depthStencilTextureMode = mode;
|
||||
++m_textureParamsVersion;
|
||||
MGP_NOTE_AGGREGATE(TextureParams);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// D-E3's whole point, at the one site that proves it: the depth-stencil mode of a
|
||||
// texture that is ONLY the READ framebuffer's attachment reaches the driver, because
|
||||
// set_texture_params is addressed by resource and is independent of every binding.
|
||||
PipePublishParams();
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -207,7 +201,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// otherwise invisible to such a memo (no bind moved).
|
||||
void BumpShapeVersion();
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// ---- P4a's client emission points (brief D-D1, D-D3, D-E1, D-I1) ----
|
||||
//
|
||||
// NON-VIRTUAL AND PUSH-ONLY, both deliberately: a virtual would grow the vtable and a
|
||||
@@ -245,7 +238,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// level that goes clean is collected at the next drain, where !IsStorageDirty is the
|
||||
// first test EmitOneLevel makes.
|
||||
void PipeNoteLevelDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel);
|
||||
#endif
|
||||
|
||||
const Uint m_externalIndex;
|
||||
const Uint64 m_lifetimeId;
|
||||
|
||||
@@ -31,21 +31,17 @@ namespace MobileGL {
|
||||
MipmapInput input) {
|
||||
BumpShapeVersion();
|
||||
m_textureStorage.AllocateLevel(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, input);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// AFTER the allocation, for TextureObjectWithOneMipmap's reason: BumpShapeVersion
|
||||
// runs first and a descriptor built there would describe the level set this call
|
||||
// is about to change. The FACE rides in `uploadTarget`, so the key the emitter
|
||||
// drops is that face's level and no other face's (final review C-1).
|
||||
PipePublishLevelDescriptor(uploadTarget, mipmapLevel);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextureObject2DCube::TruncateMipmapLevels(TextureUploadTarget uploadTarget, Uint levelCount) {
|
||||
BumpShapeVersion();
|
||||
m_textureStorage.TruncateToLevelCount(GetIndexOfTextureUploadTarget(uploadTarget), levelCount);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipePublishTruncatedDescriptor(uploadTarget, levelCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextureObject2DCube::UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
||||
@@ -63,11 +59,9 @@ namespace MobileGL {
|
||||
MGP_NOTE_AGGREGATE(TextureContent);
|
||||
}
|
||||
m_textureStorage.MarkDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, dirty);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// SIX FACES, SIX BLOBS, SIX DRAIN KEYS: the upload target is the face, and it is
|
||||
// what the sub-data record's Target byte carries beside the resource target.
|
||||
if (dirty) PipeNoteLevelDirty(uploadTarget, mipmapLevel);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool TextureObject2DCube::IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const {
|
||||
@@ -80,9 +74,7 @@ namespace MobileGL {
|
||||
MGP_NOTE_AGGREGATE(TextureContent);
|
||||
m_textureStorage.MarkDirtyRegion(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, offset,
|
||||
size);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
PipeNoteLevelDirty(uploadTarget, mipmapLevel);
|
||||
#endif
|
||||
}
|
||||
|
||||
MipmapDirtyRegion TextureObject2DCube::GetStorageDirtyRegion(TextureUploadTarget uploadTarget,
|
||||
|
||||
@@ -29,7 +29,6 @@ namespace MobileGL {
|
||||
void SetBufferRange(SizeT offset, SizeT size) {
|
||||
m_bufferRangeOffset = offset;
|
||||
m_bufferRangeSize = size;
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// Both glTexBuffer entry points bind the backing buffer and then set the
|
||||
// window, so this is the first statement at which the descriptor's
|
||||
// BufferForTexBuffer / BufOffset / BufSize trio is complete. SetInternalFormat
|
||||
@@ -37,7 +36,6 @@ namespace MobileGL {
|
||||
// not move - which is exactly the case a re-attach of a DIFFERENT buffer at
|
||||
// the same format would otherwise fall through.
|
||||
PipePublishDescriptor();
|
||||
#endif
|
||||
}
|
||||
SizeT GetBufferRangeOffset() const { return m_bufferRangeOffset; }
|
||||
// Resolved against the buffer's current size, so kWholeBuffer tracks it.
|
||||
|
||||
@@ -79,7 +79,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// to the view. GetImmutableLevels() forwards to the owner for the actual GL query, which
|
||||
// GL 4.6 core 8.18 defines as the ORIGINAL texture's value.
|
||||
SetImmutableLevels(numLevels);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// ViewOf, and it is published from HERE rather than left to SetImmutableLevels above,
|
||||
// which early-returns when the composed level count happens to be the base class's
|
||||
// current value - a degenerate view (the spec's min() composition narrowed to zero
|
||||
@@ -90,7 +89,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// at creation, which is what the spec's additive min-level rule describes and what the
|
||||
// assertion above pins, so the owner named here is never itself a view.
|
||||
PipePublishDescriptor();
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint TextureObjectView::GetImmutableLevels() const {
|
||||
|
||||
@@ -38,7 +38,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
Access = access;
|
||||
Format = format;
|
||||
++Version;
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P4a D-A4 / final review M-A: the EARLIEST producer of kMGPipeBindShaderImage. The
|
||||
// ImageBindableHint the bit feeds prevents the texture re-mint (a texture the server
|
||||
// knows may be image-bound is allocated image-bindable up front, P9 W2), so it has
|
||||
@@ -46,7 +45,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// the bind, not at the next validate point's image walk. Push-only through the
|
||||
// contract's door, like every other hook in this directory (G1).
|
||||
if (Texture) MG_Pipe::MGPipeNoteTextureImageBound(*Texture);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -107,7 +105,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
}
|
||||
}
|
||||
Int GetMaxTouchedUnit() const { return m_maxTouchedUnit; }
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// High-water mark of IMAGE units ever bound by glBindImageTexture, and it is a SECOND
|
||||
// mark rather than a widening of the one above because the two index different
|
||||
// namespaces: GL 4.6 core 8.22's image units are their own array, and folding them
|
||||
@@ -139,7 +136,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
}
|
||||
// -1 until an image unit is bound for the first time, i.e. "there is nothing to sweep".
|
||||
Int GetMaxTouchedImageUnit() const { return m_maxTouchedImageUnit; }
|
||||
#endif
|
||||
Uint64 GetTextureBindGeneration() const { return m_textureBindGeneration; }
|
||||
// Both counters below are pushed PipeInputs fields AND are moved by writes the
|
||||
// backends make into frontend objects during their own verb - a synthesised fallback
|
||||
@@ -181,7 +177,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// again (the unit tests do exactly that between cases).
|
||||
Uint64 GetContextId() const { return m_contextId; }
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P2 brief D4, the two texture aggregates. CONTENT is an upload or a dirty region;
|
||||
// PARAMS is a glTexParameter or a glSamplerParameter. They are separate because
|
||||
// NEW_SAMPLER_VIEWS and NEW_SAMPLERS are separate dirty bits and a Minecraft frame
|
||||
@@ -190,15 +185,12 @@ namespace MobileGL::MG_State::GLState {
|
||||
Uint64 GetAnyTextureContentGeneration() const { return m_anyTextureContentGeneration; }
|
||||
void NoteTextureParamsChanged() { ++m_anyTextureParamsGeneration; }
|
||||
Uint64 GetAnyTextureParamsGeneration() const { return m_anyTextureParamsGeneration; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
Uint64 m_anyTextureContentGeneration = 0;
|
||||
Uint64 m_anyTextureParamsGeneration = 0;
|
||||
// See NoteImageUnitTouched: the image-unit twin of m_maxTouchedUnit, push builds only.
|
||||
Int m_maxTouchedImageUnit = -1;
|
||||
#endif
|
||||
static Uint64 AllocateContextId();
|
||||
|
||||
const Uint64 m_contextId;
|
||||
|
||||
@@ -38,7 +38,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
}
|
||||
}
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
VertexArrayObject::~VertexArrayObject() {
|
||||
// P2 step e2 / P3a C-1: ANNOUNCE the death instead of leaving the backend to discover
|
||||
// it in a garbage sweep, and RETURN THE CLIENT'S OWN SLOT while doing it. This is the
|
||||
@@ -62,7 +61,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
// (BufferObject.cpp -> MGPipeEmitResourceDestroyAndFree).
|
||||
MG_Pipe::MGPipeEmitVertexElementsDestroyAndFree(m_lifetimeId);
|
||||
}
|
||||
#endif
|
||||
|
||||
void VertexArrayObject::EnableAttribute(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
|
||||
@@ -25,12 +25,10 @@ namespace MobileGL {
|
||||
static constexpr int MAX_VERTEX_ATTRIB_BINDINGS = 32;
|
||||
|
||||
VertexArrayObject(Uint externIndex);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P2 step e2. Out of line, and declared only where there is a notice to raise:
|
||||
// in a pull build this class keeps its implicit destructor, which is what keeps
|
||||
// the pull build's symbol set byte-for-byte the pre-P2 one (G1).
|
||||
~VertexArrayObject();
|
||||
#endif
|
||||
|
||||
void EnableAttribute(Uint index);
|
||||
void DisableAttribute(Uint index);
|
||||
@@ -106,71 +104,6 @@ namespace MobileGL {
|
||||
// "any vertex-input state changed" with one compare.
|
||||
Uint32 GetConfigVersion() const { return m_configVersion; }
|
||||
|
||||
#if MOBILEGL_PIPE_LEGACY_MEMOS
|
||||
// ---- THE BACKEND'S THREE MEMOS ON THE FRONTEND OBJECT ----
|
||||
//
|
||||
// P2 D12.5 (ARCHITECTURE.md 9.5) retires all three: a frontend state object
|
||||
// must not hold the backend's raw pointers, and under split it cannot - the
|
||||
// backend is in another process and its cache entry has no address the client
|
||||
// could store. Magma's handle arm keeps the same three facts in a slot-indexed
|
||||
// table it owns itself (VertexInputStateFactory::VaoBackendMemos), keyed on the
|
||||
// VAO's {slot, gen} and validated by the same config version, so nothing is
|
||||
// recomputed more often than it was.
|
||||
//
|
||||
// They stay compiled under MOBILEGL_PIPE_LEGACY_MEMOS - which a PULL build
|
||||
// forces ON - because that is the arm the pre-handle A/B runs, and because G1
|
||||
// admits no change to the pull build. They are deleted outright with the pull
|
||||
// path at P13.
|
||||
//
|
||||
// Backend-owned content-hash memo, valid while the config version matches
|
||||
// (same idea as ProgramObject's hash memo — avoids re-hashing all
|
||||
// attributes on every draw).
|
||||
Bool GetBackendHashMemo(Uint64& outHash) const {
|
||||
if (m_backendHashMemoVersion != m_configVersion) return false;
|
||||
outHash = m_backendHashMemo;
|
||||
return true;
|
||||
}
|
||||
void SetBackendHashMemo(Uint64 hash) const {
|
||||
m_backendHashMemo = hash;
|
||||
m_backendHashMemoVersion = m_configVersion;
|
||||
}
|
||||
|
||||
// Backend-owned resolved-state memo: an opaque pointer into the
|
||||
// backend's vertex-input-state cache plus the cache's eviction
|
||||
// epoch, valid while the config version matches. Lets the
|
||||
// per-draw path skip the content hash AND the cache lookup; the
|
||||
// epoch guards against the cache evicting the pointee.
|
||||
Bool GetBackendStateMemo(const void*& outState, Uint64& outEpoch) const {
|
||||
if (m_backendStateMemoVersion != m_configVersion) return false;
|
||||
outState = m_backendStateMemo;
|
||||
outEpoch = m_backendStateMemoEpoch;
|
||||
return true;
|
||||
}
|
||||
void SetBackendStateMemo(const void* state, Uint64 epoch) const {
|
||||
m_backendStateMemo = state;
|
||||
m_backendStateMemoEpoch = epoch;
|
||||
m_backendStateMemoVersion = m_configVersion;
|
||||
}
|
||||
|
||||
// Backend-owned aux memo: two opaque VALUE words (no pointee, so unlike the
|
||||
// state memo above they need no eviction-epoch guard), valid while the config
|
||||
// version matches. They live next to m_configVersion, which every per-draw
|
||||
// path already loads, so a backend can re-read small derived facts about this
|
||||
// VAO's configuration (e.g. a layout hash and attribute masks) without
|
||||
// chasing into its own cache's heap entry - that chase is a guaranteed cache
|
||||
// miss when an app cycles hundreds of VAOs per frame.
|
||||
Bool GetBackendAuxMemo(Uint64& outAux0, Uint64& outAux1) const {
|
||||
if (m_backendAuxMemoVersion != m_configVersion) return false;
|
||||
outAux0 = m_backendAuxMemo0;
|
||||
outAux1 = m_backendAuxMemo1;
|
||||
return true;
|
||||
}
|
||||
void SetBackendAuxMemo(Uint64 aux0, Uint64 aux1) const {
|
||||
m_backendAuxMemo0 = aux0;
|
||||
m_backendAuxMemo1 = aux1;
|
||||
m_backendAuxMemoVersion = m_configVersion;
|
||||
}
|
||||
#endif // MOBILEGL_PIPE_LEGACY_MEMOS
|
||||
|
||||
private:
|
||||
void BumpAttributeFormatVersion(Uint index);
|
||||
@@ -210,19 +143,6 @@ namespace MobileGL {
|
||||
Array<Bool, MAX_VERTEX_ATTRIBS> m_attributeUsesBindingModel = {};
|
||||
|
||||
Uint32 m_configVersion = 0;
|
||||
#if MOBILEGL_PIPE_LEGACY_MEMOS
|
||||
// The storage behind the three accessors above; retired with them (D12.5).
|
||||
// A pull build forces MOBILEGL_PIPE_LEGACY_MEMOS ON, so sizeof(this) does not
|
||||
// move there and G1 sees no change.
|
||||
mutable Uint64 m_backendHashMemo = 0;
|
||||
mutable Uint32 m_backendHashMemoVersion = ~0u;
|
||||
mutable const void* m_backendStateMemo = nullptr;
|
||||
mutable Uint64 m_backendStateMemoEpoch = 0;
|
||||
mutable Uint32 m_backendStateMemoVersion = ~0u;
|
||||
mutable Uint64 m_backendAuxMemo0 = 0;
|
||||
mutable Uint64 m_backendAuxMemo1 = 0;
|
||||
mutable Uint32 m_backendAuxMemoVersion = ~0u;
|
||||
#endif // MOBILEGL_PIPE_LEGACY_MEMOS
|
||||
};
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
|
||||
@@ -28,7 +28,6 @@ namespace MobileGL {
|
||||
const SharedPtr<VertexArrayObject>& GetBoundVertexArray();
|
||||
Vector<SharedPtr<VertexArrayObject>>& GetAllVertexArrays();
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P2 brief D4: "did the attribute configuration of ANY vertex array move".
|
||||
// Bumped from every VertexArrayObject::BumpAttribute*Version through
|
||||
// MGP_NOTE_AGGREGATE(VaoAttribute), which is coarser than the per-object
|
||||
@@ -36,12 +35,9 @@ namespace MobileGL {
|
||||
// re-push costs a push while a missed one renders stale.
|
||||
void NoteAttributeChanged() { ++m_anyVaoAttributeGeneration; }
|
||||
Uint64 GetAnyAttributeGeneration() const { return m_anyVaoAttributeGeneration; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
Uint64 m_anyVaoAttributeGeneration = 0;
|
||||
#endif
|
||||
// "Nothing bound" (an out-of-range or never-created name was bound). Distinct from
|
||||
// being bound to a live slot so that a slot filled AFTER such a bind does not
|
||||
// retroactively become the bound VAO.
|
||||
|
||||
@@ -164,11 +164,9 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
Counter g_totalGateMiss[kGateCount];
|
||||
Counter g_totalPayloadBuckets[kPayloadHistogramBuckets];
|
||||
Counter g_frameCount{0};
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P6 gate 8's second histogram, and push-only for the same reason its accessor is: its
|
||||
// only sampler is the wire encoder, which a pull build does not compile.
|
||||
Counter g_totalStagedBlobBuckets[kStagedBlobHistogramBuckets];
|
||||
#endif
|
||||
|
||||
// Window bases: the run totals as of the previous summary line. Only ever touched
|
||||
// from OnPresent()/Shutdown() (the present thread), so plain integers.
|
||||
@@ -178,13 +176,11 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
Uint64 g_windowBaseGateMiss[kGateCount] = {};
|
||||
Uint64 g_windowBaseFrames = 0;
|
||||
Bool g_shutdownDone = false;
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// The gauges' storage. Relaxed atomics like every other counter here: the publisher is
|
||||
// the GL thread at a frame boundary and the reader is whoever formats the line, which
|
||||
// under split can be the apply thread.
|
||||
Counter g_gauges[static_cast<Uint32>(Gauge::Count)] = {};
|
||||
constexpr Uint32 kGaugeCount = static_cast<Uint32>(Gauge::Count);
|
||||
#endif
|
||||
|
||||
// Frames per summary line, latched by Init() from MOBILEGL_PIPE_STATS_PERIOD.
|
||||
Uint64 g_summaryPeriod = kDefaultSummaryFramePeriod;
|
||||
@@ -225,14 +221,11 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
"stage-buffer", "stage-texture", "stage-ubo-global",
|
||||
"stage-ubo-named", "stage-vertex-client", "stage-index-client",
|
||||
"stage-indirect-cmd", "persistent-map-push", "residual-value-block",
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
"cso-blob-bytes", "stage-segment-bytes",
|
||||
#endif
|
||||
};
|
||||
const char* const kCallClassNames[kCallClassCount] = {
|
||||
"draws", "accessor-calls", "tex-upload-emissions", "tex-upload-box", "tex-upload-rect",
|
||||
"tex-upload-jobs",
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
"render-state-cso-mints", "render-state-cso-binds", "map-persistent-roundtrips",
|
||||
"framebuffer-emissions", "sampler-view-emissions", "sampler-state-emissions",
|
||||
"shader-image-emissions", "client-tex-upload-emissions", "tex-remint-pulls",
|
||||
@@ -241,7 +234,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
"wire-indirect-native-draws", "wire-indirect-cpu-expansions", "wire-indirect-barriers",
|
||||
"wire-host-waits", "wire-host-waits-indirect", "wire-host-wait-us",
|
||||
"wire-indirect-native-dispatches",
|
||||
#endif
|
||||
};
|
||||
const char* const kGateNames[kGateCount] = {
|
||||
"espryt-render-state", "espryt-texture-sync-list", "espryt-unit-bindings-epoch",
|
||||
@@ -264,9 +256,7 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
// recorded baseline stops meaning anything.
|
||||
const char* const kByteClassShort[kByteClassCount] = {"buf", "tex", "ubog", "ubon", "vtxc",
|
||||
"idxc", "icmd", "pmap", "resid",
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
"csob-blob", "seg",
|
||||
#endif
|
||||
};
|
||||
const char* const kGateShort[kGateCount] = {"ers", "etl", "eub", "mfp", "mpm", "mdt"};
|
||||
|
||||
@@ -294,16 +284,12 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
}
|
||||
g_frameCount.store(0, std::memory_order_relaxed);
|
||||
g_windowBaseFrames = 0;
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
for (Uint32 i = 0; i < kStagedBlobHistogramBuckets; ++i) {
|
||||
g_totalStagedBlobBuckets[i].store(0, std::memory_order_relaxed);
|
||||
}
|
||||
#endif
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
for (Uint32 i = 0; i < kGaugeCount; ++i) {
|
||||
g_gauges[i].store(0, std::memory_order_relaxed);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void EmitSummaryLine() {
|
||||
@@ -436,7 +422,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
Bump(g_totalCalls[index], count);
|
||||
}
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// A STORE, NOT A BUMP, and the difference is the whole reason these are a separate kind.
|
||||
// The publisher hands over its OWN run total (a maximum, or a count it has been keeping
|
||||
// since the session opened), so accumulating deltas here would double every reading; and a
|
||||
@@ -447,7 +432,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
}
|
||||
|
||||
Uint64 GaugeValue(Gauge gauge) { return Read(g_gauges[static_cast<Uint32>(gauge)]); }
|
||||
#endif
|
||||
|
||||
void CountGate(Gate gate, Bool hit) {
|
||||
const Uint32 index = static_cast<Uint32>(gate);
|
||||
@@ -462,14 +446,12 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
|
||||
void RecordDrawPayloadBytes(Uint64 bytes) { Bump(g_totalPayloadBuckets[PayloadBucketOf(bytes)], 1); }
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P6 gate 8's staged-blob distribution. A count, not a sum: the bytes already have a home
|
||||
// in stage-segment-bytes, and what this exists to answer is the SHAPE (how many blobs there
|
||||
// were and how big each one was), which a total cannot express.
|
||||
void RecordStagedBlobBytes(Uint64 bytes) {
|
||||
Bump(g_totalStagedBlobBuckets[PayloadBucketOf(bytes)], 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void OnPresent() {
|
||||
// Every frame accumulator is EXCHANGED for zero, and the exchanged value is what gets
|
||||
@@ -526,11 +508,9 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
Uint64 TotalPayloadBucket(Uint32 bucket) {
|
||||
return bucket < kPayloadHistogramBuckets ? Read(g_totalPayloadBuckets[bucket]) : 0;
|
||||
}
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
Uint64 TotalStagedBlobBucket(Uint32 bucket) {
|
||||
return bucket < kStagedBlobHistogramBuckets ? Read(g_totalStagedBlobBuckets[bucket]) : 0;
|
||||
}
|
||||
#endif
|
||||
Uint64 FrameCount() { return Read(g_frameCount); }
|
||||
|
||||
const char* NameOf(ByteClass byteClass) { return kByteClassNames[static_cast<Uint32>(byteClass)]; }
|
||||
@@ -590,7 +570,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
line += " box=" + std::to_string(calls[static_cast<Uint32>(CallClass::TextureUploadBoxEmissions)]);
|
||||
line += " rect=" + std::to_string(calls[static_cast<Uint32>(CallClass::TextureUploadRectEmissions)]);
|
||||
line += " jobs=" + std::to_string(calls[static_cast<Uint32>(CallClass::TextureUploadJobs)]);
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// Push-only, like the two counters themselves: in a pull build there is no CSO to
|
||||
// mint, and a "csom=0 csob=0" that can never be anything else is noise on the one
|
||||
// line an operator greps.
|
||||
@@ -704,7 +683,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
line += " whwus=" + std::to_string(calls[static_cast<Uint32>(CallClass::WireHostWaitMicros)]);
|
||||
// P8-SV: the indirect dispatches, on the same bracket (their barriers are in `wibar`).
|
||||
line += " wdsp=" + std::to_string(calls[static_cast<Uint32>(CallClass::WireIndirectNativeDispatches)]);
|
||||
#endif
|
||||
line += "] gates[";
|
||||
for (Uint32 i = 0; i < kGateCount; ++i) {
|
||||
if (i != 0) {
|
||||
@@ -759,7 +737,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
", \"miss\": " + std::to_string(Read(g_totalGateMiss[i])) + "}";
|
||||
json += (i + 1 == kGateCount) ? "\n" : ",\n";
|
||||
}
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// The gauges, under their long names. Run totals here as on the summary line.
|
||||
json += " },\n \"wire\": {\n";
|
||||
json += " \"max-record-bytes\": " +
|
||||
@@ -790,7 +767,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
std::to_string(Read(g_gauges[static_cast<Uint32>(Gauge::WireDeferredBytesPeak)])) + ",\n";
|
||||
json += " \"wire-deferred-syncs\": " +
|
||||
std::to_string(Read(g_gauges[static_cast<Uint32>(Gauge::WireDeferredSyncs)])) + "\n";
|
||||
#endif
|
||||
json += " },\n \"cmd-bytes-per-draw-histogram\": [";
|
||||
for (Uint32 i = 0; i < kPayloadHistogramBuckets; ++i) {
|
||||
if (i != 0) {
|
||||
@@ -798,7 +774,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
}
|
||||
json += std::to_string(Read(g_totalPayloadBuckets[i]));
|
||||
}
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P6 gate 8's two per-frame numbers have their JSON homes where every other ByteClass and
|
||||
// CallClass already does - the `bytes` and `calls` blocks above, under their long names
|
||||
// (stage-segment-bytes, wire-records) - so there is nothing to add for them here. The
|
||||
@@ -814,7 +789,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
}
|
||||
json += std::to_string(Read(g_totalStagedBlobBuckets[i]));
|
||||
}
|
||||
#endif
|
||||
json += "]\n}\n";
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
// PLACEHOLDER (plan section 6.3): the residual value block does not exist yet. The
|
||||
// class is minted now so the counter names never churn; it stays at 0 until P2.
|
||||
ResidualValueBlock,
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P4a's, and THE PUSH GUARD IS NEW ON THIS ENUM: CallClass has had one since P2 and
|
||||
// ByteClass has never had one, so the block is opened here rather than the member
|
||||
// simply appended. Without it the pull build's two counter arrays, the name table, the
|
||||
@@ -113,7 +112,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
// is what MOBILEGL_IPC_STAGE_MB has to hold for one record. The per-blob distribution
|
||||
// this average hides is the staged-blob histogram below.
|
||||
StageSegmentBytes,
|
||||
#endif
|
||||
Count
|
||||
};
|
||||
|
||||
@@ -139,7 +137,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
// Driver upload jobs issued by those emissions: 1 per box emission, N per rect-list
|
||||
// emission.
|
||||
TextureUploadJobs,
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P2's two, and they are PUSH-ONLY on purpose: a render-state CSO exists only in a
|
||||
// push build, and the pull build has to stay symbol-identical (G1) - growing this
|
||||
// enum there would resize the counter arrays, the name table and FormatWindowLine
|
||||
@@ -287,11 +284,9 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
// wire store (VulkanRenderer::DispatchWireComputeIndirect). Their barriers count in `wibar`
|
||||
// with the draws': one barrier per shader write, whichever indirect read consumes it.
|
||||
WireIndirectNativeDispatches,
|
||||
#endif
|
||||
Count
|
||||
};
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// P5's GAUGES, and they are a THIRD KIND of counter rather than three more CallClass rows.
|
||||
//
|
||||
// A ByteClass and a CallClass are SUMS this module owns and a call site increments. These
|
||||
@@ -385,7 +380,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
// the call sites are per-frame, not per-record.
|
||||
void PublishGauge(Gauge gauge, Uint64 value);
|
||||
Uint64 GaugeValue(Gauge gauge);
|
||||
#endif
|
||||
|
||||
// Memo gates. Each is a place where a backend decides "nothing moved, skip the work".
|
||||
// Hit == the gate short-circuited; Miss == it fell through and did the work. The six
|
||||
@@ -414,7 +408,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
// emit records only has to add the one call.
|
||||
inline constexpr Uint32 kPayloadHistogramBuckets = 24;
|
||||
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
// Per-STAGED-BLOB size histogram, and it is a SECOND histogram rather than a wider
|
||||
// kPayloadHistogramBuckets because the two answer different questions about different
|
||||
// populations: the one above is the command payload of a draw (plan section 4.5.7, sizing
|
||||
@@ -436,7 +429,6 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
// Sample one staged blob. Called by the wire encoder where a blob is staged, behind the
|
||||
// usual Enabled() predicate.
|
||||
void RecordStagedBlobBytes(Uint64 bytes);
|
||||
#endif
|
||||
|
||||
// Frames between two summary lines when MOBILEGL_PIPE_STATS=1.
|
||||
inline constexpr Uint64 kDefaultSummaryFramePeriod = 120;
|
||||
|
||||
Reference in New Issue
Block a user