scene/extent_cache.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-License-Identifier: BSD-3-Clause | ||
| 2 | /// @file extent_cache.cpp | ||
| 3 | /// @brief Replaying row changes into the extent boxes and recomputing stale runs. | ||
| 4 | #include "ernie/scene/extent_cache.h" | ||
| 5 | |||
| 6 | #include <algorithm> | ||
| 7 | |||
| 8 | namespace ernie { | ||
| 9 | |||
| 10 | 715 | void ExtentCache::Track(BucketId bucket, ExtentFunction compute) { | |
| 11 | 1430 | buckets_.resize(std::max<std::size_t>(buckets_.size(), bucket + 1)); | |
| 12 | 715 | buckets_[bucket].compute = compute; | |
| 13 | 715 | } | |
| 14 | |||
| 15 | 62 | void ExtentCache::Update(const PrimStore& store) { | |
| 16 | 62 | const ChangeSet changes = store.ChangesSince(cursor_); | |
| 17 | 1406 | for (const ChangeSet::Rows& rows : changes.rows) { | |
| 18 | 1344 | if (Tracked(rows.bucket)) { | |
| 19 | 1295 | Replay(buckets_[rows.bucket], rows.change); | |
| 20 | } | ||
| 21 | } | ||
| 22 | 695 | for (const ChangeSet::Values& values : changes.values) { | |
| 23 | 633 | if (Tracked(values.bucket)) { | |
| 24 | 1461 | for (const RowRange range : values.rows) { | |
| 25 | 865 | buckets_[values.bucket].stale.SetRange(range.begin, range.end); | |
| 26 | } | ||
| 27 | } | ||
| 28 | } | ||
| 29 | 217 | for (BucketId bucket = 0; bucket < buckets_.size(); ++bucket) { | |
| 30 | 155 | if (Tracked(bucket) && store.GetBucket(bucket).version > cursor_) { | |
| 31 | 66 | Refresh(buckets_[bucket], store, bucket); | |
| 32 | } | ||
| 33 | } | ||
| 34 | 62 | cursor_ = changes.version; | |
| 35 | 62 | } | |
| 36 | |||
| 37 | 13601 | std::optional<Box> ExtentCache::Find(const PrimStore& store, BucketId bucket, | |
| 38 | std::uint32_t row) const { | ||
| 39 | 13601 | if (!Tracked(bucket) || store.GetBucket(bucket).version > cursor_ || | |
| 40 | 13434 | row >= buckets_[bucket].boxes.size()) { | |
| 41 | 167 | return std::nullopt; | |
| 42 | } | ||
| 43 | 13434 | return buckets_[bucket].boxes[row]; | |
| 44 | } | ||
| 45 | |||
| 46 | 15733 | bool ExtentCache::Tracked(BucketId bucket) const { | |
| 47 | 15733 | return bucket < buckets_.size() && buckets_[bucket].compute != nullptr; | |
| 48 | } | ||
| 49 | |||
| 50 | 1295 | void ExtentCache::Replay(Entry& entry, const StructuralChange& change) { | |
| 51 | 1295 | using Kind = StructuralChange::Kind; | |
| 52 | 1295 | if (change.kind == Kind::Reset) { | |
| 53 | ✗ | Resize(entry, 0); | |
| 54 | } | ||
| 55 | 1295 | if (change.kind == Kind::Added || change.kind == Kind::Reset) { | |
| 56 | 819 | Resize(entry, change.row + change.count); | |
| 57 | 819 | entry.stale.SetRange(change.row, change.row + change.count); | |
| 58 | 476 | } else if (change.kind == Kind::Moved) { | |
| 59 | // Recomputed, not copied: the moved row's own value edits are reported at its old place. | ||
| 60 | 237 | entry.stale.Set(change.row); | |
| 61 | 237 | Resize(entry, change.from); | |
| 62 | 239 | } else if (change.row + 1 == entry.boxes.size()) { | |
| 63 | // Removing the last row moves nothing; otherwise the Moved that follows shrinks it. | ||
| 64 | 2 | Resize(entry, change.row); | |
| 65 | } | ||
| 66 | 1295 | } | |
| 67 | |||
| 68 | 1058 | void ExtentCache::Resize(Entry& entry, std::uint32_t rows) { | |
| 69 | 1058 | entry.boxes.resize(rows); | |
| 70 | 1058 | entry.stale.Resize(rows); | |
| 71 | 1058 | } | |
| 72 | |||
| 73 | 66 | void ExtentCache::Refresh(Entry& entry, const PrimStore& store, BucketId bucket) { | |
| 74 | 66 | const ExtentRows columns{store, bucket}; | |
| 75 | 66 | entry.stale.ForEachRun([&](std::size_t begin, std::size_t end) { | |
| 76 | 75 | entry.compute(columns, {static_cast<std::uint32_t>(begin), static_cast<std::uint32_t>(end)}, | |
| 77 | 75 | std::span(entry.boxes).subspan(begin, end - begin)); | |
| 78 | 75 | }); | |
| 79 | 66 | entry.stale.Clear(); | |
| 80 | 66 | } | |
| 81 | |||
| 82 | } // namespace ernie | ||
| 83 |