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 using texture_inputs = avnd::texture_input_introspection<Node_T>;
16 std::shared_ptr<Node_T> state;
17 score::gfx::Message m_last_message{};
18 ossia::time_value m_last_time{-1};
19
20 AVND_NO_UNIQUE_ADDRESS texture_inputs_storage<Node_T> texture_ins;
21 AVND_NO_UNIQUE_ADDRESS buffer_inputs_storage<Node_T> buffer_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 GfxRenderer(const GfxNode<Node_T>& p)
28 : score::gfx::OutputNodeRenderer{p}
29 , state{std::make_shared<Node_T>()}
30 {
31 prepareNewState<Node_T>(state, p);
32 }
33
35 renderTargetForInput(const score::gfx::Port& p) override
36 {
37 if constexpr(avnd::texture_input_introspection<Node_T>::size > 0)
38 {
39 auto it = texture_ins.m_rts.find(&p);
40 SCORE_ASSERT(it != texture_ins.m_rts.end());
41 return it->second;
42 }
43 return {};
44 }
45
46 void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override
47 {
48 if constexpr(requires { state->prepare(); })
49 {
50 this->node().processControlIn(
51 *this, *state, m_last_message, this->node().last_message, this->node().m_ctx);
52 state->prepare();
53 }
54
55 // Init input render targets
56 texture_ins.init(*this, renderer);
57 }
58
59 void update(
60 score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res,
61 score::gfx::Edge* edge) override
62 {
63 // FIXME update textures
64 bool updated = false;
65 /*
66 int k = 0;
67 avnd::cpu_texture_input_introspection<Node_T>::for_all(
68 avnd::get_inputs<Node_T>(state), [&]<typename F>(F& t) {
69 if constexpr(requires {
70 t.request_width;
71 t.request_height;
72 })
73 {
74 const auto tex = this->texture(k)->pixelSize();
75 if(tex.width() != t.request_width || tex.height() != t.request_height)
76 {
77 QSize sz{t.request_width, t.request_height};
78
79 // Release
80 auto port = parent.input[k];
81
82 m_rts[port].release();
83 createInput(renderer, k, t.texture, sz);
84
85 t.texture.width = sz.width();
86 t.texture.height = sz.height();
87
88 updated = true;
89 }
90 }
91 k++;
92 });
93*/
94 if(updated)
95 {
96 // We must notify the graph that the previous nodes have to be recomputed
97 }
98 }
99
100 void release(score::gfx::RenderList& r) override
101 {
102 texture_ins.release();
103 }
104
105 void inputAboutToFinish(
106 score::gfx::RenderList& renderer, const score::gfx::Port& p,
107 QRhiResourceUpdateBatch*& res) override
108 {
109 if constexpr(avnd::texture_input_introspection<Node_T>::size > 0 || avnd::buffer_input_introspection<Node_T>::size > 0)
110 {
111 res = renderer.state.rhi->nextResourceUpdateBatch();
112
113 texture_ins.inputAboutToFinish(this->node(), p, res);
114 buffer_ins.inputAboutToFinish(renderer, res, *state, this->node());
115 // buffer_ins.inputAboutToFinish(renderer, res, *state, this->node());
116 }
117 }
118
119 void runInitialPasses(
120 score::gfx::RenderList& renderer, QRhiCommandBuffer& commands,
121 QRhiResourceUpdateBatch*& res, score::gfx::Edge& edge) override
122 {
123 auto& parent = this->node();
124 auto& rhi = *renderer.state.rhi;
125
126 // Insert a synchronisation point to allow readbacks to complete
127 rhi.finish();
128
129 // If we are paused, we don't run the processor implementation.
130 if(parent.last_message.token.date == m_last_time)
131 return;
132 m_last_time = parent.last_message.token.date;
133
134 texture_ins.runInitialPasses(*this, rhi);
135 buffer_ins.readInputBuffers(renderer, parent, *state);
136
137 parent.processControlIn(
138 *this, *state, m_last_message, parent.last_message, parent.m_ctx);
139
140 // Run the processor
141 if_possible((*state)());
142
143 // Copy the data to the model node
144 parent.processControlOut(*this->state);
145 }
146};
147
148template <typename Node_T>
149 requires(
150 (avnd::texture_output_introspection<Node_T>::size + avnd::buffer_output_introspection<Node_T>::size + avnd::geometry_output_introspection<Node_T>::size) == 0
151 )
152struct GfxNode<Node_T> final
153 : CustomGpuOutputNodeBase
154 , GpuNodeElements<Node_T>
155{
156 oscr::ProcessModel<Node_T>& processModel;
157 GfxNode(
159 std::weak_ptr<Execution::ExecutionCommandQueue> q, Gfx::exec_controls ctls,
160 int64_t id, const score::DocumentContext& ctx)
161 : CustomGpuOutputNodeBase{std::move(q), std::move(ctls), ctx}
162 , processModel{element}
163 {
164 this->instance = id;
165
166 initGfxPorts<Node_T>(this, this->input, this->output);
167 }
168
170 createRenderer(score::gfx::RenderList& r) const noexcept override
171 {
172 return new GfxRenderer<Node_T>{*this};
173 }
174};
175}
176#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:97
STL namespace.
Definition DocumentContext.hpp:18
Connection between two score::gfx::Port.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:70
Definition score-plugin-gfx/Gfx/Graph/Node.hpp:50
Port of a score::gfx::Node.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:52
Useful abstraction for storing all the data related to a render target.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:115