mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Fix] (Test): warm the whole content space before the SamplerCso leak baseline, so the case measures the death path and not the content-addressed cache filling up
This commit is contained in:
@@ -703,10 +703,28 @@ void main() { oColor = texture(uTex, vUv); }
|
|||||||
// creates several. The composite round creates three ShaderCsos - two stage programs
|
// creates several. The composite round creates three ShaderCsos - two stage programs
|
||||||
// and the composite they are flattened into - but only ONE of the three is a band
|
// and the composite they are flattened into - but only ONE of the three is a band
|
||||||
// slot, so the band's answer is 1 and the ordinary space's would have been 3.
|
// slot, so the band's answer is 1 and the ordinary space's would have been 3.
|
||||||
|
// `warmUpRounds` is how many rounds run BEFORE the baseline is taken, and for one
|
||||||
|
// kind it is not two.
|
||||||
|
//
|
||||||
|
// A CONTENT-ADDRESSED KIND'S SLOT IS NOT THE OBJECT'S (D-F1, ID-17's reference-count
|
||||||
|
// ruling). SamplerCso is minted by a CACHE keyed on the parameter block: destroying
|
||||||
|
// the frontend sampler releases its REFERENCE, and the entry then stays in the cache,
|
||||||
|
// unreferenced, until LRU eviction at capacity 256. So a churn over N DISTINCT
|
||||||
|
// parameter sets legitimately retains N slots however many objects carried them, and
|
||||||
|
// "48 objects, 14 slots not returned" is the cache working, not P3a's C-1 leak.
|
||||||
|
// Asserting the flat count there measures the cache's capacity policy and calls it a
|
||||||
|
// leak - which is exactly what this case did on the tree where package C landed.
|
||||||
|
//
|
||||||
|
// The fix is not a weaker assertion but a warmer cache: run enough warm-up rounds to
|
||||||
|
// walk EVERY distinct content once, so that the baseline is taken with the cache full
|
||||||
|
// and the measured churn re-uses entries that already exist. The three assertions
|
||||||
|
// below then say something STRONGER than they could for a per-object kind - a warm
|
||||||
|
// content-addressed cache must not grow AT ALL under churn - and an unbounded leak,
|
||||||
|
// which is what C-1 is about, still moves every one of them.
|
||||||
using ChurnRound = std::function<void(bool checkPixels, const std::function<void()>& observe)>;
|
using ChurnRound = std::function<void(bool checkPixels, const std::function<void()>& observe)>;
|
||||||
void AssertChurnReturnsEverySlot(PipeSlotKind kind, SlotSpace space, const char* kindName,
|
void AssertChurnReturnsEverySlot(PipeSlotKind kind, SlotSpace space, const char* kindName,
|
||||||
const char* owner, unsigned maxInFlight,
|
const char* owner, unsigned maxInFlight,
|
||||||
const ChurnRound& round) {
|
const ChurnRound& round, unsigned warmUpRounds = 2u) {
|
||||||
// THE LANE'S OWN PIN, not the arm (F-m4). The Legacy and AbaControl lanes run
|
// THE LANE'S OWN PIN, not the arm (F-m4). The Legacy and AbaControl lanes run
|
||||||
// MOBILEGL_PIPE_PUSH=0 and really have no allocator to leak from; the Handles
|
// MOBILEGL_PIPE_PUSH=0 and really have no allocator to leak from; the Handles
|
||||||
// lanes and DirectVulkan.HandleRecycle.AbaControlHandles. all pin the shipping
|
// lanes and DirectVulkan.HandleRecycle.AbaControlHandles. all pin the shipping
|
||||||
@@ -749,8 +767,12 @@ void main() { oColor = texture(uTex, vUv); }
|
|||||||
unsigned live = 0;
|
unsigned live = 0;
|
||||||
if (ReadSpaceLiveCount(kind, space, &live) && live > peakLive) peakLive = live;
|
if (ReadSpaceLiveCount(kind, space, &live) && live > peakLive) peakLive = live;
|
||||||
};
|
};
|
||||||
|
// The first round checks pixels; the rest only churn. Two is the floor and the
|
||||||
|
// default (see the parameter's note): the first mints the one-off slots any draw
|
||||||
|
// needs and the second proves the steady state has been reached.
|
||||||
|
ASSERT_GE(warmUpRounds, 2u) << "the warm-up has to reach a steady state";
|
||||||
round(/*checkPixels=*/true, observe);
|
round(/*checkPixels=*/true, observe);
|
||||||
round(/*checkPixels=*/false, observe);
|
for (unsigned i = 1; i < warmUpRounds; ++i) round(/*checkPixels=*/false, observe);
|
||||||
peakLive = 0;
|
peakLive = 0;
|
||||||
|
|
||||||
unsigned liveBefore = 0;
|
unsigned liveBefore = 0;
|
||||||
@@ -2064,6 +2086,17 @@ void main() { oColor = vec4(0.0, 1.0, 0.0, 1.0); }
|
|||||||
// sampler CSOs are CONTENT-addressed at capacity 256 (D-F1), so 48 identical samplers
|
// sampler CSOs are CONTENT-addressed at capacity 256 (D-F1), so 48 identical samplers
|
||||||
// would legitimately be ONE CSO and the case would assert nothing about the death
|
// would legitimately be ONE CSO and the case would assert nothing about the death
|
||||||
// path. The LOD bias moves per round, which changes the hash and nothing else.
|
// path. The LOD bias moves per round, which changes the hash and nothing else.
|
||||||
|
//
|
||||||
|
// ...AND THE SET IS FINITE ON PURPOSE, which is the other half of the same argument.
|
||||||
|
// The bias cycles through kDistinctSamplerContents values, so the churn walks a
|
||||||
|
// CLOSED content space; the warm-up below walks all of it once before the baseline is
|
||||||
|
// taken, and every measured round then asks the cache for an entry it already holds.
|
||||||
|
// Without that, the case measured the cache filling up - one retained slot per
|
||||||
|
// distinct parameter block, which is C's design (ID-17) and not a death-path defect -
|
||||||
|
// and reported it as P3a's C-1 leak. Measured on the tree where C landed: 48 rounds,
|
||||||
|
// 14 slots retained, i.e. the distinct contents minus the two the warm-up had already
|
||||||
|
// interned. With the whole space warm the same churn must move nothing at all.
|
||||||
|
constexpr int kDistinctSamplerContents = 16;
|
||||||
int round = 0;
|
int round = 0;
|
||||||
AssertChurnReturnsEverySlot(
|
AssertChurnReturnsEverySlot(
|
||||||
PipeSlotKind::SamplerCso, SlotSpace::Ordinary, "SamplerCso", "C (clientsp)",
|
PipeSlotKind::SamplerCso, SlotSpace::Ordinary, "SamplerCso", "C (clientsp)",
|
||||||
@@ -2096,7 +2129,8 @@ void main() { oColor = vec4(0.0, 1.0, 0.0, 1.0); }
|
|||||||
observe();
|
observe();
|
||||||
glBindSampler(0, 0);
|
glBindSampler(0, 0);
|
||||||
glDeleteSamplers(1, &sampler);
|
glDeleteSamplers(1, &sampler);
|
||||||
});
|
},
|
||||||
|
/*warmUpRounds=*/static_cast<unsigned>(kDistinctSamplerContents) + 2u);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
GLuint cleanupTexture = texture;
|
GLuint cleanupTexture = texture;
|
||||||
|
|||||||
Reference in New Issue
Block a user