render/prim_rows.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-License-Identifier: BSD-3-Clause | ||
| 2 | /// @file prim_rows.cpp | ||
| 3 | /// @brief Replaying bucket row logs. | ||
| 4 | #include "ernie/render/prim_rows.h" | ||
| 5 | |||
| 6 | #include "ernie/util/profiler.h" | ||
| 7 | |||
| 8 | #include <algorithm> | ||
| 9 | |||
| 10 | namespace ernie { | ||
| 11 | namespace { | ||
| 12 | |||
| 13 | /// A row added since the last replay, whose prim is read from the bucket afterwards. | ||
| 14 | 3030 | bool IsPlaceholder(PrimId prim) { | |
| 15 | 3030 | return prim.slot == PrimId().slot; | |
| 16 | } | ||
| 17 | |||
| 18 | } // namespace | ||
| 19 | |||
| 20 | 77 | PrimRows::Changes PrimRows::Follow(const PrimStore& store, const ChangeSet& changes) { | |
| 21 | 77 | ERNIE_ZONE("Follow the buckets' rows"); | |
| 22 | 77 | rows_.resize(store.BucketCount()); | |
| 23 | 77 | Changes result; | |
| 24 | 77 | std::vector<BucketId> touched; | |
| 25 | 1719 | for (const ChangeSet::Rows& entry : changes.rows) { | |
| 26 | 1642 | std::vector<PrimId>& rows = rows_[entry.bucket]; | |
| 27 | 1642 | const StructuralChange& change = entry.change; | |
| 28 | 1642 | touched.push_back(entry.bucket); | |
| 29 | 1642 | switch (change.kind) { | |
| 30 | 1620 | case StructuralChange::Kind::Added: | |
| 31 | 1620 | rows.resize(change.row + change.count, PrimId()); | |
| 32 | 1620 | break; | |
| 33 | 13 | case StructuralChange::Kind::Removed: | |
| 34 | 13 | if (!IsPlaceholder(rows[change.row])) { | |
| 35 | 13 | result.removed.push_back(rows[change.row]); | |
| 36 | } | ||
| 37 | // Unless it was the last, a Moved change brings the last row here next. | ||
| 38 | 13 | if (change.row + 1 == rows.size()) { | |
| 39 | 4 | rows.pop_back(); | |
| 40 | } | ||
| 41 | break; | ||
| 42 | 9 | case StructuralChange::Kind::Moved: | |
| 43 | 9 | rows[change.row] = rows[change.from]; | |
| 44 | 9 | rows.pop_back(); | |
| 45 | 9 | if (!IsPlaceholder(rows[change.row])) { | |
| 46 | 9 | result.moved.push_back(rows[change.row]); | |
| 47 | } | ||
| 48 | break; | ||
| 49 | ✗ | case StructuralChange::Kind::Reset: | |
| 50 | ✗ | for (const PrimId prim : rows) { | |
| 51 | ✗ | if (!IsPlaceholder(prim)) { | |
| 52 | ✗ | result.removed.push_back(prim); | |
| 53 | } | ||
| 54 | } | ||
| 55 | ✗ | rows.assign(change.count, PrimId()); | |
| 56 | ✗ | break; | |
| 57 | } | ||
| 58 | } | ||
| 59 | 77 | std::ranges::sort(touched); | |
| 60 | 77 | touched.erase(std::ranges::unique(touched).begin(), touched.end()); | |
| 61 | 177 | for (const BucketId bucket : touched) { | |
| 62 | 100 | std::vector<PrimId>& rows = rows_[bucket]; | |
| 63 | 100 | const std::vector<PrimId>& now = store.GetBucket(bucket).prims; | |
| 64 | 3108 | for (std::size_t row = 0; row < rows.size(); ++row) { | |
| 65 | 3008 | if (IsPlaceholder(rows[row])) { | |
| 66 | 1620 | rows[row] = now[row]; | |
| 67 | 1620 | result.added.push_back(now[row]); | |
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| 71 | // Parents before children: ancestors' paths are interned first. | ||
| 72 | 30951 | std::ranges::sort(result.added, {}, [&](PrimId prim) { return store.PrimPath(prim); }); | |
| 73 | 77 | return result; | |
| 74 | 77 | } | |
| 75 | |||
| 76 | } // namespace ernie | ||
| 77 |