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>
13#include <score/tools/ThreadPool.hpp>
15#include <ossia-qt/invoke.hpp>
17#include <QCoreApplication>
19#include <QtGui/private/qrhi_p.h>
21#include <avnd/binding/ossia/port_run_postprocess.hpp>
22#include <avnd/binding/ossia/port_run_preprocess.hpp>
23#include <avnd/binding/ossia/soundfiles.hpp>
24#include <avnd/concepts/parameter.hpp>
25#include <avnd/introspection/input.hpp>
26#include <avnd/introspection/output.hpp>
27#include <fmt/format.h>
28#include <gpp/layout.hpp>
30#include <score_plugin_avnd_export.h>
36 requires std::is_enum_v<F>
37constexpr QRhiTexture::Format textureFormat(F f)
noexcept
39 if constexpr(
requires { F::RGBA; } ||
requires { F::RGBA8; })
41 return QRhiTexture::RGBA8;
42 if constexpr(
requires { F::BGRA; } ||
requires { F::BGRA8; })
44 return QRhiTexture::BGRA8;
45 if constexpr(
requires { F::R8; } ||
requires { F::GRAYSCALE; })
47 return QRhiTexture::R8;
48#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
49 if constexpr(
requires { F::RG8; })
51 return QRhiTexture::RG8;
53 if constexpr(
requires { F::R16; })
55 return QRhiTexture::R16;
56#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
57 if constexpr(
requires { F::RG16; })
59 return QRhiTexture::RG16;
61 if constexpr(
requires { F::RED_OR_ALPHA8; })
62 if(f == F::RED_OR_ALPHA8)
63 return QRhiTexture::RED_OR_ALPHA8;
64 if constexpr(
requires { F::RGBA16F; })
66 return QRhiTexture::RGBA16F;
67 if constexpr(
requires { F::RGBA32F; })
69 return QRhiTexture::RGBA32F;
70 if constexpr(
requires { F::R16F; })
72 return QRhiTexture::R16F;
73 if constexpr(
requires { F::R32F; })
75 return QRhiTexture::R32F;
76#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
77 if constexpr(
requires { F::RGB10A2; })
79 return QRhiTexture::RGB10A2;
81 if constexpr(
requires { F::D16; })
83 return QRhiTexture::D16;
85#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
86 if constexpr(
requires { F::D24; })
88 return QRhiTexture::D24;
89 if constexpr(
requires { F::D24S8; })
91 return QRhiTexture::D24S8;
93 if constexpr(
requires { F::D32F; })
95 return QRhiTexture::D32F;
97 if constexpr(
requires { F::BC1; })
99 return QRhiTexture::BC1;
100 if constexpr(
requires { F::BC2; })
102 return QRhiTexture::BC2;
103 if constexpr(
requires { F::BC3; })
105 return QRhiTexture::BC3;
106 if constexpr(
requires { F::BC4; })
108 return QRhiTexture::BC4;
109 if constexpr(
requires { F::BC5; })
111 return QRhiTexture::BC5;
112 if constexpr(
requires { F::BC6H; })
114 return QRhiTexture::BC6H;
115 if constexpr(
requires { F::BC7; })
117 return QRhiTexture::BC7;
118 if constexpr(
requires { F::ETC2_RGB8; })
119 if(f == F::ETC2_RGB8)
120 return QRhiTexture::ETC2_RGB8;
121 if constexpr(
requires { F::ETC2_RGB8A1; })
122 if(f == F::ETC2_RGB8A1)
123 return QRhiTexture::ETC2_RGB8A1;
124 if constexpr(
requires { F::ETC2_RGB8A8; })
125 if(f == F::ETC2_RGBA8)
126 return QRhiTexture::ETC2_RGBA8;
127 if constexpr(
requires { F::ASTC_4X4; })
129 return QRhiTexture::ASTC_4x4;
130 if constexpr(
requires { F::ASTC_5X4; })
132 return QRhiTexture::ASTC_5x4;
133 if constexpr(
requires { F::ASTC_5X5; })
135 return QRhiTexture::ASTC_5x5;
136 if constexpr(
requires { F::ASTC_6X5; })
138 return QRhiTexture::ASTC_6x5;
139 if constexpr(
requires { F::ASTC_6X6; })
141 return QRhiTexture::ASTC_6x6;
142 if constexpr(
requires { F::ASTC_8X5; })
144 return QRhiTexture::ASTC_8x5;
145 if constexpr(
requires { F::ASTC_8X6; })
147 return QRhiTexture::ASTC_8x6;
148 if constexpr(
requires { F::ASTC_8X8; })
150 return QRhiTexture::ASTC_8x8;
151 if constexpr(
requires { F::ASTC_10X5; })
152 if(f == F::ASTC_10x5)
153 return QRhiTexture::ASTC_10x5;
154 if constexpr(
requires { F::ASTC_10X6; })
155 if(f == F::ASTC_10x6)
156 return QRhiTexture::ASTC_10x6;
157 if constexpr(
requires { F::ASTC_10X8; })
158 if(f == F::ASTC_10x8)
159 return QRhiTexture::ASTC_10x8;
160 if constexpr(
requires { F::ASTC_10X10; })
161 if(f == F::ASTC_10x10)
162 return QRhiTexture::ASTC_10x10;
163 if constexpr(
requires { F::ASTC_12X10; })
164 if(f == F::ASTC_12x10)
165 return QRhiTexture::ASTC_12x10;
166 if constexpr(
requires { F::ASTC_12X12; })
167 if(f == F::ASTC_12x12)
168 return QRhiTexture::ASTC_12x12;
169 if constexpr(
requires { F::RGB; })
171 return QRhiTexture::RGBA8;
173 return QRhiTexture::RGBA8;
177constexpr QRhiTexture::Format textureFormat() noexcept
179 if constexpr(
requires { std::string_view{F::format()}; })
181 constexpr std::string_view fmt = F::format();
183 if(fmt ==
"rgba" || fmt ==
"rgba8")
184 return QRhiTexture::RGBA8;
185 else if(fmt ==
"bgra" || fmt ==
"bgra8")
186 return QRhiTexture::BGRA8;
188 return QRhiTexture::R8;
189#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
190 else if(fmt ==
"rg8")
191 return QRhiTexture::RG8;
193 else if(fmt ==
"r16")
194 return QRhiTexture::R16;
195#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
196 else if(fmt ==
"rg16")
197 return QRhiTexture::RG16;
199 else if(fmt ==
"red_or_alpha8")
200 return QRhiTexture::RED_OR_ALPHA8;
201 else if(fmt ==
"rgba16f")
202 return QRhiTexture::RGBA16F;
203 else if(fmt ==
"rgba32f")
204 return QRhiTexture::RGBA32F;
205 else if(fmt ==
"r16f")
206 return QRhiTexture::R16F;
207 else if(fmt ==
"r32")
208 return QRhiTexture::R32F;
209#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
210 else if(fmt ==
"rgb10a2")
211 return QRhiTexture::RGB10A2;
214 else if(fmt ==
"d16")
215 return QRhiTexture::D16;
217#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
218 else if(fmt ==
"d24")
219 return QRhiTexture::D24;
220 else if(fmt ==
"d24s8")
221 return QRhiTexture::D24S8;
223 else if(fmt ==
"d32f")
224 return QRhiTexture::D32F;
226 else if(fmt ==
"bc1")
227 return QRhiTexture::BC1;
228 else if(fmt ==
"bc2")
229 return QRhiTexture::BC2;
230 else if(fmt ==
"bc3")
231 return QRhiTexture::BC3;
232 else if(fmt ==
"bc4")
233 return QRhiTexture::BC4;
234 else if(fmt ==
"bc5")
235 return QRhiTexture::BC5;
236 else if(fmt ==
"bc6h")
237 return QRhiTexture::BC6H;
238 else if(fmt ==
"bc7")
239 return QRhiTexture::BC7;
240 else if(fmt ==
"etc2_rgb8")
241 return QRhiTexture::ETC2_RGB8;
242 else if(fmt ==
"etc2_rgb8a1")
243 return QRhiTexture::ETC2_RGB8A1;
244 else if(fmt ==
"etc2_rgb8a8")
245 return QRhiTexture::ETC2_RGBA8;
246 else if(fmt ==
"astc_4x4")
247 return QRhiTexture::ASTC_4x4;
248 else if(fmt ==
"astc_5x4")
249 return QRhiTexture::ASTC_5x4;
250 else if(fmt ==
"astc_5x5")
251 return QRhiTexture::ASTC_5x5;
252 else if(fmt ==
"astc_6x5")
253 return QRhiTexture::ASTC_6x5;
254 else if(fmt ==
"astc_6x6")
255 return QRhiTexture::ASTC_6x6;
256 else if(fmt ==
"astc_8x5")
257 return QRhiTexture::ASTC_8x5;
258 else if(fmt ==
"astc_8x6")
259 return QRhiTexture::ASTC_8x6;
260 else if(fmt ==
"astc_8x8")
261 return QRhiTexture::ASTC_8x8;
262 else if(fmt ==
"astc_10x5")
263 return QRhiTexture::ASTC_10x5;
264 else if(fmt ==
"astc_10x6")
265 return QRhiTexture::ASTC_10x6;
266 else if(fmt ==
"astc_10x8")
267 return QRhiTexture::ASTC_10x8;
268 else if(fmt ==
"astc_10x10")
269 return QRhiTexture::ASTC_10x10;
270 else if(fmt ==
"astc_12x10")
271 return QRhiTexture::ASTC_12x10;
272 else if(fmt ==
"astc_12x12")
273 return QRhiTexture::ASTC_12x12;
274 else if(fmt ==
"rgb")
275 return QRhiTexture::RGBA8;
277 return QRhiTexture::RGBA8;
279 else if constexpr(std::is_enum_v<typename F::format>)
281 if constexpr(
requires { F::RGBA; } ||
requires { F::RGBA8; })
282 return QRhiTexture::RGBA8;
283 else if constexpr(
requires { F::BGRA; } ||
requires { F::BGRA8; })
284 return QRhiTexture::BGRA8;
285 else if constexpr(
requires { F::R8; } ||
requires { F::GRAYSCALE; })
286 return QRhiTexture::R8;
287#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
288 else if constexpr(
requires { F::RG8; })
289 return QRhiTexture::RG8;
291 else if constexpr(
requires { F::R16; })
292 return QRhiTexture::R16;
293#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
294 else if constexpr(
requires { F::RG16; })
295 return QRhiTexture::RG16;
297 else if constexpr(
requires { F::RED_OR_ALPHA8; })
298 return QRhiTexture::RED_OR_ALPHA8;
299 else if constexpr(
requires { F::RGBA16F; })
300 return QRhiTexture::RGBA16F;
301 else if constexpr(
requires { F::RGBA32F; })
302 return QRhiTexture::RGBA32F;
303 else if constexpr(
requires { F::R16F; })
304 return QRhiTexture::R16F;
305 else if constexpr(
requires { F::R32F; })
306 return QRhiTexture::R32F;
307#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
308 else if constexpr(
requires { F::RGB10A2; })
309 return QRhiTexture::RGB10A2;
311 else if constexpr(
requires { F::D16; })
312 return QRhiTexture::D16;
314#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
315 else if constexpr(
requires { F::D24; })
316 return QRhiTexture::D24;
317 else if constexpr(
requires { F::D24S8; })
318 return QRhiTexture::D24S8;
320 else if constexpr(
requires { F::D32F; })
321 return QRhiTexture::D32F;
323 else if constexpr(
requires { F::BC1; })
324 return QRhiTexture::BC1;
325 else if constexpr(
requires { F::BC2; })
326 return QRhiTexture::BC2;
327 else if constexpr(
requires { F::BC3; })
328 return QRhiTexture::BC3;
329 else if constexpr(
requires { F::BC4; })
330 return QRhiTexture::BC4;
331 else if constexpr(
requires { F::BC5; })
332 return QRhiTexture::BC5;
333 else if constexpr(
requires { F::BC6H; })
334 return QRhiTexture::BC6H;
335 else if constexpr(
requires { F::BC7; })
336 return QRhiTexture::BC7;
337 else if constexpr(
requires { F::ETC2_RGB8; })
338 return QRhiTexture::ETC2_RGB8;
339 else if constexpr(
requires { F::ETC2_RGB8A1; })
340 return QRhiTexture::ETC2_RGB8A1;
341 else if constexpr(
requires { F::ETC2_RGB8A8; })
342 return QRhiTexture::ETC2_RGBA8;
343 else if constexpr(
requires { F::ASTC_4X4; })
344 return QRhiTexture::ASTC_4x4;
345 else if constexpr(
requires { F::ASTC_5X4; })
346 return QRhiTexture::ASTC_5x4;
347 else if constexpr(
requires { F::ASTC_5X5; })
348 return QRhiTexture::ASTC_5x5;
349 else if constexpr(
requires { F::ASTC_6X5; })
350 return QRhiTexture::ASTC_6x5;
351 else if constexpr(
requires { F::ASTC_6X6; })
352 return QRhiTexture::ASTC_6x6;
353 else if constexpr(
requires { F::ASTC_8X5; })
354 return QRhiTexture::ASTC_8x5;
355 else if constexpr(
requires { F::ASTC_8X6; })
356 return QRhiTexture::ASTC_8x6;
357 else if constexpr(
requires { F::ASTC_8X8; })
358 return QRhiTexture::ASTC_8x8;
359 else if constexpr(
requires { F::ASTC_10X5; })
360 return QRhiTexture::ASTC_10x5;
361 else if constexpr(
requires { F::ASTC_10X6; })
362 return QRhiTexture::ASTC_10x6;
363 else if constexpr(
requires { F::ASTC_10X8; })
364 return QRhiTexture::ASTC_10x8;
365 else if constexpr(
requires { F::ASTC_10X10; })
366 return QRhiTexture::ASTC_10x10;
367 else if constexpr(
requires { F::ASTC_12X10; })
368 return QRhiTexture::ASTC_12x10;
369 else if constexpr(
requires { F::ASTC_12X12; })
370 return QRhiTexture::ASTC_12x12;
371 else if constexpr(
requires { F::RGB; })
372 return QRhiTexture::RGBA8;
374 return QRhiTexture::RGBA8;
378template <avnd::cpu_texture Tex>
379constexpr QRhiTexture::Format textureFormat(
const Tex& t)
noexcept
381 QRhiTexture::Format fmt{};
382 if constexpr(avnd::cpu_dynamic_format_texture<Tex>)
383 fmt = gpp::qrhi::textureFormat(t.format);
385 fmt = gpp::qrhi::textureFormat<Tex>();
389struct DefaultPipeline
401 static constexpr auto name() {
return "position"; }
402 static constexpr int location() {
return 0; }
409 struct fragment_input
417 static QString vertex()
419 return R
"_(#version 450
420layout(location = 0) in vec2 position;
421out gl_PerVertex { vec4 gl_Position; };
423 gl_Position = vec4( position, 0.0, 1.0 );
430constexpr auto usage()
432 if constexpr(
requires { C::vertex; })
433 return QRhiBuffer::VertexBuffer;
434 else if constexpr(
requires { C::index; })
435 return QRhiBuffer::IndexBuffer;
436 else if constexpr(
requires { C::ubo; })
437 return QRhiBuffer::UniformBuffer;
438 else if constexpr(
requires { C::storage; })
439 return QRhiBuffer::StorageBuffer;
442 static_assert(C::unhandled);
448constexpr auto buffer_type()
450 if constexpr(
requires { C::immutable; })
451 return QRhiBuffer::Immutable;
452 else if constexpr(
requires { C::static_; })
453 return QRhiBuffer::Static;
454 else if constexpr(
requires { C::dynamic; })
455 return QRhiBuffer::Dynamic;
458 static_assert(C::unhandled);
466 if constexpr(
requires { C::samples; })
475 template <
typename C>
476 void operator()(C command)
478 if constexpr(
requires { C::deallocation; })
481 requires { C::vertex; } ||
requires { C::index; } ||
requires { C::ubo; })
483 auto buf =
reinterpret_cast<QRhiBuffer*
>(command.handle);
486 else if constexpr(
requires { C::sampler; })
488 auto buf =
reinterpret_cast<QRhiSampler*
>(command.handle);
491 else if constexpr(
requires { C::texture; })
493 auto buf =
reinterpret_cast<QRhiTexture*
>(command.handle);
498 static_assert(C::unhandled);
503 static_assert(C::unhandled);
508template <
typename Self,
typename Res>
509struct handle_dispatch
513 QRhiCommandBuffer& cb;
514 QRhiResourceUpdateBatch*& res;
515 QRhiComputePipeline& pip;
516 template <
typename C>
517 Res operator()(C command)
519 if constexpr(
requires { C::compute; })
521 if constexpr(
requires { C::dispatch; })
523 cb.dispatch(command.x, command.y, command.z);
526 else if constexpr(
requires { C::begin; })
528 cb.beginComputePass(res);
530 cb.setComputePipeline(&pip);
531 cb.setShaderResources(pip.shaderResourceBindings());
535 else if constexpr(
requires { C::end; })
537 cb.endComputePass(res);
544 static_assert(C::unhandled);
548 else if constexpr(
requires { C::readback; })
551 if constexpr(
requires { C::request; })
553 if constexpr(
requires { C::buffer; })
555 using ret =
typename C::return_type;
557#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
558 auto readback =
new QRhiBufferReadbackResult;
560 auto readback =
new QRhiReadbackResult;
562 self.addReadback(readback);
565 ret user_rb{.handle =
reinterpret_cast<decltype(ret::handle)
>(readback)};
576 auto next = rhi.nextResourceUpdateBatch();
577 auto buf =
reinterpret_cast<QRhiBuffer*
>(command.handle);
579 next->readBackBuffer(buf, command.offset, command.size, readback);
584 else if constexpr(
requires { C::texture; })
586 using ret =
typename C::return_type;
587 QRhiReadbackResult readback;
592 static_assert(C::unhandled);
596 else if constexpr(
requires { C::await; })
598 if constexpr(
requires { C::buffer; })
600 using ret =
typename C::return_type;
602#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
603 auto readback =
reinterpret_cast<QRhiBufferReadbackResult*
>(command.handle);
605 auto readback =
reinterpret_cast<QRhiReadbackResult*
>(command.handle);
609 .data = readback->data.data(), .size = (std::size_t)readback->data.size()};
611 else if constexpr(
requires { C::texture; })
613 using ret =
typename C::return_type;
615 auto readback =
reinterpret_cast<QRhiReadbackResult*
>(command.handle);
618 .data = readback->data.data(), .size = (std::size_t)readback->data.size()};
624 static_assert(C::unhandled);
632template <
typename Self,
typename Ret>
637 QRhiResourceUpdateBatch& res;
638 std::vector<QRhiShaderResourceBinding>& srb;
641 template <
typename C>
642 Ret operator()(C command)
644 if constexpr(
requires { C::allocation; })
647 requires { C::vertex; } ||
requires { C::index; })
649 auto buf = rhi.newBuffer(buffer_type<C>(), usage<C>(), command.size);
651 return reinterpret_cast<typename C::return_type
>(buf);
653 else if constexpr(
requires { C::sampler; })
655 auto buf = rhi.newSampler({}, {}, {}, {}, {});
657 return reinterpret_cast<typename C::return_type
>(buf);
660 requires { C::ubo; } ||
requires { C::storage; })
662 auto buf = rhi.newBuffer(buffer_type<C>(), usage<C>(), command.size);
666 score::gfx::replaceBuffer(srb, command.binding, buf);
668 return reinterpret_cast<typename C::return_type
>(buf);
670 else if constexpr(
requires { C::texture; })
672 auto tex = rhi.newTexture(
673 QRhiTexture::RGBA8, QSize{command.width, command.height}, samples(command));
676 score::gfx::replaceTexture(srb, command.binding, tex);
678 return reinterpret_cast<typename C::return_type
>(tex);
682 static_assert(C::unhandled);
686 else if constexpr(
requires { C::upload; })
688 if constexpr(
requires { C::texture; })
690 QRhiTextureSubresourceUploadDescription sub(command.data, command.size);
692 reinterpret_cast<QRhiTexture*
>(command.handle),
693 QRhiTextureUploadDescription{{0, 0, sub}});
697 auto buf =
reinterpret_cast<QRhiBuffer*
>(command.handle);
698 if constexpr(
requires { C::dynamic; })
699 res.updateDynamicBuffer(buf, command.offset, command.size, command.data);
701 requires { C::static_; } ||
requires { C::immutable; })
702 res.uploadStaticBuffer(buf, command.offset, command.size, command.data);
705 static_assert(C::unhandled);
710 else if constexpr(
requires { C::getter; })
712 if constexpr(
requires { C::ubo; })
714 auto buf = self.createdUbos.at(command.binding);
715 return reinterpret_cast<typename C::return_type
>(buf);
719 static_assert(C::unhandled);
725 handle_release{rhi}(command);
732struct generate_shaders
734 template <
typename T,
int N>
737 static constexpr std::string_view field_type(
float) {
return "float"; }
738 static constexpr std::string_view field_type(
const float (&)[2]) {
return "vec2"; }
739 static constexpr std::string_view field_type(
const float (&)[3]) {
return "vec3"; }
740 static constexpr std::string_view field_type(
const float (&)[4]) {
return "vec4"; }
742 static constexpr std::string_view field_type(
float*) {
return "float"; }
743 static constexpr std::string_view field_type(vec<float, 2>*) {
return "vec2"; }
744 static constexpr std::string_view field_type(vec<float, 3>*) {
return "vec3"; }
745 static constexpr std::string_view field_type(vec<float, 4>*) {
return "vec4"; }
747 static constexpr std::string_view field_type(
int) {
return "int"; }
748 static constexpr std::string_view field_type(
const int (&)[2]) {
return "ivec2"; }
749 static constexpr std::string_view field_type(
const int (&)[3]) {
return "ivec3"; }
750 static constexpr std::string_view field_type(
const int (&)[4]) {
return "ivec4"; }
752 static constexpr std::string_view field_type(
int*) {
return "int"; }
753 static constexpr std::string_view field_type(vec<int, 2>*) {
return "ivec2"; }
754 static constexpr std::string_view field_type(vec<int, 3>*) {
return "ivec3"; }
755 static constexpr std::string_view field_type(vec<int, 4>*) {
return "ivec4"; }
757 static constexpr std::string_view field_type(uint32_t) {
return "uint"; }
758 static constexpr std::string_view field_type(
const uint32_t (&)[2]) {
return "uvec2"; }
759 static constexpr std::string_view field_type(
const uint32_t (&)[3]) {
return "uvec3"; }
760 static constexpr std::string_view field_type(
const uint32_t (&)[4]) {
return "uvec4"; }
762 static constexpr std::string_view field_type(uint32_t*) {
return "uint"; }
763 static constexpr std::string_view field_type(vec<uint32_t, 2>*) {
return "uvec2"; }
764 static constexpr std::string_view field_type(vec<uint32_t, 3>*) {
return "uvec3"; }
765 static constexpr std::string_view field_type(vec<uint32_t, 4>*) {
return "uvec4"; }
767 static constexpr std::string_view field_type(avnd::xy_value
auto) {
return "vec2"; }
769 static constexpr bool field_array(
float) {
return false; }
770 static constexpr bool field_array(
const float (&)[2]) {
return false; }
771 static constexpr bool field_array(
const float (&)[3]) {
return false; }
772 static constexpr bool field_array(
const float (&)[4]) {
return false; }
774 static constexpr bool field_array(
float*) {
return true; }
775 static constexpr bool field_array(vec<float, 2>*) {
return true; }
776 static constexpr bool field_array(vec<float, 3>*) {
return true; }
777 static constexpr bool field_array(vec<float, 4>*) {
return true; }
779 static constexpr bool field_array(
int) {
return false; }
780 static constexpr bool field_array(
const int (&)[2]) {
return false; }
781 static constexpr bool field_array(
const int (&)[3]) {
return false; }
782 static constexpr bool field_array(
const int (&)[4]) {
return false; }
784 static constexpr bool field_array(
int*) {
return true; }
785 static constexpr bool field_array(vec<int, 2>*) {
return true; }
786 static constexpr bool field_array(vec<int, 3>*) {
return true; }
787 static constexpr bool field_array(vec<int, 4>*) {
return true; }
789 static constexpr bool field_array(uint32_t) {
return false; }
790 static constexpr bool field_array(
const uint32_t (&)[2]) {
return false; }
791 static constexpr bool field_array(
const uint32_t (&)[3]) {
return false; }
792 static constexpr bool field_array(
const uint32_t (&)[4]) {
return false; }
794 static constexpr bool field_array(uint32_t*) {
return true; }
795 static constexpr bool field_array(vec<uint32_t, 2>*) {
return true; }
796 static constexpr bool field_array(vec<uint32_t, 3>*) {
return true; }
797 static constexpr bool field_array(vec<uint32_t, 4>*) {
return true; }
799 static constexpr bool field_array(avnd::xy_value
auto) {
return false; }
801 template <
typename T>
802 static constexpr std::string_view image_qualifier()
804 if constexpr(
requires { T::readonly; })
806 else if constexpr(
requires { T::writeonly; })
809 static_assert(T::readonly || T::writeonly);
816 template <
typename T>
817 void operator()(
const T& field)
819 shader += fmt::format(
820 "layout(location = {}) in {} {};\n", T::location(), field_type(field.data),
829 template <
typename T>
830 void operator()(
const T& field)
832 if constexpr(
requires { field.location(); })
834 shader += fmt::format(
835 "layout(location = {}) out {} {};\n", T::location(), field_type(field.data),
845 template <
typename T>
846 void operator()(
const T& field)
848 shader += fmt::format(
849 " {} {}{};\n", field_type(field.value), T::name(),
850 field_array(field.value) ?
"[]" :
"");
854 struct write_bindings
858 template <
typename C>
859 void operator()(
const C& field)
861 if constexpr(
requires { C::sampler2D; })
863 shader += fmt::format(
864 "layout(binding = {}) uniform sampler2D {};\n\n", C::binding(), C::name());
866 else if constexpr(
requires { C::image2D; })
868 shader += fmt::format(
869 "layout(binding = {}, {}) {} uniform image2D {};\n\n", C::binding(),
870 C::format(), image_qualifier<C>(), C::name());
872 else if constexpr(
requires { C::ubo; })
874 shader += fmt::format(
875 "layout({}, binding = {}) uniform {}\n{{\n",
878 C::binding(), C::name());
880 boost::pfr::for_each_field(field, write_binding{shader});
882 shader += fmt::format(
"}};\n\n");
884 else if constexpr(
requires { C::buffer; })
886 shader += fmt::format(
887 "layout({}, binding = {}) buffer {}\n{{\n",
890 C::binding(), C::name());
892 boost::pfr::for_each_field(field, write_binding{shader});
894 shader += fmt::format(
"}};\n\n");
899 template <
typename T>
900 std::string vertex_shader(
const T& lay)
902 using namespace gpp::qrhi;
903 std::string shader =
"#version 450\n\n";
905 if constexpr(
requires { lay.vertex_input; })
906 boost::pfr::for_each_field(lay.vertex_input, write_input{shader});
907 else if constexpr(
requires {
typename T::vertex_input; })
908 boost::pfr::for_each_field(
typename T::vertex_input{}, write_input{shader});
910 boost::pfr::for_each_field(
911 DefaultPipeline::layout::vertex_input{}, write_input{shader});
913 if constexpr(
requires { lay.vertex_output; })
914 boost::pfr::for_each_field(lay.vertex_output, write_output{shader});
915 else if constexpr(
requires {
typename T::vertex_output; })
916 boost::pfr::for_each_field(
typename T::vertex_output{}, write_output{shader});
920 if constexpr(
requires { lay.bindings; })
921 boost::pfr::for_each_field(lay.bindings, write_bindings{shader});
922 else if constexpr(
requires {
typename T::bindings; })
923 boost::pfr::for_each_field(
typename T::bindings{}, write_bindings{shader});
928 template <
typename T>
929 std::string fragment_shader(
const T& lay)
931 std::string shader =
"#version 450\n\n";
933 if constexpr(
requires { lay.fragment_input; })
934 boost::pfr::for_each_field(lay.fragment_input, write_input{shader});
935 else if constexpr(
requires {
typename T::fragment_input; })
936 boost::pfr::for_each_field(
typename T::fragment_input{}, write_input{shader});
938 if constexpr(
requires { lay.fragment_output; })
939 boost::pfr::for_each_field(lay.fragment_output, write_output{shader});
940 else if constexpr(
requires {
typename T::fragment_output; })
941 boost::pfr::for_each_field(
typename T::fragment_output{}, write_output{shader});
945 if constexpr(
requires { lay.bindings; })
946 boost::pfr::for_each_field(lay.bindings, write_bindings{shader});
947 else if constexpr(
requires {
typename T::bindings; })
948 boost::pfr::for_each_field(
typename T::bindings{}, write_bindings{shader});
953 template <
typename T>
954 std::string compute_shader(
const T& lay)
956 std::string fstr =
"#version 450\n\n";
959 if constexpr(
requires { T::local_size_x(); })
961 fstr += fmt::format(
"local_size_x = {}, ", T::local_size_x());
963 if constexpr(
requires { T::local_size_y(); })
965 fstr += fmt::format(
"local_size_y = {}, ", T::local_size_y());
967 if constexpr(
requires { T::local_size_z(); })
969 fstr += fmt::format(
"local_size_z = {}, ", T::local_size_z());
973 fstr.resize(fstr.size() - 2);
976 boost::pfr::for_each_field(lay.bindings, write_bindings{fstr});
987 template <
typename T>
988 void initWorker(
this auto& self, std::shared_ptr<T>& state)
noexcept
990 if constexpr(avnd::has_worker<T>)
992 auto ptr = QPointer{&self};
993 auto& tq = score::TaskPool::instance();
994 using worker_type =
decltype(state->worker);
996 auto wk_state = std::weak_ptr{state};
997 state->worker.request = [ptr, &tq, wk_state]<
typename... Args>(Args&&... f) {
998 using type_of_result =
decltype(worker_type::work(std::forward<Args>(f)...));
999 tq.post([... ff = std::forward<Args>(f), wk_state, ptr]()
mutable {
1000 if constexpr(std::is_void_v<type_of_result>)
1002 worker_type::work(std::forward<
decltype(ff)>(ff)...);
1008 auto res = worker_type::work(std::forward<
decltype(ff)>(ff)...);
1012 ossia::qt::run_async(
1013 QCoreApplication::instance(),
1014 [res = std::move(res), wk_state, ptr]()
mutable {
1016 if(
auto state = wk_state.lock())
1026template <
typename GpuNodeRenderer,
typename Node>
1029 GpuNodeRenderer& gpu;
1035 bool can_process_message(std::size_t N)
1037 if(mess.input.size() <= N)
1040 if(prev_mess.input.size() == mess.input.size())
1042 auto& prev = prev_mess.input[N];
1043 auto& next = mess.input[N];
1044 if(prev.index() == 1 && next.index() == 1)
1046 if(ossia::get<ossia::value>(prev) == ossia::get<ossia::value>(next))
1055 void operator()(avnd::parameter
auto& t,
auto field_index)
1057 if(!can_process_message(field_index))
1060 if(
auto val = ossia::get_if<ossia::value>(&mess.input[field_index]))
1062 oscr::from_ossia_value(t, *val, t.value);
1063 if_possible(t.update(state));
1067#if OSCR_HAS_MMAP_FILE_STORAGE
1068 template <avnd::raw_file_port Field, std::
size_t NField>
1069 void operator()(Field& t, avnd::field_index<NField> field_index)
1072 using node_type = std::remove_cvref_t<
decltype(gpu.node())>;
1073 using file_ports = avnd::raw_file_input_introspection<Node>;
1075 if(!can_process_message(field_index))
1078 auto val = ossia::get_if<ossia::value>(&mess.input[field_index]);
1082 static constexpr bool has_text =
requires {
decltype(Field::file)::text; };
1083 static constexpr bool has_mmap =
requires {
decltype(Field::file)::mmap; };
1086 if(
auto hdl = loadRawfile(*val, ctx, has_text, has_mmap))
1088 static constexpr auto N = file_ports::field_index_to_index(NField);
1089 if constexpr(avnd::port_can_process<Field>)
1093 auto func = executePortPreprocess<Field>(*hdl);
1094 const_cast<node_type&
>(gpu.node())
1096 state, hdl, avnd::predicate_index<N>{}, avnd::field_index<NField>{});
1102 const_cast<node_type&
>(gpu.node())
1104 state, hdl, avnd::predicate_index<N>{}, avnd::field_index<NField>{});
1110 template <avnd::texture_port Field, std::
size_t NField>
1111 void operator()(Field& t, avnd::field_index<NField> field_index)
1113 using node_type = std::remove_cvref_t<
decltype(gpu.node())>;
1114 auto& node =
const_cast<node_type&
>(gpu.node());
1115 auto val = ossia::get_if<ossia::render_target_spec>(&mess.input[field_index]);
1118 node.process(NField, *val);
1121 void operator()(
auto& t,
auto field_index) =
delete;
1126 template <
typename Self,
typename Node_T>
1127 static void processControlIn(
1132 avnd::input_introspection<Node_T>::for_all_n(
1133 avnd::get_inputs<Node_T>(state),
1134 GpuProcessIns<Self, Node_T>{self, state, renderer_mess, mess, ctx});
1135 renderer_mess = mess;
1139struct GpuControlOuts
1141 std::weak_ptr<Execution::ExecutionCommandQueue> queue;
1142 Gfx::exec_controls control_outs;
1146 template <
typename Node_T>
1147 void processControlOut(Node_T& state)
const noexcept
1149 if(!this->control_outs.empty())
1151 auto q = this->queue.lock();
1156 avnd::parameter_output_introspection<Node_T>::for_all(
1157 avnd::get_outputs(state), [&]<avnd::parameter T>(
const T& t) {
1158 qq.enqueue([v = oscr::to_ossia_value(t, t.value),
1159 port = control_outs[parm_k]]()
mutable {
1160 std::swap(port->value, v);
1161 port->changed = true;
1170template <
typename T>
1171struct SCORE_PLUGIN_AVND_EXPORT GpuNodeElements
1173 [[no_unique_address]] oscr::soundfile_storage<T> soundfiles;
1175 [[no_unique_address]] oscr::midifile_storage<T> midifiles;
1177#if defined(OSCR_HAS_MMAP_FILE_STORAGE)
1178 [[no_unique_address]] oscr::raw_file_storage<T> rawfiles;
1181 template <std::
size_t N, std::
size_t NField>
1183 auto& state,
const std::shared_ptr<oscr::raw_file_data>& hdl,
1184 avnd::predicate_index<N>, avnd::field_index<NField>)
1186 this->rawfiles.load(
1187 state, hdl, avnd::predicate_index<N>{}, avnd::field_index<NField>{});
1194 :
score::gfx::NodeModel{}
1198 virtual ~CustomGfxNodeBase();
1206 virtual ~CustomGfxOutputNodeBase();
1211struct CustomGpuNodeBase
1218 std::weak_ptr<Execution::ExecutionCommandQueue>&& q, Gfx::exec_controls&& ctls,
1220 : GpuControlOuts{
std::move(q),
std::move(ctls)}
1225 virtual ~CustomGpuNodeBase() =
default;
1228 QString vertex, fragment, compute;
1233struct SCORE_PLUGIN_AVND_EXPORT CustomGpuOutputNodeBase
1239 CustomGpuOutputNodeBase(
1240 std::weak_ptr<Execution::ExecutionCommandQueue> q, Gfx::exec_controls&& ctls,
1242 virtual ~CustomGpuOutputNodeBase();
1245 std::weak_ptr<score::gfx::RenderList> m_renderer{};
1246 std::shared_ptr<score::gfx::RenderState> m_renderState{};
1247 std::function<void()> m_update;
1249 QString vertex, fragment, compute;
1254 void setRenderer(std::shared_ptr<score::gfx::RenderList>)
override;
1257 void startRendering()
override;
1258 void render()
override;
1259 void stopRendering()
override;
1260 bool canRender()
const override;
1261 void onRendererChange()
override;
1265 std::function<
void()> onUpdate, std::function<
void()> onResize)
override;
1267 void destroyOutput()
override;
1268 std::shared_ptr<score::gfx::RenderState> renderState()
const override;
1270 Configuration configuration() const noexcept override;
1273template <typename Node_T, typename Node>
1274void prepareNewState(
std::shared_ptr<Node_T>& eff, const Node& parent)
1276 if constexpr(avnd::has_worker<Node_T>)
1278 parent.initWorker(eff);
1280 if constexpr(avnd::has_processor_to_gui_bus<Node_T>)
1282 auto& process = parent.processModel;
1283 eff->send_message = [ptr = QPointer{&process}](
auto&& b)
mutable {
1287 if(ptr && ptr->to_ui)
1288 MessageBusSender{ptr->to_ui}(std::move(b));
1295 avnd::init_controls(*eff);
1297 if constexpr(avnd::can_prepare<Node_T>)
1299 if constexpr(avnd::function_reflection<&Node_T::prepare>::count == 1)
1301 using prepare_type = avnd::first_argument<&Node_T::prepare>;
1303 if_possible(t.instance = parent.instance);
1313struct port_to_type_enum
1315 template <std::
size_t I, avnd::cpu_texture_port F>
1316 constexpr auto operator()(avnd::field_reflection<I, F> p)
1318 using texture_type = std::remove_cvref_t<
decltype(F::texture)>;
1319 return avnd::cpu_fixed_format_texture<texture_type> ? score::gfx::Types::Image
1320 : score::gfx::Types::Buffer;
1322 template <std::
size_t I, avnd::sampler_port F>
1323 constexpr auto operator()(avnd::field_reflection<I, F> p)
1325 return score::gfx::Types::Image;
1327 template <std::
size_t I, avnd::image_port F>
1328 constexpr auto operator()(avnd::field_reflection<I, F> p)
1330 return score::gfx::Types::Image;
1332 template <std::
size_t I, avnd::attachment_port F>
1333 constexpr auto operator()(avnd::field_reflection<I, F> p)
1335 return score::gfx::Types::Image;
1338 template <std::
size_t I, avnd::geometry_port F>
1339 constexpr auto operator()(avnd::field_reflection<I, F> p)
1341 return score::gfx::Types::Geometry;
1343 template <std::
size_t I, avnd::mono_audio_port F>
1344 constexpr auto operator()(avnd::field_reflection<I, F> p)
1346 return score::gfx::Types::Audio;
1348 template <std::
size_t I, avnd::poly_audio_port F>
1349 constexpr auto operator()(avnd::field_reflection<I, F> p)
1351 return score::gfx::Types::Audio;
1353 template <std::
size_t I, avnd::
int_parameter F>
1354 constexpr auto operator()(avnd::field_reflection<I, F> p)
1356 return score::gfx::Types::Int;
1358 template <std::
size_t I, avnd::enum_parameter F>
1359 constexpr auto operator()(avnd::field_reflection<I, F> p)
1361 return score::gfx::Types::Int;
1363 template <std::
size_t I, avnd::
float_parameter F>
1364 constexpr auto operator()(avnd::field_reflection<I, F> p)
1366 return score::gfx::Types::Float;
1368 template <std::
size_t I, avnd::parameter F>
1369 constexpr auto operator()(avnd::field_reflection<I, F> p)
1371 using value_type = std::remove_cvref_t<
decltype(F::value)>;
1373 if constexpr(std::is_aggregate_v<value_type>)
1375 constexpr int sz = boost::pfr::tuple_size_v<value_type>;
1376 if constexpr(sz == 2)
1378 return score::gfx::Types::Vec2;
1380 else if constexpr(sz == 3)
1382 return score::gfx::Types::Vec3;
1384 else if constexpr(sz == 4)
1386 return score::gfx::Types::Vec4;
1389 return score::gfx::Types::Empty;
1391 template <std::
size_t I,
typename F>
1392 constexpr auto operator()(avnd::field_reflection<I, F> p)
1394 return score::gfx::Types::Empty;
1398template <
typename Node_T>
1399inline void initGfxPorts(
auto* self,
auto& input,
auto& output)
1401 avnd::input_introspection<Node_T>::for_all(
1402 [self, &input]<
typename Field, std::size_t I>(avnd::field_reflection<I, Field> f) {
1403 static constexpr auto type = port_to_type_enum{}(f);
1406 avnd::output_introspection<Node_T>::for_all(
1408 &output]<
typename Field, std::size_t I>(avnd::field_reflection<I, Field> f) {
1409 static constexpr auto type = port_to_type_enum{}(f);
1415inplaceMirror(
unsigned char* bytes,
int width,
int height,
int bytes_per_pixel)
1417 if(width < 1 || height <= 1)
1419 const size_t row_size = width * bytes_per_pixel;
1421 auto temp_row = (
unsigned char*)alloca(row_size);
1423 auto bottom = bytes + (height - 1) * row_size;
1427 memcpy(temp_row, top, row_size);
1428 memcpy(top, bottom, row_size);
1429 memcpy(bottom, temp_row, row_size);
Root data model for visual nodes.
Definition score-plugin-gfx/Gfx/Graph/Node.hpp:75
virtual void process(Message &&msg)
Process a message from the execution engine.
Definition Node.cpp:25
Common base class for most single-pass, simple nodes.
Definition score-plugin-gfx/Gfx/Graph/Node.hpp:230
Base class for sink nodes (QWindow, spout, syphon, NDI output, ...)
Definition OutputNode.hpp:24
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:20
Base toolkit upon which the software is built.
Definition Application.cpp:97
Definition DocumentContext.hpp:18
Definition score-plugin-gfx/Gfx/Graph/Node.hpp:50
Port of a score::gfx::Node.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:52