From ec5f6ead3f6be2c0acc3bd032eb290fa47612b7a Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 29 Sep 2026 12:26:10 -0400 Subject: [PATCH] [Test] (P11 M2): TextureEmit.MoreThanKMaxDirtyRectsCollapsesToTheBoxWithRegionCountZero keeps its name and pins the one collapse left - a footprint larger than a record carries falls back to the storage's rect list --- MobileGL/MG_Test/Pipe/TextureEmitTest.cpp | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/MobileGL/MG_Test/Pipe/TextureEmitTest.cpp b/MobileGL/MG_Test/Pipe/TextureEmitTest.cpp index fc020d87..d75bcd24 100644 --- a/MobileGL/MG_Test/Pipe/TextureEmitTest.cpp +++ b/MobileGL/MG_Test/Pipe/TextureEmitTest.cpp @@ -214,6 +214,7 @@ TEST(TextureEmit, TheEmitterIsOneNeverDestroyedProcessSingleton) { X(TextureEmit, AScatteredUploadCarriesTheLevelShadowsStridesAndNotZero) \ X(TextureEmit, AWholeLevelUploadCarriesZeroStrides) \ X(TextureEmit, MoreWritesThanTheRectListKeepsCrossAsTheExactFootprint) \ + X(TextureEmit, MoreThanKMaxDirtyRectsCollapsesToTheBoxWithRegionCountZero) \ X(TextureEmit, ASinglePartialWriteCarriesItsBoxAsOneRegion) \ X(TextureEmit, ALevelTooLargeForTheStageChunkIsCutIntoSlabs) \ X(TextureEmit, AnUploadThroughAViewKeysOnTheStorageOwner) \ @@ -609,6 +610,35 @@ TEST(TextureEmit, MoreWritesThanTheRectListKeepsCrossAsTheExactFootprint) { } } +// P11 M2: THE NAME IS P4a's AND IT STAYS TRUE, ONE LEVEL UP. The case it named - more writes than +// the rect list keeps - now crosses as the exact footprint (the case above). What still collapses +// is a footprint larger than one record may carry (kMGPipeMaxPendingUploadRegions): the emitter +// falls back to the storage's rect list, which covers the writes - so, as before, the storage's own +// answer is the oracle, read BEFORE the drain clears the level, and 0 means "the union box is the +// whole story". 16,384 one-texel writes two texels apart are that many disjoint boxes. +TEST(TextureEmit, MoreThanKMaxDirtyRectsCollapsesToTheBoxWithRegionCountZero) { + TextureScope scope; + const auto texture = MakeTexture2D(91, 256); + for (Int y = 0; y < 256; y += 2) { + for (Int x = 0; x < 256; x += 2) { + texture->MarkStorageDirtyRegion(TextureUploadTarget::Texture2D, 0, IntVec3{x, y, 0}, + IntVec3{1, 1, 1}); + } + } + Vector footprint; + texture->GetStorageDirtyFootprint(TextureUploadTarget::Texture2D, 0, footprint); + ASSERT_GT(footprint.size(), static_cast(kMGPipeMaxPendingUploadRegions)) + << "the writes must outgrow one record, or this case pins the footprint path instead"; + MipmapDirtyRegion oracle[MipmapStorage::kMaxDirtyRects]; + const SizeT oracleCount = texture->GetStorageDirtyRects(TextureUploadTarget::Texture2D, 0, oracle, + MipmapStorage::kMaxDirtyRects); + EXPECT_LE(oracleCount, MipmapStorage::kMaxDirtyRects); + Textures().DrainTextureSubData(Ctx()); + EXPECT_EQ(Textures().LastSubData().RegionCount, static_cast(oracleCount)) + << "the emitted region count is not the storage's own answer"; + EXPECT_EQ(Textures().LastRegions().size(), oracleCount); +} + // P11 M2: A SINGLE PARTIAL BOX CARRIES ITSELF AS ONE REGION. "0 regions" is the whole-level // spelling only, so the applier's accumulation - which makes an entry box-only the moment one // contribution carries no list - cannot widen two exact contributions into their union box.