Skip to content

Commit 4242de2

Browse files
committed
avnd: gpu worker: concurrency fix
1 parent 116c630 commit 4242de2

8 files changed

Lines changed: 91 additions & 78 deletions

File tree

src/plugins/score-plugin-avnd/AvndProcesses/Interpolator.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
#pragma once
2+
#include <ossia/network/value/value.hpp>
3+
24
#include <halp/controls.hpp>
35
#include <halp/dynamic_port.hpp>
46
#include <halp/meta.hpp>
5-
#include <ossia/network/value/value.hpp>
7+
8+
#include <cmath>
9+
10+
#include <algorithm>
611

712
namespace avnd_tools
813
{

src/plugins/score-plugin-avnd/Crousti/CpuAnalysisNode.hpp

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ template <typename Node_T>
1313
struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
1414
{
1515
using texture_inputs = avnd::texture_input_introspection<Node_T>;
16-
Node_T state;
16+
std::shared_ptr<Node_T> state;
1717
score::gfx::Message m_last_message{};
1818
ossia::small_flat_map<const score::gfx::Port*, score::gfx::TextureRenderTarget, 2>
1919
m_rts;
@@ -27,9 +27,10 @@ struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
2727
}
2828
GfxRenderer(const GfxNode<Node_T>& p)
2929
: score::gfx::OutputNodeRenderer{p}
30+
, state{std::make_shared<Node_T>()}
3031
, m_readbacks(texture_inputs::size)
3132
{
32-
prepareNewState(state, p);
33+
prepareNewState<Node_T>(state, p);
3334
}
3435

3536
score::gfx::TextureRenderTarget
@@ -86,17 +87,18 @@ struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
8687

8788
void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override
8889
{
89-
if constexpr(requires { state.prepare(); })
90+
if constexpr(requires { state->prepare(); })
9091
{
9192
this->node().processControlIn(
92-
*this, state, m_last_message, this->node().last_message, this->node().m_ctx);
93-
state.prepare();
93+
*this, *state, m_last_message, this->node().last_message, this->node().m_ctx);
94+
state->prepare();
9495
}
9596

9697
// Init input render targets
9798
int k = 0;
9899
avnd::cpu_texture_input_introspection<Node_T>::for_all(
99-
avnd::get_inputs<Node_T>(state), [&]<typename F>(F& t) {
100+
avnd::get_inputs<Node_T>(*state),
101+
[&]<typename F>(F& t) {
100102
// FIXME k isn't the port index, it's the texture port index
101103
auto spec = this->node().resolveRenderTargetSpecs(k, renderer);
102104
if constexpr(requires {
@@ -114,7 +116,7 @@ struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
114116
t.texture.height = spec.size.height();
115117
}
116118
k++;
117-
});
119+
});
118120
}
119121

120122
void update(
@@ -207,28 +209,28 @@ struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
207209
// "completed" callback.
208210
int k = 0;
209211
avnd::cpu_texture_input_introspection<Node_T>::for_all(
210-
avnd::get_inputs<Node_T>(state), [&](auto& t) {
211-
loadInputTexture(rhi, t.texture, k);
212-
k++;
213-
});
212+
avnd::get_inputs<Node_T>(*state), [&](auto& t) {
213+
loadInputTexture(rhi, t.texture, k);
214+
k++;
215+
});
214216
}
215217

216218
parent.processControlIn(
217-
*this, state, m_last_message, parent.last_message, parent.m_ctx);
219+
*this, *state, m_last_message, parent.last_message, parent.m_ctx);
218220

219221
// Run the processor
220-
state();
222+
(*state)();
221223

222224
// Copy the data to the model node
223-
parent.processControlOut(this->state);
225+
parent.processControlOut(*this->state);
224226

