draw optimizations

This commit is contained in:
IliaDenisov
2026-03-08 23:30:11 +02:00
parent fdcbb5d6f4
commit ac35360d60
18 changed files with 875 additions and 566 deletions
+20 -6
View File
@@ -57,22 +57,36 @@ func (w *World) collectCandidatesForTile(r Rect) []MapItem {
rowStart := w.worldToCellY(r.minY)
rowEnd := w.worldToCellY(r.maxY - 1)
seen := make(map[PrimitiveID]struct{})
result := make([]MapItem, 0)
// Start a new epoch for this tile dedupe.
w.candSeenResetIfOverflow()
// Reuse result buffer.
out := w.scratchCandidates[:0]
for row := rowStart; row <= rowEnd; row++ {
for col := colStart; col <= colEnd; col++ {
cell := w.grid[row][col]
for _, item := range cell {
id := item.ID()
if _, ok := seen[id]; ok {
if w.candSeenMark(id) {
continue
}
seen[id] = struct{}{}
result = append(result, item)
out = append(out, item)
}
}
}
return result
// Store back the reusable buffer (keep capacity).
w.scratchCandidates = out[:0]
// IMPORTANT:
// We must return a stable slice to the caller (plan stores it).
// Returning `out` directly would be overwritten on the next tile.
//
// So: copy out into a freshly allocated slice OR into a plan-level scratch pool.
// For Step 1 we keep correctness: allocate exactly once per tile.
// Step 3 will remove this allocation by making plan own a pooled backing store.
res := make([]MapItem, len(out))
copy(res, out)
return res
}