GCC Code Coverage Report


ernie/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
64 / 67
95.5%
Branches:
79 / 144
54.9%
Functions:
18 / 18
100.0%

scene/schema/vol.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 /// @file vol.cpp
3 /// @brief Volumes' and fields' registry entries and extents: fields from their grids' headers,
4 /// volumes from their fields.
5 #include "ernie/scene/schema/vol.h"
6
7 #include "ernie/io/nanovdb.h"
8
9 #include <glm/glm.hpp>
10
11 #include <stdexcept>
12 #include <string>
13 #include <vector>
14
15 namespace ernie {
16 namespace {
17
18 /// @return The bounds of the grid a field selects by name and index from the headers `read`
19 /// returns; empty when it has none, or its source is missing or unreadable (the renderer reports
20 /// those).
21 7 template <typename Read> Box SelectedGrid(const Read& read, std::string_view name, int index) {
22 try {
23
3/4
ernie::Box ernie::(anonymous namespace)::SelectedGrid<ernie::(anonymous namespace)::FileFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1}>(ernie::(anonymous namespace)::FileFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1} const&, std::basic_string_view<char, std::char_traits<char> >, int):
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 time.
ernie::Box ernie::(anonymous namespace)::SelectedGrid<ernie::(anonymous namespace)::NanoVdbFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1}>(ernie::(anonymous namespace)::NanoVdbFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1} const&, std::basic_string_view<char, std::char_traits<char> >, int):
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
7 const std::vector<NanoVdbGrid> heads = read();
24
2/4
ernie::Box ernie::(anonymous namespace)::SelectedGrid<ernie::(anonymous namespace)::FileFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1}>(ernie::(anonymous namespace)::FileFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1} const&, std::basic_string_view<char, std::char_traits<char> >, int):
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
ernie::Box ernie::(anonymous namespace)::SelectedGrid<ernie::(anonymous namespace)::NanoVdbFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1}>(ernie::(anonymous namespace)::NanoVdbFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1} const&, std::basic_string_view<char, std::char_traits<char> >, int):
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
6 const NanoVdbGrid* grid = FindNanoVdbGrid(heads, name, index);
25
4/8
ernie::Box ernie::(anonymous namespace)::SelectedGrid<ernie::(anonymous namespace)::FileFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1}>(ernie::(anonymous namespace)::FileFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1} const&, std::basic_string_view<char, std::char_traits<char> >, int):
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
ernie::Box ernie::(anonymous namespace)::SelectedGrid<ernie::(anonymous namespace)::NanoVdbFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1}>(ernie::(anonymous namespace)::NanoVdbFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1} const&, std::basic_string_view<char, std::char_traits<char> >, int):
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
6 return grid != nullptr ? grid->GridBounds() : Box();
26
1/4
ernie::Box ernie::(anonymous namespace)::SelectedGrid<ernie::(anonymous namespace)::FileFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1}>(ernie::(anonymous namespace)::FileFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1} const&, std::basic_string_view<char, std::char_traits<char> >, int):
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
ernie::Box ernie::(anonymous namespace)::SelectedGrid<ernie::(anonymous namespace)::NanoVdbFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1}>(ernie::(anonymous namespace)::NanoVdbFieldExtent(ernie::ExtentRows const&, ernie::RowRange, std::span<ernie::Box, 18446744073709551615ul>)::{lambda(unsigned int)#1}::operator()(unsigned int) const::{lambda()#1} const&, std::basic_string_view<char, std::char_traits<char> >, int):
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 } catch (const std::runtime_error&) {
27 1 return {};
28 }
29 }
30
31 /// File fields from the file's grid headers, without reading voxels.
32 6 void FileFieldExtent(const ExtentRows& rows, RowRange range, std::span<Box> out) {
33 6 const auto path = rows.Column<Token>(FieldAsset::kFilePath);
34 6 const auto name = rows.Column<Token>(FieldAsset::kFieldName);
35 6 const auto index = rows.Column<std::int32_t>(FieldAsset::kFieldIndex);
36 6 ComputeRows(range, out, [&](std::uint32_t row) {
37
3/4
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 1 time.
18 return SelectedGrid([&] { return ReadNanoVdbHeads(std::string(rows.Text(path[row]))); },
38 6 rows.Text(name[row]), index[row]);
39 });
40 6 }
41
42 /// In-memory NanoVDB fields from their grids' headers; none for grids still on a device.
43 1 void NanoVdbFieldExtent(const ExtentRows& rows, RowRange range, std::span<Box> out) {
44 1 const auto buffer = rows.Column<Tensor>(NanoVDBField::kBuffer);
45 1 const auto name = rows.Column<Token>(NanoVDBField::kFieldName);
46 1 const auto index = rows.Column<std::int32_t>(NanoVDBField::kFieldIndex);
47 1 ComputeRows(range, out, [&](std::uint32_t row) {
48
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 const Tensor& grids = buffer[row];
49
3/6
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
1 if (grids.Empty() || !grids.OnHost() || !grids.IsContiguous()) {
50 ✗ return Box();
51 }
52 1 const std::span<const std::uint8_t> bytes(static_cast<const std::uint8_t*>(grids.Data()),
53 1 static_cast<std::size_t>(grids.Elements()) *
54 1 ByteSize(grids.Type()));
55
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
2 return SelectedGrid([&] { return ParseNanoVdbHeads(bytes); }, rows.Text(name[row]),
56 1 index[row]);
57 });
58 1 }
59
60 /// Dense fields from their shape: values at the voxel size times their indices, grown by a voxel
61 /// for what trilinear sampling reaches.
62 1 void DenseFieldExtent(const ExtentRows& rows, RowRange range, std::span<Box> out) {
63 1 const auto values = rows.Column<Tensor>(DenseField::kValues);
64 1 const auto voxel = rows.Column<double>(DenseField::kVoxelSize);
65 1 ComputeRows(range, out, [&](std::uint32_t row) {
66
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 const Tensor& grid = values[row];
67
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (grid.Rank() != 3) {
68 ✗ return Box();
69 }
70 1 const glm::dvec3 shape(grid.Shape()[0], grid.Shape()[1], grid.Shape()[2]);
71 1 return Box{glm::dvec3(-voxel[row]), shape * voxel[row]};
72 });
73 1 }
74
75 /// Volumes from their fields' extents, each brought into the volume's space.
76 4 void VolumeExtent(const ExtentRows& rows, RowRange range, std::span<Box> out) {
77 4 const Bucket& bucket = rows.store.GetBucket(rows.bucket);
78 4 ComputeRows(range, out, [&](std::uint32_t row) {
79 4 Box box;
80
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 4 times.
64 for (const Column& column : bucket.columns) {
81
5/6
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
64 if (column.values->Type() != ColumnType::Relationship || !column.authored.Test(row) ||
82 4 !rows.Text(column.attribute).starts_with(tokens::kFieldPrefix)) {
83 56 continue;
84 }
85
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (const std::optional<Box> extent = rows.TargetExtent(
86
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 rows.store.Read<Target>(rows.bucket, column.attribute)[row], row)) {
87 4 box.Extend(*extent);
88 }
89 }
90 4 return box;
91 });
92 4 }
93
94 } // namespace
95
96 2 Volume& Volume::SetField(std::string_view name, const Path& field) {
97
3/6
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
8 Edit().Set(Id(), std::string(tokens::kFieldPrefix) + std::string(name), field);
98 2 return *this;
99
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 }
100
101
5/8
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 6 times.
✓ Branch 3 taken 146 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 146 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 146 times.
✗ Branch 10 not taken.
152 ERNIE_DEFINE_SCHEMA(Volume, Concrete, ComputedFromOtherPrims(VolumeExtent), ERNIE_NO_ATTRIBUTES,
102 .openNamespaces = {tokens::kFieldPrefix})
103
4/6
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 438 times.
✓ Branch 3 taken 146 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 146 times.
✗ Branch 7 not taken.
584 ERNIE_DEFINE_SCHEMA(FieldBase, Abstract, kInheritExtent, ERNIE_NO_ATTRIBUTES)
104
12/24
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 146 times.
✓ Branch 3 taken 146 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 146 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 146 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 146 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 146 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 146 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 146 times.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 146 times.
✓ Branch 29 taken 730 times.
✓ Branch 30 taken 146 times.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
1752 ERNIE_DEFINE_SCHEMA(FieldAsset, Abstract, ComputedExtent(FileFieldExtent),
105 ERNIE_FIELD_ASSET_ATTRIBUTES)
106
9/16
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 146 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 146 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 146 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 146 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 146 times.
✓ Branch 19 taken 146 times.
✓ Branch 20 taken 146 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
446 ERNIE_DEFINE_SCHEMA(OpenVDBAsset, Concrete, kInheritExtent, ERNIE_OPENVDB_ASSET_ATTRIBUTES)
107
8/16
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 146 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 146 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 146 times.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 146 times.
✓ Branch 18 taken 438 times.
✓ Branch 19 taken 146 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
1024 ERNIE_DEFINE_SCHEMA(NanoVDBField, Concrete, ComputedExtent(NanoVdbFieldExtent),
108 ERNIE_NANOVDB_FIELD_ATTRIBUTES)
109
8/16
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 146 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 146 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 146 times.
✗ Branch 10 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 146 times.
✓ Branch 18 taken 292 times.
✓ Branch 19 taken 146 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
732 ERNIE_DEFINE_SCHEMA(DenseField, Concrete, ComputedExtent(DenseFieldExtent),
110 ERNIE_DENSE_FIELD_ATTRIBUTES)
111
112 } // namespace ernie
113