Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,6 @@
[submodule "3rdparty/opengametools"]
path = 3rdparty/opengametools
url = https://github.com/jpaver/opengametools
[submodule "3rdparty/OffsetAllocator"]
path = 3rdparty/OffsetAllocator
url = https://github.com/sebbbi/OffsetAllocator
1 change: 1 addition & 0 deletions 3rdparty/OffsetAllocator
Submodule OffsetAllocator added at 3610a7
30 changes: 29 additions & 1 deletion src/plugins/score-plugin-avnd/Crousti/Concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,35 @@ make_control_in(avnd::field_index<N>, Id<Process::Port>&& id, QObject* parent)
auto [Mx, My, Mz] = c.max;
auto [ix, iy, iz] = c.init;
return new Process::XYZSpinboxes{{mx, my, mz}, {Mx, My, Mz}, {ix, iy, iz},
qname, id, parent};
false, qname, id, parent};
}
}
else if constexpr(widg.widget == avnd::widget_type::xyzw_spinbox)
{
static constexpr auto c = avnd::get_range<T>();
if constexpr(requires {
c.min == 0.f;
c.max == 0.f;
c.init == 0.f;
})
{
return new Process::XYZSpinboxes{
{c.min, c.min, c.min},
{c.max, c.max, c.max},
{c.init, c.init, c.init},
false,
qname,
id,
parent};
}
else
{
auto [mx, my, mz, mw] = c.min;
auto [Mx, My, Mz, Mw] = c.max;
auto [ix, iy, iz, iw] = c.init;
// FIXME we don't have a good 4-way widget
return new Process::XYZSpinboxes{{mx, my, mz}, {Mx, My, Mz}, {ix, iy, iz},
false, qname, id, parent};
}
}
else if constexpr(widg.widget == avnd::widget_type::color)
Expand Down
83 changes: 73 additions & 10 deletions src/plugins/score-plugin-avnd/Crousti/CpuAnalysisNode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

