render/rt/top_levels.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-License-Identifier: BSD-3-Clause | ||
| 2 | /// @file top_levels.h | ||
| 3 | /// @brief The top-level acceleration structure rays are traced through, rebuilt each frame on the | ||
| 4 | /// device from the instances' world transforms with no loop on the host. | ||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "ernie/device/acceleration.h" | ||
| 8 | #include "ernie/device/kernel.h" | ||
| 9 | #include "ernie/device/shader_compiler.h" | ||
| 10 | #include "ernie/graph/graph.h" | ||
| 11 | #include "ernie/render/instances.h" | ||
| 12 | #include "ernie/render/rt/bottom_levels.h" | ||
| 13 | #include "ernie/render/transform_graph.h" | ||
| 14 | |||
| 15 | #include <memory> | ||
| 16 | |||
| 17 | namespace ernie { | ||
| 18 | |||
| 19 | /// @brief The scene's top level, rebuilt every frame: a kernel writes each instance's record from | ||
| 20 | /// its world transform, its shape transform and its geometry's bottom level, and the build follows. | ||
| 21 | /// Instances whose bottom level is not built are switched off. An instance's custom index is its | ||
| 22 | /// geometry; its row in the instance table is `InstanceIndex()`. Capacity grows by doubling and | ||
| 23 | /// shrinks once it is four times what is needed, so instance counts that wobble do not reallocate. | ||
| 24 | class TopLevels { | ||
| 25 | public: | ||
| 26 | TopLevels(DeviceContext& context, const ShaderCompiler& compiler); | ||
| 27 | TopLevels(const TopLevels&) = delete; | ||
| 28 | TopLevels& operator=(const TopLevels&) = delete; | ||
| 29 | |||
| 30 | /// @brief Adds the passes that write the instances and build the top level, after the | ||
| 31 | /// transforms, the instance uploads and the bottom levels' builds. | ||
| 32 | /// @return The top level built, for passes to read with `Use::Trace`. | ||
| 33 | graph::Acceleration AddBuild(graph::Graph& graph, const TransformGraph& transforms, | ||
| 34 | const InstanceTable& instances, const BottomLevels& bottoms); | ||
| 35 | |||
| 36 | /// @return The top level as last built, or null before the first build. | ||
| 37 | 27 | const AccelerationStructure* Structure() const { | |
| 38 | 27 | return top_.get(); | |
| 39 | } | ||
| 40 | |||
| 41 | private: | ||
| 42 | /// Remakes the top level when `count` instances outgrow it or use under a quarter of it. | ||
| 43 | void EnsureCapacity(std::uint32_t count); | ||
| 44 | /// Adds the pass writing each instance's record from its world and shape transforms. | ||
| 45 | void AddWritePass(graph::Graph& graph, const TransformGraph& transforms, | ||
| 46 | const InstanceTable& instances, const BottomLevels& bottoms, | ||
| 47 | graph::Buffer& records) const; | ||
| 48 | graph::Acceleration AddBuildPass(graph::Graph& graph, const BottomLevels& bottoms, | ||
| 49 | graph::Buffer records, std::uint32_t count) const; | ||
| 50 | |||
| 51 | DeviceContext& context_; | ||
| 52 | ComputeKernel writer_; | ||
| 53 | AccelerationPool pool_; | ||
| 54 | std::unique_ptr<AccelerationStructure> top_; | ||
| 55 | }; | ||
| 56 | |||
| 57 | } // namespace ernie | ||
| 58 |