render/rt/bottom_levels.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-License-Identifier: BSD-3-Clause | ||
| 2 | /// @file bottom_levels.h | ||
| 3 | /// @brief A bottom-level acceleration structure for each geometry, built on the device as the | ||
| 4 | /// geometry changes: static geometry traced fast and compacted, deforming geometry refitted. | ||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "ernie/device/acceleration.h" | ||
| 8 | #include "ernie/device/column.h" | ||
| 9 | #include "ernie/device/staging.h" | ||
| 10 | #include "ernie/graph/graph.h" | ||
| 11 | #include "ernie/render/geometry.h" | ||
| 12 | |||
| 13 | #include <cstdint> | ||
| 14 | #include <memory> | ||
| 15 | #include <vector> | ||
| 16 | |||
| 17 | namespace ernie { | ||
| 18 | |||
| 19 | /// @brief The bottom levels of a geometry pool. Builds wait for the frame's graph, batched in one | ||
| 20 | /// call under a scratch budget; geometry whose bottom level is not built yet has address 0, which | ||
| 21 | /// a top level takes as an instance switched off. | ||
| 22 | /// | ||
| 23 | /// Static geometry is built to trace fast and compacted a few frames later, once its compacted | ||
| 24 | /// size has come back without a wait. Geometry refitted switches to a refittable build, and is | ||
| 25 | /// built anew after `kRefitsBeforeRebuild` refits, as refits loosen the tree. | ||
| 26 | class BottomLevels { | ||
| 27 | public: | ||
| 28 | static constexpr std::uint32_t kRefitsBeforeRebuild = 16; | ||
| 29 | |||
| 30 | /// @param arenas Where the address column lives. | ||
| 31 | /// @param scratchBudget The most scratch one frame's builds take; one build always goes. | ||
| 32 | BottomLevels(DeviceContext& context, Arenas& arenas, const GeometryPool& geometry, | ||
| 33 | std::uint64_t scratchBudget = std::uint64_t{64} << 20); | ||
| 34 | BottomLevels(const BottomLevels&) = delete; | ||
| 35 | BottomLevels& operator=(const BottomLevels&) = delete; | ||
| 36 | |||
| 37 | /// @brief Takes in what a geometry update changed: builds and refits to run, levels to free. | ||
| 38 | void Apply(const GeometryPool::Changes& changes); | ||
| 39 | /// @brief Adds the passes that compact finished levels, run this frame's builds and upload | ||
| 40 | /// the addresses, after the geometry's uploads and before the top levels' builds. | ||
| 41 | void AddBuilds(graph::Graph& graph); | ||
| 42 | |||
| 43 | /// @return Each geometry's bottom level address, a uint64 a geometry id; 0 until built. | ||
| 44 | 22 | const DeviceColumn& Addresses() const { | |
| 45 | 22 | return *addresses_; | |
| 46 | } | ||
| 47 | /// @return The pool the levels live in, which top-level builds import to read. | ||
| 48 | 27 | const AccelerationPool& Pool() const { | |
| 49 | 27 | return pool_; | |
| 50 | } | ||
| 51 | /// @return Builds and refits not run yet, as over the budget. | ||
| 52 | 1 | std::size_t Pending() const { | |
| 53 | 1 | return pending_.size(); | |
| 54 | } | ||
| 55 | /// @brief What the levels have cost so far, for memory and profiler reports. | ||
| 56 | 15 | struct Statistics { | |
| 57 | std::uint32_t built = 0; | ||
| 58 | std::uint32_t refitted = 0; | ||
| 59 | std::uint32_t compacted = 0; | ||
| 60 | /// Bytes compaction gave back. | ||
| 61 | std::uint64_t saved = 0; | ||
| 62 | }; | ||
| 63 | const Statistics& Totals() const { | ||
| 64 | 2 | return totals_; | |
| 65 | } | ||
| 66 | |||
| 67 | private: | ||
| 68 | 80 | struct Level { | |
| 69 | std::shared_ptr<AccelerationStructure> structure; | ||
| 70 | bool deforming = false; | ||
| 71 | std::uint32_t refits = 0; | ||
| 72 | /// Whether its compacted size is being read back. | ||
| 73 | bool compacting = false; | ||
| 74 | }; | ||
| 75 | struct Work { | ||
| 76 | GeometryId geometry = 0; | ||
| 77 | bool refit = false; | ||
| 78 | }; | ||
| 79 | /// Compacted sizes on their way back, for the levels built with them. | ||
| 80 | struct Compaction { | ||
| 81 | std::unique_ptr<CompactionQuery> query; | ||
| 82 | std::vector<GeometryId> geometries; | ||
| 83 | std::vector<std::shared_ptr<AccelerationStructure>> structures; | ||
| 84 | }; | ||
| 85 | |||
| 86 | /// Levels moving into compacted copies: each source, then its copy. | ||
| 87 | using Moves = std::vector< | ||
| 88 | std::pair<std::shared_ptr<AccelerationStructure>, std::shared_ptr<AccelerationStructure>>>; | ||
| 89 | /// A frame's builds and refits, and the geometry they read. | ||
| 90 | struct FrameBuilds { | ||
| 91 | std::vector<TriangleGeometry> triangles; | ||
| 92 | std::vector<BoxGeometry> boxes; | ||
| 93 | std::vector<BottomBuild> builds; | ||
| 94 | std::vector<GeometryId> built; | ||
| 95 | std::uint64_t scratch = 0; | ||
| 96 | }; | ||
| 97 | |||
| 98 | Level& At(GeometryId geometry); | ||
| 99 | void Queue(GeometryId geometry, bool refit); | ||
| 100 | void SetAddress(GeometryId geometry, std::uint64_t address); | ||
| 101 | /// @return The triangles or box a geometry's level is built over. | ||
| 102 | BottomBuild Build(GeometryId geometry, bool refit, std::vector<TriangleGeometry>& triangles, | ||
| 103 | std::vector<BoxGeometry>& boxes) const; | ||
| 104 | /// @return The moves of levels whose compacted sizes have come back. | ||
| 105 | Moves TakeCompactedSizes(); | ||
| 106 | /// @return The pending builds that fit the scratch budget; the rest wait for a later frame. | ||
| 107 | FrameBuilds PlanBuilds(); | ||
| 108 | /// @return The query reading back the compacted sizes of the static levels just built. | ||
| 109 | Compaction StartCompactionQuery(const std::vector<GeometryId>& built); | ||
| 110 | void AddAddressUpload(graph::Graph& graph); | ||
| 111 | void AddBuildPass(graph::Graph& graph, FrameBuilds builds, Moves moves, | ||
| 112 | const Compaction& compaction); | ||
| 113 | |||
| 114 | DeviceContext& context_; | ||
| 115 | const GeometryPool& geometry_; | ||
| 116 | std::uint64_t scratchBudget_; | ||
| 117 | AccelerationPool pool_; | ||
| 118 | Uploader uploader_; | ||
| 119 | std::vector<Level> levels_; | ||
| 120 | std::vector<Work> pending_; | ||
| 121 | std::vector<Compaction> compactions_; | ||
| 122 | std::vector<std::uint64_t> hostAddresses_; | ||
| 123 | std::vector<std::uint32_t> dirtyAddresses_; | ||
| 124 | std::unique_ptr<DeviceColumn> addresses_; | ||
| 125 | Statistics totals_; | ||
| 126 | }; | ||
| 127 | |||
| 128 | } // namespace ernie | ||
| 129 |