From 7fb18840dcdfe6f0c5ca35b4767ee530f822caed Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 6 Oct 2026 15:03:11 -0400 Subject: [PATCH] [Refactor] (P13 W5 S8): MOBILEGL_BUILD_RECORD_ARM is folded away - the record arm is unconditional - and retired_switches keeps it from coming back. --- CMakeLists.txt | 47 +- MobileGL/Config.h | 9 - MobileGL/ConfigLoader.cpp | 8 - MobileGL/Init.cpp | 4 - MobileGL/MG_Backend/BackendObject.h | 8 - .../DirectGLES/BackendObject_DirectGLES.cpp | 30 - MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 348 ------- MobileGL/MG_Backend/DirectGLES/DirectGLES.h | 4 - MobileGL/MG_Backend/DirectGLES/Managers.cpp | 185 ---- MobileGL/MG_Backend/DirectGLES/Managers.h | 30 - MobileGL/MG_Backend/DirectGLES/MultiDraw.cpp | 6 - MobileGL/MG_Backend/DirectGLES/Utils.cpp | 32 - MobileGL/MG_Backend/DirectGLES/Utils.h | 2 - .../DirectGLES/WireTextureReadback.inc | 2 - .../BackendObject_DirectVulkan.cpp | 4 - .../MG_Backend/DirectVulkan/DirectVulkan.cpp | 297 ------ .../MG_Backend/DirectVulkan/DirectVulkan.h | 2 - .../DirectVulkan/Renderer/BufferArena.cpp | 4 - .../DirectVulkan/Renderer/FrameContext.cpp | 8 - .../Renderer/MagmaProgramSource.h | 6 - .../DirectVulkan/Renderer/PipelineFactory.cpp | 4 - .../DirectVulkan/Renderer/PipelineFactory.h | 2 - .../DirectVulkan/Renderer/ProgramFactory.cpp | 6 - .../DirectVulkan/Renderer/UniformManager.cpp | 62 -- .../DirectVulkan/Renderer/UniformManager.h | 14 - .../Renderer/VertexInputStateFactory.cpp | 4 - .../Renderer/VertexInputStateFactory.h | 6 - .../DirectVulkan/Renderer/VkBufferManager.cpp | 24 - .../DirectVulkan/Renderer/VkBufferManager.h | 12 - .../DirectVulkan/Renderer/VkBufferObject.cpp | 12 - .../DirectVulkan/Renderer/VkBufferObject.h | 6 - .../Renderer/VkSamplerManager.cpp | 43 - .../DirectVulkan/Renderer/VkSamplerManager.h | 15 - .../Renderer/VkTextureManager.cpp | 16 - .../DirectVulkan/Renderer/VkTextureManager.h | 18 - .../DirectVulkan/Renderer/VulkanRenderer.cpp | 948 ------------------ .../DirectVulkan/Renderer/VulkanRenderer.h | 41 - .../DirectVulkan/Renderer/WireColorBlit.inc | 2 - .../Renderer/WireColorBlitFilter.h | 2 - .../DirectVulkan/Renderer/WireDeclineTally.h | 2 - .../DirectVulkan/Renderer/WireDepthMipmap.inc | 2 - .../Renderer/WireDepthResolveProbe.cpp | 2 - .../Renderer/WireDepthResolveProbe.h | 2 - .../DirectVulkan/Renderer/WireDraw.inc | 2 - .../DirectVulkan/Renderer/WireFramebuffer.inc | 2 - .../Renderer/WireMultisampleResolve.inc | 2 - .../Renderer/WirePlaceholderImages.inc | 2 - .../Renderer/WirePlaceholderKey.h | 2 - .../Renderer/WireRenderPassCompatibility.h | 2 - .../Renderer/WireTextureReadback.inc | 2 - MobileGL/MG_Backend/MGPipe/PipeInputs.cpp | 4 +- MobileGL/MG_Backend/MGPipe/PipeInputs.h | 26 - MobileGL/MG_Backend/Record/RecordVerbSink.cpp | 20 - .../MG_Backend/Record/StagedTextureStore.h | 6 - .../MG_Impl/GLImpl/Drawing/GL_Drawing.cpp | 6 - .../MG_Impl/GLImpl/Texture/GL_Texture.cpp | 12 - MobileGL/MG_Impl/Pipe/OwnedDrawInputs.h | 2 - MobileGL/MG_Impl/Pipe/PipeFill.cpp | 26 +- MobileGL/MG_Impl/Pipe/SamplerEmit.h | 2 - MobileGL/MG_Impl/Pipe/TextureEmit.h | 2 - MobileGL/MG_Impl/Pipe/VertexInputEmit.h | 4 - MobileGL/MG_IntegrationTest/CMakeLists.txt | 36 +- MobileGL/MG_Pipe/MGPipeCallbacks.h | 2 - MobileGL/MG_Pipe/MGPipeTypes.h | 8 - MobileGL/MG_Pipe/PipeApply.cpp | 55 - MobileGL/MG_Pipe/PipeApply.h | 14 - MobileGL/MG_Pipe/PipeRoute.cpp | 2 - MobileGL/MG_Pipe/PipeRoute.h | 9 - MobileGL/MG_Pipe/PipeSessionFail.h | 4 - .../GLState/BufferState/BufferObject.cpp | 29 - .../GLState/BufferState/BufferObject.h | 4 - .../GLState/BufferState/PipeResource.h | 15 - MobileGL/MG_State/GLState/Core.cpp | 2 - MobileGL/MG_State/GLState/Core.h | 2 - .../FramebufferState/FramebufferState.cpp | 2 - .../FramebufferState/FramebufferState.h | 2 - .../GLState/ProgramState/ProgramArtifacts.h | 12 - .../ProgramState/ProgramArtifactsCodec.cpp | 41 - .../ProgramState/ProgramArtifactsCodec.h | 4 - .../GLState/ProgramState/ProgramLinkTask.cpp | 6 - .../GLState/ProgramState/ProgramLinkTask.h | 2 - .../GLState/ProgramState/ProgramObject.h | 2 - MobileGL/MG_Test/Pipe/ResourceEmitTest.cpp | 56 +- .../Program/ProgramArtifactsCodecTest.cpp | 4 - .../MG_Test/Program/ProgramArtifactsTest.cpp | 4 - MobileGL/MG_Test/ScopedMonolithFrontendArm.h | 4 - MobileGL/MG_Util/SelfTest/DriverBugProbes.cpp | 4 - MobileGL/MG_Util/SelfTest/DriverBugProbes.h | 4 - MobileGL/MG_Util/SelfTest/DriverPost.cpp | 2 - scripts/ci/retired_switches.py | 13 +- scripts/ci/wire_declines_audit.py | 22 +- 91 files changed, 46 insertions(+), 2725 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 69d2e0d4..b1a13a1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -553,12 +553,9 @@ if (MOBILEGL_BUILD_DISAGGREGATED AND set(MOBILEGL_BUILD_DISAGGREGATED_INPROC OFF) endif() -# P13 W5 (notes/p13/W5-DESIGN.md): THE RECORD ARM'S OWN GUARD. A plain variable, not an option and -# not a cache entry, so no build tree can keep a stale value (W3a's lesson). It equalled -# MOBILEGL_BUILD_DISAGGREGATED while the record arm's guards were reclassified one by one; since S7 -# it is on for every build, so the library without MG_Remote (the FCL-embedded one) runs the record -# arm too. S8 removes the variable and the guards it still names. Always defined, to 0 or 1. -set(MOBILEGL_BUILD_RECORD_ARM ON) +# P13 W5 (notes/p13/W5-DESIGN.md): the record arm is part of every library - the one without +# MG_Remote (FCL's) runs it too. Its temporary guard, MOBILEGL_BUILD_RECORD_ARM, was folded away at +# S8 (scripts/ci/retired_switches.py keeps it from coming back). message(STATUS "MobileGL: PipeInputs push ON, appending the MGPipe fill sources") list(APPEND SOURCE_FILES @@ -684,23 +681,21 @@ if (MOBILEGL_BUILD_DISAGGREGATED) ) endif() -# P13 W5: the record arm's own sources, compiled wherever the record arm is (MG_Remote or not). -if (MOBILEGL_BUILD_RECORD_ARM) - list(APPEND SOURCE_FILES - # P7 gate 5 (g5-msprobe): the Magma wire arm's two multisample depth/stencil resolve - # arms and the probe that measures the first against the second, shared by the - # renderer's bring-up and the Vulkan POST. - MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthResolveProbe.cpp - # P5 b1: the block-granularity persistent-map push the record arm makes mandatory (T2). - MobileGL/MG_State/GLState/BufferState/PersistentMapTracker.cpp - # P13 W5: the verb emitters and the monolith verb port, and the client GPU-write set - # they mark before a draw or a dispatch (MG_Record; EmitTables.cpp resolves the session). - MobileGL/MG_Impl/Pipe/Verb/VerbPort.cpp - MobileGL/MG_Impl/Pipe/Verb/GpuWriteSet.cpp - # The record verbs' consumer (ServerVerbSink under a transport is this plus the session's). - MobileGL/MG_Backend/Record/RecordVerbSink.cpp - ) -endif() +# P13 W5: the record arm's own sources, compiled into every library (MG_Remote or not). +list(APPEND SOURCE_FILES + # P7 gate 5 (g5-msprobe): the Magma wire arm's two multisample depth/stencil resolve + # arms and the probe that measures the first against the second, shared by the + # renderer's bring-up and the Vulkan POST. + MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthResolveProbe.cpp + # P5 b1: the block-granularity persistent-map push the record arm makes mandatory (T2). + MobileGL/MG_State/GLState/BufferState/PersistentMapTracker.cpp + # P13 W5: the verb emitters and the monolith verb port, and the client GPU-write set + # they mark before a draw or a dispatch (MG_Record; EmitTables.cpp resolves the session). + MobileGL/MG_Impl/Pipe/Verb/VerbPort.cpp + MobileGL/MG_Impl/Pipe/Verb/GpuWriteSet.cpp + # The record verbs' consumer (ServerVerbSink under a transport is this plus the session's). + MobileGL/MG_Backend/Record/RecordVerbSink.cpp +) if (APPLE AND NOT MOBILEGL_IOS) list(APPEND SOURCE_FILES @@ -764,12 +759,6 @@ if (MOBILEGL_BUILD_DISAGGREGATED) list(APPEND MOBILEGL_COMPILE_DEF -DMOBILEGL_BUILD_DISAGGREGATED=1) endif() -if (MOBILEGL_BUILD_RECORD_ARM) - list(APPEND MOBILEGL_COMPILE_DEF -DMOBILEGL_BUILD_RECORD_ARM=1) -else() - list(APPEND MOBILEGL_COMPILE_DEF -DMOBILEGL_BUILD_RECORD_ARM=0) -endif() - if (MOBILEGL_PIPE_VERIFY) list(APPEND MOBILEGL_COMPILE_DEF -DMOBILEGL_PIPE_VERIFY=1) endif() diff --git a/MobileGL/Config.h b/MobileGL/Config.h index b873f191..63003bec 100644 --- a/MobileGL/Config.h +++ b/MobileGL/Config.h @@ -462,7 +462,6 @@ namespace MobileGL::MG_Config { NamedPipe = 4, // P6: Windows named pipe (Endpoint = ) }; -#if MOBILEGL_BUILD_RECORD_ARM // P13 W5: THE RECORD ARM'S OWN KNOBS. They kept their MOBILEGL_IPC_* names (logs, CI lanes and // notes spell them so), but they tune the record arm - the persistent-map push and Magma's wire // stores - which runs in a library without a transport too, so they are not IpcTable's. @@ -498,7 +497,6 @@ namespace MobileGL::MG_Config { Uint32 PersistentMprotect = 1; }; extern RecordArmTable RecordArm; -#endif #if MOBILEGL_BUILD_DISAGGREGATED // Parsed once by MG_ConfigLoader::Init(). Defaults to Monolith even here: building the @@ -759,7 +757,6 @@ namespace MobileGL::MG_Config { inline constexpr TransportMode Transport = TransportMode::Monolith; #endif -#if MOBILEGL_BUILD_RECORD_ARM // P13 W4: THE DATA-ARM QUESTION - do the backends read RECORDS (the applier's twins, the staged // stores, the verb's own handles) rather than frontend objects? Under a wire the answer has // always been yes; P13 makes it yes for monolith too ("monolith is the push variant"), one @@ -779,10 +776,4 @@ namespace MobileGL::MG_Config { inline Bool RecordArmAliasesFrontend() { return Transport == TransportMode::Monolith && MonolithTakesRecordArm; } -#else - // A build without the record arm reads frontend objects everywhere (the negative control a - // library built with MOBILEGL_BUILD_RECORD_ARM=0 keeps until W6 deletes the frontend arms). - inline constexpr Bool DataArmIsRecord() { return false; } - inline constexpr Bool RecordArmAliasesFrontend() { return false; } -#endif } // namespace MobileGL::MG_Config diff --git a/MobileGL/ConfigLoader.cpp b/MobileGL/ConfigLoader.cpp index accab628..bea1af33 100644 --- a/MobileGL/ConfigLoader.cpp +++ b/MobileGL/ConfigLoader.cpp @@ -39,10 +39,8 @@ namespace MobileGL::MG_Config { Bool SplitTransportRequestedByConfig = false; IpcTable Ipc; #endif -#if MOBILEGL_BUILD_RECORD_ARM Bool MonolithTakesRecordArm = false; RecordArmTable RecordArm; -#endif } // namespace MobileGL::MG_Config namespace MobileGL::MG_ConfigLoader { @@ -678,7 +676,6 @@ namespace MobileGL::MG_ConfigLoader { } #endif -#if MOBILEGL_BUILD_RECORD_ARM // P13 W4 (Config.h DataArmIsRecord). Read after InitTransport: `frontend` names monolith's // arm only - a wire has no frontend objects on its server half to read, so there it is // ignored by name rather than half-honoured. @@ -737,7 +734,6 @@ namespace MobileGL::MG_ConfigLoader { "the persistent-map push is OFF and a coherent-map scenario must go red"); } } -#endif void Init() { MGLOG_D("Loading configuration from environment variables..."); @@ -745,17 +741,13 @@ namespace MobileGL::MG_ConfigLoader { InitBackendType(); InitFeatures(); -#if MOBILEGL_BUILD_RECORD_ARM InitRecordArm(); -#endif #if MOBILEGL_BUILD_DISAGGREGATED // After InitFeatures, so the one line InitIpc logs is the last word on this run's // configuration, and before the accepted-env map is destroyed just below. InitTransport(); #endif -#if MOBILEGL_BUILD_RECORD_ARM InitDataArm(); -#endif #if MOBILEGL_BUILD_DISAGGREGATED InitIpc(); #endif diff --git a/MobileGL/Init.cpp b/MobileGL/Init.cpp index 72195d60..6a233b30 100644 --- a/MobileGL/Init.cpp +++ b/MobileGL/Init.cpp @@ -24,9 +24,7 @@ #if MOBILEGL_PIPE_VERIFY #include // MGPipeVerifyFlushSummary, before Debug::Close in DestroyImpl #endif -#if MOBILEGL_BUILD_RECORD_ARM #include -#endif #if MOBILEGL_BUILD_DISAGGREGATED #include #endif @@ -185,7 +183,6 @@ namespace MobileGL { #endif { MG_Backend::Init(); -#if MOBILEGL_BUILD_RECORD_ARM // P13 W4: monolith's record arm reads the verb's own state, which only a verb sink // writes; the port routes the ported verbs through one (MG_Impl/Pipe/Verb/VerbPort.cpp). // Installed HERE, by the library's role-neutral init, rather than by MG_Backend's: the @@ -193,7 +190,6 @@ namespace MobileGL { if (MG_Config::RecordArmAliasesFrontend() && MG_Backend::pActiveBackendObject) { MG_Record::InstallMonolithVerbPort(MG_Backend::gBackendFunctionsTable); } -#endif } MGLOG_D("MG_Backend initialized"); MG_Impl::Init(); diff --git a/MobileGL/MG_Backend/BackendObject.h b/MobileGL/MG_Backend/BackendObject.h index 7495424d..df169dc9 100644 --- a/MobileGL/MG_Backend/BackendObject.h +++ b/MobileGL/MG_Backend/BackendObject.h @@ -10,9 +10,7 @@ #include #include "MG_State/GLState/TextureState/TextureEnum.h" #include -#if MOBILEGL_BUILD_RECORD_ARM #include -#endif namespace MobileGL { namespace MG_State::GLState { @@ -37,22 +35,16 @@ namespace MobileGL { struct CopyImageEndpoint { SharedPtr Texture; SharedPtr Renderbuffer; -#if MOBILEGL_BUILD_RECORD_ARM MG_Pipe::MGPipeHandle TextureHandle = MG_Pipe::kMGPipeNullHandle; MG_Pipe::MGPipeHandle RenderbufferHandle = MG_Pipe::kMGPipeNullHandle; -#endif Bool IsRenderbuffer() const { -#if MOBILEGL_BUILD_RECORD_ARM if (!MG_Pipe::MGPipeHandleIsNull(RenderbufferHandle)) return true; -#endif return Renderbuffer != nullptr; } Bool Exists() const { -#if MOBILEGL_BUILD_RECORD_ARM if (!MG_Pipe::MGPipeHandleIsNull(TextureHandle)) return true; if (!MG_Pipe::MGPipeHandleIsNull(RenderbufferHandle)) return true; -#endif return Texture != nullptr || Renderbuffer != nullptr; } }; diff --git a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp index 5f3f1912..0960b597 100644 --- a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp @@ -32,7 +32,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT; } -#if MOBILEGL_BUILD_RECORD_ARM // ID-54 / ID-67 (v1, under ID-52/ID-59's grant for this file). Which VIRTUAL (dpy, draw, // read, ctx) the process's one native ES context is currently bound FOR, on the apply // thread. DirectGLES has one native context and one native surface (g_Context, g_Surface) @@ -78,7 +77,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } return false; } -#endif void ClearGLErrors(const MG_External::GLESFunctionsTable& gl) { if (!gl.glGetError) return; @@ -860,7 +858,6 @@ namespace MobileGL::MG_Backend::DirectGLES { Int maxSamples = 0; const SizeT formatIndex = static_cast(logicalFormat); -#if MOBILEGL_BUILD_RECORD_ARM // C6 / ID-52: read the ROLE's own cache. Under split that is the server's private backend // (ActiveBackendFormatCaps), not pActiveBackendObject, which holds the client's mirror. const FormatCapabilityCache* activeCaps = ActiveBackendFormatCaps(); @@ -872,17 +869,6 @@ namespace MobileGL::MG_Backend::DirectGLES { maxSamples = probedCounts.front(); } } -#else - if (pActiveBackendObject && targetIndex < kFormatCapabilityTargetCount && - formatIndex < kFormatCapabilityFormatCount) { - // Descending, so the head is the largest count this device actually allocated. - const Vector& probedCounts = - pActiveBackendObject->GetFormatCapabilities().SampleCounts[targetIndex][formatIndex]; - if (!probedCounts.empty()) { - maxSamples = probedCounts.front(); - } - } -#endif if (maxSamples <= 0) { maxSamples = GetGLESFormatMaxSamples(g_GLESCapabilities, logicalFormat, imageFormat); } @@ -1085,7 +1071,6 @@ namespace MobileGL::MG_Backend::DirectGLES { ResetEGLRuntimeState(); } -#if MOBILEGL_BUILD_RECORD_ARM // ID-54 / ID-67: as for the window surface - InitPbufferSurface bound natively. The pull // arm below is the original statement, byte for byte (G1). const Bool created = BackendObject::CreateEGLPbufferSurface(surface, width, height); @@ -1098,9 +1083,6 @@ namespace MobileGL::MG_Backend::DirectGLES { NoteNativeContextGone(); } return created; -#else - return BackendObject::CreateEGLPbufferSurface(surface, width, height); -#endif } Bool BackendObject_DirectGLES::ResizeEGLWindowSurface(EGLSurface surface, Uint32 width, Uint32 height) { @@ -1139,9 +1121,7 @@ namespace MobileGL::MG_Backend::DirectGLES { if (!DirectGLES::ReleaseCurrent()) { return false; } -#if MOBILEGL_BUILD_RECORD_ARM NoteNativeContextGone(); -#endif return BackendObject::MakeEGLCurrent(dpy, draw, read, ctx); } @@ -1212,9 +1192,7 @@ namespace MobileGL::MG_Backend::DirectGLES { if (!BackendObject::MakeEGLCurrent(dpy, draw, read, ctx)) { (void)DirectGLES::ReleaseCurrent(); -#if MOBILEGL_BUILD_RECORD_ARM NoteNativeContextGone(); -#endif return false; } return true; @@ -1267,9 +1245,7 @@ namespace MobileGL::MG_Backend::DirectGLES { void BackendObject_DirectGLES::ReleaseEGLResources() { const std::lock_guard lock(m_eglStateMutex); DestroyEGLContext(); -#if MOBILEGL_BUILD_RECORD_ARM NoteNativeContextGone(); -#endif m_suspendedWindowSurfaces.clear(); BackendObject::ReleaseEGLResources(); } @@ -1295,10 +1271,8 @@ namespace MobileGL::MG_Backend::DirectGLES { } m_suspendedWindowSurfaces.push_back(client); } -#if MOBILEGL_BUILD_RECORD_ARM // The native binding moved onto the placeholder: the next make-current binds for real. NoteNativeContextGone(); -#endif MGLOG_I("DirectGLES: %zu window surface(s) on server window %p now draw into placeholder pbuffers; the " "contexts and their objects stay", onWindow.size(), window); @@ -1327,9 +1301,7 @@ namespace MobileGL::MG_Backend::DirectGLES { if (surface == EGL_NO_SURFACE) return false; native->second = surface; } -#if MOBILEGL_BUILD_RECORD_ARM NoteNativeContextGone(); -#endif MGLOG_I("DirectGLES: %zu suspended window surface(s) rebuilt on server window %p (%ux%u)", suspended.size(), window, width, height); return true; @@ -1366,9 +1338,7 @@ namespace MobileGL::MG_Backend::DirectGLES { // every object the client had built - which a multi-window client hit on its first closed // popup. (void)surface; -#if MOBILEGL_BUILD_RECORD_ARM NoteNativeContextGone(); -#endif } void BackendObject_DirectGLES::OnEGLSurfaceForgotten(EGLSurface surface) { diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 59d6cb0e..e1ba43f0 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -28,12 +28,10 @@ // The draw path's attribute-values sync reads Archive->Link, so this TU needs it complete - // Managers.cpp already includes it for ProgramArchiveSource, which is the same reason. #include -#if MOBILEGL_BUILD_RECORD_ARM // P5c (tx): §1's server-side per-level extent derivation, for GenerateMipmap's shape reads. #include // The record arm's deaths and latches (MGPipeRecordFail / MGPipeRecordLatch), in every build. #include -#endif #if MOBILEGL_BUILD_DISAGGREGATED // Shared images: the registry the EGLImages are built from (SharedImageImpl below). #include @@ -79,7 +77,6 @@ #endif namespace MobileGL::MG_Backend::DirectGLES { -#if MOBILEGL_BUILD_RECORD_ARM // A readback on the server writes REPLY SCRATCH, so it has no pack buffer - and this // function is how every pack-PBO lookup in this file says so under a transport. // @@ -98,7 +95,6 @@ namespace MobileGL::MG_Backend::DirectGLES { static const SharedPtr none; return none; } -#endif MG_External::EGLFunctionsTable g_EGLFuncs; MG_External::GLESFunctionsTable g_GLESFuncs; @@ -183,7 +179,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return target == FramebufferTarget::Draw ? st.DrawFramebuffer() : st.ReadFramebuffer(); } -#if MOBILEGL_BUILD_RECORD_ARM // P5e (fb, CONTRACT-P5E.md §5.4 and §0's rule F). THE DECLINE BECOMES THE DETECTOR. // // Every framebuffer decline in this file used to fall back to the pre-handle arm, which @@ -204,7 +199,6 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_Pipe::MGPipeInputPoisonFatalForVerb(MG_Pipe::MGPipeInputField::GetFramebufferBindingSlot, MG_Pipe::gPipeInputs.CurrentVerb()); } -#endif // MOBILEGL_BUILD_RECORD_ARM static Bool IsDualSourceBlendFactor(BlendFactor v) { switch (v) { @@ -238,7 +232,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // grep and a comment naming it is a hit) and for an MG_State type inside // MGPipeResourceOps, and this is neither. SamplerImpl::BackendSamplerObject* GetRawDepthFetchSampler() { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { static UniquePtr native; static Uint generation = 0; @@ -256,7 +249,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } return native.get(); } -#endif if (!g_rawDepthFetchSamplerState) { g_rawDepthFetchSamplerState = MakeShared(0); g_rawDepthFetchSamplerState->SetMinFilter(SamplerFilterMode::Nearest); @@ -361,7 +353,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } const Uint8* ResolveIndirectCommandBytes(const void* indirect, SizeT requiredBytes, const char* label) { -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): under an active transport the command buffer resolves // from the handle the verb record carried, and its CPU bytes are the SERVER's staged // shadow (rule E) - the client's GL_DRAW_INDIRECT_BUFFER binding slot, the frontend @@ -404,7 +395,6 @@ namespace MobileGL::MG_Backend::DirectGLES { MGLOG_E_ONCE("%s skipped: the verb carried no indirect buffer handle", label); return nullptr; } -#endif auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); if (drawBuffer) { drawBuffer->SyncPersistentMappedRange(); @@ -500,7 +490,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // path and has to select the same arm; a copy of the conjunction there would be two // selectors for one family. Its rationale travelled with it. -#if MOBILEGL_BUILD_RECORD_ARM // P5e (vi): "does this draw fetch any attribute out of the application's own memory", // answered FROM THE RECORD instead of from the frontend VAO. The emitter publishes // Res == kMGPipeNullHandle for a client-memory array (VertexInputEmit.h says so in as @@ -576,9 +565,7 @@ namespace MobileGL::MG_Backend::DirectGLES { request.Serial = st.IndexBufferSerial; return request; } -#endif // MOBILEGL_BUILD_RECORD_ARM - vi's record arm ends here; sb's opens below -#if MOBILEGL_BUILD_RECORD_ARM // ---- P5e (sb, MG_Remote/CONTRACT-P5E.md §5.6): THE INDEXED BINDING POINTS BY RECORD -- // // WHICH ARM THIS SERVER TAKES, resolved once. Two conjuncts and both are the phase's @@ -692,9 +679,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } } } -#else - inline Bool BindingPointsComeFromRecords() { return false; } -#endif void SyncBufferBindingPoints(BufferTarget target, GLenum glTarget) { #ifdef TRACY_ENABLE @@ -806,7 +790,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // the frontend's CPU shadow. Flagging them makes the next MapBuffer/GetBufferSubData // pull the real contents back (BufferObject::SyncGpuWrites). void MarkShaderStorageBuffersGpuWritten() { -#if MOBILEGL_BUILD_RECORD_ARM // P5e (sb, CONTRACT-P5E.md §5.6): DELETED UNDER A TRANSPORT, and this is the one // site of the three that cannot merely be re-expressed by handle. The walk is over // CLIENT memory - the frontend's binding-point array and the BufferObject it names - @@ -824,7 +807,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // The applier's ShaderBufferWritableMask survives as the server's record of WHICH // points a shader may write through, which is what P9's narrowing channel will name. if (MG_Config::DataArmIsRecord()) return; -#endif const SizeT bindingPointCnt = MG_Pipe::gPipeInputs.GetTouchedBufferBindingPointCount(BufferTarget::ShaderStorage); for (SizeT i = 0; i < bindingPointCnt; ++i) { @@ -841,7 +823,6 @@ namespace MobileGL::MG_Backend::DirectGLES { #ifdef TRACY_ENABLE ZoneScopedC(TRACY_ZONECOLOR_BACKEND); #endif -#if MOBILEGL_BUILD_RECORD_ARM // P5e (sb, §5.6): THE RECORD ARM. `glBindings` stays the backend program's own list // - it is server-owned since the link and names which GL counter bindings THIS // program declares - and only the points themselves move sides. The bound is the @@ -906,7 +887,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } return; } -#endif const SizeT pointCount = MG_Pipe::gPipeInputs.GetBufferBindingPointCount(BufferTarget::AtomicCounter); for (const Int glBinding : glBindings) { if (glBinding < 0 || static_cast(glBinding) >= pointCount) continue; @@ -1069,7 +1049,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } } -#if MOBILEGL_BUILD_RECORD_ARM // P5e (vi), CONTRACT-P5E §5.1: THE SAME MEMO, THE SAME THREE-VALUE KEY, AND A WALK THAT // READS NO FRONTEND AT ALL. The arm above keeps the frontend attribute walk because the // push-monolith build has to keep its bytes (§5.8); this one is what a server with no @@ -1169,7 +1148,6 @@ namespace MobileGL::MG_Backend::DirectGLES { memo->vboCleanEpoch = 0; } } -#endif // MOBILEGL_BUILD_DISAGGREGATED // `vaoConfigVersion` is the caller's early read of currentVAOObject->GetConfigVersion(): // the VAO's config fields live on a cache line the draw path touches nowhere else, and @@ -1218,11 +1196,9 @@ namespace MobileGL::MG_Backend::DirectGLES { const Uint64 bufferEpoch = CurrentBufferMutationEpoch(); auto* memo = vaoTwin ? &vaoTwin->GetResolvedDrawBuffersMemo() : nullptr; const Uint32 configVersion = vaoConfigVersion; -#if MOBILEGL_BUILD_RECORD_ARM if (VertexInputReadsRecords()) { SyncVaoAttributeBuffersByRecord(memo, bufferEpoch); } else -#endif if (VertexInputSubsystemEnabled()) { SyncVaoAttributeBuffersByHandle(currentVAOObject, memo, bufferEpoch); } else @@ -1290,7 +1266,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // the config version). A stale identity hit is impossible in effect: the // clean probe re-validates the resource against the LIVE bound object. if (includeIBO) { -#if MOBILEGL_BUILD_RECORD_ARM // P5e (vi), CONTRACT-P5E §5.1: the index buffer is st.IndexBuffer.Res and the // "has it moved" question is st.IndexBufferSerial. The identity compare stays - // it always did, because the index slot is outside the configuration version @@ -1328,7 +1303,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } } } else -#endif { const auto& possibleIBO = currentVAOObject->GetIndexBufferBindingSlot().GetBoundObject(); if (possibleIBO) { @@ -1378,7 +1352,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // Indirect Buffer Object - must also be bound to GL_DRAW_INDIRECT_BUFFER on the ES // context since indirect draws now execute natively on the GPU. if (includeIndirectBuffer) { -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): under an active transport the buffer is the verb // record's handle; the frontend binding slot and the client allocator are // never read (T2). The twin's ensure is what SyncBoundBuffer's did. @@ -1391,7 +1364,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } } } else -#endif { auto& possibleIndirectBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); @@ -1411,14 +1383,12 @@ namespace MobileGL::MG_Backend::DirectGLES { // SSBOs are different: their block bindings are baked into the ESSL at compile time and // BindCurrentProgramWithResources binds no SSBO points, so this is their sole draw-path // binder (e.g. Flywheel's indirect vertex shaders pull instance data from storage buffers). -#if MOBILEGL_BUILD_RECORD_ARM // P5e (sb, §5.6): the record arm, selected by transport + bit 13. Same `if (…) else` // shape the indirect buffer above already uses. if (BindingPointsComeFromRecords()) { SyncBufferBindingPointsByRecord(MG_Pipe::kMGPipeShaderBufferClassShaderStorage, GL_SHADER_STORAGE_BUFFER); } else -#endif { SyncBufferBindingPoints(BufferTarget::ShaderStorage, GL_SHADER_STORAGE_BUFFER); } @@ -1437,21 +1407,18 @@ namespace MobileGL::MG_Backend::DirectGLES { // is why the uniform class is emitted at all: compute does NOT go through the // per-program block remap in BindCurrentProgramWithResources, so these are the // points a compute shader actually reads. -#if MOBILEGL_BUILD_RECORD_ARM if (BindingPointsComeFromRecords()) { SyncBufferBindingPointsByRecord(MG_Pipe::kMGPipeShaderBufferClassUniform, GL_UNIFORM_BUFFER); SyncBufferBindingPointsByRecord(MG_Pipe::kMGPipeShaderBufferClassShaderStorage, GL_SHADER_STORAGE_BUFFER); } else -#endif { SyncBufferBindingPoints(BufferTarget::Uniform, GL_UNIFORM_BUFFER); SyncBufferBindingPoints(BufferTarget::ShaderStorage, GL_SHADER_STORAGE_BUFFER); } MarkShaderStorageBuffersGpuWritten(); if (includeDispatchIndirectBuffer) { -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): see the draw-indirect twin above - the verb // record's handle, never the frontend binding slot or the client allocator. if (MG_Config::DataArmIsRecord()) { @@ -1463,7 +1430,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } } } else -#endif SyncBoundBuffer(BufferTarget::DispatchIndirect, GL_DISPATCH_INDIRECT_BUFFER); } } @@ -1498,13 +1464,10 @@ namespace MobileGL::MG_Backend::DirectGLES { // gl_NextBuffer is the shape that makes them differ: buffer 0 has stride 0 // and nothing bound, so target 0 describes buffer 1. SizeT bufferIndex = 0; -#if MOBILEGL_BUILD_RECORD_ARM MG_Pipe::MGPipeHandle handle = MG_Pipe::kMGPipeNullHandle; -#endif }; -#if MOBILEGL_BUILD_RECORD_ARM struct XfbProgramSource { SharedPtr Frontend; SharedPtr Archive; @@ -1530,7 +1493,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return Archive ? Archive->Link.xfbVaryings : Frontend->GetTransformFeedbackVaryings(); } }; -#endif // Per frontend transform feedback object. The default object (name 0) maps to // the driver's default object (id 0) and is always present. struct XfbObjectState { @@ -1545,13 +1507,11 @@ namespace MobileGL::MG_Backend::DirectGLES { // End scatters them into `targets`. Bool scattered = false; SharedPtr scatterProgram; -#if MOBILEGL_BUILD_RECORD_ARM SharedPtr scatterArchive; // Paused spans in different served contexts may coexist. Their captured // bytes must not share the monolith's one reusable scratch buffer. GLuint serverScatterBuffer = 0; SizeT serverScatterSize = 0; -#endif SizeT scatterCapacityVertices = 0; }; @@ -1573,7 +1533,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // null instead of reasoning about stability, and CurrentXfb re-resolves lazily. XfbObjectState* g_currentXfbState = nullptr; -#if MOBILEGL_BUILD_RECORD_ARM struct RoleXfbState { Uint NativeGeneration = 0; // Server keys are record-supplied, never-reused XFB lifetime ids. @@ -1601,10 +1560,8 @@ namespace MobileGL::MG_Backend::DirectGLES { } return state; } -#endif XfbObjectState& CurrentXfb() { -#if MOBILEGL_BUILD_RECORD_ARM auto& state = ActiveXfbState(); if (MG_Config::DataArmIsRecord()) { const Uint64 lifetime = MG_Pipe::MGPipeApplier().BoundStreamOutputLifetimeId; @@ -1616,7 +1573,6 @@ namespace MobileGL::MG_Backend::DirectGLES { auto& g_currentXfbState = state.Cached; auto& g_xfbObjects = state.Objects; const auto g_currentXfbName = state.Current; -#endif if (g_currentXfbState == nullptr) { g_currentXfbState = &g_xfbObjects[g_currentXfbName]; } @@ -1653,7 +1609,6 @@ namespace MobileGL::MG_Backend::DirectGLES { g_GLESFuncs.glResumeTransformFeedback != nullptr; } -#if MOBILEGL_BUILD_RECORD_ARM // How wide one OnBufferWriteback may be for a capture range of `rangeBytes`, which is // the whole range when the transport imposes no limit (monolith, where the callback is // a direct call with no ring under it) or when the range already fits one. @@ -1667,7 +1622,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (slice == 0 || slice >= static_cast(rangeBytes)) return rangeBytes; return static_cast(slice); } -#endif // Mirrors one capture span's results into the frontend CPU shadows. The GPU wrote // the capture buffers behind the frontend's back, so the shadows that back @@ -1687,11 +1641,8 @@ namespace MobileGL::MG_Backend::DirectGLES { } if (g_GLESFuncs.glMapBufferRange != nullptr && g_GLESFuncs.glUnmapBuffer != nullptr) { for (const auto& target : targets) { -#if MOBILEGL_BUILD_RECORD_ARM if (!MG_Config::DataArmIsRecord()) -#endif if (!target.buffer) continue; -#if MOBILEGL_BUILD_RECORD_ARM // P5c: under an active transport the frontend object is client // memory (rule E), so the persistence question is the server // resource's and the captured bytes go back as a writeback EVENT - @@ -1757,7 +1708,6 @@ namespace MobileGL::MG_Backend::DirectGLES { BufferImpl::BumpBufferMutationEpoch(); continue; } -#endif if (target.buffer->IsBackendPersistentMapped()) continue; const SizeT size = target.end - target.start; BufferImpl::BindBufferId(BufferImpl::TempBufferTarget, target.backendId); @@ -1791,11 +1741,9 @@ namespace MobileGL::MG_Backend::DirectGLES { // scratch storage cannot be provided, in which case the caller falls back to the // direct binding (which produces a wrong layout, but is what happened before). Bool BindScatterCaptureBuffer(SizeT packedStride, SizeT capacityVertices) { -#if MOBILEGL_BUILD_RECORD_ARM const Bool server = MG_Config::DataArmIsRecord(); auto& g_scatterBufferId = server ? CurrentXfb().serverScatterBuffer : ActiveXfbState().ScatterBuffer; auto& g_scatterBufferSize = server ? CurrentXfb().serverScatterSize : ActiveXfbState().ScatterSize; -#endif if (packedStride == 0 || capacityVertices == 0) return false; if (g_GLESFuncs.glGenBuffers == nullptr || g_GLESFuncs.glBufferData == nullptr) return false; const SizeT required = packedStride * capacityVertices; @@ -1832,15 +1780,9 @@ namespace MobileGL::MG_Backend::DirectGLES { // occupies are written, so the holes gl_SkipComponents asks for keep whatever the // application had put there - which is the whole point of the feature. void ScatterCapturedRecords(XfbObjectState& xfb) { -#if MOBILEGL_BUILD_RECORD_ARM auto& g_scatterBufferId = MG_Config::DataArmIsRecord() ? xfb.serverScatterBuffer : ActiveXfbState().ScatterBuffer; -#endif -#if MOBILEGL_BUILD_RECORD_ARM const XfbProgramSource program{xfb.scatterProgram, xfb.scatterArchive}; -#else - const auto& program = xfb.scatterProgram; -#endif if (!program || xfb.targets.empty()) return; if (g_GLESFuncs.glMapBufferRange == nullptr || g_GLESFuncs.glUnmapBuffer == nullptr) return; @@ -1877,16 +1819,13 @@ namespace MobileGL::MG_Backend::DirectGLES { // whole range down once. for (SizeT targetIndex = 0; targetIndex < xfb.targets.size(); ++targetIndex) { const auto& target = xfb.targets[targetIndex]; -#if MOBILEGL_BUILD_RECORD_ARM if (!MG_Config::DataArmIsRecord()) -#endif if (!target.buffer) continue; // By BUFFER index, not by position in the compacted list - see XfbCaptureTarget. const SizeT stride = program->GetTransformFeedbackStride(static_cast(target.bufferIndex)); if (stride == 0) continue; const SizeT rangeBytes = target.end - target.start; Vector staged(rangeBytes); -#if MOBILEGL_BUILD_RECORD_ARM // P5c: under an active transport BufferObject::MappedData on the apply // thread is Fatal{RoleViolation, "buffer-legacy-arm"} (CONTRACT-P5C §3.8) - // the pre-capture bytes are the SERVER's staged shadow, and the reconciled @@ -1937,7 +1876,6 @@ namespace MobileGL::MG_Backend::DirectGLES { Memcpy(staged.data(), hostBytes + target.start, rangeBytes); } } else -#endif Memcpy(staged.data(), target.buffer->MappedData() + target.start, rangeBytes); for (const auto& varying : program->GetTransformFeedbackVaryings()) { @@ -1951,7 +1889,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } } -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { if (MG_Pipe::gMGPipeCallbacks.OnBufferWriteback != nullptr) { // Sliced for the reason the readback path above is sliced: the bytes @@ -1984,7 +1921,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // capture, and the next draw must not re-upload an older range over it. splitResource->syncedChangeSerial = BufferImpl::ResourceSerialForHandle(splitRes); } else -#endif target.buffer->WritebackFromBackend({staged.data(), rangeBytes}, target.start); // Serial bumped with no backend op (see ReadbackCapturedRanges). BufferImpl::BumpBufferMutationEpoch(); @@ -2030,7 +1966,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // not captured, and opening the span would also subject it to the capture // primitive-mode rule the paused draw is exempt from. if (!xfb.pending || xfb.paused) return; -#if MOBILEGL_BUILD_RECORD_ARM XfbProgramSource program; const MG_Pipe::MGPStreamOutputBegin* span = nullptr; if (MG_Config::DataArmIsRecord()) { @@ -2044,9 +1979,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } else { program.Frontend = MG_Pipe::gPipeInputs.GetTransformFeedbackProgram(); } -#else - const auto& program = MG_Pipe::gPipeInputs.GetTransformFeedbackProgram(); -#endif if (!program) { // The pending flag is deliberately NOT consumed here. It used to be cleared // before this check, so a single draw that could not see the capture program @@ -2066,7 +1998,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // recording it here keeps End independent of the frontend capture state. const SizeT bufferCount = program->GetTransformFeedbackBufferCount(); for (SizeT i = 0; i < bufferCount; ++i) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { if (!span || i >= 4) continue; const auto& range = span->Targets[i]; @@ -2079,7 +2010,6 @@ namespace MobileGL::MG_Backend::DirectGLES { resource->id, static_cast(range.Offset), static_cast(range.Size)); continue; } -#endif auto& point = MG_Pipe::gPipeInputs.GetBufferBindingPoint(BufferTarget::TransformFeedback, static_cast(i)); const auto& bufferObject = point.GetBoundObject(); @@ -2093,18 +2023,14 @@ namespace MobileGL::MG_Backend::DirectGLES { xfb.targets.push_back({bufferObject, backendResource->id, start, end, i}); } -#if MOBILEGL_BUILD_RECORD_ARM if (!MG_Config::DataArmIsRecord()) -#endif BufferImpl::SyncTransformFeedbackBindingPoints(bufferCount); // A layout with holes or several interleaved buffers is not expressible on ES: // capture gap-free into scratch storage and place the records at End instead. xfb.scattered = false; xfb.scatterProgram.reset(); -#if MOBILEGL_BUILD_RECORD_ARM xfb.scatterArchive.reset(); -#endif xfb.scatterCapacityVertices = 0; if (program->NeedsScatteredTransformFeedbackCapture()) { SizeT capacityVertices = ~SizeT(0); @@ -2120,12 +2046,8 @@ namespace MobileGL::MG_Backend::DirectGLES { if (capacityVertices == ~SizeT(0)) capacityVertices = 0; if (BindScatterCaptureBuffer(program->GetTransformFeedbackPackedStride(), capacityVertices)) { xfb.scattered = true; -#if MOBILEGL_BUILD_RECORD_ARM xfb.scatterProgram = program.Frontend; xfb.scatterArchive = program.Archive; -#else - xfb.scatterProgram = program; -#endif xfb.scatterCapacityVertices = capacityVertices; } else { // NO SPAN RATHER THAN A SPAN THAT WRITES SOMEWHERE ELSE. The ES program for a @@ -2210,9 +2132,7 @@ namespace MobileGL::MG_Backend::DirectGLES { ScatterCapturedRecords(xfb); xfb.scattered = false; xfb.scatterProgram.reset(); -#if MOBILEGL_BUILD_RECORD_ARM xfb.scatterArchive.reset(); -#endif } else { ReadbackCapturedRanges(xfb.targets); } @@ -2235,7 +2155,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } void BindTransformFeedback(GLuint name) { -#if MOBILEGL_BUILD_RECORD_ARM auto& roleState = ActiveXfbState(); auto& g_currentXfbState = roleState.Cached; auto& g_xfbObjects = roleState.Objects; @@ -2243,7 +2162,6 @@ namespace MobileGL::MG_Backend::DirectGLES { const Bool server = MG_Config::DataArmIsRecord(); const Uint64 key = server ? MG_Pipe::MGPipeApplier().BoundStreamOutputLifetimeId : name; roleState.NeedsBind = false; -#endif g_currentXfbState = nullptr; // name changes; operator[] below may also rehash // The capture buffer bindings are the OBJECT's, not the context's: the bind below // swaps all of them for whatever the target object holds, which the redundant-bind @@ -2253,34 +2171,20 @@ namespace MobileGL::MG_Backend::DirectGLES { // Without driver objects there is only the default span; keep the frontend // name so the bookkeeping below stays consistent. g_currentXfbName = -#if MOBILEGL_BUILD_RECORD_ARM key; -#else - name; -#endif return; } -#if MOBILEGL_BUILD_RECORD_ARM auto& xfb = g_xfbObjects[key]; // Even each virtual context's name-0 object gets its own native object. if ((server || name != 0) && xfb.esId == 0) { -#else - auto& xfb = g_xfbObjects[name]; - if (name != 0 && xfb.esId == 0) { -#endif g_GLESFuncs.glGenTransformFeedbacks(1, &xfb.esId); } g_GLESFuncs.glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb.esId); g_currentXfbName = -#if MOBILEGL_BUILD_RECORD_ARM key; -#else - name; -#endif } void DeleteTransformFeedback(GLuint name) { -#if MOBILEGL_BUILD_RECORD_ARM auto& roleState = ActiveXfbState(); auto& g_currentXfbState = roleState.Cached; auto& g_xfbObjects = roleState.Objects; @@ -2290,9 +2194,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // A generated but never-bound name has no native object or lifetime. if (server && key == 0) return; const auto it = g_xfbObjects.find(key); -#else - const auto it = g_xfbObjects.find(name); -#endif if (it == g_xfbObjects.end()) return; if (it->second.esId != 0 && g_GLESFuncs.glDeleteTransformFeedbacks != nullptr) { g_GLESFuncs.glDeleteTransformFeedbacks(1, &it->second.esId); @@ -2301,13 +2202,8 @@ namespace MobileGL::MG_Backend::DirectGLES { g_xfbObjects.erase(it); // The frontend reverts to the default object when the bound one is deleted. if (g_currentXfbName == -#if MOBILEGL_BUILD_RECORD_ARM key -#else - name -#endif ) { -#if MOBILEGL_BUILD_RECORD_ARM if (server) { // The following BindStreamOutput names this context's actual // default lifetime. Never create a native object for key 0. @@ -2316,7 +2212,6 @@ namespace MobileGL::MG_Backend::DirectGLES { BufferImpl::InvalidateTransformFeedbackBindingShadows(); return; } -#endif BindTransformFeedback(0); } } @@ -2324,10 +2219,8 @@ namespace MobileGL::MG_Backend::DirectGLES { // The ES context went away (or is being torn down): the spans, their buffer ids, the // driver objects and the frontend objects they pinned all belonged to it. void OnBackendContextDestroyed() { -#if MOBILEGL_BUILD_RECORD_ARM for (auto& state : g_roleXfbState) state = {}; g_activeXfbRole = -1; -#endif g_currentXfbState = nullptr; g_xfbObjects.clear(); g_currentXfbName = 0; @@ -2388,7 +2281,6 @@ namespace MobileGL::MG_Backend::DirectGLES { vaoTwin->SyncToBackend(currentVAOObject); } -#if MOBILEGL_BUILD_RECORD_ARM // P5e (vi): the record arm's entry, and it takes NO frontend object - CONTRACT-P5E §4.1 // ("the object parameter is deleted from the transport overload, not defaulted to // null"). A null twin here is the null BoundVertexElements, i.e. "no VAO bound", which @@ -2405,7 +2297,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (!vaoTwin) return; vaoTwin->SyncToBackendFromApplier(); } -#endif // MOBILEGL_BUILD_RECORD_ARM // THE CLIENT-MEMORY VERTEX ARRAY UPLOAD, and the one read of this family that P5e does // NOT retire - it MOVES the decision instead, which is what ID-82 / ruling 2 settles. @@ -2634,7 +2525,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } static void SyncClientSideVertexArraysForDrawArrays(GLint first, GLsizei count) { -#if MOBILEGL_BUILD_RECORD_ARM if (BufferImpl::VertexInputReadsRecords()) { if (!BufferImpl::AnyClientSideVertexArrayInRecord()) return; if (MG_Pipe::MGPipeApplierIsUnbarrieredApply()) { @@ -2652,7 +2542,6 @@ namespace MobileGL::MG_Backend::DirectGLES { twin->SyncClientSideAttributesForDrawArrays(currentVAO, first, count); return; } -#endif const auto& currentVAO = MG_Pipe::gPipeInputs.GetBoundVertexArray(); if (!currentVAO) return; auto* backendVAOSlot = g_backendVertexArrayObjects.Find(currentVAO.get()); @@ -2675,7 +2564,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (!program) return; if (!vaoTwin) return; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (vi), CONTRACT-P5E §5.1: the bound-VAO row is retired here. On the record arm // the twin IS the bound vertex-elements CSO (the caller resolved it from // st.BoundVertexElements), so "is a VAO bound" is already answered by vaoTwin being @@ -2710,9 +2598,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // it. The next create_vertex_elements re-opens the memo by serial. if (elementsRecord == nullptr) return; } -#else - constexpr Bool fromRecords = false; -#endif const SharedPtr noVao; const auto& vao = fromRecords ? noVao : MG_Pipe::gPipeInputs.GetBoundVertexArray(); @@ -2729,7 +2614,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // cycled section VAOs, re-reading the cold attribute slots each time; here a // cycle re-hits every VAO's own entry. The rebuild visits only ACTIVE locations. auto& memo = vaoTwin->GetPendingAttribValueMaskMemo(); -#if MOBILEGL_BUILD_RECORD_ARM if (fromRecords) { // The re-keyed memo: {elementsHandle, ContentSerial, activeMask}. Every // Enable/DisableVertexAttribArray moves the frontend configuration version, the @@ -2758,7 +2642,6 @@ namespace MobileGL::MG_Backend::DirectGLES { memo.valid = true; } } else -#endif { const Uint32 configVersion = vao->GetConfigVersion(); if (!memo.valid || configVersion != memo.configVersion || @@ -2975,13 +2858,11 @@ namespace MobileGL::MG_Backend::DirectGLES { #ifdef TRACY_ENABLE ZoneScopedC(TRACY_ZONECOLOR_BACKEND); #endif -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): this sync still arrives holding the FRONTEND object // (the object-class rows) and resolves its twin by frontend identity - the // frontend-keyed registry P3b/P4b rekeys onto handles. The probe (and the mint on // a first sync) is named debt inside the scope, not an unwrapped violation. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif auto* backendTextureSlot = g_backendTextureObjects.Find(textureObject.get()); auto& backendSlot = backendTextureSlot ? *backendTextureSlot : g_backendTextureObjects.GetOrCreate(textureObject); @@ -3204,7 +3085,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // mode here - a silent permanent fallback is, and that is what the line is for. // The caller's MINOR-4 gate tick still counts EVERY decline, loud or not. if (st.SamplerViewCount == 0 && st.SamplerStateCount == 0) { -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2), CONTRACT-P5E §5.3: UNDER A LIVE WIRE THE DECLINE IS A REFUSAL. // // The fall-back below is the pre-handle snapshot walk over GetTextureUnitObject, @@ -3233,7 +3113,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return true; } } -#endif if (maxTouchedUnit >= 0) { MGLOG_E_ONCE("A sampler record does not describe the binding it names: a draw " "touches units 0..%d and neither a sampler-view nor a sampler-state " @@ -3345,7 +3224,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } return true; } -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2), CONTRACT-P5E §5.8 / ruling 1: THE ARM SELECTOR for every by-handle site in // this family. Under ANY active transport (lockstep or run-ahead, so RUN_AHEAD=0 stays a // pure wait-rule A/B on identical server code), and only with BOTH family bits set: a @@ -3387,7 +3265,6 @@ namespace MobileGL::MG_Backend::DirectGLES { static Uint32 g_unitTextureSyncListByHandleStart = 0; static Uint32 g_unitTextureSyncListByHandleCount = 0; static Uint g_unitTextureSyncListByHandleContextGeneration = 0; -#endif static Vector g_unitTextureSyncList; static Bool g_unitTextureSyncListValid = false; static Uint64 g_unitTextureSyncListContextId = 0; @@ -3564,7 +3441,6 @@ namespace MobileGL::MG_Backend::DirectGLES { static Uint64 g_readFboTextureSyncListContentHash = 0; static Bool g_readFboTextureSyncListRecordKeyed = false; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (fb, CONTRACT-P5E.md §5.4): THE RECORD ARM OF BOTH ATTACHMENT LISTS, and it is // the package's core - this is the one unconditional per-draw live read the framebuffer // family had, taken on every draw whether the memo hit or missed. @@ -3630,7 +3506,6 @@ namespace MobileGL::MG_Backend::DirectGLES { g_readFboAttachmentSyncListContextGeneration = g_backendContextGeneration; g_readFboAttachmentSyncListValid = true; } -#endif // MOBILEGL_BUILD_RECORD_ARM static void SyncReadFramebufferTextureAttachments(const DrawTextureSyncKeys& keys, const MG_State::GLState::FramebufferObject* drawFbo) { @@ -3722,7 +3597,6 @@ namespace MobileGL::MG_Backend::DirectGLES { const Int maxTouchedUnit = keys.maxTouchedUnit; const Uint64 samplingGeneration = keys.samplingGeneration; const Uint64 unitBindingsEpoch = keys.unitBindingsEpoch; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2), CONTRACT-P5E §5.2. THE UNIT HALF, BY HANDLE. // // set_sampler_views is the RESOLVED answer to the question this walk asks - which @@ -3783,7 +3657,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // frontend slots this arm never refreshed. g_unitTextureSyncListValid = false; } else -#endif // The epoch survives redundant re-binds; the sampling-resolution generation // covers the one membership input the epoch cannot see - a default texture's // image appearing or vanishing flips IsUndefinedDefaultTexture with no binding @@ -3854,7 +3727,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // registry keeps a backend object alive until its frontend texture expires, which an // attached texture cannot. A renderbuffer-only FBO - the common Minecraft frame - // reduces to the key compare and an empty loop. -#if MOBILEGL_BUILD_RECORD_ARM // P5e (fb): under a transport with the framebuffer bit set, BOTH attachment lists // are answered from the two records and neither binding slot is touched. The // pre-handle pair below stays compiled and stays the monolith path (ruling 1). @@ -3862,7 +3734,6 @@ namespace MobileGL::MG_Backend::DirectGLES { SyncFramebufferAttachmentTexturesByRecord(); return; } -#endif const auto& drawSlot = GetFramebufferBindingSlotChecked(FramebufferTarget::Draw); const auto& currentFBO = drawSlot.GetBoundObject(); if (currentFBO) { @@ -3996,7 +3867,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // draw-path staleness check below at one integer test. static Uint g_imageUnitHighWaterMark = 0; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (fb): the eager glBindImageTexture funnel's HANDLE ARM, and it binds nothing. // // `bind_shader_image` is an unbarriered row (§2.2) whose backend entry point takes GL @@ -4020,7 +3890,6 @@ namespace MobileGL::MG_Backend::DirectGLES { g_imageUnitHighWaterMark = unit + 1; } } -#endif // ---- P5e (fb, CONTRACT-P5E.md §5.4 / ruling 16 / ID-94): the image unit's bind ------ // // P4a e3's ResolveShaderImageRecord IS GONE, identity test, I5 seam log and all. It @@ -4254,7 +4123,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // there is one statement of it, and the unit-tracking bookkeeping below stays out of // reach of an apply thread entirely. void MarkWritableImageBufferTexturesGpuWritten() { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { // P8-C: the SERVER's twin of the buffer behind each writable buffer image, for // this side's CPU readers (SplitHostBytesForCpuRead). Every read is a record: @@ -4275,7 +4143,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } return; } -#endif if (g_writableImageBufferUnitCount == 0) return; for (Uint unit = 0; unit < g_writableImageBufferUnits.size(); ++unit) { if (!g_writableImageBufferUnits[unit]) continue; @@ -4288,7 +4155,6 @@ namespace MobileGL::MG_Backend::DirectGLES { static_cast(imageBinding.Texture.get()); const auto& bufferObject = textureBuffer->GetBufferBindingSlot().GetBoundObject(); BufferImpl::MarkBufferGpuWritten(bufferObject); -#if MOBILEGL_BUILD_RECORD_ARM // P13 W4a: image units stay on this arm until W4c, but monolith's buffer readers // are already the record arm's (SplitHostBytesForCpuRead), and they ask the TWIN. if (MG_Config::DataArmIsRecord() && bufferObject) { @@ -4297,7 +4163,6 @@ namespace MobileGL::MG_Backend::DirectGLES { twin->serverGpuWritten = true; } } -#endif } } @@ -4369,7 +4234,6 @@ namespace MobileGL::MG_Backend::DirectGLES { std::max(st.ShaderImageStart + st.ShaderImageCount, static_cast(g_imageUnitHighWaterMark)), static_cast(unitCount)); -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { for (Uint32 unit = 0; unit < end; ++unit) { if (unit >= st.BoundShaderImages.size()) break; @@ -4384,21 +4248,18 @@ namespace MobileGL::MG_Backend::DirectGLES { } return; } -#endif for (Uint32 unit = 0; unit < end; ++unit) { SyncImageTextureBinding(unit); } return; } } -#if MOBILEGL_BUILD_RECORD_ARM // The wide pre-handle sweep reads the frontend binding of every unit, which an // apply thread may not do. Under a transport there is nothing for it to do anyway: // g_imageUnitHighWaterMark is raised only by the funnel above, so if no set has // ever arrived no unit has ever been given an image, and re-binding 0 on units that // never held one is the no-op the comment above already proved. if (MG_Config::DataArmIsRecord()) return; -#endif for (Uint unit = 0; unit < unitCount; ++unit) { SyncImageTextureBinding(unit); } @@ -4416,7 +4277,6 @@ namespace MobileGL::MG_Backend::DirectGLES { static Uint64 g_imageSweepSamplingGeneration = 0; static Uint g_imageSweepBackendContextGeneration = 0; static Bool g_imageSweepValid = false; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (fb, ruling 7 / ID-86): the record arm's three applier serials. Held in their own // fields beside the frontend pair rather than reusing them, for the reason the two // framebuffer list keys are held apart - one field carrying two key shapes is how a @@ -4424,7 +4284,6 @@ namespace MobileGL::MG_Backend::DirectGLES { static Uint64 g_imageSweepShaderImagesSerial = 0; static Uint64 g_imageSweepTextureShutterSerial = 0; static Uint64 g_imageSweepContextSerial = 0; -#endif // The sweep is a glBindImageTexture per unit, so it must not run per draw: the gate is the // frontend's sampling-resolution generation, which TextureObjectBase::BumpShapeVersion @@ -4467,7 +4326,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // ES context is rebuilt, which no sweep does. void SyncImageTextureBindingsForDraw(const DrawTextureSyncKeys& keys) { if (g_imageUnitHighWaterMark == 0) return; -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const auto& st = MG_Pipe::MGPipeApplier(); if (g_imageSweepValid && g_imageSweepShaderImagesSerial == st.ShaderImagesSerial && @@ -4484,7 +4342,6 @@ namespace MobileGL::MG_Backend::DirectGLES { g_imageSweepValid = true; return; } -#endif if (g_imageSweepValid && g_imageSweepContextId == keys.contextId && g_imageSweepSamplingGeneration == keys.samplingGeneration && g_imageSweepBackendContextGeneration == g_backendContextGeneration) { @@ -4607,22 +4464,18 @@ namespace MobileGL::MG_Backend::DirectGLES { // not run at all, rather than running on a value it is not allowed to have. static Bool FramebufferRecordMatchesBinding(FramebufferTarget target, const MG_Pipe::MGPFramebufferState& record) { -#if MOBILEGL_BUILD_RECORD_ARM if (FramebufferRecordArmIsMandatory()) return true; -#endif const auto& bound = GetFramebufferBindingSlotChecked(target).GetBoundObject(); const Bool boundIsDefault = !bound || bound == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO; if ((record.IsDefault != 0) != boundIsDefault) return false; if (boundIsDefault) return true; -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd): the object-handle half of the identity check is a client-allocator // probe (T2). Under an active transport the record is the only statement of // identity (rule E) and the check does not run - the record was resolved from the // applier's OWN bound handle, so it is this binding's by construction (ID-19). // Monolith keeps the corroboration verbatim. if (MG_Config::DataArmIsRecord()) return true; -#endif return record.Fbo == g_backendFramebufferObjects.HandleOf(bound.get()); } @@ -4813,7 +4666,6 @@ namespace MobileGL::MG_Backend::DirectGLES { boundHandles[SizeT(MG_Pipe::MGPipeFramebufferTarget::Draw)] == boundHandles[SizeT(MG_Pipe::MGPipeFramebufferTarget::Read)]; -#if MOBILEGL_BUILD_RECORD_ARM if (FramebufferRecordArmIsMandatory()) { if (sameObjectOnBothBindings) { backendObj->SyncReadBufferToBackendByHandle(record.Fbo); @@ -4823,7 +4675,6 @@ namespace MobileGL::MG_Backend::DirectGLES { StampSyncedFramebufferSerial(target, st.FramebufferSerial); continue; } -#endif auto& slot = GetFramebufferBindingSlotChecked(target); const auto& currentFBO = slot.GetBoundObject(); // P4a decline-site F4: S - FLIPPED AT THE VERIFICATION ROUND to the FULL @@ -4842,13 +4693,11 @@ namespace MobileGL::MG_Backend::DirectGLES { g_fboRecordsTrusted = false; return false; } -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd): the push-monolith twin keys its applier-record lookup on the // record's own handle (m_pushedSyncHandle) rather than on the client allocator. // The state note is GONE with P5e: nothing resolves a framebuffer by handle and // then asks the table for an object any more. backendObj->m_pushedSyncHandle = record.Fbo; -#endif if (sameObjectOnBothBindings) { backendObj->SyncReadBufferToBackend(currentFBO); StampSyncedFramebufferSerial(target, st.FramebufferSerial); @@ -4876,7 +4725,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // IS D's FramebufferSubsystemEnabled() now. Silent, confirmed at the // verification round. if (FramebufferSubsystemEnabled() && SyncCurrentFBOByRecord()) return; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (fb, CONTRACT-P5E.md §5.4): AND UNDER A TRANSPORT THE DECLINE IS THE END OF // IT. The fallback below reads GetFramebufferBindingSlot, a BARRIER_PULLED row; the // value it would read belongs to a client this apply is no longer synchronous with, @@ -4889,19 +4737,16 @@ namespace MobileGL::MG_Backend::DirectGLES { if (FramebufferRecordArmIsMandatory()) { RefuseFramebufferBindingSlotRead(); } -#endif const FramebufferTarget fboTargets[] = {FramebufferTarget::Draw, FramebufferTarget::Read}; MG_State::GLState::FramebufferObject* lastUpdatedFBO = nullptr; for (auto& target : fboTargets) { -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): the twin resolutions this iteration may run // below are frontend-keyed, named debt inside the scope - P3b/P4b rekeys the // registry onto handles. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif auto& slot = GetFramebufferBindingSlotChecked(target); auto& currentFBO = slot.GetBoundObject(); @@ -5962,12 +5807,10 @@ namespace MobileGL::MG_Backend::DirectGLES { // token for token. static const MG_Pipe::MGPipeShaderCsoRecord* ResolveGlobalConstantsRecord( const MG_State::GLState::ProgramObject* program) { -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named debt inside the // scope. P5e does not delete it - it stops REACHING it under a transport, which is // the thing the allocator guard measures. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif // P4a decline-site P1: M - the mask says this family is not switched on, or there // is no current program at all; it IS D's ProgramSubsystemEnabled() now. Silent, // confirmed at the verification round. @@ -6078,12 +5921,10 @@ namespace MobileGL::MG_Backend::DirectGLES { #ifdef TRACY_ENABLE ZoneScopedC(TRACY_ZONECOLOR_BACKEND); #endif -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): the twin resolution below still keys on the frontend // program object - named debt inside the scope - P3b/P4b rekeys the registry onto // handles. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif g_backendProgramObjects.CollectGarbageIfNeeded(); SamplerImpl::g_backendSamplerObjects.CollectGarbageIfNeeded(); @@ -6313,7 +6154,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return; } } -#if MOBILEGL_BUILD_RECORD_ARM // P5e (fb, §5.4): the pre-handle arm below reads the binding slot, so under a transport // reaching it is the same refusal SyncCurrentFBO takes. Reaching it means either the // sync's trust latch is clear - and the sync aborted before it could be - or this bind @@ -6321,7 +6161,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (FramebufferRecordArmIsMandatory()) { RefuseFramebufferBindingSlotRead(); } -#endif auto& slot = GetFramebufferBindingSlotChecked(target); // No fast path on the binding slot's version. It is a 16-bit counter that only @@ -6337,11 +6176,9 @@ namespace MobileGL::MG_Backend::DirectGLES { // and the twin memo replaces even that with an array probe on the steady path. const auto& currentFBO = slot.GetBoundObject(); if (currentFBO && currentFBO != MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) { -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named debt inside // the scope - P3b/P4b rekeys the registry onto handles. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif FramebufferImpl::BackendFramebufferObject* twin = nullptr; if (EsprytSlotTablesEnabled()) { // Not "slot": the enclosing scope's `slot` is the framebuffer BINDING slot, @@ -6402,7 +6239,6 @@ namespace MobileGL::MG_Backend::DirectGLES { backendObj->Bind(target); } -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.2/§3.3): the handle-keyed form of SyncAndBindFramebufferObject. // With an active transport a framebuffer reaches the server as the handle a record // carried - the named blit's ReadFbo/DrawFbo, or the applier's own bound handle for a @@ -6456,13 +6292,11 @@ namespace MobileGL::MG_Backend::DirectGLES { backendObj->SyncToBackendByHandle(fbo, target); backendObj->Bind(target); } -#endif // MOBILEGL_BUILD_RECORD_ARM void ForceBindCurrentFBO(FramebufferTarget target) { #ifdef TRACY_ENABLE ZoneScopedC(TRACY_ZONECOLOR_BACKEND); #endif -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd): with an active transport the bound framebuffer's handle is the applier's // own working state; the object form's registry probe never runs (T2). // @@ -6482,7 +6316,6 @@ namespace MobileGL::MG_Backend::DirectGLES { : MG_Pipe::MGPipeFramebufferTarget::Draw)], target); } else -#endif { auto& slot = GetFramebufferBindingSlotChecked(target); const auto& fbo = slot.GetBoundObject(); @@ -6546,11 +6379,7 @@ namespace MobileGL::MG_Backend::DirectGLES { // conjunct only exists there (UnitTexturesByHandle is tx2's, split-only); a push-VERIFY build // therefore keeps the frontend hoist, which is what the comparator compares against. inline Bool DrawProgramFromRecords() { -#if MOBILEGL_BUILD_RECORD_ARM return ProgramHandleArm() && TextureImpl::UnitTexturesByHandle(); -#else - return false; -#endif } void PrepareForDraw(DrawSyncFlags syncBit) { @@ -6574,11 +6403,9 @@ namespace MobileGL::MG_Backend::DirectGLES { const auto& currentVAO = vertexInputFromRecords ? noFrontendVao : MG_Pipe::gPipeInputs.GetBoundVertexArray(); VertexArrayImpl::BackendVertexArrayObject* vaoTwin = nullptr; Uint32 vaoConfigVersion = 0; -#if MOBILEGL_BUILD_RECORD_ARM if (vertexInputFromRecords) { vaoTwin = VertexArrayImpl::ResolveVaoTwin(MG_Pipe::MGPipeApplier().BoundVertexElements); } else -#endif { vaoTwin = currentVAO ? VertexArrayImpl::ResolveVaoTwin(currentVAO) : nullptr; // Early config-version read: see the note on SyncNeccessaryBuffers - issuing @@ -6621,11 +6448,9 @@ namespace MobileGL::MG_Backend::DirectGLES { BufferImpl::SyncNeccessaryBuffers(currentVAO, vaoTwin, vaoConfigVersion, syncBit & DrawSyncBit::IndexBuffer, syncBit & DrawSyncBit::IndirectBuffer); -#if MOBILEGL_BUILD_RECORD_ARM if (vertexInputFromRecords) { VertexArrayImpl::SyncCurrentVAOFromRecords(vaoTwin); } else -#endif { VertexArrayImpl::SyncCurrentVAO(currentVAO, vaoTwin); } @@ -6702,7 +6527,6 @@ namespace MobileGL::MG_Backend::DirectGLES { ZoneScopedNC("ResolveAndBindUnitTextures", TRACY_ZONECOLOR_BACKEND); #endif Bool fullyResolved = true; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2), CONTRACT-P5E §5.2. ONE PASS OVER THE SAMPLER-VIEW WINDOW, AND THEN AN // UNBIND OF EVERY TARGET THE WINDOW DID NOT CLAIM. // @@ -6777,7 +6601,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } return fullyResolved; } -#endif // Frontend target the current program samples at a given unit; resolves an // aliased native binding when two real textures compete for it (see below). // Only consulted on a conflict, so the ordinary unit costs nothing. @@ -6865,11 +6688,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } // Bind texture object -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named debt // inside the scope - P3b/P4b rekeys the registry onto handles. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif auto* backendTextureSlot = TextureImpl::g_backendTextureObjects.Find(textureObject.get()); if (!backendTextureSlot || !*backendTextureSlot) { fullyResolved = false; @@ -6927,7 +6748,6 @@ namespace MobileGL::MG_Backend::DirectGLES { static SamplerImpl::BackendSamplerObject* ResolveUnitSamplerBackend( Int unit, const SharedPtr& samplerObject) { -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2), CONTRACT-P5E §4.2's last paragraph: THE IDENTITY SAMPLER FAMILY IS DELETED // UNDER A TRANSPORT AND BECOMES A NAMED REFUSAL. // @@ -6950,7 +6770,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named debt inside the // scope - the refusal above is what retires it under a transport. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif auto& memo = g_unitSamplerLookupMemos[static_cast(unit)]; if (EsprytSlotTablesEnabled()) { const MG_Pipe::MGPipeHandle handle = @@ -7044,7 +6863,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // empty window is the correct emission. All 161 hits of the unnarrowed line were // that shape - the log said `units 0..-1` on every one of them. if (st.SamplerStateCount == 0 && maxTouchedUnit >= 0) { -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2), CONTRACT-P5E §5.3: the same refusal CurrentUnitBindingsEpoch makes - // the frontend walk below reads GetTextureUnitObject per unit, which an active // transport may not do for a record whose client has moved on. @@ -7057,7 +6875,6 @@ namespace MobileGL::MG_Backend::DirectGLES { static_cast(maxTouchedUnit)); std::abort(); } -#endif MGLOG_E_ONCE("A sampler record does not describe the binding it names: a draw touches " "units 0..%d and no bind_sampler_states has ever been applied while the " "sampler subsystem bit is set; running the pre-handle sampler walk.", @@ -7189,7 +7006,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // travels) and BindingsSerial on every applied set_program_bindings (how a glUniform1i // on a sampler travels). Both are needed - ruling 6's "both" - because a relink with // UNCHANGED texture resolution still hands the twin new unit assignments. -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2), CONTRACT-P5E §5.3 / ruling 6 (ID-86): THE KEY IS BOTH HALVES. // // S2 argued SamplerViewsSerial alone - it already mixes the program-resolved opaque units, @@ -7206,7 +7022,6 @@ namespace MobileGL::MG_Backend::DirectGLES { Uint64 samplerViewsSerial = 0; Uint64 contextSerial = 0; Bool byHandle = false; -#endif decltype(TextureImpl::g_boundTexturesCache) boundTextures{}; }; // Small per-PROGRAM memo set, not one global: the program is part of the key @@ -7243,7 +7058,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // Units past the frontend's high-water mark have provably-empty slots. const Int maxTouchedUnit = keys.maxTouchedUnit; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2) / ruling 6: on the handle arm the key is the applier's rows and nothing // frontend - INCLUDING the entry selection, which used the frontend program's address. // maxTouchedUnit stays in it because the unbind sweep this memo replays is bounded by it. @@ -7263,7 +7077,6 @@ namespace MobileGL::MG_Backend::DirectGLES { bindingsSerial = cso->BindingsSerial; } } -#endif // Entry selection by program pointer; a missing program takes the round-robin // victim. WHICH entry is used is only a performance choice - correctness sits // entirely in the full key + shadow compare below, unchanged from the single @@ -7274,13 +7087,10 @@ namespace MobileGL::MG_Backend::DirectGLES { // looks at this value, but it was still being loaded out of the caller's SharedPtr every // draw - and once the caller stops holding one there is nothing there to load. const void* programKey = -#if MOBILEGL_BUILD_RECORD_ARM byHandle ? nullptr : -#endif static_cast(currentProgram.get()); ResolvedTextureBindingMemo* memoSlot = nullptr; for (auto& candidate : g_resolvedTextureBindingMemos) { -#if MOBILEGL_BUILD_RECORD_ARM if (byHandle) { if (candidate.valid && candidate.byHandle && candidate.drawProgram.Slot == drawProgram.Slot && candidate.drawProgram.Gen == drawProgram.Gen) { @@ -7289,7 +7099,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } continue; } -#endif if (candidate.valid && candidate.program == programKey) { memoSlot = &candidate; break; @@ -7323,7 +7132,6 @@ namespace MobileGL::MG_Backend::DirectGLES { memo.programLinked == (currentProgram && currentProgram->GetLinkStatus()) && memo.contextGeneration == g_backendContextGeneration); }; -#if MOBILEGL_BUILD_RECORD_ARM const Bool keysMatch = byHandle ? (memo.valid && memo.byHandle && memo.maxTouchedUnit == maxTouchedUnit && memo.contextSerial == contextSerial && memo.samplerViewsSerial == samplerViewsSerial && @@ -7331,9 +7139,6 @@ namespace MobileGL::MG_Backend::DirectGLES { memo.shaderCsoSerial == shaderCsoSerial && memo.bindingsSerial == bindingsSerial && memo.contextGeneration == g_backendContextGeneration) : legacyKeysMatch(); -#else - const Bool keysMatch = legacyKeysMatch(); -#endif // Short-circuited: the shadow compare is only meaningful once the key (and with it the // snapshotted row count) matches. if (!keysMatch || std::memcmp(memo.boundTextures.data(), TextureImpl::g_boundTexturesCache.data(), @@ -7345,7 +7150,6 @@ namespace MobileGL::MG_Backend::DirectGLES { memo.unitBindingsEpoch = unitBindingsEpoch; memo.samplingResolutionGeneration = keys.samplingGeneration; memo.program = programKey; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (pa): the four frontend program rows belong to the LEGACY key and are not // written on the handle arm - decided by `byHandle`, which is the arm, and not by // the object happening to be null, which is only a consequence of it. They are @@ -7355,7 +7159,6 @@ namespace MobileGL::MG_Backend::DirectGLES { memo.programBackendStateVersion = 0; memo.programLinked = false; } else -#endif { memo.programLifetimeId = currentProgram ? currentProgram->GetLifetimeId() : 0; memo.programBackendStateVersion = @@ -7363,14 +7166,12 @@ namespace MobileGL::MG_Backend::DirectGLES { memo.programLinked = currentProgram && currentProgram->GetLinkStatus(); } memo.contextGeneration = g_backendContextGeneration; -#if MOBILEGL_BUILD_RECORD_ARM memo.byHandle = byHandle; memo.drawProgram = drawProgram; memo.shaderCsoSerial = shaderCsoSerial; memo.bindingsSerial = bindingsSerial; memo.samplerViewsSerial = samplerViewsSerial; memo.contextSerial = contextSerial; -#endif std::memcpy(memo.boundTextures.data(), TextureImpl::g_boundTexturesCache.data(), shadowBytes); memo.valid = true; } @@ -7438,13 +7239,11 @@ namespace MobileGL::MG_Backend::DirectGLES { if (!twin) twin = PrgramImpl::ResolveProgramTwin(programCso); } else { -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): MONOLITH GLUE ONLY now. The frontend-keyed twin // resolution below is the fourth of this family's five named scope sites, and // P5e does not delete it - it stops reaching it under a transport, which is what // the allocator guard measures. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif // The twin SyncCurrentProgram just resolved for this draw; the registry // Find only runs if the stash somehow does not match (defensive fallback). twin = PrgramImpl::g_currentDrawFrontendProgram == currentProgram.get() @@ -7613,7 +7412,6 @@ namespace MobileGL::MG_Backend::DirectGLES { handleArm ? PrgramImpl::ProgramBlockBindingFromRecord(*programRecord, i) : currentProgram->GetUniformBlockBinding(i); -#if MOBILEGL_BUILD_RECORD_ARM // P5e (sb, §5.6): THE POINT HALF, by record. `binding` above is the // PROGRAM's block binding and stays exactly where it is (it is package // pg's row); what moves is the point it indexes. The index space is the @@ -7674,7 +7472,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } continue; } -#endif auto& point = MG_Pipe::gPipeInputs.GetBufferBindingPoint(BufferTarget::Uniform, binding); auto& bufferObj = point.GetBoundObject(); auto range = point.GetRange(); @@ -7790,7 +7587,6 @@ namespace MobileGL::MG_Backend::DirectGLES { samplerBinding.lastAssignedUnit = unit; } -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2), CONTRACT-P5E §5.3. THE SAMPLER PASS, FROM RECORDS. // // Four frontend reads used to live in this loop body and every one of @@ -7867,7 +7663,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } continue; } -#endif auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit); auto& samplerObject = textureUnit.GetSamplerObject(); const auto& texture2D = @@ -8002,11 +7797,9 @@ namespace MobileGL::MG_Backend::DirectGLES { if (PrgramImpl::g_currentDrawFrontendProgram == currentProgram.get()) { return PrgramImpl::g_currentDrawBackendProgram; } -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): MONOLITH GLUE ONLY now - the fifth of this family's five // named scope sites, unreachable under a transport by the arm above. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif if (auto* backendProgramSlot = PrgramImpl::g_backendProgramObjects.Find(currentProgram.get())) { return backendProgramSlot->get(); } @@ -8258,7 +8051,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return g_GLESCapabilities.SupportsDrawIndirect; } -#if MOBILEGL_BUILD_RECORD_ARM // P8-C: the command bytes an indirect executor is about to CONSUME on the CPU, made current. // Consumed means: every field on the CPU path (no native indirect), or on the native path the // uniforms fed from the command - gl_BaseVertex whenever the program reads it, and @@ -8280,7 +8072,6 @@ namespace MobileGL::MG_Backend::DirectGLES { const Uint8* base = BufferImpl::SplitHostBytesForCpuRead(*resource, handle, "indirect_command_fields"); return base != nullptr ? base + commandOffset : commandBytes; } -#endif // Runs an (indexed) indirect multi-draw. When a GL_DRAW_INDIRECT_BUFFER is bound the draws // execute natively on the GPU so commands written by compute shaders (e.g. Flywheel's @@ -8311,7 +8102,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (!restart.DrawIsValid()) return; type = restart.IndexType(); indexSize = MG_Util::GetGLTypeSize(type); -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): under an active transport the command buffer is the // handle the verb record carried (MGPipeApplier's verb stash) and the SSBO view's // resource resolves from it by handle - the frontend binding slot and the client slot @@ -8320,18 +8110,13 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_Config::DataArmIsRecord() ? MG_Pipe::MGPipeApplier().VerbIndirectBuffer : MG_Pipe::kMGPipeNullHandle; -#endif const Bool useNative = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? !MG_Pipe::MGPipeHandleIsNull(verbBufferHandle) && SupportsNativeIndirectDraws() : -#endif drawIndirectBuffer != nullptr && SupportsNativeIndirectDraws(); -#if MOBILEGL_BUILD_RECORD_ARM commandBytes = CurrentIndirectCommandBytes(verbBufferHandle, commandBytes, commandOffset, useNative, /*indexed=*/true); -#endif if (useNative) { // gl_BaseInstance must observe GPU-written command fields; expose the indirect // buffer to the program's mg_IndirectParams SSBO view and address it per draw. @@ -8339,11 +8124,9 @@ namespace MobileGL::MG_Backend::DirectGLES { const Int paramsBinding = backendProgram ? backendProgram->GetIndirectParamsBinding() : -1; if (paramsBinding >= 0) { auto* resource = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? BufferImpl::EnsureBufferResourceForHandle(nullptr, verbBufferHandle) : -#endif BufferImpl::EnsureBufferResource(drawIndirectBuffer); if (resource && resource->id != 0) { BufferImpl::BindBufferBaseCached(GL_SHADER_STORAGE_BUFFER, static_cast(paramsBinding), @@ -8415,35 +8198,27 @@ namespace MobileGL::MG_Backend::DirectGLES { // draw is what leaves a stale value, and restoring afterwards would only protect the // NEXT draw while these commands ran with the stale one. SetCurrentBaseVertex(0); -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): see ExecuteIndexedIndirectCommands - the verb's handle, // never the frontend binding slot or the client allocator. const MG_Pipe::MGPipeHandle verbBufferHandle = MG_Config::DataArmIsRecord() ? MG_Pipe::MGPipeApplier().VerbIndirectBuffer : MG_Pipe::kMGPipeNullHandle; -#endif const Bool useNative = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? !MG_Pipe::MGPipeHandleIsNull(verbBufferHandle) && SupportsNativeIndirectDraws() : -#endif drawIndirectBuffer != nullptr && SupportsNativeIndirectDraws(); -#if MOBILEGL_BUILD_RECORD_ARM commandBytes = CurrentIndirectCommandBytes(verbBufferHandle, commandBytes, commandOffset, useNative, /*indexed=*/false); -#endif if (useNative) { const auto backendProgram = GetCurrentBackendProgram(); const Int paramsBinding = backendProgram ? backendProgram->GetIndirectParamsBinding() : -1; if (paramsBinding >= 0) { auto* resource = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? BufferImpl::EnsureBufferResourceForHandle(nullptr, verbBufferHandle) : -#endif BufferImpl::EnsureBufferResource(drawIndirectBuffer); if (resource && resource->id != 0) { BufferImpl::BindBufferBaseCached(GL_SHADER_STORAGE_BUFFER, static_cast(paramsBinding), @@ -8555,38 +8330,6 @@ namespace MobileGL::MG_Backend::DirectGLES { ); } -#if !MOBILEGL_BUILD_RECORD_ARM - // P5f (fr): no declaration, dispatch-table slot or caller remains for this legacy - // helper. Exclude it from the server-capable build; retain non-D-P bytes for G1. - GLuint GetBackendProgramId(GLuint program) { - if (!MG_Pipe::gPipeInputs.ValidateProgramName(program)) { - MGLOG_E_ONCE("Invalid frontend program object: %u", program); - return 0; - } - - auto& programObject = MG_Pipe::gPipeInputs.GetProgramObject(program); - if (!programObject) { - MGLOG_E_ONCE("Program object %u is null.", program); - return 0; - } - -#if MOBILEGL_BUILD_RECORD_ARM - // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named debt inside the - // scope - P3b/P4b rekeys the registry onto handles. - const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif - auto* backendProgramSlot = PrgramImpl::g_backendProgramObjects.Find(programObject.get()); - auto& backendObj = - backendProgramSlot ? *backendProgramSlot : PrgramImpl::g_backendProgramObjects.GetOrCreate(programObject); - if (!backendObj) { - backendObj = MakeShared(); - } - if (!backendObj->GetBackendProgramId()) { - backendObj->SyncToBackend(programObject); - } - return backendObj->GetBackendProgramId(); - } -#endif void Clear(GLbitfield mask) { #if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG && MOBILEGL_ENABLE_SCOPE_MARKER @@ -8693,7 +8436,6 @@ namespace MobileGL::MG_Backend::DirectGLES { const GLenum rbErr = g_GLESFuncs.glGetError(); int feDb0 = -1, feDb1 = -1; Uint feIdx = 0, feVer = 0; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (fb): DEBUG-ONLY, and still a BARRIER_PULLED read. A diagnostic // is not a reason to touch the binding slot on an apply thread, so // under a transport the same four numbers come off the draw record - @@ -8707,7 +8449,6 @@ namespace MobileGL::MG_Backend::DirectGLES { feDb1 = (int)rec->DrawBuffers[1]; } } else -#endif { const auto& feFbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); @@ -8882,7 +8623,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // from the apply thread aborts by name instead of pulling GetBoundVertexArray behind // the family's back. void RefuseElementArrayBufferFromTheFrontend(const char* entry) { -#if MOBILEGL_BUILD_RECORD_ARM if (!MG_Config::DataArmIsRecord()) return; if (!BufferImpl::VertexInputReadsRecords()) return; MGLOG_F("MGPipe: Fatal{RoleViolation, \"MGPipeSlots\"} - %s read the frontend VAO's " @@ -8892,9 +8632,6 @@ namespace MobileGL::MG_Backend::DirectGLES { "record this draw is being applied from", entry); std::abort(); -#else - (void)entry; -#endif } const SharedPtr& BoundElementArrayBuffer() { @@ -8969,13 +8706,10 @@ namespace MobileGL::MG_Backend::DirectGLES { SizeT indexCount = 0; SizeT sourceByteOffset = 0; Bool hasElementBuffer = false; -#if MOBILEGL_BUILD_RECORD_ARM // -1: monolith, or this arm never resolved a backend id, and the tail asks // BoundElementArrayBufferId() exactly as it always did. Int serverElementBinding = -1; -#endif -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): with an active transport this constructor runs on the // apply thread, where the frontend BufferObject's legacy accessors are Fatal by name // (BufferObject.cpp's "buffer-legacy-arm" refusal). The element buffer therefore @@ -9046,7 +8780,6 @@ namespace MobileGL::MG_Backend::DirectGLES { sourceByteOffset = reinterpret_cast(indices); } } else -#endif { const auto& indexBuffer = BoundElementArrayBuffer(); if (indexBuffer) { @@ -9138,11 +8871,9 @@ namespace MobileGL::MG_Backend::DirectGLES { return; } m_previousBinding = 0; -#if MOBILEGL_BUILD_RECORD_ARM if (serverElementBinding >= 0) { m_previousBinding = static_cast(serverElementBinding); } else -#endif { m_previousBinding = BoundElementArrayBufferId(); } @@ -9281,14 +9012,12 @@ namespace MobileGL::MG_Backend::DirectGLES { } const auto& drawIndirectBuffer = -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): with an active transport the frontend binding slot // is never read - the Execute* helpers resolve the buffer from the verb record's // handle (T2). Monolith reads the slot as it always did. MG_Config::DataArmIsRecord() ? SharedPtr(nullptr) : -#endif MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); ExecuteIndexedIndirectCommands(mode, type, indexSize, commandBytes, reinterpret_cast(indirect), drawIndirectBuffer, drawcount, stride, "MultiDrawElementsIndirect"); @@ -9320,7 +9049,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return; } -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): with an active transport both buffers resolve from the // verb record's handles (MGPDrawIndirect::Buffer / ParameterBuffer) and the count // reads from the SERVER's staged shadow - the frontend binding slots, the frontend @@ -9377,7 +9105,6 @@ namespace MobileGL::MG_Backend::DirectGLES { "MultiDrawElementsIndirectCount"); return; } -#endif auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); auto parameterBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::Parameter).GetBoundObject(); @@ -9450,14 +9177,12 @@ namespace MobileGL::MG_Backend::DirectGLES { } const auto& drawIndirectBuffer = -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): with an active transport the frontend binding slot // is never read - the Execute* helpers resolve the buffer from the verb record's // handle (T2). Monolith reads the slot as it always did. MG_Config::DataArmIsRecord() ? SharedPtr(nullptr) : -#endif MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); ExecuteArraysIndirectCommands(mode, commandBytes, reinterpret_cast(indirect), drawIndirectBuffer, drawcount, stride, "MultiDrawArraysIndirect"); @@ -9489,7 +9214,6 @@ namespace MobileGL::MG_Backend::DirectGLES { DrawSyncFlags syncBit = DrawSyncBit::IndirectBuffer | DrawSyncBit::Instancing; PrepareForDraw(syncBit); -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): see the indexed twin - the verb record's handles and // the SERVER's staged shadow, never the frontend bindings or the client allocator. if (MG_Config::DataArmIsRecord()) { @@ -9541,7 +9265,6 @@ namespace MobileGL::MG_Backend::DirectGLES { "MultiDrawArraysIndirectCount"); return; } -#endif auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); auto parameterBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::Parameter).GetBoundObject(); @@ -9721,14 +9444,12 @@ namespace MobileGL::MG_Backend::DirectGLES { } const auto& drawIndirectBuffer = -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): with an active transport the frontend binding slot // is never read - the Execute* helpers resolve the buffer from the verb record's // handle (T2). Monolith reads the slot as it always did. MG_Config::DataArmIsRecord() ? SharedPtr(nullptr) : -#endif MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); ExecuteIndexedIndirectCommands(mode, type, indexSize, commandBytes, reinterpret_cast(indirect), drawIndirectBuffer, 1, sizeof(DrawElementsIndirectCommand), @@ -9770,14 +9491,12 @@ namespace MobileGL::MG_Backend::DirectGLES { } const auto& drawIndirectBuffer = -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): with an active transport the frontend binding slot // is never read - the Execute* helpers resolve the buffer from the verb record's // handle (T2). Monolith reads the slot as it always did. MG_Config::DataArmIsRecord() ? SharedPtr(nullptr) : -#endif MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); ExecuteArraysIndirectCommands(mode, commandBytes, reinterpret_cast(indirect), drawIndirectBuffer, 1, sizeof(DrawArraysIndirectCommand), "DrawArraysIndirect"); @@ -10993,7 +10712,6 @@ namespace MobileGL::MG_Backend::DirectGLES { DebugImpl::OpenGLScopeMarker marker(__func__); #endif -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.3): THE NAMED ARM. A blit record whose ReadFbo/DrawFbo are // non-null is a glBlitNamedFramebuffer: both framebuffers resolve from the record's // handles through the FBO twin table (the client's ScopedBlitBindings staging and this @@ -11043,7 +10761,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return; } } -#endif TextureImpl::SyncNeccessaryTextures(); DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) { @@ -11067,7 +10784,6 @@ namespace MobileGL::MG_Backend::DirectGLES { dstX1, dstY1, mask, MG_Util::ConvertGLEnumToString(filter).c_str()); // A no-op on every driver that honours a non-zero destination array layer, which is all // of them but the probed one. Whatever it performs itself is taken out of the mask. -#if MOBILEGL_BUILD_RECORD_ARM // P5e (fb, §5.4): the bound arm's two binding-slot reads were the last GetBoundObject // pair on this path; under a transport the two bound RECORDS answer instead // (FramebufferRecordFor(st.BoundFramebuffer[t]), through BlitEndpointRecord's null @@ -11084,7 +10800,6 @@ namespace MobileGL::MG_Backend::DirectGLES { srcY1, dstX0, dstY0, dstX1, dstY1, mask); } } else -#endif mask &= ~BlitLayeredDestinationAspects( MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject(), MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(), srcX0, srcY0, @@ -11150,9 +10865,6 @@ namespace MobileGL::MG_Backend::DirectGLES { ZoneScopedNC(__func__, TRACY_ZONECOLOR_BACKEND); #endif auto unit = MG_Pipe::gPipeInputs.GetActiveTextureUnit(); -#if !MOBILEGL_BUILD_RECORD_ARM - auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit); -#endif auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); if (!TextureImpl::IsSupportedTextureTarget(textureTarget)) { @@ -11161,7 +10873,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return false; } -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.4): under an active transport the destination is the handle // the copy_framebuffer_to_texture record carried; the unit binding slot and the client // allocator are never read (T2/T4). @@ -11182,11 +10893,8 @@ namespace MobileGL::MG_Backend::DirectGLES { backendObj->Bind(TextureImpl::ConvertTextureTargetToBackendGLEnum(textureTarget), unit); return true; } -#endif -#if MOBILEGL_BUILD_RECORD_ARM auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit); -#endif const auto& bindingSlot = textureUnit.GetBindingSlot(textureTarget); { const auto& textureObject = bindingSlot.GetBoundObject(); @@ -11422,7 +11130,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return true; } -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2): the inverse of MG_Pipe::MGPipeResourceTargetForTextureTarget, for the two // descriptor reads this file makes (Managers.cpp has the same inverse beside the storage // sync; it is file-local there, and a header for eleven cases would be the wrong trade). @@ -11479,7 +11186,6 @@ namespace MobileGL::MG_Backend::DirectGLES { window.End = std::max(window.Base, std::min(end, window.Base + chain)); return window; } -#endif static Bool EnsureGenerateMipmapStorageAllocated(const SharedPtr& texture) { // P8-B1: the transport arm that stood here (a descriptor check under the same @@ -11552,7 +11258,6 @@ namespace MobileGL::MG_Backend::DirectGLES { class ScopedDetachedTextureFramebufferAttachments { public: -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2). THE SAME SWEEP, KEYED BY THE TEXTURE'S HANDLE. // // The frontend constructor below answers "which framebuffers attach this texture" by @@ -11624,7 +11329,6 @@ namespace MobileGL::MG_Backend::DirectGLES { detachPoint(record->Stencil, FramebufferAttachmentType::Stencil); }); } -#endif explicit ScopedDetachedTextureFramebufferAttachments( const SharedPtr& texture) { @@ -11632,11 +11336,9 @@ namespace MobileGL::MG_Backend::DirectGLES { return; } -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named debt inside // the scope - P3b/P4b rekeys the registry onto handles. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif auto* backendTextureSlot = TextureImpl::g_backendTextureObjects.Find(texture.get()); if (!backendTextureSlot || !*backendTextureSlot) { return; @@ -11705,7 +11407,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } }; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (fb, CONTRACT-P5E.md §5.4): THE REVERSE INDEX REPLACES THE WALK. id's note // above names this package as the one that does it, and the reason is the line it // points at: StateForHandle handed the server a frontend FramebufferObject per live @@ -11779,7 +11480,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } return; } -#endif // Already inside #if MOBILEGL_PIPE_PUSH, so no second guard here: the arm choice // below is the RUNTIME one. if (EsprytSlotTablesEnabled()) { @@ -12074,7 +11774,6 @@ namespace MobileGL::MG_Backend::DirectGLES { g_GLESFuncs.glBindTexture(dstTarget, cachedBound ? cachedBound->GetBackendTextureId() : 0); } -#if MOBILEGL_BUILD_RECORD_ARM // WHICH LAYERS A VIEW'S MIP CHAIN MAY WRITE. A generation through a view has two coordinate // systems in it - the view's own level/layer window (the sampler view CSO) and its storage // owner's - and the native arm below carries only part of the first one: BASE_LEVEL and @@ -12191,7 +11890,6 @@ namespace MobileGL::MG_Backend::DirectGLES { static_cast(dstSize.x()), static_cast(dstSize.y()), filter); } } -#endif static void GenerateDepthTexture2DMipmap( const SharedPtr& texture, @@ -12350,7 +12048,6 @@ namespace MobileGL::MG_Backend::DirectGLES { Uint activeTextureUnit = MG_Pipe::gPipeInputs.GetActiveTextureUnit(); TextureImpl::BackendTextureObject* dstBackendTexture = nullptr; TextureInternalFormat mgInternalFormat{}; -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.4): with an active transport the destination resolves from // the handle the copy_framebuffer_to_texture record carried (MGPCopyFromFramebuffer:: // Dst, the verb stash) and its format is the applier descriptor's - the client's @@ -12375,7 +12072,6 @@ namespace MobileGL::MG_Backend::DirectGLES { dstBackendTexture = backendTexture.get(); mgInternalFormat = static_cast(dstRecord->Desc.InternalFormat); } else -#endif { const auto& textureObject = MG_Pipe::gPipeInputs.GetTextureUnitObject((Int)activeTextureUnit) .GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target)) @@ -12476,7 +12172,6 @@ namespace MobileGL::MG_Backend::DirectGLES { BindCurrentFBO(FramebufferTarget::Read); auto activeTextureUnit = MG_Pipe::gPipeInputs.GetActiveTextureUnit(); TextureImpl::BackendTextureObject* dstBackendTexture = nullptr; -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.4): see CopyTexImage2D - the record's Dst handle, never the // client's unit binding slot or the client allocator (T2/T4). if (MG_Config::DataArmIsRecord()) { @@ -12493,7 +12188,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } dstBackendTexture = backendTexture.get(); } else -#endif { const auto& textureObject = MG_Pipe::gPipeInputs.GetTextureUnitObject(activeTextureUnit) .GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target)) @@ -12632,7 +12326,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return true; } -#if MOBILEGL_BUILD_RECORD_ARM // P8-B2: RGB16F / RGB32F MIP GENERATION ON THE SERVER, FROM THE SERVER'S OWN LEVEL. // // ES generates a chain only for a colour-renderable, filterable format, and whether the @@ -12896,7 +12589,6 @@ namespace MobileGL::MG_Backend::DirectGLES { GenerateThreeChannelFloatMipmapOnServer(mipRes, record, backendTexture, driverWrittenBefore, "the driver refused glGenerateMipmap"); } -#endif void PatchParameteri(GLenum pname, GLint value) { if (g_GLESFuncs.glPatchParameteri == nullptr) return; @@ -12907,7 +12599,6 @@ namespace MobileGL::MG_Backend::DirectGLES { #if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG && MOBILEGL_ENABLE_SCOPE_MARKER DebugImpl::OpenGLScopeMarker marker(__func__); #endif -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2), CONTRACT-P5E §5.2 / ruling 14 (ID-92's neighbour): GENERATE_MIPMAP RESOLVES // ITS TEXTURE FROM VerbMipRes, NEVER FROM THE ACTIVE UNIT. // @@ -12940,7 +12631,6 @@ namespace MobileGL::MG_Backend::DirectGLES { GenerateMipmapByRecord(target, mipRes, *record, backendTexture, driverWrittenBefore); return; } -#endif auto unitIndex = MG_Pipe::gPipeInputs.GetActiveTextureUnit(); auto& unit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unitIndex); auto& slot = unit.GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target)); @@ -13096,7 +12786,6 @@ namespace MobileGL::MG_Backend::DirectGLES { static Bool MakeGLESCopyImageEndpoint(const CopyImageEndpoint& endpoint, GLenum appTarget, GLint x, GLint y, GLint z, GLESCopyImageEndpoint& out) { if (endpoint.IsRenderbuffer()) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { if (!PipeRenderbufferRecordForHandle(endpoint.RenderbufferHandle)) return false; auto* slot = RenderbufferImpl::g_backendRenderbufferObjects.GetOrCreateByHandle(endpoint.RenderbufferHandle); @@ -13105,7 +12794,6 @@ namespace MobileGL::MG_Backend::DirectGLES { out.renderbuffer = *slot; out.renderbuffer->SyncToBackendByHandle(endpoint.RenderbufferHandle); } else -#endif out.renderbuffer = SyncRenderbufferObjectToBackend(endpoint.Renderbuffer); if (!out.renderbuffer) return false; out.target = GL_RENDERBUFFER; @@ -13126,11 +12814,9 @@ namespace MobileGL::MG_Backend::DirectGLES { // An endpoint that named nothing is the frontend validator's INVALID_VALUE and never // reaches here - but the assertion that says so is compiled out of a release build, and // SyncTextureObjectToBackend would register a null state object. -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { out.texture = TextureImpl::SyncTextureToBackendByHandle(endpoint.TextureHandle); } else -#endif { if (!endpoint.Texture) return false; out.texture = TextureImpl::SyncTextureObjectToBackend(endpoint.Texture); @@ -13152,7 +12838,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } static TextureInternalFormat GetCopyImageEndpointFormat(const CopyImageEndpoint& endpoint) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const auto* record = endpoint.IsRenderbuffer() ? PipeRenderbufferRecordForHandle(endpoint.RenderbufferHandle) @@ -13160,7 +12845,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return record ? static_cast(record->Desc.InternalFormat) : TextureInternalFormat::Unknown; } -#endif if (endpoint.IsRenderbuffer()) return endpoint.Renderbuffer->GetInternalFormat(); return endpoint.Texture ? endpoint.Texture->GetFormat() : TextureInternalFormat::Unknown; } @@ -13198,7 +12882,6 @@ namespace MobileGL::MG_Backend::DirectGLES { auto* srcMipmap = MG_State::GLState::AsMipmapTexture(srcEndpoint.Texture.get()); auto* dstMipmap = MG_State::GLState::AsMipmapTexture(dstEndpoint.Texture.get()); if (!srcMipmap || !dstMipmap) return; -#if MOBILEGL_BUILD_RECORD_ARM // UNDER A REAL TRANSPORT THE SERVER HAS NO FRONTEND SHADOW TO MIRROR INTO (P5b i1, ruling // §6.7), and P8-E settled where the move lives instead - not on the client (ROADMAP P8's // original row) but in the server's staged store: CopyImageSubData's handle arm makes the @@ -13213,7 +12896,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // integration-gpu lanes under MOBILEGL_TRANSPORT=monolith, where this mirror is on an // ordinary correct path and must still run. if (MG_Config::DataArmIsRecord()) return; -#endif // P4a (D-M) named this site `copy-image-shadow-mirror` with MGPipeUnmigratedEmulation. // P8-SE removed the call: the return above means no transport reaches it, and on a // monolith arm the call was a no-op (PipeCatalogueTest's list and the lint @@ -13287,7 +12969,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (!dstEndpoint.IsRenderbuffer() && dstEndpoint.Texture) { TextureImpl::NoteDriverSideTextureWrite(dstEndpoint.Texture); } -#if MOBILEGL_BUILD_RECORD_ARM // The handle arm's endpoint names its texture by handle, and the server has no frontend // object to note. The staged store's half of the note waits for the copy (P8-E, below). const Bool handleArmDestination = @@ -13295,13 +12976,11 @@ namespace MobileGL::MG_Backend::DirectGLES { if (handleArmDestination) { TextureImpl::NoteDriverSideTextureWriteByHandle(dstEndpoint.TextureHandle, /*storeFollowsTheWrite=*/true); } -#endif if (!MakeGLESCopyImageEndpoint(srcEndpoint, srcTarget, srcX, srcY, srcZ, src) || !MakeGLESCopyImageEndpoint(dstEndpoint, dstTarget, dstX, dstY, dstZ, dst)) { MGLOG_E_ONCE("%s: source or destination image failed to sync; declining the copy", __func__); return; } -#if MOBILEGL_BUILD_RECORD_ARM // P8-E (notes/p8/E.md): THE SERVER'S STAGED STORE FOLLOWS THE COPY. Both endpoints are synced, // so every byte the store holds for them is on the driver, and the copy below is a raw // texel-block move - the store makes the same move, which keeps the destination level @@ -13320,7 +12999,6 @@ namespace MobileGL::MG_Backend::DirectGLES { IntVec3{srcWidth, srcHeight, srcDepth}); if (!followed) TextureImpl::NoteDriverSideTextureWriteByHandle(dstEndpoint.TextureHandle); } -#endif // Verbatim: GL already spells a 1D array's extent the way the ES 2D array it maps onto // wants it (height 1, layers on depth) - see MakeGLESCopyImageEndpoint. @@ -13394,12 +13072,10 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_Util::ConvertGLEnumToString(dst.target).c_str(), MG_Util::ConvertGLEnumToString(dstTarget).c_str()); MOBILEGL_ASSERT(false, "glCopyImageSubData failed after frontend validation accepted the request."); -#if MOBILEGL_BUILD_RECORD_ARM // P8-E: the store already made the move the driver just refused. if (MG_Config::DataArmIsRecord() && handleArmDestination) { TextureImpl::NoteDriverSideTextureWriteByHandle(dstEndpoint.TextureHandle); } -#endif return; } // The copy landed on the GPU. For a destination whose readback cannot be bit-exact the @@ -13418,7 +13094,6 @@ namespace MobileGL::MG_Backend::DirectGLES { (void)layer; (void)access; (void)format; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (fb): see NoteImageUnitBoundWithoutReadingTheFrontend. Under a transport this // entry point records the high-water mark and lets the next validate point's sweep do // the bind from the record; reading the frontend image binding here is the @@ -13428,7 +13103,6 @@ namespace MobileGL::MG_Backend::DirectGLES { TextureImpl::NoteImageUnitBoundWithoutReadingTheFrontend(unit, texture != 0); return; } -#endif (void)texture; TextureImpl::SyncImageTextureBinding(unit); } @@ -13470,7 +13144,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // effect by the block's next use. void ShaderStorageBlockBinding(GLuint program, const GLchar* storageBlockName, GLuint storageBlockBinding) { if (!storageBlockName) return; -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const auto handle = MG_Pipe::MGPipeApplier().VerbStorageBlockProgram; auto* slot = PrgramImpl::g_backendProgramObjects.FindByHandle(handle); @@ -13480,16 +13153,13 @@ namespace MobileGL::MG_Backend::DirectGLES { } return; } -#endif if (!MG_Pipe::gPipeInputs.ValidateProgramName(program)) return; auto& programObject = MG_Pipe::gPipeInputs.GetProgramObject(program); if (!programObject) return; -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named debt inside the // scope - P3b/P4b rekeys the registry onto handles. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif auto* backendProgramSlot = PrgramImpl::g_backendProgramObjects.Find(programObject.get()); if (!backendProgramSlot || !*backendProgramSlot) return; auto& backendObj = *backendProgramSlot; @@ -13691,10 +13361,8 @@ namespace MobileGL::MG_Backend::DirectGLES { const SizeT rowBytes = static_cast(width) * dstPixelBytes; const SizeT packedSize = dstOffset + static_cast(height - 1) * dstRowStride + rowBytes; const auto& pixelPackBufferObject = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? SplitReadbackPackBuffer() : -#endif MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject(); const SizeT pboOffset = reinterpret_cast(pixels); if (pixelPackBufferObject && pboOffset + packedSize > pixelPackBufferObject->GetSize()) { @@ -14712,10 +14380,8 @@ namespace MobileGL::MG_Backend::DirectGLES { return true; } const auto& pixelPackBufferObject = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? SplitReadbackPackBuffer() : -#endif MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject(); if (!pixelPackBufferObject && pixels == nullptr) { return true; @@ -14946,7 +14612,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return true; } const void* shadow = textureMipmapObject->MapMipmapData(uploadTarget, level); -#if MOBILEGL_BUILD_RECORD_ARM // P4a (D-M) SAID "a split server holds no shadow to convert" AND ABORTED. That is the // premise this row of P3b/P4b re-examined, and it is wrong in the only case that can // get here: the level storage this converts IS the server's own, fed by the staged @@ -14980,13 +14645,10 @@ namespace MobileGL::MG_Backend::DirectGLES { return false; } } else -#endif MG_Pipe::MGPipeUnmigratedEmulation("get-tex-image-shadow"); const auto& pixelPackBufferObject = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? SplitReadbackPackBuffer() : -#endif MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject(); if (!pixelPackBufferObject && pixels == nullptr) { return true; @@ -15306,10 +14968,8 @@ namespace MobileGL::MG_Backend::DirectGLES { // (the driver-level binding used to stay on the user PBO after this call, // capturing subsequent client-memory readbacks into it). auto& pixelPackBufferObject = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? SplitReadbackPackBuffer() : -#endif MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject(); Bool usePBO = false; GLuint packBufferId = 0; @@ -15430,11 +15090,9 @@ namespace MobileGL::MG_Backend::DirectGLES { MGLOG_D("GetTexImage: bound texture object = %p (name=%u)", textureObject.get(), textureObject ? textureObject->GetExternalIndex() : 0); -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named debt inside the // scope - P3b/P4b rekeys the registry onto handles. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif auto* backendTextureSlot = TextureImpl::g_backendTextureObjects.Find(textureObject.get()); if (!backendTextureSlot || !*backendTextureSlot) { @@ -15753,10 +15411,8 @@ namespace MobileGL::MG_Backend::DirectGLES { // Handle PBO. The pack binding is scoped: it returns to the resting 0 state // on every exit path, so a later readback can never land in a stale PBO. auto& pixelPackBufferObject = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? SplitReadbackPackBuffer() : -#endif MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject(); Bool usePBO = false; GLuint packBufferId = 0; @@ -16605,7 +16261,6 @@ namespace MobileGL::MG_Backend::DirectGLES { break; } } -#if MOBILEGL_BUILD_RECORD_ARM // P14: AND OTHERWISE ANY LIVE NATIVE CONTEXT IN THE PROCESS. The backend keeps buffers, // textures and syncs of its own in process-wide state (the UBO/unpack/upload rings, the // buffer pool, scratch textures, frame fences) and every session's apply thread uses @@ -16621,7 +16276,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } } } -#endif // Negotiate the highest ES 3.x context. Version-strict EGL implementations // (ANGLE) return exactly the requested minor, and a bare CLIENT_VERSION 3 @@ -17331,7 +16985,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return true; } -#if MOBILEGL_BUILD_RECORD_ARM // P14: THE BACKEND'S TURN MOVED TO ANOTHER APPLY THREAD (ServerLoop's BackendTurn). Each // session's apply thread keeps its own native context current, but the backend's owner // thread and every binding shadow are process-wide and still describe the context of the @@ -17345,7 +16998,6 @@ namespace MobileGL::MG_Backend::DirectGLES { g_backendContextOwnerThread.store(std::this_thread::get_id(), std::memory_order_release); InvalidateNativeBindingShadows(); } -#endif Bool ReleaseCurrent() { if (!g_EGLFuncs.eglMakeCurrent || g_Display == EGL_NO_DISPLAY) { diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.h b/MobileGL/MG_Backend/DirectGLES/DirectGLES.h index a15c42c7..7b82ee9c 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.h +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.h @@ -30,7 +30,6 @@ namespace MobileGL::MG_Backend::DirectGLES { Bool ReadTextureLevelTight(GLuint texture, TextureTarget target, TextureUploadTarget uploadTarget, TextureInternalFormat logicalFormat, GLint level, const IntVec3& logicalExtent, Bool sourceUsesImageCarrier, GLenum format, GLenum type, Vector& bytes); -#if MOBILEGL_BUILD_RECORD_ARM Bool ReadTextureImageWire(const MG_Pipe::MGPReadbackInfo& info, Vector& bytes); // Whether the NATIVE texture currently holds `level` of `uploadTarget` at `logicalExtent` // (glGetTexLevelParameteriv). False for a level the driver never allocated - one defined after @@ -38,7 +37,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // refuses answers true, keeping the caller on its readback path. Bool NativeTextureLevelHasExtent(GLuint texture, TextureTarget target, TextureUploadTarget uploadTarget, GLint level, const IntVec3& logicalExtent); -#endif void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value); void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value); @@ -432,12 +430,10 @@ namespace MobileGL::MG_Backend::DirectGLES { // native context already current on this thread IS that one - so the single-context world pays // nothing for it. Called from the bind_context path on the apply thread. Bool MakeNativeContextCurrentForBoundToken(); -#if MOBILEGL_BUILD_RECORD_ARM // P14: the server's backend turn moved to the calling apply thread (ServerLoop.cpp's // BackendTurnLock). Takes the backend's GL ownership for this thread and drops every // binding shadow, which still describes the previous holder's native context. void OnBackendTurnHandoff(); -#endif // How many native contexts this process holds, and how many of them belong to one session. The // test observables for "a second context did not tear the first one down". Uint64 NativeContextCount(); diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index b68e1b3d..dbc7984d 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -18,12 +18,10 @@ // needs only the name - the deleter is captured where the archive is constructed - but the // program build reads through it, so the one translation unit that does needs the whole type. #include -#if MOBILEGL_BUILD_RECORD_ARM // R-11's server-owned staging copy. Header-only and package v1's; see its own header block for // why GLESBufferResource does not simply gain a member. #include #include -#endif #if MOBILEGL_BUILD_DISAGGREGATED #include // P5c (ct): object_death's producer (CONTRACT-P5C.md §5.2) - the death notice's split arm @@ -1256,7 +1254,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return StorageMatchesSize(resource, bufferObject.GetSize()); } -#if MOBILEGL_BUILD_RECORD_ARM // ------------------------------------------------------------------------------- // R-11 - THE SERVER'S OWN COPY OF THE STAGED BYTES. Package v1. // @@ -1304,7 +1301,6 @@ namespace MobileGL::MG_Backend::DirectGLES { ServerStaged().RequireCoverage(&resource, hostBase, start, end, site); } } -#endif // MOBILEGL_BUILD_RECORD_ARM #if MOBILEGL_BUILD_DISAGGREGATED // ------------------------------------------------------------------------------- @@ -1385,7 +1381,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // The four hostBytes sites read the same in both builds. The non-split expansion is the // ORIGINAL EXPRESSION, character for character - `raw - offset` - so a push or verify build // compiles exactly what it compiled before R-11 and the split arm is the only new behaviour. -#if MOBILEGL_BUILD_RECORD_ARM #define MGL_SERVER_STAGED_ADOPT(res, width, bytes, offset, size) \ ServerStaged().Adopt(&(res), (width), (bytes), (offset), (size)) #define MGL_SERVER_STAGED_DROP(res) ServerStaged().Drop(&(res)) @@ -1394,14 +1389,6 @@ namespace MobileGL::MG_Backend::DirectGLES { ServerStaged().RequireCoverage(&(res), (base), (start), (end), (site)) #define MGL_SERVER_STAGED_REQUIRE_PENDING(res, base, frontendSize, site) \ RequireStagedCoverageForPendingRanges((res), (base), (frontendSize), (site)) -#else -#define MGL_SERVER_STAGED_ADOPT(res, width, bytes, offset, size) \ - (static_cast(bytes) - (offset)) -#define MGL_SERVER_STAGED_DROP(res) ((void)0) -#define MGL_SERVER_STAGED_DROP_ALL() ((void)0) -#define MGL_SERVER_STAGED_REQUIRE(res, base, start, end, site) ((void)0) -#define MGL_SERVER_STAGED_REQUIRE_PENDING(res, base, frontendSize, site) ((void)0) -#endif // The host bytes a range upload/flush reads. On the legacy arm the frontend object's // shadow; on the handle arm the base the last content-carrying call handed over. @@ -1410,9 +1397,7 @@ namespace MobileGL::MG_Backend::DirectGLES { ZoneScopedC(TRACY_ZONECOLOR_BACKEND); #endif if (start >= end || hostBase == nullptr) return; -#if MOBILEGL_BUILD_RECORD_ARM MGL_SERVER_STAGED_REQUIRE(resource, hostBase, start, end, "upload_range"); -#endif BindBufferId(TempBufferTarget, resource.id); g_GLESFuncs.glBufferSubData(TempBufferTarget, (GLintptr)start, (GLsizeiptr)(end - start), hostBase + start); @@ -1987,9 +1972,7 @@ namespace MobileGL::MG_Backend::DirectGLES { auto* glesResource = static_cast(resource.get()); if (glesResource->contextGeneration != g_bufferContextGeneration) { glesResource->id = 0; // id belonged to a destroyed context -#if MOBILEGL_BUILD_RECORD_ARM RetireT0Import(*glesResource); // P11 B2: its GL store died with that context -#endif return; } if (CanTouchGLNow()) { @@ -2005,10 +1988,8 @@ namespace MobileGL::MG_Backend::DirectGLES { g_GLESFuncs.glDeleteBuffers(1, &glesResource->id); glesResource->id = 0; } -#if MOBILEGL_BUILD_RECORD_ARM // P11 B2: a T0 store's AHardwareBuffer goes only after a fence behind the delete. RetireT0Import(*glesResource); -#endif return; } const std::lock_guard lock(g_deferredBufferReleasesMutex); @@ -2112,7 +2093,6 @@ namespace MobileGL::MG_Backend::DirectGLES { void Ops_H_Respecify(MG_Pipe::MGPipeHandle res, const MG_Pipe::MGPResourceDesc& desc, const void* initialBytes) { auto* resource = FindBufferResourceForHandle(res); -#if MOBILEGL_BUILD_RECORD_ARM // P13 W4a (§1.4): ON MONOLITH'S RECORD ARM THE TWIN IS MINTED HERE, not lazily at // the first draw. The record arm's readers have no frontend object to re-read a // base from, so the base this call carries - the client's shadow, for an orphaning @@ -2122,9 +2102,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (resource == nullptr && aliasesFrontend && initialBytes != nullptr) { resource = GetOrCreateBufferResourceForHandle(res); } -#else - constexpr Bool aliasesFrontend = false; -#endif if (resource != nullptr) { // A respecify's companion pointer IS the shadow base (offset 0) - and an // ORPHANING one (glBufferData with NULL) carries HasDefinedContent clear and @@ -2155,11 +2132,9 @@ namespace MobileGL::MG_Backend::DirectGLES { MGL_SERVER_STAGED_DROP(*resource); resource->hostBytes = nullptr; } -#if MOBILEGL_BUILD_RECORD_ARM // P8-C: whatever a shader wrote belonged to the store this call replaces. resource->serverGpuWritten = false; resource->contentSinceRespecify = false; -#endif } if (!resource) return; // lazy: the ensure path full-uploads on creation if (resource->immutableStorage) { @@ -2178,13 +2153,11 @@ namespace MobileGL::MG_Backend::DirectGLES { resource->id = 0; resource->immutableStorage = false; } -#if MOBILEGL_BUILD_RECORD_ARM // P11 B2: a respecified T0 store ends here on the server's side too. Its // AHardwareBuffer is released only after a fence behind the delete (or at once // when the store's context is already gone) - never under a frame in flight, // however the client's own release (at this respecify) raced it. RetireT0Import(*resource); -#endif resource->storageInitialized = false; resource->storageSize = 0; resource->pendingRespecify = true; @@ -2219,7 +2192,6 @@ namespace MobileGL::MG_Backend::DirectGLES { const SizeT offset = static_cast(MG_Pipe::MGPipeSubDataBufferOffset(record)); const SizeT size = static_cast(MG_Pipe::MGPipeSubDataBufferSize(record)); auto* resource = FindBufferResourceForHandle(res); -#if MOBILEGL_BUILD_RECORD_ARM // R-11 / ID-52 item 3: under an ACTIVE TRANSPORT this record's bytes are the ONLY // delivery of the buffer's content - the client sends no companion pointer and the // server has no MappedData to fall back on. But the twin is created LAZILY at the @@ -2233,9 +2205,7 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_Config::DataArmIsRecord()) { resource = GetOrCreateBufferResourceForHandle(res); } -#endif if (!resource) return; -#if MOBILEGL_BUILD_RECORD_ARM // P11 B2: A T0 STORE TAKES A SERVER-ORIGINATED WRITE GPU-ORDERED. Its pages are the // client's AHardwareBuffer, so there is no staged copy to refresh and the adopted // early return below ("the coherent map already has the bytes") is false for bytes @@ -2294,7 +2264,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (resource != nullptr) resource->serverGpuWritten = true; return; } -#endif // M-2: UNDER pendingMutex, because this line runs BEFORE the CanTouchGLNow() // test below - i.e. on the arm D-A2 deliberately keeps reachable off the render // thread - while every reader of hostBytes (Ops_H_Readback's drain, the @@ -2317,9 +2286,7 @@ namespace MobileGL::MG_Backend::DirectGLES { // ("these bytes, at this base") and the drain takes this mutex to lift them. resource->hostBytes = MGL_SERVER_STAGED_ADOPT(*resource, ResourceWidthOf(res), bytes, offset, size); -#if MOBILEGL_BUILD_RECORD_ARM if (size != 0) resource->contentSinceRespecify = true; -#endif } if (resource->pendingRespecify) return; // full re-upload pending anyway if (!CanTouchGLNow() || resource->id == 0 || @@ -2380,9 +2347,7 @@ namespace MobileGL::MG_Backend::DirectGLES { const std::lock_guard lock(resource->pendingMutex); resource->hostBytes = MGL_SERVER_STAGED_ADOPT(*resource, ResourceWidthOf(res), bytes, start, end - start); -#if MOBILEGL_BUILD_RECORD_ARM if (end > start) resource->contentSinceRespecify = true; -#endif } if (resource->pendingRespecify) return; if (!CanTouchGLNow() || resource->id == 0 || @@ -2413,14 +2378,12 @@ namespace MobileGL::MG_Backend::DirectGLES { #ifdef TRACY_ENABLE ZoneScopedC(TRACY_ZONECOLOR_BACKEND); #endif -#if MOBILEGL_BUILD_RECORD_ARM // The kill-switch arm's own Memcpy, and the one that passes // GL_MAP_INVALIDATE_RANGE_BIT - i.e. the one that tells the driver the old // bytes are dead. Bytes outside the staged coverage are exactly the ones // that claim is false for. MGL_SERVER_STAGED_REQUIRE(*resource, resource->hostBytes, start, end, "flush_range_invalidate_map"); -#endif BindBufferId(TempBufferTarget, resource->id); void* mappedData = g_GLESFuncs.glMapBufferRange( TempBufferTarget, (GLintptr)start, (GLsizeiptr)(end - start), @@ -2440,15 +2403,11 @@ namespace MobileGL::MG_Backend::DirectGLES { } void Ops_H_Readback(MG_Pipe::MGPipeHandle res, const MG_Pipe::MGPReadback& record) { -#if MOBILEGL_BUILD_RECORD_ARM // An empty capture may conservatively request a writeback before // any draw materialized this buffer. Resolve its staged resource // exactly as a GPU consumer would, then return the real bytes. auto* resource = MG_Config::DataArmIsRecord() ? EnsureBufferResourceForHandle(nullptr, res) : FindBufferResourceForHandle(res); -#else - auto* resource = FindBufferResourceForHandle(res); -#endif if (!resource || resource->id == 0 || !resource->storageInitialized) return; if (!CanTouchGLNow() || resource->contextGeneration != g_bufferContextGeneration) return; if (resource->persistentMapped) { @@ -2517,7 +2476,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // The shadow now matches the backend byte for byte; without this the next draw // would see a newer serial and re-upload the readback over it. resource->syncedChangeSerial = ResourceSerialOf(res); -#if MOBILEGL_BUILD_RECORD_ARM // P13 W4a: on monolith's record arm the base this twin reads IS the shadow the // writeback just filled, so a whole-store readback is also the refresh // SplitHostBytesForCpuRead would owe. (A copying store's copy is not the @@ -2525,7 +2483,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (MG_Config::RecordArmAliasesFrontend() && readOffset == 0 && size >= ResourceWidthOf(res)) { resource->serverGpuWritten = false; } -#endif } void Ops_H_Destroy(MG_Pipe::MGPipeHandle res) { @@ -3052,7 +3009,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } #endif // MOBILEGL_BUILD_DISAGGREGATED && __ANDROID__ -#if MOBILEGL_BUILD_RECORD_ARM // ---- P5c (tx): the TEXTURE half of the resource family, staged server-side -------- // // The buffer half's R-11 pattern (ServerStaged() above), for texture levels: the @@ -3110,7 +3066,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // disaggregation did not compile. The narrower fix (guarding the macro block too) is wrong: // that block also carries TextureDiagName and MGB_TEXTURE_RECORD_ARM_SELECTED, which the push // flavour does need. Caught by the `flavours` gate step; see ID-124. -#endif // MOBILEGL_BUILD_RECORD_ARM // The inverse of MG_Pipe::MGPipeResourceTargetForTextureTarget, for the sync's // target reads (ConvertTextureTargetToBackendGLEnum and MapToBackendTextureTarget // both want the frontend enum). @@ -3130,7 +3085,6 @@ namespace MobileGL::MG_Backend::DirectGLES { default: return TextureTarget::Unknown; } } -#if MOBILEGL_BUILD_RECORD_ARM void Ops_H_TextureSubData(MG_Pipe::MGPipeHandle res, const MG_Pipe::MGPSubData& record, const void* bytes, const MG_Pipe::MGPSubRegion* regions) { @@ -3232,7 +3186,6 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_Record::ServerStagedTexture().Drop( MG_Record::StagedTextureStore::KeyForHandle(res)); } -#endif // MOBILEGL_BUILD_RECORD_ARM const MG_Pipe::MGPipeResourceOps g_glesResourceOps = { .Create = Ops_H_Create, @@ -3244,7 +3197,6 @@ namespace MobileGL::MG_Backend::DirectGLES { .Destroy = Ops_H_DestroyTracked, .MapPersistent = Ops_H_MapPersistentTracked, .UnmapPersistent = Ops_H_UnmapPersistent, -#if MOBILEGL_BUILD_RECORD_ARM .TextureSubData = Ops_H_TextureSubData, .TextureRespecify = Ops_H_TextureRespecify, .TextureDestroy = Ops_H_TextureDestroy, @@ -3252,7 +3204,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // P11 B2 (T0). Android only: nowhere else is there an AHardwareBuffer to import. .ImportExternal = Ops_H_ImportExternalTracked, .SelfTestExternal = Ops_H_SelfTestExternal, -#endif #endif }; @@ -3512,7 +3463,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return twin ? twin->get() : nullptr; } -#if MOBILEGL_BUILD_RECORD_ARM void RequireStagedCoverage(GLESBufferResource& resource, const Uint8* hostBase, SizeT start, SizeT end, const char* site) { ServerStaged().RequireCoverage(&resource, hostBase, start, end, site); @@ -3678,7 +3628,6 @@ namespace MobileGL::MG_Backend::DirectGLES { const std::lock_guard lock(resource.pendingMutex); resource.hostBytes = MGL_SERVER_STAGED_ADOPT(resource, ResourceWidthOf(res), bytes, offset, size); } -#endif MG_Pipe::MGPipeHandle HandleOfBuffer(const MG_State::GLState::BufferObject* bufferObject) { if (bufferObject == nullptr) return MG_Pipe::kMGPipeNullHandle; @@ -3690,7 +3639,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // allocator probe on a miss - and remembers the answer, which the minting overload // was previously the only writer of. A null answer is deliberately never memoised // (see the comment at HandleOf). -#if MOBILEGL_BUILD_RECORD_ARM // P5c merge coordination (CONTRACT-P5C §3.1's named exemption): every caller of // this function is a site whose handle-carrying records (set_shader_buffers / // set_stream_output_targets) the client does not emit until sb, so the probe @@ -3706,7 +3654,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // IsBufferDrawCleanByHandle / MarkBufferGpuWrittenByHandle, which is the last // caller set this function has. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif return g_backendBufferResources.HandleOf(bufferObject); } @@ -3816,7 +3763,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // generation, and a shadow that outlived its twin would be looked up by a RECYCLED // address on the next allocation - which is the quietest possible wrong answer. MGL_SERVER_STAGED_DROP_ALL(); -#if MOBILEGL_BUILD_RECORD_ARM // tx's texture shadows die for the same reason, keyed by handle rather than address // but with the same recycled-identity failure mode: a new context's allocator may // hand out a {slot, gen} the old one's store still answers for. @@ -3827,7 +3773,6 @@ namespace MobileGL::MG_Backend::DirectGLES { #if MOBILEGL_BUILD_DISAGGREGATED ProcessDeferredT0Retires(); SweepT0Retired(/*contextGone=*/true); -#endif #endif } @@ -3929,11 +3874,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } const auto* record = ResourceRecordOf(res); if (record == nullptr) return false; -#if MOBILEGL_PIPE_VERIFY && !MOBILEGL_BUILD_RECORD_ARM - MOBILEGL_ASSERT(!record->HasLiveHostWrites, - "MGPipeResourceRecord::HasLiveHostWrites is set, but this build has no producer " - "for it - P5 b1's producer is MGPSubData::HasLiveHostWrites and is split-only"); -#endif if (record->HasLiveHostWrites) return false; // THE LAST FRONTEND READ IN THIS FUNCTION, AND P5 b1 RETIRES IT - under split // only, because that is the only build where it is both wrong and replaceable. @@ -4012,7 +3952,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // fallback for the drains that have NO object (the readback flush), and it is // nulled at both of those events. const auto liveHostBase = [&resource, &bufferObject]() -> const Uint8* { -#if MOBILEGL_BUILD_RECORD_ARM // M-2 / codex 3 / ID-52 item 3: under an ACTIVE TRANSPORT the server's staged // copy (resource->hostBytes, filled by MGL_SERVER_STAGED_ADOPT in Ops_H_SubData / // Ops_H_FlushRange) is the ONLY authoritative base. Preferring the frontend @@ -4024,7 +3963,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (MG_Config::DataArmIsRecord()) { return resource->hostBytes; } -#endif if (bufferObject) return bufferObject->MappedData(); return resource->hostBytes; }; @@ -4041,7 +3979,6 @@ namespace MobileGL::MG_Backend::DirectGLES { resource->persistentMapped = false; resource->persistentPtr = nullptr; resource->immutableStorage = false; -#if MOBILEGL_BUILD_RECORD_ARM // m-5 / codex 5: OnBackendContextDestroyed ran MGL_SERVER_STAGED_DROP_ALL(), which // frees every server shadow but does NOT null the hostBytes that name them - so a // twin that SURVIVES a context loss still carries a base into the freed allocation. @@ -4084,7 +4021,6 @@ namespace MobileGL::MG_Backend::DirectGLES { RetireT0Import(*resource); } } -#endif #endif } @@ -4129,12 +4065,10 @@ namespace MobileGL::MG_Backend::DirectGLES { // application ORPHANED the gap is its own undefined content and the upload is // legal (ResourceContentIsDeclared, above). RequireCoverage is a no-op for the // legacy arm's MappedData() and for a non-copying store. -#if MOBILEGL_BUILD_RECORD_ARM if (ResourceContentIsDeclared(res)) { MGL_SERVER_STAGED_REQUIRE(*resource, liveHostBase(), 0, poolSize, "pool_reuse_whole_store"); } -#endif g_GLESFuncs.glBufferSubData(TempBufferTarget, 0, (GLsizeiptr)poolSize, liveHostBase()); if (MG_Util::PipeStats::Enabled()) { MG_Util::PipeStats::AddBytes(MG_Util::PipeStats::ByteClass::StageBuffer, @@ -4161,7 +4095,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // D-N keeps this call here for P3a. It can queue ranges and move the record, so // everything below is read AFTER it. -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.8): under an active transport the frontend accessor is a // layer-1 surface ("buffer-legacy-arm") and the client's own pre-verb // persistent-map push is the only producer; the call is skipped outright. Under @@ -4169,9 +4102,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (bufferObject && !MG_Config::DataArmIsRecord()) { bufferObject->SyncPersistentMappedRange(); } -#else - if (bufferObject) bufferObject->SyncPersistentMappedRange(); -#endif const auto* record = ResourceRecordOf(res); const SizeT size = record != nullptr ? static_cast(record->Desc.Width) : 0; @@ -4214,13 +4144,11 @@ namespace MobileGL::MG_Backend::DirectGLES { // the last orphan". With no coverage and a clear bit the store is undefined by the // application's own declaration and the upload stays a pure NULL reallocation. const Bool shadowHasContent = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? (record->Desc.HasDefinedContent != 0 || (ServerStaged().CopiesIntoServerStorage() ? ServerStaged().CoveredRunCount(resource) != 0 : resource->contentSinceRespecify)) : -#endif (bufferObject ? bufferObject->HasDefinedContent() : (record->Desc.HasDefinedContent != 0)); const void* initialData = shadowHasContent ? hostBase : nullptr; // M-3 / codex 4: a RespecifyStorageWith(..., initialData != nullptr) is a WHOLE-STORE @@ -4235,14 +4163,10 @@ namespace MobileGL::MG_Backend::DirectGLES { // the bytes it did not write are undefined by its own glBufferData(NULL) - the rule at // ResourceContentIsDeclared. Round 2 refused that idiom and aborted six joint entries. const auto requireWholeStoreCoverage = [&]() { -#if MOBILEGL_BUILD_RECORD_ARM if (initialData != nullptr && record->Desc.HasDefinedContent != 0) { MGL_SERVER_STAGED_REQUIRE(*resource, static_cast(initialData), 0, size, "respecify_whole_store"); } -#else - (void)initialData; -#endif }; if (resource->pendingRespecify || !resource->storageInitialized || resource->storageSize != size) { @@ -4942,7 +4866,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return true; } -#if MOBILEGL_BUILD_RECORD_ARM // THE SAFETY ARGUMENT P4a MADE AND NEVER RAN (P3b/P4b espryt D1 slice 5). // // "Running the legacy arm" is a real answer in a monolith and a POSTPONED CRASH under a @@ -4974,7 +4897,6 @@ namespace MobileGL::MG_Backend::DirectGLES { bit, detail); BufferImpl::StopOnArmlessPipeSubsystem(what); } -#endif // The release-build VOICE for StateBackendObjectRegistry::GetOrCreateByHandle's two // silent refusals, shared by the kinds P4a re-keys so the wording cannot drift between @@ -5096,7 +5018,6 @@ namespace MobileGL::MG_Backend::DirectGLES { "MOBILEGL_PIPE_PUSH leaves kMGPipeSubsystemFramebuffer (bit 9) clear (or refuses " "it) and MOBILEGL_PIPE_LEGACY_MEMOS=0 disables the pre-handle g_fboSynced* arm"); } -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord() && verdict != BufferImpl::PipeSubsystemArmVerdict::Handles) { StopOnTransportWithoutRecordArm( @@ -5107,7 +5028,6 @@ namespace MobileGL::MG_Backend::DirectGLES { "to reach it would raise Fatal{UnmigratedPipeInput, " "\"GetFramebufferBindingSlot@\"} mid-frame instead"); } -#endif const Bool enabled = verdict == BufferImpl::PipeSubsystemArmVerdict::Handles; MGLOG_D("MGPipe: Espryt framebuffer family runs the %s arm", enabled ? "handle" : "legacy"); return enabled; @@ -5141,7 +5061,6 @@ namespace MobileGL::MG_Backend::DirectGLES { "refuses it) and MOBILEGL_PIPE_LEGACY_MEMOS=0 disables the pre-handle texture " "cheap-gate trio"); } -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord() && verdict != BufferImpl::PipeSubsystemArmVerdict::Handles) { StopOnTransportWithoutRecordArm( @@ -5150,7 +5069,6 @@ namespace MobileGL::MG_Backend::DirectGLES { "objects and their binding slots, which under a transport are client memory (rule " "E) rather than anything this side owns"); } -#endif const Bool enabled = verdict == BufferImpl::PipeSubsystemArmVerdict::Handles; MGLOG_D("MGPipe: Espryt texture-resource family runs the %s arm", enabled ? "handle" : "legacy"); return enabled; @@ -5177,7 +5095,6 @@ namespace MobileGL::MG_Backend::DirectGLES { "it) and MOBILEGL_PIPE_LEGACY_MEMOS=0 disables UnitSamplerLookupMemo's WeakPtr " "arm and SamplerPassMemo's raw-pointer rows"); } -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord() && verdict != BufferImpl::PipeSubsystemArmVerdict::Handles) { StopOnTransportWithoutRecordArm( @@ -5187,7 +5104,6 @@ namespace MobileGL::MG_Backend::DirectGLES { "this side to key on - a WeakPtr that can never lock is not a slower arm, it is a " "unit that samples through whatever it last held"); } -#endif const Bool enabled = verdict == BufferImpl::PipeSubsystemArmVerdict::Handles; MGLOG_D("MGPipe: Espryt sampler family runs the %s arm", enabled ? "handle" : "legacy"); return enabled; @@ -5206,7 +5122,6 @@ namespace MobileGL::MG_Backend::DirectGLES { "MOBILEGL_PIPE_PUSH leaves kMGPipeSubsystemPrograms (bit 12) clear and " "MOBILEGL_PIPE_LEGACY_MEMOS=0 disables g_programTwinLookupMemo"); } -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord() && verdict != BufferImpl::PipeSubsystemArmVerdict::Handles) { StopOnTransportWithoutRecordArm( @@ -5216,7 +5131,6 @@ namespace MobileGL::MG_Backend::DirectGLES { "ShaderCso handle with its archive beside the record and there is no frontend " "program here at all"); } -#endif const Bool enabled = verdict == BufferImpl::PipeSubsystemArmVerdict::Handles; MGLOG_D("MGPipe: Espryt program family runs the %s arm", enabled ? "handle" : "legacy"); return enabled; @@ -5487,11 +5401,9 @@ namespace MobileGL::MG_Backend::DirectGLES { // MGPipeSlots().FindByLifetimeId, which is a hash lookup. HandleOf answers // identically - the same allocator probe on a miss - and remembers the answer; a // null answer is deliberately never memoised (SlotTables.h, at HandleOf). -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named debt inside // the scope - P3b/P4b rekeys the sampler-view registry onto handles. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif return g_backendSamplerViews.HandleOf(textureObject); } } // namespace SamplerViewImpl @@ -6366,15 +6278,11 @@ namespace MobileGL::MG_Backend::DirectGLES { // recorded shadow base for such a resource read freed memory; hostBytes is nulled // at adoption for the same reason, so the fallback below is a null and a refusal // rather than a stale read. -#if MOBILEGL_BUILD_RECORD_ARM const Bool sourceGpuWritten = MG_Config::DataArmIsRecord() && resource->serverGpuWritten; if (sourceGpuWritten) { BufferImpl::SplitHostBytesForCpuRead(*resource, binding.Res, "fp64_vertex_narrowing"); } -#else - constexpr Bool sourceGpuWritten = false; -#endif const Uint8* const sourceBase = (resource->persistentMapped && resource->persistentPtr != nullptr) ? static_cast(resource->persistentPtr) @@ -6553,7 +6461,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (m_imageBindableStorageRequired) { return; } -#if MOBILEGL_BUILD_RECORD_ARM // P13 W4b (defect h): monolith's record arm takes the body too; its old arm only // cleared m_isInitialized and replayed the frontend shadow at the next sync. if (MG_Config::DataArmIsRecord()) { @@ -6704,10 +6611,6 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_Util::PipeStats::AddCalls(MG_Util::PipeStats::CallClass::TextureRemintPulls, 1); } } -#else - (void)res; - (void)record; -#endif // Every defined byte now belongs to the server and every required // replay is in its pending set. The existing upload path builds and // fills the immutable/widened carrier from those records. @@ -6948,11 +6851,9 @@ namespace MobileGL::MG_Backend::DirectGLES { const MG_Pipe::MGPipeHandle rearmRes = TextureResourceSubsystemEnabled() ? [&]() { -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed resolution, named // debt inside the scope - P3b/P4b rekeys the registry. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif return g_backendTextureObjects.HandleOf(stateTextureObject.get()); }() : MG_Pipe::kMGPipeNullHandle; @@ -7171,11 +7072,9 @@ namespace MobileGL::MG_Backend::DirectGLES { static inline GLint s_skipImages = 0; }; -#if MOBILEGL_BUILD_RECORD_ARM void ExerciseDefaultUnpackScopeForTesting() { const ScopedDefaultUnpackState scope; } -#endif // --- Unpack-ring staging (see BufferImpl::UnpackRingAvailable) --------------- // One rectangular (or whole-level) region of a level shadow, repacked TIGHTLY @@ -7859,12 +7758,8 @@ namespace MobileGL::MG_Backend::DirectGLES { // read). Sites that were previously correct only because every writer of a handle-note happens // to be transport-gated now say so themselves, so a future by-handle noter cannot quietly // re-open ID-107's hole somewhere else. -#if MOBILEGL_BUILD_RECORD_ARM #define MGB_TEXTURE_RECORD_ARM_SELECTED() \ (MG_Config::DataArmIsRecord() && TextureResourceSubsystemEnabled()) -#else -#define MGB_TEXTURE_RECORD_ARM_SELECTED() (false) -#endif // Returns true when the caller must decline (no handle noted: the caller's bug it always // was, named by the caller's own log line), false when the record arm can serve the call, @@ -8017,7 +7912,6 @@ namespace MobileGL::MG_Backend::DirectGLES { StampViewSyncKeys(stateTextureObject); } -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2): see the declaration for the split between what the record answers and what // the wire still cannot say about a view. void BackendTextureObject::SyncTextureViewToBackendByRecord( @@ -8102,7 +7996,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // The storage's, for the steady arm's reason above (P3b/P4b D3). m_syncedResourceSerial = storageSerial; } -#endif // P4a (D-D5), the dirty-ownership inversion, applied at the two places the upload loops // below actually ask: "does this (uploadTarget, level) owe an upload" and "it has been @@ -8126,7 +8019,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // pre-P4a expression exactly when MOBILEGL_PIPE_PUSH is off, so the pull build's // preprocessed text, and therefore its object code, is unchanged. Both are #undef'd // immediately after the function. -#if MOBILEGL_BUILD_RECORD_ARM // P5c (tx): THE READS THE FOUR UPLOAD ARMS MAKE, re-sourced. With an active transport the // apply thread may not name the client's TextureObjectMipmap at all (rule E), so on the // handle arm: @@ -8172,15 +8064,7 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_Record::StagedTextureStore::KeyForHandle(pushedRes), static_cast(tgt), \ static_cast(lvl), site) \ : (obj)->MapMipmapData(tgt, lvl)) -#else -#define MGB_TEXTURE_TARGET(obj) ((obj)->GetTarget()) -#define MGB_UPLOAD_TARGETS(obj) ((obj)->GetUploadTargets()) -#define MGB_LEVEL_TEXEL_SIZE(obj, tgt, lvl) ((obj)->GetMipmapTexelSize(tgt, lvl)) -#define MGB_LEVEL_BYTE_SIZE(obj, tgt, lvl) ((obj)->GetMipmapByteSize(tgt, lvl)) -#define MGB_LEVEL_TEXELS(obj, tgt, lvl, site) ((obj)->MapMipmapData(tgt, lvl)) -#endif -#if MOBILEGL_BUILD_RECORD_ARM // P5c (tx): the disaggregated pair adds ONE term and ONE clear to the P4a shapes - the // staged-texture store's GPU-dirty mark (T5: a level the GPU generated dirties the SERVER's // shadow, and the pending set cannot see it). The mark is never set on Espryt today - its @@ -8210,23 +8094,6 @@ namespace MobileGL::MG_Backend::DirectGLES { (obj)->MarkStorageDirty(tgt, lvl, false); \ } \ } while (0) -#else -#define MGB_LEVEL_NEEDS_UPLOAD(obj, tgt, lvl) \ - (pushedStorage != nullptr \ - ? FindPipeTextureUpload(*pushedStorage, static_cast(tgt), static_cast(lvl)) != nullptr \ - : (obj)->IsStorageDirty(tgt, lvl)) -// Re-resolves the record itself, so it is safe after any amount of driver work - and it -// invalidates any PendingUpload* taken earlier for THIS texture, which is why every such pointer -// is used and dropped inside one level's iteration. -#define MGB_LEVEL_UPLOAD_DONE(obj, tgt, lvl) \ - do { \ - if (pushedStorage != nullptr) { \ - ConsumePipeTextureUpload(pushedRes, static_cast(tgt), static_cast(lvl)); \ - } else { \ - (obj)->MarkStorageDirty(tgt, lvl, false); \ - } \ - } while (0) -#endif // THE STORAGE SHAPE, and on the handle arm it is the DESCRIPTOR's (C.3's d2: "the // m_prevTextureInfo probe re-keyed onto the resource record's Serial AND Desc"; review @@ -8480,7 +8347,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return; } } -#if MOBILEGL_BUILD_RECORD_ARM #if MOBILEGL_BUILD_DISAGGREGATED // SHARED IMAGES: ahead of the view test and of the staged-store and serial gates below, // none of which knows the texels belong to an image - the staged store holds none of @@ -8515,7 +8381,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (MG_Config::DataArmIsRecord() && pushedStorage != nullptr) { // Not a view: fall through to the storage body with the frontend test skipped. } else -#endif // A texture created by glTextureView owns no storage: the levels, the format and // every texel belong to the texture it views, and this name only has to be made to // ALIAS them. Everything below - storage allocation, respecification, per-level @@ -8563,14 +8428,12 @@ namespace MobileGL::MG_Backend::DirectGLES { pushedStorage->Desc.ImageBindableHint != 0 || (pushedStorage->Desc.BindMask & MG_Pipe::kMGPipeBindShaderImage) != 0; if (pushedWantsImageBindableStorage && !m_imageBindableStorageRequired) { -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2), ruling 1's arm: under a transport the re-dirty half is a NAMED // refusal at its entry (§5.2) instead of a walk of the client's level shadows; // the push-monolith build keeps the frontend transition exactly as it is. if (MG_Config::DataArmIsRecord()) { RequireImageBindableStorageByHandle(pushedRes, *pushedStorage); } else -#endif RequireImageBindableStorage(stateTextureObject); } @@ -8638,7 +8501,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // left the backend name with no levels whatsoever, so the level that WAS defined could // never be sampled or read back. Sync whenever some level holds an image; the per-level // loops below skip the degenerate ones individually. -#if MOBILEGL_BUILD_RECORD_ARM // P5c (gt, CONTRACT-P5C §6 layer 1): on the staged arm the same question is answered // out of the SERVER's staged-texture store, never out of the frontend object - the // store's Defined-ness (fed by the respecify hook and the sub-data adoption) IS "some @@ -8679,7 +8541,6 @@ namespace MobileGL::MG_Backend::DirectGLES { return; } } else -#endif if (!stateTextureObject->IsComplete() && !HasAnyDefinedMipmapLevel(stateTextureObject.get())) { MGLOG_D("Texture object with ID: %u has no defined image level, skipping sync.", stateTextureObject->GetExternalIndex()); @@ -9263,7 +9124,6 @@ namespace MobileGL::MG_Backend::DirectGLES { : nullptr; const auto dirtyRegion = [&]() -> MG_State::GLState::MipmapDirtyRegion { if (pendingUpload == nullptr) { -#if MOBILEGL_BUILD_RECORD_ARM // P5c (tx): a level this arm owes with NO pending upload behind it // was dirtied by the GPU (T5), and the dirty answer is the // server's own mark on the staged shadow - the whole level, @@ -9276,7 +9136,6 @@ namespace MobileGL::MG_Backend::DirectGLES { static_cast(uploadTarget), static_cast(level)); return MG_State::GLState::MipmapDirtyRegion{IntVec3{0, 0, 0}, gpuExtent}; } -#endif return textureMipmapObject->GetStorageDirtyRegion(uploadTarget, level); } // MGPBox is {origin, extent}; MipmapDirtyRegion is {lo, hi}. The @@ -9469,13 +9328,11 @@ namespace MobileGL::MG_Backend::DirectGLES { region.Z + static_cast(region.D)}}; } } else -#if MOBILEGL_BUILD_RECORD_ARM // tx: with an active transport the rect list is the record's (the // pendingUpload arm above) or nothing - the server's GPU-dirty mark // is whole-level and has no scatter refinement to hand out, and the // frontend's rect model is not this side's to read. if (!MGB_STAGED_TEXTURE_LIVE) -#endif dirtyRectCount = textureMipmapObject->GetStorageDirtyRects( uploadTarget, level, dirtyRects, MG_State::GLState::MipmapStorage::kMaxDirtyRects); @@ -9512,14 +9369,12 @@ namespace MobileGL::MG_Backend::DirectGLES { region.Z + static_cast(region.D)}}); } } else -#if MOBILEGL_BUILD_RECORD_ARM // With an active transport and no record behind the level, the // server's own whole-level GPU-dirty mark is the whole story (the // same reason the rect list above is not read here). if (MGB_STAGED_TEXTURE_LIVE) { dirtyFootprint.clear(); } else -#endif textureMipmapObject->GetStorageDirtyFootprint(uploadTarget, level, dirtyFootprint); // One box is the union box itself, which the branches below already // upload exactly (as the whole level when it is the whole level). @@ -10052,9 +9907,7 @@ namespace MobileGL::MG_Backend::DirectGLES { #undef MGB_LEVEL_TEXEL_SIZE #undef MGB_LEVEL_BYTE_SIZE #undef MGB_LEVEL_TEXELS -#if MOBILEGL_BUILD_RECORD_ARM #undef MGB_STAGED_TEXTURE_LIVE -#endif // P5e (tx2), CONTRACT-P5E §5.2: THIS TWIN'S OWN RECORD. On the by-handle arm the handle // is already known - the caller resolved the record before it resolved this twin and @@ -10066,11 +9919,9 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_Pipe::MGPipeHandle res = m_pushedSyncHandle; if (MG_Pipe::MGPipeHandleIsNull(res)) { if (!stateTextureObject) return nullptr; -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed resolution, named debt inside the // scope - the by-handle arm above is what retires it. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif res = g_backendTextureObjects.HandleOf(stateTextureObject.get()); } return PipeTextureRecordForHandle(res); @@ -10687,18 +10538,13 @@ namespace MobileGL::MG_Backend::DirectGLES { storage = record->Desc.ViewOf; } if (auto* twin = ResolveTextureTwin(storage)) twin->NoteDriverSideWrite(); -#if MOBILEGL_BUILD_RECORD_ARM // P8-E: the staged store stops standing for this texture's content (a no-op on a // monolith arm, where the store does not copy). if (!storeFollowsTheWrite && !MG_Pipe::MGPipeHandleIsNull(storage)) { MG_Record::ServerStagedTexture().MarkDriverWritten( MG_Record::StagedTextureStore::KeyForHandle(storage)); } -#else - (void)storeFollowsTheWrite; -#endif } -#if MOBILEGL_BUILD_RECORD_ARM Bool FollowCopyImageInStagedStore(MG_Pipe::MGPipeHandle source, Uint32 sourceLevel, const IntVec3& sourceOrigin, MG_Pipe::MGPipeHandle destination, Uint32 destinationLevel, const IntVec3& destinationOrigin, const IntVec3& size) { @@ -10737,7 +10583,6 @@ namespace MobileGL::MG_Backend::DirectGLES { destinationTarget, static_cast(destinationLevel), destinationOrigin, size); } -#endif } // namespace TextureImpl namespace FramebufferImpl { @@ -10900,11 +10745,9 @@ namespace MobileGL::MG_Backend::DirectGLES { if (attachmentObject.IsTexture()) { const auto& textureObject = attachmentObject.GetTexture(); SharedPtr backendTextureObject; -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution (and the mint on // a first attach), named debt inside the scope - P3b/P4b rekeys the registry. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif if (auto* backendTextureSlot = TextureImpl::g_backendTextureObjects.Find(textureObject.get())) { backendTextureObject = *backendTextureSlot; } else { @@ -10957,11 +10800,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } } else if (attachmentObject.IsRenderbuffer()) { const auto& renderbufferObject = attachmentObject.GetRenderbuffer(); -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution (and the mint on // a first attach), named debt inside the scope - P3b/P4b rekeys the registry. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif SharedPtr backendRenderbufferObject; if (auto* backendRenderbufferSlot = RenderbufferImpl::g_backendRenderbufferObjects.Find(renderbufferObject.get())) { @@ -11295,14 +11136,12 @@ namespace MobileGL::MG_Backend::DirectGLES { // push-monolith arm keeps the frontend sync it had at f6cfcbd3, token for token, // because tx2's record arm inside SyncMipmapsToBackend is itself selected by // `Transport != Monolith` and cannot answer here. -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { backendTextureObject->SyncMipmapsToBackendByHandle(surface.Res); // From here on every draw, clear and blit into this framebuffer can write the // texture behind the staged shadow's back (the frontend arm's note, by handle). TextureImpl::NoteDriverSideTextureWriteByHandle(surface.Res); } else -#endif { const SharedPtr monolithTexture = (monolithAttachment != nullptr && monolithAttachment->IsTexture()) @@ -11384,11 +11223,9 @@ namespace MobileGL::MG_Backend::DirectGLES { // GLContext (RecordError) and the by-handle form deliberately does not, because // under a transport there is no application on this side to report it to. On the // push-monolith arm there is, so the monolith arm keeps the object form. -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { backendRenderbufferObject->SyncToBackendByHandle(surface.Res); } else -#endif { const SharedPtr monolithRenderbuffer = (monolithAttachment != nullptr && monolithAttachment->IsRenderbuffer()) @@ -11436,12 +11273,10 @@ namespace MobileGL::MG_Backend::DirectGLES { // (the three-channel colour-renderable widening). GL answers such a read with 1.0, but // the storage holds whatever the draw wrote there, so the readback has to overwrite it. Bool IsAlphaWidenedFallbackReadAttachment() { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const auto* record = MG_Pipe::MGPipeApplier().ReadFramebuffer(); return record && IsAlphaWidenedColorSurface(record->ReadSurface); } -#endif const auto* attachmentObject = GetReadColorAttachment(); if (attachmentObject == nullptr) { return false; @@ -11450,13 +11285,11 @@ namespace MobileGL::MG_Backend::DirectGLES { } Bool IsFixedPointFallbackReadAttachment() { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const auto* record = MG_Pipe::MGPipeApplier().ReadFramebuffer(); return record && record->ReadSurface.Kind != MG_Pipe::kMGPipeSurfaceKindNone && IsSnormFormat(static_cast(record->ReadSurface.InternalFormat)); } -#endif const auto& readFBO = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject(); if (!readFBO) { @@ -11623,11 +11456,9 @@ namespace MobileGL::MG_Backend::DirectGLES { // P5c (hd): with an active transport the handle is the caller's // (m_pushedSyncHandle), never the client allocator's - see SyncToBackend. const MG_Pipe::MGPipeHandle fbo = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? m_pushedSyncHandle : -#endif g_backendFramebufferObjects.HandleOf(stateFBOObject.get()); // ID-19: the OBJECT's record, not "the record of whatever is bound to READ". A // framebuffer whose read buffer is being pushed need not be the read binding at @@ -11801,11 +11632,9 @@ namespace MobileGL::MG_Backend::DirectGLES { // is never probed (T2). A null there means a caller reached this arm without a // record, which the null-record refusal below names. const MG_Pipe::MGPipeHandle fbo = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? m_pushedSyncHandle : -#endif g_backendFramebufferObjects.HandleOf(stateFBOObject.get()); pushedRecord = PushedFramebufferRecord(fbo); if (pushedRecord == nullptr) { @@ -12083,11 +11912,9 @@ namespace MobileGL::MG_Backend::DirectGLES { // Verify that the backend object's name and parameters match the frontend attachment state if (attachmentObject.IsTexture()) { const auto& textureObject = attachmentObject.GetTexture(); -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named // debt inside the scope - P3b/P4b rekeys the registry. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif auto* backendTextureSlot = TextureImpl::g_backendTextureObjects.Find(textureObject.get()); MOBILEGL_ASSERT(backendTextureSlot != nullptr && *backendTextureSlot != nullptr, "No backend texture found while framebuffer reports texture attachment."); @@ -12104,11 +11931,9 @@ namespace MobileGL::MG_Backend::DirectGLES { "Attachment texture level mismatch between GLES and state object."); } else if (attachmentObject.IsRenderbuffer()) { const auto& renderbufferObject = attachmentObject.GetRenderbuffer(); -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named // debt inside the scope - P3b/P4b rekeys the registry. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif auto* backendRboSlot = RenderbufferImpl::g_backendRenderbufferObjects.Find(renderbufferObject.get()); MOBILEGL_ASSERT( @@ -12253,11 +12078,9 @@ namespace MobileGL::MG_Backend::DirectGLES { fbo.Slot, fbo.Gen); return; } -#if MOBILEGL_BUILD_RECORD_ARM // Kept in step for the monolith-glue overloads that still resolve their record // through it (SyncReadBufferToBackend's push arm). m_pushedSyncHandle = fbo; -#endif const GLenum glFBOTarget = MG_Util::ConvertFramebufferTargetToGLEnum(asTarget); Bind(asTarget); @@ -13109,7 +12932,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // outside the frontend's array, which cannot be addressed at all. Uint BoundImageUnitFormat(Int unit) { if (unit < 0 || unit >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) return 0; -#if MOBILEGL_BUILD_RECORD_ARM // P5e (fb, §5.4): the format-less image bake asks what format the APPLICATION // named at this unit, and under a transport the record is the only statement of // it - MGPImageView::InternalFormat is that same GLenum, copied by the client @@ -13120,7 +12942,6 @@ namespace MobileGL::MG_Backend::DirectGLES { if (static_cast(unit) >= st.BoundShaderImages.size()) return 0; return static_cast(st.BoundShaderImages[static_cast(unit)].InternalFormat); } -#endif return static_cast(MG_Pipe::gPipeInputs.GetImageTextureBinding(unit).Format); } @@ -15241,14 +15062,12 @@ namespace MobileGL::MG_Backend::DirectGLES { // nine-clause rebuild condition reads on the handle arm; the clause COUNT does not // shrink, its inputs move (D-H5). if (ProgramSubsystemEnabled()) { -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): MONOLITH GLUE ONLY. This is the frontend-keyed // lookup the phase exists to retire, and it survives here for the reason // ruling 1 (ID-81) gives: under Transport=monolith the push build keeps its // frontend arms token for token, and this arm is only ever reached from them. // The handle half below names no frontend identity at all. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif // The reader hides the composite band, so a program-pipeline composite - which // the server must never learn is one - resolves through the same call. const MG_Pipe::MGPipeHandle cso = g_backendProgramObjects.HandleOf(stateProgramObject.get()); @@ -15593,12 +15412,10 @@ namespace MobileGL::MG_Backend::DirectGLES { // the values are taken from the object, which in monolith are the very // values the client content-addressed, so the picture stays right while // the gap is visible rather than silent. -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): the registration probe below resolves the // sampler's handle by frontend identity - frontend-keyed twin resolution, // named debt inside the scope - P3b/P4b rekeys the registry onto handles. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif if (!MG_Pipe::MGPipeHandleIsNull( g_backendSamplerObjects.HandleOf(stateSamplerObject.get()))) { MGLOG_E_ONCE("MGPipe: sampler %u was synced without its unit's SamplerCso handle, so " @@ -15849,12 +15666,10 @@ namespace MobileGL::MG_Backend::DirectGLES { const MG_Pipe::MGPipeResourceRecord* pushedRecord = nullptr; if (TextureResourceSubsystemEnabled()) { -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §5.4): the renderbuffer's handle is resolved by // frontend identity below - frontend-keyed twin resolution, named debt inside // the scope - P3b/P4b rekeys the registry onto handles. const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry; -#endif // MONOLITH GLUE, named as such: the Renderbuffer handle of an object this // backend still arrives holding. Under a real split it rides in the payload. const MG_Pipe::MGPipeHandle res = g_backendRenderbufferObjects.HandleOf(stateRBOObject.get()); diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.h b/MobileGL/MG_Backend/DirectGLES/Managers.h index 17a172a4..bcb65002 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.h +++ b/MobileGL/MG_Backend/DirectGLES/Managers.h @@ -478,27 +478,19 @@ namespace MobileGL::MG_Backend::DirectGLES { if (!EsprytSlotTablesEnabled()) return nullptr; if (MG_Pipe::MGPipeHandleIsNull(handle)) return nullptr; if (handle.Slot >= SlotTable::kMaxHandleSlot) { -#if MOBILEGL_BUILD_RECORD_ARM MG_Pipe::MGPipeRecordFail( // @Ph-declined (ID-P7-1): PH-2 stays Fatal, CONTRACT-P7 §12 MG_Pipe::MGFatalFamily::ProtocolCorruption, "MGPipe: Fatal{ProtocolCorruption, \"BackendSlotTable.HandleSlot\"} - " "GetOrCreateByHandle named slot %u, past this table's %u bound", handle.Slot, SlotTable::kMaxHandleSlot); -#else - return nullptr; -#endif } const Uint32 liveGen = m_slotTables.LiveGenAt(handle.Slot); if (liveGen != 0 && liveGen > handle.Gen) { -#if MOBILEGL_BUILD_RECORD_ARM MG_Pipe::MGPipeRecordFail( // @Ph-declined (ID-P7-1): PH-2 stays Fatal, CONTRACT-P7 §12 MG_Pipe::MGFatalFamily::ProtocolCorruption, "MGPipe: Fatal{ProtocolCorruption, \"BackendSlotTable.Generation\"} - " "GetOrCreateByHandle named generation %u at slot %u, behind live generation %u", handle.Gen, handle.Slot, liveGen); -#else - return nullptr; -#endif } return &m_slotTables.GetOrCreate(handle); } @@ -940,7 +932,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // AcquirePersistentMap or (FLUSH_EXPLICIT) publish only via FlushMappedRange. Uint64 CurrentBufferMutationEpoch(); void BumpBufferMutationEpoch(); -#if MOBILEGL_BUILD_RECORD_ARM // P5e (vi), CONTRACT-P5E §5.1's first pin: how many bumps came from a thread other than // the apply thread WHILE an apply thread was running, under a live transport. The // record arm's clean gate stamps this counter and skips its probes while the stamp @@ -985,7 +976,6 @@ namespace MobileGL::MG_Backend::DirectGLES { Uint64 Serial = 0; }; DrawIndexBufferRequest ResolveDrawIndexBufferFromRecord(const MG_Pipe::MGPipeApplierState& st); -#endif // The DirectGLES storage behind one frontend buffer. Owned (refcounted) by // the frontend BufferObject; immediate BufferBackendOps keep it current, so @@ -1073,7 +1063,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // the legacy arm did; this member exists for the drains that have no object, which // in P3a is the readback flush and the fp64 narrowing. const Uint8* hostBytes = nullptr; -#if MOBILEGL_BUILD_RECORD_ARM // P11 B2 (T0): the client's AHardwareBuffer this store IS - imported with // glBufferStorageExternalEXT, so `id` is immutable, persistentMapped and // persistentPtr is this server's own coherent map of the client's pages. The @@ -1092,7 +1081,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // record arm) keeps no coverage, so the twin says it - the streaming idiom (orphan, then // glBufferSubData) defines content no descriptor declares. Bool contentSinceRespecify = false; -#endif }; // P3a (D-A4): the SEVENTH Espryt slot table, and the first one keyed by a handle the @@ -1152,7 +1140,6 @@ namespace MobileGL::MG_Backend::DirectGLES { GLESBufferResource* GetOrCreateBufferResourceForHandle(MG_Pipe::MGPipeHandle res); GLESBufferResource* FindBufferResourceForHandle(MG_Pipe::MGPipeHandle res); -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd): the staged-coverage assertion (StagedShadowStore::RequireCoverage) for a // read of the server shadow outside the upload ladders - the indirect command-byte // resolver. A no-op for a base that is not this resource's server shadow. @@ -1201,7 +1188,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // ladder and DirectGLES.cpp's XFB scatter are its two callers and they must not be able // to answer it differently. Bool ResourceContentIsDeclared(MG_Pipe::MGPipeHandle res); -#endif // MONOLITH GLUE, and named as such: the handle of a resource this backend is looking // at through a frontend object, resolved through the client allocator's lifetime-id @@ -1326,12 +1312,8 @@ namespace MobileGL::MG_Backend::DirectGLES { // conjunction in MultiDraw.cpp would satisfy in letter while giving the family two // selectors that can drift apart. One definition, spelled at every site that reads it. inline Bool VertexInputReadsRecords() { -#if MOBILEGL_BUILD_RECORD_ARM return MG_Config::DataArmIsRecord() && VertexInputSubsystemEnabled(); -#else - return false; -#endif } // Registered as the frontend's BufferBackendOps at backend init and on @@ -1830,10 +1812,8 @@ namespace MobileGL::MG_Backend::DirectGLES { } // namespace VertexArrayImpl namespace TextureImpl { -#if MOBILEGL_BUILD_RECORD_ARM // Drives the actual unpack save/restore helper without needing a texture upload. void ExerciseDefaultUnpackScopeForTesting(); -#endif inline Bool IsSupportedTextureTarget(TextureTarget target) { // Every desktop-only target is stored on an ES one; see MapToBackendTextureTarget. (void)target; @@ -1968,7 +1948,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // parameter and sampler halves are unchanged and run on this name as on any other. void SyncTextureViewToBackend(const SharedPtr& stateTextureObject); void StampViewSyncKeys(const SharedPtr& stateTextureObject); -#if MOBILEGL_BUILD_RECORD_ARM // P5e (tx2). THE VIEW ARM UNDER A TRANSPORT, and what it can and cannot answer. // // `Desc.ViewOf` names the storage owner BY HANDLE, so the STEADY question - "is my ES @@ -1983,7 +1962,6 @@ namespace MobileGL::MG_Backend::DirectGLES { void SyncTextureViewToBackendByRecord( MG_Pipe::MGPipeHandle res, const MG_Pipe::MGPipeResourceRecord& record, const SharedPtr& stateTextureObject); -#endif // The storage half of the sync for a texture created by glTextureView. Instead of // allocating storage and replaying uploads, it makes this object's ES name BE a view // of the storage texture's ES name (EXT/OES_texture_view), which is what gives the @@ -2367,7 +2345,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // glCopyImageSubData passes: it tries FollowCopyImageInStagedStore first and marks the store // itself when that fails. void NoteDriverSideTextureWriteByHandle(MG_Pipe::MGPipeHandle texture, Bool storeFollowsTheWrite = false); -#if MOBILEGL_BUILD_RECORD_ARM // P8-E (notes/p8/E.md): make glCopyImageSubData's texel-block move in the server's staged // store too (StagedTextureStore::FollowCopy), so the destination level's bytes stay its // content. Box in each image's own texel grid. False when the store cannot follow: a cube @@ -2377,7 +2354,6 @@ namespace MobileGL::MG_Backend::DirectGLES { Bool FollowCopyImageInStagedStore(MG_Pipe::MGPipeHandle source, Uint32 sourceLevel, const IntVec3& sourceOrigin, MG_Pipe::MGPipeHandle destination, Uint32 destinationLevel, const IntVec3& destinationOrigin, const IntVec3& size); -#endif // Brings every texture the next draw reads - the touched units' bindings and the draw // FBO's texture attachments - onto the backend, through the two borrowed-pair memos // documented at their definitions. Declared here so tests can drive those memos directly. @@ -2424,14 +2400,12 @@ namespace MobileGL::MG_Backend::DirectGLES { // "one object is bound to BOTH bindings" skip, where the DRAW pass already did the // attachment work and only glReadBuffer is READ-target-specific. void SyncReadBufferToBackendByHandle(MG_Pipe::MGPipeHandle fbo); -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.2): the framebuffer handle the CURRENT sync is keyed on. // A caller applying a record sets it before SyncToBackend / SyncReadBufferToBackend, // which then read the applier's record for THAT handle instead of probing the // client's slot allocator for the frontend object's lifetime id (T2). Read only // with an active transport; monolith resolves through HandleOf as it always did. MG_Pipe::MGPipeHandle m_pushedSyncHandle = MG_Pipe::kMGPipeNullHandle; -#endif void InvalidateSyncedState(); Uint GetBackendFramebufferId() const { return m_backendFBOId; } void Bind(FramebufferTarget target) const; @@ -3124,11 +3098,9 @@ namespace MobileGL::MG_Backend::DirectGLES { // Same for gl_BaseVertex: only a program that reads it pays for the per-draw // uniform write, and only such a program needs the reset after one. Bool ReadsBaseVertex() const { return m_baseVertexUniformLocation >= 0; } -#if MOBILEGL_BUILD_RECORD_ARM // P8-C: same for the gl_BaseInstance uniform - which an indirect draw feeds from the // command on the CPU only when the mg_IndirectParams view is absent. Bool ReadsBaseInstance() const { return m_baseInstanceUniformLocation >= 0; } -#endif // Which viewport indices the next draw's fragments may keep, one bit each. Written // once per replay pass; see ForEachViewportRoutingPass. void SetViewportPassMask(Uint32 indexMask) const; @@ -3672,7 +3644,6 @@ namespace MobileGL::MG_Backend::DirectGLES { g_backendRenderbufferObjects; } // namespace RenderbufferImpl -#if MOBILEGL_BUILD_RECORD_ARM // P5c (ct), CONTRACT-P5C.md §5.2: object_death's per-kind release, one entry point for all // seven kinds for the same reason the notice switch is one - the answer is the same for // all of them: every holder of the kind's twin table lets go of the twin at this handle. @@ -3704,5 +3675,4 @@ namespace MobileGL::MG_Backend::DirectGLES { // destructor calls into the driver (there is no current context, and the ids name nothing). // A no-op once exit() has begun (the statics may already be gone). Monolith never calls it. void DropEveryTwinForEndedServerSession(); -#endif } // namespace MobileGL::MG_Backend::DirectGLES diff --git a/MobileGL/MG_Backend/DirectGLES/MultiDraw.cpp b/MobileGL/MG_Backend/DirectGLES/MultiDraw.cpp index f435a01c..5d7cd985 100644 --- a/MobileGL/MG_Backend/DirectGLES/MultiDraw.cpp +++ b/MobileGL/MG_Backend/DirectGLES/MultiDraw.cpp @@ -125,7 +125,6 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl { const Uint8* HostBytes = nullptr; // HostBytes: null when there is no CPU copy }; -#if MOBILEGL_BUILD_RECORD_ARM // A missing record on the handle arm is a NAMED refusal and never a quiet fall-back to // the frontend (TASK-mv requirement 2; the shape is Managers.cpp's // RefuseNullFrontendTextureOffTheHandleArm). The frontend element slot is not a second @@ -175,11 +174,9 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl { if (!candidate.Live || candidate.Gen != res.Gen) return false; return candidate.Desc.HasDefinedContent != 0; } -#endif BoundIndexBufferView ResolveBoundIndexBuffer(IndexBufferQuestion question, const char* entry) { BoundIndexBufferView view; -#if MOBILEGL_BUILD_RECORD_ARM if (BufferImpl::VertexInputReadsRecords()) { const auto& st = MG_Pipe::MGPipeApplier(); const MG_Pipe::MGPipeHandle res = BufferImpl::ResolveDrawIndexBufferFromRecord(st).Res; @@ -219,7 +216,6 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl { } return view; } -#endif // MONOLITH GLUE from here down, token for token what each call site did before. const auto& vao = MG_Pipe::gPipeInputs.GetBoundVertexArray(); if (!vao) return view; @@ -293,7 +289,6 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl { // an empty slot, and not the arm test (ID-110: the arm was decided by the transport // above, never inferred from a null). Uint BoundDrawIndirectBufferId() { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const MG_Pipe::MGPipeHandle res = MG_Pipe::MGPipeApplier().VerbIndirectBuffer; if (MG_Pipe::MGPipeHandleIsNull(res)) return 0; @@ -303,7 +298,6 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl { } return resource->id; } -#endif // MONOLITH GLUE from here down, token for token what this function did before. const auto& indirect = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.cpp b/MobileGL/MG_Backend/DirectGLES/Utils.cpp index 351e6b11..c8cc59f8 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Utils.cpp @@ -37,16 +37,13 @@ #include namespace MobileGL::MG_Backend::DirectGLES { -#if MOBILEGL_BUILD_RECORD_ARM // read_pixels writes server reply scratch. The client refuses PACK_BUFFER before // emission, so no frontend pack binding can affect this destination. static const SharedPtr& SplitReadbackPackBuffer() { static const SharedPtr none; return none; } -#endif -#if MOBILEGL_BUILD_RECORD_ARM const FormatCapabilityCache* ActiveBackendFormatCaps() { // Under a live split session the SERVER's private backend is what owns the context on the // apply thread (and these reads all run there), so its cache is the authoritative one. @@ -70,7 +67,6 @@ namespace MobileGL::MG_Backend::DirectGLES { #endif return pActiveBackendObject ? &pActiveBackendObject->GetFormatCapabilities() : nullptr; } -#endif namespace { Flags GetForcedPixelFormatNormalizeOptions() { @@ -110,26 +106,16 @@ namespace MobileGL::MG_Backend::DirectGLES { SizeT targetIndex, Bool caveat, FormatCapability capability) { -#if MOBILEGL_BUILD_RECORD_ARM const FormatCapabilityCache* activeCaps = ActiveBackendFormatCaps(); if (activeCaps == nullptr || targetIndex >= kFormatCapabilityTargetCount) { return false; } -#else - if (!pActiveBackendObject || targetIndex >= kFormatCapabilityTargetCount) { - return false; - } -#endif const SizeT formatIndex = static_cast(internalFormat); if (formatIndex >= kFormatCapabilityFormatCount) { return false; } -#if MOBILEGL_BUILD_RECORD_ARM const FormatCapabilityCache& cache = *activeCaps; -#else - const FormatCapabilityCache& cache = pActiveBackendObject->GetFormatCapabilities(); -#endif const FormatCapabilityFlags caps = caveat ? cache.CaveatCaps[targetIndex][formatIndex] : cache.FullCaps[targetIndex][formatIndex]; return HasFormatCapability(caps, capability); @@ -173,11 +159,7 @@ namespace MobileGL::MG_Backend::DirectGLES { using namespace MobileGL::MG_Util::TextureFormatProcessor; const GLenum requestedInternalFormat = MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat); Flags options; -#if MOBILEGL_BUILD_RECORD_ARM if (ActiveBackendFormatCaps() == nullptr || ShouldUseCaveatFormat(internalFormat, targetIndex)) { -#else - if (!pActiveBackendObject || ShouldUseCaveatFormat(internalFormat, targetIndex)) { -#endif options = GetRuntimeFallbackNormalizeOptions( requestedInternalFormat, TextureImpl::GetRenderTargetNormalizeOptions(g_GLESCapabilities, targetIndex)); @@ -271,15 +253,9 @@ namespace MobileGL::MG_Backend::DirectGLES { // not be resolved yet - a probe run then would latch "cannot tell" as "clean" // forever. Once the backend exists, the first narrow-format image this process // creates runs the probe on a live context. -#if MOBILEGL_BUILD_RECORD_ARM if (ActiveBackendFormatCaps() == nullptr) { return false; } -#else - if (pActiveBackendObject == nullptr) { - return false; - } -#endif return MG_Util::SelfTest::CopyImageMirrorsPacked16FieldOrder(g_GLESFuncs); } @@ -317,15 +293,9 @@ namespace MobileGL::MG_Backend::DirectGLES { if (!TargetRequiresRenderableFormat(targetIndex)) { return false; } -#if MOBILEGL_BUILD_RECORD_ARM if (ActiveBackendFormatCaps() != nullptr && !ShouldUseCaveatFormat(internalFormat, targetIndex)) { return false; } -#else - if (pActiveBackendObject && !ShouldUseCaveatFormat(internalFormat, targetIndex)) { - return false; - } -#endif const GLenum requestedInternalFormat = MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat); const Flags options = GetRuntimeFallbackNormalizeOptions( requestedInternalFormat, GetRenderTargetNormalizeOptions(g_GLESCapabilities, targetIndex)); @@ -2364,10 +2334,8 @@ namespace MobileGL::MG_Backend::DirectGLES { static Bool StoreClientRows(SizeT dstPixelBytes, SizeT swapGroupSize, GLsizei width, GLsizei sliceHeight, GLsizei sliceCount, void* pixels, Bool applyPackImageParams, FillRow&& fillRow) { const auto& pixelPackBufferObject = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? SplitReadbackPackBuffer() : -#endif MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject(); // Destination layout is computed from the client-side PACK parameters; only the actual pixel diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.h b/MobileGL/MG_Backend/DirectGLES/Utils.h index edef8080..3b497103 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.h +++ b/MobileGL/MG_Backend/DirectGLES/Utils.h @@ -13,7 +13,6 @@ #include namespace MobileGL::MG_Backend::DirectGLES { -#if MOBILEGL_BUILD_RECORD_ARM // C6 / ID-52 / CONTRACT-P5 table 3's pActiveBackendObject row. The format-capability cache of // THIS ROLE's backend. Under an active transport the server's own private // BackendObject_DirectGLES owns the context on the apply thread, so a backend-internal format @@ -24,7 +23,6 @@ namespace MobileGL::MG_Backend::DirectGLES { // (five in Utils.cpp, ClampSamplesToBackendSupport in BackendObject_DirectGLES.cpp) go through // this instead of dereferencing pActiveBackendObject directly. const FormatCapabilityCache* ActiveBackendFormatCaps(); -#endif namespace DebugImpl { class ErrorLopper { diff --git a/MobileGL/MG_Backend/DirectGLES/WireTextureReadback.inc b/MobileGL/MG_Backend/DirectGLES/WireTextureReadback.inc index 30e0bba3..2afc9fd4 100644 --- a/MobileGL/MG_Backend/DirectGLES/WireTextureReadback.inc +++ b/MobileGL/MG_Backend/DirectGLES/WireTextureReadback.inc @@ -281,7 +281,6 @@ return true; } -#if MOBILEGL_BUILD_RECORD_ARM // P9 W2-a. The store's Defined-ness follows the client's respecifies; the driver's follows the // twin's last sync. A re-mint asks this before reading a level back, because a level defined // after that sync (null data, or null data plus a partial upload) is not on the driver yet and @@ -460,4 +459,3 @@ bytes = Move(result); return true; } -#endif // MOBILEGL_BUILD_DISAGGREGATED diff --git a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp index 253cd7f5..9cc0307b 100644 --- a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp @@ -423,11 +423,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { } Bool BackendObject_DirectVulkan::LatchIfGpuFaulted() { -#if MOBILEGL_BUILD_RECORD_ARM return pVulkanRenderer != nullptr && pVulkanRenderer->LatchIfGpuHung("apply"); -#else - return false; -#endif } void BackendObject_DirectVulkan::Initialize() { diff --git a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp index 45f298f3..047dc230 100644 --- a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp @@ -38,16 +38,12 @@ namespace MobileGL::MG_Backend::DirectVulkan { RendererSlot pVulkanRenderer; namespace { -#if MOBILEGL_BUILD_RECORD_ARM void RejectWireLegacyBuffer() { if (MG_Config::DataArmIsRecord()) { MGLOG_F("MGPipe: Fatal{RoleViolation, \"buffer-legacy-arm\"} (Magma P7 buffer consumer)"); std::abort(); } } -#else - inline void RejectWireLegacyBuffer() {} -#endif // Generation of the live VulkanRenderer instance, mirroring // DirectGLES's g_syncContextGeneration. BackendObject_DirectVulkan // bumps it (BumpRendererGeneration) wherever pVulkanRenderer is reset @@ -138,53 +134,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } namespace { -#if !MOBILEGL_BUILD_RECORD_ARM - // P7 wave 2 package C, OQ-8: THE PULL BUILD'S HALF, VERBATIM. A disaggregated build - // answers GetShaderStorageBlock{Index,Binding} out of LinkArtifacts::storageBlocks - // instead (see those functions below), which retires this whole cache - the map, the - // SPIRV-Reflect rebuild, the teardown clear and the rehash hazard. It cannot be - // retired HERE because the archive member it reads is itself disaggregated-only, for - // G1: one more Vector in LinkArtifacts moves the pull build's .text, which is pinned - // byte-for-byte at 0xa52203. - // - // NOTHING OUTSIDE THIS FILE READS ANY OF IT (measured: BufferVariableResource, - // bufferVariables, activeVariables and StorageBlockResource have no reference anywhere - // else in the tree, and `dataSize` is written and never read - GL_BUFFER_VARIABLE and - // GL_ACTIVE_VARIABLES are answered by MG_Impl/GLImpl/Program/ProgramInterface.cpp out - // of glslang's own reflection, which is a different index space). So the two arms - // below differ in exactly the two functions their callers use, and in nothing else. - struct BufferVariableResource { - String name; - GLuint blockIndex = 0; - GLint offset = 0; - GLint size = 0; - }; - - struct StorageBlockResource { - String name; - GLuint binding = 0; - GLint dataSize = 0; - Vector activeVariables; - }; - - struct ProgramResourceCache { - // Lifetime id of the program the cached reflection belongs to. GL names are - // recycled (IndexGenerator hands freed indices straight back), and a - // recreated program's backendStateVersion restarts at the same small values, - // so the version alone can collide; the never-reused lifetime id makes the - // slot's ownership unambiguous. - Uint64 programLifetimeId = 0; - Uint32 backendStateVersion = 0; - // glShaderStorageBlockBinding deliberately does NOT bump the backend state - // version, and the pipeline composite is unnamed so the in-place patch in - // DirectVulkan::ShaderStorageBlockBinding can never reach its slot - the - // mirror replay bumps only the program's block-binding version. Without this - // key the composite's slot kept serving the pre-rebind block.binding. - Uint32 blockBindingVersion = 0; - Vector storageBlocks; - Vector bufferVariables; - }; -#endif // !MOBILEGL_BUILD_RECORD_ARM struct DrawElementsIndirectCommand { Uint32 count = 0; @@ -201,14 +150,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { Uint32 baseInstance = 0; }; -#if !MOBILEGL_BUILD_RECORD_ARM - // Keyed by GL program name so the freed-name reuse in IndexGenerator bounds the - // map at the peak-simultaneous-program high-water mark; each slot's ownership is - // checked against the program's lifetime id before it is served (see - // GetProgramResourceCache). Cleared wholesale at EGL teardown via - // ClearProgramResourceCaches. - UnorderedMap g_programResourceCaches; -#endif void ClearReadPixelsOutput(GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) { if (!pixels || width <= 0 || height <= 0) { @@ -223,160 +164,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { } } -#if !MOBILEGL_BUILD_RECORD_ARM - String NormalizeDescriptorName(const SpvReflectDescriptorBinding& binding) { - const char* rawName = binding.name; - if (binding.type_description != nullptr && binding.type_description->type_name != nullptr) { - rawName = binding.type_description->type_name; - } - if (rawName == nullptr) { - return {}; - } - String name = rawName; - const auto arraySuffix = name.find("[0]"); - if (arraySuffix != String::npos) { - name = name.substr(0, arraySuffix); - } - return name; - } - void AddBufferVariablesRecursive(const SpvReflectBlockVariable& variable, const String& prefix, - GLuint blockIndex, Vector& variables, - Vector& activeVariables) { - for (Uint32 memberIndex = 0; memberIndex < variable.member_count; ++memberIndex) { - const auto& member = variable.members[memberIndex]; - String name = prefix; - if (!name.empty()) { - name += "."; - } - name += member.name ? member.name : ""; - - if (member.member_count > 0) { - AddBufferVariablesRecursive(member, name, blockIndex, variables, activeVariables); - continue; - } - - BufferVariableResource resource{}; - resource.name = name; - resource.blockIndex = blockIndex; - resource.offset = static_cast(member.offset); - resource.size = static_cast(member.size); - const GLuint variableIndex = static_cast(variables.size()); - variables.push_back(resource); - activeVariables.push_back(variableIndex); - } - } - - ProgramResourceCache& GetProgramResourceCache(const MG_State::GLState::ProgramObject& program) { - auto& cache = g_programResourceCaches[program.GetExternalIndex()]; - const Uint64 programLifetimeId = program.GetLifetimeId(); - const Uint32 backendStateVersion = program.GetBackendStateVersion(); - const Uint32 blockBindingVersion = program.GetBlockBindingVersion(); - // The lifetime id must match too: a new program that reuses a deleted - // program's name and happens to land on the same backendStateVersion (both - // count from zero) would otherwise be served the dead program's reflection. - if (cache.programLifetimeId == programLifetimeId && - cache.backendStateVersion == backendStateVersion && - (!cache.storageBlocks.empty() || !cache.bufferVariables.empty())) { - if (cache.blockBindingVersion != blockBindingVersion) { - // Only the block bindings moved (glShaderStorageBlockBinding, or the - // pipeline composite's mirror replay - neither touches the backend - // state version): the reflection itself is unchanged, so re-apply the - // overrides by name instead of re-running spirv-reflect. Overrides - // only ever accumulate, so a block without one still holds its - // declared binding. - for (auto& block : cache.storageBlocks) { - const Int rebound = program.GetShaderStorageBlockBindingOverride(block.name); - if (rebound >= 0) block.binding = static_cast(rebound); - } - cache.blockBindingVersion = blockBindingVersion; - } - return cache; - } - - cache = {}; - cache.programLifetimeId = programLifetimeId; - cache.backendStateVersion = backendStateVersion; - cache.blockBindingVersion = blockBindingVersion; - - Vector modules; - Vector validModules; - const auto& spirvs = program.GetGeneratedSpirv(); - for (const auto& spirv : spirvs) { - if (spirv.empty()) { - continue; - } - SpvReflectShaderModule module{}; - const SpvReflectResult result = - spvReflectCreateShaderModule(spirv.size() * sizeof(Uint), spirv.data(), &module); - if (result != SPV_REFLECT_RESULT_SUCCESS) { - continue; - } - modules.push_back(module); - validModules.push_back(true); - } - - for (auto& module : modules) { - uint32_t bindingCount = 0; - SpvReflectResult result = spvReflectEnumerateDescriptorBindings(&module, &bindingCount, nullptr); - if (result != SPV_REFLECT_RESULT_SUCCESS || bindingCount == 0) { - continue; - } - Vector bindings(bindingCount); - result = spvReflectEnumerateDescriptorBindings(&module, &bindingCount, bindings.data()); - if (result != SPV_REFLECT_RESULT_SUCCESS) { - continue; - } - std::sort(bindings.begin(), bindings.end(), [](const auto* lhs, const auto* rhs) { - const String lhsName = lhs ? NormalizeDescriptorName(*lhs) : String(); - const String rhsName = rhs ? NormalizeDescriptorName(*rhs) : String(); - if (lhsName != rhsName) return lhsName < rhsName; - return lhs->binding < rhs->binding; - }); - for (const auto* binding : bindings) { - if (binding == nullptr || - binding->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) { - continue; - } - const String blockName = NormalizeDescriptorName(*binding); - if (blockName.empty()) { - continue; - } - const auto existing = std::find_if( - cache.storageBlocks.begin(), cache.storageBlocks.end(), - [&](const StorageBlockResource& block) { return block.name == blockName; }); - if (existing != cache.storageBlocks.end()) { - continue; - } - - StorageBlockResource block{}; - block.name = blockName; - block.binding = binding->binding; - // glShaderStorageBlockBinding survives every rebuild of this cache: the - // authoritative record of a rebound block lives on the program (it is what - // GL_BUFFER_BINDING reports), and only the shader's declared binding is - // recoverable from the SPIR-V. Without this, any unrelated state-version - // bump would silently revert the block to its declared binding. - const Int rebound = program.GetShaderStorageBlockBindingOverride(blockName); - if (rebound >= 0) block.binding = static_cast(rebound); - block.dataSize = static_cast(binding->block.size); - const GLuint blockIndex = static_cast(cache.storageBlocks.size()); - AddBufferVariablesRecursive(binding->block, blockName, blockIndex, cache.bufferVariables, - block.activeVariables); - cache.storageBlocks.push_back(block); - } - } - - for (SizeT i = 0; i < modules.size(); ++i) { - if (validModules[i]) { - spvReflectDestroyShaderModule(&modules[i]); - } - } - return cache; - } -#endif // !MOBILEGL_BUILD_RECORD_ARM - -#if MOBILEGL_BUILD_RECORD_ARM // The verb's handles identify server stores; never inspect a client binding. // // P8-D: THE GPU READS THE WORDS (VulkanRenderer::DrawWireIndirectNative, WireDraw.inc), as @@ -456,7 +244,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { pVulkanRenderer->MultiDrawArrays(payload); } } -#endif MG_State::GLState::ProgramObject* TryGetDirectVulkanProgram(GLuint program) { if (!MG_Pipe::gPipeInputs.ValidateProgramName(program)) { @@ -495,7 +282,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } // namespace -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 2 package C, OQ-8 (CONTRACT-P7 §5.3): THE MONOLITH CONSUMER READS THE ARCHIVE // TOO, so one published list serves both of this backend's arms. // @@ -555,43 +341,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { if (rebound >= 0) return static_cast(rebound); return blocks[blockIndex].binding; } -#else - void ClearProgramResourceCaches() { - // Called from EGL teardown while the backend's m_eglStateMutex is held; GL - // calls are serialized in this codebase (contexts migrate threads but never - // run concurrently), so no other thread can be inside the unsynchronized map. - // Live programs in another context self-heal: their entry rebuilds from the - // retained generated SPIR-V on the next resource query. - g_programResourceCaches.clear(); - } - - GLuint GetShaderStorageBlockIndex(const MG_State::GLState::ProgramObject& program, const String& name) { - auto& cache = GetProgramResourceCache(program); - auto find = [&cache](const String& key) { - return std::find_if(cache.storageBlocks.begin(), cache.storageBlocks.end(), - [&](const StorageBlockResource& block) { return block.name == key; }); - }; - auto it = find(name); - if (it == cache.storageBlocks.end()) { - // Cache names are normalized (NormalizeDescriptorName drops the array suffix), so - // an arrayed block that GL enumerates per element - "B[0]", "B[1]" - is one entry - // here, spelled "B". Retry against the bare name before giving up. - const auto bracket = name.rfind('['); - if (bracket == String::npos || name.empty() || name.back() != ']') return GL_INVALID_INDEX; - it = find(name.substr(0, bracket)); - if (it == cache.storageBlocks.end()) return GL_INVALID_INDEX; - } - return static_cast(std::distance(cache.storageBlocks.begin(), it)); - } - - GLuint GetShaderStorageBlockBinding(const MG_State::GLState::ProgramObject& program, GLuint blockIndex) { - auto& cache = GetProgramResourceCache(program); - if (blockIndex >= cache.storageBlocks.size()) { - return 0; - } - return cache.storageBlocks[blockIndex].binding; - } -#endif void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ClearBufferfi called with null VulkanRenderer"); @@ -646,23 +395,19 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { DrawWireIndirect(mode, type, indirect, drawcount, stride, true); return; } -#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElementsIndirect called with null VulkanRenderer"); MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MultiDrawElementsIndirect called with null GL context"); pVulkanRenderer->MultiDrawElementsIndirect(mode, type, indirect, drawcount, stride); } void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { DrawWireIndirect(mode, 0, indirect, drawcount, stride, false); return; } -#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawArraysIndirect called with null VulkanRenderer"); MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MultiDrawArraysIndirect called with null GL context"); @@ -714,24 +459,20 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void MultiDrawElementsIndirectCount(GLenum mode, GLenum type, const void* indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { DrawWireIndirect(mode, type, indirect, maxdrawcount, stride, true, true, drawcount); return; } -#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElementsIndirectCount called with null VulkanRenderer"); MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MultiDrawElementsIndirectCount called with null GL context"); pVulkanRenderer->MultiDrawElementsIndirectCount(mode, type, indirect, drawcount, maxdrawcount, stride); } void MultiDrawArraysIndirectCount(GLenum mode, const void* indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { DrawWireIndirect(mode, 0, indirect, maxdrawcount, stride, false, true, drawcount); return; } -#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawArraysIndirectCount called with null VulkanRenderer"); MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MultiDrawArraysIndirectCount called with null GL context"); @@ -804,12 +545,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { DrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instancecount, 0, 0); } void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { DrawWireIndirect(mode, type, indirect, 1, 0, true); return; } -#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElementsIndirect called with null VulkanRenderer"); MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::DrawElementsIndirect called with null GL context"); @@ -869,12 +608,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { DrawArraysInstancedBaseInstance(mode, first, count, instancecount, 0); } void DrawArraysIndirect(GLenum mode, const void* indirect) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { DrawWireIndirect(mode, 0, indirect, 1, 0, false); return; } -#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArraysIndirect called with null VulkanRenderer"); MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::DrawArraysIndirect called with null GL context"); @@ -943,7 +680,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void DispatchComputeIndirect(GLintptr indirect) { -#if MOBILEGL_BUILD_RECORD_ARM // P8-SV: THE GPU READS THE GROUP COUNTS on the wire arm too - VulkanRenderer's // DispatchComputeIndirect takes its transport branch into DispatchWireComputeIndirect // (WireDraw.inc), which issues vkCmdDispatchIndirect from the verb's store. The CPU read @@ -952,7 +688,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { pVulkanRenderer->DispatchComputeIndirect(indirect); return; } -#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DispatchComputeIndirect called with null VulkanRenderer"); MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::DispatchComputeIndirect called with null GL context"); pVulkanRenderer->DispatchComputeIndirect(indirect); @@ -1014,7 +749,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void ShaderStorageBlockBinding(GLuint program, const GLchar* storageBlockName, GLuint storageBlockBinding) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { auto& state = MG_Pipe::MGPipeApplier(); const auto handle = state.VerbStorageBlockProgram; @@ -1032,7 +766,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { ++record.BindingsSerial; return; } -#endif auto* programObject = TryGetDirectVulkanProgram(program); if (!programObject || storageBlockName == nullptr) return; const Int maxBindings = @@ -1058,7 +791,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { MakeUnique("DirectVulkan", __func__, "Shader storage binding is out of range.")); return; } -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 2 package C, OQ-8: NOTHING LEFT TO PATCH, and the hazard goes with it. // // The frontend has already recorded the new binding on the program, and that record is @@ -1078,26 +810,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // cache is the retirement. The pull build below keeps both. (void)storageBlockBinding; } -#else - // The frontend already validated that the name denotes an active block, and has - // already recorded the new binding on the program - which is what reseeds this cache - // whenever it is rebuilt. Writing the entry here as well keeps an ALREADY-BUILT cache - // (the common case: the very next draw reads it) from having to be thrown away. - // - // Resolve the index BEFORE taking the reference, and bounds-check the way the - // sibling getter does. GetShaderStorageBlockIndex re-enters GetProgramResourceCache, - // which indexes g_programResourceCaches and can therefore insert - and that map is - // open-addressed, so a rehash MOVES its entries and a reference taken before the - // call is left dangling. Binding a program's storage block - // while another program's entry was still absent from the cache was a reproducible - // segfault (ProgramPipelineScenario's two storage-block cases, in one process). - const GLuint blockIndex = GetShaderStorageBlockIndex(*programObject, storageBlockName); - if (blockIndex == GL_INVALID_INDEX) return; - auto& cache = GetProgramResourceCache(*programObject); - if (blockIndex >= cache.storageBlocks.size()) return; - cache.storageBlocks[blockIndex].binding = storageBlockBinding; - } -#endif void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) { MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ReadPixels called with null VulkanRenderer"); MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::ReadPixels called with null GL context"); @@ -1140,7 +852,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // memory) into uint32 values with the loop-closing first index appended. static Bool BuildClosedLineLoopIndices(GLsizei count, GLenum type, const void* indices, Vector& outIndices) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const SizeT width = MG_Util::GetGLTypeSize(type); if ((width != 1 && width != 2 && width != 4) || count < 2) return false; @@ -1163,7 +874,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { outIndices[count] = outIndices[0]; return true; } -#endif const SizeT indexSize = MG_Util::GetGLTypeSize(type); if (indexSize == 0 || count < 2) { return false; @@ -1318,15 +1028,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { // MultiDrawIndexedCmd left the client-memory shape addressing a view whose byte // offset is a hardcoded 0, so UploadAndBindIndexBuffer saw a null client pointer, // declined the whole batch and painted nothing.) -#if MOBILEGL_BUILD_RECORD_ARM const Bool noIndexBuffer = MG_Config::DataArmIsRecord() ? MG_Pipe::MGPipeHandleIsNull(MG_Pipe::MGPipeApplier().IndexBuffer.Res) : MG_Pipe::gPipeInputs.GetBoundVertexArray()->GetIndexBufferBindingSlot().GetBoundObject() == nullptr; if (noIndexBuffer) { -#else - const auto& vao = *MG_Pipe::gPipeInputs.GetBoundVertexArray(); - if (vao.GetIndexBufferBindingSlot().GetBoundObject() == nullptr) { -#endif for (GLsizei i = 0; i < drawcount; ++i) { if (count[i] <= 0) { continue; @@ -1512,7 +1217,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } // Pure status read (glGetSynciv must not flush). if (pVulkanRenderer->IsSubmitIndexComplete(sync->submitIndex)) return true; -#if MOBILEGL_BUILD_RECORD_ARM // P13 W4: A STATUS POLL THAT CAN NEVER BE ANSWERED. On the record arm a frame's draws stay // in one command buffer (and one render pass) until something submits it, so a client that // only polls - glGetSynciv in a loop, no flush bit, no swap - waits for work nothing will @@ -1526,7 +1230,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { pVulkanRenderer->FlushForSyncPoint(sync->submitIndex); return pVulkanRenderer->IsSubmitIndexComplete(sync->submitIndex); } -#endif return false; } diff --git a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.h b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.h index 1ffd4b8a..da6d3e8e 100644 --- a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.h +++ b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.h @@ -45,7 +45,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { Uint64 GetRendererGeneration(); void BumpRendererGeneration(); -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 2 package C (CONTRACT-P7 §5.5). Magma's StateObjectDeathOps table, installed // from BackendObject_DirectVulkan::Initialize() so that GetStateObjectDeathOps() is // non-null on every Magma role that owns a backend. See the definition for what the one @@ -55,7 +54,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // True when the notice currently installed is this backend's. Read by MG_Test so the // install can be asserted without a death having to happen first. Bool StateObjectDeathOpsInstalled(); -#endif // Drops every cached program-resource reflection entry (CPU-side strings/vectors // only, no Vulkan handles). Called at EGL teardown next to the renderer reset; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/BufferArena.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/BufferArena.cpp index 20d99c8a..d9d15f58 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/BufferArena.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/BufferArena.cpp @@ -7,9 +7,7 @@ // End of Source File Header #include "BufferArena.h" -#if MOBILEGL_BUILD_RECORD_ARM #include -#endif namespace MobileGL::MG_Backend::DirectVulkan { Bool BufferArena::Initialize(const BufferArenaDesc& desc) { @@ -128,14 +126,12 @@ namespace MobileGL::MG_Backend::DirectVulkan { bufferDesc.usage = m_desc.usage; bufferDesc.memoryUsage = m_desc.memoryUsage; bufferDesc.allocationFlags = m_desc.allocationFlags; -#if MOBILEGL_BUILD_RECORD_ARM // Split staging may also be the destination of a GPU UBO range copy. // Persistent host writes must be coherent: Upload deliberately writes // the mapped pointer without a per-range VMA flush. if (MG_Config::DataArmIsRecord() && m_desc.persistentlyMapped) { bufferDesc.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; } -#endif if (!buffer.Create(bufferDesc)) { return false; } diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp index b7ae0f0d..6820e496 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp @@ -7,9 +7,7 @@ // End of Source File Header #include "FrameContext.h" -#if MOBILEGL_BUILD_RECORD_ARM #include -#endif namespace MobileGL::MG_Backend::DirectVulkan { VkResult FrameContext::Initialize(VkDevice device, VkCommandPool commandPool, Uint32 frameCount) { @@ -224,13 +222,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkImageMemoryBarrier presentBarrier{}; presentBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; presentBarrier.srcAccessMask = 0; -#if MOBILEGL_BUILD_RECORD_ARM // A layout transition writes the image too. Order it after the wire // render pass's storeOp, clears and copies instead of relying on the old // per-draw queue-idle path. This applies even when contents are discarded. if (MG_Config::DataArmIsRecord()) presentBarrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; -#endif presentBarrier.dstAccessMask = 0; presentBarrier.oldLayout = oldLayout; presentBarrier.newLayout = presentLayout; @@ -243,12 +239,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { presentBarrier.subresourceRange.baseArrayLayer = 0; presentBarrier.subresourceRange.layerCount = 1; vkCmdPipelineBarrier(commandBuffer, -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, -#else - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, -#endif VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &presentBarrier); diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/MagmaProgramSource.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/MagmaProgramSource.h index c5d5b06d..06c575fe 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/MagmaProgramSource.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/MagmaProgramSource.h @@ -3,7 +3,6 @@ #include -#if MOBILEGL_BUILD_RECORD_ARM #include #include #include "../DirectVulkanResourceState.h" @@ -12,10 +11,8 @@ // the archive (LinkArtifacts::storageBlocks), so the SPIR-V reflector is off the Magma wire // draw path entirely. A future edit that re-adds the include is re-adding a per-draw reflect, // because a MagmaProgramSource is constructed once per draw and can memoise nothing. -#endif namespace MobileGL::MG_Backend::DirectVulkan { -#if MOBILEGL_BUILD_RECORD_ARM // A borrowed view, valid only while its frontend object or server record lives. // It never constructs a ProgramObject on the server. Post-link mutable values // come from the record tails, not from the archive's link-time defaults. @@ -218,7 +215,4 @@ namespace MobileGL::MG_Backend::DirectVulkan { // also why they never helped: a view lives for one draw, so the latch was cold every // time it was read. }; -#else - using MagmaProgramSource = MG_State::GLState::ProgramObject; -#endif } diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.cpp index 52cb47b7..883147ad 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.cpp @@ -198,14 +198,12 @@ namespace MobileGL::MG_Backend::DirectVulkan { XXHASH_VERIFY(XXH64_update(m_hashState, &payload.programHash, sizeof(payload.programHash))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.vertexInputHash, sizeof(payload.vertexInputHash))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.pipelineLayout, sizeof(payload.pipelineLayout))); -#if MOBILEGL_BUILD_RECORD_ARM if (payload.wireRenderPassCompatibilityId != 0) { constexpr Uint64 wireDomain = 0x5749524552504b59ull; XXHASH_VERIFY(XXH64_update(m_hashState, &wireDomain, sizeof(wireDomain))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.wireRenderPassCompatibilityId, sizeof(payload.wireRenderPassCompatibilityId))); } else -#endif { XXHASH_VERIFY(XXH64_update(m_hashState, &payload.renderPass, sizeof(payload.renderPass))); } @@ -286,12 +284,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { return VK_NULL_HANDLE; } m_cache.emplace(hash, PipelineCacheEntry{pipeline, payload.programHash, -#if MOBILEGL_BUILD_RECORD_ARM // Wire pipelines outlive their creator pass and // may serve another compatible pass in flight. // Never evict them by a recycled native handle. payload.wireRenderPassCompatibilityId != 0 ? VK_NULL_HANDLE : -#endif payload.renderPass, m_frameCounter}); return pipeline; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.h index adf69844..4823b7ee 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.h @@ -35,11 +35,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { HashType vertexInputHash = 0; VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; VkRenderPass renderPass = VK_NULL_HANDLE; -#if MOBILEGL_BUILD_RECORD_ARM // Nonzero is an exact, renderer-lifetime compatibility identity. // renderPass remains the valid creation handle, not the cache key. Uint64 wireRenderPassCompatibilityId = 0; -#endif Uint32 colorAttachmentCount = 1; VkSampleCountFlagBits rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; // glEnable(GL_SAMPLE_SHADING) + glMinSampleShading, which Vulkan bakes into the diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp index edd81f49..580b292e 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp @@ -3199,11 +3199,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { if (descriptorKind == DescriptorBindingKind::StorageBuffer) { const GLuint blockIndex = -#if MOBILEGL_BUILD_RECORD_ARM program.GetShaderStorageBlockIndex(uniformName); -#else - GetShaderStorageBlockIndex(program, uniformName); -#endif if (blockIndex == GL_INVALID_INDEX) { MGLOG_D("ProgramFactory::ReflectLayout: skipping inactive SSBO '%s' at binding %u", uniformName.c_str(), binding); @@ -3495,13 +3491,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { updateAfterBindSampledImages + updateAfterBindStorageImages; const auto& uab = m_updateAfterBindLimits; entry.usesUpdateAfterBind = -#if MOBILEGL_BUILD_RECORD_ARM // Vulkan forbids ANY update-after-bind binding in a set layout that // contains a dynamic buffer descriptor (VUID 03001/03011). Wire draws // retain UniformManager's per-frame, content-versioned descriptor sets; // this selects the legal ordinary pool, not in-place mutation of a live set. (!program.IsWire() || entry.dynamicBindings.empty()) && -#endif uab.enabled && updateAfterBindSamplers <= uab.maxPerStageSamplers && updateAfterBindUniformBuffers <= uab.maxPerStageUniformBuffers && updateAfterBindStorageBuffers <= uab.maxPerStageStorageBuffers && diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/UniformManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/UniformManager.cpp index ff2bb5cb..d4c76e15 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/UniformManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/UniformManager.cpp @@ -28,13 +28,11 @@ #include "MG_Util/Metrics/TextureMetrics.h" #include "MG_Util/ShaderTranspiler/Types.h" #include -#if MOBILEGL_BUILD_RECORD_ARM #include // P7 wave 0: the seam WireDescriptorFatal dies through. See MG_Pipe/PipeSessionFail.h. #include // P7 wave 2 package B3: rule I's tally for this file's silent wire-draw exits. #include "WireDeclineTally.h" -#endif #include #include #include @@ -43,7 +41,6 @@ #include namespace MobileGL::MG_Backend::DirectVulkan { -#if MOBILEGL_BUILD_RECORD_ARM SizeT UniformManager::WireImageViewKeyHash::operator()(const WireImageViewKey& key) const { SizeT hash = std::hash{}(key.image); const auto mix = [&hash](Uint64 value) { @@ -323,7 +320,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } return true; } -#endif namespace { constexpr Uint kFallbackTexture2DExternalIndex = 0xFFFFFF00u; // One id for every storage-image placeholder. They are never reachable through GL - no @@ -590,7 +586,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_bufferManager = bufferManager; m_programFactory = programFactory; m_minDynamicOffsetAlignment = std::max(1, minUniformBufferOffsetAlignment); -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { VkPhysicalDeviceProperties properties{}; vkGetPhysicalDeviceProperties(m_physicalDevice, &properties); @@ -600,7 +595,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_wireMaxStorageRange = properties.limits.maxStorageBufferRange; m_wireMaxTexelElements = properties.limits.maxTexelBufferElements; } -#endif m_frameCount = frameCount; m_maxBindings = maxBindings; m_samplerResolveMemo.assign(m_maxBindings, SamplerResolveMemo{}); @@ -656,11 +650,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_unboundStorageImageTextures.clear(); for (auto& frame : m_frames) { if (m_device != VK_NULL_HANDLE) { -#if MOBILEGL_BUILD_RECORD_ARM frame.wireImageViewCache.clear(); for (const auto view : frame.wireImageViews) vkDestroyImageView(m_device, view, nullptr); frame.wireImageViews.clear(); -#endif for (auto& view : frame.texelBufferViews) { if (view != VK_NULL_HANDLE) { vkDestroyBufferView(m_device, view, nullptr); @@ -683,12 +675,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { frame.quietEpochs = 0; } m_frames.clear(); -#if MOBILEGL_BUILD_RECORD_ARM for (auto& entry : m_wirePlaceholderImages) DestroyWirePlaceholderImage(entry.second); m_wirePlaceholderImages.clear(); m_wirePrivateStoragePlaceholders = 0; m_wireInvalidStorageImagesBindNull = false; -#endif m_epochSlot = 0; m_epochOpen = false; @@ -712,12 +702,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { void UniformManager::BeginFrame(Uint32 frameIndex) { MOBILEGL_ASSERT(frameIndex < m_frames.size(), "UniformDescriptorBinder::BeginFrame invalid frame index"); auto& frame = m_frames[frameIndex]; -#if MOBILEGL_BUILD_RECORD_ARM m_wireFrameIndex = frameIndex; frame.wireImageViewCache.clear(); for (const auto view : frame.wireImageViews) vkDestroyImageView(m_device, view, nullptr); frame.wireImageViews.clear(); -#endif for (auto& view : frame.texelBufferViews) { if (view != VK_NULL_HANDLE) { vkDestroyBufferView(m_device, view, nullptr); @@ -766,7 +754,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } } -#if MOBILEGL_BUILD_RECORD_ARM Bool UniformManager::WireDescriptorSetBudgetReached(Uint32 frameIndex) const { MOBILEGL_ASSERT(frameIndex < m_frames.size(), "WireDescriptorSetBudgetReached invalid frame index"); return m_frames[frameIndex].allocatedSetsThisFrame >= kWireDescriptorSetBudget; @@ -799,7 +786,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } return cachedSets; } -#endif void UniformManager::InvalidateDescriptorSetMemos() { // Every VkDescriptorSet handle held outside the per-layout caches - in this backend they all @@ -907,9 +893,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { Uint32 binding, Uint32 element, VkDescriptorImageInfo& outImageInfo, Bool trustUnchangedHint) const { -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire()) return ResolveWireImageDescriptor(commandBuffer, program, programObj, binding, element, false, outImageInfo); -#endif MOBILEGL_ASSERT(m_textureManager != nullptr, "ResolveSamplerDescriptor: texture manager is null"); MOBILEGL_ASSERT(m_samplerManager != nullptr, "ResolveSamplerDescriptor: sampler manager is null"); // The whole-descriptor memo below is keyed by binding alone, so it describes a binding @@ -1192,9 +1176,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { Bool UniformManager::ProgramSamplesOnlySingleLevelTextures( const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj) { -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire()) return false; // Conservative optimization gate; no frontend probe. -#endif // A declined program never draws (see VkProgramObject::declinedDescriptors), and its // declined binding has no resolvable uniform location - so there is nothing to prove // about the textures it would have sampled. @@ -1305,7 +1287,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { return texture; } -#if MOBILEGL_BUILD_RECORD_ARM Bool UniformManager::ResolveWireTexelBufferDescriptor(const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj, Uint32 binding, Uint32 frameIndex, Bool storage, VkBufferView& out) { @@ -1407,16 +1388,13 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_bufferManager->MarkWireBufferGpuWritten(buffer, start, size); return true; } -#endif Bool UniformManager::ResolveTexelBufferDescriptor(const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj, Uint32 binding, Uint32 frameIndex, VkBufferView& outBufferView) { -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire()) return ResolveWireTexelBufferDescriptor(program, programObj, binding, frameIndex, false, outBufferView); -#endif outBufferView = VK_NULL_HANDLE; MOBILEGL_ASSERT(m_bufferManager != nullptr, "ResolveTexelBufferDescriptor: buffer manager is null"); MOBILEGL_ASSERT(frameIndex < m_frames.size(), "ResolveTexelBufferDescriptor: frame index out of range"); @@ -1541,10 +1519,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { const ProgramFactory::VkProgramObject& programObj, Uint32 binding, Uint32 frameIndex, VkBufferView& outBufferView) { -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire()) return ResolveWireTexelBufferDescriptor(program, programObj, binding, frameIndex, true, outBufferView); -#endif outBufferView = VK_NULL_HANDLE; MOBILEGL_ASSERT(m_bufferManager != nullptr, "ResolveStorageTexelBufferDescriptor: buffer manager is null"); MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "ResolveStorageTexelBufferDescriptor: GL context is null"); @@ -1712,18 +1688,14 @@ namespace MobileGL::MG_Backend::DirectVulkan { MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "ResolveStorageBufferDescriptor: GL context is null"); MOBILEGL_ASSERT(binding < programObj.storageBlockIndexByBinding.size(), "ResolveStorageBufferDescriptor: binding %u out of range", binding); -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire() && (binding >= programObj.storageBlockIndexByBinding.size() || binding >= programObj.storageBlockNameByBinding.size())) WireDescriptorFatal("storage-buffer-reflection-binding"); -#endif const Int blockIndex = programObj.storageBlockIndexByBinding[binding]; MOBILEGL_ASSERT(blockIndex >= 0, "ResolveStorageBufferDescriptor: no SSBO block mapped to binding %u", binding); -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire() && blockIndex < 0) WireDescriptorFatal("storage-buffer-reflection-block"); -#endif // An atomic counter is not an SSBO the application ever declared: glslang lowers every // atomic_uint onto a synthesized gl_AtomicCounterBlock_ storage block, where N is the // GL ATOMIC-COUNTER binding. That block arrives here auto-mapped to an arbitrary @@ -1753,13 +1725,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { isAtomicCounterBlock ? static_cast(atomicCounterBinding) : -#if MOBILEGL_BUILD_RECORD_ARM (program.IsWire() ? program.GetShaderStorageBlockBinding(static_cast(blockIndex)) : GetShaderStorageBlockBinding(*program.Frontend(), static_cast(blockIndex))) + element; -#else - GetShaderStorageBlockBinding(program, static_cast(blockIndex)) + element; -#endif -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire()) { const auto& state = MG_Pipe::MGPipeApplier(); const Uint32 cls = isAtomicCounterBlock ? MG_Pipe::kMGPipeShaderBufferClassAtomicCounter @@ -1835,7 +1802,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_bufferManager->MarkWireBufferGpuWritten(range.Res, start, size); return true; } -#endif const Uint32 bindingPointCount = static_cast(MG_Pipe::gPipeInputs.GetBufferBindingPointCount(bufferTarget)); MOBILEGL_ASSERT(frontendBinding < bindingPointCount, @@ -1914,9 +1880,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { const ProgramFactory::VkProgramObject& programObj, Uint32 binding, Uint32 element, VkDescriptorImageInfo& outImageInfo) const { -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire()) return ResolveWireImageDescriptor(commandBuffer, program, programObj, binding, element, true, outImageInfo); -#endif outImageInfo = {}; MOBILEGL_ASSERT(m_textureManager != nullptr, "ResolveStorageImageDescriptor: texture manager is null"); MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "ResolveStorageImageDescriptor: GL context is null"); @@ -2369,9 +2333,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { const ProgramFactory::VkProgramObject& programObj, Vector& outTextures, Vector* outBindingRecords) { -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire()) { outTextures.clear(); if (outBindingRecords) outBindingRecords->clear(); return true; } -#endif outTextures.clear(); if (outBindingRecords != nullptr) { outBindingRecords->clear(); @@ -2418,9 +2380,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { Bool UniformManager::SampledBindingsUnchanged(const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj, const Vector& previousRecords) const { -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire()) return false; -#endif // A declined program takes the full path every time and is refused there. if (programObj.declinedDescriptors) { return false; @@ -2464,9 +2424,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj, Vector& outTextures) const { -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire()) { outTextures.clear(); return true; } -#endif outTextures.clear(); MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "CollectStorageImageTextures: GL context is null"); @@ -2549,9 +2507,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj, Vector& outBindings) const { -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire()) { outBindings.clear(); return true; } -#endif outBindings.clear(); MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "CollectSamplerImageFeedback: GL context is null"); @@ -2627,7 +2583,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { return true; } -#if MOBILEGL_BUILD_RECORD_ARM Bool UniformManager::ResolveWireUniformBufferPayload(const MagmaProgramSource& program, Uint32 blockIndex, Uint32 bindingPoint, UboBindResult& out) const { if (bindingPoint >= MG_Pipe::kMGPipeMaxBufferBindingPoints) @@ -2722,7 +2677,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { out.dynamicOffset = padded.offset; return true; } -#endif Bool UniformManager::ResolveUniformBufferPayload(const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj, Uint32 binding, @@ -2752,10 +2706,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { MOBILEGL_ASSERT(binding < programObj.uniformBlockIndexByBinding.size(), "ResolveUniformBufferPayload: UBO mapping binding %u out of range", binding); -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire() && binding >= programObj.uniformBlockIndexByBinding.size()) WireDescriptorFatal("uniform-buffer-reflection-binding"); -#endif Int blockIndex = programObj.uniformBlockIndexByBinding[binding]; if (arrayElement > 0) { const auto arrayIt = programObj.arrayedUniformBlockIndicesByBinding.find(binding); @@ -2776,16 +2728,12 @@ namespace MobileGL::MG_Backend::DirectVulkan { MOBILEGL_ASSERT(static_cast(blockIndex) < activeUniformBlockCount, "ResolveUniformBufferPayload: uniform block index %d out of range (count=%u)", blockIndex, activeUniformBlockCount); -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire() && (blockIndex < 0 || static_cast(blockIndex) >= activeUniformBlockCount)) WireDescriptorFatal("uniform-buffer-reflection-block"); -#endif const Uint32 frontendBinding = program.GetUniformBlockBinding(static_cast(blockIndex)); -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire()) return ResolveWireUniformBufferPayload(program, static_cast(blockIndex), frontendBinding, out); -#endif const Uint32 uniformBindingPointCount = static_cast(MG_Pipe::gPipeInputs.GetBufferBindingPointCount(BufferTarget::Uniform)); MOBILEGL_ASSERT(frontendBinding < uniformBindingPointCount, @@ -3059,9 +3007,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { Uint32& outDynamicOffset) { UboBindResult ubo{}; const Bool hasPayload = ResolveUniformBufferPayload(program, programObj, binding, arrayElement, ubo); -#if MOBILEGL_BUILD_RECORD_ARM if (program.IsWire() && !hasPayload) return false; -#endif MOBILEGL_ASSERT(hasPayload && (ubo.directBindable || (ubo.payload != nullptr && ubo.payloadSize > 0)), "UniformDescriptorBinder::ResolveDynamicUboDescriptor failed: missing UBO payload on binding %u element %u", binding, arrayElement); @@ -3150,7 +3096,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } } -#if MOBILEGL_BUILD_RECORD_ARM Bool UniformManager::PrepareWireTextureResources(const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj) { if (!program.IsWire()) return true; @@ -3204,7 +3149,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_textureManager->FlushPendingUploads(); return true; } -#endif Bool UniformManager::BindProgramUniformBuffers(VkCommandBuffer commandBuffer, const MagmaProgramSource& program, @@ -3244,12 +3188,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { (samplerBindingOverrides == nullptr || samplerBindingOverrides->empty()); if (cacheable && samplerDescriptorsUnchangedHint && m_fastRebindMemo.valid && m_fastRebindMemo.frameIndex == frameIndex && -#if MOBILEGL_BUILD_RECORD_ARM // A wire store destroyed since the memo was taken may have handed its handle // value to a later mint (see FastRebindMemo): "same VkBuffer" then names a // different store, so the memo is refused and the full walk re-records it. m_fastRebindMemo.wireStoreDestroyEpoch == m_bufferManager->GetWireStoreDestroyEpoch() && -#endif m_fastRebindMemo.programLifetimeId == program.GetLifetimeId() && m_fastRebindMemo.programHash == programObj.hash) { VkBuffer uboBuffer = VK_NULL_HANDLE; @@ -3546,7 +3488,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } }; mixWords(&programObj.descriptorSetLayout, sizeof(programObj.descriptorSetLayout)); -#if MOBILEGL_BUILD_RECORD_ARM // P7 M2 round 2 (ID-P7-43): the buffer infos below name WIRE stores by VkBuffer // handle, and a wire store can be destroyed mid-frame (VkBufferManager:: // DeferredWireRelease) with its handle value re-minted before this frame's memo @@ -3555,7 +3496,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // store. NOT the slice epoch: that moves on every glBufferSubData and would make // the memo miss on every draw. mix64(m_bufferManager->GetWireStoreDestroyEpoch()); -#endif for (const auto& write : writes) { mix64((static_cast(write.dstBinding) << 40) ^ (static_cast(write.descriptorType) << 8) ^ @@ -3611,9 +3551,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { /*valid=*/true, frameIndex, program.GetLifetimeId(), programObj.hash, fastRebindUboBinding, bufferInfos[0].buffer, bufferInfos[0].range, descriptorSet, -#if MOBILEGL_BUILD_RECORD_ARM m_bufferManager->GetWireStoreDestroyEpoch(), -#endif }; } else { m_fastRebindMemo.valid = false; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/UniformManager.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/UniformManager.h index 63abf4eb..385ba98d 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/UniformManager.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/UniformManager.h @@ -56,7 +56,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { void Shutdown(); void BeginFrame(Uint32 frameIndex); -#if MOBILEGL_BUILD_RECORD_ARM // A present-less wire frame may run arbitrarily many draws. Before its // descriptor cursor reaches this budget, the renderer retires the // submission that last used the sets and rewinds every layout cursor. @@ -74,7 +73,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // store inside one pass reading zero, nor privacy past kWirePrivateStoragePlaceholderCap // placeholders (CONTRACT-P7 §12). Called after Initialize. void SetWireInvalidStorageImageArm(Bool deviceNullDescriptor); -#endif // A command buffer (re)began recording: descriptor bindings recorded into // the previous buffer do not carry over, so drop the bind-dedup shadow. void OnCommandBufferBoundary() { m_lastBindValid = false; } @@ -123,13 +121,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { Vector& outBindings) const; static Bool SamplerOverlapsWritableImageSubresource(Int samplerBaseLevel, Int samplerMaxLevel, GLint imageLevel, GLenum imageAccess); -#if MOBILEGL_BUILD_RECORD_ARM // Resolve lazy texture uploads/promotions before the caller captures the // command buffer passed to BindProgramUniformBuffers. Preparation may // submit older work, but descriptor recording must never rotate it. Bool PrepareWireTextureResources(const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj); -#endif // samplerDescriptorsUnchangedHint: the caller (SetupDraw fast path) proved that // every input of every combined-image-sampler resolution is unchanged since the // previous draw's resolve - same (texture, sampler) per binding, texture params @@ -215,7 +211,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { Uint32 cursor = 0; }; -#if MOBILEGL_BUILD_RECORD_ARM // ResolveWireImageDescriptor emits no pNext chain. Key every view-create // value explicitly: hash collisions must never alias different windows, // formats or swizzles. The root handle and allocation epoch also prevent @@ -273,7 +268,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { const ProgramFactory::VkProgramObject& programObj, Uint32 binding, Bool storage, VkDescriptorImageInfo& out, VkFormat boundStorageFormat = VK_FORMAT_UNDEFINED, Uint32 unit = ~0u) const; void DestroyWirePlaceholderImage(WirePlaceholderImage& image) const; -#endif // descriptorSetCacheByLayout is the per-frame set cache: BeginFrame rewinds every cursor, so // a slot re-writes the sets it allocated in earlier frames instead of allocating new ones, and @@ -283,12 +277,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { Vector descriptorPools; UnorderedMap descriptorSetCacheByLayout; Vector texelBufferViews; -#if MOBILEGL_BUILD_RECORD_ARM mutable Vector wireImageViews; // Own views in the vector above until this slot's fence/idle proof. // Cache hits preserve the handle, enabling descriptor-content reuse. mutable UnorderedMap wireImageViewCache; -#endif Uint32 activeDescriptorPoolIndex = 0; Uint32 allocatedSetsThisFrame = 0; Uint32 peakAllocatedSetsThisFrame = 0; @@ -366,7 +358,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { const ProgramFactory::VkProgramObject& programObj, Uint32 binding, Uint32 element, VkDescriptorImageInfo& outImageInfo, Bool trustUnchangedHint = false) const; -#if MOBILEGL_BUILD_RECORD_ARM Bool ResolveWireImageDescriptor(VkCommandBuffer commandBuffer, const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj, Uint32 binding, Uint32 element, Bool storage, VkDescriptorImageInfo& out) const; @@ -379,7 +370,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkDeviceSize m_wireMaxUniformRange = ~VkDeviceSize{0}; VkDeviceSize m_wireMaxStorageRange = ~VkDeviceSize{0}; Uint32 m_wireMaxTexelElements = ~Uint32{0}; -#endif Bool ResolveSamplerDescriptorOverride(const SamplerBindingOverride& samplerBindingOverride, VkDescriptorImageInfo& outImageInfo) const; Bool ResolveTexelBufferDescriptor(const MagmaProgramSource& program, @@ -415,10 +405,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { const void* payload = nullptr; // fallback UploadTransient path VkDeviceSize payloadSize = 0; }; -#if MOBILEGL_BUILD_RECORD_ARM Bool ResolveWireUniformBufferPayload(const MagmaProgramSource& program, Uint32 blockIndex, Uint32 bindingPoint, UboBindResult& out) const; -#endif Bool ResolveUniformBufferPayload(const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj, Uint32 binding, Uint32 arrayElement, UboBindResult& out) const; @@ -563,9 +551,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkBuffer uboBuffer = VK_NULL_HANDLE; VkDeviceSize uboRange = 0; VkDescriptorSet set = VK_NULL_HANDLE; -#if MOBILEGL_BUILD_RECORD_ARM Uint64 wireStoreDestroyEpoch = 0; -#endif }; FastRebindMemo m_fastRebindMemo; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp index 4a2faf50..bac5bf21 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp @@ -394,7 +394,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { return entry; } -#if MOBILEGL_BUILD_RECORD_ARM Bool VertexInputStateFactory::BuildWireVertexInput(const MG_Pipe::MGPipeVertexElementsRecord& elements, const MG_Pipe::MGPipeApplierState& state, Uint32 activeMask, BackendVertexInputState& out) const { out = BackendVertexInputState{}; @@ -532,7 +531,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } return true; } -#endif void VertexInputStateFactory::OnFrameBoundary() { ++m_frameBoundaryCounter; @@ -802,7 +800,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { if (m_physicalDevice == VK_NULL_HANDLE || format == VK_FORMAT_UNDEFINED) { return false; } -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const auto found = m_wireVertexFormatSupport.find(format); if (found != m_wireVertexFormatSupport.end()) return found->second; @@ -812,7 +809,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_wireVertexFormatSupport.emplace(format, supported); return supported; } -#endif VkFormatProperties properties{}; vkGetPhysicalDeviceFormatProperties(m_physicalDevice, format, &properties); return (properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.h index 619b942d..0b29ad2a 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.h @@ -10,9 +10,7 @@ // MG_Pipe::MGPipeHandle for the P2 D12.5 memo table below. A header of constexpr constants, // so the pull build gains nothing from it. #include -#if MOBILEGL_BUILD_RECORD_ARM #include -#endif #include "Config.h" #include "MagmaPipeArms.h" @@ -122,13 +120,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { // normal types, and 4 (one packed word) for the 2_10_10_10 types and GL_BGRA. Returns 0 for // an unknown/unsupported type. static SizeT GetAttributeByteSize(DataType type, Int size, Bool isBgra); -#if MOBILEGL_BUILD_RECORD_ARM // A wire VAO is a layout record plus a separate per-attribute buffer window. // No frontend VAO identity, address or memo participates in this layout. Bool BuildWireVertexInput(const MG_Pipe::MGPipeVertexElementsRecord& elements, const MG_Pipe::MGPipeApplierState& state, Uint32 activeMask, BackendVertexInputState& out) const; -#endif private: static VkFormat ToVkVertexFormat(DataType type, Int size, Bool normalized, Bool isInteger, Bool isBgra = false, @@ -175,11 +171,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { const VulkanRendererConfig& m_config; VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE; -#if MOBILEGL_BUILD_RECORD_ARM // Physical-device format capabilities never change during this factory's // lifetime. The wire path rebuilds layouts without the legacy VAO memo. mutable UnorderedMap m_wireVertexFormatSupport; -#endif // Values are heap-allocated: UnorderedMap is open-addressing, so INSERT // invalidates references to stored values - and so does ERASE, which shifts // the rest of the probe cluster into the hole and therefore moves entries diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferManager.cpp index c57a280c..7b49956a 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferManager.cpp @@ -12,7 +12,6 @@ #include "VulkanRenderer.h" #include "MG_Util/Metrics/PipeStats.h" -#if MOBILEGL_BUILD_RECORD_ARM #include "MG_Pipe/MGPipeCallbacks.h" #include "MG_Pipe/PipeApply.h" #include @@ -25,11 +24,9 @@ #include #include #include -#endif namespace MobileGL::MG_Backend::DirectVulkan { namespace { -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 2 package B3, INVESTIGATION PROBE (split-only, read once, not in // ConfigLoader's accepted-env table - package B's MGITEST_MAGMA_FORCE_SHADER_MIPMAP // shape). MOBILEGL_MAGMA_WIREBUF_PROBE=1 prints one line per streamed-buffer event so @@ -74,7 +71,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // Counts only the writes the busy predicate wanted to ORDER, so the selector indexes // the streamed subdata -> draw pairs and nothing else. Uint64 g_orderedWireWriteCounter = 0; -#endif constexpr VmaAllocationCreateFlags kResidentBufferAllocationFlags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; constexpr SizeT kLiveResourcePruneThreshold = 256; @@ -181,7 +177,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { .ReadbackFromGpu = Ops_ReadbackFromGpu, }; -#if MOBILEGL_BUILD_RECORD_ARM // The session's manager, or null once its renderer is gone - a client's records can still // arrive after its eglTerminate released it (or, surfaceless, before its first surface built // one). Such a record is declined with one line rather than taking the whole server down. @@ -237,10 +232,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { }, #endif }; -#endif } // namespace -#if MOBILEGL_BUILD_RECORD_ARM void VkBufferManager::RegisterWireResourceOps() { if (MG_Config::DataArmIsRecord()) { MG_Pipe::MGPipeSetResourceOps(&g_vulkanWireResourceOps); @@ -1208,7 +1201,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_deferredWireReleases.clear(); m_deferredWireBytes = 0; } -#endif Bool VkBufferManager::Initialize(const VkBufferManagerInitInfo& initInfo) { Shutdown(); @@ -1227,16 +1219,13 @@ namespace MobileGL::MG_Backend::DirectVulkan { } g_activeBufferManager.Get() = this; MG_State::GLState::SetBufferBackendOps(&g_vulkanBufferBackendOps); -#if MOBILEGL_BUILD_RECORD_ARM RegisterWireResourceOps(); -#endif return true; } void VkBufferManager::Shutdown() { if (g_activeBufferManager.Get() == this) { g_activeBufferManager.Get() = nullptr; -#if MOBILEGL_BUILD_RECORD_ARM // Under a transport the table is the PROCESS's and serves every session: it dispatches // to the calling session's own manager (WireManager), so one session's renderer going // away must not take it from the others - their buffer creates would be dropped from @@ -1245,7 +1234,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { MG_Pipe::MGPipeGetResourceOps() == &g_vulkanWireResourceOps) { MG_Pipe::MGPipeSetResourceOps(nullptr); } -#endif if (MG_State::GLState::GetBufferBackendOps() == &g_vulkanBufferBackendOps) { MG_State::GLState::SetBufferBackendOps(nullptr); } @@ -1255,7 +1243,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_unboundTexelBuffer.Destroy(); DestroyAllDeferredReleases(); ReleaseAllLiveResources(); -#if MOBILEGL_BUILD_RECORD_ARM // DestroyAllDeferredReleases above emptied the parked list; this destroys the stores the // records still hold, so nothing this arm minted outlives the count. if (!m_wireBuffers.empty()) ++m_wireStoreDestroyEpoch; @@ -1264,7 +1251,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_wireStoreCountPeak = 0; m_deferredWireBytesPeak = 0; m_wireDeferredSyncs = 0; -#endif m_copyProvider = nullptr; m_initInfo = {}; m_currentFrameIndex = 0; @@ -1293,13 +1279,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { "VkBufferManager::BeginFrame frame index out of range"); m_currentFrameIndex = frameIndex; ++m_frameSerial; -#if MOBILEGL_BUILD_RECORD_ARM if (WireBufProbeEnabled()) { MGLOG_I("WBUF BEGINFRAME idx=%u newSerial=%llu floor=%llu (arena slot rewound)", frameIndex, static_cast(m_frameSerial), static_cast(m_completedSerialFloor)); } -#endif CollectDeferredReleases(frameIndex); m_transientUploadArena.BeginFrame(frameIndex); } @@ -1399,9 +1383,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { .frameCount = m_initInfo.frameCount, .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | -#if MOBILEGL_BUILD_RECORD_ARM (MG_Config::DataArmIsRecord() ? VkBufferUsageFlags{VK_BUFFER_USAGE_TRANSFER_DST_BIT} : 0u) | -#endif VK_BUFFER_USAGE_TRANSFER_SRC_BIT, .memoryUsage = m_initInfo.transientMemoryUsage, .allocationFlags = m_initInfo.transientAllocationFlags, @@ -1557,7 +1539,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { return true; } -#if MOBILEGL_BUILD_RECORD_ARM Bool VkBufferManager::StagedWireRangeCopy(WireBufferResource& resource, const void* data, SizeT offset, SizeT size) { if (!m_copyProvider) { @@ -1610,7 +1591,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { return true; } -#endif void VkBufferManager::OnRespecify(MG_State::GLState::BufferObject& bufferObject) { auto* resource = ResourceOf(bufferObject); @@ -1987,12 +1967,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { "VkBufferManager::CollectDeferredReleases frame index out of range"); m_deferredBufferReleases[frameIndex].clear(); m_deferredResourceReleases[frameIndex].clear(); -#if MOBILEGL_BUILD_RECORD_ARM // The wire list is not per-slot and does not wait for a frame boundary; a boundary is // just one more point to sweep at (BeginFrame after its slot fence, and every slot of // the idle drain, where the renderer-idle rule empties the list). SweepDeferredWireReleases(); -#endif } BufferSlice VkBufferManager::AcquireUnboundStorageDescriptor() { @@ -2088,10 +2066,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void VkBufferManager::DestroyAllDeferredReleases() { -#if MOBILEGL_BUILD_RECORD_ARM // Both callers (Shutdown, RecreateTransientArenas) have proven the device idle. DestroyAllDeferredWireReleases(); -#endif for (auto& releases : m_deferredBufferReleases) { for (auto& buffer : releases) { buffer.Destroy(); diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferManager.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferManager.h index 32ad2b23..89b2aed0 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferManager.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferManager.h @@ -13,10 +13,8 @@ #include "../VkIncludes.h" #include #include -#if MOBILEGL_BUILD_RECORD_ARM #include "MG_Pipe/MGPipeTypes.h" #include -#endif namespace MobileGL::MG_Backend::DirectVulkan { enum class BufferKind : Uint8 { @@ -103,7 +101,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { Bool Initialize(const VkBufferManagerInitInfo& initInfo); void Shutdown(); -#if MOBILEGL_BUILD_RECORD_ARM // Registered before caps publication; the initialized renderer owns the storage. static void RegisterWireResourceOps(); // Transport resources are owned by their complete wire handle, never by a @@ -158,7 +155,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { void* DonateWireBuffer(MG_Pipe::MGPipeHandle res, Uint64 size, const void* seedBytes); // The POST self-test of the sustained-lock pattern on this device (see the definition). static Bool SelfTestWireImport(char* why, Uint64 whyBytes); -#endif // Recreate all per-frame transient arenas Bool RecreateTransientArenas(Uint32 frameCount); @@ -232,13 +228,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { // back, and none was persistently mapped, in between - so a memo of resolved // slices needs no per-buffer re-check. See AcquirePersistentMap for the mapping half. Uint64 GetSliceEpochCounter() const { return m_sliceEpochCounter; } -#if MOBILEGL_BUILD_RECORD_ARM // Bumped every time this manager destroys a WIRE store's VkBuffer (see // m_wireStoreDestroyEpoch). Unchanged since a memo was taken means no VkBuffer handle // that memo names can have been freed and re-minted in between, which is the one // fact a handle-keyed memo of wire descriptors needs and cannot read off the handle. Uint64 GetWireStoreDestroyEpoch() const { return m_wireStoreDestroyEpoch; } -#endif // Highest frame serial whose GPU work is known complete; serials at or // below it may be considered signaled. Drives IsResourceBusy and the // backend GL fence objects. @@ -254,7 +248,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { void DeferRelease(VkBufferObject&& buffer); private: -#if MOBILEGL_BUILD_RECORD_ARM struct WireBufferResource { VkBufferObject buffer; Uint64 size = 0; @@ -374,7 +367,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // the stats channel is on; MagmaWireReclaimScenario reads them off the server's line. void NoteWireStorePeaks(); void PublishWireReclaimGauges(); -#endif Bool InitializeTransientArenas(); static VkBufferUsageFlags GetVkBufferUsage(BufferKind kind); VkBufferResource* GetOrCreateResource(const SharedPtr& bufferObject); @@ -387,9 +379,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { // in-flight and already-recorded GPU work. Bool StagedRangeCopy(VkBufferResource& resource, const void* data, SizeT offset, SizeT size); -#if MOBILEGL_BUILD_RECORD_ARM Bool StagedWireRangeCopy(WireBufferResource& resource, const void* data, SizeT offset, SizeT size); -#endif void CollectDeferredReleases(Uint32 frameIndex); void DestroyAllDeferredReleases(); void TrackLiveResource(const SharedPtr& resource); @@ -408,7 +398,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { Vector> m_deferredBufferReleases; Vector>> m_deferredResourceReleases; Vector> m_liveResources; -#if MOBILEGL_BUILD_RECORD_ARM std::unordered_map m_wireBuffers; // See DeferredWireRelease. ONE FLAT LIST rather than the per-frame-slot buckets above: // the whole point is that these entries do not wait for a frame slot to come round. @@ -427,7 +416,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // for m_sliceEpochCounter's reason: a memo taken before a re-initialize must not match // a handle minted after it. Uint64 m_wireStoreDestroyEpoch = 0; -#endif // Size m_liveResources had just after the last sweep; the next sweep waits for it to double. SizeT m_liveResourcesLastPruned = 0; Uint32 m_currentFrameIndex = 0; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp index b166bc69..369e7460 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp @@ -13,7 +13,6 @@ #endif namespace MobileGL::MG_Backend::DirectVulkan { -#if MOBILEGL_BUILD_RECORD_ARM void VkBufferObject::MoveExternalFrom(VkBufferObject& other) { m_device = other.m_device; m_externalMemory = other.m_externalMemory; @@ -36,7 +35,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_externalCoherent = coherent; m_externalAhb = ahb; } -#endif VkBufferObject::VkBufferObject(VkBufferObject&& other) noexcept { m_allocator = other.m_allocator; @@ -44,9 +42,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_allocation = other.m_allocation; m_mappedData = other.m_mappedData; m_size = other.m_size; -#if MOBILEGL_BUILD_RECORD_ARM MoveExternalFrom(other); -#endif other.m_allocator = nullptr; other.m_buffer = VK_NULL_HANDLE; @@ -67,9 +63,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_allocation = other.m_allocation; m_mappedData = other.m_mappedData; m_size = other.m_size; -#if MOBILEGL_BUILD_RECORD_ARM MoveExternalFrom(other); -#endif other.m_allocator = nullptr; other.m_buffer = VK_NULL_HANDLE; @@ -170,10 +164,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void VkBufferObject::Unmap() { -#if MOBILEGL_BUILD_RECORD_ARM // An imported store stays mapped for its life (Destroy unmaps it). if (m_externalMemory != VK_NULL_HANDLE) return; -#endif if (!IsValid() || m_mappedData == nullptr) { m_mappedData = nullptr; return; @@ -200,7 +192,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } Memcpy(static_cast(mapped) + offset, data, static_cast(size)); -#if MOBILEGL_BUILD_RECORD_ARM if (m_externalMemory != VK_NULL_HANDLE) { if (m_externalCoherent) return true; VkMappedMemoryRange range{VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE}; @@ -209,7 +200,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { range.size = VK_WHOLE_SIZE; return vkFlushMappedMemoryRanges(m_device, 1, &range) == VK_SUCCESS; } -#endif const VkResult flushResult = vmaFlushAllocation(m_allocator, m_allocation, offset, size); if (flushResult != VK_SUCCESS) { MGLOG_E_ONCE("VkBufferObject::Upload failed: vmaFlushAllocation returned %d", flushResult); @@ -234,7 +224,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { if (resolvedSize == 0) { return true; } -#if MOBILEGL_BUILD_RECORD_ARM if (m_externalMemory != VK_NULL_HANDLE) { if (m_externalCoherent) return true; VkMappedMemoryRange range{VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE}; @@ -243,7 +232,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { range.size = VK_WHOLE_SIZE; return vkInvalidateMappedMemoryRanges(m_device, 1, &range) == VK_SUCCESS; } -#endif const VkResult result = vmaInvalidateAllocation(m_allocator, m_allocation, offset, resolvedSize); if (result != VK_SUCCESS) { diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.h index e8a6291f..73cca2c7 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.h @@ -65,13 +65,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { void* GetMappedData() const { return m_mappedData; } Bool IsMapped() const { return m_mappedData != nullptr; } Bool IsValid() const { -#if MOBILEGL_BUILD_RECORD_ARM if (m_externalMemory != VK_NULL_HANDLE) return m_buffer != VK_NULL_HANDLE; -#endif return m_allocator != nullptr && m_buffer != VK_NULL_HANDLE && m_allocation != nullptr; } -#if MOBILEGL_BUILD_RECORD_ARM // P11 B2 (T0): a store whose memory is NOT this allocator's - a client's AHardwareBuffer // imported with VK_ANDROID_external_memory_android_hardware_buffer into `memory` (a // dedicated allocation bound to `buffer`, mapped persistently at `mapped`). It behaves @@ -82,7 +79,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { void AdoptExternal(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize size, void* mapped, Bool coherent, void* ahb); Bool IsExternal() const { return m_externalMemory != VK_NULL_HANDLE; } -#endif private: VmaAllocator m_allocator = nullptr; @@ -90,12 +86,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { VmaAllocation m_allocation = nullptr; void* m_mappedData = nullptr; VkDeviceSize m_size = 0; -#if MOBILEGL_BUILD_RECORD_ARM VkDevice m_device = VK_NULL_HANDLE; VkDeviceMemory m_externalMemory = VK_NULL_HANDLE; void* m_externalAhb = nullptr; Bool m_externalCoherent = true; void MoveExternalFrom(VkBufferObject& other); -#endif }; } // namespace MobileGL::MG_Backend::DirectVulkan diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.cpp index 0e793b7a..784a1757 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.cpp @@ -15,7 +15,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { namespace { -#if MOBILEGL_BUILD_RECORD_ARM // An accessor view over the wire's POD values, not a GL object with constructor, // lifetime ID, allocator hooks or mutation callbacks. Both sources below use // one sampler policy, including format-sensitive border-color conversion. @@ -43,9 +42,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { template Bool UsesBorderColor(const SamplerSource& sampler) { -#else - Bool UsesBorderColor(const MG_State::GLState::SamplerObject& sampler) { -#endif return sampler.GetWrapS() == SamplerWrapMode::ClampToBorder || sampler.GetWrapT() == SamplerWrapMode::ClampToBorder || sampler.GetWrapR() == SamplerWrapMode::ClampToBorder; @@ -221,24 +217,16 @@ namespace MobileGL::MG_Backend::DirectVulkan { return std::fabs(lhs - rhs) <= 1e-6f; } -#if MOBILEGL_BUILD_RECORD_ARM template Float ResolveEffectiveMaxLod(const SamplerSource& sampler) { -#else - Float ResolveEffectiveMaxLod(const MG_State::GLState::SamplerObject& sampler) { -#endif if (sampler.GetMipmapMode() == SamplerMipmapMode::None) { return 0.0f; } return sampler.GetMaxLod(); } -#if MOBILEGL_BUILD_RECORD_ARM template Float ResolveEffectiveMinLod(const SamplerSource& sampler, Float effectiveMaxLod) { -#else - Float ResolveEffectiveMinLod(const MG_State::GLState::SamplerObject& sampler, Float effectiveMaxLod) { -#endif return std::min(sampler.GetMinLod(), effectiveMaxLod); } @@ -249,12 +237,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { // GL's non-mipmapped minification - large enough for lambda to stay positive, small enough // that a NEAREST mip mode still rounds down to level 0. Clamped rather than assigned, so a // texture whose GL_TEXTURE_MAX_LOD really is 0 keeps magnifying as GL says it must. -#if MOBILEGL_BUILD_RECORD_ARM template Float ResolveSingleLevelMaxLod(const SamplerSource& sampler, Bool singleLevelView) { -#else - Float ResolveSingleLevelMaxLod(const MG_State::GLState::SamplerObject& sampler, Bool singleLevelView) { -#endif const Float maxLod = ResolveEffectiveMaxLod(sampler); return singleLevelView ? std::min(maxLod, 0.25f) : maxLod; } @@ -275,12 +259,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { return true; } -#if MOBILEGL_BUILD_RECORD_ARM template Float VkSamplerManager::ResolveEffectiveMaxAnisotropy(const SamplerSource& sampler, -#else - Float VkSamplerManager::ResolveEffectiveMaxAnisotropy(const MG_State::GLState::SamplerObject& sampler, -#endif Bool forceNearestFiltering) const { if (!m_samplerAnisotropySupported) return 1.0f; if (forceNearestFiltering) return 1.0f; @@ -339,12 +319,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { } } -#if MOBILEGL_BUILD_RECORD_ARM template Uint64 VkSamplerManager::BuildSamplerKey(const SamplerSource& sampler, -#else - Uint64 VkSamplerManager::BuildSamplerKey(const MG_State::GLState::SamplerObject& sampler, -#endif Bool forceNearestFiltering, Bool singleLevelView, const ResolvedBorderColor& borderColor) const { MOBILEGL_ASSERT(m_config != nullptr, "VkSamplerManager::BuildSamplerKey: m_config is null"); @@ -390,14 +366,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { return XXH64_digest(m_hashState); } -#if MOBILEGL_BUILD_RECORD_ARM template VkSampler VkSamplerManager::GetOrCreateSamplerImpl(const SamplerSource& sampler, TextureInternalFormat format, -#else - VkSampler VkSamplerManager::GetOrCreateSampler(const MG_State::GLState::SamplerObject& sampler, - const MG_State::GLState::ITextureObject& texture, -#endif Bool forceNearestFiltering, Uint32 viewLevelCount) { // A view that exposes a single mip level has no second level to blend with, so GL's // *_MIPMAP_* minification filters degenerate to plain filtering on the base level - @@ -409,11 +380,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { // the default-framebuffer blit shader had to work around with an explicit-LOD sample. const Bool singleLevelView = viewLevelCount == 1; // Resolved once and used for both the key and the create-info; see ResolvedBorderColor. -#if MOBILEGL_BUILD_RECORD_ARM const ResolvedBorderColor borderColor = ResolveBorderColor(sampler, format); -#else - const ResolvedBorderColor borderColor = ResolveBorderColor(sampler, texture); -#endif const Uint64 key = BuildSamplerKey(sampler, forceNearestFiltering, singleLevelView, borderColor); auto it = m_samplers.find(key); if (it != m_samplers.end()) { @@ -473,7 +440,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { return vkSampler; } -#if MOBILEGL_BUILD_RECORD_ARM VkSampler VkSamplerManager::GetOrCreateSampler(const MG_State::GLState::SamplerObject& sampler, const MG_State::GLState::ITextureObject& texture, Bool forceNearestFiltering, Uint32 viewLevelCount) { @@ -485,7 +451,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { return GetOrCreateSamplerImpl(SamplerParametersSource{parameters}, format, forceNearestFiltering, viewLevelCount); } -#endif VkFilter VkSamplerManager::ToVkFilter(SamplerFilterMode mode) { return mode == SamplerFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR; @@ -542,14 +507,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { } } -#if MOBILEGL_BUILD_RECORD_ARM template VkSamplerManager::ResolvedBorderColor VkSamplerManager::ResolveBorderColor( const SamplerSource& sampler, TextureInternalFormat format) const { -#else - VkSamplerManager::ResolvedBorderColor VkSamplerManager::ResolveBorderColor( - const MG_State::GLState::SamplerObject& sampler, const MG_State::GLState::ITextureObject& texture) const { -#endif ResolvedBorderColor resolved{}; if (!UsesBorderColor(sampler)) { return resolved; // FLOAT_TRANSPARENT_BLACK, never sampled @@ -557,9 +517,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // Border colour is sampler state: a bound sampler object supplies its own, and a texture // with none reaches the very same value through the sampler object it owns. -#if !MOBILEGL_BUILD_RECORD_ARM - const auto format = texture.GetFormat(); -#endif const auto domain = ResolveBorderColorDomain(format); const Bool canUseCustom = m_customBorderColorSupported && m_maxCustomBorderColorSamplers > 0 && m_customBorderColorSamplerCount < m_maxCustomBorderColorSamplers; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.h index 7b46aaaa..e0870255 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.h @@ -46,12 +46,10 @@ public: const MG_State::GLState::ITextureObject& texture, Bool forceNearestFiltering = false, Uint32 viewLevelCount = 0); -#if MOBILEGL_BUILD_RECORD_ARM // The applier owns these values: effective bound/builtin sampler parameters and // the sampled texture view's format/range. No frontend object is constructed. VkSampler GetOrCreateSamplerFromParameters(const SamplerParameters& parameters, TextureInternalFormat format, Bool forceNearestFiltering = false, Uint32 viewLevelCount = 0); -#endif // Frame boundary hook: ages the sampler cache and destroys samplers not used // for many frames. The key hashes continuous float state (lodBias, LOD clamps, // anisotropy), so an app animating those would otherwise mint an unbounded @@ -92,37 +90,24 @@ private: Bool usesCustomBorderColor = false; }; -#if MOBILEGL_BUILD_RECORD_ARM template VkSampler GetOrCreateSamplerImpl(const SamplerSource& sampler, TextureInternalFormat format, Bool forceNearestFiltering, Uint32 viewLevelCount); template Uint64 BuildSamplerKey(const SamplerSource& sampler, Bool forceNearestFiltering, -#else - Uint64 BuildSamplerKey(const MG_State::GLState::SamplerObject& sampler, Bool forceNearestFiltering, -#endif Bool singleLevelView, const ResolvedBorderColor& borderColor) const; static VkFilter ToVkFilter(SamplerFilterMode mode); static VkSamplerMipmapMode ToVkMipmapMode(SamplerMipmapMode mode); static VkSamplerAddressMode ToVkAddressMode(SamplerWrapMode mode); static VkCompareOp ToVkCompareOp(SamplerCompareFunc func); -#if MOBILEGL_BUILD_RECORD_ARM template ResolvedBorderColor ResolveBorderColor(const SamplerSource& sampler, TextureInternalFormat format) const; -#else - ResolvedBorderColor ResolveBorderColor(const MG_State::GLState::SamplerObject& sampler, - const MG_State::GLState::ITextureObject& texture) const; -#endif // The anisotropy Vulkan will actually apply: 1.0 (i.e. disabled) unless the feature is on and // the sampler filters linearly both ways, otherwise the GL request clamped to the device limit. // GL happily carries GL_TEXTURE_MAX_ANISOTROPY on a NEAREST sampler (Blaze3D's blocks do exactly // that) while Vulkan forbids anisotropyEnable there, so the GL value must never be forwarded raw. -#if MOBILEGL_BUILD_RECORD_ARM template Float ResolveEffectiveMaxAnisotropy(const SamplerSource& sampler, -#else - Float ResolveEffectiveMaxAnisotropy(const MG_State::GLState::SamplerObject& sampler, -#endif Bool forceNearestFiltering) const; VkDevice m_device = VK_NULL_HANDLE; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp index 010b1974..fba43f95 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp @@ -18,7 +18,6 @@ #include "MG_Util/Metrics/PipeStats.h" #include -#if MOBILEGL_BUILD_RECORD_ARM // P5f (fm): the handle-keyed texture arm's two sources - the applier's resource records // (shape) and the server's staged-texture store (texels). #include @@ -26,7 +25,6 @@ #include "../DirectVulkan.h" // P7 wave 2 package B3: rule I's tally for the silent exits on this file's wire arm. #include "WireDeclineTally.h" -#endif #if MOBILEGL_BUILD_DISAGGREGATED // Shared images: a texture whose level 0 is a server-allocated AHardwareBuffer. #include @@ -319,9 +317,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkQueue graphicsQueue, const VkTextureManager::TextureResource& oldResource, VkTextureManager::TextureResource& newResource -#if MOBILEGL_BUILD_RECORD_ARM , Bool splitAspects = false -#endif ) { MOBILEGL_ASSERT(device != VK_NULL_HANDLE, "PreserveTextureContentsOnRecreate: device is null"); MOBILEGL_ASSERT(commandPool != VK_NULL_HANDLE, "PreserveTextureContentsOnRecreate: commandPool is null"); @@ -380,7 +376,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { copy.extent.width = std::max(oldResource.extent.width >> level, 1u); copy.extent.height = std::max(oldResource.extent.height >> level, 1u); copy.extent.depth = std::max(oldResource.depth >> level, 1u); -#if MOBILEGL_BUILD_RECORD_ARM if (splitAspects) { for (const VkImageAspectFlags aspect : {VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_DEPTH_BIT, @@ -391,7 +386,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { copyRegions.push_back(copy); } } else -#endif copyRegions.push_back(copy); } @@ -723,12 +717,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { DestroyDeferredReleases(); ++m_resourceEraseEpoch; // every memoized resource pointer dies with the map m_textureResources.clear(); -#if MOBILEGL_BUILD_RECORD_ARM // Destroy images while the device/allocator still exist, including after context death. m_wireTextureResources.clear(); m_wireRenderbufferResources.clear(); m_sharedImageUses.clear(); -#endif m_aliveObjects.clear(); m_storageImageTextures.clear(); @@ -1846,7 +1838,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { EraseTrackedTexture(identity); } prunedCount += orphanIdentities.size(); -#if MOBILEGL_BUILD_RECORD_ARM const auto pruneWire = [&](auto& resources, const auto& records) { for (auto it = resources.begin(); it != resources.end();) { const Uint32 slot = static_cast(it->first >> 32) & 0x7fffffffu; @@ -1864,11 +1855,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { const auto& applier = MG_Pipe::MGPipeApplier(); pruneWire(m_wireTextureResources, applier.TextureResources); pruneWire(m_wireRenderbufferResources, applier.RenderbufferResources); -#endif return prunedCount; } -#if MOBILEGL_BUILD_RECORD_ARM // --------------------------------------------------------------------------------- // P5f (fm): THE HANDLE-KEYED TEXTURE ARM // --------------------------------------------------------------------------------- @@ -3275,7 +3264,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { std::construct_at(&resource, Move(grown)); return true; } -#endif // MOBILEGL_BUILD_RECORD_ARM Bool VkTextureManager::SyncTexture(MG_State::GLState::ITextureObject &texture, TextureResource &outResource) { @@ -3832,9 +3820,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { resource.perMipViews.empty() && resource.perMipSampledViews.empty() && resource.attachmentViews.empty() && resource.alternateSampledViews.empty() && resource.storageImageViews.empty() -#if MOBILEGL_BUILD_RECORD_ARM && resource.yuvSource == nullptr -#endif ) { return; } @@ -4006,7 +3992,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { return current->mapped + alignedCursor; } -#if MOBILEGL_BUILD_RECORD_ARM Bool VkTextureManager::WireUploadsAreIdle() { // An open batch still owns references even before it has a fence. Poll // submitted batches without waiting; reclamation is deferred if any lives. @@ -4014,7 +3999,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { ReclaimCompletedUploads(); return m_pendingUploadReclaims.empty(); } -#endif void VkTextureManager::FlushPendingUploads() { if (!m_uploadBatchOpen) { diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.h index a163a8a6..e5258176 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.h @@ -19,20 +19,16 @@ #include #include -#if MOBILEGL_BUILD_RECORD_ARM // The handle-keyed arm's key type. Header-only POD, disagg-only, exactly the shape // MagmaPipeArms.h already gives this directory. #include -#endif namespace MobileGL::MG_State::GLState { class ITextureObject; } -#if MOBILEGL_BUILD_RECORD_ARM namespace MobileGL::MG_Pipe { struct MGPipeResourceRecord; } -#endif namespace MobileGL::MG_Backend::DirectVulkan { enum class SamplerNumericDomain : Uint8; @@ -355,7 +351,6 @@ public: // Serial at the last successful sync. 0 also means "this resource has only ever been // synced by the frontend arm" - a wire record's Serial starts at 0 on a create and moves // on every mutation, so the first handle sync of a fresh image always re-checks. -#if MOBILEGL_BUILD_RECORD_ARM Uint64 syncedWireSerial = 0; // SHARED IMAGES: level 0 is a server shared image (an imported AHardwareBuffer), not a // VMA allocation. The resource owns the image and its dedicated imported memory, and @@ -381,7 +376,6 @@ public: SharedPtr yuvOwner; SharedPtr yuvSource; Uint64 yuvConvertedFrame = 0; -#endif TextureResource() = default; TextureResource(const TextureResource&) = delete; @@ -415,7 +409,6 @@ public: std::swap(this->syncedContentVersion, that.syncedContentVersion); std::swap(this->syncedMipLevelCount, that.syncedMipLevelCount); std::swap(this->syncedShapeVersion, that.syncedShapeVersion); -#if MOBILEGL_BUILD_RECORD_ARM std::swap(this->syncedWireSerial, that.syncedWireSerial); std::swap(this->importedMemory, that.importedMemory); std::swap(this->sharedImageId, that.sharedImageId); @@ -428,7 +421,6 @@ public: std::swap(this->yuvOwner, that.yuvOwner); std::swap(this->yuvSource, that.yuvSource); std::swap(this->yuvConvertedFrame, that.yuvConvertedFrame); -#endif } void Reset() { @@ -466,7 +458,6 @@ public: if (image != VK_NULL_HANDLE && allocation != nullptr) { vmaDestroyImage(s_allocator.Get(), image, allocation); } -#if MOBILEGL_BUILD_RECORD_ARM if (importedMemory != VK_NULL_HANDLE) { if (image != VK_NULL_HANDLE) vkDestroyImage(s_device.Get(), image, nullptr); vkFreeMemory(s_device.Get(), importedMemory, nullptr); @@ -482,7 +473,6 @@ public: yuvOwner.reset(); yuvSource.reset(); yuvConvertedFrame = 0; -#endif fullView = VK_NULL_HANDLE; sampledView = VK_NULL_HANDLE; perMipViews.clear(); @@ -510,9 +500,7 @@ public: syncedContentVersion = 0; syncedMipLevelCount = 0; syncedShapeVersion = 0; -#if MOBILEGL_BUILD_RECORD_ARM syncedWireSerial = 0; -#endif } ~TextureResource() { @@ -539,11 +527,9 @@ public: // preserve-on-recreate copy are the existing callers. No-op when the // batch is empty. void FlushPendingUploads(); -#if MOBILEGL_BUILD_RECORD_ARM // Non-blocking idle proof for wire-object retirement. Independent texture // submissions are not represented by VulkanRenderer's submit counter. Bool WireUploadsAreIdle(); -#endif // Drains every frame slot's deferred image/view releases. Only valid when // the caller has proven every queue submission complete; used by the @@ -604,7 +590,6 @@ public: TextureResource* SyncTextureAndGetDescriptor( MG_State::GLState::ITextureObject& texture); -#if MOBILEGL_BUILD_RECORD_ARM // P5f (fm): THE HANDLE-KEYED ARM of SyncTextureAndGetDescriptor. Under an active transport // the apply thread may not name the client's ITextureObject (rule E), so the clear / blit / // readback / mipmap verbs resolve their attachment textures from the wire handle the @@ -679,7 +664,6 @@ public: const auto it = m_wireTextureResources.find(key); return it != m_wireTextureResources.end() && it->second.image != VK_NULL_HANDLE ? &it->second : nullptr; } -#endif VkImageView GetOrCreateViewAtMipLevel(MG_State::GLState::ITextureObject& texture, Uint32 mipLevel); VkImageView GetOrCreateAttachmentViewAtMipLevel(MG_State::GLState::ITextureObject& texture, Uint32 mipLevel, Uint32 baseArrayLayer, Uint32 layerCount, @@ -856,7 +840,6 @@ private: void EraseTrackedTexture(const TextureIdentity& identity); void PruneStaleTextureAliases(MG_State::GLState::ITextureObject* texture); SizeT PruneDeadTextures(); -#if MOBILEGL_BUILD_RECORD_ARM // The two halves of SyncTextureResourceByHandle: shape from the resource record's // descriptor (create / recreate / compatibility), then the pending-upload walk against the // server's staged store. UploadPendingWireLevels mutates the applier's record (consumed @@ -879,7 +862,6 @@ private: Vector m_sharedImageUses; // Handles are per-kind; a renderbuffer and texture may have identical slot/gen. std::unordered_map m_wireRenderbufferResources; -#endif VkDevice m_device = VK_NULL_HANDLE; VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index a04a8841..da9c3505 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -42,7 +42,6 @@ #include "MG_Util/SelfTest/PrimitivesGeneratedNoXfbProbe.h" #include "MG_Util/Texture/PixelStoreProcessor.h" #include -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 0: the seam WireFramebuffer.inc's MagmaWireFatal and WireDraw.inc's // WireBufferLegacyFatal die through. Declared by MG_Pipe on purpose - see PipeSessionFail.h. #include @@ -55,7 +54,6 @@ #include "WireColorBlitFilter.h" #include "WireDepthResolveArm.h" #include "WireDepthResolveProbe.h" -#endif #if MOBILEGL_BUILD_DISAGGREGATED #include // Shared images: the present side resolves the image it imports (WireSharedImage.inc). @@ -1484,96 +1482,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { namespace { static constexpr Uint32 kDescriptorSetsPerFrame = 64; -#if !MOBILEGL_BUILD_RECORD_ARM - // P7 wave 2-B2, CONTRACT-P7 §5.2 (B'): THE HIDDEN GL PROGRAMS ONLY EXIST IN THE PULL - // BUILD NOW. In a disaggregated build the monolith arm drives WireColorBlit.inc and - // WireDepthMipmap.inc - the baked modules the wire arm already uses - so nothing below - // this line is compiled: no GLSL text, no hidden object ids, no ShaderObject, - // ProgramObject or SamplerObject construction on a DirectVulkan path. That is what - // takes those three classes out of the link-closure ratchet's `p7-magma` bucket (§4.2), - // and the reason it is an `#if` and not a runtime branch is exactly that: a runtime - // early return leaves the symbols referenced. - // - // The pull build keeps every statement below byte for byte, which is what G1 pins. - static constexpr Uint kHiddenBlitProgramId = 0xFFFFFFF0u; - static constexpr Uint kHiddenBlitVertexShaderId = 0xFFFFFFF1u; - static constexpr Uint kHiddenBlitFragmentShaderId = 0xFFFFFFF2u; - static constexpr Uint kHiddenBlitNearestSamplerId = 0xFFFFFFF3u; - static constexpr Uint kHiddenBlitLinearSamplerId = 0xFFFFFFF4u; - static constexpr Uint kHiddenDepthMipmapProgramId = 0xFFFFFFF5u; - static constexpr Uint kHiddenDepthMipmapVertexShaderId = 0xFFFFFFF6u; - static constexpr Uint kHiddenDepthMipmapFragmentShaderId = 0xFFFFFFF7u; - static constexpr const char* kFullscreenTriangleVertexShaderSource = R"(#version 460 core -uniform vec4 uSrcRect; -uniform vec4 uDstRect; -uniform int uSurfaceTransform; -layout(location = 0) out vec2 vTexCoord; - -vec2 ApplySurfaceTransform(vec2 position, int transform) { - vec2 p = position; - p.y = -p.y; - if (transform == 1) { - p = vec2(-p.y, p.x); - } else if (transform == 2) { - p = -p; - } else if (transform == 3) { - p = vec2(p.y, -p.x); - } - return p; -} - -void main() { - const vec2 uvTri[3] = vec2[]( - vec2(0.0, 0.0), - vec2(2.0, 0.0), - vec2(0.0, 2.0) - ); - vec2 uv = uvTri[gl_VertexID]; - vec2 dst = uDstRect.xy + uv * uDstRect.zw; - vec2 clip = dst * 2.0 - 1.0; - clip = ApplySurfaceTransform(clip, uSurfaceTransform); - gl_Position = vec4(clip, 0.0, 1.0); - vTexCoord = uSrcRect.xy + uv * uSrcRect.zw; -} -)"; - - static constexpr const char* kBlitFragmentShaderSource = R"(#version 460 core -layout(binding = 0) uniform sampler2D uSource; -layout(location = 0) in vec2 vTexCoord; -layout(location = 0) out vec4 outColor; - -void main() { - // Explicit LOD, not texture(): a blit reads exactly the selected level, so - // derivative-based mip selection has no business here. It is also load-bearing: - // on Adreno 650 (driver 512.502) an implicit-LOD sample of this single-mip - // UBWC render target through the pre-rotation (ROTATE_90) mapping reads past - // the image's allocation - despite the sampler's maxLod=0 and a nominal 1:1 - // texel mapping whose LOD is 0, so the driver's implicit-LOD path itself is at - // fault - and page-faults the GPU once the neighbouring memory is returned to - // the kernel (frame 2 of Minecraft 26.2's resource reload; the kernel then - // invalidates the context and the next submit dies with EDEADLK -> - // VK_ERROR_DEVICE_LOST at Present). Verified on device: texture() faults on - // the second frame every run, textureLod survives with identical state. - outColor = textureLod(uSource, vTexCoord, 0.0); -} -)"; - - static constexpr const char* kDepthMipmapFragmentShaderSource = R"(#version 460 core -layout(binding = 0) uniform sampler2D uSource; -layout(location = 0) in vec2 vTexCoord; -uniform ivec2 uSrcTexelSize; - -void main() { - ivec2 srcBase = ivec2(vTexCoord * vec2(uSrcTexelSize)); - ivec2 srcMax = uSrcTexelSize - ivec2(1); - float depth0 = texelFetch(uSource, clamp(srcBase, ivec2(0), srcMax), 0).r; - float depth1 = texelFetch(uSource, clamp(srcBase + ivec2(1, 0), ivec2(0), srcMax), 0).r; - float depth2 = texelFetch(uSource, clamp(srcBase + ivec2(0, 1), ivec2(0), srcMax), 0).r; - float depth3 = texelFetch(uSource, clamp(srcBase + ivec2(1, 1), ivec2(0), srcMax), 0).r; - gl_FragDepth = 0.25 * (depth0 + depth1 + depth2 + depth3); -} -)"; -#endif // !MOBILEGL_BUILD_RECORD_ARM static Uint32 ComputeFullMipLevelCount(const IntVec3& baseTexelSize) { @@ -1687,7 +1595,6 @@ void main() { return true; } -#if MOBILEGL_BUILD_RECORD_ARM // P5c (T5 / tx): the split arm of EnsureGenerateMipmapStorageAllocated. Under an active // transport the apply thread may not WRITE the client's level storage - AllocateStorage // and MarkStorageDirty on a frontend TextureObjectMipmap are §6 layer-1 surfaces @@ -1737,7 +1644,6 @@ void main() { } return true; } -#endif static VkImageLayout ResolveGenerateMipmapFinalLayout(VkImageAspectFlags aspectMask) { return (aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0 @@ -3221,17 +3127,12 @@ void main() { inline ProgramFactory::CompileOptionFlags GetShaderTransformFlags(VkSurfaceTransformFlagBitsKHR preTransform) { ProgramFactory::CompileOptionFlags flags = ProgramFactory::CompileOptionBit::PositionZRemap; -#if MOBILEGL_BUILD_RECORD_ARM const Bool wire = MG_Config::DataArmIsRecord(); const auto* wireFbo = wire ? MG_Pipe::MGPipeApplier().DrawFramebuffer() : nullptr; const auto currentDrawFBO = wire ? SharedPtr{} : MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); const Bool isDefault = wire ? (wireFbo && wireFbo->IsDefault) : (currentDrawFBO && currentDrawFBO->IsDefaultFramebuffer()); -#else - const auto& currentDrawFBO = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); - const Bool isDefault = currentDrawFBO != nullptr && currentDrawFBO->IsDefaultFramebuffer(); -#endif if (isDefault) { flags |= ProgramFactory::CompileOptionBit::PositionYFlip; // gl_FragCoord follows the same rule the default-framebuffer RECTANGLES follow @@ -3272,9 +3173,7 @@ void main() { CreateAllocator(); CreateCommandPool(); -#if MOBILEGL_BUILD_RECORD_ARM m_progressMarkers.Init(m_device, m_physicalDevice.queueFamilies.graphicsFamily); -#endif // Frames-in-flight is a request, not a guarantee: it also seeds the swapchain image // count (SwapchainObject clamps the hint into [minImageCount, maxImageCount]). Not every @@ -3447,9 +3346,7 @@ void main() { m_physicalDevice.properties.limits.minUniformBufferOffsetAlignment, m_config.MaxFramesInFlight, maxProgramBindings, kDescriptorSetsPerFrame, m_textureManager.get(), m_samplerManager.get()); MOBILEGL_ASSERT(succeeded, "UniformDescriptorBinder initialization failed."); -#if MOBILEGL_BUILD_RECORD_ARM m_uniformManager->SetWireInvalidStorageImageArm(m_wireNullDescriptor); -#endif m_vertexInputStateFactory = MakeUnique(m_config, m_physicalDevice.handle, m_pipeIdentity); MOBILEGL_ASSERT(m_vertexInputStateFactory != nullptr, "VertexInputStateFactory creation failed."); @@ -3500,13 +3397,10 @@ void main() { if (m_device != VK_NULL_HANDLE) { VK_VERIFY(vkDeviceWaitIdle(m_device)); } -#if MOBILEGL_BUILD_RECORD_ARM m_progressMarkers.Shutdown(); -#endif // Parked surface targets (ActivateSurfaceTarget) go before the device and instance. for (auto& [_, target] : m_parkedTargets) DestroyParkedTarget(target); m_parkedTargets.clear(); -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 2 package B3: the session's decline tally. Silent when nothing declined, so a // green lane stays quiet and a lane that dropped a draw cannot (rule I's observable). WireDeclineTally::Dump("shutdown"); @@ -3526,7 +3420,6 @@ void main() { #if MOBILEGL_BUILD_DISAGGREGATED DestroySharedImagePresentTargets(false); DestroySharedImageSync(); -#endif #endif OnSubmitsCompletedUpTo(m_submitCounter); DestroySubmitFencePool(); @@ -3622,9 +3515,7 @@ void main() { m_device = VK_NULL_HANDLE; } s_vkCmdDrawIndexedIndirectCount = nullptr; -#if MOBILEGL_BUILD_RECORD_ARM s_vkCmdWireDrawIndirectCount = nullptr; -#endif s_vkCmdDrawMultiEXT = nullptr; s_vkCmdDrawMultiIndexedEXT = nullptr; @@ -4601,7 +4492,6 @@ void main() { } Bool VulkanRenderer::InitializeBlitResources() { -#if MOBILEGL_BUILD_RECORD_ARM // P5f fv gave this an early return for every non-monolith transport, because the hidden // programs are frontend objects and creating them on the server would retain a client // compiler/allocator dependency. P7 wave 2-B2 (CONTRACT-P7 §5.2, (B')) takes the last @@ -4613,77 +4503,6 @@ void main() { // object file, so the link-closure ratchet counted them whether or not the branch ever // ran. Compiling the construction out is what makes them fall. return true; -#else - ShutdownBlitResources(); - - auto vertexShader = MakeShared(ShaderStage::Vertex, kHiddenBlitVertexShaderId); - vertexShader->SetShaderSource(kFullscreenTriangleVertexShaderSource); - vertexShader->Compile(); - if (!vertexShader->GetCompileStatus()) { - MGLOG_E("InitializeBlitResources failed: vertex shader compile error: %s", vertexShader->GetInfoLog().c_str()); - return false; - } - - auto fragmentShader = MakeShared(ShaderStage::Fragment, kHiddenBlitFragmentShaderId); - fragmentShader->SetShaderSource(kBlitFragmentShaderSource); - fragmentShader->Compile(); - if (!fragmentShader->GetCompileStatus()) { - MGLOG_E("InitializeBlitResources failed: fragment shader compile error: %s", fragmentShader->GetInfoLog().c_str()); - return false; - } - - m_blitResources.program = MakeShared(kHiddenBlitProgramId); - m_blitResources.program->AttachShader(vertexShader); - m_blitResources.program->AttachShader(fragmentShader); - m_blitResources.program->Link(false); - if (!m_blitResources.program->GetLinkStatus()) { - MGLOG_E("InitializeBlitResources failed: program link error: %s", m_blitResources.program->GetInfoLog().c_str()); - return false; - } - - m_blitResources.srcRectLocation = m_blitResources.program->GetUniformLocation("uSrcRect"); - m_blitResources.dstRectLocation = m_blitResources.program->GetUniformLocation("uDstRect"); - m_blitResources.surfaceTransformLocation = m_blitResources.program->GetUniformLocation("uSurfaceTransform"); - MOBILEGL_ASSERT(m_blitResources.srcRectLocation >= 0, "InitializeBlitResources: missing uSrcRect"); - MOBILEGL_ASSERT(m_blitResources.dstRectLocation >= 0, "InitializeBlitResources: missing uDstRect"); - MOBILEGL_ASSERT(m_blitResources.surfaceTransformLocation >= 0, - "InitializeBlitResources: missing uSurfaceTransform"); - MOBILEGL_ASSERT(m_blitResources.program->GetUBOSize() > 0, - "InitializeBlitResources: blit program global UBO is empty"); - MOBILEGL_ASSERT(m_programFactory != nullptr, "InitializeBlitResources: program factory is null"); - - ProgramFactory::CompileOptionFlags blitTransformFlags = 0; - const auto& blitProgramObj = m_programFactory->GetOrCreateProgram(*m_blitResources.program, blitTransformFlags); - Bool foundBlitSamplerBinding = false; - for (Uint32 binding = 0; binding < blitProgramObj.samplerNameByBinding.size(); ++binding) { - if (blitProgramObj.bindingKinds[binding] != ProgramFactory::DescriptorBindingKind::CombinedImageSampler) { - continue; - } - if (blitProgramObj.samplerNameByBinding[binding] == "uSource") { - m_blitResources.samplerBinding = binding; - foundBlitSamplerBinding = true; - break; - } - } - MOBILEGL_ASSERT(foundBlitSamplerBinding, - "InitializeBlitResources: failed to resolve reflected binding for uSource"); - - auto createSampler = [](Uint externalIndex, SamplerFilterMode filter) { - auto sampler = MakeShared(externalIndex); - sampler->SetWrapS(SamplerWrapMode::ClampToEdge); - sampler->SetWrapT(SamplerWrapMode::ClampToEdge); - sampler->SetWrapR(SamplerWrapMode::ClampToEdge); - sampler->SetMinFilter(filter); - sampler->SetMagFilter(filter); - sampler->SetMipmapMode(SamplerMipmapMode::None); - sampler->SetLodRange(0.0f, 0.0f); - return sampler; - }; - - m_blitResources.nearestSampler = createSampler(kHiddenBlitNearestSamplerId, SamplerFilterMode::Nearest); - m_blitResources.linearSampler = createSampler(kHiddenBlitLinearSamplerId, SamplerFilterMode::Linear); - return true; -#endif } void VulkanRenderer::ShutdownBlitResources() { @@ -4713,81 +4532,11 @@ void main() { } Bool VulkanRenderer::InitializeDepthMipmapResources() { -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 2-B2 (CONTRACT-P7 §5.2, (B')): the depth-mip half of the same step. In a // disaggregated build the monolith arm generates its depth chain with // WireDepthMipmap.inc's baked pass, so there is no hidden GL program to build on any // transport. See InitializeBlitResources above for why this is an `#if`. return true; -#else - ShutdownDepthMipmapResources(); - - auto vertexShader = MakeShared(ShaderStage::Vertex, - kHiddenDepthMipmapVertexShaderId); - vertexShader->SetShaderSource(kFullscreenTriangleVertexShaderSource); - vertexShader->Compile(); - if (!vertexShader->GetCompileStatus()) { - MGLOG_E("InitializeDepthMipmapResources failed: vertex shader compile error: %s", - vertexShader->GetInfoLog().c_str()); - return false; - } - - auto fragmentShader = MakeShared(ShaderStage::Fragment, - kHiddenDepthMipmapFragmentShaderId); - fragmentShader->SetShaderSource(kDepthMipmapFragmentShaderSource); - fragmentShader->Compile(); - if (!fragmentShader->GetCompileStatus()) { - MGLOG_E("InitializeDepthMipmapResources failed: fragment shader compile error: %s", - fragmentShader->GetInfoLog().c_str()); - return false; - } - - m_depthMipmapResources.program = MakeShared(kHiddenDepthMipmapProgramId); - m_depthMipmapResources.program->AttachShader(vertexShader); - m_depthMipmapResources.program->AttachShader(fragmentShader); - m_depthMipmapResources.program->Link(false); - if (!m_depthMipmapResources.program->GetLinkStatus()) { - MGLOG_E("InitializeDepthMipmapResources failed: program link error: %s", - m_depthMipmapResources.program->GetInfoLog().c_str()); - return false; - } - - m_depthMipmapResources.srcRectLocation = m_depthMipmapResources.program->GetUniformLocation("uSrcRect"); - m_depthMipmapResources.dstRectLocation = m_depthMipmapResources.program->GetUniformLocation("uDstRect"); - m_depthMipmapResources.surfaceTransformLocation = - m_depthMipmapResources.program->GetUniformLocation("uSurfaceTransform"); - m_depthMipmapResources.srcTexelSizeLocation = - m_depthMipmapResources.program->GetUniformLocation("uSrcTexelSize"); - MOBILEGL_ASSERT(m_depthMipmapResources.srcRectLocation >= 0, - "InitializeDepthMipmapResources: missing uSrcRect"); - MOBILEGL_ASSERT(m_depthMipmapResources.dstRectLocation >= 0, - "InitializeDepthMipmapResources: missing uDstRect"); - MOBILEGL_ASSERT(m_depthMipmapResources.surfaceTransformLocation >= 0, - "InitializeDepthMipmapResources: missing uSurfaceTransform"); - MOBILEGL_ASSERT(m_depthMipmapResources.srcTexelSizeLocation >= 0, - "InitializeDepthMipmapResources: missing uSrcTexelSize"); - MOBILEGL_ASSERT(m_depthMipmapResources.program->GetUBOSize() > 0, - "InitializeDepthMipmapResources: depth mipmap program global UBO is empty"); - MOBILEGL_ASSERT(m_programFactory != nullptr, "InitializeDepthMipmapResources: program factory is null"); - - ProgramFactory::CompileOptionFlags transformFlags = 0; - const auto& programObj = - m_programFactory->GetOrCreateProgram(*m_depthMipmapResources.program, transformFlags); - Bool foundSamplerBinding = false; - for (Uint32 binding = 0; binding < programObj.samplerNameByBinding.size(); ++binding) { - if (programObj.bindingKinds[binding] != ProgramFactory::DescriptorBindingKind::CombinedImageSampler) { - continue; - } - if (programObj.samplerNameByBinding[binding] == "uSource") { - m_depthMipmapResources.samplerBinding = binding; - foundSamplerBinding = true; - break; - } - } - MOBILEGL_ASSERT(foundSamplerBinding, - "InitializeDepthMipmapResources: failed to resolve reflected binding for uSource"); - return true; -#endif } void VulkanRenderer::ShutdownDepthMipmapResources() { @@ -4840,66 +4589,6 @@ void main() { m_deferredDepthMipmapCleanup.clear(); } -#if !MOBILEGL_BUILD_RECORD_ARM - // P7 wave 2-B2 (CONTRACT-P7 §5.2, (B')): the pull build's blit pipeline, built out of the - // hidden GL program through the program/pipeline factories. A disaggregated build has no - // such program on either arm - WireColorBlit.inc owns its pipeline - so this is compiled - // out with its only caller's body. - VkPipeline VulkanRenderer::GetOrCreateBlitPipeline(const RenderPassEntry& renderPassEntry) { - MOBILEGL_ASSERT(m_blitResources.program != nullptr, "GetOrCreateBlitPipeline: blit program is null"); - MOBILEGL_ASSERT(m_programFactory != nullptr, "GetOrCreateBlitPipeline: program factory is null"); - MOBILEGL_ASSERT(m_uniformManager != nullptr, "GetOrCreateBlitPipeline: descriptor binder is null"); - - static const VkPipelineVertexInputStateCreateInfo kEmptyVertexInputState { - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO - }; - ProgramFactory::CompileOptionFlags transformFlags = 0; - const auto& programObj = m_programFactory->GetOrCreateProgram(*m_blitResources.program, transformFlags); - PipelineFactory::PipelineCreatePayload payload{ - .programHash = programObj.hash, - .vertexInputHash = 0, - .pipelineLayout = programObj.pipelineLayout, - .renderPass = renderPassEntry.renderPass, - .colorAttachmentCount = renderPassEntry.colorAttachmentCount, - .rasterizationSamples = renderPassEntry.sampleCount, - .subpass = 0, - .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - .cullMode = VK_CULL_MODE_NONE, - .frontFace = VK_FRONT_FACE_CLOCKWISE, - // Functionally irrelevant to the blit (no flat varying, no capture), but on a device with - // provokingVertexModePerPipeline == VK_FALSE a blit pipeline left on FIRST inside a render - // pass whose draw pipelines are LAST is an illegal mix. Note this does NOT cover - // GenerateDepthMipmapWithShader, which builds its pipeline directly and keeps Vulkan's - // FIRST - legal only because it creates and begins its own render pass. Anything that ever - // records that pipeline inside an outer render pass must route through this selector too. - .provokingVertexMode = SelectProvokingVertexMode(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false), - .depthTestEnable = false, - .depthWriteEnable = false, - .depthCompareOp = VK_COMPARE_OP_ALWAYS, - .stages = &programObj.stages, - .vertexInputState = &kEmptyVertexInputState, - .stageSpirvDigests = &programObj.stageSpirvDigests - }; - static constexpr VkColorComponentFlags kColorWriteMask = - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - MOBILEGL_ASSERT(payload.colorAttachmentCount <= PipelineFactory::PipelineCreatePayload::kMaxColorAttachments, - "GetOrCreateBlitPipeline: colorAttachmentCount=%u exceeds payload capacity", - payload.colorAttachmentCount); - for (Uint32 i = 0; i < payload.colorAttachmentCount; ++i) { - payload.colorBlendAttachments[i] = MakeColorBlendAttachmentState( - false, - VK_BLEND_FACTOR_ONE, - VK_BLEND_FACTOR_ZERO, - VK_BLEND_OP_ADD, - VK_BLEND_FACTOR_ONE, - VK_BLEND_FACTOR_ZERO, - VK_BLEND_OP_ADD, - kColorWriteMask); - } - return m_pipelineFactory->GetOrCreatePipeline(payload); - } -#endif // !MOBILEGL_BUILD_RECORD_ARM Bool VulkanRenderer::GenerateDepthMipmapWithShader(FrameContext::FrameData& frame, MG_State::GLState::ITextureObject& texture, @@ -4909,7 +4598,6 @@ void main() { const IntVec3& storageBaseTexelSize, VkImageLayout originalLayout, VkImageLayout finalLayout) { -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 2-B2 (CONTRACT-P7 §5.2, (B')): THE MONOLITH ARM ON THE BAKED PASS. Every // level below is WireDepthMipmap.inc's GenerateWireDepthMipLevel - the same 2x2 // texelFetch box, the same clamp, the same average, the same half-texel offset, since @@ -4954,310 +4642,6 @@ void main() { whole.extent = resource.extent; TransitionWireImage(whole, finalLayout); return true; -#else - MOBILEGL_ASSERT(m_depthMipmapResources.program != nullptr, - "GenerateDepthMipmapWithShader: depth mipmap program is null"); - MOBILEGL_ASSERT(m_blitResources.nearestSampler != nullptr, - "GenerateDepthMipmapWithShader: helper sampler is null"); - MOBILEGL_ASSERT(m_programFactory != nullptr, "GenerateDepthMipmapWithShader: program factory is null"); - MOBILEGL_ASSERT(m_uniformManager != nullptr, "GenerateDepthMipmapWithShader: uniform manager is null"); - MOBILEGL_ASSERT(texture.GetTarget() == TextureTarget::Texture2D, - "GenerateDepthMipmapWithShader only supports GL_TEXTURE_2D depth textures"); - MOBILEGL_ASSERT(resource.aspect == VK_IMAGE_ASPECT_DEPTH_BIT, - "GenerateDepthMipmapWithShader requires a depth-only aspect"); - MOBILEGL_ASSERT(resource.depth == 1 && resource.arrayLayers == 1, - "GenerateDepthMipmapWithShader only supports single-layer depth textures"); - MOBILEGL_ASSERT(m_frameContext.GetCurrentFrameIndex() < m_deferredDepthMipmapCleanup.size(), - "GenerateDepthMipmapWithShader: frame index %u out of range (cleanup slots=%zu)", - m_frameContext.GetCurrentFrameIndex(), m_deferredDepthMipmapCleanup.size()); - - auto& deferredCleanup = m_deferredDepthMipmapCleanup[m_frameContext.GetCurrentFrameIndex()]; - - ProgramFactory::CompileOptionFlags transformFlags = 0; - const auto& programObj = - m_programFactory->GetOrCreateProgram(*m_depthMipmapResources.program, transformFlags); - - VkAttachmentDescription depthAttachment{}; - depthAttachment.format = resource.format; - depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depthAttachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depthAttachmentRef{}; - depthAttachmentRef.attachment = 0; - depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpassDesc{}; - subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDesc.pDepthStencilAttachment = &depthAttachmentRef; - - VkRenderPassCreateInfo renderPassCreateInfo{}; - renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassCreateInfo.attachmentCount = 1; - renderPassCreateInfo.pAttachments = &depthAttachment; - renderPassCreateInfo.subpassCount = 1; - renderPassCreateInfo.pSubpasses = &subpassDesc; - - VkRenderPass renderPass = VK_NULL_HANDLE; - VK_VERIFY(vkCreateRenderPass(m_device, &renderPassCreateInfo, nullptr, &renderPass), - "GenerateDepthMipmapWithShader: vkCreateRenderPass"); - - static const VkPipelineVertexInputStateCreateInfo kEmptyVertexInputState { - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO - }; - - VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; - inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - - VkPipelineViewportStateCreateInfo viewportState{}; - viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewportState.viewportCount = 1; - viewportState.scissorCount = 1; - - VkPipelineRasterizationStateCreateInfo rasterizationState{}; - rasterizationState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizationState.polygonMode = VK_POLYGON_MODE_FILL; - rasterizationState.cullMode = VK_CULL_MODE_NONE; - rasterizationState.frontFace = VK_FRONT_FACE_CLOCKWISE; - rasterizationState.lineWidth = 1.0f; - - VkPipelineMultisampleStateCreateInfo multisampleState{}; - multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - - VkPipelineDepthStencilStateCreateInfo depthStencilState{}; - depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depthStencilState.depthTestEnable = VK_TRUE; - depthStencilState.depthWriteEnable = VK_TRUE; - depthStencilState.depthCompareOp = VK_COMPARE_OP_ALWAYS; - depthStencilState.minDepthBounds = 0.0f; - depthStencilState.maxDepthBounds = 1.0f; - - VkPipelineColorBlendStateCreateInfo colorBlendState{}; - colorBlendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - - const VkDynamicState dynamicStates[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState{}; - dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamicState.dynamicStateCount = static_cast(sizeof(dynamicStates) / sizeof(dynamicStates[0])); - dynamicState.pDynamicStates = dynamicStates; - - VkGraphicsPipelineCreateInfo pipelineCreateInfo{}; - pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineCreateInfo.stageCount = static_cast(programObj.stages.size()); - pipelineCreateInfo.pStages = programObj.stages.data(); - pipelineCreateInfo.pVertexInputState = &kEmptyVertexInputState; - pipelineCreateInfo.pInputAssemblyState = &inputAssembly; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.layout = programObj.pipelineLayout; - pipelineCreateInfo.renderPass = renderPass; - pipelineCreateInfo.subpass = 0; - - VkPipeline pipeline = VK_NULL_HANDLE; - VK_VERIFY(vkCreateGraphicsPipelines(m_device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, nullptr, &pipeline), - "GenerateDepthMipmapWithShader: vkCreateGraphicsPipelines"); - deferredCleanup.renderPasses.push_back(renderPass); - deferredCleanup.pipelines.push_back(pipeline); - - auto createMipView = [&](Uint32 mipLevel, VkImageAspectFlags aspectMask) { - VkImageViewCreateInfo viewCreateInfo{}; - viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewCreateInfo.image = resource.image; - viewCreateInfo.viewType = resource.viewType; - viewCreateInfo.format = resource.format; - viewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - viewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - viewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - viewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - viewCreateInfo.subresourceRange.aspectMask = aspectMask; - viewCreateInfo.subresourceRange.baseMipLevel = mipLevel; - viewCreateInfo.subresourceRange.levelCount = 1; - viewCreateInfo.subresourceRange.baseArrayLayer = 0; - viewCreateInfo.subresourceRange.layerCount = 1; - - VkImageView view = VK_NULL_HANDLE; - VK_VERIFY(vkCreateImageView(m_device, &viewCreateInfo, nullptr, &view), - "GenerateDepthMipmapWithShader: vkCreateImageView"); - return view; - }; - - VkPipelineStageFlags originalSrcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - VkAccessFlags originalSrcAccessMask = 0; - GetImageTransitionSourceState(originalLayout, originalSrcStageMask, originalSrcAccessMask); - - VkPipelineStageFlags finalDstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - VkAccessFlags finalDstAccessMask = 0; - GetImageTransitionDestinationState(finalLayout, finalDstStageMask, finalDstAccessMask); - - VkPipelineStageFlags attachmentStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - VkAccessFlags attachmentAccessMask = 0; - GetImageTransitionDestinationState(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - attachmentStageMask, attachmentAccessMask); - - if (originalLayout != finalLayout) { - if (baseMipLevel > 0) { - VkImageLayout lowerMipLayout = originalLayout; - const Bool lowerReady = VkTextureManager::TransitionImageLayout( - frame.commandBuffer, resource.image, lowerMipLayout, finalLayout, - originalSrcStageMask, finalDstStageMask, - originalSrcAccessMask, finalDstAccessMask, - resource.aspect, 0, baseMipLevel); - MOBILEGL_ASSERT(lowerReady, "%s: failed to transition lower untouched mip levels", __func__); - } - - if (generateMipLevelCount < resource.mipLevels) { - VkImageLayout upperMipLayout = originalLayout; - const Bool upperReady = VkTextureManager::TransitionImageLayout( - frame.commandBuffer, resource.image, upperMipLayout, finalLayout, - originalSrcStageMask, finalDstStageMask, - originalSrcAccessMask, finalDstAccessMask, - resource.aspect, generateMipLevelCount, resource.mipLevels - generateMipLevelCount); - MOBILEGL_ASSERT(upperReady, "%s: failed to transition upper untouched mip levels", __func__); - } - - VkImageLayout baseMipLayout = originalLayout; - const Bool baseReady = VkTextureManager::TransitionImageLayout( - frame.commandBuffer, resource.image, baseMipLayout, finalLayout, - originalSrcStageMask, finalDstStageMask, - originalSrcAccessMask, finalDstAccessMask, - resource.aspect, baseMipLevel, 1); - MOBILEGL_ASSERT(baseReady, "%s: failed to transition base mip level to sampled layout", __func__); - } - - resource.layout = finalLayout; - - auto* depthProgramData = static_cast(m_depthMipmapResources.program->MapUBO()); - MOBILEGL_ASSERT(depthProgramData != nullptr, "GenerateDepthMipmapWithShader: depth mipmap UBO is null"); - auto writeUniform = [&](Int location, const void* data, SizeT size) { - MOBILEGL_ASSERT(location >= 0, "GenerateDepthMipmapWithShader: invalid uniform location"); - const Uint offset = m_depthMipmapResources.program->GetUniformOffset(static_cast(location)); - // A RETURN, not only an assert: the assert compiles out in release, and a program - // whose SPIR-V job settled cancelled reports kInvalidUniformOffset (~0u) with a - // zero-sized shadow - which would make the memcpy below a wild write at - // depthProgramData + 4 GiB rather than a dropped uniform. - if (offset == MG_State::GLState::ProgramObject::kInvalidUniformOffset || - offset + size > m_depthMipmapResources.program->GetUBOSize()) { - MOBILEGL_ASSERT(false, "GenerateDepthMipmapWithShader: uniform write out of bounds"); - return; - } - memcpy(depthProgramData + offset, data, size); - m_depthMipmapResources.program->MarkUBOContentDirty(); - }; - - for (Uint32 level = baseMipLevel + 1; level < generateMipLevelCount; ++level) { - VkImageLayout dstMipLayout = originalLayout; - const Bool dstReady = VkTextureManager::TransitionImageLayout( - frame.commandBuffer, resource.image, dstMipLayout, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - originalSrcStageMask, attachmentStageMask, - originalSrcAccessMask, attachmentAccessMask, - resource.aspect, level, 1); - MOBILEGL_ASSERT(dstReady, "%s: failed to transition mip level %u to depth attachment layout", __func__, level); - - const IntVec3 srcTexelSize = ComputeMipTexelSize(storageBaseTexelSize, level - 1); - const IntVec3 dstTexelSize = ComputeMipTexelSize(storageBaseTexelSize, level); - const Int srcTexelSizeUniform[2] = {srcTexelSize.x(), srcTexelSize.y()}; - - const VkImageView sourceImageView = createMipView(level - 1, VK_IMAGE_ASPECT_DEPTH_BIT); - const VkImageView depthAttachmentView = createMipView(level, resource.aspect); - deferredCleanup.imageViews.push_back(sourceImageView); - deferredCleanup.imageViews.push_back(depthAttachmentView); - - VkFramebufferCreateInfo framebufferCreateInfo{}; - framebufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferCreateInfo.renderPass = renderPass; - framebufferCreateInfo.attachmentCount = 1; - framebufferCreateInfo.pAttachments = &depthAttachmentView; - framebufferCreateInfo.width = static_cast(dstTexelSize.x()); - framebufferCreateInfo.height = static_cast(dstTexelSize.y()); - framebufferCreateInfo.layers = 1; - - VkFramebuffer framebuffer = VK_NULL_HANDLE; - VK_VERIFY(vkCreateFramebuffer(m_device, &framebufferCreateInfo, nullptr, &framebuffer), - "GenerateDepthMipmapWithShader: vkCreateFramebuffer"); - deferredCleanup.framebuffers.push_back(framebuffer); - - VkRenderPassBeginInfo renderPassBeginInfo{}; - renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = framebuffer; - renderPassBeginInfo.renderArea.offset = {0, 0}; - renderPassBeginInfo.renderArea.extent = { - static_cast(dstTexelSize.x()), static_cast(dstTexelSize.y()) - }; - - EndActiveRenderPassOn(frame.commandBuffer); - vkCmdBeginRenderPass(frame.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport{}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = static_cast(dstTexelSize.x()); - viewport.height = static_cast(dstTexelSize.y()); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(frame.commandBuffer, 0, 1, &viewport); - - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = {static_cast(dstTexelSize.x()), static_cast(dstTexelSize.y())}; - vkCmdSetScissor(frame.commandBuffer, 0, 1, &scissor); - - vkCmdBindPipeline(frame.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - // The depth-mipmap pipeline's narrower dynamic set (viewport/scissor - // only) leaves the other dynamic states undefined; its raw scissor - // and viewport writes also bypass the shadow. - ResetDynamicStateShadow(); - - std::fill(depthProgramData, - depthProgramData + m_depthMipmapResources.program->GetUBOSize(), - Uint8{0}); - BlitUniformData blitUniformData{}; - writeUniform(m_depthMipmapResources.srcRectLocation, - blitUniformData.srcRect, - sizeof(blitUniformData.srcRect)); - writeUniform(m_depthMipmapResources.dstRectLocation, - blitUniformData.dstRect, - sizeof(blitUniformData.dstRect)); - writeUniform(m_depthMipmapResources.surfaceTransformLocation, - &blitUniformData.surfaceTransform, - sizeof(blitUniformData.surfaceTransform)); - writeUniform(m_depthMipmapResources.srcTexelSizeLocation, - srcTexelSizeUniform, - sizeof(srcTexelSizeUniform)); - - const auto samplerBindingOverride = UniformManager::SamplerBindingOverride{ - .binding = m_depthMipmapResources.samplerBinding, - .texture = &texture, - .sampler = m_blitResources.nearestSampler.get(), - .imageView = sourceImageView, - }; - const Bool bound = m_uniformManager->BindProgramUniformBuffers( - frame.commandBuffer, *m_depthMipmapResources.program, programObj, - m_frameContext.GetCurrentFrameIndex(), VK_PIPELINE_BIND_POINT_GRAPHICS, &samplerBindingOverride); - MOBILEGL_ASSERT(bound, "GenerateDepthMipmapWithShader: BindProgramUniformBuffers failed"); - vkCmdDraw(frame.commandBuffer, 3, 1, 0, 0); - vkCmdEndRenderPass(frame.commandBuffer); - - VkImageLayout finishedMipLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - const Bool finishedReady = VkTextureManager::TransitionImageLayout( - frame.commandBuffer, resource.image, finishedMipLayout, finalLayout, - attachmentStageMask, finalDstStageMask, - attachmentAccessMask, finalDstAccessMask, - resource.aspect, level, 1); - MOBILEGL_ASSERT(finishedReady, "%s: failed to transition mip level %u to sampled layout", __func__, level); - } - return true; -#endif } // Boost-style hash combine. The inputs are tiny enum ordinals and bit masks, so @@ -5362,7 +4746,6 @@ void main() { return rsp.PrimitiveRestartIndex <= MG_Util::FixedRestartIndexForGLType(pIndexBufferView->indexType); } -#if MOBILEGL_BUILD_RECORD_ARM // MOBILEGL_TEST_PIPELINE_CREATE_DELAY_MS - milliseconds to spend in a pipeline-creation MISS // on the wire arm. See the call site below for why it exists: the device's divergence needs a // COLD driver pipeline cache, and this host's is always warm, so the only way to reproduce @@ -5376,7 +4759,6 @@ void main() { }(); return milliseconds; } -#endif VkPipeline VulkanRenderer::GetOrCreatePipeline( GLenum mode, @@ -5386,7 +4768,6 @@ void main() { const MG_State::GLState::VertexArrayObject& vao, const RenderPassEntry& renderPassEntry, Bool primitiveRestartEnable) { -#if MOBILEGL_BUILD_RECORD_ARM return GetOrCreatePipelineWithInput(mode, program, programObj, transformFlags, m_vertexInputStateFactory->GetOrCreateVertexInputState(vao), renderPassEntry, primitiveRestartEnable); } @@ -5395,7 +4776,6 @@ void main() { const ProgramFactory::VkProgramObject& programObj, ProgramFactory::CompileOptionFlags transformFlags, const VertexInputStateFactory::BackendVertexInputState& vis, const RenderPassEntry& renderPassEntry, Bool primitiveRestartEnable, Uint64 wireRenderPassCompatibilityId) { -#endif Bool invertClockwise = transformFlags & ProgramFactory::CompileOptionBit::PositionYFlip; if (programObj.stages.empty()) { MGLOG_D("GetOrCreatePipeline skipped: program has no shader stages"); @@ -5413,14 +4793,9 @@ void main() { // payload key on the resolved LAYOUT hash instead, so draws over identical // layouts share one pipeline. // The one-arg fetch rides the VAO's state-pointer memo (no hash, no map). -#if !MOBILEGL_BUILD_RECORD_ARM - auto& vis = m_vertexInputStateFactory->GetOrCreateVertexInputState(vao); -#endif const Uint64 vertexLayoutHash = vis.layoutHash; const Uint64 renderPassHash = -#if MOBILEGL_BUILD_RECORD_ARM wireRenderPassCompatibilityId != 0 ? 0 : -#endif renderPassEntry.hash; // The pipeline-relevant subset only: glViewport / glScissor / glBlendColor / glStencilMask // and friends are dynamic state or not pipeline state at all, and keying the memo on the @@ -5448,9 +4823,7 @@ void main() { if (entry.pipeline != VK_NULL_HANDLE && entry.mode == mode && entry.programHash == programObj.hash && entry.vertexInputHash == vertexLayoutHash && entry.renderPassHash == renderPassHash && -#if MOBILEGL_BUILD_RECORD_ARM entry.wireRenderPassCompatibilityId == wireRenderPassCompatibilityId && -#endif entry.pipelineStateHash == pipelineStateHash && entry.renderStateCso == renderStateCso && entry.primitiveRestartEnable == primitiveRestartEnable && @@ -5637,7 +5010,6 @@ void main() { // (stencil) test always passes and nothing is written - even when the bound // image is a packed depth-stencil texture attached through only one half. { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const auto* fbo = MG_Pipe::MGPipeApplier().DrawFramebuffer(); if (fbo && !fbo->IsDefault) { @@ -5645,7 +5017,6 @@ void main() { if (fbo->Stencil.Kind == MG_Pipe::kMGPipeSurfaceKindNone) stencilTestEnabled = false; } } else -#endif { const auto& gatingFbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); @@ -5742,9 +5113,7 @@ void main() { .vertexInputHash = vertexLayoutHash, .pipelineLayout = programObj.pipelineLayout, .renderPass = renderPassEntry.renderPass, -#if MOBILEGL_BUILD_RECORD_ARM .wireRenderPassCompatibilityId = wireRenderPassCompatibilityId, -#endif .colorAttachmentCount = renderPassEntry.colorAttachmentCount, .rasterizationSamples = renderPassEntry.sampleCount, // ARB_sample_shading. Dropped on a device without sampleRateShading rather than @@ -5871,35 +5240,19 @@ void main() { MOBILEGL_ASSERT(payload.colorAttachmentCount <= PipelineFactory::PipelineCreatePayload::kMaxColorAttachments, "GetOrCreatePipeline: colorAttachmentCount=%u exceeds payload capacity", payload.colorAttachmentCount); -#if MOBILEGL_BUILD_RECORD_ARM const auto* wireFbo = MG_Config::DataArmIsRecord() ? MG_Pipe::MGPipeApplier().DrawFramebuffer() : nullptr; const auto drawFboBinding = wireFbo ? SharedPtr{} : MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); -#else - const auto& drawFboBinding = - MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); -#endif -#if MOBILEGL_BUILD_RECORD_ARM MOBILEGL_ASSERT(wireFbo != nullptr || drawFboBinding != nullptr, "GetOrCreatePipeline: draw framebuffer is null"); -#else - MOBILEGL_ASSERT(drawFboBinding != nullptr, "GetOrCreatePipeline: draw framebuffer is null"); -#endif -#if MOBILEGL_BUILD_RECORD_ARM const Bool isDefaultDrawFbo = wireFbo ? wireFbo->IsDefault : drawFboBinding->IsDefaultFramebuffer(); Array wireDrawBuffers{}; if (wireFbo) for (SizeT i = 0; i < wireDrawBuffers.size(); ++i) wireDrawBuffers[i] = wireFbo->DrawBuffers[i] < 0 ? FramebufferAttachmentType::None : static_cast(static_cast(FramebufferAttachmentType::Color0) + wireFbo->DrawBuffers[i]); const auto& drawBuffers = wireFbo ? wireDrawBuffers : drawFboBinding->GetDrawBuffers(); -#else - const Bool isDefaultDrawFbo = drawFboBinding->IsDefaultFramebuffer(); - const auto& drawBuffers = drawFboBinding->GetDrawBuffers(); -#endif auto resolveCompleteColorAttachmentTexture = [&](Uint32 drawBufferIndex) -> MG_State::GLState::ITextureObject* { -#if MOBILEGL_BUILD_RECORD_ARM if (wireFbo) return nullptr; -#endif if (isDefaultDrawFbo || drawBufferIndex >= drawBuffers.size()) { return nullptr; } @@ -5950,7 +5303,6 @@ void main() { attachmentColorWriteMask = 0; effectiveBlendEnabled = false; } -#if MOBILEGL_BUILD_RECORD_ARM if (wireFbo && !isDefaultDrawFbo) { const Int32 slot = wireFbo->DrawBuffers[i]; if (slot < 0 || wireFbo->Color[slot].Kind == MG_Pipe::kMGPipeSurfaceKindNone) { @@ -5958,7 +5310,6 @@ void main() { effectiveBlendEnabled = false; } } else -#endif if (!isDefaultDrawFbo && i < drawBuffers.size()) { const auto drawBuffer = drawBuffers[i]; colorAttachmentTexture = resolveCompleteColorAttachmentTexture(i); @@ -6054,12 +5405,10 @@ void main() { VkFormat colorAttachmentFormat = VK_FORMAT_UNDEFINED; Int textureExternalIndex = -1; -#if MOBILEGL_BUILD_RECORD_ARM if (wireFbo && !isDefaultDrawFbo) { const Int32 slot = wireFbo->DrawBuffers[i]; colorAttachmentFormat = ResolveWireImage(*wireFbo, wireFbo->Color[slot], VK_IMAGE_ASPECT_COLOR_BIT).format; } else -#endif if (isDefaultDrawFbo) { colorAttachmentFormat = m_swapchainObject.GetSurfaceFormat().format; } else if (colorAttachmentRenderbuffer != nullptr) { @@ -6188,9 +5537,7 @@ void main() { entry.programHash = programObj.hash; entry.vertexInputHash = vertexLayoutHash; entry.renderPassHash = renderPassHash; -#if MOBILEGL_BUILD_RECORD_ARM entry.wireRenderPassCompatibilityId = wireRenderPassCompatibilityId; -#endif entry.pipelineStateHash = pipelineStateHash; entry.renderStateCso = renderStateCso; entry.primitiveRestartEnable = primitiveRestartEnable; @@ -6556,12 +5903,10 @@ void main() { // the SAME draw-framebuffer binding the draw uses - see the assert below. MOBILEGL_ASSERT( [&] { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const auto* fbo = MG_Pipe::MGPipeApplier().DrawFramebuffer(); return isDefaultFbo == (fbo != nullptr && fbo->IsDefault); } -#endif const auto& fbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); return isDefaultFbo == (fbo != nullptr && fbo->IsDefaultFramebuffer()); @@ -6902,9 +6247,7 @@ void main() { if (entry.pipeline != VK_NULL_HANDLE && entry.mode == mode && entry.programHash == programObj.hash && entry.vertexInputHash == vaoLayoutHash && entry.renderPassHash == snap.renderPassHash && -#if MOBILEGL_BUILD_RECORD_ARM entry.wireRenderPassCompatibilityId == 0 && -#endif entry.pipelineStateHash == pipelineStateHash && entry.renderStateCso == renderStateCso && entry.primitiveRestartEnable == drawPrimitiveRestartEnable && @@ -6989,7 +6332,6 @@ void main() { // split server records every draw its client sends into the same frame command buffer, so // the same loading frame grows it the same way there. SplitOversizedRecording(); -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { if (!RewindWireDescriptorSetsIfDue()) return false; // The wire route returns before the monolith branch's draw-gated @@ -6998,7 +6340,6 @@ void main() { m_textureManager->CollectGarbage(); return SetupWireDraw(frame, mode, aspects, drawParams, pIndexBufferView); } -#endif // Sync each sampled texture at most once across this whole draw: the layout // probe loop, the post-transition loop, and ResolveSamplerDescriptor would // otherwise each re-run the full SyncTexture path on the same textures. @@ -7624,14 +6965,12 @@ void main() { void VulkanRenderer::DispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) { // Before the wire branch, for SetupDraw's reason. SplitOversizedRecording(); -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { if (!RewindWireDescriptorSetsIfDue()) return; m_textureManager->CollectGarbage(); DispatchWireCompute(numGroupsX, numGroupsY, numGroupsZ); return; } -#endif m_textureManager->CollectGarbage(); auto& frame = m_frameContext.GetCurrent(); // The DISPATCH accessor: with a pipeline bound this is its compute stage program @@ -7689,7 +7028,6 @@ void main() { void VulkanRenderer::DispatchComputeIndirect(GLintptr indirect) { SplitOversizedRecording(); -#if MOBILEGL_BUILD_RECORD_ARM // P8-SV: the wire arm's own indirect dispatch, DispatchCompute's shape one call over. if (MG_Config::DataArmIsRecord()) { if (!RewindWireDescriptorSetsIfDue()) return; @@ -7697,7 +7035,6 @@ void main() { DispatchWireComputeIndirect(indirect); return; } -#endif m_textureManager->CollectGarbage(); auto& frame = m_frameContext.GetCurrent(); // See DispatchCompute: the dispatch accessor, not the draw one. @@ -7800,15 +7137,11 @@ void main() { MGLOG_D("DirectVulkan: glMemoryBarrier(0x%x)", static_cast(barriers)); vkCmdPipelineBarrier(frame.commandBuffer, -#if MOBILEGL_BUILD_RECORD_ARM // ALL_COMMANDS does not include HOST. The barrier's // HOST_WRITE access must have a matching source stage. MG_Config::DataArmIsRecord() ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT | VK_PIPELINE_STAGE_HOST_BIT : VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, -#else - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, -#endif VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr); } @@ -7968,7 +7301,6 @@ void main() { #include "WireYuvImage.inc" void VulkanRenderer::Clear(GLbitfield mask) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const auto* fbo = MG_Pipe::MGPipeApplier().DrawFramebuffer(); if (!fbo) MagmaWireFatal("clear-framebuffer-record"); @@ -7980,7 +7312,6 @@ void main() { ClearWireFramebuffer(*fbo, payload); return; } -#endif m_clearManager->CollectGarbage(); if ((mask & (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) == 0) { return; @@ -8372,14 +7703,12 @@ void main() { void VulkanRenderer::QueueClearBufferPayload(GLenum buffer, GLint drawbuffer, const ClearAttachmentPayload& clearPayload) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const auto* fbo = MG_Pipe::MGPipeApplier().DrawFramebuffer(); if (!fbo) MagmaWireFatal("clear-buffer-framebuffer-record"); ClearWireFramebuffer(*fbo,clearPayload,buffer == GL_COLOR ? drawbuffer : -1); return; } -#endif auto* fbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject().get(); if (!fbo) { return; @@ -9296,7 +8625,6 @@ void main() { MOBILEGL_ASSERT(clearReady, "TryBlitToDefaultFramebufferWithShader: failed to materialize pending clear for textureId=%d", sourceTexture->GetExternalIndex()); -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 2-B2 (CONTRACT-P7 §5.2, (B')): THE MONOLITH ARM ON THE BAKED MODULE. Below // this line the pull build binds a hidden GL program, writes three default-block // uniforms into its global UBO and hands the sampler to the application's descriptor @@ -9342,118 +8670,6 @@ void main() { return BlitWireColorToDefault(source, destination, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, filter); } -#else - const Bool ready = m_textureManager->TransitionTextureForSampling(frame.commandBuffer, *sourceTexture); - if (!ready) { - MGLOG_E_ONCE("BlitFramebuffer skipped: failed to transition source textureId=%d for sampling", - sourceTexture->GetExternalIndex()); - return false; - } - if (m_textureManager->SyncTextureAndGetDescriptor(*sourceTexture) == nullptr) { - MGLOG_E_ONCE("BlitFramebuffer skipped: failed to resolve source textureId=%d after sampling transition", - sourceTexture->GetExternalIndex()); - return false; - } - const VkImageView sourceImageView = - m_textureManager->GetOrCreateSampledViewAtMipLevel(*sourceTexture, srcBinding.mipLevel); - MOBILEGL_ASSERT(sourceImageView != VK_NULL_HANDLE, - "TryBlitToDefaultFramebufferWithShader: failed to create sampled view for textureId=%d mip=%u", - sourceTexture->GetExternalIndex(), srcBinding.mipLevel); - - // A color-only blit never touches depth/stencil: let the default-FBO pass - // it opens skip the depth attachment (depth-less flavor). - auto* renderPassEntryPtr = - m_renderPassManager->GetOrCreateRenderPass(drawFbo, drawDefaultImageIndex, /*drawUsesDepthStencil=*/false); - if (renderPassEntryPtr == nullptr) { - // Declined (the builder logged which attachment). The caller's contract for `false` is - // "this blit was not serviced here", which is the honest answer. - return false; - } - auto& renderPassEntry = *renderPassEntryPtr; - const Bool ok = VkRenderPassManager::BeginRenderPass(frame.commandBuffer, renderPassEntry); - MOBILEGL_ASSERT(ok, "%s: BeginRenderPass failed", __func__); - - ApplyGLViewportState(frame.commandBuffer, renderPassEntry.extent, - m_swapchainObject.GetPreTransform(), drawIsDefaultFbo); - - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = {static_cast(renderPassEntry.extent.x()), static_cast(renderPassEntry.extent.y())}; - vkCmdSetScissor(frame.commandBuffer, 0, 1, &scissor); - - MOBILEGL_ASSERT(m_blitResources.program != nullptr, "TryBlitToDefaultFramebufferWithShader: blit program is null"); - const VkPipeline pipeline = GetOrCreateBlitPipeline(renderPassEntry); - MOBILEGL_ASSERT(pipeline != VK_NULL_HANDLE, "TryBlitToDefaultFramebufferWithShader: blit pipeline is null"); - vkCmdBindPipeline(frame.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - // The blit pipeline's narrower dynamic set (viewport/scissor only) - // leaves the other dynamic states undefined; its raw viewport/scissor - // writes also bypass the shadow. - ResetDynamicStateShadow(); - - auto* blitProgramData = static_cast(m_blitResources.program->MapUBO()); - MOBILEGL_ASSERT(blitProgramData != nullptr, "TryBlitToDefaultFramebufferWithShader: blit UBO is null"); - std::fill(blitProgramData, blitProgramData + m_blitResources.program->GetUBOSize(), Uint8{0}); - - BlitUniformData blitUniformData{}; - const float srcWidth = static_cast(srcBinding.extent.x()); - const float srcHeight = static_cast(srcBinding.extent.y()); - const float dstWidth = static_cast(dstBinding.extent.x()); - const float dstHeight = static_cast(dstBinding.extent.y()); - float dstNormWidth = dstWidth; - float dstNormHeight = dstHeight; - switch (m_swapchainObject.GetPreTransform()) { - case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: - case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: - dstNormWidth = dstHeight; - dstNormHeight = dstWidth; - break; - default: - break; - } - blitUniformData.srcRect[0] = static_cast(srcX0) / srcWidth; - blitUniformData.srcRect[1] = static_cast(srcY0) / srcHeight; - blitUniformData.srcRect[2] = static_cast(srcX1 - srcX0) / srcWidth; - blitUniformData.srcRect[3] = static_cast(srcY1 - srcY0) / srcHeight; - blitUniformData.dstRect[0] = static_cast(dstX0) / dstNormWidth; - blitUniformData.dstRect[1] = static_cast(dstY0) / dstNormHeight; - blitUniformData.dstRect[2] = static_cast(dstX1 - dstX0) / dstNormWidth; - blitUniformData.dstRect[3] = static_cast(dstY1 - dstY0) / dstNormHeight; - blitUniformData.surfaceTransform = static_cast(ToBlitSurfaceTransform(m_swapchainObject.GetPreTransform())); - - auto writeUniform = [&](Int location, const void* data, SizeT size) { - MOBILEGL_ASSERT(location >= 0, "TryBlitToDefaultFramebufferWithShader: invalid uniform location"); - const Uint offset = m_blitResources.program->GetUniformOffset(static_cast(location)); - // A RETURN, not only an assert - see GenerateDepthMipmapWithShader's copy of this - // guard: kInvalidUniformOffset must not reach the memcpy in a release build. - if (offset == MG_State::GLState::ProgramObject::kInvalidUniformOffset || - offset + size > m_blitResources.program->GetUBOSize()) { - MOBILEGL_ASSERT(false, "TryBlitToDefaultFramebufferWithShader: uniform write out of bounds"); - return; - } - memcpy(blitProgramData + offset, data, size); - }; - writeUniform(m_blitResources.srcRectLocation, blitUniformData.srcRect, sizeof(blitUniformData.srcRect)); - writeUniform(m_blitResources.dstRectLocation, blitUniformData.dstRect, sizeof(blitUniformData.dstRect)); - writeUniform(m_blitResources.surfaceTransformLocation, &blitUniformData.surfaceTransform, - sizeof(blitUniformData.surfaceTransform)); - m_blitResources.program->MarkUBOContentDirty(); - - const auto samplerBindingOverride = UniformManager::SamplerBindingOverride{ - .binding = m_blitResources.samplerBinding, - .texture = sourceTexture.get(), - .sampler = (filter == GL_LINEAR ? m_blitResources.linearSampler.get() - : m_blitResources.nearestSampler.get()), - .imageView = sourceImageView, - }; - ProgramFactory::CompileOptionFlags blitTransformFlags = 0; - const auto& blitProgramObj = m_programFactory->GetOrCreateProgram(*m_blitResources.program, blitTransformFlags); - const Bool bound = m_uniformManager->BindProgramUniformBuffers( - frame.commandBuffer, *m_blitResources.program, blitProgramObj, m_frameContext.GetCurrentFrameIndex(), - VK_PIPELINE_BIND_POINT_GRAPHICS, &samplerBindingOverride); - MOBILEGL_ASSERT(bound, "TryBlitToDefaultFramebufferWithShader: BindProgramUniformBuffers failed"); - vkCmdDraw(frame.commandBuffer, 3, 1, 0, 0); - return true; -#endif } // A single-aspect depth/stencil copy between two images of the same format. An image copy @@ -9511,12 +8727,10 @@ void main() { void VulkanRenderer::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { BlitWireFramebuffers(srcX0,srcY0,srcX1,srcY1,dstX0,dstY0,dstX1,dstY1,mask,filter); return; } -#endif auto readFbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject(); auto drawFbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); BlitNamedFramebuffer(readFbo, drawFbo, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); @@ -10153,12 +9367,10 @@ void main() { void VulkanRenderer::CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { CopyWireFramebufferToTexture(target,level,xoffset,yoffset,x,y,width,height); return; } -#endif if (width <= 0 || height <= 0) { return; } @@ -10472,10 +9684,8 @@ void main() { } Uint CopyImageEndpointName(const CopyImageEndpoint& endpoint) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) return endpoint.IsRenderbuffer() ? endpoint.RenderbufferHandle.Slot : endpoint.TextureHandle.Slot; -#endif if (endpoint.IsRenderbuffer()) return endpoint.Renderbuffer->GetExternalIndex(); return endpoint.Texture ? endpoint.Texture->GetExternalIndex() : 0u; } @@ -10486,14 +9696,12 @@ void main() { const CopyImageEndpoint& dstEndpoint, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) { -#if MOBILEGL_BUILD_RECORD_ARM const Bool wire = MG_Config::DataArmIsRecord(); MG_Pipe::MGPipeHandle dstStorageHandle = dstEndpoint.TextureHandle; if (wire && HasPendingRecordedWork() && !FlushPendingCommands()) { if (LatchWireDeviceLoss("copy-image-flush")) return; MagmaWireFatal("copy-image-flush"); } -#endif MOBILEGL_ASSERT(srcEndpoint.Exists() && dstEndpoint.Exists(), "CopyImageSubData requires valid source and destination images."); // The frontend already declines a zero or negative extent, so anything else here is a @@ -10521,9 +9729,7 @@ void main() { const auto* dstStorageTexture = dstEndpoint.Texture ? &VkTextureManager::StorageTextureOf(*dstEndpoint.Texture) : nullptr; if ( -#if MOBILEGL_BUILD_RECORD_ARM !wire && -#endif srcStorageTexture == dstStorageTexture && srcEndpoint.Renderbuffer == dstEndpoint.Renderbuffer) { MGLOG_E_ONCE("%s: in-place copy on objectId=%u is not supported; declining the copy", __func__, CopyImageEndpointName(srcEndpoint)); @@ -10534,7 +9740,6 @@ void main() { // SyncTextureAndGetDescriptor the copy always used; the renderbuffer arm goes through the // render-pass manager, which is where a renderbuffer's VkImage lives. const auto resolveImage = [this](const CopyImageEndpoint& endpoint, CopyImageVkImage& out) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { const Bool renderbuffer = endpoint.IsRenderbuffer(); // The same handle-keyed allocation used by wire FBO clear/draw/read. @@ -10553,7 +9758,6 @@ void main() { out.format = resource->format; return out.image != VK_NULL_HANDLE; } -#endif if (endpoint.IsRenderbuffer()) { auto* resource = m_renderPassManager->GetOrCreateRenderbufferResource(endpoint.Renderbuffer); if (resource == nullptr) return false; @@ -10588,7 +9792,6 @@ void main() { CopyImageVkImage dstImage{}; const Bool srcResolved = resolveImage(srcEndpoint, srcImage); const Bool dstResolved = resolveImage(dstEndpoint, dstImage); -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 2-B, CONTRACT-P7 §3.2: `copy-image-in-place@P7` RETIRES. // // What the Fatal here used to say was true of the code below it and of nothing else: the @@ -10605,9 +9808,6 @@ void main() { const Bool inPlace = wire && srcImage.image != VK_NULL_HANDLE && srcImage.image == dstImage.image; if (wire) m_textureManager->FlushPendingUploads(); -#else - constexpr Bool inPlace = false; -#endif // Real checks, not MOBILEGL_ASSERT: the assertions this replaces compile to nothing in // a release build, which is where both observed failures happened - a null resource // dereferenced right below (lavapipe) and a mip level the VkImage does not have handed @@ -10632,7 +9832,6 @@ void main() { // dstLevel and the z origins below arrived relative to whichever name the application // passed - so a view's level 0 has to become the parent level it opened onto before it // can index a subresource, exactly as at every other attachment boundary. -#if MOBILEGL_BUILD_RECORD_ARM if (wire) { const auto mapSubresource = [this](const CopyImageEndpoint& endpoint, GLint& mip, GLint& layer) { if (endpoint.IsRenderbuffer()) { @@ -10649,7 +9848,6 @@ void main() { (void)mapSubresource(srcEndpoint, srcLevel, srcZ); dstStorageHandle = mapSubresource(dstEndpoint, dstLevel, dstZ); } -#endif srcLevel = static_cast(ToStorageMipLevel(srcEndpoint.Texture.get(), srcLevel)); dstLevel = static_cast(ToStorageMipLevel(dstEndpoint.Texture.get(), dstLevel)); srcZ = static_cast(ToStorageArrayLayer(srcEndpoint.Texture.get(), srcZ)); @@ -10752,7 +9950,6 @@ void main() { __func__, srcZ, srcSlices.availableSlices, dstZ, dstSlices.availableSlices, srcDepth); return; } -#if MOBILEGL_BUILD_RECORD_ARM // THE ONE IN-PLACE SHAPE THAT STAYS A DECLINE (§3.2). GL 4.6 core 18.3.2: if the source // and destination name the same image AND the same level AND the same layers, the result // is UNDEFINED where the regions overlap. GENERAL makes the command legal to record, not @@ -10779,7 +9976,6 @@ void main() { return; } } -#endif // Syncing either endpoint can flush and retire the current command buffer for // a texture upload. Prepare recording only after both images and uploads are ready. @@ -10792,9 +9988,7 @@ void main() { } const auto materializeClear = [this, &frame](const CopyImageEndpoint& endpoint) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) return true; -#endif if (endpoint.IsRenderbuffer()) { return MaterializePendingClearForRenderbuffer(frame.commandBuffer, endpoint.Renderbuffer); } @@ -10925,12 +10119,10 @@ void main() { srcImage.image, copySourceLayout, dstImage.image, copyDestinationLayout, 1, ©Region); -#if MOBILEGL_BUILD_RECORD_ARM // The copy coordinates above are already storage-relative. Name that // storage here too, so a texture view's offsets are not applied twice. if (wire && !dstImage.isRenderbuffer) m_textureManager->MarkWireTextureGpuWritten(dstStorageHandle, dstMipLevel, dstSlices.BaseArrayLayer(), dstSlices.slicesAreDepth ? 1u : copySliceCount); -#endif VkPipelineStageFlags srcRestoreStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; VkAccessFlags srcRestoreAccessMask = 0; @@ -11027,7 +10219,6 @@ void main() { // UNDER #if, although this function serves both arms of the disaggregated build: the PULL // build has no wire arm, cannot flush before a readback, and is the image G1 pins to // 0xa52203. Its single-fence wait stays the statement it always was. -#if MOBILEGL_BUILD_RECORD_ARM Vector readbackFences; readbackFences.reserve(m_inFlightSubmits.size() + 1); for (const auto& record : m_inFlightSubmits) { @@ -11044,9 +10235,6 @@ void main() { // outstanding; the code this replaces waited on one. VkResult result = vkWaitForFences(m_device, static_cast(readbackFences.size()), readbackFences.data(), VK_TRUE, UINT64_MAX); -#else - VkResult result = vkWaitForFences(m_device, 1, &frame.imageInFlightFence, VK_TRUE, UINT64_MAX); -#endif if (result != VK_SUCCESS) { NoteDeviceLoss(result, "readback vkWaitForFences"); MGLOG_E_ONCE("DirectVulkan readback: vkWaitForFences returned %d", result); @@ -11072,12 +10260,10 @@ void main() { void VulkanRenderer::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { ReadWirePixels(x,y,width,height,format,type,pixels); return; } -#endif if (width <= 0 || height <= 0) { return; } @@ -11770,13 +10956,9 @@ void main() { const SizeT dstPixelBytes = packed.size() / pixelCount; // Store honoring the client pack state (single slice). -#if MOBILEGL_BUILD_RECORD_ARM const SharedPtr wireReplyHasNoPackBuffer; -#endif const auto& pixelPackBufferObject = -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::DataArmIsRecord() ? wireReplyHasNoPackBuffer : -#endif MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject(); const auto packParams = MG_Pipe::gPipeInputs.GetPixelStoreParameters(false); const SizeT rowPixels = static_cast(packParams.RowLength > 0 ? packParams.RowLength : width); @@ -12052,12 +11234,10 @@ void main() { } void VulkanRenderer::GenerateMipmap(GLenum target) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { GenerateWireMipmap(); return; } -#endif const auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); // Whatever is left here is a coverage gap in this backend, not a broken invariant, so it // declines (leaving the mip chain unwritten) rather than asserting the process down. What @@ -12157,7 +11337,6 @@ void main() { "GenerateMipmap: depth-stencil mipmap generation is not supported yet."); } -#if MOBILEGL_BUILD_RECORD_ARM // P5c (T5 / tx): under an active transport the generated chain is defined on the // server's staged shadow (keyed by the synced TextureResource above) and the client's // level storage is never written; in monolith the client-object path runs unchanged. @@ -12165,10 +11344,6 @@ void main() { MG_Config::DataArmIsRecord() ? EnsureGenerateMipmapShadowAllocated(*resource, baseMipLevel, uploadTargets) : EnsureGenerateMipmapStorageAllocated(*mipmapTexture, baseMipLevel, endMipLevel); -#else - const Bool allocatedMipmapStorage = - EnsureGenerateMipmapStorageAllocated(*mipmapTexture, baseMipLevel, endMipLevel); -#endif MOBILEGL_ASSERT(allocatedMipmapStorage, "GenerateMipmap could not allocate a full mip chain for this texture."); resource = m_textureManager->SyncTextureAndGetDescriptor(*texture); @@ -12457,10 +11632,8 @@ void main() { "undefined behaviour rather than a capture"); return false; } -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) return BeginWireXfbCaptureForDraw(frame); -#endif const auto& program = MG_Pipe::gPipeInputs.GetTransformFeedbackProgram(); if (!program || program->GetTransformFeedbackVaryingCount() == 0) { return false; @@ -13580,13 +12753,8 @@ void main() { return false; } if (m_device == VK_NULL_HANDLE || m_graphicsQueue == VK_NULL_HANDLE) { -#if MOBILEGL_BUILD_RECORD_ARM return IsFrameSerialComplete(serial); -#else - return true; -#endif } -#if MOBILEGL_BUILD_RECORD_ARM // More than one submit can carry the same frame serial (mid-frame flush, // then Present). The completed floor is clamped below any serial still // held by an in-flight record; the first matching fence is not proof. @@ -13604,22 +12772,6 @@ void main() { TryDrainFrameTransients(); if (IsFrameSerialComplete(serial)) return true; } -#else - // Pull build's historical one-fence wait stays byte-identical. - for (const auto& record : m_inFlightSubmits) { - if (record.frameSerial < serial || record.fence == VK_NULL_HANDLE) { - continue; - } - if (vkWaitForFences(m_device, 1, &record.fence, VK_TRUE, UINT64_MAX) != VK_SUCCESS) { - break; // fall through to the drain below - } - OnSubmitsCompletedUpTo(record.submitIndex); - // Deliberately no NotifyDeviceIdle() here: that claims every submission has retired, - // which is only true after a real queue drain. Work past this record may still run. - TryDrainFrameTransients(); - return true; - } -#endif // No usable record - fall back to draining the graphics queue. This over-waits (bounded by // the in-flight frame count) but never deadlocks. @@ -13634,11 +12786,7 @@ void main() { // The queue was just drained; take the free frame-boundary drain when // nothing is recorded (present-less timer-query loops). No-op otherwise. TryDrainFrameTransients(); -#if MOBILEGL_BUILD_RECORD_ARM return IsFrameSerialComplete(serial); -#else - return true; -#endif } Uint64 VulkanRenderer::GetSyncPointSubmitIndex() const { @@ -13652,15 +12800,10 @@ void main() { return false; } const auto& frame = m_frameContext.GetCurrent(); -#if MOBILEGL_BUILD_RECORD_ARM return frame.isCommandRecording || frame.hasCommandBufferRecorded || frame.isPreCommandRecording || frame.hasPreCommandBufferRecorded; -#else - return frame.isCommandRecording || frame.hasCommandBufferRecorded; -#endif } -#if MOBILEGL_BUILD_RECORD_ARM Bool VulkanRenderer::RewindWireDescriptorSetsIfDue() { if (!m_uniformManager || m_frameContext.GetFrameCount() == 0) return true; const Uint32 frameIndex = m_frameContext.GetCurrentFrameIndex(); @@ -13694,7 +12837,6 @@ void main() { UniformManager::kWireDescriptorSetBudget, cachedSets); return true; } -#endif Bool VulkanRenderer::IsSubmitIndexComplete(Uint64 submitIndex) { if (submitIndex <= m_completedSubmitCounter) { @@ -13729,7 +12871,6 @@ void main() { } } -#if MOBILEGL_BUILD_RECORD_ARM Bool VulkanRenderer::WaitForSubmitsUpTo(Uint64 submitIndex, Uint64 timeoutNs) { if (submitIndex <= m_completedSubmitCounter) return true; if (submitIndex > m_submitCounter || m_device == VK_NULL_HANDLE) return false; @@ -13747,11 +12888,9 @@ void main() { MGLOG_E_ONCE("WaitForSubmitsUpTo: vkWaitForFences returned %d", result); return false; } -#endif void VulkanRenderer::OnSubmitsCompletedUpTo(Uint64 submitIndex) { m_completedSubmitCounter = std::max(m_completedSubmitCounter, submitIndex); -#if MOBILEGL_BUILD_RECORD_ARM // ---- P7 wave 2 package B3: THE COMPLETED-FRAME-SERIAL FLOOR MUST BE PROVABLE -------- // // "Frame-serial completion piggybacks on submission completion" holds only while a @@ -13778,19 +12917,11 @@ void main() { // unchanged, which is what keeps G1's .text byte-identical. Bool retiredAny = false; Uint64 advanceTo = 0; -#endif while (!m_inFlightSubmits.empty() && m_inFlightSubmits.front().submitIndex <= submitIndex) { SubmitRecord record = m_inFlightSubmits.front(); m_inFlightSubmits.erase(m_inFlightSubmits.begin()); -#if MOBILEGL_BUILD_RECORD_ARM retiredAny = true; advanceTo = std::max(advanceTo, record.frameSerial); -#else - // Frame-serial completion piggybacks on submission completion. - // NotifyFrameSerialComplete refuses the current (still-recording) - // serial, so mid-frame flush records do not mark it early. - m_bufferManager.NotifyFrameSerialComplete(record.frameSerial); -#endif if (!record.pooledFence || m_device == VK_NULL_HANDLE) { continue; // frame-slot fences are reset/destroyed by FrameContext } @@ -13800,7 +12931,6 @@ void main() { vkDestroyFence(m_device, record.fence, nullptr); } } -#if MOBILEGL_BUILD_RECORD_ARM if (retiredAny) { // Clamp to one below the lowest serial still in flight. for (const auto& remaining : m_inFlightSubmits) { @@ -13843,22 +12973,17 @@ void main() { } m_bufferManager.NotifyFrameSerialComplete(advanceTo); } -#endif // Mid-frame-flushed command buffers whose submission just completed can // be freed now; present-less flush loops have no other reclaim point. m_frameContext.FreeRetiredCommandBuffersCompletedUpTo(m_completedSubmitCounter); -#if MOBILEGL_BUILD_RECORD_ARM CollectWireObjects(m_completedSubmitCounter); -#endif #if MOBILEGL_BUILD_DISAGGREGATED RecycleSharedImageSemaphores(m_completedSubmitCounter); #endif } Bool VulkanRenderer::TryDrainFrameTransients() { -#if MOBILEGL_BUILD_RECORD_ARM if (m_wirePreparationDepth != 0) return false; -#endif if (m_device == VK_NULL_HANDLE || m_frameContext.GetFrameCount() == 0) { return false; } @@ -13872,7 +12997,6 @@ void main() { return false; } -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { // Texture uploads submit on this queue with their own fences. The // renderer watermark alone cannot prove images/views are idle. @@ -13883,7 +13007,6 @@ void main() { CollectWireObjects(m_completedSubmitCounter, true); ClearAllWireDrawPassCaches(); } -#endif // Every submission is complete and nothing recorded references the // per-frame transients. Pure-reclaim work runs on every drain: it only @@ -13916,7 +13039,6 @@ void main() { // loops still rewind the arena and age their caches every 8 iterations - // bounded by 8 iterations' transient usage. ++m_drainsSinceLastPresent; -#if MOBILEGL_BUILD_RECORD_ARM // B3 probe: a drain that reaches here found the GPU caught up and nothing recording. // Every 8th one is treated as a FRAME BOUNDARY - mid-frame. This probe is what REFUTED // that as the OpenRA mechanism (one successful drain, zero boundary works across the @@ -13934,7 +13056,6 @@ void main() { static_cast(m_completedSubmitCounter)); } } -#endif if ((m_drainsSinceLastPresent % 8) != 0) { return true; } @@ -14005,9 +13126,7 @@ void main() { } Bool VulkanRenderer::SubmitPendingCommandBuffer(FrameContext::FrameData& frame, VkFence fence, Bool pooledFence) { -#if MOBILEGL_BUILD_RECORD_ARM RetireWireDrawPass(); -#endif // Batched texture uploads must reach the queue before the frame's // commands: the recording being submitted may sample images whose // texels only exist in the texture manager's open upload batch. @@ -14071,12 +13190,8 @@ void main() { // pooled fences and mid-frame command buffers. RefreshCompletedSubmits(); auto& frame = m_frameContext.GetCurrent(); -#if MOBILEGL_BUILD_RECORD_ARM if (!frame.isCommandRecording && !frame.hasCommandBufferRecorded && !frame.isPreCommandRecording && !frame.hasPreCommandBufferRecorded) { -#else - if (!frame.isCommandRecording && !frame.hasCommandBufferRecorded) { -#endif // GL flush semantics still demand batched texture uploads start // executing in finite time even when no draw was recorded. if (m_textureManager) { @@ -14119,15 +13234,9 @@ void main() { const VkResult retireResult = m_frameContext.RetireCurrentCommandBuffer(submittingPreCommandBuffer); if (retireResult != VK_SUCCESS) { MGLOG_E_ONCE("FlushPendingCommands: RetireCurrentCommandBuffer returned %d; draining submission", retireResult); -#if MOBILEGL_BUILD_RECORD_ARM if (WaitForSubmitsUpTo(m_submitCounter, UINT64_MAX)) { // Every registered fence through this submission was waited. } else if (vkQueueWaitIdle(m_graphicsQueue) == VK_SUCCESS) { -#else - if (vkWaitForFences(m_device, 1, &fence, VK_TRUE, UINT64_MAX) == VK_SUCCESS) { - OnSubmitsCompletedUpTo(m_submitCounter); - } else if (vkQueueWaitIdle(m_graphicsQueue) == VK_SUCCESS) { -#endif m_bufferManager.NotifyDeviceIdle(); OnSubmitsCompletedUpTo(m_submitCounter); } else { @@ -14161,7 +13270,6 @@ void main() { return m_deviceLost; } -#if MOBILEGL_BUILD_RECORD_ARM Bool VulkanRenderer::LatchWireDeviceLoss(const char* site) { if (!IsDeviceLost()) return false; if (!m_deviceLossLatched) { @@ -14201,7 +13309,6 @@ void main() { } return true; } -#endif Bool VulkanRenderer::FlushForSyncPoint(Uint64 submitIndex) { // A flush only helps a sync point whose commands are not submitted @@ -14278,33 +13385,10 @@ void main() { return false; } } -#if MOBILEGL_BUILD_RECORD_ARM if (!WaitForSubmitsUpTo(submitIndex, timeoutNs)) return false; // A blocking wait can drain a present-less loop's frame transients. TryDrainFrameTransients(); return true; -#else - for (const auto& record : m_inFlightSubmits) { - if (record.submitIndex >= submitIndex) { - const VkResult result = vkWaitForFences(m_device, 1, &record.fence, VK_TRUE, timeoutNs); - if (result == VK_SUCCESS) { - OnSubmitsCompletedUpTo(record.submitIndex); - // The wait already stalled the pipeline; if it happens to - // have drained everything (present-less fence loops), take - // the free frame-boundary drain. No-op otherwise. - TryDrainFrameTransients(); - return true; - } - if (result != VK_TIMEOUT) { - MGLOG_E_ONCE("WaitForSubmitIndex: vkWaitForFences returned %d", result); - } - return false; - } - } - // No in-flight record at or beyond the index: it was already observed - // complete via a fence wait on a later submission. - return true; -#endif } void VulkanRenderer::OnFrameCommandRecordingBegan(VkCommandBuffer commandBuffer) { @@ -14461,7 +13545,6 @@ void main() { return; } m_presentSuspended = false; -#if MOBILEGL_BUILD_RECORD_ARM // A slot's Present fence alone does not prove its older pooled // flushes retired. Wait the full prefix before FrameContext may // free its retired command buffers and reset the slot fence. @@ -14471,7 +13554,6 @@ void main() { if (LatchWireDeviceLoss("deferred-acquire-submit-wait")) return; MagmaWireFatal("deferred-acquire-submit-wait"); } -#endif const VkResult acquireResult = m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired); if (acquireResult == VK_SUBOPTIMAL_KHR) { @@ -14560,9 +13642,7 @@ void main() { const VkResult presentSubmit = vkQueueSubmit(m_graphicsQueue, 1, &submitPacket.submitInfo, frame.imageInFlightFence); #endif NoteDeviceLoss(presentSubmit, "Present vkQueueSubmit"); -#if MOBILEGL_BUILD_RECORD_ARM if (presentSubmit != VK_SUCCESS && LatchWireDeviceLoss("present-submit")) return; -#endif VK_VERIFY(presentSubmit); RegisterSubmit(frame.imageInFlightFence, /*pooledFence=*/false); frame.lastSubmitIndex = m_submitCounter; @@ -14600,9 +13680,7 @@ void main() { result = VK_SUCCESS; } NoteDeviceLoss(result, "vkQueuePresentKHR"); -#if MOBILEGL_BUILD_RECORD_ARM if (result != VK_SUCCESS && LatchWireDeviceLoss("present-queue")) return; -#endif VK_VERIFY(result, "Present, vkQueuePresentKHR"); // EGL swap semantics: the presented color buffer's content is undefined the // next time this image is acquired (EGL_BUFFER_DESTROYED, the default swap @@ -14652,7 +13730,6 @@ void main() { // 3) Advance frame slot. m_frameContext.AdvanceToNext(); -#if MOBILEGL_BUILD_RECORD_ARM // FrameContext waits then resets the slot fence and frees retired // command buffers. A later Present fence is not aggregate proof for // earlier pooled flushes, so wait every registered submission in this @@ -14663,7 +13740,6 @@ void main() { if (LatchWireDeviceLoss("present-slot-submit-wait")) return; MagmaWireFatal("present-slot-submit-wait"); } -#endif // 4) Wait/reset/acquire for next frame. result = m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired); if (result == VK_SUBOPTIMAL_KHR) { @@ -14688,20 +13764,16 @@ void main() { m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired); } NoteDeviceLoss(result, "vkAcquireNextImageKHR"); -#if MOBILEGL_BUILD_RECORD_ARM if (result != VK_SUCCESS && LatchWireDeviceLoss("present-acquire")) return; -#endif VK_VERIFY(result, "Present, vkAcquireNextImageKHR"); // Pull keeps its historical slot-fence inference. In a disaggregated // build the aggregate wait above already retired the registered prefix // before FrameContext reset the slot fence; this repeat is idempotent. OnSubmitsCompletedUpTo(m_frameContext.GetCurrent().lastSubmitIndex); CollectDeferredDepthMipmapCleanup(m_frameContext.GetCurrentFrameIndex()); -#if MOBILEGL_BUILD_RECORD_ARM // Its previous recording has completed. Drop cached attachment views // before the texture manager can release their retired images. ClearWireDrawPassCache(m_frameContext.GetCurrentFrameIndex()); -#endif m_textureManager->BeginFrame(m_frameContext.GetCurrentFrameIndex()); m_bufferManager.BeginFrame(m_frameContext.GetCurrentFrameIndex()); m_convertedVertexStreams.clear(); @@ -15363,7 +14435,6 @@ void main() { getPhysicalDeviceProperties2 = reinterpret_cast( vkGetInstanceProcAddr(m_instance, "vkGetPhysicalDeviceProperties2KHR")); } -#if MOBILEGL_BUILD_RECORD_ARM // Linux/Android request Vulkan 1.1: a 1.2 physical device alone does // not expose the promoted renderpass2/depth-resolve API to this app. #ifdef VK_USE_PLATFORM_WIN32_KHR @@ -15462,7 +14533,6 @@ void main() { m_sharedImageSyncFd ? "wait and signal on the GPU (SYNC_FD semaphores)" : "are waited for on the CPU (no SYNC_FD semaphore import and export)"); } -#endif #endif if ((descriptorIndexingCore || descriptorIndexingExtension) && getPhysicalDeviceFeatures2 != nullptr && getPhysicalDeviceProperties2 != nullptr) { @@ -15887,7 +14957,6 @@ void main() { } } -#if MOBILEGL_BUILD_RECORD_ARM // YUV shared images (WireYuvImage.inc) are sampled through a VkSamplerYcbcrConversion, a // feature of its own; asked only where AHardwareBuffers are imported at all. m_samplerYcbcrConversion = false; @@ -15904,7 +14973,6 @@ void main() { m_samplerYcbcrConversion = true; } } -#endif // VK_EXT_multi_draw: tier 1 of the multi-draw dispatch - one vkCmdDrawMulti(Indexed)EXT // for a whole glMultiDraw* batch (VkMultiDrawIndexedInfoEXT carries per-draw @@ -15956,7 +15024,6 @@ void main() { } } -#if MOBILEGL_BUILD_RECORD_ARM // Codex closeout finding 2 (cf-magma): GL 4.6 core 8.26 makes an access through an // invalid image unit load zero and DISCARD stores and atomics. A null storage-image // descriptor is that rule exactly, so the wire arm binds one for such a unit @@ -15989,7 +15056,6 @@ void main() { MGLOG_I("Magma wire: robustness2 nullDescriptor %s (%s)", m_wireNullDescriptor ? "enabled" : "unavailable", robustness2Name != nullptr ? robustness2Name : "no robustness2 extension"); } -#endif deviceCreateInfo.enabledExtensionCount = static_cast(enabledDeviceExtensions.size()); deviceCreateInfo.ppEnabledExtensionNames = enabledDeviceExtensions.data(); @@ -16036,12 +15102,10 @@ void main() { m_shaderDrawParametersFeatureEnabled ? "true" : "false"); VK_VERIFY(vkCreateDevice(m_physicalDevice.handle, &deviceCreateInfo, nullptr, &m_device), "vkCreateDevice"); -#if MOBILEGL_BUILD_RECORD_ARM if (wireDepthResolveEnabled) { m_wireCreateRenderPass2 = reinterpret_cast( vkGetDeviceProcAddr(m_device, wireDepthResolveCore ? "vkCreateRenderPass2" : "vkCreateRenderPass2KHR")); } -#endif #if MOBILEGL_BUILD_DISAGGREGATED if (m_wireAhbImport) { m_wireGetAhbProperties = @@ -16071,7 +15135,6 @@ void main() { MGLOG_W("VK_KHR_draw_indirect_count enabled but vkCmdDrawIndexedIndirectCount entry point is missing, will continue as if VK_KHR_draw_indirect_count is not supported!"); m_drawIndirectCountExtensionEnabled = false; } -#if MOBILEGL_BUILD_RECORD_ARM // P8-D: the wire arm's glMultiDrawArraysIndirectCount. Null = that verb reads its count on // the CPU (WireDraw.inc's DrawWireIndirectNative answers false for it). s_vkCmdWireDrawIndirectCount = reinterpret_cast( @@ -16080,7 +15143,6 @@ void main() { s_vkCmdWireDrawIndirectCount = reinterpret_cast( vkGetDeviceProcAddr(m_device, "vkCmdDrawIndirectCount")); } -#endif s_vkCmdDrawMultiEXT = nullptr; s_vkCmdDrawMultiIndexedEXT = nullptr; @@ -16201,13 +15263,10 @@ void main() { // Last, because it records on m_graphicsQueue: decide the PRIMITIVES_GENERATED // reroute for XFB-inactive draws. Nothing else has touched the queue yet. ArmPrimGenReroute(); -#if MOBILEGL_BUILD_RECORD_ARM // Same terms: it records on m_graphicsQueue, which nothing but the probe above has used. ArmWireDepthResolveOrder(); -#endif } -#if MOBILEGL_BUILD_RECORD_ARM // P7 gate 5 (g5-msprobe): THE ARM ORDER OF THE MULTISAMPLE DEPTH/STENCIL RESOLVE IS A MEASURED // PROPERTY OF THIS DEVICE. WireDepthResolveArm.h says why (the Adreno 830's no-draw // VK_KHR_depth_stencil_resolve pass writes nothing), WireDepthResolveProbe.h what is run. The @@ -16287,7 +15346,6 @@ void main() { }); m_wirePreferShaderDepthResolve = resolved.preferShader; } -#endif void VulkanRenderer::ArmPrimGenReroute() { using namespace MG_Util::SelfTest; @@ -16832,13 +15890,11 @@ void main() { vkDeviceWaitIdle(m_device); OnSubmitsCompletedUpTo(m_submitCounter); -#if MOBILEGL_BUILD_RECORD_ARM // The old swapchain will be destroyed below, including recordings that // are being abandoned instead of submitted. Release all their views now. DestroyWireDrawPass(); CollectWireObjects(m_submitCounter, true); ClearAllWireDrawPassCaches(); -#endif if (m_timerQueryManager) { // The in-progress command buffer is abandoned below (its recording @@ -17104,11 +16160,9 @@ void main() { FlushPendingCommands(); VK_VERIFY(vkDeviceWaitIdle(m_device)); OnSubmitsCompletedUpTo(m_submitCounter); -#if MOBILEGL_BUILD_RECORD_ARM DestroyWireDrawPass(); CollectWireObjects(m_submitCounter, true); ClearAllWireDrawPassCaches(); -#endif if (m_renderPassManager) m_renderPassManager->PurgeRenderPasses(); InvalidatePipelineMemo(); ResetDynamicStateShadow(); @@ -17157,7 +16211,6 @@ void main() { return m_instance; } -#if MOBILEGL_BUILD_RECORD_ARM Bool VulkanRenderer::GetWireAhbImport(WireAhbImport& out) const { out = WireAhbImport{}; if (!m_wireAhbImport || m_device == VK_NULL_HANDLE || m_wireGetAhbProperties == nullptr) return false; @@ -17168,7 +16221,6 @@ void main() { out.getAhbProperties = m_wireGetAhbProperties; return true; } -#endif Bool VulkanRenderer::IsDrawIndirectCountExtensionEnabled() const { return m_drawIndirectCountExtensionEnabled; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index 0bb047cf..8c91765a 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -22,13 +22,11 @@ #include "VkSamplerManager.h" #include "VkTextureManager.h" #include "VkTimerQueryManager.h" -#if MOBILEGL_BUILD_RECORD_ARM #include "GpuProgressMarkers.h" #include "WireRenderPassCompatibility.h" #if MOBILEGL_BUILD_DISAGGREGATED #include #endif -#endif #include "MG_Util/Math/VectorTypes.h" #include #include @@ -150,7 +148,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // of the swapchain image acquired for it (SwapchainObject::BufferAgeOf). Asking makes the // target keep its presented images' content from then on. Int32 CurrentDrawBufferAge(); -#if MOBILEGL_BUILD_RECORD_ARM VkBufferManager& GetWireBufferManager() { return m_bufferManager; } Bool FlushWirePendingCommandsForTextureUpdate() { // A new texture upload must not race graphics work that samples @@ -222,7 +219,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // P13 W5: no transport, no shared image (only a server allocates one), so a texture's // sharedImageId is never set and there is nothing to acquire. void AcquireSharedImage(VkTextureManager::TextureResource&) {} -#endif #endif // FrameContext::IRecordingObserver: prepares the frame's timer-query @@ -296,11 +292,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); void GenerateMipmap(GLenum target); void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels); -#if MOBILEGL_BUILD_RECORD_ARM // Server resource handle in, tightly packed owned bytes out. No frontend // texture, pixel-pack state or PBO is consulted by this readback. Bool ReadTextureImageWire(const MG_Pipe::MGPReadbackInfo& info, Vector& ownedBytes); -#endif // GL_DEPTH_COMPONENT / GL_DEPTH_STENCIL / GL_STENCIL_INDEX readback from the // read framebuffer's depth/stencil attachment (per-aspect buffer copies with // CPU repacking into the requested client layout). @@ -410,7 +404,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // loss here is this session's alone. void NoteDeviceLoss(VkResult result, const char* where); Bool IsDeviceLost(); -#if MOBILEGL_BUILD_RECORD_ARM // For a wire site whose submit or wait just failed: true when the failure is a lost // device, in which case this session has been latched (MGPipeSessionLatch - it ends, the // display server's other sessions do not) and the caller must return from its verb @@ -422,7 +415,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // is latched, and the caller returns from its verb without submitting anything more. Asked // before every frame submission and by the apply loop before it applies another record. Bool LatchIfGpuHung(const char* site); -#endif // Flush gated on usefulness: only flushes when `submitIndex` is still // unsubmitted, so poll loops on already-submitted fences do not split // the frame's render pass (a full tile load/store on TBDR GPUs). @@ -581,26 +573,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { // The structs stay, empty, so ShutdownBlitResources and the two `= {}` assignments read // the same on both builds. struct BlitResources { -#if !MOBILEGL_BUILD_RECORD_ARM - SharedPtr program; - SharedPtr nearestSampler; - SharedPtr linearSampler; - Int srcRectLocation = -1; - Int dstRectLocation = -1; - Int surfaceTransformLocation = -1; - Uint32 samplerBinding = 0; -#endif }; struct DepthMipmapResources { -#if !MOBILEGL_BUILD_RECORD_ARM - SharedPtr program; - Int srcRectLocation = -1; - Int dstRectLocation = -1; - Int surfaceTransformLocation = -1; - Int srcTexelSizeLocation = -1; - Uint32 samplerBinding = 0; -#endif }; // A single-sample staging image for multisample-resolve blits that also have to change @@ -639,7 +614,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { // See NoteDeviceLoss. Set once, never cleared: a lost VkDevice stays lost. Bool m_deviceLost = false; Bool m_deviceLossLatched = false; -#if MOBILEGL_BUILD_RECORD_ARM // Brackets this device's frame submissions for the GPU hang watch (LatchIfGpuHung). GpuProgressMarkers m_progressMarkers; struct WireImage { @@ -925,7 +899,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { void CopyWireFramebufferToTexture(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -#endif void QueueClearBufferPayloadForFramebuffer(const MG_State::GLState::FramebufferObject& framebuffer, GLenum buffer, GLint drawbuffer, const ClearAttachmentPayload& clearPayload); @@ -972,11 +945,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { // was waited or the device was idled); drops their records and // recycles pooled fences. void OnSubmitsCompletedUpTo(Uint64 submitIndex); -#if MOBILEGL_BUILD_RECORD_ARM // A later fence alone cannot retire earlier submissions. Wait for the // whole still-live prefix before advancing the completed submit floor. Bool WaitForSubmitsUpTo(Uint64 submitIndex, Uint64 timeoutNs); -#endif VkFence AcquirePooledSubmitFence(); void DestroySubmitFencePool(); Bool HasPendingRecordedWork() const; @@ -1160,12 +1131,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkDeviceSize countBufferOffset, Uint32 maxDrawCount, Uint32 stride); PFNDrawIndexedIndirectCountFunc s_vkCmdDrawIndexedIndirectCount = nullptr; -#if MOBILEGL_BUILD_RECORD_ARM // P8-D: vkCmdDrawIndirectCount (same signature, same extension), for the wire arm's // glMultiDrawArraysIndirectCount. The monolith arm never loads it: it reads that count on // the CPU (DirectVulkan.cpp's MultiDrawArraysIndirectCount). PFNDrawIndexedIndirectCountFunc s_vkCmdWireDrawIndirectCount = nullptr; -#endif // VK_EXT_multi_draw entry points, loaded at device creation when the extension // (and its multiDraw feature) is enabled; null otherwise. PFN_vkCmdDrawMultiEXT s_vkCmdDrawMultiEXT = nullptr; @@ -1233,9 +1202,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { Bool BeginXfbCaptureWithBuffers(FrameContext::FrameData& frame, Uint32 count, const VkBuffer* buffers, const VkDeviceSize* offsets, const VkDeviceSize* sizes); -#if MOBILEGL_BUILD_RECORD_ARM Bool BeginWireXfbCaptureForDraw(FrameContext::FrameData& frame); -#endif Uint32 m_currentDrawXfbBufferCount = 0; Uint32 m_currentDrawXfbBufferMask = 0; void EndXfbCaptureForDraw(FrameContext::FrameData& frame, Bool began); @@ -1383,9 +1350,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { Uint64 programHash = 0; Uint64 vertexInputHash = 0; Uint64 renderPassHash = 0; -#if MOBILEGL_BUILD_RECORD_ARM Uint64 wireRenderPassCompatibilityId = 0; -#endif // The PRE-HANDLE arm's key component (P2 brief D12.1), and 0 in every entry the // handle arm mints. VALUE hash of the pipeline-relevant fixed-function state (see // ComputePipelineStateHash), not the monotonic pipeline-state version: the version @@ -2158,12 +2123,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { Bool MaterializePendingDepthStencilClearForDefaultFramebuffer( VkCommandBuffer commandBuffer, const MG_State::GLState::FramebufferAttachmentObject& attachment, const ClearAttachmentPayload& payload); -#if !MOBILEGL_BUILD_RECORD_ARM - // P7 wave 2-B2 (CONTRACT-P7 §5.2, (B')): the hidden blit program's pipeline. A - // disaggregated build has no hidden program on either arm, so this has neither a body - // nor a caller there. - VkPipeline GetOrCreateBlitPipeline(const RenderPassEntry& renderPassEntry); -#endif Bool GenerateDepthMipmapWithShader(FrameContext::FrameData& frame, MG_State::GLState::ITextureObject& texture, VkTextureManager::TextureResource& resource, diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireColorBlit.inc b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireColorBlit.inc index e7f7d7b5..95b03ffb 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireColorBlit.inc +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireColorBlit.inc @@ -1,6 +1,5 @@ // Included by VulkanRenderer.cpp inside the backend namespace, after WireFramebuffer.inc. // The native blit owns no frontend object and never invokes the GL shader compiler. -#if MOBILEGL_BUILD_RECORD_ARM #include "WireColorBlitSpirv.h" struct VulkanRenderer::WireColorBlitResources { @@ -405,4 +404,3 @@ if (destination.isDefault) m_swapchainObject.SetImageContentDefined(destination.swapchainImageIndex, true); return true; } -#endif diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireColorBlitFilter.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireColorBlitFilter.h index 089b811d..ba52b672 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireColorBlitFilter.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireColorBlitFilter.h @@ -35,7 +35,6 @@ // GL's own (logical) rectangles for identity and all three rotations. BlitWireColorImage declines // any other transform before it chooses a sampler; for one, this answers with the filter's own // mapping, as before this package. -#if MOBILEGL_BUILD_RECORD_ARM namespace MobileGL::MG_Backend::DirectVulkan { // A glBlitFramebuffer rectangle as GL names it: two corners, either order. struct WireBlitRect { @@ -63,4 +62,3 @@ namespace MobileGL::MG_Backend::DirectVulkan { return VK_FILTER_LINEAR; } } // namespace MobileGL::MG_Backend::DirectVulkan -#endif diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDeclineTally.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDeclineTally.h index eb98c01b..be3160a3 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDeclineTally.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDeclineTally.h @@ -9,7 +9,6 @@ #pragma once #include -#if MOBILEGL_BUILD_RECORD_ARM #include #include @@ -169,4 +168,3 @@ private: } // namespace MobileGL::MG_Backend::DirectVulkan -#endif // MOBILEGL_BUILD_RECORD_ARM diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthMipmap.inc b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthMipmap.inc index 0bc03d73..46179afc 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthMipmap.inc +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthMipmap.inc @@ -15,7 +15,6 @@ // frontend objects and a GL compiler on the server's apply thread. The baked program below is // the same shader with the same arithmetic, driven by a push constant and its own descriptor // set, which is what lets the server generate a depth mip while owning nothing of the client. -#if MOBILEGL_BUILD_RECORD_ARM #include "WireDepthMipmapSpirv.h" struct VulkanRenderer::WireDepthMipmapResources { @@ -326,4 +325,3 @@ RetireWireObjects(Move(retired)); return true; } -#endif diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthResolveProbe.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthResolveProbe.cpp index 03ab847f..7acb3d3c 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthResolveProbe.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthResolveProbe.cpp @@ -21,7 +21,6 @@ #include #include -#if MOBILEGL_BUILD_RECORD_ARM namespace MobileGL::MG_Backend::DirectVulkan { #include "WireMultisampleResolveSpirv.h" @@ -993,4 +992,3 @@ namespace MobileGL::MG_Backend::DirectVulkan { return measurement; } } // namespace MobileGL::MG_Backend::DirectVulkan -#endif diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthResolveProbe.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthResolveProbe.h index ad3999d4..d1abab23 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthResolveProbe.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthResolveProbe.h @@ -27,7 +27,6 @@ // // Disaggregated builds only: the monolith never records either arm, and the pull build's image // must not change (P7 gate G1). -#if MOBILEGL_BUILD_RECORD_ARM namespace MobileGL::MG_Backend::DirectVulkan { // Every aspect a wire depth/stencil format has. VkImageAspectFlags WireDepthStencilFormatAspects(VkFormat format); @@ -118,4 +117,3 @@ namespace MobileGL::MG_Backend::DirectVulkan { Uint32 graphicsQueueFamilyIndex, const Vector& deviceExtensions, Bool& renderPassArmAvailable, Bool& shaderStencilExport); } // namespace MobileGL::MG_Backend::DirectVulkan -#endif diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.inc b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.inc index d82411f9..72f7ebad 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.inc +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.inc @@ -1,5 +1,4 @@ // Server-owned draw/dispatch setup. The legacy setup remains the monolith implementation. -#if MOBILEGL_BUILD_RECORD_ARM static MagmaProgramSource WireProgramSource(MG_Pipe::MGPipeHandle handle) { auto& state = MG_Pipe::MGPipeApplier(); const Bool composite = handle.Slot >= MG_Pipe::kMGPipeShaderCsoCompositeSlotBase; @@ -909,4 +908,3 @@ if (MG_Util::PipeStats::Enabled()) MG_Util::PipeStats::AddCalls(MG_Util::PipeStats::CallClass::WireIndirectNativeDispatches, 1); } -#endif diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.inc b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.inc index 9592df11..4123f3d0 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.inc +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.inc @@ -1,6 +1,5 @@ // P5f fm: included by VulkanRenderer.cpp inside the backend namespace. All inputs here // belong to the applier; no frontend object, lifetime-id lookup or allocator is used. -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 0. THE MESSAGE IS UNCHANGED; where it goes is not. This funnel is how eleven of // the fifteen P7-marked refusals die (the other four are WireDescriptorFatal's), and until now // every one of them raised its own abort: no SessionFault frame for the peer, no @@ -1730,4 +1729,3 @@ } } } -#endif diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireMultisampleResolve.inc b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireMultisampleResolve.inc index 08f712cd..b5c3e161 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireMultisampleResolve.inc +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireMultisampleResolve.inc @@ -15,7 +15,6 @@ // shader arm fetches sample 0 - not an average. Two arms that answer differently on two devices // would make "the wire arm is observably the monolith's" untestable, and GL 4.6 core 18.3.1 // requires a SELECTED sample for stencil anyway. -#if MOBILEGL_BUILD_RECORD_ARM // The pass's modules, layouts, render passes and pipeline, and the draw it records, are // WireDepthResolveProbe.cpp's (g5-msprobe): the multisample depth/stencil resolve probe runs // this exact arm as its CONTROL, so it is defined once for both. @@ -164,4 +163,3 @@ RetireWireObjects(Move(retired)); return true; } -#endif diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WirePlaceholderImages.inc b/MobileGL/MG_Backend/DirectVulkan/Renderer/WirePlaceholderImages.inc index 7ec0a258..527ec0e3 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WirePlaceholderImages.inc +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WirePlaceholderImages.inc @@ -1,6 +1,5 @@ // UniformManager-owned native descriptors for wire bindings with no image. // No GL object is constructed or inserted into the client's resource namespace. -#if MOBILEGL_BUILD_RECORD_ARM void UniformManager::DestroyWirePlaceholderImage(WirePlaceholderImage& image) const { if (m_device != VK_NULL_HANDLE) { if (image.clearFramebuffer) vkDestroyFramebuffer(m_device, image.clearFramebuffer, nullptr); @@ -245,4 +244,3 @@ out = {image.sampler, image.view, VK_IMAGE_LAYOUT_GENERAL}; return true; } -#endif diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WirePlaceholderKey.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/WirePlaceholderKey.h index fa440ce8..22379a73 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WirePlaceholderKey.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WirePlaceholderKey.h @@ -12,7 +12,6 @@ // The pure half of UniformManager's wire placeholder cache (WirePlaceholderImages.inc): WHICH // placeholder a binding with no usable image takes. A unit test pins it // (MG_Test/Pipeline/PipelineQuirkTest.cpp); the Vulkan half that makes the image stays in the .inc. -#if MOBILEGL_BUILD_RECORD_ARM #include namespace MobileGL::MG_Backend::DirectVulkan { @@ -59,4 +58,3 @@ namespace MobileGL::MG_Backend::DirectVulkan { return key; } } // namespace MobileGL::MG_Backend::DirectVulkan -#endif diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireRenderPassCompatibility.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireRenderPassCompatibility.h index 4a57e506..08131141 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireRenderPassCompatibility.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireRenderPassCompatibility.h @@ -2,7 +2,6 @@ #include #include "../VkIncludes.h" -#if MOBILEGL_BUILD_RECORD_ARM namespace MobileGL::MG_Backend::DirectVulkan { // The wire draw pass has one graphics subpass, no input attachments, // multiview or extensions. Its Vulkan pipeline compatibility is formats, @@ -46,4 +45,3 @@ namespace MobileGL::MG_Backend::DirectVulkan { Uint64 m_nextId = 1; // zero selects the native-handle pipeline domain }; } -#endif diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireTextureReadback.inc b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireTextureReadback.inc index df5a77c3..05f84d2c 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireTextureReadback.inc +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireTextureReadback.inc @@ -1,6 +1,5 @@ // Server-owned texture readback. Included after WireFramebuffer.inc so image // layout tracking and frame retirement are the same as every other wire verb. -#if MOBILEGL_BUILD_RECORD_ARM static Bool PackWireColorTight(const Uint8* source, SizeT sourceBytes, VkFormat format, TextureInternalFormat logicalFormat, const MG_Pipe::MGPReadbackInfo& info, Vector& result) { @@ -211,4 +210,3 @@ ownedBytes = Move(result); return true; } -#endif diff --git a/MobileGL/MG_Backend/MGPipe/PipeInputs.cpp b/MobileGL/MG_Backend/MGPipe/PipeInputs.cpp index b4a79756..91263c10 100644 --- a/MobileGL/MG_Backend/MGPipe/PipeInputs.cpp +++ b/MobileGL/MG_Backend/MGPipe/PipeInputs.cpp @@ -16,10 +16,8 @@ #include #include -#if MOBILEGL_BUILD_RECORD_ARM #include #include -#endif namespace MobileGL::MG_Pipe { const char* MGPipeVerbName(MGPipeVerb verb) { @@ -49,7 +47,7 @@ namespace MobileGL::MG_Pipe { // The stamp is the poison's (m_filled, the generations): a build without MOBILEGL_PIPE_POISON // compiles no read check that could ask any of this. Every transport build has the poison. -#if MOBILEGL_BUILD_RECORD_ARM && MOBILEGL_PIPE_POISON +#if MOBILEGL_PIPE_POISON // ================================================================================ // P5: the server's verb stamp, the residual-pull counter, and the four-way read verdict // ================================================================================ diff --git a/MobileGL/MG_Backend/MGPipe/PipeInputs.h b/MobileGL/MG_Backend/MGPipe/PipeInputs.h index 25fa86cd..57e496fa 100644 --- a/MobileGL/MG_Backend/MGPipe/PipeInputs.h +++ b/MobileGL/MG_Backend/MGPipe/PipeInputs.h @@ -13,14 +13,12 @@ // the live context happens on the client side, in MG_Impl/Pipe/PipeFill.cpp. #include -#if MOBILEGL_BUILD_RECORD_ARM // P5c (rv, CONTRACT-P5C.md §5.3): the three texture shutters' server-side answer lives in the // applier - MGPipeApplierTextureShutterSerial() / MGPipeApplierContextSerial(), declared here // so the accessors below can answer with them under a server-stamped verb. MG_Pipe is below // MG_Backend, so this direction is the layering's, and PipeApply.h forward-declares // PipeInputs rather than including this header, so there is no cycle. #include -#endif // MOBILEGL_PIPE_POISON: the per-verb generation stamps and the read-side // Fatal{UnmigratedPipeInput} check. Derived here, once. The repository's debug gate is @@ -53,7 +51,6 @@ namespace MobileGL::MG_Pipe { Optional MGPipeFindInputField(const char* name); Optional MGPipeFindVerb(const char* name); -#if MOBILEGL_BUILD_RECORD_ARM // ---- P5: the split arm of the read check (R-7.2, R-7.3) ------------------------------ // // A stale read stops being one answer and becomes FOUR, keyed on the field's table-2 class @@ -87,13 +84,11 @@ namespace MobileGL::MG_Pipe { // from either counting the same read twice or - worse, because the field's own class would // not be BARRIER-PULLED - aborting a read the argument row had just declared legal. Bool MGPipeInputArgumentRead(MGPipeInputField field, Uint32 arg0, MGPipeVerb verb, Bool serverStamped); -#endif // The read-side poison check, on every non-forwarded accessor. Under MOBILEGL_PIPE_POISON // a read of a field whose stamp is older than the current verb serial is // Fatal{UnmigratedPipeInput, "Field@Verb"}; otherwise the accessor is a plain load. #if MOBILEGL_PIPE_POISON -#if MOBILEGL_BUILD_RECORD_ARM #define MGP_INPUT_CHECK(Field) \ do { \ if ((m_serverStampedVerb && ::MobileGL::MG_Pipe::MGPipeFieldOwnershipOf(Field) == \ @@ -110,15 +105,6 @@ namespace MobileGL::MG_Pipe { } \ } while (0) #else -#define MGP_INPUT_CHECK(Field) \ - do { \ - if (!::MobileGL::MG_Pipe::MGPipeInputFieldIsFresh(m_filled, (Field))) { \ - ::MobileGL::MG_Pipe::MGPipeInputPoisonFatalForVerb((Field), m_currentVerb); \ - } \ - } while (0) -#define MGP_INPUT_CHECK_ARG(Field, Arg0) MGP_INPUT_CHECK(Field) -#endif -#else #define MGP_INPUT_CHECK(Field) ((void)0) #define MGP_INPUT_CHECK_ARG(Field, Arg0) ((void)0) #endif @@ -266,7 +252,6 @@ namespace MobileGL::MG_Pipe { #if MOBILEGL_PIPE_POISON const MGPipeFilledState& FilledState() const { return m_filled; } #endif -#if MOBILEGL_BUILD_RECORD_ARM // TRUE between the server's verb-boundary stamp and whoever clears it. It is the // arming condition of the whole split read path: only inside a server-stamped verb is // a BARRIER-PULLED read counted rather than Fatal, and only there is a sticky forward @@ -285,7 +270,6 @@ namespace MobileGL::MG_Pipe { // case the sticky exemption was written for, would be counted and, under strict, would // abort. So: PipeApplier clears on leaving the applier. Not optional. Bool ServerStampedVerb() const { return m_serverStampedVerb; } -#endif // ---- V: values ---- Int GetActiveTextureUnit() const { @@ -491,9 +475,7 @@ namespace MobileGL::MG_Pipe { Uint64 GetSamplingResolutionGeneration() const { MGP_INPUT_CHECK(MGPipeInputField::GetSamplingResolutionGeneration); MGP_INPUT_VERIFY_READ(MGPipeInputField::GetSamplingResolutionGeneration, 0, 0); -#if MOBILEGL_BUILD_RECORD_ARM if (m_serverStampedVerb) return MGPipeApplierTextureShutterSerial(); -#endif return m_samplingResolutionGeneration; } const IntVec4& GetScissorBox() const { @@ -509,21 +491,17 @@ namespace MobileGL::MG_Pipe { Uint64 GetTextureBindGeneration() const { MGP_INPUT_CHECK(MGPipeInputField::GetTextureBindGeneration); MGP_INPUT_VERIFY_READ(MGPipeInputField::GetTextureBindGeneration, 0, 0); -#if MOBILEGL_BUILD_RECORD_ARM // See GetSamplingResolutionGeneration: the server answers from its own Serial. if (m_serverStampedVerb) return MGPipeApplierTextureShutterSerial(); -#endif return m_textureBindGeneration; } Uint64 GetTextureContextId() const { MGP_INPUT_CHECK(MGPipeInputField::GetTextureContextId); MGP_INPUT_VERIFY_READ(MGPipeInputField::GetTextureContextId, 0, 0); -#if MOBILEGL_BUILD_RECORD_ARM // A context IDENTITY rather than a generation: stable within the served context, // moved by every MGPipeApplierReset - which is all the backends' per-context memo // keys ask of it. if (m_serverStampedVerb) return MGPipeApplierContextSerial(); -#endif return m_textureContextId; } Uint64 GetTransformFeedbackCapturedVertices() const { @@ -757,9 +735,7 @@ namespace MobileGL::MG_Pipe { #if MOBILEGL_PIPE_POISON MGPipeFilledState m_filled{}; #endif -#if MOBILEGL_BUILD_RECORD_ARM Bool m_serverStampedVerb = false; -#endif // ---- V ---- Int m_activeTextureUnit = 0; @@ -1019,7 +995,6 @@ namespace MobileGL::MG_Pipe { // The docs budget ~20 KB; the block is a few KB. static_assert(sizeof(PipeInputs) < 20 * 1024, "PipeInputs outgrew its budget"); -#if MOBILEGL_BUILD_RECORD_ARM // ============================================================================ // P5: the server-side verb stamp, and the counter that sizes what it leaves behind // ============================================================================ @@ -1094,7 +1069,6 @@ namespace MobileGL::MG_Pipe { // object or write into the frontend. This is what puts them in `rsp` and, under // MOBILEGL_IPC_STRICT_ERRORS=1, makes them Fatal like any other BARRIER-PULLED row. void MGPipeStickyForwardPull(MGPipeInputField field); -#endif #if MOBILEGL_PIPE_VERIFY // PipeInputs.cpp. Per-field equality for the entry compare (P1 brief D8): V by value diff --git a/MobileGL/MG_Backend/Record/RecordVerbSink.cpp b/MobileGL/MG_Backend/Record/RecordVerbSink.cpp index 89355676..9bbe96f1 100644 --- a/MobileGL/MG_Backend/Record/RecordVerbSink.cpp +++ b/MobileGL/MG_Backend/Record/RecordVerbSink.cpp @@ -130,7 +130,6 @@ namespace MobileGL::MG_Record { const MG_Backend::GlobalBackendFunctionsTable* table = Table("blit"); if (table == nullptr) return false; if (table->GL.BlitFramebuffer == nullptr) return false; -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.3): the record's handles cross to the backend as the verb's // own state. The bound form carries two nulls and nothing changes; the named form's // pair is what the backend's named-blit arm resolves - the sink no longer relies on @@ -143,12 +142,10 @@ namespace MobileGL::MG_Record { applierState.VerbBlitDrawFbo = blit.DrawFbo; const Bool named = !MG_Pipe::MGPipeHandleIsNull(blit.ReadFbo) || !MG_Pipe::MGPipeHandleIsNull(blit.DrawFbo); -#endif table->GL.BlitFramebuffer(blit.SrcX0, blit.SrcY0, blit.SrcX1, blit.SrcY1, blit.DstX0, blit.DstY0, blit.DstX1, blit.DstY1, static_cast(blit.Mask), static_cast(blit.Filter)); -#if MOBILEGL_BUILD_RECORD_ARM if (named && !applierState.VerbBlitNamedConsumed) { MGLOG_E_ONCE("MGPipe: a named blit (read {%u, %u}, draw {%u, %u}) reached a backend " "with no named-blit arm; the verb is DECLINED rather than applied to " @@ -158,7 +155,6 @@ namespace MobileGL::MG_Record { applierState.VerbBlitDrawFbo = MG_Pipe::kMGPipeNullHandle; return false; } -#endif ++m_blits; return true; } @@ -303,13 +299,11 @@ namespace MobileGL::MG_Record { } Bool RecordVerbSink::ReadTextureImageTight(const MG_Pipe::MGPReadbackInfo& image, Vector& bytes) { -#if MOBILEGL_BUILD_RECORD_ARM if (m_backend && m_backend->GetBackendType() == BackendType::DirectGLES) return MG_Backend::DirectGLES::ReadTextureImageWire(image, bytes); if (m_backend && m_backend->GetBackendType() == BackendType::DirectVulkan && MG_Backend::DirectVulkan::pVulkanRenderer) return MG_Backend::DirectVulkan::pVulkanRenderer->ReadTextureImageWire(image, bytes); -#endif (void)image; (void)bytes; return false; @@ -535,7 +529,6 @@ namespace MobileGL::MG_Record { // with a span (our client stages client indices into an owned element buffer and never sets // kDrawHasUserIndices) and a multi-draw that claims instancing (no GL entry point produces // one; the client never sends it). Only a foreign peer reaches either. -#if MOBILEGL_BUILD_RECORD_ARM namespace { // P5e (tx2), CONTRACT-P5E §5.3 / ruling 19 (ID-95, A8 closed). THE TWO UNIT WINDOWS MUST // COVER [0, MaxTouchedTextureUnit], AND THIS IS WHERE THAT PROMISE IS CHECKED. @@ -595,7 +588,6 @@ namespace MobileGL::MG_Record { return true; } } // namespace -#endif Bool RecordVerbSink::OnDrawVbo(const MG_Pipe::MGPDrawInfo& info, const MG_Pipe::MGPDrawRange* ranges, @@ -619,11 +611,9 @@ namespace MobileGL::MG_Record { } ++m_drawRecords; -#if MOBILEGL_BUILD_RECORD_ARM // Ruling 19 / ID-95: the window promise, checked at every draw, before the backend is // asked to resolve anything out of the windows. if (!CheckUnitWindows(MG_Pipe::MGPipeApplier(), "draw_vbo")) return false; -#endif const MG_Backend::GlobalBackendFunctionsTable* table = Table("draw_vbo"); if (table == nullptr) return false; const MG_Backend::GLFunctionsTable& gl = table->GL; @@ -645,7 +635,6 @@ namespace MobileGL::MG_Record { if (indirect != nullptr) { // The layout already refused a record that sets both flags or declares ranges // beside the block, so NumDraws is 0 and there is no span here. -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): the command/parameter buffer handles cross as the // verb's own state; the backend's indirect arm resolves the buffer twins from // them instead of reading the client's GL_DRAW_INDIRECT_BUFFER binding slot. @@ -653,7 +642,6 @@ namespace MobileGL::MG_Record { applierState.ClearVerbHandles(); applierState.VerbIndirectBuffer = indirect->Buffer; applierState.VerbIndirectParameterBuffer = indirect->ParameterBuffer; -#endif const auto offset = reinterpret_cast(static_cast(indirect->Offset)); const auto drawCount = static_cast(indirect->DrawCount); const auto stride = static_cast(indirect->Stride); @@ -843,10 +831,8 @@ namespace MobileGL::MG_Record { // identical - and it is also the honest statement of the debt, which `rsp` counts. Bool RecordVerbSink::OnLaunchGrid(const MG_Pipe::MGPGridInfo& grid) { -#if MOBILEGL_BUILD_RECORD_ARM // Ruling 19 / ID-95: a dispatch samples through the same unit windows a draw does. if (!CheckUnitWindows(MG_Pipe::MGPipeApplier(), "launch_grid")) return false; -#endif const MG_Backend::GlobalBackendFunctionsTable* table = Table("launch_grid"); if (table == nullptr) return false; const MG_Backend::GLFunctionsTable& gl = table->GL; @@ -868,14 +854,12 @@ namespace MobileGL::MG_Record { // IndirectBuffer travels for P7's sake; the BINDING is server state, put there by // the set_buffer_bindings record that preceded this one, exactly as OnClear's Fbo // is not re-resolved here. glDispatchComputeIndirect takes only the offset. -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.5): the buffer handle itself is now also the verb's own // state, so the backend's dispatch-indirect arm resolves the twin from the record // rather than from the client's GL_DISPATCH_INDIRECT_BUFFER binding slot. auto& applierState = MG_Pipe::MGPipeApplier(); applierState.ClearVerbHandles(); applierState.VerbDispatchIndirectBuffer = grid.IndirectBuffer; -#endif gl.DispatchComputeIndirect(static_cast(grid.IndirectOffset)); } else { if (gl.DispatchCompute == nullptr) return false; @@ -1116,7 +1100,6 @@ namespace MobileGL::MG_Record { Bool RecordVerbSink::OnGenerateMipmap(const MG_Pipe::MGPMipPlan& plan) { const auto* table = Table("GenerateMipmap"); if (table == nullptr || table->GL.GenerateMipmap == nullptr) return false; -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.2): the texture the client resolved at Target on the active // unit crosses as the verb's own state; the backend's mip-descriptor check resolves // the record from it instead of probing the client allocator for the bound object's @@ -1126,7 +1109,6 @@ namespace MobileGL::MG_Record { applierState.VerbMipRes = plan.Res; applierState.VerbMipBaseLevel = plan.BaseLevel; applierState.VerbMipLevelCount = plan.LevelCount; -#endif table->GL.GenerateMipmap(plan.Target); return true; } @@ -1134,14 +1116,12 @@ namespace MobileGL::MG_Record { Bool RecordVerbSink::OnCopyFramebufferToTexture(const MG_Pipe::MGPCopyFromFramebuffer& copy) { const auto* table = Table(copy.SubImage ? "CopyTexSubImage2D" : "CopyTexImage2D"); if (table == nullptr) return false; -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.4): the destination texture the client resolved at the // active unit crosses as the verb's own state; the backend resolves its twin from the // handle instead of reading the client's texture-unit binding slot (T4). auto& applierState = MG_Pipe::MGPipeApplier(); applierState.ClearVerbHandles(); applierState.VerbCopyTexDst = copy.Dst; -#endif if (copy.SubImage) { if (table->GL.CopyTexSubImage2D == nullptr) return false; table->GL.CopyTexSubImage2D(copy.Target, copy.Level, copy.XOffset, copy.YOffset, diff --git a/MobileGL/MG_Backend/Record/StagedTextureStore.h b/MobileGL/MG_Backend/Record/StagedTextureStore.h index 86255d1f..782fe7b7 100644 --- a/MobileGL/MG_Backend/Record/StagedTextureStore.h +++ b/MobileGL/MG_Backend/Record/StagedTextureStore.h @@ -114,9 +114,7 @@ #include #include -#if MOBILEGL_BUILD_RECORD_ARM #include -#endif namespace MobileGL::MG_Record { @@ -355,7 +353,6 @@ namespace MobileGL::MG_Record { const std::lock_guard lock(m_mutex); LevelShadow& shadow = m_shadows[bucketed].Levels[PackLevel(uploadTarget, level)]; RequireDeclaredLevel(shadow, key, uploadTarget, level, extent); -#if MOBILEGL_BUILD_RECORD_ARM // A run can be the first piece of a redefined level. Old coverage // belongs to the previous coordinate system even when the new run // happens to touch its old range; retaining it invents bytes that @@ -369,7 +366,6 @@ namespace MobileGL::MG_Record { shadow.Alias = nullptr; shadow.Covered.clear(); } -#endif if (shadow.HoldsFollowedCopy) { // P8-E: a run landed whole over a followed copy (AdoptClientBoxes is the spelling // that keeps it), so the bytes no longer hold what the driver does. @@ -1030,7 +1026,6 @@ namespace MobileGL::MG_Record { std::atomic m_any{false}; }; -#if MOBILEGL_BUILD_RECORD_ARM // ONE PER PROCESS, and its copying arm is decided ONCE at first use - StagedShadow's // ServerStaged() ruling verbatim: the two arms hold the authoritative bytes in DIFFERENT // places, so an answer that changed mid-run would strand every level already staged. @@ -1043,6 +1038,5 @@ namespace MobileGL::MG_Record { *new StagedTextureStore(MG_Config::Transport != MG_Config::TransportMode::Monolith); return store; } -#endif } // namespace MobileGL::MG_Record diff --git a/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.cpp b/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.cpp index c9f03aa5..ed164c3a 100644 --- a/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.cpp +++ b/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.cpp @@ -12,9 +12,7 @@ #include #include #include -#if MOBILEGL_BUILD_RECORD_ARM #include -#endif // CONTRACT-P5.md §7 / ID-14: a null check on a GLFunctionsTable slot may not survive into the // client under split - it becomes a caps-mirror read. SlotCaps.h carries the rule and the test // that decides which of its two spellings a site takes; in a pull build both expand to exactly @@ -1332,7 +1330,6 @@ namespace MobileGL::MG_Impl::GLImpl { static_cast(bufferIndex)); const auto& buffer = bindingPoint.GetBoundObject(); if (buffer == nullptr) continue; -#if MOBILEGL_BUILD_RECORD_ARM // This fixup READS the captured bytes back through the shadow, so it is the one // consumer that cannot simply inherit the deferral EndTransformFeedback's dropped // fence introduces. Under split it pays the reconciliation itself, which is the @@ -1345,7 +1342,6 @@ namespace MobileGL::MG_Impl::GLImpl { // caller still runs, so the readback it emits is pure new work on the monolith // path and integration-gpu cannot see it. if (MG_Config::DataArmIsRecord()) buffer->SyncGpuWrites(); -#endif const Range1D range = bindingPoint.GetRange(); const Uint8* mapped = buffer->MappedData(); if (mapped == nullptr) continue; @@ -1386,12 +1382,10 @@ namespace MobileGL::MG_Impl::GLImpl { MGP_FILL(EndTransformFeedback); endXfb(); } -#if MOBILEGL_BUILD_RECORD_ARM // P5 (b1), the second producer the client-side GPU-write set ADDS, and it has to be // taken HERE - before GLContext::EndTransformFeedback clears the live bindings, since // a mark taken after it marks nothing. MG_Record::MarkEndTransformFeedbackCaptureTargets(); -#endif MG_State::pGLContext->EndTransformFeedback(); // Captured results must be visible to MapBuffer/GetBufferSubData after // End; the capture targets are host-coherent GPU memory, so completing diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index 71041c68..6f40ed94 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -49,11 +49,7 @@ // SyncGpuWrites, exactly as glMapBufferRange and glGetBufferSubData already do. Monolith keeps its // read as it was: its ReadPixels maps the driver PBO back into the shadow inside the call, and the // pull build compiles this to nothing (G1). -#if MOBILEGL_BUILD_RECORD_ARM #define MGL_SYNC_PIXEL_UNPACK_SOURCE(buffer) do { if (MG_Config::DataArmIsRecord()) (buffer)->SyncGpuWrites(); } while (0) -#else -#define MGL_SYNC_PIXEL_UNPACK_SOURCE(buffer) ((void)0) -#endif namespace MobileGL::MG_Impl::GLImpl { static SharedPtr nullTextureObject; @@ -6121,10 +6117,8 @@ namespace MobileGL::MG_Impl::GLImpl { viewObject->SetInternalFormat(viewInternalFormat); viewObject->SetSamples(storageOwner->GetSamples()); viewObject->SetFixedSampleLocations(storageOwner->HasFixedSampleLocations()); -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) MG_Pipe::MGPipeEmitSamplerViewCreate(*viewObject); -#endif } void TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) { @@ -6586,14 +6580,12 @@ namespace MobileGL::MG_Impl::GLImpl { static void GetTextureImageForUploadTarget(const SharedPtr& textureObject, TextureUploadTarget uploadTarget, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels, const char* caller) { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { MGP_FILL(GetTextureImage); MG_Backend::gBackendFunctionsTable.GL.GetTextureImage(textureObject, uploadTarget, level, format, type, bufSize, pixels); return; } -#endif if (MG_Backend::pActiveBackendObject != nullptr && MG_Backend::pActiveBackendObject->GetBackendType() == BackendType::DirectVulkan && MGL_BACKEND_SLOT_LOCAL(GetTextureImage)) { @@ -6614,12 +6606,10 @@ namespace MobileGL::MG_Impl::GLImpl { return; } auto uploadTarget = GetPrimaryUploadTarget(textureObject); -#if MOBILEGL_BUILD_RECORD_ARM // Unlike glGetTexImage's face target, this DSA call reads all six faces. if (MG_Config::DataArmIsRecord() && textureObject->GetTarget() == TextureTarget::TextureCubeMap) uploadTarget = TextureUploadTarget::Unknown; -#endif GetTextureImageForUploadTarget(textureObject, uploadTarget, level, format, type, bufSize, pixels, __func__); } @@ -6880,12 +6870,10 @@ namespace MobileGL::MG_Impl::GLImpl { void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) { if (!GetTexImage_State(target, level, format, type, pixels)) return; -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { GetTexImage_Backend(target, level, format, type, pixels); return; } -#endif if (MGL_BACKEND_SLOT_LOCAL(GetTexImage)) { GetTexImage_Backend(target, level, format, type, pixels); return; diff --git a/MobileGL/MG_Impl/Pipe/OwnedDrawInputs.h b/MobileGL/MG_Impl/Pipe/OwnedDrawInputs.h index 9fac88dd..dd6783a6 100644 --- a/MobileGL/MG_Impl/Pipe/OwnedDrawInputs.h +++ b/MobileGL/MG_Impl/Pipe/OwnedDrawInputs.h @@ -9,7 +9,6 @@ // Client memory becomes ordinary owned buffer resources before a draw. #pragma once -#if MOBILEGL_BUILD_RECORD_ARM #include #include #include @@ -207,4 +206,3 @@ namespace MobileGL::MG_Pipe { Bool m_indexBindingChanged = false; }; } // namespace MobileGL::MG_Pipe -#endif diff --git a/MobileGL/MG_Impl/Pipe/PipeFill.cpp b/MobileGL/MG_Impl/Pipe/PipeFill.cpp index bf9e6293..62b2968f 100644 --- a/MobileGL/MG_Impl/Pipe/PipeFill.cpp +++ b/MobileGL/MG_Impl/Pipe/PipeFill.cpp @@ -40,7 +40,7 @@ #include #include #include -#if MOBILEGL_BUILD_RECORD_ARM && MOBILEGL_PIPE_VERIFY +#if MOBILEGL_PIPE_VERIFY #include #endif @@ -96,7 +96,6 @@ namespace MobileGL::MG_Pipe { return inputs.m_currentVertexAttribute; } -#if MOBILEGL_BUILD_RECORD_ARM // P5e (ra, CONTRACT-P5E §2.3). THE FOUR O-CLASS ROWS, AND ONLY THEY: these are the only // members of this block that own a frontend object rather than point into one, so they // are the only ones through which the apply thread can become a last owner. The raw @@ -108,7 +107,6 @@ namespace MobileGL::MG_Pipe { inputs.m_programForDraw.reset(); inputs.m_transformFeedbackProgram.reset(); } -#endif static void CopyField(PipeInputs& dst, GLContext& ctx, MGPipeInputField field) { using F = MGPipeInputField; @@ -691,7 +689,6 @@ namespace MobileGL::MG_Pipe { if (&self != &gPipeInputs || !g_verify.Enabled) return; const auto index = static_cast(field); if (kMGPipeInputFieldSticky[index]) return; -#if MOBILEGL_BUILD_RECORD_ARM // P13 W5: the monolith verb port applies records without a server stamp, and its readback // forces the neutral pack around the backend's read exactly as the server's does. if ((self.ServerStampedVerb() || MG_Record::MonolithPortApplyingForVerify()) && @@ -711,7 +708,6 @@ namespace MobileGL::MG_Pipe { } return; } -#endif if (g_verify.InHook) return; auto* ctx = LiveContext(); if (ctx == nullptr) return; @@ -1106,7 +1102,6 @@ namespace MobileGL::MG_Pipe { // one was emitted, so this cannot be false - but a zeroed record (null // handle, size 0) is not the answer if that pre-pass is ever relaxed. if (!MGPipeBuildSubDataRecord(handle, at, length, record, /*verbatimShadow=*/true)) return; -#if MOBILEGL_BUILD_RECORD_ARM // P5 (b1): the live-host-writes bit rides the content record, because // "someone may be writing these bytes without telling you" is a fact about the // CONTENT and not about the storage. It is set from the object's PUBLISHED @@ -1114,7 +1109,6 @@ namespace MobileGL::MG_Pipe { // edge that announced it can never disagree. MGPipeBuildSubDataRecord does not // take the object, which is why it is set here and not in the builder. record.HasLiveHostWrites = buffer.HasLiveHostWritesForWire() ? 1 : 0; -#endif // `length` is this chunk's byte count, which the record also declares // (MGPipeBuildSubDataRecord writes it into the destination range) - passed // rather than re-read so the staged run and the record's own claim come from @@ -1140,7 +1134,6 @@ namespace MobileGL::MG_Pipe { // store, or the pattern FillSubData expanded locally, and neither is this // client's untransformed shadow of the level. if (!MGPipeBuildSubDataRecord(handle, at, length, record, /*verbatimShadow=*/false)) return; -#if MOBILEGL_BUILD_RECORD_ARM // P5 (b1): THE SECOND CONTENT EMITTER, and it has to speak for the same reason // the first does. ApplyBufferWrite ASSIGNS the bit - a content record emitted // while nothing maps the buffer is how the state goes back to false - so a @@ -1148,7 +1141,6 @@ namespace MobileGL::MG_Pipe { // map. `glBufferSubData` against a persistently mapped arena is legal and is // the ordinary Flywheel/Create shape, so that is not a corner. record.HasLiveHostWrites = buffer.HasLiveHostWritesForWire() ? 1 : 0; -#endif // The application's STAGING store, valid for the duration of the call only. MGPipeRouteBufferSubDataResident(record, base + (at - offset), length); // P7 wave 2 package C, OQ-10: `rsd=`, counted HERE rather than at the call @@ -2270,11 +2262,9 @@ namespace MobileGL::MG_Pipe { } Bool PipeInputs::HasOpenTransformFeedbackSpan(Uint64 lifetimeId) const { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord()) { return lifetimeId != 0 && MGPipeApplier().StreamOutputSpans.count(lifetimeId) != 0; } -#endif MGP_STICKY_FORWARD_PULL(HasOpenTransformFeedbackSpan); const auto* ctx = LiveContext(); @@ -2369,9 +2359,7 @@ namespace MobileGL::MG_Pipe { // stamped, so every stamp this verb made falls behind the serial. ++MGPipeFillAccess::Filled(inputs).CurrentVerbSerial; #endif -#if MOBILEGL_BUILD_RECORD_ARM MGPipeClientClearVerbBoundary(); -#endif MGPipeFillAccess::SetVerb(inputs, MGPipeVerb::kVerbCount); // The pending base instance belongs to the verb that was about to run, so leaving // one drops it. @@ -2917,9 +2905,7 @@ namespace MobileGL::MG_Pipe { Bool ApplierDerives = false; Bool ContextValuesWireLive = false; Bool P4aConsumer = false; -#if MOBILEGL_BUILD_RECORD_ARM Uint64 CapsGeneration = 0; -#endif // One bit per FIELD - not per verb class. The class mask is applied at the walk // exactly as it always was, so "does this verb read this field" stays the walk's // business and this stays a statement about EMISSION alone. @@ -3125,9 +3111,7 @@ namespace MobileGL::MG_Pipe { // `g_attribDefaultLastHeader`, which is what it just published; there is nothing // the mirror could add that the wire does not already carry. A build that ever // needs the repair arm again has to earn it with a barriered row. -#if MOBILEGL_BUILD_RECORD_ARM if (ClientRunsAhead()) return sizeof(MGPVertexAttribDefaults) + header.Count * sizeof(MGPAttribValue); -#endif const auto* mirror = MGPipeFillAccess::VertexAttribDefaultsOf(MGPipeClientInputs()); Bool reproduced = true; for (SizeT i = 0; i < kAttribs && reproduced; ++i) { @@ -3144,7 +3128,6 @@ namespace MobileGL::MG_Pipe { return sizeof(MGPVertexAttribDefaults) + header.Count * sizeof(MGPAttribValue); } -#if MOBILEGL_BUILD_RECORD_ARM // set_context_values (P5c rv, CONTRACT-P5C.md §5.3): the residual-value record. One // POD carrying every value-class field no other set_* supplies - the two texture-unit // counters, the 15 per-target touched-buffer-binding counts and the five XFB values - @@ -3201,7 +3184,6 @@ namespace MobileGL::MG_Pipe { MGPipeFieldMaskHas(mask, MGPipeInputField::GetBoundTransformFeedbackLifetimeId) || MGPipeFieldMaskHas(mask, MGPipeInputField::GetTransformFeedbackCapturedVertices); } -#endif @@ -3403,7 +3385,6 @@ namespace MobileGL::MG_Pipe { // is the CLIENT-role block and gPipeInputs is the server's alone; off, or under // monolith transport, it folds back onto gPipeInputs and nothing below changes. PipeInputs& inputs = MGPipeClientInputs(); -#if MOBILEGL_BUILD_RECORD_ARM // ---- P5e (ra), CONTRACT-P5E §3: WHO OWNS gPipeInputs FOR THIS VERB ---------------- // // Under run-ahead the block is SERVER-ROLE MEMORY for an unbarriered record: the @@ -3418,7 +3399,6 @@ namespace MobileGL::MG_Pipe { // every verb) and the guard below then fires Fatal{RoleViolation, "gPipeInputs"} on // the first unbarriered verb, by name. const Bool runAhead = ClientRunsAhead(); -#endif ParsePoisonOmissionKnob(); #if MOBILEGL_PIPE_VERIFY ArmVerify(); @@ -3479,7 +3459,6 @@ namespace MobileGL::MG_Pipe { // Fatal{UnmigratedPipeInput, "@"} rather than default storage. ++MGPipeFillAccess::Filled(inputs).CurrentVerbSerial; #endif -#if MOBILEGL_BUILD_RECORD_ARM // The client is filling, so whatever the server stamped at its last verb boundary // is withdrawn: the stamps below are the CLIENT's again and a stale read is a // defect, not a residual pull. Disarming here rather than at the end of the @@ -3499,7 +3478,6 @@ namespace MobileGL::MG_Pipe { // (PipeApplier::LeaveApplier) - which is CONTRACT-P5E §3.2's per-role stamp // ownership, landed as the dual block rather than as moved fields. MGPipeClientClearVerbBoundary(); -#endif MGPipeFillAccess::SetVerb(inputs, verb); } #if MOBILEGL_PIPE_POISON @@ -3742,7 +3720,6 @@ namespace MobileGL::MG_Pipe { payloadBytes += EmitVertexAttribDefaults(*ctx, tracker.FreshlyPrimed()); } -#if MOBILEGL_BUILD_RECORD_ARM // P5c rv (CONTRACT-P5C.md §5.3): the residual-value record, emitted when any covered // value moved. THE GATE IS THE SUBSYSTEM BIT PLUS THE WIRE BEING LIVE - the family has // no dirty bit (NoDirtyBitOwnsTheResidualSubsystem) and no P4a consumer predicate (it @@ -3753,7 +3730,6 @@ namespace MobileGL::MG_Pipe { VerbMaskReadsContextValues(mask)) { payloadBytes += EmitContextValues(*ctx); } -#endif // P3a's vertex segment, in the order the design fixes: vertex elements, then the // vertex buffers that fill them, then the index binding. All three are LIVE now (m1): diff --git a/MobileGL/MG_Impl/Pipe/SamplerEmit.h b/MobileGL/MG_Impl/Pipe/SamplerEmit.h index 9837850b..b5e79570 100644 --- a/MobileGL/MG_Impl/Pipe/SamplerEmit.h +++ b/MobileGL/MG_Impl/Pipe/SamplerEmit.h @@ -37,9 +37,7 @@ // detection. Neither is reproduced here and neither may be. // // HEADER-ONLY, for the ownership reason Tracker.h and ResourceTracker.h both state. -#if MOBILEGL_BUILD_RECORD_ARM #include -#endif #include #include #include diff --git a/MobileGL/MG_Impl/Pipe/TextureEmit.h b/MobileGL/MG_Impl/Pipe/TextureEmit.h index 0f7002ae..29cfd6a4 100644 --- a/MobileGL/MG_Impl/Pipe/TextureEmit.h +++ b/MobileGL/MG_Impl/Pipe/TextureEmit.h @@ -899,7 +899,6 @@ namespace MobileGL::MG_Pipe { MGPRespecifiedLevel key{}; key.UploadTarget = packedTarget; key.Level = static_cast(firstLevel + i); -#if MOBILEGL_BUILD_RECORD_ARM const auto* mipmap = MG_State::GLState::AsMipmapTexture(&texture); if (mipmap == nullptr) { MGLOG_E_ONCE("MGPipe: a per-level texture respecify had no mipmap storage; it was not emitted"); @@ -910,7 +909,6 @@ namespace MobileGL::MG_Pipe { key.Width = static_cast(exactLevelExtent.x()); key.Height = static_cast(exactLevelExtent.y()); key.Depth = static_cast(exactLevelExtent.z()); -#endif accepted = RespecifyOnce(texture, handle, entry, desc, &key, viewOf, bufferHandle, bufOffset, bufSize); if (!accepted) break; diff --git a/MobileGL/MG_Impl/Pipe/VertexInputEmit.h b/MobileGL/MG_Impl/Pipe/VertexInputEmit.h index 22bfce7a..122f9aa7 100644 --- a/MobileGL/MG_Impl/Pipe/VertexInputEmit.h +++ b/MobileGL/MG_Impl/Pipe/VertexInputEmit.h @@ -382,19 +382,15 @@ namespace MobileGL::MG_Pipe { for (SizeT i = 0; i < kAttribs; ++i) { m_attributes[i] = MGPipeBuildVertexAttribWire(vao.GetAttribute(static_cast(i)), vao.GetAttributeBindingIndex(static_cast(i))); -#if MOBILEGL_BUILD_RECORD_ARM // Client addresses never cross the transport. Draw emission snapshots // their referenced elements into owned buffers with a zero byte origin. if (MG_Config::DataArmIsRecord() && !vao.GetAttribute(static_cast(i)).Buffer) m_attributes[i].Offset = 0; -#endif } for (SizeT i = 0; i < kBindings; ++i) { m_bindingPoints[i] = MGPipeBuildVertexBindingPointWire(vao.GetBindingPoint(static_cast(i))); -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord() && !vao.GetBindingPoint(static_cast(i)).Buffer) m_bindingPoints[i].Offset = 0; -#endif } // Attributes first, then binding points, both ascending and contiguous. constexpr SizeT kAttribBytes = kAttribs * sizeof(MGPVertexAttribWire); diff --git a/MobileGL/MG_IntegrationTest/CMakeLists.txt b/MobileGL/MG_IntegrationTest/CMakeLists.txt index 89148be4..14b18a9d 100644 --- a/MobileGL/MG_IntegrationTest/CMakeLists.txt +++ b/MobileGL/MG_IntegrationTest/CMakeLists.txt @@ -1939,9 +1939,7 @@ endif() # not true. All this file has to decide now is whether that peek can be COMPILED, which is exactly # "did this build compile MG_Remote", which is exactly the build option. # P13 W5: the record arm's half of the peek (dataArmIsRecord) needs no transport. -if (MOBILEGL_BUILD_RECORD_ARM) - target_compile_definitions(MobileGLIntegrationTest PRIVATE -DMGITEST_RECORD_ARM_PEEK=1) -endif() +target_compile_definitions(MobileGLIntegrationTest PRIVATE -DMGITEST_RECORD_ARM_PEEK=1) if (MOBILEGL_BUILD_DISAGGREGATED) target_compile_definitions(MobileGLIntegrationTest PRIVATE -DMGITEST_SPLIT_RUNTIME_PEEK=1) message(STATUS "Integration tests: the DirectGLES.Split. lanes arm from the RUNNING PROCESS - " @@ -1965,25 +1963,19 @@ if (MOBILEGL_BUILD_DISAGGREGATED AND DEFINED MOBILEGL_LOG_ACTIVE_LEVEL endif() # Package b1's client-side persistent-map tracker, which is what Harness/PersistentMapPeek.cpp -# asks the membership question of (b1-v1.md 4.1 item 2). TWO halves, and both are needed: -# MOBILEGL_BUILD_RECORD_ARM because a build that never compiled the record arm cannot LINK the call -# (P13 W5: the tracker is record core, MG_Record, and no longer needs MG_Remote), and the content -# probe because b1 may not have landed it yet. __has_include in the peek would answer yes in a -# build without it - the header is in the source tree of every build - and turn a healthy build -# into a link error, which is why this decision is made here. -if (MOBILEGL_BUILD_RECORD_ARM) - mgl_itest_probe_for_symbol(MGL_ITEST_PERSISTENT_MAP_TRACKER - "${MGL_ITEST_ROOT}/MobileGL/MG_State/GLState/BufferState" "IsLivePersistentMap") - if (MGL_ITEST_PERSISTENT_MAP_TRACKER) - message(STATUS "Integration tests: package b1's persistent-map tracker is present " - "(${MGL_ITEST_PERSISTENT_MAP_TRACKER}) - PersistentCoherentMapScenario's " - "membership assertion is live") - target_compile_definitions(MobileGLIntegrationTest PRIVATE -DMGITEST_PERSISTENT_MAP_TRACKER=1) - else() - message(STATUS "Integration tests: no source under MobileGL/MG_State/GLState/BufferState names " - "IsLivePersistentMap - package b1's tracker has not landed, so " - "PersistentCoherentMapScenario's membership assertion SKIPS") - endif() +# asks the membership question of (b1-v1.md 4.1 item 2). Every library builds it since P13 W5 (the +# tracker is record core, MG_Record); the content probe stays so a tree without it skips by name. +mgl_itest_probe_for_symbol(MGL_ITEST_PERSISTENT_MAP_TRACKER + "${MGL_ITEST_ROOT}/MobileGL/MG_State/GLState/BufferState" "IsLivePersistentMap") +if (MGL_ITEST_PERSISTENT_MAP_TRACKER) + message(STATUS "Integration tests: package b1's persistent-map tracker is present " + "(${MGL_ITEST_PERSISTENT_MAP_TRACKER}) - PersistentCoherentMapScenario's " + "membership assertion is live") + target_compile_definitions(MobileGLIntegrationTest PRIVATE -DMGITEST_PERSISTENT_MAP_TRACKER=1) +else() + message(STATUS "Integration tests: no source under MobileGL/MG_State/GLState/BufferState names " + "IsLivePersistentMap - package b1's tracker has not landed, so " + "PersistentCoherentMapScenario's membership assertion SKIPS") endif() # ARCHITECTURE.md:543 - every new ctest ENVIRONMENT and add_trace_replay_test's SPLIT branch diff --git a/MobileGL/MG_Pipe/MGPipeCallbacks.h b/MobileGL/MG_Pipe/MGPipeCallbacks.h index d861fe98..6ab67136 100644 --- a/MobileGL/MG_Pipe/MGPipeCallbacks.h +++ b/MobileGL/MG_Pipe/MGPipeCallbacks.h @@ -76,7 +76,6 @@ namespace MobileGL::MG_Pipe { // Null-initialized: a backend that installs nothing sends nothing. inline MGPipeCallbacks gMGPipeCallbacks{}; -#if MOBILEGL_BUILD_RECORD_ARM // HOW MUCH OF ITSELF ONE REVERSE-CHANNEL RECORD MAY BE, and it is not a tuning knob: a // producer that ignores it kills the server process. // @@ -113,5 +112,4 @@ namespace MobileGL::MG_Pipe { const Uint64 quarter = capacity / 4; return quarter < 4096 ? 4096 : quarter; } -#endif } // namespace MobileGL::MG_Pipe diff --git a/MobileGL/MG_Pipe/MGPipeTypes.h b/MobileGL/MG_Pipe/MGPipeTypes.h index 88bf4547..1246a071 100644 --- a/MobileGL/MG_Pipe/MGPipeTypes.h +++ b/MobileGL/MG_Pipe/MGPipeTypes.h @@ -463,25 +463,17 @@ namespace MobileGL::MG_Pipe { desc.HasRespecifiedLevel = 1; desc.RespecifiedUploadTarget = uploadTarget; desc.RespecifiedLevel = level; -#if MOBILEGL_BUILD_RECORD_ARM // Non-buffer texture targets leave this descriptor range unused. A named-level // respecify repurposes it as exact W/H/D; TexBuffer cannot legally name a mip level. desc.BufOffset = (static_cast(width) << 32) | static_cast(height); desc.BufSize = depth; -#else - (void)width; - (void)height; - (void)depth; -#endif } inline constexpr void MGPipeClearRespecifiedLevel(MGPResourceDesc& desc) { -#if MOBILEGL_BUILD_RECORD_ARM if (desc.HasRespecifiedLevel != 0 && desc.Target != static_cast(MGPipeResourceTarget::TexBuffer)) { desc.BufOffset = 0; desc.BufSize = 0; } -#endif desc.HasRespecifiedLevel = 0; desc.RespecifiedUploadTarget = 0; desc.RespecifiedLevel = 0; diff --git a/MobileGL/MG_Pipe/PipeApply.cpp b/MobileGL/MG_Pipe/PipeApply.cpp index d2398295..ca1dc0da 100644 --- a/MobileGL/MG_Pipe/PipeApply.cpp +++ b/MobileGL/MG_Pipe/PipeApply.cpp @@ -16,11 +16,9 @@ #include -#if MOBILEGL_BUILD_RECORD_ARM // MGPipeUnmigratedEmulation's split arm reads MG_Config::Transport, which is what tells an // emulation site whether it is running inside a server or in the monolith it was written for. #include -#endif #if MOBILEGL_PIPE_VERIFY // THE ONE PLACE THE PROGRAM ARCHIVE'S CODEC IS CALLED, and it is compiled into the VERIFY @@ -53,9 +51,7 @@ #include #include #endif -#if MOBILEGL_BUILD_RECORD_ARM #include -#endif #include #include @@ -209,7 +205,6 @@ namespace MobileGL::MG_Pipe { return g_clientLossConfirmer != nullptr && g_clientLossConfirmer(waitMs); } -#if MOBILEGL_BUILD_RECORD_ARM // ---------------------------------------------------------------------------- // THE BACKEND-SIDE SESSION-FAIL SEAM (P7 wave 0). PipeSessionFail.h holds the argument; // this is the whole implementation. @@ -250,9 +245,7 @@ namespace MobileGL::MG_Pipe { std::abort(); } -#endif // MOBILEGL_BUILD_RECORD_ARM -#if MOBILEGL_BUILD_RECORD_ARM namespace { MGPipeSessionLatchHook g_sessionLatchHook = nullptr; MGPipeSessionLatchArmedHook g_sessionLatchArmedHook = nullptr; @@ -267,7 +260,6 @@ namespace MobileGL::MG_Pipe { bool MGPipeSessionLatchArmed() { return g_sessionLatchArmedHook != nullptr && g_sessionLatchArmedHook(); } -#endif // MOBILEGL_BUILD_RECORD_ARM #if MOBILEGL_BUILD_DISAGGREGATED bool MGPipeDebugDeviceLossDue() { @@ -349,7 +341,6 @@ namespace MobileGL::MG_Pipe { #endif // MOBILEGL_BUILD_DISAGGREGATED -#if MOBILEGL_BUILD_RECORD_ARM bool MGPipeSessionLatch(MGPipeFatalFamily family, const char* fmt, ...) { char line[512]; va_list args; @@ -364,7 +355,6 @@ namespace MobileGL::MG_Pipe { // NO HOOK: no session to latch, so the death the fail seam would have given. MGPipeSessionFail(family, "%s", line); } -#endif namespace { // ---------------------------------------------------------------------------- @@ -1343,28 +1333,7 @@ namespace MobileGL::MG_Pipe { return true; } -#if MOBILEGL_PIPE_VERIFY && !MOBILEGL_BUILD_RECORD_ARM - // D-A4's pin, AND P5 (b1) IS THE PHASE IT WAS WAITING FOR. It said "HasLiveHostWrites - // is always false in this phase and is written by nobody: it exists so the phase that - // pushes persistent-mapped host writes can set it with no new record kind", and a - // verify build refused to let such a producer arrive unannounced. - // - // The producer is announced: MGPSubData::HasLiveHostWrites, set by - // MGPipeEmitResourceSubData from BufferObject::HasLiveHostWritesForWire and read by - // ApplyBufferWrite below. So the pin is LIFTED FOR A SPLIT BUILD ONLY, and left - // standing everywhere else - in a monolith build nothing sets the bit and the wire is - // still the thing that would say so if something started to. That is the whole value - // of the pin and it survives the phase it was written for. - void PinNoLiveHostWrites(const MGPipeResourceRecord& record, MGPipeHandle res, const char* call) { - if (!record.HasLiveHostWrites) return; - MGP_TRIP_WIRE_REPORT("MGPipe: " MGP_TRIP_WIRE_TAG("PipeLiveHostWrites") - " %s {slot=%u, gen=%u}: the resource record says host writes are live, and " - "no path in this phase may set that", - call, res.Slot, res.Gen); - } -#else void PinNoLiveHostWrites(const MGPipeResourceRecord&, MGPipeHandle, const char*) {} -#endif #if MOBILEGL_PIPE_VERIFY // P5's pin, RELAXED BY P7 WAVE 3 (CONTRACT-P7 §6) - and relaxed rather than deleted, @@ -1492,7 +1461,6 @@ namespace MobileGL::MG_Pipe { return false; } PinNoLiveHostWrites(*stored, record.Res, call); -#if MOBILEGL_BUILD_RECORD_ARM // P5 (b1): THE PRODUCER. The record's own statement about the resource, applied // before the serial moves so that a probe re-entered from inside the backend hook // below already sees it. It is an assignment and not an OR: the bit is a STATE, @@ -1501,7 +1469,6 @@ namespace MobileGL::MG_Pipe { // (BufferObject::NotePersistentMapStateChanged) rather than relying on the next // ordinary write to arrive. stored->HasLiveHostWrites = record.HasLiveHostWrites != 0; -#endif // THE SERIAL MOVES BEFORE THE BACKEND IS TOLD, and that order is load-bearing: // the backend stamps its own synced serial from this record inside the hook, so a @@ -1528,7 +1495,6 @@ namespace MobileGL::MG_Pipe { return true; } -#if MOBILEGL_BUILD_RECORD_ARM // Texture records can have a server consumer without the buffer ops table (Magma). // Their staged bytes still belong to the server before SEG_STAGE retires. Keep the // existing backend hooks authoritative when present, and use this fallback otherwise. @@ -1596,7 +1562,6 @@ namespace MobileGL::MG_Pipe { default: break; } } -#endif // The texture half of resource_subdata, and it DISPATCHES TO NOBODY at GL-call time: // a texture write marks a level dirty and Espryt uploads it at its own sync point, out @@ -1646,7 +1611,6 @@ namespace MobileGL::MG_Pipe { // record was accumulated, so the texels are the server's now, and that is the true // this returns. ++stored->Serial; -#if MOBILEGL_BUILD_RECORD_ARM // P5c (tx): THE STAGED BYTES ARE ADOPTED HERE, at the last instant `bytes` is known // alive (rule C: SEG_STAGE retires when this record does, and PendingUpload // deliberately holds no byte pointer). The hook copies the run into the server's @@ -1660,7 +1624,6 @@ namespace MobileGL::MG_Pipe { } else { AdoptTextureWithoutBackendHook(*stored, record, bytes, regions); } -#endif return true; } @@ -1985,12 +1948,10 @@ namespace MobileGL::MG_Pipe { MGPipeApplier().DrawProgram = kMGPipeNullHandle; MGPipeApplier().DispatchProgram = kMGPipeNullHandle; MGPipeApplier().BoundShaderCso = kMGPipeNullHandle; -#if MOBILEGL_BUILD_RECORD_ARM MGPipeApplier().BoundStreamOutputLifetimeId = 0; // Begin is emitted once per span, not on make-current. Its immutable object // snapshot survives with the resource/program records until End or release; // set_context_values restores the returning context's bound lifetime id. -#endif // P5e (sb, CONTRACT-P5E.md §5.6): the three binding-point windows are per-context // WORKING state and go with the rest of it - a returning context has its own // glBindBufferBase history and may not inherit the one this applier was left holding. @@ -2010,12 +1971,10 @@ namespace MobileGL::MG_Pipe { } void MGPipeApplierReleaseObjectRecords() { -#if MOBILEGL_BUILD_RECORD_ARM if (MG_Config::DataArmIsRecord() && (g_resourceOps == nullptr || g_resourceOps->TextureDestroy == nullptr)) { MG_Record::ServerStagedTexture().DropAll(); } -#endif // The served context is going away and this applier with it. Under split that is one // applier per served context; in the monolith there is one applier behind every // context, so nothing wires this - see PipeApply.h. The two serials advance here for @@ -2049,10 +2008,8 @@ namespace MobileGL::MG_Pipe { MGPipeApplier().DrawProgram = kMGPipeNullHandle; MGPipeApplier().DispatchProgram = kMGPipeNullHandle; MGPipeApplier().BoundShaderCso = kMGPipeNullHandle; -#if MOBILEGL_BUILD_RECORD_ARM MGPipeApplier().BoundStreamOutputLifetimeId = 0; MGPipeApplier().StreamOutputSpans.clear(); -#endif // AND "THE WORKING HANDLES THEY COULD NAME" IS ALL OF THEM, NOT JUST THE THREE ABOVE. // Every framebuffer record holds eleven MGPSurface::Res naming texture and renderbuffer // records this function has just dropped - which is why the table itself goes above - @@ -2215,9 +2172,7 @@ namespace MobileGL::MG_Pipe { // memory the rule exists to stop it reading. One store, inert until the caps bit is // published, and it is what makes the two roles' third clause the same clause. MGPipeApplier().IsTransformFeedbackActive = values.IsTransformFeedbackActive != 0; -#if MOBILEGL_BUILD_RECORD_ARM MGPipeApplier().BoundStreamOutputLifetimeId = values.BoundTransformFeedbackLifetimeId; -#endif } void MGPipeApplySetPatchState(const MGPPatchState& patch) { @@ -2352,7 +2307,6 @@ namespace MobileGL::MG_Pipe { // ================================================================================ Bool MGPipeApplyResourceCreate(const MGPResourceDesc& desc) { -#if MOBILEGL_BUILD_RECORD_ARM if (!MGPipeRespecifyIsWholeResource(desc)) { MGP_TRIP_WIRE_REPORT("MGPipe: Fatal{ProtocolCorruption, \"ResourceCreate.RespecifyScope\"} - " "resource_create cannot carry a per-level respecify extent"); @@ -2362,7 +2316,6 @@ namespace MobileGL::MG_Pipe { MGP_TRIP_WIRE_REPORT("MGPipe: Fatal{ProtocolCorruption, \"ResourceCreate.BufferRange\"} - " "only a texture-buffer resource may carry BufOffset/BufSize"); } -#endif MOBILEGL_ASSERT(desc.Resource.Slot >= kMGPipeFirstAllocatableSlot, "resource_create named the reserved slot 0"); if (desc.Resource.Slot < kMGPipeFirstAllocatableSlot) return false; @@ -2453,7 +2406,6 @@ namespace MobileGL::MG_Pipe { if (record == nullptr) return false; PinNoLiveHostWrites(*record, desc.Resource, "resource_respecify"); PinRespecifyScopeCoversItsDeclaration(desc, level, desc.Resource, "resource_respecify"); -#if MOBILEGL_BUILD_RECORD_ARM if (level != nullptr && (desc.Target == kMGPipeResourceTargetBuffer || desc.Target == static_cast(MGPipeResourceTarget::Renderbuffer) || @@ -2471,7 +2423,6 @@ namespace MobileGL::MG_Pipe { MGP_TRIP_WIRE_REPORT("MGPipe: Fatal{ProtocolCorruption, \"ResourceRespecify.BufferRange\"} - " "a whole non-buffer resource may not carry BufOffset/BufSize"); } -#endif // IS THIS A REDEFINITION AT ALL? Asked BEFORE the descriptor is replaced, because the // stored one is the only thing there is to compare against (ID-18 M4). See @@ -2493,14 +2444,12 @@ namespace MobileGL::MG_Pipe { level != nullptr ? "one level" : "whole resource"); record->SharedImageId = 0; } -#if MOBILEGL_BUILD_RECORD_ARM if (level != nullptr && desc.Target != static_cast(MGPipeResourceTarget::TexBuffer)) { // Scope and BufOffset/BufSize are transient respecify carriers, not resource state. MGPipeClearRespecifiedLevel(record->Desc); record->Desc.BufOffset = 0; record->Desc.BufSize = 0; } -#endif // THE SERIAL MOVES EITHER WAY, and for a metadata update it is the entire publication: // the twin re-derives its storage flags from the new mask at its next sync and decides // for itself whether the backend needs a recreate. @@ -2561,7 +2510,6 @@ namespace MobileGL::MG_Pipe { record->PendingUploads.clear(); } -#if MOBILEGL_BUILD_RECORD_ARM // P5c (tx): the staged-texture store's defined-ness and drop bookkeeping rides THE SAME // scope rules as the pending-set drops above - a named level redefines that one // (uploadTarget, level), a whole-resource respecify drops every level, and a metadata @@ -2578,7 +2526,6 @@ namespace MobileGL::MG_Pipe { else DefineTextureWithoutBackendHook(desc, level); } -#endif // resource_respecify is the catalogue's only kNeedsAck call, and the per-record half // of that flag is MGPipeResourceRespecifyNeedsAck(desc): glBufferStorage is a real @@ -2780,7 +2727,6 @@ namespace MobileGL::MG_Pipe { // AND ONLY A BUFFER IS HANDED ON, for resource_create's reason: the op table is the // buffer family's, its Destroy takes a handle whose kind that backend registered for, // and a texture's death is read out of the record at the sync that would have used it. -#if MOBILEGL_BUILD_RECORD_ARM // P5c (tx): with ONE exception - the staged-texture store is keyed by the handle, so // the death must reach it or a recycled slot's stale levels would answer for the // successor. This does not hand the texture to the buffer family's Destroy. @@ -2791,7 +2737,6 @@ namespace MobileGL::MG_Pipe { MG_Record::ServerStagedTexture().Drop( MG_Record::StagedTextureStore::KeyForHandle(handle.Handle)); } -#endif if (static_cast(handle.Kind) != MGPipeKind::Buffer) return; if (g_resourceOps != nullptr && g_resourceOps->Destroy != nullptr) { g_resourceOps->Destroy(handle.Handle); diff --git a/MobileGL/MG_Pipe/PipeApply.h b/MobileGL/MG_Pipe/PipeApply.h index 0dc12df7..2903c825 100644 --- a/MobileGL/MG_Pipe/PipeApply.h +++ b/MobileGL/MG_Pipe/PipeApply.h @@ -108,7 +108,6 @@ namespace MobileGL::MG_Pipe { void (*Destroy)(MGPipeHandle res); void* (*MapPersistent)(MGPipeHandle res, Uint64 size, const void* seedBytes); void (*UnmapPersistent)(MGPipeHandle res); -#if MOBILEGL_BUILD_RECORD_ARM // P5c (tx): the TEXTURE half of the resource family, appended so every positional // initialiser of the nine P3a members keeps its meaning. TextureSubData is called // from ApplyTextureUpload AFTER the gate, the accumulation and the serial, while @@ -143,7 +142,6 @@ namespace MobileGL::MG_Pipe { // pattern of its own, and read that back through the held pointer (and through the // backend's own host map of the import). False with the reason in `why`. Bool (*SelfTestExternal)(char* why, Uint64 whyBytes); -#endif }; // Install / read the table. A null argument uninstalls, which is what a backend does at @@ -873,7 +871,6 @@ namespace MobileGL::MG_Pipe { Uint64 TextureShutterSerial = 0; Uint64 ContextSerial = 0; -#if MOBILEGL_BUILD_RECORD_ARM // ---- P5c (hd, CONTRACT-P5C §3.2): THE CURRENT VERB'S OWN HANDLES. ---------------- // // Server state, written by ServerVerbSink at the top of a verb's dispatch and read by @@ -932,7 +929,6 @@ namespace MobileGL::MG_Pipe { VerbIndirectParameterBuffer = kMGPipeNullHandle; VerbDispatchIndirectBuffer = kMGPipeNullHandle; } -#endif }; @@ -1309,13 +1305,11 @@ namespace MobileGL::MG_Pipe { struct MGPRespecifiedLevel { Uint16 UploadTarget = 0; Uint16 Level = 0; -#if MOBILEGL_BUILD_RECORD_ARM // P7 PH-4: mutable mip dimensions do not follow from the base descriptor. These fields // are carried by the split resource_respecify record; the pull helper remains 4 bytes. Uint32 Width = 0; Uint32 Height = 0; Uint32 Depth = 0; -#endif }; inline MGPRespecifiedLevel MGPipeMakeRespecifiedLevel(Uint16 uploadTarget, Uint16 level, @@ -1324,15 +1318,9 @@ namespace MobileGL::MG_Pipe { MGPRespecifiedLevel value{}; value.UploadTarget = uploadTarget; value.Level = level; -#if MOBILEGL_BUILD_RECORD_ARM value.Width = width; value.Height = height; value.Depth = depth; -#else - (void)width; - (void)height; - (void)depth; -#endif return value; } @@ -1483,14 +1471,12 @@ namespace MobileGL::MG_Pipe { // unmap_persistent: the donation ends. Never emitted by P3a's own paths; the call exists // so the pair is complete and the transport has both halves. void MGPipeApplyUnmapPersistent(const MGPHandleOnly& handle); -#if MOBILEGL_BUILD_RECORD_ARM // P11 B2 (T0): the split server's map_persistent for a session that runs T0. The client's // AHardwareBuffer `ahb` (`size` bytes) becomes buffer `handle`'s resident store through the // backend's ImportExternal. A handle that is not a live buffer of that width, or a backend // without the member, declines (false); the codec answers DECLINED and the store runs T2. // MapPersistentRoundtrips is not moved: under split the server never counted map_persistent. Bool MGPipeApplyAdoptExternal(const MGPHandleOnly& handle, void* ahb, Uint64 size); -#endif // --------------------------------------------------------------------------------- // P3a: the five vertex-input entry points (D-G, D-H, D-I) diff --git a/MobileGL/MG_Pipe/PipeRoute.cpp b/MobileGL/MG_Pipe/PipeRoute.cpp index 0079877b..b8d27338 100644 --- a/MobileGL/MG_Pipe/PipeRoute.cpp +++ b/MobileGL/MG_Pipe/PipeRoute.cpp @@ -310,7 +310,6 @@ namespace MobileGL::MG_Pipe { // the monolith twin reads GetLinkedShaderStages() off the frontend object it is // handed. Named and discarded rather than left out of the signature, so the two // arms stay one row. -#if MOBILEGL_BUILD_RECORD_ARM // P13 W4c: MONOLITH'S RECORD ARM READS THE RECORD'S ARCHIVE (ProgramHandleArm), so it // gets one: the link's snapshot, taken here, once per link - the same thing the wire // decodes into the record, without the codec. A copy rather than a borrow, because the @@ -324,7 +323,6 @@ namespace MobileGL::MG_Pipe { MGPipeApplyCreateShaderState(*desc, link, spirv, std::move(archive)); return; } -#endif (void)linkedStages; (void)linkedStageCount; // P5e (pg): NO ARCHIVE ON THIS ARM, and the null is the arm selection rather than a diff --git a/MobileGL/MG_Pipe/PipeRoute.h b/MobileGL/MG_Pipe/PipeRoute.h index f765d07b..c9e73425 100644 --- a/MobileGL/MG_Pipe/PipeRoute.h +++ b/MobileGL/MG_Pipe/PipeRoute.h @@ -294,15 +294,10 @@ namespace MobileGL::MG_Pipe { // latch clear, so every later row for that object keeps taking the real answer. The cost of // that case is throughput, never silence. inline Bool MGPipeResourceRespecifyWantsItsReply(const MGPResourceDesc& desc) { -#if MOBILEGL_BUILD_RECORD_ARM if (MGPipeInstalledArm() != MGPipeRouteArm::kClientWire) return true; if (static_cast(desc.Target) == MGPipeResourceTarget::Buffer) return false; return !MGPipeHandleIsPublished(MGPipeKind::Texture, desc.Resource); -#else - (void)desc; - return true; -#endif } inline Bool MGPipeRouteResourceRespecify(const MGPResourceDesc& desc, const void* initialBytes, const MGPRespecifiedLevel* level = nullptr) { @@ -372,12 +367,10 @@ namespace MobileGL::MG_Pipe { // invariant MGPipeTypes.h asserts beside the packer and which the applier's own // SubDataNamesABuffer already reads. inline Bool MGPipeSubDataWantsItsReply(const MGPSubData& record) { -#if MOBILEGL_BUILD_RECORD_ARM // THE WIRE ARM ONLY. Everything above is an argument about a client talking to a server // over SEG_CMD/SEG_STAGE; a monolith run inside a split build (every unit and // integration-gpu lane is one) keeps the answer it always gave. if (MGPipeInstalledArm() == MGPipeRouteArm::kClientWire) return false; -#endif // THE PULL BUILD PREPROCESSES TO EXACTLY THIS LINE AND NOTHING ELSE, which is what G1 // compares: the arm test above sits inside the build switch, so the pull arm emits the // expression this function has always had. @@ -396,10 +389,8 @@ namespace MobileGL::MG_Pipe { MGPReplySlot reply = MGPipeMintReplySlot(); MGP_ResourceSubData(&record, bytes, byteCount, regions, record.RegionCount, &reply); const Bool accepted = MGPipeTakeReplyBool(reply, "resource_subdata"); -#if MOBILEGL_BUILD_RECORD_ARM // A cancelled wire upload is declined even when no server reply was requested. if (MGPipeInstalledArm() == MGPipeRouteArm::kClientWire) return accepted; -#endif return MGPipeSubDataWantsItsReply(record) ? accepted : true; } inline void MGPipeRouteBufferSubDataResident(const MGPSubData& record, const void* bytes, diff --git a/MobileGL/MG_Pipe/PipeSessionFail.h b/MobileGL/MG_Pipe/PipeSessionFail.h index 23704f8b..35128761 100644 --- a/MobileGL/MG_Pipe/PipeSessionFail.h +++ b/MobileGL/MG_Pipe/PipeSessionFail.h @@ -58,13 +58,11 @@ namespace MobileGL::MG_Pipe { UnmigratedVerb, // A call that reached an arm this build did not compile, or ran on the wrong role. RoleViolation, -#if MOBILEGL_BUILD_RECORD_ARM // A malformed peer record rejected by the server-side applier. ProtocolCorruption, // The GPU device a session's backend renders with is lost (a GPU fault or hang the driver // reset). Raised only through MGPipeSessionLatch below: it ends THAT session. DeviceLost, -#endif }; // What the layer above installs. `line` is the FULLY FORMATTED message, so the hook forwards @@ -131,7 +129,6 @@ namespace MobileGL::MG_Pipe { [[noreturn]] void MGPipeProtocolFatal(const char* what, const char* detail); [[noreturn]] void MGPipeProtocolFatalAt(const char* what, ::std::uint64_t got, ::std::uint64_t expected); -#if MOBILEGL_BUILD_RECORD_ARM // ---- THE LATCH TWIN: A LOST GPU DEVICE ENDS ITS SESSION, NOT THE PROCESS ---------------- // // MGPipeSessionFail is for a verb the backend cannot honour, and it does not return. A device @@ -161,7 +158,6 @@ namespace MobileGL::MG_Pipe { __attribute__((format(printf, 2, 3))) #endif MGPipeSessionLatch(MGPipeFatalFamily family, const char* fmt, ...); -#endif #if MOBILEGL_BUILD_DISAGGREGATED diff --git a/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp b/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp index 96218f1d..c67d794b 100644 --- a/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp +++ b/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp @@ -17,14 +17,12 @@ // role IS MG_State plus MG_Impl - and the edge exists only in a build that has the transport at all. #include #endif -#if MOBILEGL_BUILD_RECORD_ARM // The client role's persistent-map tracker (P13 W5: the record arm's, so beside this file). #include #include #include #include -#endif namespace MobileGL::MG_State::GLState { namespace { @@ -32,7 +30,6 @@ namespace MobileGL::MG_State::GLState { // Starts at 1 so a zero-initialized cache slot can never carry a live buffer's id. std::atomic g_nextBufferLifetimeId{1}; -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd, CONTRACT-P5C §3.8 / §6 layer 1): the frontend BufferObject's legacy // accessors are a layer-1 surface. With an active transport, the pre-handle buffer // arm that reads them (Managers.cpp's RespecifyStorageNow / UploadRangeNow / @@ -66,10 +63,6 @@ namespace MobileGL::MG_State::GLState { if (!MG_Record::PersistentMapTracker::OnServerRole()) return; FatalLegacyBufferArmFromApplyThread(accessor); } -#else - // No record arm, no apply thread to refuse. - inline void RefuseLegacyBufferArmFromApplyThread(const char*) {} -#endif } Uint64 BufferObject::AllocateLifetimeId() { @@ -97,13 +90,11 @@ namespace MobileGL::MG_State::GLState { } BufferObject::~BufferObject() { -#if MOBILEGL_BUILD_RECORD_ARM // Unconditional, not behind PushIsArmed(): the transport mode cannot change, but the // tracker is a leaked singleton whose entries are raw pointers, and an entry that // outlives its object is the one failure this set must not have. Forget is a no-op // for a buffer that was never a member. MG_Record::PersistentMapTracker::Instance().Forget(*this); -#endif // 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 @@ -215,12 +206,10 @@ namespace MobileGL::MG_State::GLState { } m_size = size; m_resource.ResizeShadow(size); -#if MOBILEGL_BUILD_RECORD_ARM // The store this buffer's membership was about no longer exists, and ResizeShadow is // reserve+resize - a grow past the reserve reallocates - so a pushed block's source // base has moved too. Both are the same event to the tracker: re-read the predicate. NotePersistentMapStateChanged(); -#endif } void BufferObject::Respecify(SizeT size, const void* data) { @@ -364,12 +353,10 @@ namespace MobileGL::MG_State::GLState { m_mappedRange = {0, 0}; m_stagingBias = 0; m_ownsStagingData = false; -#if MOBILEGL_BUILD_RECORD_ARM // AFTER the reset, so the predicate reads the post-unmap state, and after the landing // above, so the last bytes of a write map are already on the wire when the record // that says "no live writer" goes out behind them. NotePersistentMapStateChanged(); -#endif } void BufferObject::FlushMemoryRange(SizeT offset, SizeT length) { @@ -406,7 +393,6 @@ namespace MobileGL::MG_State::GLState { } void BufferObject::SyncPersistentMappedRange() { -#if MOBILEGL_BUILD_RECORD_ARM // P5c (hd): the named refusal comes FIRST - a silent return here used to let a // server-side caller slip through with one MGLOG_D's worth of evidence (B3). // @@ -431,7 +417,6 @@ namespace MobileGL::MG_State::GLState { MG_Record::PersistentMapTracker::Instance().PushBlocksFor(*this); return; } -#endif if (!m_isMapped) return; // GPU-resident: the app already wrote directly into coherent GPU memory. This is // the whole point of the persistent-map path - the per-draw whole-buffer re-upload @@ -445,7 +430,6 @@ namespace MobileGL::MG_State::GLState { NotifySubData(m_mappedRange.start, m_mappedRange.end - m_mappedRange.start); } -#if MOBILEGL_BUILD_RECORD_ARM void BufferObject::PushMappedSpanBlock(SizeT offset, SizeT size) { // NotifySubData and not MGPipeEmitResourceSubData directly: the serial bump, the // defined-content promotion and the legacy-ops fallback are what the monolith span @@ -532,7 +516,6 @@ namespace MobileGL::MG_State::GLState { Bool BufferObject::HasLiveHostWritesForWire() const { return m_publishedLiveHostWrites; } -#endif void BufferObject::WritebackFromBackend(DataPtr data, SizeT atOffset) { MOBILEGL_ASSERT(atOffset + data.size <= m_size, @@ -541,7 +524,6 @@ namespace MobileGL::MG_State::GLState { Memcpy(m_resource.Bytes() + atOffset, data.data, data.size); ++m_changeSerial; MGP_NOTE_AGGREGATE(BufferChange); -#if MOBILEGL_BUILD_RECORD_ARM // THE THIRD STATE'S ONLY EXIT. In a split build SyncGpuWrites does NOT clear the // flag before emitting, because between the emission and the answer the shadow is // stale and the object has no way to say so; the answer landing here is what makes it @@ -556,7 +538,6 @@ namespace MobileGL::MG_State::GLState { if (MG_Config::DataArmIsRecord() && atOffset == 0 && data.size >= m_size) { m_gpuWritePending = false; } -#endif } void BufferObject::MarkGpuWritten() { @@ -824,12 +805,10 @@ namespace MobileGL::MG_State::GLState { m_mappingAccess = (read ? BufferMappingAccessBit::Read : BufferMappingAccessBit::Null) | (write ? BufferMappingAccessBit::Write : BufferMappingAccessBit::Null); m_mappedRange = {0, m_size}; -#if MOBILEGL_BUILD_RECORD_ARM // glMapBuffer never takes the Persistent bit, so this buffer can never join the // push set - but a WRITE map still mutates the shadow with no call, which is the // half of the live-host-writes bit that is not about the push at all. NotePersistentMapStateChanged(); -#endif if (m_mappingAccess & BufferMappingAccessBit::Write) { // glMapBuffer maps from offset 0, so no bias: the allocation's own @@ -909,7 +888,6 @@ namespace MobileGL::MG_State::GLState { m_isMapped = true; m_mappingAccess = access; m_mappedRange = range; -#if MOBILEGL_BUILD_RECORD_ARM // BEFORE the adoption attempt below, deliberately. Under R-6 the acquisition always // declines, so the predicate this publishes is already final; if a later phase ever // mints one, the adoption path notes the change itself (it does now - the call is @@ -917,7 +895,6 @@ namespace MobileGL::MG_State::GLState { // having been made, which is the order that keeps the set conservative under both // answers. NotePersistentMapStateChanged(); -#endif if (access & BufferMappingAccessBit::Persistent) { m_ownsStagingData = false; @@ -931,14 +908,11 @@ namespace MobileGL::MG_State::GLState { !(access & BufferMappingAccessBit::FlushExplicit) && MG_Pipe::MGPipeResourceSubsystemEnabled()) { if (void* pushedBase = MG_Pipe::MGPipeEmitMapPersistent(*this)) { -#if MOBILEGL_BUILD_RECORD_ARM // P11 B2 made this reachable (a T0 adoption), so the tracker lets go of the // shadow range WHILE THE SHADOW IS STILL OURS: AdoptPersistentMap frees it, and // an untrack after that would mprotect pages the buffer no longer owns. MG_Record::PersistentMapTracker::Instance().Forget(*this); -#endif m_resource.AdoptPersistentMap(pushedBase); -#if MOBILEGL_BUILD_RECORD_ARM // An adoption takes the buffer OUT of the push set and out of the // live-host-writes state: the application now writes coherent GPU memory // and there is nothing to ship. Under R-6 this is unreachable; it is here @@ -946,7 +920,6 @@ namespace MobileGL::MG_State::GLState { // entry and nothing did, which would have left the published bit true // across an adoption until unmap (latent for P11). NotePersistentMapStateChanged(); -#endif } return m_resource.Bytes() + range.start; } @@ -994,7 +967,6 @@ namespace MobileGL::MG_State::GLState { return m_resource.Bytes(); } -#if MOBILEGL_BUILD_RECORD_ARM SizeT BufferObject::ShadowAllocationBytes() const { // The extent of the very pointer MappedData() hands out, read by the same caller // (the tracker's registration) on the same thread: the same rule-E surface, the @@ -1002,7 +974,6 @@ namespace MobileGL::MG_State::GLState { RefuseLegacyBufferArmFromApplyThread("ShadowAllocationBytes"); return m_resource.ShadowAllocationBytes(); } -#endif Bool BufferObject::IsBackendPersistentMapped() const { return m_resource.IsGpuResident(); diff --git a/MobileGL/MG_State/GLState/BufferState/BufferObject.h b/MobileGL/MG_State/GLState/BufferState/BufferObject.h index 7de8955d..5530e082 100644 --- a/MobileGL/MG_State/GLState/BufferState/BufferObject.h +++ b/MobileGL/MG_State/GLState/BufferState/BufferObject.h @@ -187,7 +187,6 @@ namespace MobileGL { // from every path that reads the shadow on the app's behalf. void SyncGpuWrites(); -#if MOBILEGL_BUILD_RECORD_ARM // ---- P5 b1: the two things a split build has to do that a monolith does not --- // // Everything here is behind the build option AND behind @@ -238,7 +237,6 @@ namespace MobileGL { // layer-1 read of client memory like MappedData (CONTRACT-P5C rule E) and carries // the same apply-thread refusal. SizeT ShadowAllocationBytes() const; -#endif Bool IsMapped() const; Bool IsImmutableStorage() const; @@ -321,12 +319,10 @@ namespace MobileGL { // and, in a split build, cleared by WritebackFromBackend instead, because there // the answer arrives later than the request. See SyncGpuWrites' definition. Bool m_gpuWritePending = false; -#if MOBILEGL_BUILD_RECORD_ARM // The last value of MGPResourceDesc::HasLiveHostWrites this object published. // Behind the option so the pull build's layout - and therefore every inlined // constructor and accessor in it - does not move (G1). Bool m_publishedLiveHostWrites = false; -#endif Range1D m_mappedRange; // The write-map staging store. MapAlignedData because the application is handed a // pointer into it, and biased by m_stagingBias because ARB_map_buffer_alignment diff --git a/MobileGL/MG_State/GLState/BufferState/PipeResource.h b/MobileGL/MG_State/GLState/BufferState/PipeResource.h index ea811138..9ab1c11b 100644 --- a/MobileGL/MG_State/GLState/BufferState/PipeResource.h +++ b/MobileGL/MG_State/GLState/BufferState/PipeResource.h @@ -53,11 +53,9 @@ namespace MobileGL::MG_State::GLState { // never exceed what was allocated. The pull build keeps the exact count and does not // see this function at all: it has no tracker to spend the rounding on, and G1 holds // its symbol set and .text byte-identical only if allocate()'s own text does not move. -#if MOBILEGL_BUILD_RECORD_ARM inline constexpr SizeT ShadowAllocationBytesFor(SizeT count) { return (count + SHADOW_ALLOCATION_ALIGNMENT - 1) & ~(SHADOW_ALLOCATION_ALIGNMENT - 1); } -#endif // Allocator that gives every allocation SHADOW_ALLOCATION_ALIGNMENT (and, in a split // build, a page-granular size - see ShadowAllocationBytesFor). Deliberately minimal: the @@ -73,13 +71,8 @@ namespace MobileGL::MG_State::GLState { T* allocate(SizeT count) { if (count == 0) return nullptr; -#if MOBILEGL_BUILD_RECORD_ARM return static_cast(::operator new(ShadowAllocationBytesFor(count * sizeof(T)), std::align_val_t{SHADOW_ALLOCATION_ALIGNMENT})); -#else - return static_cast( - ::operator new(count * sizeof(T), std::align_val_t{SHADOW_ALLOCATION_ALIGNMENT})); -#endif } void deallocate(T* pointer, SizeT) noexcept { ::operator delete(pointer, std::align_val_t{SHADOW_ALLOCATION_ALIGNMENT}); @@ -141,7 +134,6 @@ namespace MobileGL::MG_State::GLState { const SizeT reserved = std::bit_ceil(size == 0 ? SizeT{1} : size); m_shadow->reserve(reserved); m_shadow->resize(size); -#if MOBILEGL_BUILD_RECORD_ARM // RECORDED HERE, NOT INFERRED FROM capacity(). `reserved` is the count this // call asked the allocator for, so ShadowAllocationBytesFor(reserved) is the // block the allocator handed back whenever this reserve reallocated - and when @@ -155,14 +147,12 @@ namespace MobileGL::MG_State::GLState { // under-report costs nothing: the tracker still needs rangeEnd <= extent, and // size <= reserved always. m_shadowExtent = ShadowAllocationBytesFor(reserved); -#endif } // Direct shadow access, used only by the backend's upload-from-shadow path, // which never runs for a GPU-resident (persistent) buffer. MapAlignedData& Shadow() { return *m_shadow; } const MapAlignedData& Shadow() const { return *m_shadow; } -#if MOBILEGL_BUILD_RECORD_ARM // The extent of the shadow's heap allocation in bytes, as ResizeShadow asked for // it: every byte of [Bytes(), Bytes() + this) belongs to this shadow and to // nothing else, and the extent is a whole number of SHADOW_ALLOCATION_ALIGNMENT @@ -172,7 +162,6 @@ namespace MobileGL::MG_State::GLState { // kill). Zero for an adopted (GPU-resident) store, whose shadow was released, and // for a shadow that was never sized; the tracker excludes both. SizeT ShadowAllocationBytes() const { return m_gpuMapped != nullptr ? 0 : m_shadowExtent; } -#endif // Transition to persistent GPU residency: adopt the backend's coherent // mapped base as the source of truth and drop the CPU shadow. The caller @@ -182,10 +171,8 @@ namespace MobileGL::MG_State::GLState { m_gpuMapped = mappedBase; m_shadow->clear(); m_shadow->shrink_to_fit(); -#if MOBILEGL_BUILD_RECORD_ARM // The block is gone with the shrink; the next ResizeShadow records the next one. m_shadowExtent = 0; -#endif } // Give the adoption back: the bytes resolve against the shadow again (which @@ -209,9 +196,7 @@ namespace MobileGL::MG_State::GLState { SharedPtr m_shadow = MakeShared(); void* m_gpuMapped = nullptr; SharedPtr m_backend; -#if MOBILEGL_BUILD_RECORD_ARM // See ShadowAllocationBytes. Split-only so the pull build's layout does not move (G1). SizeT m_shadowExtent = 0; -#endif }; } // namespace MobileGL::MG_State::GLState diff --git a/MobileGL/MG_State/GLState/Core.cpp b/MobileGL/MG_State/GLState/Core.cpp index 34242519..3695706b 100644 --- a/MobileGL/MG_State/GLState/Core.cpp +++ b/MobileGL/MG_State/GLState/Core.cpp @@ -1556,12 +1556,10 @@ namespace MobileGL::MG_State { return it != m_transformFeedbackObjects.end() && it->second.everBound; } -#if MOBILEGL_BUILD_RECORD_ARM Uint64 GLContext::GetTransformFeedbackLifetimeId(Uint index) const { const auto found = m_transformFeedbackObjects.find(index); return found == m_transformFeedbackObjects.end() ? 0 : found->second.lifetimeId; } -#endif void GLContext::MarkTransformFeedbackObjectForDeletion(Uint index) { if (index == 0 || !m_transformFeedbackNames.IsValid(index)) return; diff --git a/MobileGL/MG_State/GLState/Core.h b/MobileGL/MG_State/GLState/Core.h index d6655f3c..07f1457c 100644 --- a/MobileGL/MG_State/GLState/Core.h +++ b/MobileGL/MG_State/GLState/Core.h @@ -571,9 +571,7 @@ namespace MobileGL { // Never returns 0 - the counter starts at 1 so a zero-initialised memo slot cannot // be mistaken for a live object. Uint64 GetBoundTransformFeedbackLifetimeId() const { return m_boundTransformFeedbackLifetimeId; } -#if MOBILEGL_BUILD_RECORD_ARM Uint64 GetTransformFeedbackLifetimeId(Uint index) const; -#endif // Whether the object carrying this identity still has an OPEN capture span - one // that glBeginTransformFeedback started and glEndTransformFeedback has not closed, // paused or not. A backend that hands out a bounded set of per-object slots must diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp b/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp index 75b84ac2..df8db39b 100644 --- a/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp @@ -87,7 +87,6 @@ namespace MobileGL::MG_State::GLState { return m_framebufferObjects.find(index) != m_framebufferObjects.end(); } -#if MOBILEGL_BUILD_RECORD_ARM SharedPtr FramebufferState::FindFramebufferObjectByLifetimeId(Uint64 lifetimeId) const { for (const auto& [index, framebufferObject] : m_framebufferObjects) { if (framebufferObject && framebufferObject->GetLifetimeId() == lifetimeId) { @@ -96,5 +95,4 @@ namespace MobileGL::MG_State::GLState { } return nullptr; } -#endif } // namespace MobileGL::MG_State::GLState diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.h b/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.h index 6cf5ef92..e7754953 100644 --- a/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.h +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.h @@ -28,7 +28,6 @@ namespace MobileGL::MG_State::GLState { Bool ValidateName(Uint index) const; Bool ValidateFramebufferObject(Uint index) const; -#if MOBILEGL_BUILD_RECORD_ARM // P5c (G6, CONTRACT-P5C §3.3/§5.4): the reverse of HandleFor() for a server that holds // only the handle - the named-blit consumer on a backend with no FBO twin registry // (Magma) resolves the verb's ReadFbo/DrawFbo to the frontend object by the lifetime @@ -36,7 +35,6 @@ namespace MobileGL::MG_State::GLState { // MGPipeFrontendKeyedRegistryScope; P3b/P4b retire it by carrying the object identity // in the record. nullptr when no live framebuffer owns the id. SharedPtr FindFramebufferObjectByLifetimeId(Uint64 lifetimeId) const; -#endif // 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 diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramArtifacts.h b/MobileGL/MG_State/GLState/ProgramState/ProgramArtifacts.h index b192442f..90fce830 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramArtifacts.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramArtifacts.h @@ -90,7 +90,6 @@ namespace MobileGL::MG_State::GLState { using PipeInputReflection = ResourceReflection; using PipeOutputReflection = ResourceReflection; -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 2 package C, OQ-8 (CONTRACT-P7 §5.3): THE SHADER STORAGE BLOCKS AS DIRECTVULKAN // INDEXES THEM, published once at link time instead of re-derived per draw. // @@ -129,7 +128,6 @@ namespace MobileGL::MG_State::GLState { // it; the wire consumer does not read it today. Int32 dataSize = 0; }; -#endif // Transform feedback (GL 3.0 core: glTransformFeedbackVaryings applies on // the NEXT link; the linked snapshot below is what draws and queries see). @@ -208,12 +206,10 @@ namespace MobileGL::MG_State::GLState { // The owned reflection snapshot. Indexed by TProgram index; see the structs above. Vector uniformReflection; Vector blockReflection; -#if MOBILEGL_BUILD_RECORD_ARM // P7 OQ-8: DirectVulkan's storage-block index space, filled beside blockReflection in // SnapshotGlslangReflection. See StorageBlockReflection above for what the order is // and why it is not blockReflection's. Vector storageBlocks; -#endif Vector pipeInputReflection; Vector pipeOutputReflection; // Program-level scalars glslang answers off the linked intermediates. @@ -526,7 +522,6 @@ namespace MobileGL::MG_State::GLState { v("blockMemberElement", a.blockMemberElement); } // 11 fields -#if MOBILEGL_BUILD_RECORD_ARM // P7 OQ-8. Three plain fields, so the generic codec arms carry it with no new arm of their // own - which is the whole reason it is a table rather than hand-written bytes. template @@ -536,7 +531,6 @@ namespace MobileGL::MG_State::GLState { v("binding", a.binding); v("dataSize", a.dataSize); } // 3 fields -#endif // Every member EXCEPT `program`: it is null for every archived instance by construction // (ProgramTranslationCache.h asserts that at insert) and must never be serialized - it is @@ -547,11 +541,9 @@ namespace MobileGL::MG_State::GLState { void VisitFields(Self& a, V&& v) { v("uniformReflection", a.uniformReflection); v("blockReflection", a.blockReflection); -#if MOBILEGL_BUILD_RECORD_ARM // Beside blockReflection because that is where it is FILLED, and a visitor that walks // the table in declaration order then reads the two together. v("storageBlocks", a.storageBlocks); -#endif v("pipeInputReflection", a.pipeInputReflection); v("pipeOutputReflection", a.pipeOutputReflection); v("lastStageIsFragment", a.lastStageIsFragment); @@ -634,13 +626,9 @@ namespace MobileGL::MG_State::GLState { #if defined(__GLIBCXX__) && !defined(_GLIBCXX_DEBUG) && (SIZE_MAX == UINT64_MAX) #define MGL_RESOURCEREFLECTION_SIZE 128 #define MGL_XFBVARYING_SIZE 128 -#if MOBILEGL_BUILD_RECORD_ARM // P7 OQ-8 added storageBlocks, one more Vector, in the disaggregated build ONLY. The pull // number below is the one G1 measures and it has not moved. #define MGL_LINKARTIFACTS_SIZE 1080 -#else -#define MGL_LINKARTIFACTS_SIZE 1056 -#endif #define MGL_SPIRVARTIFACTS_SIZE 88 #elif defined(_LIBCPP_VERSION) && (SIZE_MAX == UINT64_MAX) && defined(MGL_ARTIFACT_SIZES_LIBCXX_PINNED) // The integrator pins these from the NDK build (brief C.4); until then this branch is inert. diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramArtifactsCodec.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramArtifactsCodec.cpp index e61d59c6..dbd15cc5 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramArtifactsCodec.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramArtifactsCodec.cpp @@ -85,7 +85,6 @@ namespace MobileGL::MG_State::GLState { visit("floatValues", value.floatValues); } -#if MOBILEGL_BUILD_RECORD_ARM void SchemaWord(Uint64& hash, Uint64 word) { for (unsigned i = 0; i < 8; ++i) { hash ^= (word >> (i * 8)) & 255u; @@ -151,7 +150,6 @@ namespace MobileGL::MG_State::GLState { SchemaName(hash, "end-record"); } } -#endif // ---- the writer ---- @@ -200,20 +198,9 @@ namespace MobileGL::MG_State::GLState { } else if constexpr (ArchiveVector) { WriteSequence(out, value); } else if constexpr (ArchiveUniformInitializer) { -#if MOBILEGL_BUILD_RECORD_ARM VisitUniformInitializer(value, [&out](const char*, const auto& member) { WriteValue(out, member); }); -#else - WriteValue(out, value.name); - WriteValue(out, value.basicType); - WriteValue(out, value.vectorSize); - WriteValue(out, value.matrixCols); - WriteValue(out, value.matrixRows); - WriteValue(out, value.arraySize); - WriteValue(out, value.intValues); - WriteValue(out, value.floatValues); -#endif } else { // The archive's own structs: TypeFacts, ResourceReflection, XfbVarying. ONE // table serves both directions, so a member added to any of them is carried by @@ -366,20 +353,9 @@ namespace MobileGL::MG_State::GLState { if (!in.Ok) return; } } else if constexpr (ArchiveUniformInitializer) { -#if MOBILEGL_BUILD_RECORD_ARM VisitUniformInitializer(value, [&in](const char*, auto& member) { if (in.Ok) ReadValue(in, member); }); -#else - ReadValue(in, value.name); - ReadValue(in, value.basicType); - ReadValue(in, value.vectorSize); - ReadValue(in, value.matrixCols); - ReadValue(in, value.matrixRows); - ReadValue(in, value.arraySize); - ReadValue(in, value.intValues); - ReadValue(in, value.floatValues); -#endif } else { VisitFields(value, [&in](const char*, auto& field) { if (in.Ok) ReadValue(in, field); @@ -389,16 +365,8 @@ namespace MobileGL::MG_State::GLState { // v1 is retained for local monolith verification. Its native size echo is not a // wire compatibility fact: libstdc++ writes 1056 while unpinned libc++ writes zero. -#if !MOBILEGL_BUILD_RECORD_ARM -#ifdef MGL_LINKARTIFACTS_SIZE - inline constexpr Uint64 kLinkArtifactsSizeEcho = MGL_LINKARTIFACTS_SIZE; -#else - inline constexpr Uint64 kLinkArtifactsSizeEcho = 0; -#endif -#endif } // namespace -#if MOBILEGL_BUILD_RECORD_ARM Uint64 ProgramArtifactsSchemaFingerprint() { static const Uint64 fingerprint = [] { Uint64 hash = 1469598103934665603ull; @@ -412,16 +380,11 @@ namespace MobileGL::MG_State::GLState { }(); return fingerprint; } -#endif void EncodeProgramArtifacts(const LinkArtifacts& link, const SpirvArtifacts& spirv, Vector& out) { PutRaw(out, kProgramArtifactsCodecVersion); -#if MOBILEGL_BUILD_RECORD_ARM PutRaw(out, ProgramArtifactsSchemaFingerprint()); -#else - PutRaw(out, kLinkArtifactsSizeEcho); -#endif // `link` is walked through its own VisitFields table, which omits the live // SharedPtr: 57 of the 58 members. There is no arm here for it and // there must not be one - it points into a glslang arena that no archived instance @@ -446,11 +409,7 @@ namespace MobileGL::MG_State::GLState { // Refuse the declared wire shape before reading any field. In v2 the second word // follows serialization types/order; C++ container object sizes are irrelevant. if (version != kProgramArtifactsCodecVersion) return false; -#if MOBILEGL_BUILD_RECORD_ARM if (schema != ProgramArtifactsSchemaFingerprint()) return false; -#else - if (schema != kLinkArtifactsSizeEcho) return false; -#endif ReadValue(in, link); ReadValue(in, spirv); diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramArtifactsCodec.h b/MobileGL/MG_State/GLState/ProgramState/ProgramArtifactsCodec.h index 8bcf94ad..c9ac83f4 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramArtifactsCodec.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramArtifactsCodec.h @@ -60,7 +60,6 @@ namespace MobileGL::MG_State::GLState { // Bumped whenever the byte format changes in a way a previous reader would misread. A // reader that sees a different word REFUSES; it never tries to guess a layout. -#if MOBILEGL_BUILD_RECORD_ARM // 3 since P7 wave 2 package C (OQ-8): LinkArtifacts gained `storageBlocks`, so a v2 reader // would run out of bytes in the middle of the stream rather than notice. The schema // fingerprint beside the version would catch it on its own - it is derived from the @@ -72,9 +71,6 @@ namespace MobileGL::MG_State::GLState { // Derived from the actual VisitFields order/names, container element schemas and scalar // representations. No native container size/offset is included. Also checked in Hello. Uint64 ProgramArtifactsSchemaFingerprint(); -#else - inline constexpr Uint32 kProgramArtifactsCodecVersion = 1; -#endif // Appends the archive to `out` (which is not cleared, so a caller may frame it). Never // fails: everything it walks is owned plain data. diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramLinkTask.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramLinkTask.cpp index c501f5a6..6cbd47ab 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramLinkTask.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramLinkTask.cpp @@ -106,7 +106,6 @@ namespace { return bracket == MobileGL::String::npos ? name : name.substr(0, bracket); } -#if MOBILEGL_BUILD_RECORD_ARM // P7 OQ-8. ShaderStage -> EShLanguage, so a reflection record's `stages` mask (which is an // EShLanguageMask) can be tested against the stage of a snapshotted shader. Written here // rather than lifted into a shared header because this is the only caller and @@ -127,7 +126,6 @@ namespace { } return EShLangCount; } -#endif // Element index of an arrayed interface-block instance: "GOKU[3]" -> 3, "GOKU" -> 0. // Reflection spells arrayed instances exactly this way (glslang expands the instance @@ -1758,17 +1756,14 @@ namespace MobileGL::MG_State::GLState { } SnapshotGlslangReflection(); -#if MOBILEGL_BUILD_RECORD_ARM // P7 OQ-8. Guarded at the CALL as well as at the definition, which is not belt and // braces: LinkArtifacts::storageBlocks does not exist in a pull build, so neither can // the function that fills it, and G1 requires this translation unit to be statement // for statement what it was there. SnapshotStorageBlockIndexSpace(); -#endif return true; } -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 2 package C, OQ-8 (CONTRACT-P7 §5.3): DIRECTVULKAN'S STORAGE-BLOCK INDEX SPACE, // BUILT ONCE HERE INSTEAD OF PER DRAW. // @@ -1847,7 +1842,6 @@ namespace MobileGL::MG_State::GLState { MGLOG_D("ProgramObject %u: Reflection - %zu storage block(s) in the backend index space", in.externalIndex, artifacts.storageBlocks.size()); } -#endif // The last thing DoReflection does, and the thing that lets everything after it stop // caring that a glslang::TProgram ever existed: copy every reflection record the GL query diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramLinkTask.h b/MobileGL/MG_State/GLState/ProgramState/ProgramLinkTask.h index 40aa09ea..40693b2c 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramLinkTask.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramLinkTask.h @@ -207,14 +207,12 @@ namespace MobileGL::MG_State::GLState { // one and overwritten the qualifier. See the definition for why the invented binding is // deliberately left in place for the backends' own use. void SeedDefaultStorageBlockBindings(); -#if MOBILEGL_BUILD_RECORD_ARM // P7 wave 2 package C, OQ-8: builds LinkArtifacts::storageBlocks - DirectVulkan's own // storage-block index space - out of the reflection snapshot the call above produced, // so the backends stop re-deriving it with SPIRV-Reflect on every draw. Runs after // SnapshotGlslangReflection because it reads blockReflection. See the definition for // which order it has to reproduce and why each clause of it is derivable here. void SnapshotStorageBlockIndexSpace(); -#endif Bool ValidateFragmentOutputLocations(); Bool ResolveTransformFeedbackVaryings(); void ResolveGsTriangleStripCapture(const glslang::TIntermediate* captureIntermediate); diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h index 181f7e64..a61a08bc 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h @@ -48,10 +48,8 @@ namespace MobileGL::MG_State::GLState { using BlockReflection = ResourceReflection; using PipeInputReflection = ResourceReflection; using PipeOutputReflection = ResourceReflection; -#if MOBILEGL_BUILD_RECORD_ARM // P7 OQ-8: DirectVulkan's storage-block index space, carried in LinkArtifacts. using StorageBlockReflection = MobileGL::MG_State::GLState::StorageBlockReflection; -#endif using XfbVarying = MobileGL::MG_State::GLState::XfbVarying; using LinkArtifacts = MobileGL::MG_State::GLState::LinkArtifacts; using SpirvArtifacts = MobileGL::MG_State::GLState::SpirvArtifacts; diff --git a/MobileGL/MG_Test/Pipe/ResourceEmitTest.cpp b/MobileGL/MG_Test/Pipe/ResourceEmitTest.cpp index 85c43187..ac9f386b 100644 --- a/MobileGL/MG_Test/Pipe/ResourceEmitTest.cpp +++ b/MobileGL/MG_Test/Pipe/ResourceEmitTest.cpp @@ -1205,65 +1205,11 @@ namespace { // always true) and the production-path probe pair in MG_Test/SanityTest.cpp and // MG_Test/Buffer/SplitBufferTest.cpp, both of which go red when the producer is // deleted. This skip is what the build-verify-split lane exists to make visible. -#elif MOBILEGL_BUILD_RECORD_ARM +#else // P13 W5: the producer is the record arm's (BufferObject::NotePersistentMapStateChanged), // so the wire is retired wherever that arm is built (PipeApply.cpp's pin follows it). GTEST_SKIP() << "P5 gave HasLiveHostWrites a producer, so the always-false wire is retired " "wherever the record arm is built; PinLiveHostWritesNamesABuffer replaces it"; -#elif !MGTEST_HAVE_FORK - GTEST_SKIP() << "no fork on this platform; the wire's verdict is std::abort()"; -#else - ApplierGuard guard; - const MGPipeHandle res{8, 4}; - const Uint8 bytes[64] = {}; - MGPipeApplyResourceCreate(BufferDesc(res, 0, 55)); - MGPipeApplyResourceRespecify(BufferDesc(res, 256, 55), nullptr); - - // The negative control: with the flag clear the same call is silent and answers - // normally, so what follows is the flag firing and not the call. - EXPECT_EQ(MGPipeApplyMapPersistent(BufferHandle(res), 256, bytes), nullptr); - EXPECT_EQ(ReadLog().find("PipeLiveHostWrites"), std::string::npos); - - struct Drive { - MGPipeHandle Res; - const char* Call; - }; - const Drive drives[] = { - {res, "map_persistent"}, {res, "resource_respecify"}, {res, "resource_subdata"}, - {res, "resource_flush_range"}, {res, "resource_readback"}, - }; - for (const Drive& drive : drives) { - const ChildResult child = RunInChild([&drive, &bytes]() { - // Set in the CHILD: the parent's applier must stay honest for the next drive. - MGPipeApplier().Resources[drive.Res.Slot].HasLiveHostWrites = true; - const String call = drive.Call; - if (call == "map_persistent") { - MGPipeApplyMapPersistent(MGPHandleOnly{drive.Res, static_cast(MGPipeKind::Buffer), 0}, - 256, bytes); - } else if (call == "resource_respecify") { - MGPResourceDesc desc{}; - desc.Resource = drive.Res; - desc.Width = 256; - desc.GlNameForDiag = 55; - MGPipeApplyResourceRespecify(desc, nullptr); - } else if (call == "resource_subdata") { - MGPSubData record{}; - record.Res = drive.Res; - MGPipeSetSubDataBufferRange(record, 0, 64); - MGPipeApplyResourceSubData(record, bytes); - } else if (call == "resource_flush_range") { - MGPipeApplyResourceFlushRange(MGPFlushRange{drive.Res, 0, 64, 0, 0}, bytes); - } else { - MGPipeApplyResourceReadback(MGPReadback{drive.Res, 0, 256}); - } - }); - EXPECT_TRUE(DiedOfAbort(child)) - << drive.Call << ": " << DescribeStatus(child) << "; log: " << child.Log; - const std::string wanted = - std::string("Fatal{PipeLiveHostWrites} ") + drive.Call + " {slot=8, gen=4}"; - EXPECT_NE(child.Log.find(wanted), std::string::npos) - << "wanted \"" << wanted << "\"; log: " << child.Log; - } #endif } diff --git a/MobileGL/MG_Test/Program/ProgramArtifactsCodecTest.cpp b/MobileGL/MG_Test/Program/ProgramArtifactsCodecTest.cpp index 9f8203ab..aeebd9b0 100644 --- a/MobileGL/MG_Test/Program/ProgramArtifactsCodecTest.cpp +++ b/MobileGL/MG_Test/Program/ProgramArtifactsCodecTest.cpp @@ -529,14 +529,10 @@ TEST(ProgramArtifactsCodec, AVersionMismatchIsRefused) { // TProgram, which is null for every archived instance by construction and points into an arena // no archive owns. A codec arm for it would be a use-after-free waiting for a cache hit. TEST(ProgramArtifactsCodec, TheTablesVisitEveryMemberExceptTheLiveProgram) { -#if MOBILEGL_BUILD_RECORD_ARM // P7 OQ-8: 59 members, 58 visited. The 59th is still the live TProgram; the 58th is // storageBlocks, which follows the record arm's guard (ProgramArtifacts.h). EXPECT_EQ(ProgramArtifactsVisitedFieldCount(), 58u); EXPECT_EQ(ProgramArtifactsVisitedFieldCount(), 3u); -#else - EXPECT_EQ(ProgramArtifactsVisitedFieldCount(), 57u); -#endif EXPECT_EQ(ProgramArtifactsVisitedFieldCount(), 8u); EXPECT_EQ(ProgramArtifactsVisitedFieldCount(), 14u); EXPECT_EQ(ProgramArtifactsVisitedFieldCount(), 11u); diff --git a/MobileGL/MG_Test/Program/ProgramArtifactsTest.cpp b/MobileGL/MG_Test/Program/ProgramArtifactsTest.cpp index 77eb4657..98a6212a 100644 --- a/MobileGL/MG_Test/Program/ProgramArtifactsTest.cpp +++ b/MobileGL/MG_Test/Program/ProgramArtifactsTest.cpp @@ -81,14 +81,10 @@ namespace { EXPECT_EQ(CountFields(), 20u); EXPECT_EQ(CountFields(), 14u); EXPECT_EQ(CountFields(), 11u); -#if MOBILEGL_BUILD_RECORD_ARM // P7 OQ-8 added LinkArtifacts::storageBlocks and its own three-field table; since P13 W5 // the member follows the record arm (ProgramArtifacts.h), which every library builds. EXPECT_EQ(CountFields(), 3u); EXPECT_EQ(CountFields(), 58u); -#else - EXPECT_EQ(CountFields(), 57u); -#endif EXPECT_EQ(CountFields(), 8u); } diff --git a/MobileGL/MG_Test/ScopedMonolithFrontendArm.h b/MobileGL/MG_Test/ScopedMonolithFrontendArm.h index 3a6fa57c..5f86adff 100644 --- a/MobileGL/MG_Test/ScopedMonolithFrontendArm.h +++ b/MobileGL/MG_Test/ScopedMonolithFrontendArm.h @@ -24,18 +24,14 @@ namespace MobileGL::MG_Test { class ScopedMonolithFrontendArm { public: ScopedMonolithFrontendArm() : m_savedTable(MG_Backend::gBackendFunctionsTable) { -#if MOBILEGL_BUILD_RECORD_ARM m_saved = MG_Config::MonolithTakesRecordArm; MG_Config::MonolithTakesRecordArm = false; if (MG_Config::Transport == MG_Config::TransportMode::Monolith && MG_Backend::pActiveBackendObject) { MG_Backend::gBackendFunctionsTable = MG_Backend::pActiveBackendObject->GetBackendFunctions(); } -#endif } ~ScopedMonolithFrontendArm() { -#if MOBILEGL_BUILD_RECORD_ARM MG_Config::MonolithTakesRecordArm = m_saved; -#endif MG_Backend::gBackendFunctionsTable = m_savedTable; } ScopedMonolithFrontendArm(const ScopedMonolithFrontendArm&) = delete; diff --git a/MobileGL/MG_Util/SelfTest/DriverBugProbes.cpp b/MobileGL/MG_Util/SelfTest/DriverBugProbes.cpp index d0279ce3..cff298ca 100644 --- a/MobileGL/MG_Util/SelfTest/DriverBugProbes.cpp +++ b/MobileGL/MG_Util/SelfTest/DriverBugProbes.cpp @@ -11,9 +11,7 @@ #include #include -#if MOBILEGL_BUILD_RECORD_ARM #include -#endif #include #include @@ -2479,7 +2477,6 @@ namespace MobileGL::MG_Util::SelfTest { return findings; } -#if MOBILEGL_BUILD_RECORD_ARM Optional DescribeDepthStencilResolvePassBug( const MG_Backend::DirectVulkan::WireDepthResolveProbeMeasurement& measurement, Bool shaderStencilExport) { using namespace MG_Backend::DirectVulkan; @@ -2546,5 +2543,4 @@ namespace MobileGL::MG_Util::SelfTest { } return findings; } -#endif } // namespace MobileGL::MG_Util::SelfTest diff --git a/MobileGL/MG_Util/SelfTest/DriverBugProbes.h b/MobileGL/MG_Util/SelfTest/DriverBugProbes.h index e96152fc..b03c7df8 100644 --- a/MobileGL/MG_Util/SelfTest/DriverBugProbes.h +++ b/MobileGL/MG_Util/SelfTest/DriverBugProbes.h @@ -9,9 +9,7 @@ #pragma once #include #include -#if MOBILEGL_BUILD_RECORD_ARM #include -#endif namespace MobileGL::MG_Util::SelfTest { // ===================== KNOWN DRIVER BUGS ===================== @@ -347,7 +345,6 @@ namespace MobileGL::MG_Util::SelfTest { // so an unaffected device renders an empty section rather than a wall of "not affected". Vector CollectGlesKnownDriverBugs(const MG_External::GLESFunctionsTable& gl); -#if MOBILEGL_BUILD_RECORD_ARM // ===================== KNOWN VULKAN DRIVER BUGS ===================== // // The DirectVulkan (Magma) backend's table, under the rules above: a control per probe, an @@ -376,5 +373,4 @@ namespace MobileGL::MG_Util::SelfTest { // Every known driver bug this Vulkan driver actually has. Vector CollectVulkanKnownDriverBugs(const VulkanDriverBugProbeContext& context); -#endif } // namespace MobileGL::MG_Util::SelfTest diff --git a/MobileGL/MG_Util/SelfTest/DriverPost.cpp b/MobileGL/MG_Util/SelfTest/DriverPost.cpp index 24300009..48b6a885 100644 --- a/MobileGL/MG_Util/SelfTest/DriverPost.cpp +++ b/MobileGL/MG_Util/SelfTest/DriverPost.cpp @@ -3028,7 +3028,6 @@ namespace MobileGL::MG_Util::SelfTest { graphicsQueueFamilyIndex, deviceExtensions, features, vkGetPhysicalDeviceFeatures2Fn, vkGetPhysicalDeviceProperties2Fn); -#if MOBILEGL_BUILD_RECORD_ARM // The "Known Driver Bugs" section's Vulkan table (DriverBugProbes.h): each probe makes its // own throwaway device on the physical device picked above. { @@ -3040,7 +3039,6 @@ namespace MobileGL::MG_Util::SelfTest { bugContext.deviceExtensions = &deviceExtensions; builder.report.knownDriverBugs = CollectVulkanKnownDriverBugs(bugContext); } -#endif if (HasVkExtension(deviceExtensions, VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME)) { builder.Pass("VK_KHR_draw_indirect_count", diff --git a/scripts/ci/retired_switches.py b/scripts/ci/retired_switches.py index faab406e..ccb56a6c 100644 --- a/scripts/ci/retired_switches.py +++ b/scripts/ci/retired_switches.py @@ -23,6 +23,9 @@ RULES = ( 'MOBILEGL_PIPE_LEGACY_MEMOS)'), (re.compile(r'\bMGB_CTX(?:_LIVE|_IDENTITY)?\b'), 'MGB_CTX is back; backends read MG_Pipe::gPipeInputs directly since P13 W3b'), + (re.compile(r'^\s*#\s*(?:if|ifdef|ifndef|elif)\b.*\bMOBILEGL_BUILD_RECORD_ARM\b'), + 'a preprocessor conditional names MOBILEGL_BUILD_RECORD_ARM, folded away at P13 W5 S8 - the ' + 'record arm is in every library; a transport-only block takes MOBILEGL_BUILD_DISAGGREGATED'), ) @@ -49,12 +52,15 @@ def self_test(): planted = [('planted.cpp', '#if MOBILEGL_PIPE_PUSH\nx();\n#endif\n'), ('planted.h', ' # elif !MOBILEGL_PIPE_LEGACY_MEMOS && FOO\n'), ('planted.inc', 'auto v = MGB_CTX->GetX();\n'), - ('planted2.cpp', 'if (MGB_CTX_LIVE) {}\n')] + ('planted2.cpp', 'if (MGB_CTX_LIVE) {}\n'), + ('planted3.cpp', '#if MOBILEGL_BUILD_RECORD_ARM && MOBILEGL_PIPE_POISON\n'), + ('planted4.h', '#elif !MOBILEGL_BUILD_RECORD_ARM\n')] for item in planted: assert scan([item]), f'the gate missed a planted line: {item}' clean = [('clean.cpp', 'features.PipePush = QueryEnvUint64("MOBILEGL_PIPE_PUSH", 0x3fff);\n'), ('clean.h', '// MOBILEGL_PIPE_PUSH=0x7f was the P2 mask\n'), - ('clean.inc', 'MG_Pipe::gPipeInputs.GetX();\n')] + ('clean.inc', 'MG_Pipe::gPipeInputs.GetX();\n'), + ('clean2.cpp', '// MOBILEGL_BUILD_RECORD_ARM was W5\'s temporary guard\n')] for item in clean: assert not scan([item]), f'the gate fired on a legitimate line: {item}' print(f'retired switches self-test: {len(planted)} planted lines caught, {len(clean)} clean lines left alone') @@ -68,7 +74,8 @@ def main(): print(f'::error::{line}') if findings: return 1 - print('retired switches: none of MOBILEGL_PIPE_PUSH / MOBILEGL_PIPE_LEGACY_MEMOS (as #if) or MGB_CTX in source') + print('retired switches: none of MOBILEGL_PIPE_PUSH / MOBILEGL_PIPE_LEGACY_MEMOS / MOBILEGL_BUILD_RECORD_ARM ' + '(as #if) or MGB_CTX in source') return 0 diff --git a/scripts/ci/wire_declines_audit.py b/scripts/ci/wire_declines_audit.py index 68056eb4..c2608903 100644 --- a/scripts/ci/wire_declines_audit.py +++ b/scripts/ci/wire_declines_audit.py @@ -82,9 +82,7 @@ FLOW_STOP = re.compile(r"^\s*(?:case\b|default\s*:|break\s*;|return\b|continue\s PP_OPEN = re.compile(r"^\s*#\s*(?:if|ifdef|ifndef)\b") PP_CLOSE = re.compile(r"^\s*#\s*endif\b") PP_STOP = re.compile(r"^\s*#\s*(?:else|elif)\b") -# P13 W5: the record arm's own guard, MOBILEGL_BUILD_RECORD_ARM, is the same build-selecting kind of -# opener (it equals the disaggregated build until W5's flip and is unifdef'd away after it). -PP_DISAGGREGATED = re.compile(r"^\s*#\s*(?:if|ifdef)\s+MOBILEGL_BUILD_(?:DISAGGREGATED|RECORD_ARM)\s*$") +PP_DISAGGREGATED = re.compile(r"^\s*#\s*(?:if|ifdef)\s+MOBILEGL_BUILD_DISAGGREGATED\s*$") def strip_code(text: str) -> str: @@ -361,24 +359,6 @@ SELF_TEST_FIXTURES = ( "#endif\n" " WireDeclineTally::Count(WireDeclineSite::GhostRow);\n" "}\n", 1, NO_LOG), - ("log only on the other side of a RECORD_ARM #else", _DEF_GHOST, - "void F(int x) {\n" - "#if MOBILEGL_BUILD_RECORD_ARM\n" - " MGLOG_W(\"x\");\n" - "#else\n" - " MGLOG_D(\"compiled away\");\n" - "#endif\n" - " WireDeclineTally::Count(WireDeclineSite::GhostRow);\n" - "}\n", 1, NO_LOG), - ("count under its log across a column-0 RECORD_ARM #if/#endif", _DEF_GHOST, - "void F(int x) {\n" - " if (x) {\n" - " MGLOG_W(\"x\");\n" - "#if MOBILEGL_BUILD_RECORD_ARM\n" - " WireDeclineTally::Count(WireDeclineSite::GhostRow);\n" - "#endif\n" - " }\n" - "}\n", 0, "0 unlogged, 0 unknown"), ("log only under a #if 0 above the Count", _DEF_GHOST, "void F(int x) {\n" " if (x) {\n"