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>
30constexpr QRhiTexture::Format textureFormat()
32 if constexpr(
requires { std::string_view{F::format()}; })
34 constexpr std::string_view fmt = F::format();
36 if(fmt ==
"rgba" || fmt ==
"rgba8")
37 return QRhiTexture::RGBA8;
38 else if(fmt ==
"bgra" || fmt ==
"bgra8")
39 return QRhiTexture::BGRA8;
41 return QRhiTexture::R8;
42#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
44 return QRhiTexture::RG8;
47 return QRhiTexture::R16;
48#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
49 else if(fmt ==
"rg16")
50 return QRhiTexture::RG16;
52 else if(fmt ==
"red_or_alpha8")
53 return QRhiTexture::RED_OR_ALPHA8;
54 else if(fmt ==
"rgba16f")
55 return QRhiTexture::RGBA16F;
56 else if(fmt ==
"rgba32f")
57 return QRhiTexture::RGBA32F;
58 else if(fmt ==
"r16f")
59 return QRhiTexture::R16F;
61 return QRhiTexture::R32F;
62#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
63 else if(fmt ==
"rgb10a2")
64 return QRhiTexture::RGB10A2;
68 return QRhiTexture::D16;
70#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
72 return QRhiTexture::D24;
73 else if(fmt ==
"d24s8")
74 return QRhiTexture::D24S8;
76 else if(fmt ==
"d32f")
77 return QRhiTexture::D32F;
80 return QRhiTexture::BC1;
82 return QRhiTexture::BC2;
84 return QRhiTexture::BC3;
86 return QRhiTexture::BC4;
88 return QRhiTexture::BC5;
89 else if(fmt ==
"bc6h")
90 return QRhiTexture::BC6H;
92 return QRhiTexture::BC7;
93 else if(fmt ==
"etc2_rgb8")
94 return QRhiTexture::ETC2_RGB8;
95 else if(fmt ==
"etc2_rgb8a1")
96 return QRhiTexture::ETC2_RGB8A1;
97 else if(fmt ==
"etc2_rgb8a8")
98 return QRhiTexture::ETC2_RGBA8;
99 else if(fmt ==
"astc_4x4")
100 return QRhiTexture::ASTC_4x4;
101 else if(fmt ==
"astc_5x4")
102 return QRhiTexture::ASTC_5x4;
103 else if(fmt ==
"astc_5x5")
104 return QRhiTexture::ASTC_5x5;
105 else if(fmt ==
"astc_6x5")
106 return QRhiTexture::ASTC_6x5;
107 else if(fmt ==
"astc_6x6")
108 return QRhiTexture::ASTC_6x6;
109 else if(fmt ==
"astc_8x5")
110 return QRhiTexture::ASTC_8x5;
111 else if(fmt ==
"astc_8x6")
112 return QRhiTexture::ASTC_8x6;
113 else if(fmt ==
"astc_8x8")
114 return QRhiTexture::ASTC_8x8;
115 else if(fmt ==
"astc_10x5")
116 return QRhiTexture::ASTC_10x5;
117 else if(fmt ==
"astc_10x6")
118 return QRhiTexture::ASTC_10x6;
119 else if(fmt ==
"astc_10x8")
120 return QRhiTexture::ASTC_10x8;
121 else if(fmt ==
"astc_10x10")
122 return QRhiTexture::ASTC_10x10;
123 else if(fmt ==
"astc_12x10")
124 return QRhiTexture::ASTC_12x10;
125 else if(fmt ==
"astc_12x12")
126 return QRhiTexture::ASTC_12x12;
128 return QRhiTexture::RGBA8;
130 else if constexpr(std::is_enum_v<typename F::format>)
132 if constexpr(
requires { F::RGBA; } ||
requires { F::RGBA8; })
133 return QRhiTexture::RGBA8;
134 else if constexpr(
requires { F::BGRA; } ||
requires { F::BGRA8; })
135 return QRhiTexture::BGRA8;
136 else if constexpr(
requires { F::R8; } ||
requires { F::GRAYSCALE; })
137 return QRhiTexture::R8;
138#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
139 else if constexpr(
requires { F::RG8; })
140 return QRhiTexture::RG8;
142 else if constexpr(
requires { F::R16; })
143 return QRhiTexture::R16;
144#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
145 else if constexpr(
requires { F::RG16; })
146 return QRhiTexture::RG16;
148 else if constexpr(
requires { F::RED_OR_ALPHA8; })
149 return QRhiTexture::RED_OR_ALPHA8;
150 else if constexpr(
requires { F::RGBA16F; })
151 return QRhiTexture::RGBA16F;
152 else if constexpr(
requires { F::RGBA32F; })
153 return QRhiTexture::RGBA32F;
154 else if constexpr(
requires { F::R16F; })
155 return QRhiTexture::R16F;
156 else if constexpr(
requires { F::R32F; })
157 return QRhiTexture::R32F;
158#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
159 else if constexpr(
requires { F::RGB10A2; })
160 return QRhiTexture::RGB10A2;
162 else if constexpr(
requires { F::D16; })
163 return QRhiTexture::D16;
165#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
166 else if constexpr(
requires { F::D24; })
167 return QRhiTexture::D24;
168 else if constexpr(
requires { F::D24S8; })
169 return QRhiTexture::D24S8;
171 else if constexpr(
requires { F::D32F; })
172 return QRhiTexture::D32F;
174 else if constexpr(
requires { F::BC1; })
175 return QRhiTexture::BC1;
176 else if constexpr(
requires { F::BC2; })
177 return QRhiTexture::BC2;
178 else if constexpr(
requires { F::BC3; })
179 return QRhiTexture::BC3;
180 else if constexpr(
requires { F::BC4; })
181 return QRhiTexture::BC4;
182 else if constexpr(
requires { F::BC5; })
183 return QRhiTexture::BC5;
184 else if constexpr(
requires { F::BC6H; })
185 return QRhiTexture::BC6H;
186 else if constexpr(
requires { F::BC7; })
187 return QRhiTexture::BC7;
188 else if(
requires { F::ETC2_RGB8; })
189 return QRhiTexture::ETC2_RGB8;
190 else if(
requires { F::ETC2_RGB8A1; })
191 return QRhiTexture::ETC2_RGB8A1;
192 else if(
requires { F::ETC2_RGB8A8; })
193 return QRhiTexture::ETC2_RGBA8;
194 else if(
requires { F::ASTC_4X4; })
195 return QRhiTexture::ASTC_4x4;
196 else if(
requires { F::ASTC_5X4; })
197 return QRhiTexture::ASTC_5x4;
198 else if(
requires { F::ASTC_5X5; })
199 return QRhiTexture::ASTC_5x5;
200 else if(
requires { F::ASTC_6X5; })
201 return QRhiTexture::ASTC_6x5;
202 else if(
requires { F::ASTC_6X6; })
203 return QRhiTexture::ASTC_6x6;
204 else if(
requires { F::ASTC_8X5; })
205 return QRhiTexture::ASTC_8x5;
206 else if(
requires { F::ASTC_8X6; })
207 return QRhiTexture::ASTC_8x6;
208 else if(
requires { F::ASTC_8X8; })
209 return QRhiTexture::ASTC_8x8;
210 else if(
requires { F::ASTC_10X5; })
211 return QRhiTexture::ASTC_10x5;
212 else if(
requires { F::ASTC_10X6; })
213 return QRhiTexture::ASTC_10x6;
214 else if(
requires { F::ASTC_10X8; })
215 return QRhiTexture::ASTC_10x8;
216 else if(
requires { F::ASTC_10X10; })
217 return QRhiTexture::ASTC_10x10;
218 else if(
requires { F::ASTC_12X10; })
219 return QRhiTexture::ASTC_12x10;
220 else if(
requires { F::ASTC_12X12; })
221 return QRhiTexture::ASTC_12x12;
223 return QRhiTexture::RGBA8;
227struct DefaultPipeline
239 static constexpr auto name() {
return "position"; }
240 static constexpr int location() {
return 0; }
247 struct fragment_input
255 static QString vertex()
257 return R
"_(#version 450
258layout(location = 0) in vec2 position;
259out gl_PerVertex { vec4 gl_Position; };
261 gl_Position = vec4( position, 0.0, 1.0 );
268constexpr auto usage()
270 if constexpr(
requires { C::vertex; })
271 return QRhiBuffer::VertexBuffer;
272 else if constexpr(
requires { C::index; })
273 return QRhiBuffer::IndexBuffer;
274 else if constexpr(
requires { C::ubo; })
275 return QRhiBuffer::UniformBuffer;
276 else if constexpr(
requires { C::storage; })
277 return QRhiBuffer::StorageBuffer;
280 static_assert(C::unhandled);
286constexpr auto buffer_type()
288 if constexpr(
requires { C::immutable; })
289 return QRhiBuffer::Immutable;
290 else if constexpr(
requires { C::static_; })
291 return QRhiBuffer::Static;
292 else if constexpr(
requires { C::dynamic; })
293 return QRhiBuffer::Dynamic;
296 static_assert(C::unhandled);
304 if constexpr(
requires { C::samples; })
313 template <
typename C>
314 void operator()(C command)
316 if constexpr(
requires { C::deallocation; })
319 requires { C::vertex; } ||
requires { C::index; } ||
requires { C::ubo; })
321 auto buf =
reinterpret_cast<QRhiBuffer*
>(command.handle);
324 else if constexpr(
requires { C::sampler; })
326 auto buf =
reinterpret_cast<QRhiSampler*
>(command.handle);
329 else if constexpr(
requires { C::texture; })
331 auto buf =
reinterpret_cast<QRhiTexture*
>(command.handle);
336 static_assert(C::unhandled);
341 static_assert(C::unhandled);
346template <
typename Self,
typename Res>
347struct handle_dispatch
351 QRhiCommandBuffer& cb;
352 QRhiResourceUpdateBatch*& res;
353 QRhiComputePipeline& pip;
354 template <
typename C>
355 Res operator()(C command)
357 if constexpr(
requires { C::compute; })
359 if constexpr(
requires { C::dispatch; })
361 cb.dispatch(command.x, command.y, command.z);
364 else if constexpr(
requires { C::begin; })
366 cb.beginComputePass(res);
368 cb.setComputePipeline(&pip);
369 cb.setShaderResources(pip.shaderResourceBindings());
373 else if constexpr(
requires { C::end; })
375 cb.endComputePass(res);
382 static_assert(C::unhandled);
386 else if constexpr(
requires { C::readback; })
389 if constexpr(
requires { C::request; })
391 if constexpr(
requires { C::buffer; })
393 using ret =
typename C::return_type;
395#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
396 auto readback =
new QRhiBufferReadbackResult;
398 auto readback =
new QRhiReadbackResult;
400 self.addReadback(readback);
403 ret user_rb{.handle =
reinterpret_cast<decltype(ret::handle)
>(readback)};
414 auto next = rhi.nextResourceUpdateBatch();
415 auto buf =
reinterpret_cast<QRhiBuffer*
>(command.handle);
417 next->readBackBuffer(buf, command.offset, command.size, readback);
422 else if constexpr(
requires { C::texture; })
424 using ret =
typename C::return_type;
425 QRhiReadbackResult readback;
430 static_assert(C::unhandled);
434 else if constexpr(
requires { C::await; })
436 if constexpr(
requires { C::buffer; })
438 using ret =
typename C::return_type;
440#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
441 auto readback =
reinterpret_cast<QRhiBufferReadbackResult*
>(command.handle);
443 auto readback =
reinterpret_cast<QRhiReadbackResult*
>(command.handle);
447 .data = readback->data.data(), .size = (std::size_t)readback->data.size()};
449 else if constexpr(
requires { C::texture; })
451 using ret =
typename C::return_type;
453 auto readback =
reinterpret_cast<QRhiReadbackResult*
>(command.handle);
456 .data = readback->data.data(), .size = (std::size_t)readback->data.size()};
462 static_assert(C::unhandled);
470template <
typename Self,
typename Ret>
475 QRhiResourceUpdateBatch& res;
476 std::vector<QRhiShaderResourceBinding>& srb;
479 template <
typename C>
480 Ret operator()(C command)
482 if constexpr(
requires { C::allocation; })
485 requires { C::vertex; } ||
requires { C::index; })
487 auto buf = rhi.newBuffer(buffer_type<C>(), usage<C>(), command.size);
489 return reinterpret_cast<typename C::return_type
>(buf);
491 else if constexpr(
requires { C::sampler; })
493 auto buf = rhi.newSampler({}, {}, {}, {}, {});
495 return reinterpret_cast<typename C::return_type
>(buf);
498 requires { C::ubo; } ||
requires { C::storage; })
500 auto buf = rhi.newBuffer(buffer_type<C>(), usage<C>(), command.size);
504 score::gfx::replaceBuffer(srb, command.binding, buf);
506 return reinterpret_cast<typename C::return_type
>(buf);
508 else if constexpr(
requires { C::texture; })
510 auto tex = rhi.newTexture(
511 QRhiTexture::RGBA8, QSize{command.width, command.height}, samples(command));
514 score::gfx::replaceTexture(srb, command.binding, tex);
516 return reinterpret_cast<typename C::return_type
>(tex);
520 static_assert(C::unhandled);
524 else if constexpr(
requires { C::upload; })
526 if constexpr(
requires { C::texture; })
528 QRhiTextureSubresourceUploadDescription sub(command.data, command.size);
530 reinterpret_cast<QRhiTexture*
>(command.handle),
531 QRhiTextureUploadDescription{{0, 0, sub}});
535 auto buf =
reinterpret_cast<QRhiBuffer*
>(command.handle);
536 if constexpr(
requires { C::dynamic; })
537 res.updateDynamicBuffer(buf, command.offset, command.size, command.data);
539 requires { C::static_; } ||
requires { C::immutable; })
540 res.uploadStaticBuffer(buf, command.offset, command.size, command.data);
543 static_assert(C::unhandled);
548 else if constexpr(
requires { C::getter; })
550 if constexpr(
requires { C::ubo; })
552 auto buf = self.createdUbos.at(command.binding);
553 return reinterpret_cast<typename C::return_type
>(buf);
557 static_assert(C::unhandled);
563 handle_release{rhi}(command);
570struct generate_shaders
572 template <
typename T,
int N>
575 static constexpr std::string_view field_type(
float) {
return "float"; }
576 static constexpr std::string_view field_type(
const float (&)[2]) {
return "vec2"; }
577 static constexpr std::string_view field_type(
const float (&)[3]) {
return "vec3"; }
578 static constexpr std::string_view field_type(
const float (&)[4]) {
return "vec4"; }
580 static constexpr std::string_view field_type(
float*) {
return "float"; }
581 static constexpr std::string_view field_type(vec<float, 2>*) {
return "vec2"; }
582 static constexpr std::string_view field_type(vec<float, 3>*) {
return "vec3"; }
583 static constexpr std::string_view field_type(vec<float, 4>*) {
return "vec4"; }
585 static constexpr std::string_view field_type(
int) {
return "int"; }
586 static constexpr std::string_view field_type(
const int (&)[2]) {
return "ivec2"; }
587 static constexpr std::string_view field_type(
const int (&)[3]) {
return "ivec3"; }
588 static constexpr std::string_view field_type(
const int (&)[4]) {
return "ivec4"; }
590 static constexpr std::string_view field_type(
int*) {
return "int"; }
591 static constexpr std::string_view field_type(vec<int, 2>*) {
return "ivec2"; }
592 static constexpr std::string_view field_type(vec<int, 3>*) {
return "ivec3"; }
593 static constexpr std::string_view field_type(vec<int, 4>*) {
return "ivec4"; }
595 static constexpr std::string_view field_type(uint32_t) {
return "uint"; }
596 static constexpr std::string_view field_type(
const uint32_t (&)[2]) {
return "uvec2"; }
597 static constexpr std::string_view field_type(
const uint32_t (&)[3]) {
return "uvec3"; }
598 static constexpr std::string_view field_type(
const uint32_t (&)[4]) {
return "uvec4"; }
600 static constexpr std::string_view field_type(uint32_t*) {
return "uint"; }
601 static constexpr std::string_view field_type(vec<uint32_t, 2>*) {
return "uvec2"; }
602 static constexpr std::string_view field_type(vec<uint32_t, 3>*) {
return "uvec3"; }
603 static constexpr std::string_view field_type(vec<uint32_t, 4>*) {
return "uvec4"; }
605 static constexpr std::string_view field_type(avnd::xy_value
auto) {
return "vec2"; }
607 static constexpr bool field_array(
float) {
return false; }
608 static constexpr bool field_array(
const float (&)[2]) {
return false; }
609 static constexpr bool field_array(
const float (&)[3]) {
return false; }
610 static constexpr bool field_array(
const float (&)[4]) {
return false; }
612 static constexpr bool field_array(
float*) {
return true; }
613 static constexpr bool field_array(vec<float, 2>*) {
return true; }
614 static constexpr bool field_array(vec<float, 3>*) {
return true; }
615 static constexpr bool field_array(vec<float, 4>*) {
return true; }
617 static constexpr bool field_array(
int) {
return false; }
618 static constexpr bool field_array(
const int (&)[2]) {
return false; }
619 static constexpr bool field_array(
const int (&)[3]) {
return false; }
620 static constexpr bool field_array(
const int (&)[4]) {
return false; }
622 static constexpr bool field_array(
int*) {
return true; }
623 static constexpr bool field_array(vec<int, 2>*) {
return true; }
624 static constexpr bool field_array(vec<int, 3>*) {
return true; }
625 static constexpr bool field_array(vec<int, 4>*) {
return true; }
627 static constexpr bool field_array(uint32_t) {
return false; }
628 static constexpr bool field_array(
const uint32_t (&)[2]) {
return false; }
629 static constexpr bool field_array(
const uint32_t (&)[3]) {
return false; }
630 static constexpr bool field_array(
const uint32_t (&)[4]) {
return false; }
632 static constexpr bool field_array(uint32_t*) {
return true; }
633 static constexpr bool field_array(vec<uint32_t, 2>*) {
return true; }
634 static constexpr bool field_array(vec<uint32_t, 3>*) {
return true; }
635 static constexpr bool field_array(vec<uint32_t, 4>*) {
return true; }
637 static constexpr bool field_array(avnd::xy_value
auto) {
return false; }
639 template <
typename T>
640 static constexpr std::string_view image_qualifier()
642 if constexpr(
requires { T::readonly; })
644 else if constexpr(
requires { T::writeonly; })
647 static_assert(T::readonly || T::writeonly);
654 template <
typename T>
655 void operator()(
const T& field)
657 shader += fmt::format(
658 "layout(location = {}) in {} {};\n", T::location(), field_type(field.data),
667 template <
typename T>
668 void operator()(
const T& field)
670 if constexpr(
requires { field.location(); })
672 shader += fmt::format(
673 "layout(location = {}) out {} {};\n", T::location(), field_type(field.data),
683 template <
typename T>
684 void operator()(
const T& field)
686 shader += fmt::format(
687 " {} {}{};\n", field_type(field.value), T::name(),
688 field_array(field.value) ?
"[]" :
"");
692 struct write_bindings
696 template <
typename C>
697 void operator()(
const C& field)
699 if constexpr(
requires { C::sampler2D; })
701 shader += fmt::format(
702 "layout(binding = {}) uniform sampler2D {};\n\n", C::binding(), C::name());
704 else if constexpr(
requires { C::image2D; })
706 shader += fmt::format(
707 "layout(binding = {}, {}) {} uniform image2D {};\n\n", C::binding(),
708 C::format(), image_qualifier<C>(), C::name());
710 else if constexpr(
requires { C::ubo; })
712 shader += fmt::format(
713 "layout({}, binding = {}) uniform {}\n{{\n",
716 C::binding(), C::name());
718 boost::pfr::for_each_field(field, write_binding{shader});
720 shader += fmt::format(
"}};\n\n");
722 else if constexpr(
requires { C::buffer; })
724 shader += fmt::format(
725 "layout({}, binding = {}) buffer {}\n{{\n",
728 C::binding(), C::name());
730 boost::pfr::for_each_field(field, write_binding{shader});
732 shader += fmt::format(
"}};\n\n");
737 template <
typename T>
738 std::string vertex_shader(
const T& lay)
740 using namespace gpp::qrhi;
741 std::string shader =
"#version 450\n\n";
743 if constexpr(
requires { lay.vertex_input; })
744 boost::pfr::for_each_field(lay.vertex_input, write_input{shader});
745 else if constexpr(
requires {
typename T::vertex_input; })
746 boost::pfr::for_each_field(
typename T::vertex_input{}, write_input{shader});
748 boost::pfr::for_each_field(
749 DefaultPipeline::layout::vertex_input{}, write_input{shader});
751 if constexpr(
requires { lay.vertex_output; })
752 boost::pfr::for_each_field(lay.vertex_output, write_output{shader});
753 else if constexpr(
requires {
typename T::vertex_output; })
754 boost::pfr::for_each_field(
typename T::vertex_output{}, write_output{shader});
758 if constexpr(
requires { lay.bindings; })
759 boost::pfr::for_each_field(lay.bindings, write_bindings{shader});
760 else if constexpr(
requires {
typename T::bindings; })
761 boost::pfr::for_each_field(
typename T::bindings{}, write_bindings{shader});
766 template <
typename T>
767 std::string fragment_shader(
const T& lay)
769 std::string shader =
"#version 450\n\n";
771 if constexpr(
requires { lay.fragment_input; })
772 boost::pfr::for_each_field(lay.fragment_input, write_input{shader});
773 else if constexpr(
requires {
typename T::fragment_input; })
774 boost::pfr::for_each_field(
typename T::fragment_input{}, write_input{shader});
776 if constexpr(
requires { lay.fragment_output; })
777 boost::pfr::for_each_field(lay.fragment_output, write_output{shader});
778 else if constexpr(
requires {
typename T::fragment_output; })
779 boost::pfr::for_each_field(
typename T::fragment_output{}, write_output{shader});
783 if constexpr(
requires { lay.bindings; })
784 boost::pfr::for_each_field(lay.bindings, write_bindings{shader});
785 else if constexpr(
requires {
typename T::bindings; })
786 boost::pfr::for_each_field(
typename T::bindings{}, write_bindings{shader});
791 template <
typename T>
792 std::string compute_shader(
const T& lay)
794 std::string fstr =
"#version 450\n\n";
797 if constexpr(
requires { T::local_size_x(); })
799 fstr += fmt::format(
"local_size_x = {}, ", T::local_size_x());
801 if constexpr(
requires { T::local_size_y(); })
803 fstr += fmt::format(
"local_size_y = {}, ", T::local_size_y());
805 if constexpr(
requires { T::local_size_z(); })
807 fstr += fmt::format(
"local_size_z = {}, ", T::local_size_z());
811 fstr.resize(fstr.size() - 2);
814 boost::pfr::for_each_field(lay.bindings, write_bindings{fstr});
825 template <
typename Node>
826 static void initWorker(Node& state)
noexcept
828 if constexpr(avnd::has_worker<Node>)
830 using worker_type =
decltype(state.worker);
832 state.worker.request = [&state]<
typename... Args>(Args&&... f) {
833 using type_of_result =
decltype(worker_type::work(std::forward<Args>(f)...));
834 if constexpr(std::is_void_v<type_of_result>)
836 worker_type::work(std::forward<Args>(f)...);
842 auto res = worker_type::work(std::forward<Args>(f)...);
852template <
typename GpuNodeRenderer,
typename Node>
855 GpuNodeRenderer& gpu;
861 bool can_process_message(std::size_t N)
863 if(mess.input.size() <= N)
866 if(prev_mess.input.size() == mess.input.size())
868 auto& prev = prev_mess.input[N];
869 auto& next = mess.input[N];
870 if(prev.index() == 1 && next.index() == 1)
872 if(ossia::get<ossia::value>(prev) == ossia::get<ossia::value>(next))
881 void operator()(avnd::parameter
auto& t,
auto field_index)
883 if(!can_process_message(field_index))
886 if(
auto val = ossia::get_if<ossia::value>(&mess.input[field_index]))
888 oscr::from_ossia_value(t, *val, t.value);
889 if_possible(t.update(state));
893#if OSCR_HAS_MMAP_FILE_STORAGE
894 template <avnd::raw_file_port Field, std::
size_t NField>
895 void operator()(Field& t, avnd::field_index<NField> field_index)
898 using node_type = std::remove_cvref_t<
decltype(gpu.parent)>;
899 using file_ports = avnd::raw_file_input_introspection<Node>;
901 if(!can_process_message(field_index))
904 auto val = ossia::get_if<ossia::value>(&mess.input[field_index]);
908 static constexpr bool has_text =
requires {
decltype(Field::file)::text; };
909 static constexpr bool has_mmap =
requires {
decltype(Field::file)::mmap; };
912 if(
auto hdl = loadRawfile(*val, ctx, has_text, has_mmap))
914 static constexpr auto N = file_ports::field_index_to_index(NField);
915 if constexpr(avnd::port_can_process<Field>)
919 auto func = executePortPreprocess<Field>(*hdl);
920 const_cast<node_type&
>(gpu.parent)
922 state, hdl, avnd::predicate_index<N>{}, avnd::field_index<NField>{});
928 const_cast<node_type&
>(gpu.parent)
930 state, hdl, avnd::predicate_index<N>{}, avnd::field_index<NField>{});
936 void operator()(
auto& t,
auto field_index) { }
941 template <
typename Self,
typename Node_T>
942 static void processControlIn(
947 avnd::input_introspection<Node_T>::for_all_n(
948 avnd::get_inputs<Node_T>(state),
949 GpuProcessIns<Self, Node_T>{self, state, renderer_mess, mess, ctx});
950 renderer_mess = mess;
956 std::weak_ptr<Execution::ExecutionCommandQueue> queue;
957 Gfx::exec_controls control_outs;
961 template <
typename Node_T>
962 void processControlOut(Node_T& state)
const noexcept
964 if(!this->control_outs.empty())
966 auto q = this->queue.lock();
971 avnd::parameter_output_introspection<Node_T>::for_all(
972 avnd::get_outputs(state), [&]<avnd::parameter T>(
const T& t) {
973 qq.enqueue([v = oscr::to_ossia_value(t, t.value),
974 port = control_outs[parm_k]]()
mutable {
975 std::swap(port->value, v);
976 port->changed = true;
986struct SCORE_PLUGIN_AVND_EXPORT GpuNodeElements
988 [[no_unique_address]] oscr::soundfile_storage<T> soundfiles;
990 [[no_unique_address]] oscr::midifile_storage<T> midifiles;
992#if defined(OSCR_HAS_MMAP_FILE_STORAGE)
993 [[no_unique_address]] oscr::raw_file_storage<T> rawfiles;
996 template <std::
size_t N, std::
size_t NField>
998 auto& state,
const std::shared_ptr<oscr::raw_file_data>& hdl,
999 avnd::predicate_index<N>, avnd::field_index<NField>)
1001 this->rawfiles.load(
1002 state, hdl, avnd::predicate_index<N>{}, avnd::field_index<NField>{});
1009 :
score::gfx::NodeModel{}
1013 virtual ~CustomGfxNodeBase();
1020 virtual ~CustomGfxOutputNodeBase();
1025struct CustomGpuNodeBase
1032 std::weak_ptr<Execution::ExecutionCommandQueue>&& q, Gfx::exec_controls&& ctls,
1034 : GpuControlOuts{
std::move(q),
std::move(ctls)}
1039 virtual ~CustomGpuNodeBase() =
default;
1042 QString vertex, fragment, compute;
1047struct SCORE_PLUGIN_AVND_EXPORT CustomGpuOutputNodeBase
1053 CustomGpuOutputNodeBase(
1054 std::weak_ptr<Execution::ExecutionCommandQueue> q, Gfx::exec_controls&& ctls,
1056 virtual ~CustomGpuOutputNodeBase();
1059 std::weak_ptr<score::gfx::RenderList> m_renderer{};
1060 std::shared_ptr<score::gfx::RenderState> m_renderState{};
1061 std::function<void()> m_update;
1063 QString vertex, fragment, compute;
1067 void setRenderer(std::shared_ptr<score::gfx::RenderList>)
override;
1070 void startRendering()
override;
1071 void render()
override;
1072 void stopRendering()
override;
1073 bool canRender()
const override;
1074 void onRendererChange()
override;
1078 std::function<
void()> onUpdate, std::function<
void()> onResize)
override;
1080 void destroyOutput()
override;
1081 std::shared_ptr<score::gfx::RenderState> renderState()
const override;
1083 Configuration configuration() const noexcept override;
1086template <typename Node_T, typename Node>
1087void prepareNewState(Node_T& eff, const Node& parent)
1089 if constexpr(avnd::has_worker<Node_T>)
1091 parent.initWorker(eff);
1093 if constexpr(avnd::has_processor_to_gui_bus<Node_T>)
1095 auto& process = parent.processModel;
1096 eff.send_message = [&process](
auto&& b)
mutable {
1101 MessageBusSender{process.to_ui}(std::move(b));
1108 avnd::init_controls(eff);
1110 if constexpr(avnd::can_prepare<Node_T>)
1112 using prepare_type = avnd::first_argument<&Node_T::prepare>;
1114 if_possible(t.instance = parent.instance);
1119struct port_to_type_enum
1121 template <std::
size_t I, avnd::cpu_texture_port F>
1122 constexpr auto operator()(avnd::field_reflection<I, F> p)
1124 using texture_type = std::remove_cvref_t<
decltype(F::texture)>;
1125 return avnd::cpu_fixed_format_texture<texture_type> ? score::gfx::Types::Image
1126 : score::gfx::Types::Buffer;
1128 template <std::
size_t I, avnd::sampler_port F>
1129 constexpr auto operator()(avnd::field_reflection<I, F> p)
1131 return score::gfx::Types::Image;
1133 template <std::
size_t I, avnd::image_port F>
1134 constexpr auto operator()(avnd::field_reflection<I, F> p)
1136 return score::gfx::Types::Image;
1138 template <std::
size_t I, avnd::attachment_port F>
1139 constexpr auto operator()(avnd::field_reflection<I, F> p)
1141 return score::gfx::Types::Image;
1144 template <std::
size_t I, avnd::geometry_port F>
1145 constexpr auto operator()(avnd::field_reflection<I, F> p)
1147 return score::gfx::Types::Geometry;
1149 template <std::
size_t I, avnd::mono_audio_port F>
1150 constexpr auto operator()(avnd::field_reflection<I, F> p)
1152 return score::gfx::Types::Audio;
1154 template <std::
size_t I, avnd::poly_audio_port F>
1155 constexpr auto operator()(avnd::field_reflection<I, F> p)
1157 return score::gfx::Types::Audio;
1159 template <std::
size_t I, avnd::
int_parameter F>
1160 constexpr auto operator()(avnd::field_reflection<I, F> p)
1162 return score::gfx::Types::Int;
1164 template <std::
size_t I, avnd::enum_parameter F>
1165 constexpr auto operator()(avnd::field_reflection<I, F> p)
1167 return score::gfx::Types::Int;
1169 template <std::
size_t I, avnd::
float_parameter F>
1170 constexpr auto operator()(avnd::field_reflection<I, F> p)
1172 return score::gfx::Types::Float;
1174 template <std::
size_t I, avnd::parameter F>
1175 constexpr auto operator()(avnd::field_reflection<I, F> p)
1177 using value_type = std::remove_cvref_t<
decltype(F::value)>;
1179 if constexpr(std::is_aggregate_v<value_type>)
1181 constexpr int sz = boost::pfr::tuple_size_v<value_type>;
1182 if constexpr(sz == 2)
1184 return score::gfx::Types::Vec2;
1186 else if constexpr(sz == 3)
1188 return score::gfx::Types::Vec3;
1190 else if constexpr(sz == 4)
1192 return score::gfx::Types::Vec4;
1195 return score::gfx::Types::Empty;
1197 template <std::
size_t I,
typename F>
1198 constexpr auto operator()(avnd::field_reflection<I, F> p)
1200 return score::gfx::Types::Empty;
1204template <
typename Node_T>
1205inline void initGfxPorts(
auto* self,
auto& input,
auto& output)
1207 avnd::input_introspection<Node_T>::for_all(
1208 [self, &input]<
typename Field, std::size_t I>(avnd::field_reflection<I, Field> f) {
1209 static constexpr auto type = port_to_type_enum{}(f);
1212 avnd::output_introspection<Node_T>::for_all(
1214 &output]<
typename Field, std::size_t I>(avnd::field_reflection<I, Field> f) {
1215 static constexpr auto type = port_to_type_enum{}(f);
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
Port of a score::gfx::Node.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:48