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 const GfxNode<Node_T>& parent;
19 ossia::small_flat_map<const score::gfx::Port*, score::gfx::TextureRenderTarget, 2>
22 std::vector<QRhiReadbackResult> m_readbacks;
23 ossia::time_value m_last_time{-1};
25 GfxRenderer(
const GfxNode<Node_T>& p)
26 :
score::gfx::OutputNodeRenderer{}
28 , m_readbacks(texture_inputs::size)
30 prepareNewState(state, parent);
36 auto it = m_rts.find(&p);
37 SCORE_ASSERT(it != m_rts.end());
41 template <
typename Tex>
45 auto port = parent.input[k];
46 static constexpr auto flags
47 = QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource;
48 auto texture = renderer.
state.rhi->newTexture(
49 gpp::qrhi::textureFormat<Tex>(), size, 1, flags);
50 SCORE_ASSERT(texture->create());
55 QRhiTexture* texture(
int k)
const noexcept
57 auto port = parent.input[k];
58 auto it = m_rts.find(port);
59 SCORE_ASSERT(it != m_rts.end());
60 SCORE_ASSERT(it->second.texture);
61 return it->second.texture;
64 void loadInputTexture(avnd::cpu_texture
auto& cpu_tex,
int k)
66 auto& buf = m_readbacks[k].data;
67 if(buf.size() != 4 * cpu_tex.width * cpu_tex.height)
69 cpu_tex.bytes =
nullptr;
73 cpu_tex.bytes =
reinterpret_cast<unsigned char*
>(buf.data());
74 cpu_tex.changed =
true;
80 if constexpr(
requires { state.prepare(); })
82 parent.processControlIn(
83 *
this, state, m_last_message, this->parent.last_message, this->parent.m_ctx);
89 avnd::cpu_texture_input_introspection<Node_T>::for_all(
90 avnd::get_inputs<Node_T>(state), [&]<
typename F>(F& t) {
91 QSize sz = renderer.
state.renderSize;
92 if constexpr(
requires {
97 sz.rwidth() = t.request_width;
98 sz.rheight() = t.request_height;
100 createInput(renderer, k, t.texture, sz);
101 if constexpr(avnd::cpu_fixed_format_texture<
decltype(t.texture)>)
103 t.texture.width = sz.width();
104 t.texture.height = sz.height();
111 bool updated =
false;
151 for(
auto [port, rt] : m_rts)
156 void inputAboutToFinish(
158 QRhiResourceUpdateBatch*& res)
override
160 res = renderer.
state.rhi->nextResourceUpdateBatch();
161 const auto& inputs = this->parent.input;
162 auto index_of_port = ossia::find(inputs, &p) - inputs.begin();
163 SCORE_ASSERT(index_of_port == 0);
165 auto tex = m_rts[&p].texture;
166 auto& readback = m_readbacks[index_of_port];
168 res->readBackTexture(QRhiReadbackDescription{tex}, &readback);
172 void runInitialPasses(
176 auto& rhi = *renderer.
state.rhi;
179 if(parent.last_message.token.date == m_last_time)
183 m_last_time = parent.last_message.token.date;
194 avnd::cpu_texture_input_introspection<Node_T>::for_all(
195 avnd::get_inputs<Node_T>(state), [&](
auto& t) {
196 loadInputTexture(t.texture, k);
201 parent.processControlIn(
202 *
this, state, m_last_message, this->parent.last_message, this->parent.m_ctx);
208 parent.processControlOut(this->state);
212 avnd::geometry_output_introspection<Node_T>::for_all_n2(
213 state.outputs, [&]<std::size_t F, std::size_t P>(
214 auto& t, avnd::predicate_index<P>, avnd::field_index<F>) {
215 postprocess_geometry(t);
218 template <avnd::geometry_port Field>
219 void postprocess_geometry(Field& ctrl)
221 using namespace avnd;
224 mesh_dirty = ctrl.dirty_mesh;
228 auto meshes = std::make_shared<ossia::mesh_list>();
229 auto& ossia_meshes = *meshes;
230 if constexpr(static_geometry_type<Field> || dynamic_geometry_type<Field>)
232 ossia_meshes.meshes.resize(1);
233 oscr::load_geometry(ctrl, ossia_meshes.meshes[0]);
236 static_geometry_type<
decltype(Field::mesh)>
237 || dynamic_geometry_type<
decltype(Field::mesh)>)
239 ossia_meshes.meshes.resize(1);
240 oscr::load_geometry(ctrl.mesh, ossia_meshes.meshes[0]);
244 oscr::load_geometry(ctrl, ossia_meshes);
247 ctrl.dirty_mesh =
false;
268template <
typename Node_T>
269 requires(avnd::texture_input_introspection<Node_T>::size > 0
270 && avnd::texture_output_introspection<Node_T>::size == 0)
271struct GfxNode<Node_T>
final
272 : CustomGpuOutputNodeBase
273 , GpuNodeElements<Node_T>
278 std::weak_ptr<Execution::ExecutionCommandQueue> q, Gfx::exec_controls ctls,
int id,
280 : CustomGpuOutputNodeBase{
std::move(q),
std::move(ctls), ctx}
281 , processModel{element}
285 initGfxPorts<Node_T>(
this, this->input, this->output);
291 return new GfxRenderer<Node_T>{*
this};
Definition score-plugin-avnd/Crousti/ProcessModel.hpp:77
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:89
Definition Factories.hpp:19
TextureRenderTarget createRenderTarget(const RenderState &state, QRhiTexture *tex, int samples)
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:90
Definition DocumentContext.hpp:18
Connection between two score::gfx::Port.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:66
Definition score-plugin-gfx/Gfx/Graph/Node.hpp:51
Port of a score::gfx::Node.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:48
Useful abstraction for storing all the data related to a render target.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:111