bvh/common.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-License-Identifier: BSD-3-Clause | ||
| 2 | #include "chrono_batch_render/bvh/common.h" | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include <numeric> | ||
| 6 | #include <utility> | ||
| 7 | #include <variant> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include "chrono_batch_render/device/device.h" | ||
| 11 | #include "chrono_batch_render/util/log.h" | ||
| 12 | |||
| 13 | namespace chrono::batch_render::bvh { | ||
| 14 | |||
| 15 | using device::Buffer; | ||
| 16 | using device::BufferRange; | ||
| 17 | using device::Device; | ||
| 18 | using device::Traversal; | ||
| 19 | |||
| 20 | 728 | const char* FormatName(Traversal format) { | |
| 21 | 728 | return format == Traversal::Hardware ? "hardware" : "software"; | |
| 22 | } | ||
| 23 | |||
| 24 | 3341 | uint32_t Kind(const Geometry& geometry) { | |
| 25 | 3341 | return std::holds_alternative<device::AccelBoxes>(geometry) ? kBvhBoxes : kBvhTriangles; | |
| 26 | } | ||
| 27 | |||
| 28 | 2013 | uint32_t PrimitiveCount(const Geometry& geometry) { | |
| 29 | 2013 | return std::visit([](const auto& held) { return held.count; }, geometry); | |
| 30 | } | ||
| 31 | |||
| 32 | 121 | device::AccelInput ToAccelInput(const Geometry& geometry) { | |
| 33 | 121 | return std::visit([](const auto& held) -> device::AccelInput { return held; }, geometry); | |
| 34 | } | ||
| 35 | |||
| 36 | 619 | std::vector<Ref<Buffer>> GeometryBuffers(const Geometry& geometry) { | |
| 37 | 619 | std::vector<Ref<Buffer>> buffers; | |
| 38 | 619 | device::ForEachBuffer(geometry, | |
| 39 | 619 | [&](BufferRange range) { buffers.emplace_back(&range.GetBuffer()); }); | |
| 40 | 619 | return buffers; | |
| 41 | ✗ | } | |
| 42 | |||
| 43 | 3238 | uint64_t StorageBytes(uint32_t count, uint32_t kind) { | |
| 44 | 3251 | return BvhLeavesOffset(count) + uint64_t(count) * BvhRecordWords(kind) * 16; | |
| 45 | } | ||
| 46 | |||
| 47 | 3597 | uint64_t Total(std::span<const uint32_t> capacities) { | |
| 48 | 3597 | return std::accumulate(capacities.begin(), capacities.end(), uint64_t(0)); | |
| 49 | } | ||
| 50 | |||
| 51 | 1615 | std::vector<uint32_t> Offsets(std::span<const uint32_t> capacities) { | |
| 52 | 1615 | std::vector<uint32_t> offsets = {0}; | |
| 53 | 3534 | for (const uint32_t capacity : capacities) { | |
| 54 | 1919 | offsets.push_back(offsets.back() + capacity); | |
| 55 | } | ||
| 56 | 1615 | return offsets; | |
| 57 | ✗ | } | |
| 58 | |||
| 59 | 238 | Buffer& Reserve(Device& device, Ref<Buffer>& buffer, const device::BufferDesc& desc) { | |
| 60 | 238 | if (!buffer || buffer->Bytes() < desc.bytes) { | |
| 61 | 230 | Log(LogLevel::Debug, "{} grows from {} to {} bytes", desc.label, | |
| 62 | 115 | buffer ? buffer->Bytes() : 0, desc.bytes); | |
| 63 | 129 | buffer = device.CreateBuffer(desc); | |
| 64 | } | ||
| 65 | 238 | return *buffer; | |
| 66 | } | ||
| 67 | |||
| 68 | 785 | void RequireInstances(const char* what, const Tlas& tlas, BufferRange instances) { | |
| 69 | 785 | const uint64_t total = Total(tlas.Capacities()); | |
| 70 | 785 | const uint64_t bytes = total * sizeof(InstanceRecord); | |
| 71 | 785 | if (instances.Bytes() < bytes) { | |
| 72 | 1 | throw Error("{} of a TLAS of {} instances from {} bytes; it takes {}", what, total, | |
| 73 | 1 | instances.Bytes(), bytes); | |
| 74 | } | ||
| 75 | 784 | } | |
| 76 | |||
| 77 | 784 | std::vector<uint32_t> SelectWorlds(const char* what, const Tlas& tlas, | |
| 78 | std::span<const uint32_t> worlds) { | ||
| 79 | 784 | if (worlds.empty()) { | |
| 80 | 1 | std::vector<uint32_t> all(tlas.Count()); | |
| 81 | 1 | std::iota(all.begin(), all.end(), 0u); | |
| 82 | 1 | return all; | |
| 83 | 1 | } | |
| 84 | 783 | std::vector<bool> seen(tlas.Count(), false); | |
| 85 | 1691 | for (const uint32_t world : worlds) { | |
| 86 | 910 | if (world >= tlas.Count()) { | |
| 87 | 1 | throw Error("{} of world {} of a TLAS of {} worlds", what, world, tlas.Count()); | |
| 88 | } | ||
| 89 | 909 | if (seen[world]) { | |
| 90 | 1 | throw Error("{} of world {} twice", what, world); | |
| 91 | } | ||
| 92 | 908 | seen[world] = true; | |
| 93 | } | ||
| 94 | 783 | return {worlds.begin(), worlds.end()}; | |
| 95 | 781 | } | |
| 96 | |||
| 97 | 121 | void RequireRefittable(const char* what, const device::AccelInput& input) { | |
| 98 | 242 | if (!device::Refittable(input)) { | |
| 99 | 1 | throw Error("{} of a BLAS that wasn't made refittable", what); | |
| 100 | } | ||
| 101 | 120 | } | |
| 102 | |||
| 103 | 222 | Ref<Buffer> Tables::Upload(Device& device, std::string label) const { | |
| 104 | 444 | return device.CreateBuffer({.label = std::move(label)}, std::span<const std::byte>(m_bytes)); | |
| 105 | 222 | } | |
| 106 | |||
| 107 | } | ||
| 108 |