[Refactor] (P13 W5 S2): MG_Backend/DirectVulkan's record-arm guards name MOBILEGL_BUILD_RECORD_ARM.

This commit is contained in:
2026-10-06 10:51:26 -04:00
parent 036d1ac36e
commit 22739a033c
34 changed files with 219 additions and 219 deletions
@@ -423,7 +423,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
Bool BackendObject_DirectVulkan::LatchIfGpuFaulted() {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
return pVulkanRenderer != nullptr && pVulkanRenderer->LatchIfGpuHung("apply");
#else
return false;
@@ -431,7 +431,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
void BackendObject_DirectVulkan::Initialize() {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
VkBufferManager::RegisterWireResourceOps();
// P7 wave 2 package C (CONTRACT-P7 §5.5). BESIDE the resource ops and for the same
// reason: this is the one place both Magma server roles pass through - the inproc
@@ -602,7 +602,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Bool BackendObject_DirectVulkan::ExportNativeFence(int* fence) {
*fence = -1;
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
return pVulkanRenderer ? pVulkanRenderer->ExportNativeFence(fence) : true;
#else
@@ -38,7 +38,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
RendererSlot pVulkanRenderer;
namespace {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
void RejectWireLegacyBuffer() {
if (MG_Config::DataArmIsRecord()) {
MGLOG_F("MGPipe: Fatal{RoleViolation, \"buffer-legacy-arm\"} (Magma P7 buffer consumer)");
@@ -138,7 +138,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
namespace {
#if !MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -184,7 +184,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Vector<StorageBlockResource> storageBlocks;
Vector<BufferVariableResource> bufferVariables;
};
#endif // !MOBILEGL_BUILD_DISAGGREGATED
#endif // !MOBILEGL_BUILD_RECORD_ARM
struct DrawElementsIndirectCommand {
Uint32 count = 0;
@@ -201,7 +201,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint32 baseInstance = 0;
};
#if !MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -223,7 +223,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
}
#if !MOBILEGL_BUILD_DISAGGREGATED
#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) {
@@ -374,9 +374,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
return cache;
}
#endif // !MOBILEGL_BUILD_DISAGGREGATED
#endif // !MOBILEGL_BUILD_RECORD_ARM
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -495,7 +495,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} // namespace
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
//
@@ -646,7 +646,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
DrawWireIndirect(mode, type, indirect, drawcount, stride, true);
return;
@@ -657,7 +657,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
pVulkanRenderer->MultiDrawElementsIndirect(mode, type, indirect, drawcount, stride);
}
void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
DrawWireIndirect(mode, 0, indirect, drawcount, stride, false);
return;
@@ -714,7 +714,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
void MultiDrawElementsIndirectCount(GLenum mode, GLenum type, const void* indirect, GLintptr drawcount,
GLsizei maxdrawcount, GLsizei stride) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
DrawWireIndirect(mode, type, indirect, maxdrawcount, stride, true, true, drawcount);
return;
@@ -726,7 +726,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
void MultiDrawArraysIndirectCount(GLenum mode, const void* indirect, GLintptr drawcount,
GLsizei maxdrawcount, GLsizei stride) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
DrawWireIndirect(mode, 0, indirect, maxdrawcount, stride, false, true, drawcount);
return;
@@ -804,7 +804,7 @@ 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
DrawWireIndirect(mode, type, indirect, 1, 0, true);
return;
@@ -869,7 +869,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
DrawArraysInstancedBaseInstance(mode, first, count, instancecount, 0);
}
void DrawArraysIndirect(GLenum mode, const void* indirect) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
DrawWireIndirect(mode, 0, indirect, 1, 0, false);
return;
@@ -943,7 +943,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
void DispatchComputeIndirect(GLintptr indirect) {
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -1014,7 +1014,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
void ShaderStorageBlockBinding(GLuint program, const GLchar* storageBlockName, GLuint storageBlockBinding) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
auto& state = MG_Pipe::MGPipeApplier();
const auto handle = state.VerbStorageBlockProgram;
@@ -1058,7 +1058,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
MakeUnique<GenericErrorInfo>("DirectVulkan", __func__, "Shader storage binding is out of range."));
return;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -1140,7 +1140,7 @@ 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<Uint32>& outIndices) {
#if MOBILEGL_BUILD_DISAGGREGATED
#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;
@@ -1318,7 +1318,7 @@ 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_DISAGGREGATED
#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;
@@ -1512,7 +1512,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
// Pure status read (glGetSynciv must not flush).
if (pVulkanRenderer->IsSubmitIndexComplete(sync->submitIndex)) return true;
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -45,7 +45,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint64 GetRendererGeneration();
void BumpRendererGeneration();
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -7,7 +7,7 @@
// End of Source File Header
#include "BufferArena.h"
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
#include <Config.h>
#endif
@@ -128,7 +128,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
bufferDesc.usage = m_desc.usage;
bufferDesc.memoryUsage = m_desc.memoryUsage;
bufferDesc.allocationFlags = m_desc.allocationFlags;
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -7,7 +7,7 @@
// End of Source File Header
#include "FrameContext.h"
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
#include <Config.h>
#endif
@@ -224,7 +224,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkImageMemoryBarrier presentBarrier{};
presentBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
presentBarrier.srcAccessMask = 0;
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -243,7 +243,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
presentBarrier.subresourceRange.baseArrayLayer = 0;
presentBarrier.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(commandBuffer,
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
MG_Config::DataArmIsRecord()
? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
#else
@@ -3,7 +3,7 @@
#include <MG_State/GLState/ProgramState/ProgramObject.h>
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
#include <MG_Pipe/PipeApply.h>
#include <MG_State/GLState/ProgramState/ProgramArtifactsCodec.h>
#include "../DirectVulkanResourceState.h"
@@ -15,7 +15,7 @@
#endif
namespace MobileGL::MG_Backend::DirectVulkan {
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -198,7 +198,7 @@ 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (payload.wireRenderPassCompatibilityId != 0) {
constexpr Uint64 wireDomain = 0x5749524552504b59ull;
XXHASH_VERIFY(XXH64_update(m_hashState, &wireDomain, sizeof(wireDomain)));
@@ -286,7 +286,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return VK_NULL_HANDLE;
}
m_cache.emplace(hash, PipelineCacheEntry{pipeline, payload.programHash,
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -35,7 +35,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
HashType vertexInputHash = 0;
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
VkRenderPass renderPass = VK_NULL_HANDLE;
#if MOBILEGL_BUILD_DISAGGREGATED
#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;
@@ -3199,7 +3199,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (descriptorKind == DescriptorBindingKind::StorageBuffer) {
const GLuint blockIndex =
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
program.GetShaderStorageBlockIndex(uniformName);
#else
GetShaderStorageBlockIndex(program, uniformName);
@@ -3495,7 +3495,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
updateAfterBindSampledImages + updateAfterBindStorageImages;
const auto& uab = m_updateAfterBindLimits;
entry.usesUpdateAfterBind =
#if MOBILEGL_BUILD_DISAGGREGATED
#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;
@@ -590,7 +590,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
m_bufferManager = bufferManager;
m_programFactory = programFactory;
m_minDynamicOffsetAlignment = std::max<VkDeviceSize>(1, minUniformBufferOffsetAlignment);
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
VkPhysicalDeviceProperties properties{};
vkGetPhysicalDeviceProperties(m_physicalDevice, &properties);
@@ -656,7 +656,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
m_unboundStorageImageTextures.clear();
for (auto& frame : m_frames) {
if (m_device != VK_NULL_HANDLE) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
frame.wireImageViewCache.clear();
for (const auto view : frame.wireImageViews) vkDestroyImageView(m_device, view, nullptr);
frame.wireImageViews.clear();
@@ -683,7 +683,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
frame.quietEpochs = 0;
}
m_frames.clear();
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
for (auto& entry : m_wirePlaceholderImages) DestroyWirePlaceholderImage(entry.second);
m_wirePlaceholderImages.clear();
m_wirePrivateStoragePlaceholders = 0;
@@ -712,7 +712,7 @@ 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
m_wireFrameIndex = frameIndex;
frame.wireImageViewCache.clear();
for (const auto view : frame.wireImageViews) vkDestroyImageView(m_device, view, nullptr);
@@ -766,7 +766,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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;
@@ -907,7 +907,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint32 binding, Uint32 element,
VkDescriptorImageInfo& outImageInfo,
Bool trustUnchangedHint) const {
#if MOBILEGL_BUILD_DISAGGREGATED
#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");
@@ -1192,7 +1192,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Bool UniformManager::ProgramSamplesOnlySingleLevelTextures(
const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj) {
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -1305,7 +1305,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return texture;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
Bool UniformManager::ResolveWireTexelBufferDescriptor(const MagmaProgramSource& program,
const ProgramFactory::VkProgramObject& programObj, Uint32 binding, Uint32 frameIndex,
Bool storage, VkBufferView& out) {
@@ -1413,7 +1413,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const ProgramFactory::VkProgramObject& programObj,
Uint32 binding, Uint32 frameIndex,
VkBufferView& outBufferView) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire())
return ResolveWireTexelBufferDescriptor(program, programObj, binding, frameIndex, false, outBufferView);
#endif
@@ -1541,7 +1541,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const ProgramFactory::VkProgramObject& programObj,
Uint32 binding, Uint32 frameIndex,
VkBufferView& outBufferView) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire())
return ResolveWireTexelBufferDescriptor(program, programObj, binding, frameIndex, true, outBufferView);
#endif
@@ -1712,7 +1712,7 @@ 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire() && (binding >= programObj.storageBlockIndexByBinding.size() ||
binding >= programObj.storageBlockNameByBinding.size()))
WireDescriptorFatal("storage-buffer-reflection-binding");
@@ -1721,7 +1721,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const Int blockIndex = programObj.storageBlockIndexByBinding[binding];
MOBILEGL_ASSERT(blockIndex >= 0, "ResolveStorageBufferDescriptor: no SSBO block mapped to binding %u",
binding);
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -1753,13 +1753,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
isAtomicCounterBlock
? static_cast<GLuint>(atomicCounterBinding)
:
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
(program.IsWire() ? program.GetShaderStorageBlockBinding(static_cast<GLuint>(blockIndex)) :
GetShaderStorageBlockBinding(*program.Frontend(), static_cast<GLuint>(blockIndex))) + element;
#else
GetShaderStorageBlockBinding(program, static_cast<GLuint>(blockIndex)) + element;
#endif
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire()) {
const auto& state = MG_Pipe::MGPipeApplier();
const Uint32 cls = isAtomicCounterBlock ? MG_Pipe::kMGPipeShaderBufferClassAtomicCounter
@@ -1914,7 +1914,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const ProgramFactory::VkProgramObject& programObj,
Uint32 binding, Uint32 element,
VkDescriptorImageInfo& outImageInfo) const {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire()) return ResolveWireImageDescriptor(commandBuffer, program, programObj, binding, element, true, outImageInfo);
#endif
outImageInfo = {};
@@ -2369,7 +2369,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const ProgramFactory::VkProgramObject& programObj,
Vector<MG_State::GLState::ITextureObject*>& outTextures,
Vector<SampledBindingRecord>* outBindingRecords) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire()) { outTextures.clear(); if (outBindingRecords) outBindingRecords->clear(); return true; }
#endif
outTextures.clear();
@@ -2418,7 +2418,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Bool UniformManager::SampledBindingsUnchanged(const MagmaProgramSource& program,
const ProgramFactory::VkProgramObject& programObj,
const Vector<SampledBindingRecord>& previousRecords) const {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire()) return false;
#endif
// A declined program takes the full path every time and is refused there.
@@ -2464,7 +2464,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const MagmaProgramSource& program,
const ProgramFactory::VkProgramObject& programObj,
Vector<MG_State::GLState::ITextureObject*>& outTextures) const {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire()) { outTextures.clear(); return true; }
#endif
outTextures.clear();
@@ -2549,7 +2549,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const MagmaProgramSource& program,
const ProgramFactory::VkProgramObject& programObj,
Vector<SamplerImageFeedbackBinding>& outBindings) const {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire()) { outBindings.clear(); return true; }
#endif
outBindings.clear();
@@ -2752,7 +2752,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
MOBILEGL_ASSERT(binding < programObj.uniformBlockIndexByBinding.size(),
"ResolveUniformBufferPayload: UBO mapping binding %u out of range", binding);
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire() && binding >= programObj.uniformBlockIndexByBinding.size())
WireDescriptorFatal("uniform-buffer-reflection-binding");
#endif
@@ -2776,13 +2776,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
MOBILEGL_ASSERT(static_cast<Uint32>(blockIndex) < activeUniformBlockCount,
"ResolveUniformBufferPayload: uniform block index %d out of range (count=%u)", blockIndex,
activeUniformBlockCount);
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire() && (blockIndex < 0 || static_cast<Uint32>(blockIndex) >= activeUniformBlockCount))
WireDescriptorFatal("uniform-buffer-reflection-block");
#endif
const Uint32 frontendBinding = program.GetUniformBlockBinding(static_cast<Uint32>(blockIndex));
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire())
return ResolveWireUniformBufferPayload(program, static_cast<Uint32>(blockIndex), frontendBinding, out);
#endif
@@ -3059,7 +3059,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint32& outDynamicOffset) {
UboBindResult ubo{};
const Bool hasPayload = ResolveUniformBufferPayload(program, programObj, binding, arrayElement, ubo);
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (program.IsWire() && !hasPayload) return false;
#endif
MOBILEGL_ASSERT(hasPayload && (ubo.directBindable || (ubo.payload != nullptr && ubo.payloadSize > 0)),
@@ -56,7 +56,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void Shutdown();
void BeginFrame(Uint32 frameIndex);
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -123,7 +123,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Vector<SamplerImageFeedbackBinding>& outBindings) const;
static Bool SamplerOverlapsWritableImageSubresource(Int samplerBaseLevel, Int samplerMaxLevel,
GLint imageLevel, GLenum imageAccess);
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -283,7 +283,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Vector<DescriptorPoolBucket> descriptorPools;
UnorderedMap<VkDescriptorSetLayout, DescriptorSetCacheEntry> descriptorSetCacheByLayout;
Vector<VkBufferView> texelBufferViews;
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
mutable Vector<VkImageView> wireImageViews;
// Own views in the vector above until this slot's fence/idle proof.
// Cache hits preserve the handle, enabling descriptor-content reuse.
@@ -366,7 +366,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const ProgramFactory::VkProgramObject& programObj, Uint32 binding,
Uint32 element, VkDescriptorImageInfo& outImageInfo,
Bool trustUnchangedHint = false) const;
#if MOBILEGL_BUILD_DISAGGREGATED
#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;
@@ -415,7 +415,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const void* payload = nullptr; // fallback UploadTransient path
VkDeviceSize payloadSize = 0;
};
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
Bool ResolveWireUniformBufferPayload(const MagmaProgramSource& program, Uint32 blockIndex,
Uint32 bindingPoint, UboBindResult& out) const;
#endif
@@ -801,7 +801,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (m_physicalDevice == VK_NULL_HANDLE || format == VK_FORMAT_UNDEFINED) {
return false;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
const auto found = m_wireVertexFormatSupport.find(format);
if (found != m_wireVertexFormatSupport.end()) return found->second;
@@ -10,7 +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 <MG_Pipe/MGPipeHandles.h>
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
#include <MG_Pipe/PipeApply.h>
#endif
@@ -122,7 +122,7 @@ 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_DISAGGREGATED
#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,
@@ -175,7 +175,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const VulkanRendererConfig& m_config;
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
#if MOBILEGL_BUILD_DISAGGREGATED
#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<VkFormat, Bool> m_wireVertexFormatSupport;
@@ -29,7 +29,7 @@
namespace MobileGL::MG_Backend::DirectVulkan {
namespace {
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -181,7 +181,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
.ReadbackFromGpu = Ops_ReadbackFromGpu,
};
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -1227,7 +1227,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
g_activeBufferManager.Get() = this;
MG_State::GLState::SetBufferBackendOps(&g_vulkanBufferBackendOps);
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
RegisterWireResourceOps();
#endif
return true;
@@ -1293,7 +1293,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
"VkBufferManager::BeginFrame frame index out of range");
m_currentFrameIndex = frameIndex;
++m_frameSerial;
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (WireBufProbeEnabled()) {
MGLOG_I("WBUF BEGINFRAME idx=%u newSerial=%llu floor=%llu (arena slot rewound)", frameIndex,
static_cast<unsigned long long>(m_frameSerial),
@@ -1399,7 +1399,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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
(MG_Config::DataArmIsRecord() ? VkBufferUsageFlags{VK_BUFFER_USAGE_TRANSFER_DST_BIT} : 0u) |
#endif
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
@@ -1557,7 +1557,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return true;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
Bool VkBufferManager::StagedWireRangeCopy(WireBufferResource& resource, const void* data,
SizeT offset, SizeT size) {
if (!m_copyProvider) {
@@ -1987,7 +1987,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
"VkBufferManager::CollectDeferredReleases frame index out of range");
m_deferredBufferReleases[frameIndex].clear();
m_deferredResourceReleases[frameIndex].clear();
#if MOBILEGL_BUILD_DISAGGREGATED
#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).
@@ -2088,7 +2088,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
void VkBufferManager::DestroyAllDeferredReleases() {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
// Both callers (Shutdown, RecreateTransientArenas) have proven the device idle.
DestroyAllDeferredWireReleases();
#endif
@@ -13,7 +13,7 @@
#include "../VkIncludes.h"
#include <Includes.h>
#include <vk_mem_alloc.h>
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
#include "MG_Pipe/MGPipeTypes.h"
#include <unordered_map>
#endif
@@ -103,7 +103,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Bool Initialize(const VkBufferManagerInitInfo& initInfo);
void Shutdown();
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -254,7 +254,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void DeferRelease(VkBufferObject&& buffer);
private:
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
struct WireBufferResource {
VkBufferObject buffer;
Uint64 size = 0;
@@ -387,7 +387,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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
Bool StagedWireRangeCopy(WireBufferResource& resource, const void* data, SizeT offset, SizeT size);
#endif
void CollectDeferredReleases(Uint32 frameIndex);
@@ -44,7 +44,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
m_allocation = other.m_allocation;
m_mappedData = other.m_mappedData;
m_size = other.m_size;
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
MoveExternalFrom(other);
#endif
@@ -67,7 +67,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
m_allocation = other.m_allocation;
m_mappedData = other.m_mappedData;
m_size = other.m_size;
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
MoveExternalFrom(other);
#endif
@@ -170,7 +170,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
void VkBufferObject::Unmap() {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
// An imported store stays mapped for its life (Destroy unmaps it).
if (m_externalMemory != VK_NULL_HANDLE) return;
#endif
@@ -200,7 +200,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
Memcpy(static_cast<Uint8*>(mapped) + offset, data, static_cast<SizeT>(size));
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (m_externalMemory != VK_NULL_HANDLE) {
if (m_externalCoherent) return true;
VkMappedMemoryRange range{VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE};
@@ -234,7 +234,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (resolvedSize == 0) {
return true;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (m_externalMemory != VK_NULL_HANDLE) {
if (m_externalCoherent) return true;
VkMappedMemoryRange range{VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE};
@@ -65,13 +65,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void* GetMappedData() const { return m_mappedData; }
Bool IsMapped() const { return m_mappedData != nullptr; }
Bool IsValid() const {
#if MOBILEGL_BUILD_DISAGGREGATED
#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_DISAGGREGATED
#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
@@ -15,7 +15,7 @@
namespace MobileGL::MG_Backend::DirectVulkan {
namespace {
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -221,7 +221,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return std::fabs(lhs - rhs) <= 1e-6f;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
template <class SamplerSource>
Float ResolveEffectiveMaxLod(const SamplerSource& sampler) {
#else
@@ -233,7 +233,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return sampler.GetMaxLod();
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
template <class SamplerSource>
Float ResolveEffectiveMinLod(const SamplerSource& sampler, Float effectiveMaxLod) {
#else
@@ -249,7 +249,7 @@ 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
template <class SamplerSource>
Float ResolveSingleLevelMaxLod(const SamplerSource& sampler, Bool singleLevelView) {
#else
@@ -275,7 +275,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return true;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
template <class SamplerSource>
Float VkSamplerManager::ResolveEffectiveMaxAnisotropy(const SamplerSource& sampler,
#else
@@ -339,7 +339,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
template <class SamplerSource>
Uint64 VkSamplerManager::BuildSamplerKey(const SamplerSource& sampler,
#else
@@ -390,7 +390,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return XXH64_digest(m_hashState);
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
template <class SamplerSource>
VkSampler VkSamplerManager::GetOrCreateSamplerImpl(const SamplerSource& sampler,
TextureInternalFormat format,
@@ -409,7 +409,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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
const ResolvedBorderColor borderColor = ResolveBorderColor(sampler, format);
#else
const ResolvedBorderColor borderColor = ResolveBorderColor(sampler, texture);
@@ -473,7 +473,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return vkSampler;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
VkSampler VkSamplerManager::GetOrCreateSampler(const MG_State::GLState::SamplerObject& sampler,
const MG_State::GLState::ITextureObject& texture,
Bool forceNearestFiltering, Uint32 viewLevelCount) {
@@ -542,7 +542,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
template <class SamplerSource>
VkSamplerManager::ResolvedBorderColor VkSamplerManager::ResolveBorderColor(
const SamplerSource& sampler, TextureInternalFormat format) const {
@@ -557,7 +557,7 @@ 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_DISAGGREGATED
#if !MOBILEGL_BUILD_RECORD_ARM
const auto format = texture.GetFormat();
#endif
const auto domain = ResolveBorderColorDomain(format);
@@ -46,7 +46,7 @@ public:
const MG_State::GLState::ITextureObject& texture,
Bool forceNearestFiltering = false,
Uint32 viewLevelCount = 0);
#if MOBILEGL_BUILD_DISAGGREGATED
#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,
@@ -92,7 +92,7 @@ private:
Bool usesCustomBorderColor = false;
};
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
template <class SamplerSource>
VkSampler GetOrCreateSamplerImpl(const SamplerSource& sampler, TextureInternalFormat format,
Bool forceNearestFiltering, Uint32 viewLevelCount);
@@ -106,7 +106,7 @@ private:
static VkSamplerMipmapMode ToVkMipmapMode(SamplerMipmapMode mode);
static VkSamplerAddressMode ToVkAddressMode(SamplerWrapMode mode);
static VkCompareOp ToVkCompareOp(SamplerCompareFunc func);
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
template <class SamplerSource>
ResolvedBorderColor ResolveBorderColor(const SamplerSource& sampler, TextureInternalFormat format) const;
#else
@@ -117,7 +117,7 @@ private:
// 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
template <class SamplerSource>
Float ResolveEffectiveMaxAnisotropy(const SamplerSource& sampler,
#else
@@ -317,7 +317,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkQueue graphicsQueue,
const VkTextureManager::TextureResource& oldResource,
VkTextureManager::TextureResource& newResource
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
, Bool splitAspects = false
#endif
) {
@@ -378,7 +378,7 @@ 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (splitAspects) {
for (const VkImageAspectFlags aspect : {VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_ASPECT_DEPTH_BIT,
@@ -721,7 +721,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
DestroyDeferredReleases();
++m_resourceEraseEpoch; // every memoized resource pointer dies with the map
m_textureResources.clear();
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
// Destroy images while the device/allocator still exist, including after context death.
m_wireTextureResources.clear();
m_wireRenderbufferResources.clear();
@@ -3820,7 +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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
&& resource.yuvSource == nullptr
#endif
) {
@@ -3994,7 +3994,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return current->mapped + alignedCursor;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -19,7 +19,7 @@
#include <unordered_set>
#include <Config.h>
#if MOBILEGL_BUILD_DISAGGREGATED
#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 <MG_Pipe/MGPipeHandles.h>
@@ -28,7 +28,7 @@
namespace MobileGL::MG_State::GLState {
class ITextureObject;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
namespace MobileGL::MG_Pipe {
struct MGPipeResourceRecord;
}
@@ -355,7 +355,7 @@ 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_DISAGGREGATED
#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
@@ -415,7 +415,7 @@ public:
std::swap(this->syncedContentVersion, that.syncedContentVersion);
std::swap(this->syncedMipLevelCount, that.syncedMipLevelCount);
std::swap(this->syncedShapeVersion, that.syncedShapeVersion);
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
std::swap(this->syncedWireSerial, that.syncedWireSerial);
std::swap(this->importedMemory, that.importedMemory);
std::swap(this->sharedImageId, that.sharedImageId);
@@ -466,7 +466,7 @@ public:
if (image != VK_NULL_HANDLE && allocation != nullptr) {
vmaDestroyImage(s_allocator.Get(), image, allocation);
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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);
@@ -510,7 +510,7 @@ public:
syncedContentVersion = 0;
syncedMipLevelCount = 0;
syncedShapeVersion = 0;
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
syncedWireSerial = 0;
#endif
}
@@ -539,7 +539,7 @@ public:
// preserve-on-recreate copy are the existing callers. No-op when the
// batch is empty.
void FlushPendingUploads();
#if MOBILEGL_BUILD_DISAGGREGATED
#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();
@@ -1482,7 +1482,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
namespace {
static constexpr Uint32 kDescriptorSetsPerFrame = 64;
#if !MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -1571,7 +1571,7 @@ void main() {
gl_FragDepth = 0.25 * (depth0 + depth1 + depth2 + depth3);
}
)";
#endif // !MOBILEGL_BUILD_DISAGGREGATED
#endif // !MOBILEGL_BUILD_RECORD_ARM
static Uint32 ComputeFullMipLevelCount(const IntVec3& baseTexelSize) {
@@ -3219,7 +3219,7 @@ void main() {
inline ProgramFactory::CompileOptionFlags GetShaderTransformFlags(VkSurfaceTransformFlagBitsKHR preTransform) {
ProgramFactory::CompileOptionFlags flags = ProgramFactory::CompileOptionBit::PositionZRemap;
#if MOBILEGL_BUILD_DISAGGREGATED
#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_State::GLState::FramebufferObject>{} :
@@ -3270,7 +3270,7 @@ void main() {
CreateAllocator();
CreateCommandPool();
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
m_progressMarkers.Init(m_device, m_physicalDevice.queueFamilies.graphicsFamily);
#endif
@@ -3445,7 +3445,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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
m_uniformManager->SetWireInvalidStorageImageArm(m_wireNullDescriptor);
#endif
m_vertexInputStateFactory =
@@ -3498,7 +3498,7 @@ void main() {
if (m_device != VK_NULL_HANDLE) {
VK_VERIFY(vkDeviceWaitIdle(m_device));
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
m_progressMarkers.Shutdown();
#endif
// Parked surface targets (ActivateSurfaceTarget) go before the device and instance.
@@ -3616,7 +3616,7 @@ void main() {
m_device = VK_NULL_HANDLE;
}
s_vkCmdDrawIndexedIndirectCount = nullptr;
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
s_vkCmdWireDrawIndirectCount = nullptr;
#endif
s_vkCmdDrawMultiEXT = nullptr;
@@ -4595,7 +4595,7 @@ void main() {
}
Bool VulkanRenderer::InitializeBlitResources() {
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -4707,7 +4707,7 @@ void main() {
}
Bool VulkanRenderer::InitializeDepthMipmapResources() {
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -4834,7 +4834,7 @@ void main() {
m_deferredDepthMipmapCleanup.clear();
}
#if !MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -4893,7 +4893,7 @@ void main() {
}
return m_pipelineFactory->GetOrCreatePipeline(payload);
}
#endif // !MOBILEGL_BUILD_DISAGGREGATED
#endif // !MOBILEGL_BUILD_RECORD_ARM
Bool VulkanRenderer::GenerateDepthMipmapWithShader(FrameContext::FrameData& frame,
MG_State::GLState::ITextureObject& texture,
@@ -4903,7 +4903,7 @@ void main() {
const IntVec3& storageBaseTexelSize,
VkImageLayout originalLayout,
VkImageLayout finalLayout) {
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -5356,7 +5356,7 @@ void main() {
return rsp.PrimitiveRestartIndex <= MG_Util::FixedRestartIndexForGLType(pIndexBufferView->indexType);
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -5380,7 +5380,7 @@ void main() {
const MG_State::GLState::VertexArrayObject& vao,
const RenderPassEntry& renderPassEntry,
Bool primitiveRestartEnable) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
return GetOrCreatePipelineWithInput(mode, program, programObj, transformFlags,
m_vertexInputStateFactory->GetOrCreateVertexInputState(vao), renderPassEntry, primitiveRestartEnable);
}
@@ -5407,12 +5407,12 @@ 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_DISAGGREGATED
#if !MOBILEGL_BUILD_RECORD_ARM
auto& vis = m_vertexInputStateFactory->GetOrCreateVertexInputState(vao);
#endif
const Uint64 vertexLayoutHash = vis.layoutHash;
const Uint64 renderPassHash =
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
wireRenderPassCompatibilityId != 0 ? 0 :
#endif
renderPassEntry.hash;
@@ -5442,7 +5442,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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
entry.wireRenderPassCompatibilityId == wireRenderPassCompatibilityId &&
#endif
entry.pipelineStateHash == pipelineStateHash &&
@@ -5631,7 +5631,7 @@ 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
const auto* fbo = MG_Pipe::MGPipeApplier().DrawFramebuffer();
if (fbo && !fbo->IsDefault) {
@@ -5736,7 +5736,7 @@ void main() {
.vertexInputHash = vertexLayoutHash,
.pipelineLayout = programObj.pipelineLayout,
.renderPass = renderPassEntry.renderPass,
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
.wireRenderPassCompatibilityId = wireRenderPassCompatibilityId,
#endif
.colorAttachmentCount = renderPassEntry.colorAttachmentCount,
@@ -5865,7 +5865,7 @@ void main() {
MOBILEGL_ASSERT(payload.colorAttachmentCount <= PipelineFactory::PipelineCreatePayload::kMaxColorAttachments,
"GetOrCreatePipeline: colorAttachmentCount=%u exceeds payload capacity",
payload.colorAttachmentCount);
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
const auto* wireFbo = MG_Config::DataArmIsRecord() ?
MG_Pipe::MGPipeApplier().DrawFramebuffer() : nullptr;
const auto drawFboBinding = wireFbo ? SharedPtr<MG_State::GLState::FramebufferObject>{} :
@@ -5874,12 +5874,12 @@ void main() {
const auto& drawFboBinding =
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
#endif
#if MOBILEGL_BUILD_DISAGGREGATED
#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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
const Bool isDefaultDrawFbo = wireFbo ? wireFbo->IsDefault : drawFboBinding->IsDefaultFramebuffer();
Array<FramebufferAttachmentType, MG_Pipe::kMGPipeMaxColorAttachments> wireDrawBuffers{};
if (wireFbo) for (SizeT i = 0; i < wireDrawBuffers.size(); ++i)
@@ -5891,7 +5891,7 @@ void main() {
const auto& drawBuffers = drawFboBinding->GetDrawBuffers();
#endif
auto resolveCompleteColorAttachmentTexture = [&](Uint32 drawBufferIndex) -> MG_State::GLState::ITextureObject* {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (wireFbo) return nullptr;
#endif
if (isDefaultDrawFbo || drawBufferIndex >= drawBuffers.size()) {
@@ -5944,7 +5944,7 @@ void main() {
attachmentColorWriteMask = 0;
effectiveBlendEnabled = false;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (wireFbo && !isDefaultDrawFbo) {
const Int32 slot = wireFbo->DrawBuffers[i];
if (slot < 0 || wireFbo->Color[slot].Kind == MG_Pipe::kMGPipeSurfaceKindNone) {
@@ -6048,7 +6048,7 @@ void main() {
VkFormat colorAttachmentFormat = VK_FORMAT_UNDEFINED;
Int textureExternalIndex = -1;
#if MOBILEGL_BUILD_DISAGGREGATED
#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;
@@ -6182,7 +6182,7 @@ void main() {
entry.programHash = programObj.hash;
entry.vertexInputHash = vertexLayoutHash;
entry.renderPassHash = renderPassHash;
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
entry.wireRenderPassCompatibilityId = wireRenderPassCompatibilityId;
#endif
entry.pipelineStateHash = pipelineStateHash;
@@ -6550,7 +6550,7 @@ void main() {
// the SAME draw-framebuffer binding the draw uses - see the assert below.
MOBILEGL_ASSERT(
[&] {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
const auto* fbo = MG_Pipe::MGPipeApplier().DrawFramebuffer();
return isDefaultFbo == (fbo != nullptr && fbo->IsDefault);
@@ -6896,7 +6896,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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
entry.wireRenderPassCompatibilityId == 0 &&
#endif
entry.pipelineStateHash == pipelineStateHash &&
@@ -6983,7 +6983,7 @@ 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
if (!RewindWireDescriptorSetsIfDue()) return false;
// The wire route returns before the monolith branch's draw-gated
@@ -7618,7 +7618,7 @@ void main() {
void VulkanRenderer::DispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) {
// Before the wire branch, for SetupDraw's reason.
SplitOversizedRecording();
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
if (!RewindWireDescriptorSetsIfDue()) return;
m_textureManager->CollectGarbage();
@@ -7683,7 +7683,7 @@ void main() {
void VulkanRenderer::DispatchComputeIndirect(GLintptr indirect) {
SplitOversizedRecording();
#if MOBILEGL_BUILD_DISAGGREGATED
#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;
@@ -7794,7 +7794,7 @@ void main() {
MGLOG_D("DirectVulkan: glMemoryBarrier(0x%x)", static_cast<Uint32>(barriers));
vkCmdPipelineBarrier(frame.commandBuffer,
#if MOBILEGL_BUILD_DISAGGREGATED
#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()
@@ -7962,7 +7962,7 @@ void main() {
#include "WireYuvImage.inc"
void VulkanRenderer::Clear(GLbitfield mask) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
const auto* fbo = MG_Pipe::MGPipeApplier().DrawFramebuffer();
if (!fbo) MagmaWireFatal("clear-framebuffer-record");
@@ -8366,7 +8366,7 @@ void main() {
void VulkanRenderer::QueueClearBufferPayload(GLenum buffer, GLint drawbuffer,
const ClearAttachmentPayload& clearPayload) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
const auto* fbo = MG_Pipe::MGPipeApplier().DrawFramebuffer();
if (!fbo) MagmaWireFatal("clear-buffer-framebuffer-record");
@@ -9290,7 +9290,7 @@ void main() {
MOBILEGL_ASSERT(clearReady,
"TryBlitToDefaultFramebufferWithShader: failed to materialize pending clear for textureId=%d",
sourceTexture->GetExternalIndex());
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -9505,7 +9505,7 @@ 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
BlitWireFramebuffers(srcX0,srcY0,srcX1,srcY1,dstX0,dstY0,dstX1,dstY1,mask,filter);
return;
@@ -10147,7 +10147,7 @@ void main() {
void VulkanRenderer::CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLint x, GLint y, GLsizei width, GLsizei height) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
CopyWireFramebufferToTexture(target,level,xoffset,yoffset,x,y,width,height);
return;
@@ -10466,7 +10466,7 @@ void main() {
}
Uint CopyImageEndpointName(const CopyImageEndpoint& endpoint) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord())
return endpoint.IsRenderbuffer() ? endpoint.RenderbufferHandle.Slot : endpoint.TextureHandle.Slot;
#endif
@@ -10480,7 +10480,7 @@ void main() {
const CopyImageEndpoint& dstEndpoint,
GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ,
GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
const Bool wire = MG_Config::DataArmIsRecord();
MG_Pipe::MGPipeHandle dstStorageHandle = dstEndpoint.TextureHandle;
if (wire && HasPendingRecordedWork() && !FlushPendingCommands()) {
@@ -10515,7 +10515,7 @@ void main() {
const auto* dstStorageTexture =
dstEndpoint.Texture ? &VkTextureManager::StorageTextureOf(*dstEndpoint.Texture) : nullptr;
if (
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
!wire &&
#endif
srcStorageTexture == dstStorageTexture && srcEndpoint.Renderbuffer == dstEndpoint.Renderbuffer) {
@@ -10528,7 +10528,7 @@ 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_DISAGGREGATED
#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.
@@ -10582,7 +10582,7 @@ void main() {
CopyImageVkImage dstImage{};
const Bool srcResolved = resolveImage(srcEndpoint, srcImage);
const Bool dstResolved = resolveImage(dstEndpoint, dstImage);
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -10626,7 +10626,7 @@ 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (wire) {
const auto mapSubresource = [this](const CopyImageEndpoint& endpoint, GLint& mip, GLint& layer) {
if (endpoint.IsRenderbuffer()) {
@@ -10746,7 +10746,7 @@ void main() {
__func__, srcZ, srcSlices.availableSlices, dstZ, dstSlices.availableSlices, srcDepth);
return;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -10786,7 +10786,7 @@ void main() {
}
const auto materializeClear = [this, &frame](const CopyImageEndpoint& endpoint) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) return true;
#endif
if (endpoint.IsRenderbuffer()) {
@@ -10919,7 +10919,7 @@ void main() {
srcImage.image, copySourceLayout,
dstImage.image, copyDestinationLayout,
1, &copyRegion);
#if MOBILEGL_BUILD_DISAGGREGATED
#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,
@@ -11021,7 +11021,7 @@ 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
Vector<VkFence> readbackFences;
readbackFences.reserve(m_inFlightSubmits.size() + 1);
for (const auto& record : m_inFlightSubmits) {
@@ -11066,7 +11066,7 @@ void main() {
void VulkanRenderer::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
void* pixels) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
ReadWirePixels(x,y,width,height,format,type,pixels);
return;
@@ -11764,11 +11764,11 @@ void main() {
const SizeT dstPixelBytes = packed.size() / pixelCount;
// Store honoring the client pack state (single slice).
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
const SharedPtr<MG_State::GLState::BufferObject> wireReplyHasNoPackBuffer;
#endif
const auto& pixelPackBufferObject =
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
MG_Config::DataArmIsRecord() ? wireReplyHasNoPackBuffer :
#endif
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
@@ -12046,7 +12046,7 @@ void main() {
}
void VulkanRenderer::GenerateMipmap(GLenum target) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
GenerateWireMipmap();
return;
@@ -12151,7 +12151,7 @@ void main() {
"GenerateMipmap: depth-stencil mipmap generation is not supported yet.");
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -12451,7 +12451,7 @@ void main() {
"undefined behaviour rather than a capture");
return false;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord())
return BeginWireXfbCaptureForDraw(frame);
#endif
@@ -13574,13 +13574,13 @@ void main() {
return false;
}
if (m_device == VK_NULL_HANDLE || m_graphicsQueue == VK_NULL_HANDLE) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
return IsFrameSerialComplete(serial);
#else
return true;
#endif
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -13628,7 +13628,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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
return IsFrameSerialComplete(serial);
#else
return true;
@@ -13646,7 +13646,7 @@ void main() {
return false;
}
const auto& frame = m_frameContext.GetCurrent();
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
return frame.isCommandRecording || frame.hasCommandBufferRecorded ||
frame.isPreCommandRecording || frame.hasPreCommandBufferRecorded;
#else
@@ -13654,7 +13654,7 @@ void main() {
#endif
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
Bool VulkanRenderer::RewindWireDescriptorSetsIfDue() {
if (!m_uniformManager || m_frameContext.GetFrameCount() == 0) return true;
const Uint32 frameIndex = m_frameContext.GetCurrentFrameIndex();
@@ -13723,7 +13723,7 @@ void main() {
}
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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;
@@ -13745,7 +13745,7 @@ void main() {
void VulkanRenderer::OnSubmitsCompletedUpTo(Uint64 submitIndex) {
m_completedSubmitCounter = std::max(m_completedSubmitCounter, submitIndex);
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -13776,7 +13776,7 @@ void main() {
while (!m_inFlightSubmits.empty() && m_inFlightSubmits.front().submitIndex <= submitIndex) {
SubmitRecord record = m_inFlightSubmits.front();
m_inFlightSubmits.erase(m_inFlightSubmits.begin());
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
retiredAny = true;
advanceTo = std::max(advanceTo, record.frameSerial);
#else
@@ -13794,7 +13794,7 @@ void main() {
vkDestroyFence(m_device, record.fence, nullptr);
}
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (retiredAny) {
// Clamp to one below the lowest serial still in flight.
for (const auto& remaining : m_inFlightSubmits) {
@@ -13848,7 +13848,7 @@ void main() {
}
Bool VulkanRenderer::TryDrainFrameTransients() {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (m_wirePreparationDepth != 0) return false;
#endif
if (m_device == VK_NULL_HANDLE || m_frameContext.GetFrameCount() == 0) {
@@ -13864,7 +13864,7 @@ void main() {
return false;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -13908,7 +13908,7 @@ 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_DISAGGREGATED
#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
@@ -13997,7 +13997,7 @@ void main() {
}
Bool VulkanRenderer::SubmitPendingCommandBuffer(FrameContext::FrameData& frame, VkFence fence, Bool pooledFence) {
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
RetireWireDrawPass();
#endif
// Batched texture uploads must reach the queue before the frame's
@@ -14063,7 +14063,7 @@ void main() {
// pooled fences and mid-frame command buffers.
RefreshCompletedSubmits();
auto& frame = m_frameContext.GetCurrent();
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (!frame.isCommandRecording && !frame.hasCommandBufferRecorded &&
!frame.isPreCommandRecording && !frame.hasPreCommandBufferRecorded) {
#else
@@ -14111,7 +14111,7 @@ 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_DISAGGREGATED
#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) {
@@ -14270,7 +14270,7 @@ void main() {
return false;
}
}
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (!WaitForSubmitsUpTo(submitIndex, timeoutNs)) return false;
// A blocking wait can drain a present-less loop's frame transients.
TryDrainFrameTransients();
@@ -14453,7 +14453,7 @@ void main() {
return;
}
m_presentSuspended = false;
#if MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -14552,7 +14552,7 @@ void main() {
const VkResult presentSubmit = vkQueueSubmit(m_graphicsQueue, 1, &submitPacket.submitInfo, frame.imageInFlightFence);
#endif
NoteDeviceLoss(presentSubmit, "Present vkQueueSubmit");
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (presentSubmit != VK_SUCCESS && LatchWireDeviceLoss("present-submit")) return;
#endif
VK_VERIFY(presentSubmit);
@@ -14592,7 +14592,7 @@ void main() {
result = VK_SUCCESS;
}
NoteDeviceLoss(result, "vkQueuePresentKHR");
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (result != VK_SUCCESS && LatchWireDeviceLoss("present-queue")) return;
#endif
VK_VERIFY(result, "Present, vkQueuePresentKHR");
@@ -14644,7 +14644,7 @@ void main() {
// 3) Advance frame slot.
m_frameContext.AdvanceToNext();
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -14680,7 +14680,7 @@ void main() {
m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired);
}
NoteDeviceLoss(result, "vkAcquireNextImageKHR");
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
if (result != VK_SUCCESS && LatchWireDeviceLoss("present-acquire")) return;
#endif
VK_VERIFY(result, "Present, vkAcquireNextImageKHR");
@@ -14689,7 +14689,7 @@ void main() {
// before FrameContext reset the slot fence; this repeat is idempotent.
OnSubmitsCompletedUpTo(m_frameContext.GetCurrent().lastSubmitIndex);
CollectDeferredDepthMipmapCleanup(m_frameContext.GetCurrentFrameIndex());
#if MOBILEGL_BUILD_DISAGGREGATED
#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());
@@ -15355,7 +15355,7 @@ void main() {
getPhysicalDeviceProperties2 = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2>(
vkGetInstanceProcAddr(m_instance, "vkGetPhysicalDeviceProperties2KHR"));
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -15879,7 +15879,7 @@ void main() {
}
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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;
@@ -15948,7 +15948,7 @@ void main() {
}
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -16061,7 +16061,7 @@ 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_DISAGGREGATED
#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<PFNDrawIndexedIndirectCountFunc>(
@@ -16191,13 +16191,13 @@ 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_DISAGGREGATED
#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_DISAGGREGATED
#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
@@ -16822,7 +16822,7 @@ void main() {
vkDeviceWaitIdle(m_device);
OnSubmitsCompletedUpTo(m_submitCounter);
#if MOBILEGL_BUILD_DISAGGREGATED
#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();
@@ -17094,7 +17094,7 @@ void main() {
FlushPendingCommands();
VK_VERIFY(vkDeviceWaitIdle(m_device));
OnSubmitsCompletedUpTo(m_submitCounter);
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
DestroyWireDrawPass();
CollectWireObjects(m_submitCounter, true);
ClearAllWireDrawPassCaches();
@@ -17147,7 +17147,7 @@ void main() {
return m_instance;
}
#if MOBILEGL_BUILD_DISAGGREGATED
#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;
@@ -286,7 +286,7 @@ 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_DISAGGREGATED
#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<Uint8>& ownedBytes);
@@ -400,7 +400,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// loss here is this session's alone.
void NoteDeviceLoss(VkResult result, const char* where);
Bool IsDeviceLost();
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -571,7 +571,7 @@ 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_DISAGGREGATED
#if !MOBILEGL_BUILD_RECORD_ARM
SharedPtr<MG_State::GLState::ProgramObject> program;
SharedPtr<MG_State::GLState::SamplerObject> nearestSampler;
SharedPtr<MG_State::GLState::SamplerObject> linearSampler;
@@ -583,7 +583,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
};
struct DepthMipmapResources {
#if !MOBILEGL_BUILD_DISAGGREGATED
#if !MOBILEGL_BUILD_RECORD_ARM
SharedPtr<MG_State::GLState::ProgramObject> program;
Int srcRectLocation = -1;
Int dstRectLocation = -1;
@@ -960,7 +960,7 @@ 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_DISAGGREGATED
#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);
@@ -1148,7 +1148,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkDeviceSize countBufferOffset, Uint32 maxDrawCount,
Uint32 stride);
PFNDrawIndexedIndirectCountFunc s_vkCmdDrawIndexedIndirectCount = nullptr;
#if MOBILEGL_BUILD_DISAGGREGATED
#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).
@@ -1221,7 +1221,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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
Bool BeginWireXfbCaptureForDraw(FrameContext::FrameData& frame);
#endif
Uint32 m_currentDrawXfbBufferCount = 0;
@@ -1371,7 +1371,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint64 programHash = 0;
Uint64 vertexInputHash = 0;
Uint64 renderPassHash = 0;
#if MOBILEGL_BUILD_DISAGGREGATED
#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
@@ -2146,7 +2146,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Bool MaterializePendingDepthStencilClearForDefaultFramebuffer(
VkCommandBuffer commandBuffer, const MG_State::GLState::FramebufferAttachmentObject& attachment,
const ClearAttachmentPayload& payload);
#if !MOBILEGL_BUILD_DISAGGREGATED
#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.
@@ -1,6 +1,6 @@
// 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
#include "WireColorBlitSpirv.h"
struct VulkanRenderer::WireColorBlitResources {
@@ -35,7 +35,7 @@
// 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
namespace MobileGL::MG_Backend::DirectVulkan {
// A glBlitFramebuffer rectangle as GL names it: two corners, either order.
struct WireBlitRect {
@@ -9,7 +9,7 @@
#pragma once
#include <Config.h>
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
#include <Includes.h>
#include <MG_Util/Debug/Log.h>
@@ -169,4 +169,4 @@ private:
} // namespace MobileGL::MG_Backend::DirectVulkan
#endif // MOBILEGL_BUILD_DISAGGREGATED
#endif // MOBILEGL_BUILD_RECORD_ARM
@@ -15,7 +15,7 @@
// 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
#include "WireDepthMipmapSpirv.h"
struct VulkanRenderer::WireDepthMipmapResources {
@@ -21,7 +21,7 @@
#include <cstring>
#include <vulkan/vulkan_core.h>
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
namespace MobileGL::MG_Backend::DirectVulkan {
#include "WireMultisampleResolveSpirv.h"
@@ -27,7 +27,7 @@
//
// Disaggregated builds only: the monolith never records either arm, and the pull build's image
// must not change (P7 gate G1).
#if MOBILEGL_BUILD_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
namespace MobileGL::MG_Backend::DirectVulkan {
// Every aspect a wire depth/stencil format has.
VkImageAspectFlags WireDepthStencilFormatAspects(VkFormat format);
@@ -15,7 +15,7 @@
// 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_DISAGGREGATED
#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.
@@ -1,6 +1,6 @@
// 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_DISAGGREGATED
#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);
@@ -12,7 +12,7 @@
// 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
#include <MG_Pipe/MGPipeTypes.h>
namespace MobileGL::MG_Backend::DirectVulkan {
@@ -2,7 +2,7 @@
#include <Includes.h>
#include "../VkIncludes.h"
#if MOBILEGL_BUILD_DISAGGREGATED
#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,
@@ -1,6 +1,6 @@
// 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_DISAGGREGATED
#if MOBILEGL_BUILD_RECORD_ARM
static Bool PackWireColorTight(const Uint8* source, SizeT sourceBytes, VkFormat format,
TextureInternalFormat logicalFormat, const MG_Pipe::MGPReadbackInfo& info,
Vector<Uint8>& result) {