MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
DataReadProcessor.hpp
Go to the documentation of this file.
1#pragma once
2
8
9namespace MayaFlux::Buffers {
10
11/**
12 * @brief Reads selected buffer storage into owned host data, one snapshot per request.
13 *
14 * Each read_* call arms one request that runs on the next graphics cycle; the
15 * matching resolve_* call finishes it on the consuming thread, waiting for a
16 * device-local copy when one is in flight. Arm again after resolving to read
17 * every frame.
18 *
19 * Geometry: read_vertices, read_mesh. Pixels: read_host_pixels,
20 * read_texture_pixels. Data: read_bytes, read_buffer, read_field,
21 * read_back_buffer.
22 */
23class MAYAFLUX_API DataReadProcessor : public VKBufferProcessor {
24public:
27
28 /**
29 * @brief Read the attached buffer's primary storage.
30 * @param byte_count Bytes to read, or zero for the full allocation.
31 */
32 void read_bytes(size_t byte_count = 0);
33
34 /**
35 * @brief Read another VKBuffer, such as a descriptor-bound or instance buffer.
36 * @param source Buffer to read; retained until the request runs.
37 * @param byte_count Bytes to read, or zero for its full allocation, which
38 * may exceed the bytes its owner currently fills.
39 */
40 void read_buffer(std::shared_ptr<VKBuffer> source, size_t byte_count = 0);
41
42 /**
43 * @brief Read the current read slot of a named field on the attached buffer.
44 *
45 * Resolves a VolumeGridBuffer field or a NetworkGeometryBuffer state field,
46 * at the time the request runs so a swapped generation is not read stale.
47 */
48 void read_field(std::string name);
49
50 /**
51 * @brief Read a raw back_buffers slot of the attached buffer.
52 * @param index Slot index into its back_buffers.
53 * @param byte_count Bytes to read. A slot does not carry its size, so this
54 * must not exceed what the buffer's owner allocated for it.
55 */
56 void read_back_buffer(size_t index, size_t byte_count);
57
58 /** @brief Read the attached buffer's declared vertices; the layout count may represent capacity. */
59 void read_vertices();
60
61 /**
62 * @brief Read the attached mesh.
63 *
64 * A MeshBuffer, a GeometryBuffer driven by a MeshWriterNode, and a
65 * MeshNetworkBuffer yield a copy of their CPU-authoritative geometry with
66 * no transfer; a network is merged into one mesh with a submesh per slot,
67 * in local space with no transforms applied. A ComputeMeshBuffer or a
68 * VolumeGridBuffer with a surface yields its live vertices as non-indexed
69 * triangles, sized by its live counter rather than its capacity.
70 */
71 void read_mesh();
72
73 /** @brief Read the host pixel data a TextureBuffer retains. */
74 void read_host_pixels();
75
76 /**
77 * @brief Download the base level of a TextureBuffer or NodeTextureBuffer image.
78 *
79 * Blocks the graphics cycle for the transfer, reusing one staging buffer.
80 */
81 void read_texture_pixels();
82
83 /** @brief Whether a requested read has been submitted. */
84 [[nodiscard]] bool has_result() const noexcept;
85
86 /** @brief Whether a read is armed, or its result has not been resolved yet. */
87 [[nodiscard]] bool is_pending() const noexcept;
88
89 /**
90 * @brief Drop read_* calls while a read is armed or unresolved.
91 *
92 * By default a newer read replaces an armed one that has not run yet. With
93 * this set the call is dropped instead, so a caller that re-arms every tick
94 * never displaces a read still in flight. Best effort across the brief
95 * moment a read is running. Set it and call read_* from the consuming thread.
96 */
97 void set_skip_while_pending(bool skip) noexcept { m_skip_while_pending = skip; }
98
99 /**
100 * @brief Finish the read as raw bytes.
101 *
102 * Waits for a device-local transfer when necessary. Call outside the
103 * graphics processing thread. A pixel read yields its raw pixel bytes.
104 * Returns nullopt if no result is pending or the pending result is a
105 * MeshBuffer copy; use resolve_mesh() for that.
106 */
107 [[nodiscard]] std::optional<Kakshya::DataVariant> resolve_bytes();
108
109 /**
110 * @brief Finish a read_vertices() read as typed channels.
111 *
112 * One DataVariant per layout attribute, in layout order (see VertexInsertion).
113 * Returns nullopt, leaving the result pending, when the pending read was
114 * not a vertex read; returns nullopt and discards it when its layout has
115 * an attribute that cannot be decoded. resolve_bytes() still yields the raw
116 * interleaved bytes of any vertex read.
117 */
118 [[nodiscard]] std::optional<std::vector<Kakshya::DataVariant>> resolve_vertices();
119
120 /**
121 * @brief Finish a read_mesh() read as MeshData.
122 *
123 * Returns nullopt, leaving the result pending, when the pending read was
124 * not a mesh read.
125 */
126 [[nodiscard]] std::optional<Kakshya::MeshData> resolve_mesh();
127
128 /**
129 * @brief Finish a pixel read as typed ImageData with its format and dimensions.
130 *
131 * Returns nullopt, leaving the result pending, when the pending read was
132 * not a pixel read.
133 */
134 [[nodiscard]] std::optional<Kakshya::ImageData> resolve_pixels();
135
136 [[nodiscard]] bool is_compatible_with(const std::shared_ptr<Buffer>& buffer) const override;
137
138protected:
139 void on_attach(const std::shared_ptr<Buffer>& buffer) override;
140 void on_detach(const std::shared_ptr<Buffer>& buffer) override;
141 void processing_function(const std::shared_ptr<Buffer>& buffer) override;
142
143private:
144 struct ReadRequest;
145 struct PendingRead;
146 enum class ReadKind { Bytes, Vertices, Mesh, Pixels };
147
148 using ReadFill = std::function<bool(DataReadProcessor&, const std::shared_ptr<VKBuffer>&, PendingRead&)>;
149
150 void arm(ReadFill fill);
151
152 static bool submit_read(
153 PendingRead& pending,
154 std::shared_ptr<VKBuffer>& staging,
155 size_t available_bytes,
156 size_t byte_count,
157 bool mapped,
158 bool transferable);
159
160 std::unique_ptr<PendingRead> collect_result(ReadKind kind);
161
164 std::atomic<bool> m_result_occupied { false };
165 std::atomic<bool> m_result_ready { false };
166 std::shared_ptr<VKBuffer> m_staging;
167 std::shared_ptr<VKBuffer> m_texture_staging;
168 bool m_skip_while_pending {};
169};
170
171}
std::shared_ptr< NetworkGeometryBuffer > buffer
AttributeKind kind
std::string name
Definition VKDevice.cpp:123
uint32_t index
Definition VKDevice.cpp:122
std::shared_ptr< VKBuffer > m_texture_staging
Memory::SweepList< std::unique_ptr< PendingRead > > m_result
Memory::SweepList< ReadRequest > m_request
std::shared_ptr< VKBuffer > m_staging
std::function< bool(DataReadProcessor &, const std::shared_ptr< VKBuffer > &, PendingRead &)> ReadFill
Reads selected buffer storage into owned host data, one snapshot per request.
Lock-free, unbounded, multi-producer collection of in-flight items.
Definition SweepList.hpp:68