225227
// Copy the geometry
226228
// FIXME we need something such as port_run_{pre,post}process for GPU nodes
227229
avnd::geometry_output_introspection<Node_T>::for_all_n2(
228-
state.outputs, [&]<std::size_t F, std::size_t P>(
229-
auto& t, avnd::predicate_index<P>, avnd::field_index<F>) {
230-
postprocess_geometry(t);
231-
});
230+
state->outputs, [&]<std::size_t F, std::size_t P>(
231+
auto& t, avnd::predicate_index<P>, avnd::field_index<F>) {
232+
postprocess_geometry(t);
233+
});
232234
}
233235
template <avnd::geometry_port Field>
234236
void postprocess_geometry(Field& ctrl)

src/plugins/score-plugin-avnd/Crousti/CpuFilterNode.hpp

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
1414
{
1515
using texture_inputs = avnd::texture_input_introspection<Node_T>;
1616
using texture_outputs = avnd::texture_output_introspection<Node_T>;
17-
Node_T state;
17+
std::shared_ptr<Node_T> state;
1818
score::gfx::Message m_last_message{};
1919
ossia::small_flat_map<const score::gfx::Port*, score::gfx::TextureRenderTarget, 2>
2020
m_rts;
@@ -29,9 +29,10 @@ struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
2929

3030
GfxRenderer(const GfxNode<Node_T>& p)
3131
: score::gfx::GenericNodeRenderer{p}
32+
, state{std::make_shared<Node_T>()}
3233
, m_readbacks(texture_inputs::size)
3334
{
34-
prepareNewState(state, p);
35+
prepareNewState<Node_T>(state, p);
3536
}
3637

3738
score::gfx::TextureRenderTarget
@@ -165,11 +166,11 @@ struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
165166
void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override
166167
{
167168
auto& parent = node();
168-
if constexpr(requires { state.prepare(); })
169+
if constexpr(requires { state->prepare(); })
169170
{
170171
parent.processControlIn(
171-
*this, state, m_last_message, parent.last_message, parent.m_ctx);
172-
state.prepare();
172+
*this, *state, m_last_message, parent.last_message, parent.m_ctx);
173+
state->prepare();
173174
}
174175

175176
const auto& mesh = renderer.defaultTriangle();
@@ -185,7 +186,8 @@ struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
185186
// Init input render targets
186187
int k = 0;
187188
avnd::cpu_texture_input_introspection<Node_T>::for_all(
188-
avnd::get_inputs<Node_T>(state), [&]<typename F>(F& t) {
189+
avnd::get_inputs<Node_T>(*state),
190+
[&]<typename F>(F& t) {
189191
// FIXME k isn't the port index, it's the texture port index
190192
auto spec = this->node().resolveRenderTargetSpecs(k, renderer);
191193
if constexpr(requires {
@@ -203,13 +205,13 @@ struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
203205
t.texture.height = spec.size.height();
204206
}
205207
k++;
206-
});
208+
});
207209
}
208210

209211
{
210212
// Init textures for the outputs
211213
avnd::cpu_texture_output_introspection<Node_T>::for_all(
212-
avnd::get_outputs<Node_T>(state), [&](auto& t) {
214+
avnd::get_outputs<Node_T>(*state), [&](auto& t) {
213215
createOutput(renderer, t.texture, QSize{t.texture.width, t.texture.height});
214216
});
215217
}
@@ -282,23 +284,23 @@ struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
282284
// "completed" callback.
283285
int k = 0;
284286
avnd::cpu_texture_input_introspection<Node_T>::for_all(
285-
avnd::get_inputs<Node_T>(state), [&](auto& t) {
286-
loadInputTexture(rhi, t.texture, k);
287-
k++;
288-
});
287+
avnd::get_inputs<Node_T>(*state), [&](auto& t) {
288+
loadInputTexture(rhi, t.texture, k);
289+
k++;
290+
});
289291
}
290292

291293
parent.processControlIn(
292-
*this, state, m_last_message, parent.last_message, parent.m_ctx);
294+
*this, *state, m_last_message, parent.last_message, parent.m_ctx);
293295

294296
// Run the processor
295-
state();
297+
(*state)();
296298

