Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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