namespace oscr
{

template <typename Node_T>
requires(
(avnd::texture_output_introspection<Node_T>::size + avnd::buffer_output_introspection<Node_T>::size + avnd::geometry_output_introspection<Node_T>::size) == 0
(avnd::texture_output_introspection<Node_T>::size + avnd::buffer_output_introspection<Node_T>::size + avnd::geometry_output_introspection<Node_T>::size + scene_output_introspection<Node_T>::size) == 0
&& (avnd::gpu_render_target_output_port_output_introspection<Node_T>::size == 0)
)
struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
{
Expand All @@ -19,6 +19,7 @@ struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
AVND_NO_UNIQUE_ADDRESS texture_inputs_storage<Node_T> texture_ins;
AVND_NO_UNIQUE_ADDRESS buffer_inputs_storage<Node_T> buffer_ins;
AVND_NO_UNIQUE_ADDRESS geometry_inputs_storage<Node_T> geometry_ins;
AVND_NO_UNIQUE_ADDRESS scene_inputs_storage<Node_T> scene_ins;

const GfxNode<Node_T>& node() const noexcept
{
Expand All @@ -44,9 +45,19 @@ struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
return {};
}

void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override
// See CpuFilterNode.hpp for the reasoning: init must live in initState
// so the incremental edge-rewire path also runs it.
void initState(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override
{
auto& parent = node();
if(m_initialized)
return;

// See CpuFilterNode for the reasoning: optional renderlist
// backchannel populated via SFINAE so nodes can reach the
// RenderList's GpuResourceRegistry / AssetTable without plumbing.
if constexpr(requires { state->renderlist = &renderer; })
state->renderlist = &renderer;

if constexpr(requires { state->prepare(); })
{
this->node().processControlIn(
Expand All @@ -59,6 +70,13 @@ struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
texture_ins.init(*this, renderer);

if_possible(state->init(renderer, res));

m_initialized = true;
}

void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override
{
initState(renderer, res);
}

void update(
Expand All @@ -82,32 +100,69 @@ struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
}
}

void release(score::gfx::RenderList& r) override
void releaseState(score::gfx::RenderList& r) override
{
if(!m_initialized)
return;

if constexpr(avnd::texture_input_introspection<Node_T>::size > 0)
texture_ins.release();

if constexpr(avnd::geometry_input_introspection<Node_T>::size > 0)
geometry_ins.release(r);

if constexpr(scene_input_introspection<Node_T>::size > 0)
scene_ins.release(r);

if constexpr(
avnd::texture_input_introspection<Node_T>::size > 0
|| avnd::texture_output_introspection<Node_T>::size > 0)
{
// FIXME this->defaultRelease(r);
// No call-through to GenericNodeRenderer::defaultRelease here:
// CpuAnalysisNode's GfxRenderer derives from OutputNodeRenderer,
// not GenericNodeRenderer, and OutputNodeRenderer has no
// defaultRelease equivalent (it owns no pipeline / passes — it
// is a sink, not a node renderer with m_p / m_pipelineCache).
// CpuFilterNode's mirror at line ~357 IS valid because that
// GfxRenderer derives from GenericNodeRenderer.
//
// If a future CpuAnalysisNode uses textures via OutputNodeRenderer
// surfaces, they'll need their own per-storage release path
// (texture_ins.release above already handles texture INPUTS).
}

if_possible(state->release(r));

// Clear the optional renderlist backchannel. Paired with initState;
// same SFINAE guard.
if constexpr(requires { state->renderlist = nullptr; })
state->renderlist = nullptr;

m_initialized = false;
}

void release(score::gfx::RenderList& r) override
{
releaseState(r);
}

void inputAboutToFinish(
score::gfx::RenderList& renderer, const score::gfx::Port& p,
QRhiResourceUpdateBatch*& res) override
{
// Outer guard includes scene_input_introspection so a node with ONLY
// scene inputs (no texture / buffer / geometry) still allocates `res`
// — necessary if scene_inputs_storage ever grows an inputAboutToFinish
// method (today it's read-only via readInputScenes, but the storage's
// lifecycle is part of the new scene_port concept and may evolve).
// Without the include, a scene-only sink would silently skip the
// res allocation and any future scene-side write would have nowhere
// to land.
if constexpr(
avnd::texture_input_introspection<Node_T>::size > 0
|| avnd::buffer_input_introspection<Node_T>::size > 0
|| avnd::geometry_input_introspection<Node_T>::size > 0)
|| avnd::geometry_input_introspection<Node_T>::size > 0
|| scene_input_introspection<Node_T>::size > 0)
{
res = renderer.state.rhi->nextResourceUpdateBatch();

Expand All @@ -118,6 +173,8 @@ struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
if constexpr(avnd::geometry_input_introspection<Node_T>::size > 0)
geometry_ins.inputAboutToFinish(
renderer, res, this->geometry, *state, this->node());
// No scene_ins.inputAboutToFinish today — the guard is forward-
// looking; add the call here when scene_inputs_storage grows one.
}

if_possible(state->inputAboutToFinish(renderer, p, res));
Expand All @@ -144,6 +201,8 @@ struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
buffer_ins.readInputBuffers(renderer, parent, *state);
if constexpr(avnd::geometry_input_introspection<Node_T>::size > 0)
geometry_ins.readInputGeometries(renderer, this->geometry, parent, *state);
if constexpr(scene_input_introspection<Node_T>::size > 0)
scene_ins.readInputScenes(this->scene, *state);

parent.processControlIn(
*this, *state, m_last_message, parent.last_message, parent.m_ctx);
Expand All @@ -158,9 +217,13 @@ struct GfxRenderer<Node_T> final : score::gfx::OutputNodeRenderer
};

template <typename Node_T>
requires(
(avnd::texture_output_introspection<Node_T>::size + avnd::buffer_output_introspection<Node_T>::size + avnd::geometry_output_introspection<Node_T>::size) == 0
)
requires((avnd::texture_output_introspection<Node_T>::size
+ avnd::buffer_output_introspection<Node_T>::size
+ avnd::geometry_output_introspection<Node_T>::size
+ scene_output_introspection<Node_T>::size)
== 0
&& (avnd::gpu_render_target_output_port_output_introspection<Node_T>::size
== 0))
struct GfxNode<Node_T> final
: CustomGpuOutputNodeBase
, GpuNodeElements<Node_T>
Expand Down
Loading
Loading