From 40c5443fc03c3441f45ffb3b1cf54cd57c737051 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sun, 20 Sep 2026 12:46:01 -0400 Subject: [PATCH] [MGPipe] carry full mutable mip extents independently of dirty upload boxes --- MobileGL/MG_Impl/Pipe/TextureEmit.h | 3 +++ MobileGL/MG_Pipe/MGPipeTypes.h | 5 ++++- MobileGL/MG_Remote/Wire/PipeWireCodec.cpp | 9 +++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/MobileGL/MG_Impl/Pipe/TextureEmit.h b/MobileGL/MG_Impl/Pipe/TextureEmit.h index 46f9c9fb..04798d4a 100644 --- a/MobileGL/MG_Impl/Pipe/TextureEmit.h +++ b/MobileGL/MG_Impl/Pipe/TextureEmit.h @@ -1249,6 +1249,9 @@ namespace MobileGL::MG_Pipe { static_cast(MGPipeResourceTargetForTextureTarget(texture->GetTarget())), static_cast(uploadTarget)); m_lastSubData.Level = static_cast(level); + m_lastSubData.LevelWidth = static_cast(levelSize.x()); + m_lastSubData.LevelHeight = static_cast(levelSize.y()); + m_lastSubData.LevelDepth = static_cast(levelSize.z()); // ALWAYS 1 ON THE CLIENT SIDE. The conversion fallbacks (the packed-norm, widened // and fallback upload preparers) are the server's and run there, so the bytes this // record declares ARE the level shadow. The server clears the flag internally when diff --git a/MobileGL/MG_Pipe/MGPipeTypes.h b/MobileGL/MG_Pipe/MGPipeTypes.h index ddee8eb4..6347fea4 100644 --- a/MobileGL/MG_Pipe/MGPipeTypes.h +++ b/MobileGL/MG_Pipe/MGPipeTypes.h @@ -1290,8 +1290,11 @@ namespace MobileGL::MG_Pipe { Uint32 RegionCount; // MGPSubRegion[] in the variable tail Uint32 Pad1; MGPBlobRef Blob; + // Mutable GL images may define a lone mip or a noncanonical mip size. + // The dirty box describes changed texels, not the full staged image. + Uint32 LevelWidth, LevelHeight, LevelDepth, LevelPad; }; - MGP_ASSERT_POD(MGPSubData, 72); + MGP_ASSERT_POD(MGPSubData, 88); // The one spelling of MGPSubData::Target's encoding, stated above the struct. // diff --git a/MobileGL/MG_Remote/Wire/PipeWireCodec.cpp b/MobileGL/MG_Remote/Wire/PipeWireCodec.cpp index 1fc7163d..8653eac3 100644 --- a/MobileGL/MG_Remote/Wire/PipeWireCodec.cpp +++ b/MobileGL/MG_Remote/Wire/PipeWireCodec.cpp @@ -2040,6 +2040,15 @@ namespace MobileGL::MG_Remote::Wire { // ---- transfer --------------------------------------------------------------------- case MGPWireOp::ResourceSubData: { const auto& rec = *static_cast(payload); + const Bool hasExtent = rec.LevelWidth || rec.LevelHeight || rec.LevelDepth; + if (hasExtent && (rec.Target == kMGPipeResourceTargetBuffer || !rec.LevelWidth || + !rec.LevelHeight || !rec.LevelDepth || rec.LevelWidth > 0x7fffffffu || + rec.LevelHeight > 0x7fffffffu || rec.LevelDepth > 0x7fffffffu || + rec.UnionBox.X < 0 || rec.UnionBox.Y < 0 || rec.UnionBox.Z < 0 || + Uint64(rec.UnionBox.X) + rec.UnionBox.W > rec.LevelWidth || + Uint64(rec.UnionBox.Y) + rec.UnionBox.H > rec.LevelHeight || + Uint64(rec.UnionBox.Z) + rec.UnionBox.D > rec.LevelDepth)) + WireProtocolFatal("ResourceSubData.LevelExtent", "invalid full image extent or dirty box"); // Rule A arms both halves. The buffer half already declared a real size in // monolith and is cross-checked at PipeApply.cpp:702; THE TEXTURE HALF DECLARED 0 // (TextureEmit.h:1265-1267, on the grounds that the byte count was "the server's