297299
// Upload output textures
298300
{
299301
int k = 0;
300302
avnd::cpu_texture_output_introspection<Node_T>::for_all(
301-
avnd::get_outputs<Node_T>(state), [&](auto& t) {
303+
avnd::get_outputs<Node_T>(*state), [&](auto& t) {
302304
uploadOutputTexture(renderer, k, t.texture, res);
303305
k++;
304306
});
@@ -308,7 +310,7 @@ struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
308310
}
309311

310312
// Copy the data to the model node
311-
parent.processControlOut(this->state);
313+
parent.processControlOut(*this->state);
312314
}
313315
};
314316

src/plugins/score-plugin-avnd/Crousti/CpuGeneratorNode.hpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ template <typename Node_T>
1313
struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
1414
{
1515
using texture_outputs = avnd::texture_output_introspection<Node_T>;
16-
Node_T state;
16+
std::shared_ptr<Node_T> state;
1717
score::gfx::Message m_last_message{};
1818
ossia::time_value m_last_time{-1};
1919

@@ -24,8 +24,9 @@ struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
2424

2525
GfxRenderer(const GfxNode<Node_T>& p)
2626
: score::gfx::GenericNodeRenderer{p}
27+
, state{std::make_shared<Node_T>()}
2728
{
28-
prepareNewState(state, p);
29+
prepareNewState<Node_T>(state, p);
2930
}
3031

3132
score::gfx::TextureRenderTarget
@@ -122,11 +123,11 @@ struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
122123
void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override
123124
{
124125
auto& parent = node();
125-
if constexpr(requires { state.prepare(); })
126+
if constexpr(requires { state->prepare(); })
126127
{
127128
parent.processControlIn(
128-
*this, state, m_last_message, parent.last_message, parent.m_ctx);
129-
state.prepare();
129+
*this, *state, m_last_message, parent.last_message, parent.m_ctx);
130+
state->prepare();
130131
}
131132

132133
const auto& mesh = renderer.defaultTriangle();
@@ -139,7 +140,7 @@ struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
139140

140141
// Init textures for the outputs
141142
avnd::cpu_texture_output_introspection<Node_T>::for_all(
142-
avnd::get_outputs<Node_T>(state), [&](auto& t) {
143+
avnd::get_outputs<Node_T>(*state), [&](auto& t) {
143144
createOutput(renderer, t.texture, QSize{t.texture.width, t.texture.height});
144145
});
145146

@@ -179,15 +180,15 @@ struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
179180
m_last_time = parent.last_message.token.date;
180181

181182
parent.processControlIn(
182-
*this, state, m_last_message, parent.last_message, parent.m_ctx);
183+
*this, *state, m_last_message, parent.last_message, parent.m_ctx);
183184

184185
// Run the processor
185-
state();
186+
(*state)();
186187

187188
// Upload output textures
188189
int k = 0;
189190
avnd::cpu_texture_output_introspection<Node_T>::for_all(
190-
avnd::get_outputs<Node_T>(state), [&](auto& t) {
191+
avnd::get_outputs<Node_T>(*state), [&](auto& t) {
191192
uploadOutputTexture(renderer, k, t.texture, res);
192193
k++;
193194
});
@@ -196,7 +197,7 @@ struct GfxRenderer<Node_T> final : score::gfx::GenericNodeRenderer
196197
res = renderer.state.rhi->nextResourceUpdateBatch();
197198

198199
// Copy the data to the model node
199-
parent.processControlOut(this->state);
200+
parent.processControlOut(*this->state);
200201
}
201202
};
202203

