From 6a138a5221df5f29a7835673c220f11b33da7d03 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sat, 19 Sep 2026 22:40:04 -0400 Subject: [PATCH] [MG_Backend] (Disaggregated): P5f fm - fence remaining buffer debt and preserve native transfer layouts --- .../MG_Backend/DirectVulkan/DirectVulkan.cpp | 37 +++++++++++++++++++ .../DirectVulkan/Renderer/VulkanRenderer.cpp | 8 +++- .../DirectVulkan/Renderer/VulkanRenderer.h | 2 +- .../DirectVulkan/Renderer/WireDraw.inc | 20 +++++++--- .../DirectVulkan/Renderer/WireFramebuffer.inc | 36 ++++++++++++++---- MobileGL/MG_IntegrationTest/CMakeLists.txt | 2 +- 6 files changed, 90 insertions(+), 15 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp index 41d3d554..eb2a2fe3 100644 --- a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp @@ -32,6 +32,16 @@ namespace MobileGL::MG_Backend::DirectVulkan { UniquePtr& pVulkanRenderer = *new UniquePtr(); namespace { +#if MOBILEGL_BUILD_DISAGGREGATED + void RejectWireLegacyBuffer() { + if (MG_Config::Transport != MG_Config::TransportMode::Monolith) { + 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 @@ -391,11 +401,17 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride) { +#if MOBILEGL_BUILD_DISAGGREGATED + RejectWireLegacyBuffer(); +#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElementsIndirect called with null VulkanRenderer"); MOBILEGL_ASSERT(MGB_CTX_LIVE, "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_DISAGGREGATED + RejectWireLegacyBuffer(); +#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawArraysIndirect called with null VulkanRenderer"); MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::MultiDrawArraysIndirect called with null GL context"); @@ -447,12 +463,18 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void MultiDrawElementsIndirectCount(GLenum mode, GLenum type, const void* indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride) { +#if MOBILEGL_BUILD_DISAGGREGATED + RejectWireLegacyBuffer(); +#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElementsIndirectCount called with null VulkanRenderer"); MOBILEGL_ASSERT(MGB_CTX_LIVE, "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_DISAGGREGATED + RejectWireLegacyBuffer(); +#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawArraysIndirectCount called with null VulkanRenderer"); MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::MultiDrawArraysIndirectCount called with null GL context"); @@ -525,6 +547,9 @@ 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 + RejectWireLegacyBuffer(); +#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElementsIndirect called with null VulkanRenderer"); MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::DrawElementsIndirect called with null GL context"); @@ -584,6 +609,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { DrawArraysInstancedBaseInstance(mode, first, count, instancecount, 0); } void DrawArraysIndirect(GLenum mode, const void* indirect) { +#if MOBILEGL_BUILD_DISAGGREGATED + RejectWireLegacyBuffer(); +#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArraysIndirect called with null VulkanRenderer"); MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::DrawArraysIndirect called with null GL context"); @@ -652,6 +680,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void DispatchComputeIndirect(GLintptr indirect) { +#if MOBILEGL_BUILD_DISAGGREGATED + RejectWireLegacyBuffer(); +#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DispatchComputeIndirect called with null VulkanRenderer"); MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::DispatchComputeIndirect called with null GL context"); pVulkanRenderer->DispatchComputeIndirect(indirect); @@ -817,6 +848,9 @@ 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_DISAGGREGATED + RejectWireLegacyBuffer(); +#endif const SizeT indexSize = MG_Util::GetGLTypeSize(type); if (indexSize == 0 || count < 2) { return false; @@ -932,6 +966,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { // vkCmdDrawIndexed all carry natively. static void MultiDrawElementsImpl(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices, GLsizei drawcount, const GLint* basevertex) { +#if MOBILEGL_BUILD_DISAGGREGATED + RejectWireLegacyBuffer(); +#endif if (drawcount <= 0) { return; } diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index b32438f8..608ebd0d 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -6869,7 +6869,7 @@ void main() { const IndexBufferView* pIndexBufferView) { #if MOBILEGL_BUILD_DISAGGREGATED if (MG_Config::Transport != MG_Config::TransportMode::Monolith) - return SetupWireDraw(frame, mode, aspects, drawParams); + 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 @@ -11226,7 +11226,13 @@ void main() { } // Store honoring the client pack state (single slice). +#if MOBILEGL_BUILD_DISAGGREGATED + const SharedPtr wireReplyHasNoPackBuffer; +#endif const auto& pixelPackBufferObject = +#if MOBILEGL_BUILD_DISAGGREGATED + MG_Config::Transport != MG_Config::TransportMode::Monolith ? wireReplyHasNoPackBuffer : +#endif MGB_CTX->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject(); const auto packParams = MGB_CTX->GetPixelStoreParameters(false); const SizeT rowPixels = static_cast(packParams.RowLength > 0 ? packParams.RowLength : width); diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index 08a61c60..fbea6f66 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -458,7 +458,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { GLenum format, GLenum type, void* pixels); void GenerateWireMipmap(); Bool SetupWireDraw(FrameContext::FrameData& frame, GLenum mode, Flags aspects, - const DrawCmdParam& drawParams); + const DrawCmdParam& drawParams, const IndexBufferView* indices); void DestroyWireDrawPass(); void DispatchWireCompute(GLuint x, GLuint y, GLuint z); UniquePtr m_wireDrawPass; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.inc b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.inc index dd612878..34f28548 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.inc +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.inc @@ -23,11 +23,12 @@ } Bool VulkanRenderer::SetupWireDraw(FrameContext::FrameData& frame, GLenum mode, - Flags aspects, const DrawCmdParam& drawParams) { + Flags aspects, const DrawCmdParam& drawParams, const IndexBufferView* indices) { auto& state = MG_Pipe::MGPipeApplier(); const auto program = WireProgramSource(state.BoundShaderCso); if (!program.GetLinkStatus() || !program.GetSpirvStatus()) return false; - if (aspects & DrawSetupAspect::IndexBuffer || aspects & DrawSetupAspect::IndirectDrawBuffer || + if (((aspects & DrawSetupAspect::IndexBuffer) && (!indices || !indices->forceClientMemory)) || + aspects & DrawSetupAspect::IndirectDrawBuffer || MGB_CTX->IsTransformFeedbackActive()) WireBufferLegacyFatal(); const auto* fbo = state.DrawFramebuffer(); if (!fbo) MagmaWireFatal("draw-framebuffer-record"); @@ -43,6 +44,7 @@ if (programObject->pointSizeCapabilityUnsupported) return false; const auto& programObj = *programObject; const auto vaoHandle = state.BoundVertexElements; + if (MG_Pipe::MGPipeHandleIsNull(vaoHandle)) MagmaWireFatal("vertex-elements-record"); if (!MG_Pipe::MGPipeHandleIsNull(vaoHandle)) { if (vaoHandle.Slot >= state.VertexElementsCsos.size()) MagmaWireFatal("vertex-elements-record"); const auto& vao = state.VertexElementsCsos[vaoHandle.Slot]; @@ -55,7 +57,7 @@ Vector attachments; Vector views; Vector colors; - VkAttachmentReference depth{VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; + VkAttachmentReference depth{VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL}; VkExtent2D extent{~0u, ~0u}; Uint32 layers = ~0u; VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; @@ -65,7 +67,7 @@ if (!image.image) return VK_ATTACHMENT_UNUSED; m_textureManager->FlushPendingUploads(); const VkImageLayout layout = aspect == VK_IMAGE_ASPECT_COLOR_BIT ? - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_GENERAL; TransitionWireImage(image, layout); VkImageViewCreateInfo info{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; info.image = image.image; @@ -101,7 +103,7 @@ for (Uint32 i = 0; i < MG_Pipe::kMGPipeMaxColorAttachments; ++i) { const Int32 slot = fbo->DrawBuffers[i]; const Uint32 index = slot < 0 ? VK_ATTACHMENT_UNUSED : add(fbo->Color[slot], VK_IMAGE_ASPECT_COLOR_BIT); - colors.push_back({index, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}); + colors.push_back({index, VK_IMAGE_LAYOUT_GENERAL}); } while (!colors.empty() && colors.back().attachment == VK_ATTACHMENT_UNUSED) colors.pop_back(); if (fbo->IsDefault || fbo->Depth.Kind != MG_Pipe::kMGPipeSurfaceKindNone) @@ -154,6 +156,14 @@ data, size, 16, slice)) return false; vkCmdBindVertexBuffers(frame.commandBuffer, binding++, 1, &slice.buffer, &slice.offset); } + if (indices) { + BufferSlice slice{}; + if (!m_bufferManager.UploadTransient(BufferKind::Index, m_frameContext.GetCurrentFrameIndex(), + reinterpret_cast(indices->indexByteOffset), indices->indexByteSize, 16, slice)) return false; + const VkIndexType type = indices->indexType == GL_UNSIGNED_INT ? VK_INDEX_TYPE_UINT32 : + indices->indexType == GL_UNSIGNED_SHORT ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT8; + vkCmdBindIndexBuffer(frame.commandBuffer, slice.buffer, slice.offset, type); + } if (!VkRenderPassManager::BeginRenderPass(frame.commandBuffer, pass)) return false; vkCmdBindPipeline(frame.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); ApplyDynamicDrawStateTail(frame, pass.extent, fbo->IsDefault, diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.inc b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.inc index 71dad21b..8eb767e9 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.inc +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.inc @@ -283,9 +283,27 @@ region.dstOffsets[0].y = static_cast(destination.extent.height)-dy0; region.dstOffsets[1].y = static_cast(destination.extent.height)-dy1; } - vkCmdBlitImage(m_frameContext.GetCurrent().commandBuffer,source.image,srcLayout, - destination.image,dstLayout,1,®ion, - filter == GL_LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST); + auto command = m_frameContext.GetCurrent().commandBuffer; + if (source.samples != VK_SAMPLE_COUNT_1_BIT || destination.samples != VK_SAMPLE_COUNT_1_BIT) { + const Int32 width = region.srcOffsets[1].x - region.srcOffsets[0].x; + const Int32 height = region.srcOffsets[1].y - region.srcOffsets[0].y; + if (width <= 0 || height <= 0 || width != region.dstOffsets[1].x - region.dstOffsets[0].x || + height != region.dstOffsets[1].y - region.dstOffsets[0].y || source.format != destination.format) + MagmaWireFatal("multisample-blit-shape@P7"); + if (source.samples != VK_SAMPLE_COUNT_1_BIT && destination.samples == VK_SAMPLE_COUNT_1_BIT && + aspect == VK_IMAGE_ASPECT_COLOR_BIT) { + VkImageResolve resolve{region.srcSubresource, region.srcOffsets[0], + region.dstSubresource, region.dstOffsets[0], {static_cast(width), static_cast(height), 1}}; + vkCmdResolveImage(command, source.image, srcLayout, destination.image, dstLayout, 1, &resolve); + } else if (source.samples == destination.samples) { + VkImageCopy copy{region.srcSubresource, region.srcOffsets[0], region.dstSubresource, + region.dstOffsets[0], {static_cast(width), static_cast(height), 1}}; + vkCmdCopyImage(command, source.image, srcLayout, destination.image, dstLayout, 1, ©); + } else MagmaWireFatal("multisample-blit-aspect@P7"); + } else { + vkCmdBlitImage(command,source.image,srcLayout,destination.image,dstLayout,1,®ion, + filter == GL_LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST); + } if (!destination.isDefault && dst.Kind == MG_Pipe::kMGPipeSurfaceKindTexture) m_textureManager->MarkWireTextureGpuWritten(destination.storage, destination.level, destination.layer, destination.layers); if (destination.isDefault) { @@ -328,8 +346,12 @@ WireImage destination = ResolveWireImage(fake,surface,aspect); if (!source.image || !destination.image) return; m_textureManager->FlushPendingUploads(); - TransitionWireImage(source,VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - TransitionWireImage(destination,VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + const Bool sameImage = source.image == destination.image; + const VkImageLayout srcLayout = sameImage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + const VkImageLayout dstLayout = sameImage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + TransitionWireImage(source,srcLayout); + if (sameImage) destination.layout = source.layout; + else TransitionWireImage(destination,dstLayout); VkImageBlit region{}; region.srcSubresource = {aspect,source.level,source.layer,1}; region.dstSubresource = {aspect,destination.level,destination.layer,1}; @@ -339,8 +361,8 @@ region.srcOffsets[0].y = static_cast(source.extent.height)-y; region.srcOffsets[1].y = static_cast(source.extent.height)-y-height; } - vkCmdBlitImage(m_frameContext.GetCurrent().commandBuffer,source.image,VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - destination.image,VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,1,®ion,VK_FILTER_NEAREST); + vkCmdBlitImage(m_frameContext.GetCurrent().commandBuffer,source.image,srcLayout, + destination.image,dstLayout,1,®ion,VK_FILTER_NEAREST); m_textureManager->MarkWireTextureGpuWritten(destination.storage,destination.level,destination.layer); } diff --git a/MobileGL/MG_IntegrationTest/CMakeLists.txt b/MobileGL/MG_IntegrationTest/CMakeLists.txt index 44c603f3..7cfecead 100644 --- a/MobileGL/MG_IntegrationTest/CMakeLists.txt +++ b/MobileGL/MG_IntegrationTest/CMakeLists.txt @@ -2386,7 +2386,7 @@ if (MOBILEGL_BUILD_DISAGGREGATED) foreach(fmSlot PartialTextureUploadPreservesGpuClear TextureViewClearTargetsItsRootMipAndLayer ClearBufferfi ClearBufferfv ClearBufferiv ClearBufferuiv ClearNamedFramebufferfi ClearNamedFramebufferfv ClearNamedFramebufferiv ClearNamedFramebufferuiv CopyTexImage2D CopyTexSubImage2D GenerateMipmap GenerateMipmapPackedFloat GenerateMipmapDepth) gtest_discover_tests(MobileGLIntegrationTest TEST_PREFIX "DirectVulkan.Split.Fm." - TEST_FILTER "F1WireScenario.${fmSlot}Pixels" + TEST_FILTER "F1WireScenario.${fmSlot}*" DISCOVERY_TIMEOUT 30 PROPERTIES LABELS "integration-magma-split"