4#include <Crousti/GfxNode.hpp>
9template <
typename Node_T>
11 avnd::texture_input_introspection<Node_T>::size > 0
12 && avnd::texture_output_introspection<Node_T>::size == 0)
13struct GfxRenderer<Node_T>
final :
score::gfx::OutputNodeRenderer
15 using texture_inputs = avnd::texture_input_introspection<Node_T>;
16 std::shared_ptr<Node_T> state;
18 ossia::small_flat_map<const score::gfx::Port*, score::gfx::TextureRenderTarget, 2>
21 std::vector<QRhiReadbackResult> m_readbacks;
22 ossia::time_value m_last_time{-1};
24 const GfxNode<Node_T>& node() const noexcept
26 return static_cast<const GfxNode<Node_T>&
>(score::gfx::NodeRenderer::node);
28 GfxRenderer(
const GfxNode<Node_T>& p)
29 :
score::gfx::OutputNodeRenderer{p}
30 , state{
std::make_shared<Node_T>()}
31 , m_readbacks(texture_inputs::size)
33 prepareNewState<Node_T>(state, p);
39 auto it = m_rts.find(&p);
40 SCORE_ASSERT(it != m_rts.end());
44 template <
typename Tex>
49 auto port = this->node().input[k];
50 static constexpr auto flags
51 = QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource;
52 auto texture = renderer.
state.rhi->newTexture(
53 gpp::qrhi::textureFormat(texture_spec), spec.size, 1, flags);
54 SCORE_ASSERT(texture->create());
59 QRhiTexture* texture(
int k)
const noexcept
61 auto port = this->node().input[k];
62 auto it = m_rts.find(port);
63 SCORE_ASSERT(it != m_rts.end());
64 SCORE_ASSERT(it->second.texture);
65 return it->second.texture;
68 void loadInputTexture(QRhi& rhi, avnd::cpu_texture
auto& cpu_tex,
int k)
70 oscr::loadInputTexture(rhi, m_readbacks, cpu_tex, k);
75 if constexpr(
requires { state->prepare(); })
77 this->node().processControlIn(
78 *
this, *state, m_last_message, this->node().last_message, this->node().m_ctx);
84 avnd::cpu_texture_input_introspection<Node_T>::for_all(
85 avnd::get_inputs<Node_T>(*state),
86 [&]<
typename F>(F& t) {
88 auto spec = this->node().resolveRenderTargetSpecs(k, renderer);
89 if constexpr(
requires {
94 spec.size.rwidth() = t.request_width;
95 spec.size.rheight() = t.request_height;
97 createInput(renderer, k, t.texture, spec);
98 if constexpr(avnd::cpu_fixed_format_texture<
decltype(t.texture)>)
100 t.texture.width = spec.size.width();
101 t.texture.height = spec.size.height();
111 bool updated =
false;
151 for(
auto [port, rt] : m_rts)
156 void inputAboutToFinish(
158 QRhiResourceUpdateBatch*& res)
override
160 auto& parent = this->node();
161 res = renderer.
state.rhi->nextResourceUpdateBatch();
162 const auto& inputs = parent.input;
163 auto index_of_port = ossia::find(inputs, &p) - inputs.begin();
164 SCORE_ASSERT(index_of_port == 0);
166 auto tex = m_rts[&p].texture;
167 auto& readback = m_readbacks[index_of_port];
169 res->readBackTexture(QRhiReadbackDescription{tex}, &readback);
173 void runInitialPasses(
177 auto& parent = this->node();
178 auto& rhi = *renderer.
state.rhi;
184 if(parent.last_message.token.date == m_last_time)
188 m_last_time = parent.last_message.token.date;
196 avnd::cpu_texture_input_introspection<Node_T>::for_all(
197 avnd::get_inputs<Node_T>(*state), [&](
auto& t) {
198 loadInputTexture(rhi, t.texture, k);
203 parent.processControlIn(
204 *
this, *state, m_last_message, parent.last_message, parent.m_ctx);
210 parent.processControlOut(*this->state);
214 avnd::geometry_output_introspection<Node_T>::for_all_n2(
215 state->outputs, [&]<std::size_t F, std::size_t P>(
216 auto& t, avnd::predicate_index<P>, avnd::field_index<F>) {
217 postprocess_geometry(t);
220 template <avnd::geometry_port Field>
221 void postprocess_geometry(Field& ctrl)
223 using namespace avnd;
230 auto meshes = std::make_shared<ossia::mesh_list>();
231 auto& ossia_meshes = *meshes;
232 if constexpr(static_geometry_type<Field> || dynamic_geometry_type<Field>)
234 ossia_meshes.meshes.resize(1);
235 oscr::load_geometry(ctrl, ossia_meshes.meshes[0]);
238 static_geometry_type<
decltype(Field::mesh)>
239 || dynamic_geometry_type<
decltype(Field::mesh)>)
241 ossia_meshes.meshes.resize(1);
242 oscr::load_geometry(ctrl.mesh, ossia_meshes.meshes[0]);
246 oscr::load_geometry(ctrl, ossia_meshes);
249 ctrl.dirty_mesh =
false;
270template <
typename Node_T>
271 requires(avnd::texture_input_introspection<Node_T>::size > 0
272 && avnd::texture_output_introspection<Node_T>::size == 0)
273struct GfxNode<Node_T>
final
274 : CustomGpuOutputNodeBase
275 , GpuNodeElements<Node_T>
280 std::weak_ptr<Execution::ExecutionCommandQueue> q, Gfx::exec_controls ctls,
282 : CustomGpuOutputNodeBase{
std::move(q),
std::move(ctls), ctx}
283 , processModel{element}
287 initGfxPorts<Node_T>(
this, this->input, this->output);
293 return new GfxRenderer<Node_T>{*
this};
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
bool requiresDepth() const noexcept
Whether this list of rendering actions requires depth testing at all.
Definition RenderList.hpp:137
RenderState & state
RenderState corresponding to this RenderList.
Definition RenderList.hpp:89
Definition Factories.hpp:19
TextureRenderTarget createRenderTarget(const RenderState &state, QRhiTexture *tex, int samples, bool depth)
Create a render target from a texture.
Definition score-plugin-gfx/Gfx/Graph/Utils.cpp:10
Base toolkit upon which the software is built.
Definition Application.cpp:97
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
Definition score-plugin-gfx/Gfx/Graph/Node.hpp:57
Useful abstraction for storing all the data related to a render target.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:115