MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
GeometryReadbackNode.hpp
Go to the documentation of this file.
1#pragma once
2
4
6
7namespace MayaFlux::Buffers {
8class VKBuffer;
9} // namespace MayaFlux::Buffers
10
12
13/**
14 * @class GeometryReadbackNode
15 * @brief GeometryWriterNode that downloads vertex data from a GPU buffer each frame.
16 *
17 * Symmetric to ComputeOutNode but for vertex buffers. Each compute_frame()
18 * derives the current vertex count from the buffer's resident byte size,
19 * issues a synchronous GPU-to-CPU transfer, and re-emits the result into
20 * the inherited vertex buffer so the node can be placed directly in a
21 * GeometryBuffer for a second render target.
22 *
23 * Intended for closing visual-to-audio and visual-to-visual feedback loops:
24 * positions produced by a GPU geometry pass (SDF mesh, mesh deformation,
25 * particle simulation) become inputs to the node graph or a second window
26 * on the next cycle.
27 *
28 * Vertex count is derived fresh each frame from get_size_bytes() so dynamic
29 * geometry (SDF, marching cubes) that changes triangle count per frame is
30 * handled without stale sizing.
31 *
32 * The download is synchronous (execute_immediate_commands). Use at
33 * VISUAL_RATE. For high-frequency readback a double-buffered async path
34 * would be required.
35 *
36 * Usage - second window from SDF mesh:
37 * @code
38 * auto readback = std::make_shared<GeometryReadbackNode>(mesh_buf) | Graphics;
39 * auto buf2 = vega.GeometryBuffer(readback) | Graphics;
40 * buf2->setup_rendering({ .target_window = window2 });
41 * @endcode
42 *
43 * Usage - positions into audio:
44 * @code
45 * auto readback = std::make_shared<GeometryReadbackNode>(mesh_buf);
46 * schedule_metro(1.0 / 60.0, [readback]() {
47 * readback->compute_frame();
48 * glm::vec3 p = readback->get_position(0);
49 * }, "readback", Vruta::ProcessingToken::FRAME_ACCURATE);
50 * @endcode
51 */
52class MAYAFLUX_API GeometryReadbackNode : public GeometryWriterNode {
53public:
54 /**
55 * @brief Construct from a GPU vertex buffer.
56 *
57 * @param buffer GPU vertex buffer to download from. Must remain
58 * valid for the lifetime of this node.
59 * @param vertex_count Expected number of MeshVertex elements. Used to
60 * size the readback vector. If 0, the count is
61 * derived from buffer->get_size_bytes().
62 */
63 explicit GeometryReadbackNode(
64 std::shared_ptr<Buffers::VKBuffer> buffer,
65 size_t vertex_count = 0);
66
67 /**
68 * @brief Suppress automatic compute_frame() invocation by the node graph.
69 *
70 * GeometryReadbackNode::compute_frame() issues a synchronous GPU-to-CPU
71 * transfer via download_from_gpu_async. Calling it from the graphics thread
72 * (which is what GpuSync::process_sample does when the node is registered
73 * at VISUAL_RATE) produces undefined behaviour due to re-entrant queue
74 * submission. The node must be driven manually from a FRAME_ACCURATE metro
75 * that runs on the scheduler thread.
76 *
77 * @return Always 0.0.
78 */
79 double process_sample(double /*input*/) override { return 0.0; }
80
81 /**
82 * @brief Download vertex data from GPU to CPU.
83 *
84 * Issues a synchronous GPU-to-CPU transfer. Safe to call at VISUAL_RATE
85 * from a FRAME_ACCURATE metro callback.
86 */
87 void compute_frame() override;
88
89 /**
90 * @brief Downloaded vertex array from the last compute_frame() call.
91 */
92 [[nodiscard]] const std::vector<Kakshya::MeshVertex>& get_vertices() const
93 {
94 return m_vertices;
95 }
96
97 /**
98 * @brief Position of vertex at index, or zero if out of range.
99 */
100 [[nodiscard]] glm::vec3 get_position(size_t index) const;
101
103 {
104 return Portal::Graphics::PrimitiveTopology::TRIANGLE_LIST;
105 }
106
107private:
108 std::shared_ptr<Buffers::VKBuffer> m_gpu_buffer;
109 std::shared_ptr<Buffers::VKBuffer> m_staging_buffer;
110 std::vector<Kakshya::MeshVertex> m_vertices;
111};
112
113} // namespace MayaFlux::Nodes::GpuSync
const std::vector< Kakshya::MeshVertex > & get_vertices() const
Downloaded vertex array from the last compute_frame() call.
Portal::Graphics::PrimitiveTopology get_primitive_topology() const override
Get primitive topology for rendering.
std::shared_ptr< Buffers::VKBuffer > m_gpu_buffer
double process_sample(double) override
Suppress automatic compute_frame() invocation by the node graph.
std::shared_ptr< Buffers::VKBuffer > m_staging_buffer
GeometryWriterNode that downloads vertex data from a GPU buffer each frame.
Base class for nodes that generate 3D geometry data.
PrimitiveTopology
Vertex assembly primitive topology.