src/plugins/score-plugin-avnd/Crousti/GpuComputeNode.hpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ struct GpuComputeRenderer final : ComputeRendererBaseType<Node_T>
5252
{
5353
using texture_inputs = avnd::gpu_image_input_introspection<Node_T>;
5454
using texture_outputs = avnd::gpu_image_output_introspection<Node_T>;
55-
Node_T state;
55+
std::shared_ptr<Node_T> state;
5656
score::gfx::Message m_last_message{};
5757
ossia::small_flat_map<const score::gfx::Port*, score::gfx::TextureRenderTarget, 2>
5858
m_rts;
@@ -84,8 +84,9 @@ struct GpuComputeRenderer final : ComputeRendererBaseType<Node_T>
8484

8585
GpuComputeRenderer(const GpuComputeNode<Node_T>& p)
8686
: ComputeRendererBaseType<Node_T>{p}
87+
, state{std::make_shared<Node_T>()}
8788
{
88-
prepareNewState(state, p);
89+
prepareNewState<Node_T>(state, p);
8990
}
9091

9192
score::gfx::TextureRenderTarget
@@ -229,11 +230,11 @@ struct GpuComputeRenderer final : ComputeRendererBaseType<Node_T>
229230
void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override
230231
{
231232
auto& parent = node();
232-
if constexpr(requires { state.prepare(); })
233+
if constexpr(requires { state->prepare(); })
233234
{
234235
parent.processControlIn(
235-
*this, state, m_last_message, parent.last_message, parent.m_ctx);
236-
state.prepare();
236+
*this, *state, m_last_message, parent.last_message, parent.m_ctx);
237+
state->prepare();
237238
}
238239

239240
// Create the global shared inputs
@@ -260,7 +261,7 @@ struct GpuComputeRenderer final : ComputeRendererBaseType<Node_T>
260261
{
261262
// First copy all the "public" uniforms to their space in memory
262263
avnd::gpu_uniform_introspection<Node_T>::for_all(
263-
avnd::get_inputs<Node_T>(state), [&]<avnd::uniform_port F>(const F& t) {
264+
avnd::get_inputs<Node_T>(*state), [&]<avnd::uniform_port F>(const F& t) {
264265
using uniform_type =
265266
typename avnd::member_reflection<F::uniform()>::member_type;
266267
using ubo_type = typename avnd::member_reflection<F::uniform()>::class_type;
@@ -284,7 +285,7 @@ struct GpuComputeRenderer final : ComputeRendererBaseType<Node_T>
284285
{
285286
bool srb_touched{false};
286287
tmp.assign(m_srb->cbeginBindings(), m_srb->cendBindings());
287-
for(auto& promise : state.update())
288+
for(auto& promise : state->update())
288289
{
289290
using ret_type = decltype(promise.feedback_value);
290291
gpp::qrhi::handle_update<GpuComputeRenderer, ret_type> handler{
@@ -340,12 +341,12 @@ struct GpuComputeRenderer final : ComputeRendererBaseType<Node_T>
340341
// Release the object's internal states
341342
if constexpr(requires { &Node_T::release; })
342343
{
343-
for(auto& promise : state.release())
344+
for(auto& promise : state->release())
344345
{
345346
gpp::qrhi::handle_release handler{*r.state.rhi};
346347
visit(handler, promise.current_command);
347348
}
348-
state.release();
349+
state->release();
349350
}
350351

351352
// Release the allocated textures
@@ -393,13 +394,13 @@ struct GpuComputeRenderer final : ComputeRendererBaseType<Node_T>
393394

394395
// Apply the controls
395396
parent.processControlIn(
396-
*this, this->state, m_last_message, parent.last_message, parent.m_ctx);
397+
*this, *this->state, m_last_message, parent.last_message, parent.m_ctx);
397398

398399
// Run the compute shader
399400
{
400401
SCORE_ASSERT(this->m_pipeline);
401402
SCORE_ASSERT(this->m_pipeline->shaderResourceBindings());
402-
for(auto& promise : this->state.dispatch())
403+
for(auto& promise : this->state->dispatch())
403404
{
404405
using ret_type = decltype(promise.feedback_value);
405406
gpp::qrhi::handle_dispatch<GpuComputeRenderer, ret_type> handler{
@@ -419,7 +420,7 @@ struct GpuComputeRenderer final : ComputeRendererBaseType<Node_T>
419420
this->texReadbacks.clear();
420421

421422
// Copy the data to the model node
422-
parent.processControlOut(this->state);
423+
parent.processControlOut(*this->state);
423424
}
424425

425426
void runInitialPasses(

0 commit comments

Comments
 (0)