Loading...
Searching...
No Matches
CpuAnalysisNode.hpp
1#pragma once
2
3#if SCORE_PLUGIN_GFX
4#include <Crousti/GfxNode.hpp>
5
6namespace oscr
7{
8
9template <typename Node_T>
10 requires(
11 (avnd::texture_output_introspection<Node_T>::size + avnd::buffer_output_introspection<Node_T>::size + avnd::geometry_output_introspection<Node_T>::size) == 0
12 )
13struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
14{
15 std::shared_ptr<Node_T> state;
16 score::gfx::Message m_last_message{};
17 ossia::time_value m_last_time{-1};
18
19 AVND_NO_UNIQUE_ADDRESS texture_inputs_storage<Node_T> texture_ins;
20 AVND_NO_UNIQUE_ADDRESS buffer_inputs_storage<Node_T> buffer_ins;
21 AVND_NO_UNIQUE_ADDRESS geometry_inputs_storage<Node_T> geometry_ins;
22
23 const GfxNode<Node_T>& node() const noexcept
24 {
25 return static_cast<const GfxNode<Node_T>&>(score::gfx::NodeRenderer::node);
26 }
27
28 GfxRenderer(const GfxNode<Node_T>& p)
29 : score::gfx::OutputNodeRenderer{p}
30 , state{std::make_shared<Node_T>()}
31 {
32 prepareNewState<Node_T>(state, p);
33 }
34
36 renderTargetForInput(const score::gfx::Port& p) override
37 {
38 if constexpr(avnd::texture_input_introspection<Node_T>::size > 0)
39 {
40 auto it = texture_ins.m_rts.find(&p);
41 SCORE_ASSERT(it != texture_ins.m_rts.end());
42 return it->second;
43 }
44 return {};
45 }
46
47 void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override
48 {
49 auto& parent = node();
50 if constexpr(requires { state->prepare(); })
51 {
52 this->node().processControlIn(
53 *this, *state, m_last_message, this->node().last_message, this->node().m_ctx);
54 state->prepare();
55 }
56
57 // Init input render targets
58 if constexpr(avnd::texture_input_introspection<Node_T>::size > 0)
59 texture_ins.init(*this, renderer);
60
61 if_possible(state->init(renderer, res));
62 }
63
64 void update(
65 score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res,
66 score::gfx::Edge* e) override
67 {
68 // FIXME update textures
69 bool updated = false;
70 /*
71 int k = 0;
72 avnd::cpu_texture_input_introspection<Node_T>::for_all(
73 avnd::get_inputs<Node_T>(state), [&]<typename F>(F& t) {
74 if constexpr(requires {
75 t.request_width;
76 t.request_height;
77 })
78 {
79 const auto tex = this->texture(k)->pixelSize();
80 if(tex.width() != t.request_width || tex.height() != t.request_height)
81 {
82 QSize sz{t.request_width, t.request_height};
83
84 // Release
85 auto port = parent.input[k];
86
87 m_rts[port].release();
88 createInput(renderer, k, t.texture, sz);
89
90 t.texture.width = sz.width();
91 t.texture.height = sz.height();
92
93 updated = true;
94 }
95 }
96 k++;
97 });
98*/
99 if(updated)
100 {
101 // We must notify the graph that the previous nodes have to be recomputed
102 }
103
104 if_possible(state->update(renderer, res, e));
105 }
106
107 void release(score::gfx::RenderList& r) override
108 {
109 if constexpr(avnd::texture_input_introspection<Node_T>::size > 0)
110 texture_ins.release();
111
112 if constexpr(avnd::geometry_input_introspection<Node_T>::size > 0)
113 geometry_ins.release(r);
114
115 if constexpr(
116 avnd::texture_input_introspection<Node_T>::size > 0
117 || avnd::texture_output_introspection<Node_T>::size > 0)
118 {
119 // FIXME this->defaultRelease(r);
120 }
121
122 if_possible(state->release(r));
123 }
124
125 void inputAboutToFinish(
126 score::gfx::RenderList& renderer, const score::gfx::Port& p,
127 QRhiResourceUpdateBatch*& res) override
128 {
129 if constexpr(
130 avnd::texture_input_introspection<Node_T>::size > 0
131 || avnd::buffer_input_introspection<Node_T>::size > 0
132 || avnd::geometry_input_introspection<Node_T>::size > 0)
133 {
134 res = renderer.state.rhi->nextResourceUpdateBatch();
135
136 if constexpr(avnd::texture_input_introspection<Node_T>::size > 0)
137 texture_ins.inputAboutToFinish(this->node(), p, res);
138 if constexpr(avnd::buffer_input_introspection<Node_T>::size > 0)
139 buffer_ins.inputAboutToFinish(renderer, res, *state, this->node());
140 if constexpr(avnd::geometry_input_introspection<Node_T>::size > 0)
141 geometry_ins.inputAboutToFinish(
142 renderer, res, this->geometry, *state, this->node());
143 }
144
145 if_possible(state->inputAboutToFinish(renderer, p, res));
146 }
147
148 void runInitialPasses(
149 score::gfx::RenderList& renderer, QRhiCommandBuffer& commands,
150 QRhiResourceUpdateBatch*& res, score::gfx::Edge& edge) override
151 {
152 auto& parent = this->node();
153 auto& rhi = *renderer.state.rhi;
154
155 // Insert a synchronisation point to allow readbacks to complete
156 rhi.finish();
157
158 // If we are paused, we don't run the processor implementation.
159 if(parent.last_message.token.date == m_last_time)
160 return;
161 m_last_time = parent.last_message.token.date;
162
163 if constexpr(avnd::texture_input_introspection<Node_T>::size > 0)
164 texture_ins.runInitialPasses(*this, rhi);
165 if constexpr(avnd::buffer_input_introspection<Node_T>::size > 0)
166 buffer_ins.readInputBuffers(renderer, parent, *state);
167 if constexpr(avnd::geometry_input_introspection<Node_T>::size > 0)
168 geometry_ins.readInputGeometries(renderer, this->geometry, parent, *state);
169
170 parent.processControlIn(
171 *this, *state, m_last_message, parent.last_message, parent.m_ctx);
172
173 // Run the processor
174 if_possible(state->runInitialPasses(renderer, commands, res, edge));
175 if_possible((*state)());
176
177 // Copy the data to the model node
178 parent.processControlOut(*this->state);
179 }
180};
181
182template <typename Node_T>
183 requires(
184 (avnd::texture_output_introspection<Node_T>::size + avnd::buffer_output_introspection<Node_T>::size + avnd::geometry_output_introspection<Node_T>::size) == 0
185 )
186struct GfxNode<Node_T> final
187 : CustomGpuOutputNodeBase
188 , GpuNodeElements<Node_T>
189{
190 oscr::ProcessModel<Node_T>& processModel;
191 GfxNode(
193 std::weak_ptr<Execution::ExecutionCommandQueue> q, Gfx::exec_controls ctls,
194 int64_t id, const score::DocumentContext& ctx)
195 : CustomGpuOutputNodeBase{std::move(q), std::move(ctls), ctx}
196 , processModel{element}
197 {
198 this->instance = id;
199
200 initGfxPorts<Node_T>(this, this->input, this->output);
201 }
202
204 createRenderer(score::gfx::RenderList& r) const noexcept override
205 {
206 return new GfxRenderer<Node_T>{*this};
207 }
208};
209}
210#endif
Definition score-plugin-avnd/Crousti/ProcessModel.hpp:86
Definition OutputNode.hpp:11
List of nodes to be rendered to an output.
Definition RenderList.hpp:19
RenderState & state
RenderState corresponding to this RenderList.
Definition RenderList.hpp:94
Definition Factories.hpp:19
Base toolkit upon which the software is built.
Definition Application.cpp:99
STL namespace.
Definition DocumentContext.hpp:18
Connection between two score::gfx::Port.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:71
Definition score-plugin-gfx/Gfx/Graph/Node.hpp:46
Port of a score::gfx::Node.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:53
Useful abstraction for storing all the data related to a render target.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:116