| Line |
Branch |
Exec |
Source |
| 1 |
|
|
// SPDX-License-Identifier: BSD-3-Clause |
| 2 |
|
|
#include "chrono_batch_render/render/render_output.h" |
| 3 |
|
|
|
| 4 |
|
|
#include <condition_variable> |
| 5 |
|
|
#include <cstddef> |
| 6 |
|
|
#include <cstring> |
| 7 |
|
|
#include <deque> |
| 8 |
|
|
#include <exception> |
| 9 |
|
|
#include <fstream> |
| 10 |
|
|
#include <functional> |
| 11 |
|
|
#include <mutex> |
| 12 |
|
|
#include <string> |
| 13 |
|
|
#include <thread> |
| 14 |
|
|
#include <utility> |
| 15 |
|
|
|
| 16 |
|
|
#include <fmt/format.h> |
| 17 |
|
|
|
| 18 |
|
|
#include "chrono_batch_render/device/buffer.h" |
| 19 |
|
|
#include "chrono_batch_render/device/queue.h" |
| 20 |
|
|
#include "chrono_batch_render/io/image.h" |
| 21 |
|
|
#include "chrono_batch_render/util/error.h" |
| 22 |
|
|
#include "chrono_batch_render/util/log.h" |
| 23 |
|
|
#include "chrono_batch_render/util/span.h" |
| 24 |
|
|
#include "chrono_batch_render/util/text.h" |
| 25 |
|
|
|
| 26 |
|
|
namespace chrono::batch_render { |
| 27 |
|
|
|
| 28 |
|
15 |
const RenderVarOutput& FrameOutput::RenderVar(std::string_view path) const { |
| 29 |
|
15 |
const auto found = renderVars.find(path); |
| 30 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 |
if (found == renderVars.end()) { |
| 31 |
0/1
✗ Branch 2 not taken.
|
✗ |
throw Error("The frame has no render var {}", path); |
| 32 |
|
|
} |
| 33 |
|
15 |
return found->second; |
| 34 |
|
|
} |
| 35 |
|
|
|
| 36 |
|
3421 |
const RenderVarOutput& FrameOutput::Source(std::string_view sourceName) const { |
| 37 |
4/4
✓ Branch 0 taken 3420 times.
✓ Branch 1 taken 147 times.
✓ Branch 2 taken 3567 times.
✓ Branch 3 taken 1 time.
|
3568 |
for (const auto& [path, var] : renderVars) { |
| 38 |
2/2
✓ Branch 0 taken 3420 times.
✓ Branch 1 taken 147 times.
|
3567 |
if (var.sourceName == sourceName) { |
| 39 |
|
3420 |
return var; |
| 40 |
|
|
} |
| 41 |
|
|
} |
| 42 |
1/1
✓ Branch 2 taken 1 time.
|
1 |
throw Error("The frame has no render var whose source is {}", sourceName); |
| 43 |
|
|
} |
| 44 |
|
|
|
| 45 |
|
✗ |
IdTexts DecodeIdMap(const device::Tensor& map) { |
| 46 |
|
✗ |
constexpr size_t kRecordWords = 6; |
| 47 |
|
✗ |
const std::vector<std::byte> bytes = map.ToHostBytes(); |
| 48 |
|
✗ |
uint32_t count = 0; |
| 49 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
if (bytes.size() < sizeof(count)) { |
| 50 |
0/1
✗ Branch 1 not taken.
|
✗ |
throw Error("An id map holds at least its {}-byte count, not {} bytes", sizeof(count), |
| 51 |
0/1
✗ Branch 2 not taken.
|
✗ |
bytes.size()); |
| 52 |
|
|
} |
| 53 |
|
✗ |
const size_t texts = bytes.size() - sizeof(count); |
| 54 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
std::memcpy(&count, bytes.data() + texts, sizeof(count)); |
| 55 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
if (size_t(count) * kRecordWords * sizeof(uint32_t) > texts) { |
| 56 |
0/1
✗ Branch 2 not taken.
|
✗ |
throw Error("An id map of {} bytes can't hold {} entries", bytes.size(), count); |
| 57 |
|
|
} |
| 58 |
|
✗ |
IdTexts entries; |
| 59 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
for (uint32_t entry = 0; entry < count; ++entry) { |
| 60 |
|
✗ |
uint32_t record[kRecordWords]; |
| 61 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
std::memcpy(record, bytes.data() + entry * sizeof(record), sizeof(record)); |
| 62 |
|
✗ |
const size_t size = record[4]; |
| 63 |
|
✗ |
const size_t offset = record[5]; |
| 64 |
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
✗ |
if (offset > texts || size > texts - offset) { |
| 65 |
0/1
✗ Branch 2 not taken.
|
✗ |
throw Error("Id map entry {} runs past the map's {} bytes", entry, bytes.size()); |
| 66 |
|
|
} |
| 67 |
0/2
✗ Branch 1 not taken.
✗ Branch 4 not taken.
|
✗ |
entries[{record[0], record[1], record[2], record[3]}] = |
| 68 |
0/1
✗ Branch 1 not taken.
|
✗ |
std::string(reinterpret_cast<const char*>(bytes.data()) + offset, size); |
| 69 |
|
|
} |
| 70 |
|
✗ |
return entries; |
| 71 |
|
✗ |
} |
| 72 |
|
|
|
| 73 |
|
|
namespace { |
| 74 |
|
|
|
| 75 |
|
✗ |
void WriteLabels(const std::filesystem::path& path, const IdMap& map, bool single) { |
| 76 |
|
✗ |
const auto escaped = [](std::string_view text) { |
| 77 |
|
✗ |
std::string result; |
| 78 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
for (const char c : text) { |
| 79 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
if (c == '"' || c == '\\') { |
| 80 |
0/1
✗ Branch 1 not taken.
|
✗ |
result += '\\'; |
| 81 |
0/1
✗ Branch 1 not taken.
|
✗ |
result += c; |
| 82 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
} else if (uint8_t(c) < 0x20) { |
| 83 |
0/1
✗ Branch 1 not taken.
|
✗ |
result += fmt::format("\\u{:04x}", int(c)); |
| 84 |
|
|
} else { |
| 85 |
0/1
✗ Branch 1 not taken.
|
✗ |
result += c; |
| 86 |
|
|
} |
| 87 |
|
|
} |
| 88 |
|
✗ |
return result; |
| 89 |
|
✗ |
}; |
| 90 |
|
✗ |
std::string text = "{"; |
| 91 |
|
✗ |
const char* separator = "\n"; |
| 92 |
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
✗ |
for (const auto& [id, label] : map) { |
| 93 |
|
✗ |
const std::array<uint8_t, 4> color = |
| 94 |
0/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
|
✗ |
IdColor(Span<const uint32_t>(id.data(), single ? 1 : id.size())); |
| 95 |
|
✗ |
const std::string key = single |
| 96 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
? std::to_string(id[0]) |
| 97 |
0/1
✗ Branch 2 not taken.
|
✗ |
: fmt::format("({}, {}, {}, {})", id[0], id[1], id[2], id[3]); |
| 98 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
std::string fields; |
| 99 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
if (!label.path.empty()) { |
| 100 |
0/2
✗ Branch 1 not taken.
✗ Branch 4 not taken.
|
✗ |
fields += fmt::format("\"path\": \"{}\", ", escaped(label.path)); |
| 101 |
|
|
} |
| 102 |
0/1
✗ Branch 1 not taken.
|
✗ |
fields += "\"labels\": {"; |
| 103 |
|
✗ |
const char* comma = ""; |
| 104 |
0/3
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
✗ |
for (const auto& [taxonomy, names] : label.labels) { |
| 105 |
0/2
✗ Branch 1 not taken.
✗ Branch 4 not taken.
|
✗ |
fields += fmt::format("{}\"{}\": [", comma, escaped(taxonomy)); |
| 106 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
for (size_t i = 0; i < names.size(); ++i) { |
| 107 |
0/4
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
|
✗ |
fields += fmt::format("{}\"{}\"", i > 0 ? ", " : "", escaped(names[i])); |
| 108 |
|
|
} |
| 109 |
0/1
✗ Branch 1 not taken.
|
✗ |
fields += "]"; |
| 110 |
|
✗ |
comma = ", "; |
| 111 |
|
|
} |
| 112 |
0/1
✗ Branch 1 not taken.
|
✗ |
text += fmt::format("{} \"{}\": {{{}}}, \"color\": [{}, {}, {}, {}]}}", separator, key, |
| 113 |
0/1
✗ Branch 1 not taken.
|
✗ |
fields, color[0], color[1], color[2], color[3]); |
| 114 |
|
✗ |
separator = ",\n"; |
| 115 |
|
✗ |
} |
| 116 |
0/1
✗ Branch 1 not taken.
|
✗ |
text += "\n}\n"; |
| 117 |
0/1
✗ Branch 1 not taken.
|
✗ |
std::ofstream file(path, std::ios::binary); |
| 118 |
0/1
✗ Branch 1 not taken.
|
✗ |
file << text; |
| 119 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
if (!file) { |
| 120 |
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
|
✗ |
throw Error("Cannot write {}", path.string()); |
| 121 |
|
|
} |
| 122 |
|
✗ |
} |
| 123 |
|
|
|
| 124 |
4/4
chrono::batch_render::Pixels chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::Pixels>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::Pixels const&):
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
chrono::batch_render::device::Tensor chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::device::Tensor>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::device::Tensor const&):
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
16 |
template <class T> T Viewable(std::string_view source, device::DType type, const T& image) { |
| 125 |
6/8
chrono::batch_render::Pixels chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::Pixels>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::Pixels const&):
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
chrono::batch_render::device::Tensor chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::device::Tensor>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::device::Tensor const&):
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
16 |
if (source == "DistanceToCamera" || source == "DistanceToImagePlane" || |
| 126 |
4/8
chrono::batch_render::Pixels chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::Pixels>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::Pixels const&):
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
chrono::batch_render::device::Tensor chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::device::Tensor>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::device::Tensor const&):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
8 |
source == "NormalizedDepth") { |
| 127 |
|
8 |
return ColorizeScalars(image, kDepthColors); |
| 128 |
|
|
} |
| 129 |
2/4
chrono::batch_render::Pixels chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::Pixels>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::Pixels const&):
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
chrono::batch_render::device::Tensor chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::device::Tensor>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::device::Tensor const&):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
8 |
if (source == "Intensity") { |
| 130 |
|
✗ |
return ColorizeScalars(image); |
| 131 |
|
|
} |
| 132 |
2/4
chrono::batch_render::Pixels chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::Pixels>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::Pixels const&):
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
chrono::batch_render::device::Tensor chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::device::Tensor>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::device::Tensor const&):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
8 |
if (source == "RadialVelocity") { |
| 133 |
|
✗ |
return ColorizeScalars(image, {.colormap = Colormap::Turbo, .centered = true}); |
| 134 |
|
|
} |
| 135 |
2/4
chrono::batch_render::Pixels chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::Pixels>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::Pixels const&):
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
chrono::batch_render::device::Tensor chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::device::Tensor>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::device::Tensor const&):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
8 |
if (source == "Normal") { |
| 136 |
|
✗ |
return ColorizeNormals(image); |
| 137 |
|
|
} |
| 138 |
2/4
chrono::batch_render::Pixels chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::Pixels>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::Pixels const&):
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
chrono::batch_render::device::Tensor chrono::batch_render::(anonymous namespace)::Viewable<chrono::batch_render::device::Tensor>(std::basic_string_view<char, std::char_traits<char> >, chrono::batch_render::device::DType, chrono::batch_render::device::Tensor const&):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
8 |
if (type == device::DType::UInt32) { |
| 139 |
|
✗ |
return ColorizeIds(image); |
| 140 |
|
|
} |
| 141 |
|
8 |
return image; |
| 142 |
|
|
} |
| 143 |
|
|
|
| 144 |
|
12 |
std::filesystem::path WriteVar(std::filesystem::path path, const RenderVarOutput& renderVar, |
| 145 |
|
|
const Pixels& image) { |
| 146 |
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
12 |
if (renderVar.idMap && image.type == device::DType::UInt32) { |
| 147 |
0/3
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
|
✗ |
WriteLabels(std::filesystem::path(path).replace_extension(".json"), *renderVar.idMap, |
| 148 |
|
✗ |
image.channels == 1); |
| 149 |
|
|
} |
| 150 |
2/3
✓ Branch 2 taken 12 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
|
36 |
if (Lowercase(path.extension().string()) == ".exr") { |
| 151 |
0/1
✗ Branch 2 not taken.
|
✗ |
return WriteImage(std::move(path), image); |
| 152 |
|
|
} |
| 153 |
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
|
12 |
if (!path.has_extension()) { |
| 154 |
|
✗ |
path += ".png"; |
| 155 |
|
|
} |
| 156 |
1/1
✓ Branch 3 taken 12 times.
|
24 |
return WriteImage(std::move(path), Viewable(renderVar.sourceName, image.type, image)); |
| 157 |
|
|
} |
| 158 |
|
|
|
| 159 |
|
4 |
std::function<Pixels()> Fetch(const device::Tensor& tensor) { |
| 160 |
|
4 |
const Span<const int64_t> shape = tensor.Shape(); |
| 161 |
|
4 |
const Span<const int64_t> strides = tensor.Strides(); |
| 162 |
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 |
bool compact = shape.size() == 2 || shape.size() == 3; |
| 163 |
|
|
int64_t expected = 1; |
| 164 |
3/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 4 times.
|
16 |
for (size_t axis = shape.size(); compact && axis-- > 0;) { |
| 165 |
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 |
compact = shape[axis] <= 1 || strides[axis] == expected; |
| 166 |
|
12 |
expected *= shape[axis]; |
| 167 |
|
|
} |
| 168 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 |
if (!compact) { |
| 169 |
0/2
✗ Branch 1 not taken.
✗ Branch 8 not taken.
|
✗ |
return [pixels = Pixels(tensor)] { return pixels; }; |
| 170 |
|
|
} |
| 171 |
|
4 |
const uint64_t bytes = uint64_t(expected) * device::ElementBytes(tensor.Type()); |
| 172 |
|
4 |
device::Buffer& buffer = tensor.GetBuffer(); |
| 173 |
|
4 |
const device::Download download = |
| 174 |
|
4 |
buffer.GetDevice().GetQueue().ReadAsync(buffer.Slice(tensor.Offset(), bytes)); |
| 175 |
2/2
✓ Branch 5 taken 4 times.
✓ Branch 8 taken 4 times.
|
12 |
return [download, tensor] { |
| 176 |
|
4 |
download.Wait(); |
| 177 |
|
4 |
const Span<const int64_t> sides = tensor.Shape(); |
| 178 |
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 |
return Pixels(download.Bytes(), tensor.Type(), sides[0], sides[1], |
| 179 |
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 |
sides.size() == 3 ? sides[2] : 1); |
| 180 |
1/1
✓ Branch 1 taken 4 times.
|
4 |
}; |
| 181 |
|
4 |
} |
| 182 |
|
|
|
| 183 |
|
|
} |
| 184 |
|
|
|
| 185 |
|
12 |
std::filesystem::path WriteRenderVar(std::filesystem::path path, const RenderVarOutput& renderVar, |
| 186 |
|
|
int64_t camera) { |
| 187 |
2/2
✓ Branch 2 taken 12 times.
✓ Branch 6 taken 12 times.
|
24 |
return WriteVar(std::move(path), renderVar, Pixels(renderVar.tensor.Select(camera))); |
| 188 |
|
|
} |
| 189 |
|
|
|
| 190 |
|
|
namespace { |
| 191 |
|
|
|
| 192 |
|
|
template <class Write> |
| 193 |
|
4 |
std::vector<std::filesystem::path> WriteVars(const std::filesystem::path& directory, |
| 194 |
|
|
const FrameOutput& frame, bool raw, Write write) { |
| 195 |
|
4 |
std::filesystem::create_directories(directory); |
| 196 |
|
4 |
std::vector<std::filesystem::path> written; |
| 197 |
4/4
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
|
12 |
for (const auto& [path, renderVar] : frame.renderVars) { |
| 198 |
2/4
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
8 |
const Span<const int64_t> shape = renderVar.tensor.Shape(); |
| 199 |
2/4
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
8 |
if (shape.size() < 3) { |
| 200 |
|
✗ |
continue; |
| 201 |
|
|
} |
| 202 |
2/2
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✓ Branch 1 taken 2 times.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✓ Branch 1 taken 6 times.
|
8 |
const std::string name = path.substr(path.rfind('/') + 1); |
| 203 |
2/8
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
8 |
const bool exr = raw && renderVar.tensor.Type() != device::DType::UInt8; |
| 204 |
4/4
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
|
24 |
for (int64_t camera = 0; camera < shape[0]; ++camera) { |
| 205 |
8/10
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 6 taken 4 times.
✓ Branch 9 taken 4 times.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 6 taken 12 times.
✓ Branch 9 taken 12 times.
|
48 |
const std::filesystem::path file = |
| 206 |
|
|
directory / fmt::format("{}_{}{}", name, camera, exr ? ".exr" : ".png"); |
| 207 |
2/2
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✓ Branch 1 taken 4 times.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✓ Branch 1 taken 12 times.
|
16 |
write(file, renderVar, camera); |
| 208 |
2/2
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✓ Branch 1 taken 4 times.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✓ Branch 1 taken 12 times.
|
16 |
written.push_back(file); |
| 209 |
|
|
} |
| 210 |
|
|
} |
| 211 |
2/4
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
4 |
if (!frame.overlay.Empty()) { |
| 212 |
0/6
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
|
✗ |
const RenderVarOutput overlay{"overlay", "Overlay", frame.overlay, nullptr}; |
| 213 |
0/4
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 1 not taken.
✗ Branch 2 not taken.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
✗ |
for (int64_t camera = 0; camera < frame.overlay.Shape()[0]; ++camera) { |
| 214 |
0/6
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
|
✗ |
const std::filesystem::path file = directory / fmt::format("overlay_{}.png", camera); |
| 215 |
0/2
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 1 not taken.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 1 not taken.
|
✗ |
write(file, overlay, camera); |
| 216 |
0/2
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::ImageWriter::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 1 not taken.
std::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > chrono::batch_render::(anonymous namespace)::WriteVars<chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}>(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool, chrono::batch_render::WriteFrame(std::filesystem::__cxx11::path const&, chrono::batch_render::FrameOutput const&, bool)::{lambda(std::filesystem::__cxx11::path const&, chrono::batch_render::RenderVarOutput const&, long)#1}):
✗ Branch 1 not taken.
|
✗ |
written.push_back(file); |
| 217 |
|
|
} |
| 218 |
|
✗ |
} |
| 219 |
|
4 |
return written; |
| 220 |
|
✗ |
} |
| 221 |
|
|
|
| 222 |
|
|
} |
| 223 |
|
|
|
| 224 |
|
3 |
std::vector<std::filesystem::path> WriteFrame(const std::filesystem::path& directory, |
| 225 |
|
|
const FrameOutput& frame, bool raw) { |
| 226 |
|
3 |
return WriteVars(directory, frame, raw, |
| 227 |
|
12 |
[](const std::filesystem::path& file, const RenderVarOutput& renderVar, |
| 228 |
1/1
✓ Branch 3 taken 12 times.
|
39 |
int64_t camera) { WriteRenderVar(file, renderVar, camera); }); |
| 229 |
|
|
} |
| 230 |
|
|
|
| 231 |
|
|
struct ImageWriter::State { |
| 232 |
|
|
std::mutex mutex; |
| 233 |
|
|
std::condition_variable changed; |
| 234 |
|
|
std::deque<std::function<void()>> jobs; |
| 235 |
|
|
std::vector<std::thread> threads; |
| 236 |
|
|
uint32_t maxPending = 0; |
| 237 |
|
|
size_t pending = 0; |
| 238 |
|
|
std::exception_ptr error; |
| 239 |
|
|
bool stopping = false; |
| 240 |
|
|
|
| 241 |
|
2 |
void Run() { |
| 242 |
|
2 |
std::unique_lock lock(mutex); |
| 243 |
|
10 |
while (true) { |
| 244 |
5/5
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 4 times.
✓ Branch 5 taken 6 times.
|
21 |
changed.wait(lock, [&] { return stopping || !jobs.empty(); }); |
| 245 |
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
|
6 |
if (jobs.empty()) { |
| 246 |
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 |
return; |
| 247 |
|
|
} |
| 248 |
|
4 |
std::function<void()> job = std::move(jobs.front()); |
| 249 |
|
4 |
jobs.pop_front(); |
| 250 |
1/1
✓ Branch 1 taken 4 times.
|
4 |
lock.unlock(); |
| 251 |
1/1
✓ Branch 1 taken 4 times.
|
4 |
std::exception_ptr failed; |
| 252 |
|
4 |
try { |
| 253 |
1/1
✓ Branch 1 taken 4 times.
|
4 |
job(); |
| 254 |
|
✗ |
} catch (...) { |
| 255 |
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
✗ |
failed = std::current_exception(); |
| 256 |
|
✗ |
} |
| 257 |
|
4 |
job = nullptr; |
| 258 |
1/1
✓ Branch 1 taken 4 times.
|
4 |
lock.lock(); |
| 259 |
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
4 |
if (failed && !error) { |
| 260 |
|
✗ |
error = failed; |
| 261 |
|
|
} |
| 262 |
|
4 |
--pending; |
| 263 |
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 |
changed.notify_all(); |
| 264 |
|
4 |
} |
| 265 |
|
2 |
} |
| 266 |
|
|
|
| 267 |
|
4 |
void Submit(std::function<void()> job) { |
| 268 |
|
4 |
std::unique_lock lock(mutex); |
| 269 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 |
changed.wait(lock, [&] { return pending < maxPending; }); |
| 270 |
|
4 |
++pending; |
| 271 |
1/1
✓ Branch 1 taken 4 times.
|
4 |
jobs.push_back(std::move(job)); |
| 272 |
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 |
changed.notify_all(); |
| 273 |
|
4 |
} |
| 274 |
|
|
|
| 275 |
|
2 |
void Drain() { |
| 276 |
|
2 |
std::unique_lock lock(mutex); |
| 277 |
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
3 |
changed.wait(lock, [&] { return pending == 0; }); |
| 278 |
|
2 |
} |
| 279 |
|
|
}; |
| 280 |
|
|
|
| 281 |
|
1 |
ImageWriter::ImageWriter(uint32_t threads, uint32_t maxPending) |
| 282 |
|
1 |
: m_state(std::make_unique<State>()) { |
| 283 |
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
1 |
if (threads == 0 || maxPending == 0) { |
| 284 |
|
✗ |
throw Error( |
| 285 |
|
|
"An image writer needs at least one thread and one pending write, not {} and {}", |
| 286 |
0/1
✗ Branch 2 not taken.
|
✗ |
threads, maxPending); |
| 287 |
|
|
} |
| 288 |
|
1 |
m_state->maxPending = maxPending; |
| 289 |
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
|
3 |
for (uint32_t i = 0; i < threads; ++i) { |
| 290 |
1/1
✓ Branch 2 taken 2 times.
|
4 |
m_state->threads.emplace_back([state = m_state.get()] { state->Run(); }); |
| 291 |
|
|
} |
| 292 |
|
1 |
} |
| 293 |
|
|
|
| 294 |
|
1 |
ImageWriter::~ImageWriter() { |
| 295 |
|
1 |
m_state->Drain(); |
| 296 |
|
1 |
{ |
| 297 |
|
1 |
const std::lock_guard lock(m_state->mutex); |
| 298 |
|
1 |
m_state->stopping = true; |
| 299 |
|
1 |
} |
| 300 |
|
1 |
m_state->changed.notify_all(); |
| 301 |
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
|
3 |
for (std::thread& thread : m_state->threads) { |
| 302 |
|
2 |
thread.join(); |
| 303 |
|
|
} |
| 304 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 |
if (m_state->error) { |
| 305 |
|
✗ |
try { |
| 306 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
std::rethrow_exception(m_state->error); |
| 307 |
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
✗ |
} catch (const std::exception& error) { |
| 308 |
|
✗ |
Log(LogLevel::Error, "an image writer dropped a failed write: {}", error.what()); |
| 309 |
|
✗ |
} |
| 310 |
|
|
} |
| 311 |
|
1 |
} |
| 312 |
|
|
|
| 313 |
|
✗ |
void ImageWriter::WriteImage(std::filesystem::path path, Pixels image) { |
| 314 |
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
|
✗ |
m_state->Submit([path = std::move(path), image = std::move(image)] { |
| 315 |
0/1
✗ Branch 2 not taken.
|
✗ |
chrono::batch_render::WriteImage(path, image); |
| 316 |
|
✗ |
}); |
| 317 |
|
✗ |
} |
| 318 |
|
|
|
| 319 |
|
✗ |
void ImageWriter::WriteImage(std::filesystem::path path, const device::Tensor& image) { |
| 320 |
0/3
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
|
✗ |
m_state->Submit([path = std::move(path), fetch = Fetch(image)] { |
| 321 |
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
|
✗ |
chrono::batch_render::WriteImage(path, fetch()); |
| 322 |
|
✗ |
}); |
| 323 |
|
✗ |
} |
| 324 |
|
|
|
| 325 |
|
4 |
void ImageWriter::WriteRenderVar(std::filesystem::path path, const RenderVarOutput& renderVar, |
| 326 |
|
|
int64_t camera) { |
| 327 |
|
4 |
const device::Tensor image = renderVar.tensor.Select(camera); |
| 328 |
1/1
✓ Branch 1 taken 4 times.
|
4 |
device::Tensor shown = image; |
| 329 |
3/4
✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
|
12 |
if (Lowercase(path.extension().string()) != ".exr") { |
| 330 |
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 |
if (!path.has_extension()) { |
| 331 |
0/1
✗ Branch 1 not taken.
|
✗ |
path += ".png"; |
| 332 |
|
|
} |
| 333 |
1/1
✓ Branch 1 taken 4 times.
|
4 |
shown = Viewable(renderVar.sourceName, image.Type(), image); |
| 334 |
|
|
} |
| 335 |
|
4 |
const Span<const int64_t> shape = image.Shape(); |
| 336 |
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
4 |
const bool single = shape.size() == 2 || shape[2] == 1; |
| 337 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 |
std::shared_ptr<const IdMap> labels = |
| 338 |
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
4 |
image.Type() == device::DType::UInt32 ? renderVar.idMap : nullptr; |
| 339 |
3/5
✓ Branch 2 taken 4 times.
✓ Branch 5 taken 4 times.
✓ Branch 8 taken 4 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
8 |
m_state->Submit([path = std::move(path), labels = std::move(labels), single, |
| 340 |
|
|
fetch = Fetch(shown)] { |
| 341 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 |
if (labels) { |
| 342 |
0/3
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
|
✗ |
WriteLabels(std::filesystem::path(path).replace_extension(".json"), *labels, single); |
| 343 |
|
|
} |
| 344 |
2/2
✓ Branch 2 taken 4 times.
✓ Branch 5 taken 4 times.
|
12 |
chrono::batch_render::WriteImage(path, fetch()); |
| 345 |
|
4 |
}); |
| 346 |
|
4 |
} |
| 347 |
|
|
|
| 348 |
|
1 |
std::vector<std::filesystem::path> ImageWriter::WriteFrame(const std::filesystem::path& directory, |
| 349 |
|
|
const FrameOutput& frame, bool raw) { |
| 350 |
|
1 |
return WriteVars(directory, frame, raw, |
| 351 |
|
4 |
[this](const std::filesystem::path& file, const RenderVarOutput& renderVar, |
| 352 |
1/1
✓ Branch 3 taken 4 times.
|
9 |
int64_t camera) { WriteRenderVar(file, renderVar, camera); }); |
| 353 |
|
|
} |
| 354 |
|
|
|
| 355 |
|
1 |
void ImageWriter::Wait() { |
| 356 |
|
1 |
m_state->Drain(); |
| 357 |
|
1 |
const std::lock_guard lock(m_state->mutex); |
| 358 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 |
if (m_state->error) { |
| 359 |
|
✗ |
std::exception_ptr error = std::exchange(m_state->error, nullptr); |
| 360 |
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
✗ |
std::rethrow_exception(error); |
| 361 |
|
✗ |
} |
| 362 |
|
1 |
} |
| 363 |
|
|
|
| 364 |
|
1 |
size_t ImageWriter::Pending() const { |
| 365 |
|
1 |
const std::lock_guard lock(m_state->mutex); |
| 366 |
|
1 |
return m_state->pending; |
| 367 |
|
1 |
} |
| 368 |
|
|
|
| 369 |
|
3381 |
const ProductOutput& RenderOutput::operator[](std::string_view product) const { |
| 370 |
|
3381 |
const auto found = m_products.find(product); |
| 371 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3381 times.
|
3381 |
if (found == m_products.end()) { |
| 372 |
0/1
✗ Branch 2 not taken.
|
✗ |
throw Error("The step rendered no product {}", product); |
| 373 |
|
|
} |
| 374 |
|
3381 |
return found->second; |
| 375 |
|
|
} |
| 376 |
|
|
|
| 377 |
|
|
} |
| 378 |
|
|
|