MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ download_volume()

std::optional< Kakshya::VolumeData > MayaFlux::IO::download_volume ( const std::shared_ptr< Buffers::VolumeGridBuffer > &  volume,
const std::vector< std::string > &  field_names = {} 
)

Download named fields from a GPU-resident volume into host VolumeData.

Performs one blocking GPU->host transfer per field via VolumeGridBuffer::read_field, reading the current read slot of each. The calling thread must have command queue access, and the call costs a full round trip at each field's byte size. Not for per-frame use on the graphics thread.

Fields with stride sizeof(float) land as scalars. Fields with stride sizeof(glm::vec4) are read into scratch storage and gathered into glm::vec3, discarding the padding component the GPU layout requires and nothing reads. That gather costs a second allocation at four thirds the output size, which is the price of doing the pack on the host.

Any other stride is unrepresentable in VolumeData and is skipped with an error. A named field that was never declared is likewise skipped.

Parameters
volumeVolume to read from.
field_namesFields to download. Empty means every declared field, in declaration order.
Returns
Populated VolumeData, or std::nullopt if nothing was downloaded or the result failed is_consistent().

Definition at line 18 of file VolumeTransfer.cpp.

21{
22 if (!volume) {
23 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
24 "download_volume: null volume");
25 return std::nullopt;
26 }
27
28 const auto names = field_names.empty() ? volume->get_field_names() : field_names;
29 if (names.empty()) {
30 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
31 "download_volume: volume declares no fields");
32 return std::nullopt;
33 }
34
35 Kakshya::VolumeData result;
36 result.lattice = volume->get_lattice();
37 result.fields.reserve(names.size());
38
39 const size_t cells = result.cell_count();
40
41 std::vector<std::string> batch_names;
42 std::vector<std::pair<void*, size_t>> batch_dsts;
43 std::vector<std::vector<glm::vec4>> padded;
44
45 batch_names.reserve(names.size());
46 batch_dsts.reserve(names.size());
47 padded.reserve(names.size());
48
49 for (const auto& name : names) {
50 if (!volume->has_field(name)) {
51 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
52 "download_volume: no field named '{}', skipped", name);
53 continue;
54 }
55
56 const size_t stride = volume->get_field_stride(name);
57
58 Kakshya::VolumeField field;
59 field.name = name;
60 field.semantics = volume->get_field_semantics(name);
61
62 if (stride == sizeof(float)) {
63 field.values = std::vector<float>(cells);
64 result.fields.push_back(std::move(field));
65 auto& values = *result.fields.back().as_scalar();
66 batch_names.push_back(name);
67 batch_dsts.emplace_back(values.data(), cells * sizeof(float));
68 continue;
69 }
70
71 if (stride == sizeof(glm::vec4)) {
72 field.values = std::vector<glm::vec3>(cells);
73 result.fields.push_back(std::move(field));
74 auto& scratch = padded.emplace_back(cells);
75 batch_names.push_back(name);
76 batch_dsts.emplace_back(scratch.data(), cells * sizeof(glm::vec4));
77 continue;
78 }
79
80 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
81 "download_volume: field '{}' has stride {}, which VolumeData "
82 "cannot represent (expected {} or {})",
83 name, stride, sizeof(float), sizeof(glm::vec4));
84 }
85
86 volume->read_fields(batch_names, batch_dsts);
87
88 size_t vector_index = 0;
89 for (auto& field : result.fields) {
90 auto* out = field.as_vector();
91 if (!out) {
92 continue;
93 }
94 const auto& src = padded[vector_index++];
95 for (size_t i = 0; i < cells; ++i) {
96 (*out)[i] = glm::vec3(src[i]);
97 }
98 }
99
100 if (result.fields.empty()) {
101 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
102 "download_volume: no field was downloaded");
103 return std::nullopt;
104 }
105
106 if (!result.is_consistent()) {
107 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
108 "download_volume: resulting VolumeData failed is_consistent()");
109 return std::nullopt;
110 }
111
112 MF_DEBUG(Journal::Component::IO, Journal::Context::FileIO,
113 "download_volume: {}x{}x{} lattice, {} of {} fields",
114 result.lattice.resolution.x, result.lattice.resolution.y,
115 result.lattice.resolution.z, result.fields.size(), names.size());
116
117 return result;
118}
#define MF_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
const uint32_t * src
std::vector< float > * out
std::vector< std::byte > values
Definition VDBWriter.cpp:26
std::string name
Definition VKDevice.cpp:143

References MayaFlux::Kakshya::VolumeData::cell_count(), MayaFlux::Kakshya::VolumeData::fields, MayaFlux::Journal::FileIO, MayaFlux::Journal::IO, MayaFlux::Kakshya::VolumeData::is_consistent(), MayaFlux::Kakshya::VolumeData::lattice, MF_DEBUG, MF_ERROR, name, MayaFlux::Kakshya::VolumeField::name, out, MayaFlux::Kinesis::Lattice3D::resolution, MayaFlux::Kakshya::VolumeField::semantics, src, values, and MayaFlux::Kakshya::VolumeField::values.

Referenced by MayaFlux::IO::VolumeCapture::capture_frame(), MayaFlux::IO::IOManager::save_volume(), and save_volume().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: