4 #include <Process/ExecutionContext.hpp>
6 #include <Crousti/File.hpp>
7 #include <Crousti/MessageBus.hpp>
8 #include <Gfx/GfxExecNode.hpp>
9 #include <Gfx/Graph/Node.hpp>
10 #include <Gfx/Graph/OutputNode.hpp>
11 #include <Gfx/Graph/RenderState.hpp>
14 #include <QtGui/private/qrhi_p.h>
16 #include <avnd/binding/ossia/port_run_postprocess.hpp>
17 #include <avnd/binding/ossia/port_run_preprocess.hpp>
18 #include <avnd/binding/ossia/soundfiles.hpp>
19 #include <avnd/concepts/parameter.hpp>
20 #include <avnd/introspection/input.hpp>
21 #include <avnd/introspection/output.hpp>
22 #include <fmt/format.h>
23 #include <gpp/layout.hpp>
25 #include <score_plugin_avnd_export.h>
30 requires requires { F::format(); }
31 constexpr QRhiTexture::Format textureFormat()
33 constexpr std::string_view fmt = F::format();
35 if(fmt ==
"rgba" || fmt ==
"rgba8")
36 return QRhiTexture::RGBA8;
37 else if(fmt ==
"bgra" || fmt ==
"bgra8")
38 return QRhiTexture::BGRA8;
40 return QRhiTexture::R8;
41 #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
43 return QRhiTexture::RG8;
46 return QRhiTexture::R16;
47 #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
48 else if(fmt ==
"rg16")
49 return QRhiTexture::RG16;
51 else if(fmt ==
"red_or_alpha8")
52 return QRhiTexture::RED_OR_ALPHA8;
53 else if(fmt ==
"rgba16f")
54 return QRhiTexture::RGBA16F;
55 else if(fmt ==
"rgba32f")
56 return QRhiTexture::RGBA32F;
57 else if(fmt ==
"r16f")
58 return QRhiTexture::R16F;
60 return QRhiTexture::R32F;
61 #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
62 else if(fmt ==
"rgb10a2")
63 return QRhiTexture::RGB10A2;
67 return QRhiTexture::D16;
69 #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
71 return QRhiTexture::D24;
72 else if(fmt ==
"d24s8")
73 return QRhiTexture::D24S8;
75 else if(fmt ==
"d32f")
76 return QRhiTexture::D32F;
79 return QRhiTexture::BC1;
81 return QRhiTexture::BC2;
83 return QRhiTexture::BC3;
85 return QRhiTexture::BC4;
87 return QRhiTexture::BC5;
88 else if(fmt ==
"bc6h")
89 return QRhiTexture::BC6H;
91 return QRhiTexture::BC7;
92 else if(fmt ==
"etc2_rgb8")
93 return QRhiTexture::ETC2_RGB8;
94 else if(fmt ==
"etc2_rgb8a1")
95 return QRhiTexture::ETC2_RGB8A1;
96 else if(fmt ==
"etc2_rgb8a8")
97 return QRhiTexture::ETC2_RGBA8;
98 else if(fmt ==
"astc_4x4")
99 return QRhiTexture::ASTC_4x4;
100 else if(fmt ==
"astc_5x4")
101 return QRhiTexture::ASTC_5x4;
102 else if(fmt ==
"astc_5x5")
103 return QRhiTexture::ASTC_5x5;
104 else if(fmt ==
"astc_6x5")
105 return QRhiTexture::ASTC_6x5;
106 else if(fmt ==
"astc_6x6")
107 return QRhiTexture::ASTC_6x6;
108 else if(fmt ==
"astc_8x5")
109 return QRhiTexture::ASTC_8x5;
110 else if(fmt ==
"astc_8x6")
111 return QRhiTexture::ASTC_8x6;
112 else if(fmt ==
"astc_8x8")
113 return QRhiTexture::ASTC_8x8;
114 else if(fmt ==
"astc_10x5")
115 return QRhiTexture::ASTC_10x5;
116 else if(fmt ==
"astc_10x6")
117 return QRhiTexture::ASTC_10x6;
118 else if(fmt ==
"astc_10x8")
119 return QRhiTexture::ASTC_10x8;
120 else if(fmt ==
"astc_10x10")
121 return QRhiTexture::ASTC_10x10;
122 else if(fmt ==
"astc_12x10")
123 return QRhiTexture::ASTC_12x10;
124 else if(fmt ==
"astc_12x12")
125 return QRhiTexture::ASTC_12x12;
127 return QRhiTexture::RGBA8;
130 template <
typename F>
131 requires std::is_enum_v<typename F::format>
132 constexpr QRhiTexture::Format textureFormat()
135 requires { F::RGBA; } || requires { F::RGBA8; })
136 return QRhiTexture::RGBA8;
138 requires { F::BGRA; } || requires { F::BGRA8; })
139 return QRhiTexture::BGRA8;
141 requires { F::R8; } || requires { F::GRAYSCALE; })
142 return QRhiTexture::R8;
143 #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
144 else if constexpr(requires { F::RG8; })
145 return QRhiTexture::RG8;
147 else if constexpr(requires { F::R16; })
148 return QRhiTexture::R16;
149 #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
150 else if constexpr(requires { F::RG16; })
151 return QRhiTexture::RG16;
153 else if constexpr(requires { F::RED_OR_ALPHA8; })
154 return QRhiTexture::RED_OR_ALPHA8;
155 else if constexpr(requires { F::RGBA16F; })
156 return QRhiTexture::RGBA16F;
157 else if constexpr(requires { F::RGBA32F; })
158 return QRhiTexture::RGBA32F;
159 else if constexpr(requires { F::R16F; })
160 return QRhiTexture::R16F;
161 else if constexpr(requires { F::R32F; })
162 return QRhiTexture::R32F;
163 #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
164 else if constexpr(requires { F::RGB10A2; })
165 return QRhiTexture::RGB10A2;
167 else if constexpr(requires { F::D16; })
168 return QRhiTexture::D16;
170 #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
171 else if constexpr(requires { F::D24; })
172 return QRhiTexture::D24;
173 else if constexpr(requires { F::D24S8; })
174 return QRhiTexture::D24S8;
176 else if constexpr(requires { F::D32F; })
177 return QRhiTexture::D32F;
179 else if constexpr(requires { F::BC1; })
180 return QRhiTexture::BC1;
181 else if constexpr(requires { F::BC2; })
182 return QRhiTexture::BC2;
183 else if constexpr(requires { F::BC3; })
184 return QRhiTexture::BC3;
185 else if constexpr(requires { F::BC4; })
186 return QRhiTexture::BC4;
187 else if constexpr(requires { F::BC5; })
188 return QRhiTexture::BC5;
189 else if constexpr(requires { F::BC6H; })
190 return QRhiTexture::BC6H;
191 else if constexpr(requires { F::BC7; })
192 return QRhiTexture::BC7;
193 else if(requires { F::ETC2_RGB8; })
194 return QRhiTexture::ETC2_RGB8;
195 else if(requires { F::ETC2_RGB8A1; })
196 return QRhiTexture::ETC2_RGB8A1;
197 else if(requires { F::ETC2_RGB8A8; })
198 return QRhiTexture::ETC2_RGBA8;
199 else if(requires { F::ASTC_4X4; })
200 return QRhiTexture::ASTC_4x4;
201 else if(requires { F::ASTC_5X4; })
202 return QRhiTexture::ASTC_5x4;
203 else if(requires { F::ASTC_5X5; })
204 return QRhiTexture::ASTC_5x5;
205 else if(requires { F::ASTC_6X5; })
206 return QRhiTexture::ASTC_6x5;
207 else if(requires { F::ASTC_6X6; })
208 return QRhiTexture::ASTC_6x6;
209 else if(requires { F::ASTC_8X5; })
210 return QRhiTexture::ASTC_8x5;
211 else if(requires { F::ASTC_8X6; })
212 return QRhiTexture::ASTC_8x6;
213 else if(requires { F::ASTC_8X8; })
214 return QRhiTexture::ASTC_8x8;
215 else if(requires { F::ASTC_10X5; })
216 return QRhiTexture::ASTC_10x5;
217 else if(requires { F::ASTC_10X6; })
218 return QRhiTexture::ASTC_10x6;
219 else if(requires { F::ASTC_10X8; })
220 return QRhiTexture::ASTC_10x8;
221 else if(requires { F::ASTC_10X10; })
222 return QRhiTexture::ASTC_10x10;
223 else if(requires { F::ASTC_12X10; })
224 return QRhiTexture::ASTC_12x10;
225 else if(requires { F::ASTC_12X12; })
226 return QRhiTexture::ASTC_12x12;
228 return QRhiTexture::RGBA8;
231 struct DefaultPipeline
243 static constexpr
auto name() {
return "position"; }
244 static constexpr
int location() {
return 0; }
251 struct fragment_input
259 static QString vertex()
261 return R
"_(#version 450
262 layout(location = 0) in vec2 position;
263 out gl_PerVertex { vec4 gl_Position; };
265 gl_Position = vec4( position, 0.0, 1.0 );
271 template <
typename C>
272 constexpr
auto usage()
274 if constexpr(requires { C::vertex; })
275 return QRhiBuffer::VertexBuffer;
276 else if constexpr(requires { C::index; })
277 return QRhiBuffer::IndexBuffer;
278 else if constexpr(requires { C::ubo; })
279 return QRhiBuffer::UniformBuffer;
280 else if constexpr(requires { C::storage; })
281 return QRhiBuffer::StorageBuffer;
284 static_assert(C::unhandled);
289 template <
typename C>
290 constexpr
auto buffer_type()
292 if constexpr(requires { C::immutable; })
293 return QRhiBuffer::Immutable;
294 else if constexpr(requires { C::static_; })
295 return QRhiBuffer::Static;
296 else if constexpr(requires { C::dynamic; })
297 return QRhiBuffer::Dynamic;
300 static_assert(C::unhandled);
305 template <
typename C>
308 if constexpr(requires { C::samples; })
314 struct handle_release
317 template <
typename C>
318 void operator()(C command)
320 if constexpr(requires { C::deallocation; })
323 requires { C::vertex; } || requires { C::index; } || requires { C::ubo; })
325 auto buf =
reinterpret_cast<QRhiBuffer*
>(command.handle);
328 else if constexpr(requires { C::sampler; })
330 auto buf =
reinterpret_cast<QRhiSampler*
>(command.handle);
333 else if constexpr(requires { C::texture; })
335 auto buf =
reinterpret_cast<QRhiTexture*
>(command.handle);
340 static_assert(C::unhandled);
345 static_assert(C::unhandled);
350 template <
typename Self,
typename Res>
351 struct handle_dispatch
355 QRhiCommandBuffer& cb;
356 QRhiResourceUpdateBatch*& res;
357 QRhiComputePipeline& pip;
358 template <
typename C>
359 Res operator()(C command)
361 if constexpr(requires { C::compute; })
363 if constexpr(requires { C::dispatch; })
365 cb.dispatch(command.x, command.y, command.z);
368 else if constexpr(requires { C::begin; })
370 cb.beginComputePass(res);
372 cb.setComputePipeline(&pip);
373 cb.setShaderResources(pip.shaderResourceBindings());
377 else if constexpr(requires { C::end; })
379 cb.endComputePass(res);
386 static_assert(C::unhandled);
390 else if constexpr(requires { C::readback; })
393 if constexpr(requires { C::request; })
395 if constexpr(requires { C::buffer; })
397 using ret =
typename C::return_type;
399 #if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
400 auto readback =
new QRhiBufferReadbackResult;
402 auto readback =
new QRhiReadbackResult;
404 self.addReadback(readback);
407 ret user_rb{.handle =
reinterpret_cast<decltype(ret::handle)
>(readback)};
418 auto next = rhi.nextResourceUpdateBatch();
419 auto buf =
reinterpret_cast<QRhiBuffer*
>(command.handle);
421 next->readBackBuffer(buf, command.offset, command.size, readback);
426 else if constexpr(requires { C::texture; })
428 using ret =
typename C::return_type;
429 QRhiReadbackResult readback;
434 static_assert(C::unhandled);
438 else if constexpr(requires { C::await; })
440 if constexpr(requires { C::buffer; })
442 using ret =
typename C::return_type;
444 #if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
445 auto readback =
reinterpret_cast<QRhiBufferReadbackResult*
>(command.handle);
447 auto readback =
reinterpret_cast<QRhiReadbackResult*
>(command.handle);
451 .data = readback->data.data(), .size = (std::size_t)readback->data.size()};
453 else if constexpr(requires { C::texture; })
455 using ret =
typename C::return_type;
457 auto readback =
reinterpret_cast<QRhiReadbackResult*
>(command.handle);
460 .data = readback->data.data(), .size = (std::size_t)readback->data.size()};
466 static_assert(C::unhandled);
474 template <
typename Self,
typename Ret>
479 QRhiResourceUpdateBatch& res;
480 std::vector<QRhiShaderResourceBinding>& srb;
483 template <
typename C>
484 Ret operator()(C command)
486 if constexpr(requires { C::allocation; })
489 requires { C::vertex; } || requires { C::index; })
491 auto buf = rhi.newBuffer(buffer_type<C>(), usage<C>(), command.size);
493 return reinterpret_cast<typename C::return_type
>(buf);
495 else if constexpr(requires { C::sampler; })
497 auto buf = rhi.newSampler({}, {}, {}, {}, {});
499 return reinterpret_cast<typename C::return_type
>(buf);
502 requires { C::ubo; } || requires { C::storage; })
504 auto buf = rhi.newBuffer(buffer_type<C>(), usage<C>(), command.size);
508 score::gfx::replaceBuffer(srb, command.binding, buf);
510 return reinterpret_cast<typename C::return_type
>(buf);
512 else if constexpr(requires { C::texture; })
514 auto tex = rhi.newTexture(
515 QRhiTexture::RGBA8, QSize{command.width, command.height}, samples(command));
518 score::gfx::replaceTexture(srb, command.binding, tex);
520 return reinterpret_cast<typename C::return_type
>(tex);
524 static_assert(C::unhandled);
528 else if constexpr(requires { C::upload; })
530 if constexpr(requires { C::texture; })
532 QRhiTextureSubresourceUploadDescription sub(command.data, command.size);
534 reinterpret_cast<QRhiTexture*
>(command.handle),
535 QRhiTextureUploadDescription{{0, 0, sub}});
539 auto buf =
reinterpret_cast<QRhiBuffer*
>(command.handle);
540 if constexpr(requires { C::dynamic; })
541 res.updateDynamicBuffer(buf, command.offset, command.size, command.data);
543 requires { C::static_; } || requires { C::immutable; })
544 res.uploadStaticBuffer(buf, command.offset, command.size, command.data);
547 static_assert(C::unhandled);
552 else if constexpr(requires { C::getter; })
554 if constexpr(requires { C::ubo; })
556 auto buf =
self.createdUbos.at(command.binding);
557 return reinterpret_cast<typename C::return_type
>(buf);
561 static_assert(C::unhandled);
567 handle_release{rhi}(command);
574 struct generate_shaders
576 template <
typename T,
int N>
579 static constexpr std::string_view field_type(
float) {
return "float"; }
580 static constexpr std::string_view field_type(
const float (&)[2]) {
return "vec2"; }
581 static constexpr std::string_view field_type(
const float (&)[3]) {
return "vec3"; }
582 static constexpr std::string_view field_type(
const float (&)[4]) {
return "vec4"; }
584 static constexpr std::string_view field_type(
float*) {
return "float"; }
585 static constexpr std::string_view field_type(vec<float, 2>*) {
return "vec2"; }
586 static constexpr std::string_view field_type(vec<float, 3>*) {
return "vec3"; }
587 static constexpr std::string_view field_type(vec<float, 4>*) {
return "vec4"; }
589 static constexpr std::string_view field_type(
int) {
return "int"; }
590 static constexpr std::string_view field_type(
const int (&)[2]) {
return "ivec2"; }
591 static constexpr std::string_view field_type(
const int (&)[3]) {
return "ivec3"; }
592 static constexpr std::string_view field_type(
const int (&)[4]) {
return "ivec4"; }
594 static constexpr std::string_view field_type(
int*) {
return "int"; }
595 static constexpr std::string_view field_type(vec<int, 2>*) {
return "ivec2"; }
596 static constexpr std::string_view field_type(vec<int, 3>*) {
return "ivec3"; }
597 static constexpr std::string_view field_type(vec<int, 4>*) {
return "ivec4"; }
599 static constexpr std::string_view field_type(uint32_t) {
return "uint"; }
600 static constexpr std::string_view field_type(
const uint32_t (&)[2]) {
return "uvec2"; }
601 static constexpr std::string_view field_type(
const uint32_t (&)[3]) {
return "uvec3"; }
602 static constexpr std::string_view field_type(
const uint32_t (&)[4]) {
return "uvec4"; }
604 static constexpr std::string_view field_type(uint32_t*) {
return "uint"; }
605 static constexpr std::string_view field_type(vec<uint32_t, 2>*) {
return "uvec2"; }
606 static constexpr std::string_view field_type(vec<uint32_t, 3>*) {
return "uvec3"; }
607 static constexpr std::string_view field_type(vec<uint32_t, 4>*) {
return "uvec4"; }
609 static constexpr std::string_view field_type(avnd::xy_value
auto) {
return "vec2"; }
611 static constexpr
bool field_array(
float) {
return false; }
612 static constexpr
bool field_array(
const float (&)[2]) {
return false; }
613 static constexpr
bool field_array(
const float (&)[3]) {
return false; }
614 static constexpr
bool field_array(
const float (&)[4]) {
return false; }
616 static constexpr
bool field_array(
float*) {
return true; }
617 static constexpr
bool field_array(vec<float, 2>*) {
return true; }
618 static constexpr
bool field_array(vec<float, 3>*) {
return true; }
619 static constexpr
bool field_array(vec<float, 4>*) {
return true; }
621 static constexpr
bool field_array(
int) {
return false; }
622 static constexpr
bool field_array(
const int (&)[2]) {
return false; }
623 static constexpr
bool field_array(
const int (&)[3]) {
return false; }
624 static constexpr
bool field_array(
const int (&)[4]) {
return false; }
626 static constexpr
bool field_array(
int*) {
return true; }
627 static constexpr
bool field_array(vec<int, 2>*) {
return true; }
628 static constexpr
bool field_array(vec<int, 3>*) {
return true; }
629 static constexpr
bool field_array(vec<int, 4>*) {
return true; }
631 static constexpr
bool field_array(uint32_t) {
return false; }
632 static constexpr
bool field_array(
const uint32_t (&)[2]) {
return false; }
633 static constexpr
bool field_array(
const uint32_t (&)[3]) {
return false; }
634 static constexpr
bool field_array(
const uint32_t (&)[4]) {
return false; }
636 static constexpr
bool field_array(uint32_t*) {
return true; }
637 static constexpr
bool field_array(vec<uint32_t, 2>*) {
return true; }
638 static constexpr
bool field_array(vec<uint32_t, 3>*) {
return true; }
639 static constexpr
bool field_array(vec<uint32_t, 4>*) {
return true; }
641 static constexpr
bool field_array(avnd::xy_value
auto) {
return false; }
643 template <
typename T>
644 static constexpr std::string_view image_qualifier()
646 if constexpr(requires { T::readonly; })
648 else if constexpr(requires { T::writeonly; })
651 static_assert(T::readonly || T::writeonly);
658 template <
typename T>
659 void operator()(
const T& field)
661 shader += fmt::format(
662 "layout(location = {}) in {} {};\n", T::location(), field_type(field.data),
671 template <
typename T>
672 void operator()(
const T& field)
674 if constexpr(requires { field.location(); })
676 shader += fmt::format(
677 "layout(location = {}) out {} {};\n", T::location(), field_type(field.data),
687 template <
typename T>
688 void operator()(
const T& field)
690 shader += fmt::format(
691 " {} {}{};\n", field_type(field.value), T::name(),
692 field_array(field.value) ?
"[]" :
"");
696 struct write_bindings
700 template <
typename C>
701 void operator()(
const C& field)
703 if constexpr(requires { C::sampler2D; })
705 shader += fmt::format(
706 "layout(binding = {}) uniform sampler2D {};\n\n", C::binding(), C::name());
708 else if constexpr(requires { C::image2D; })
710 shader += fmt::format(
711 "layout(binding = {}, {}) {} uniform image2D {};\n\n", C::binding(),
712 C::format(), image_qualifier<C>(), C::name());
714 else if constexpr(requires { C::ubo; })
716 shader += fmt::format(
717 "layout({}, binding = {}) uniform {}\n{{\n",
720 C::binding(), C::name());
722 boost::pfr::for_each_field(field, write_binding{shader});
724 shader += fmt::format(
"}};\n\n");
726 else if constexpr(requires { C::buffer; })
728 shader += fmt::format(
729 "layout({}, binding = {}) buffer {}\n{{\n",
732 C::binding(), C::name());
734 boost::pfr::for_each_field(field, write_binding{shader});
736 shader += fmt::format(
"}};\n\n");
741 template <
typename T>
742 std::string vertex_shader(
const T& lay)
744 using namespace gpp::qrhi;
745 std::string shader =
"#version 450\n\n";
747 if constexpr(requires { lay.vertex_input; })
748 boost::pfr::for_each_field(lay.vertex_input, write_input{shader});
749 else if constexpr(requires {
typename T::vertex_input; })
750 boost::pfr::for_each_field(
typename T::vertex_input{}, write_input{shader});
752 boost::pfr::for_each_field(
753 DefaultPipeline::layout::vertex_input{}, write_input{shader});
755 if constexpr(requires { lay.vertex_output; })
756 boost::pfr::for_each_field(lay.vertex_output, write_output{shader});
757 else if constexpr(requires {
typename T::vertex_output; })
758 boost::pfr::for_each_field(
typename T::vertex_output{}, write_output{shader});
762 if constexpr(requires { lay.bindings; })
763 boost::pfr::for_each_field(lay.bindings, write_bindings{shader});
764 else if constexpr(requires {
typename T::bindings; })
765 boost::pfr::for_each_field(
typename T::bindings{}, write_bindings{shader});
770 template <
typename T>
771 std::string fragment_shader(
const T& lay)
773 std::string shader =
"#version 450\n\n";
775 if constexpr(requires { lay.fragment_input; })
776 boost::pfr::for_each_field(lay.fragment_input, write_input{shader});
777 else if constexpr(requires {
typename T::fragment_input; })
778 boost::pfr::for_each_field(
typename T::fragment_input{}, write_input{shader});
780 if constexpr(requires { lay.fragment_output; })
781 boost::pfr::for_each_field(lay.fragment_output, write_output{shader});
782 else if constexpr(requires {
typename T::fragment_output; })
783 boost::pfr::for_each_field(
typename T::fragment_output{}, write_output{shader});
787 if constexpr(requires { lay.bindings; })
788 boost::pfr::for_each_field(lay.bindings, write_bindings{shader});
789 else if constexpr(requires {
typename T::bindings; })
790 boost::pfr::for_each_field(
typename T::bindings{}, write_bindings{shader});
795 template <
typename T>
796 std::string compute_shader(
const T& lay)
798 std::string fstr =
"#version 450\n\n";
801 if constexpr(requires { T::local_size_x(); })
803 fstr += fmt::format(
"local_size_x = {}, ", T::local_size_x());
805 if constexpr(requires { T::local_size_y(); })
807 fstr += fmt::format(
"local_size_y = {}, ", T::local_size_y());
809 if constexpr(requires { T::local_size_z(); })
811 fstr += fmt::format(
"local_size_z = {}, ", T::local_size_z());
815 fstr.resize(fstr.size() - 2);
818 boost::pfr::for_each_field(lay.bindings, write_bindings{fstr});
829 template <
typename Node>
830 static void initWorker(Node& state) noexcept
832 if constexpr(avnd::has_worker<Node>)
834 using worker_type = decltype(state.worker);
836 state.worker.request = [&state]<
typename... Args>(Args&&... f) {
837 using type_of_result = decltype(worker_type::work(std::forward<Args>(f)...));
838 if constexpr(std::is_void_v<type_of_result>)
840 worker_type::work(std::forward<Args>(f)...);
846 auto res = worker_type::work(std::forward<Args>(f)...);
856 template <
typename GpuNodeRenderer,
typename Node>
859 GpuNodeRenderer& gpu;
865 bool can_process_message(std::size_t N)
867 if(mess.input.size() <= N)
870 if(prev_mess.input.size() == mess.input.size())
872 auto& prev = prev_mess.input[N];
873 auto& next = mess.input[N];
874 if(prev.index() == 1 && next.index() == 1)
876 if(ossia::get<ossia::value>(prev) == ossia::get<ossia::value>(next))
885 void operator()(avnd::parameter
auto& t,
auto field_index)
887 if(!can_process_message(field_index))
890 if(
auto val = ossia::get_if<ossia::value>(&mess.input[field_index]))
892 oscr::from_ossia_value(t, *val, t.value);
893 if_possible(t.update(state));
897 #if OSCR_HAS_MMAP_FILE_STORAGE
898 template <avnd::raw_file_port Field, std::
size_t NField>
899 void operator()(Field& t, avnd::field_index<NField> field_index)
902 using node_type = std::remove_cvref_t<decltype(gpu.parent)>;
903 using file_ports = avnd::raw_file_input_introspection<Node>;
905 if(!can_process_message(field_index))
908 auto val = ossia::get_if<ossia::value>(&mess.input[field_index]);
912 static constexpr
bool has_text = requires { decltype(Field::file)::text; };
913 static constexpr
bool has_mmap = requires { decltype(Field::file)::mmap; };
916 if(
auto hdl = loadRawfile(*val, ctx, has_text, has_mmap))
918 static constexpr
auto N = file_ports::field_index_to_index(NField);
919 if constexpr(avnd::port_can_process<Field>)
923 auto func = executePortPreprocess<Field>(*hdl);
924 const_cast<node_type&
>(gpu.parent)
926 state, hdl, avnd::predicate_index<N>{}, avnd::field_index<NField>{});
932 const_cast<node_type&
>(gpu.parent)
934 state, hdl, avnd::predicate_index<N>{}, avnd::field_index<NField>{});
940 void operator()(
auto& t,
auto field_index) { }
945 template <
typename Self,
typename Node_T>
946 static void processControlIn(
951 avnd::input_introspection<Node_T>::for_all_n(
952 avnd::get_inputs<Node_T>(state),
953 GpuProcessIns<Self, Node_T>{
self, state, renderer_mess, mess, ctx});
954 renderer_mess = mess;
958 struct GpuControlOuts
960 std::weak_ptr<Execution::ExecutionCommandQueue> queue;
961 Gfx::exec_controls control_outs;
965 template <
typename Node_T>
966 void processControlOut(Node_T& state)
const noexcept
968 if(!this->control_outs.empty())
970 auto q = this->queue.lock();
975 avnd::parameter_output_introspection<Node_T>::for_all(
976 avnd::get_outputs(state), [&]<avnd::parameter T>(
const T& t) {
977 qq.enqueue([v = oscr::to_ossia_value(t, t.value),
978 port = control_outs[parm_k]]()
mutable {
979 std::swap(port->value, v);
980 port->changed = true;
989 template <
typename T>
990 struct SCORE_PLUGIN_AVND_EXPORT GpuNodeElements
992 [[no_unique_address]] oscr::soundfile_storage<T> soundfiles;
994 [[no_unique_address]] oscr::midifile_storage<T> midifiles;
996 #if defined(OSCR_HAS_MMAP_FILE_STORAGE)
997 [[no_unique_address]] oscr::raw_file_storage<T> rawfiles;
1000 template <std::
size_t N, std::
size_t NField>
1002 auto& state,
const std::shared_ptr<oscr::raw_file_data>& hdl,
1003 avnd::predicate_index<N>, avnd::field_index<NField>)
1005 this->rawfiles.load(
1006 state, hdl, avnd::predicate_index<N>{}, avnd::field_index<NField>{});
1013 :
score::gfx::NodeModel{}
1017 virtual ~CustomGfxNodeBase();
1024 virtual ~CustomGfxOutputNodeBase();
1029 struct CustomGpuNodeBase
1036 std::weak_ptr<Execution::ExecutionCommandQueue>&& q, Gfx::exec_controls&& ctls,
1038 : GpuControlOuts{std::move(q), std::move(ctls)}
1043 virtual ~CustomGpuNodeBase() =
default;
1046 QString vertex, fragment, compute;
1051 struct SCORE_PLUGIN_AVND_EXPORT CustomGpuOutputNodeBase
1057 CustomGpuOutputNodeBase(
1058 std::weak_ptr<Execution::ExecutionCommandQueue> q, Gfx::exec_controls&& ctls,
1060 virtual ~CustomGpuOutputNodeBase();
1063 std::weak_ptr<score::gfx::RenderList> m_renderer{};
1064 std::shared_ptr<score::gfx::RenderState> m_renderState{};
1065 std::function<void()> m_update;
1067 QString vertex, fragment, compute;
1071 void setRenderer(std::shared_ptr<score::gfx::RenderList>)
override;
1074 void startRendering()
override;
1075 void render()
override;
1076 void stopRendering()
override;
1077 bool canRender()
const override;
1078 void onRendererChange()
override;
1082 std::function<
void()> onUpdate, std::function<
void()> onResize)
override;
1084 void destroyOutput()
override;
1085 std::shared_ptr<score::gfx::RenderState> renderState()
const override;
1087 Configuration configuration() const noexcept override;
1090 template <typename Node_T, typename Node>
1091 void prepareNewState(Node_T& eff, const Node& parent)
1093 if constexpr(avnd::has_worker<Node_T>)
1095 parent.initWorker(eff);
1097 if constexpr(avnd::has_processor_to_gui_bus<Node_T>)
1099 auto& process = parent.processModel;
1100 eff.send_message = [&process](
auto&& b)
mutable {
1105 MessageBusSender{process.to_ui}(std::move(b));
1112 avnd::init_controls(eff);
1114 if constexpr(avnd::can_prepare<Node_T>)
1116 using prepare_type = avnd::first_argument<&Node_T::prepare>;
1118 if_possible(t.instance = parent.instance);
Root data model for visual nodes.
Definition: score-plugin-gfx/Gfx/Graph/Node.hpp:60
Common base class for most single-pass, simple nodes.
Definition: score-plugin-gfx/Gfx/Graph/Node.hpp:181
Base class for sink nodes (QWindow, spout, syphon, NDI output, ...)
Definition: OutputNode.hpp:23
List of nodes to be rendered to an output.
Definition: RenderList.hpp:19
TreeNode< DeviceExplorerNode > Node
Definition: DeviceNode.hpp:74
Definition: Factories.hpp:19
GraphicsApi
Available graphics APIs to use.
Definition: RenderState.hpp:17
Base toolkit upon which the software is built.
Definition: Application.cpp:90
Definition: DocumentContext.hpp:18
Definition: score-plugin-gfx/Gfx/Graph/Node.hpp:51