re: coverage is 96.4% (6069/6294) -- and the 225 misses get a gate breakdown
undecoded.rs supplies the denominator the coverage numbers never had; the disc holds 6294 XBG7 resources, 6069 decode, 225 are searched and missed, 0 lack a descriptor. gate_histogram.rs attributes each miss to the furthest gate its best candidate reached: 120 connectivity, 74 grouped-pool (different path), 15 degenerate/extent, 9 winding, 7 buffer-not-covered. Recorded as a work-list, not a verdict -- a wrong candidate can pass more gates than the true block. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -755,6 +755,67 @@ pub fn debug_try_anchor(
|
||||
None
|
||||
}
|
||||
|
||||
/// How far did the anchor scan get for a resource it failed to place?
|
||||
///
|
||||
/// Runs the same candidate loop the decoder runs and keeps the **furthest**
|
||||
/// rejection — the candidate that passed the most gates before failing. Over the
|
||||
/// resources that never decode, the distribution of these says which gate to
|
||||
/// work on, instead of tuning one threshold and re-measuring.
|
||||
pub fn debug_best_rejection(bytes: &[u8], name: &str) -> Option<(usize, String)> {
|
||||
let (decl, markers) = decl_of(bytes, name)?;
|
||||
let starts = debug_vertex_run_starts(bytes, decl.stride);
|
||||
let rank = |why: &str| -> usize {
|
||||
if why.contains("out of range") {
|
||||
1
|
||||
} else if why.contains("buffer not covered") {
|
||||
2
|
||||
} else if why.contains("not finite") || why.contains("degenerate") {
|
||||
3
|
||||
} else if why.contains("connectivity") {
|
||||
4
|
||||
} else if why.contains("winding") {
|
||||
5
|
||||
} else {
|
||||
0
|
||||
}
|
||||
};
|
||||
// Only the single-block path is modelled here. A grouped-pool resource is
|
||||
// placed by its pivot, so running the single-block loop on `markers[0]`
|
||||
// would report a gate the decoder never consulted.
|
||||
if markers.len() > 1 {
|
||||
return Some((9, format!("grouped pool ({} sub-meshes) — not analysed here", markers.len())));
|
||||
}
|
||||
let (vtx_count, index_count) = *markers.first()?;
|
||||
let idx_bytes = index_count * 2;
|
||||
let mut best = (0usize, String::from("no candidate reached any gate"));
|
||||
for &vb in &starts {
|
||||
for pad in 0..=3usize {
|
||||
if vb < idx_bytes + pad {
|
||||
continue;
|
||||
}
|
||||
let mc = if pad == 0 { 0.0 } else { 0.85 };
|
||||
if let Err(why) = validate_block_report(
|
||||
bytes,
|
||||
vb - idx_bytes - pad,
|
||||
vb,
|
||||
vtx_count,
|
||||
index_count,
|
||||
&decl,
|
||||
mc,
|
||||
true,
|
||||
) {
|
||||
let r = rank(&why);
|
||||
if r > best.0 {
|
||||
best = (r, why);
|
||||
}
|
||||
} else {
|
||||
return None; // it would have decoded — not a miss
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(best)
|
||||
}
|
||||
|
||||
/// Diagnostic: why does the decoder refuse a grouped-pool resource at a given
|
||||
/// pool start? Recomputes the pool layout exactly as [`anchor_grouped_meshes`]
|
||||
/// does and reports the pivot sub-mesh's verdict for each index/vertex pad —
|
||||
|
||||
Reference in New Issue
Block a user