Loading...
Searching...
No Matches
RenderedRawRasterPipelineNode.hpp
1#pragma once
2#include <atomic>
3
4#include <Gfx/Graph/ISFNode.hpp>
5#include <Gfx/Graph/IndirectCountClamp.hpp>
6#include <Gfx/Graph/IsfBindingsBuilder.hpp>
7#include <Gfx/Graph/NodeRenderer.hpp>
8#include <Gfx/Graph/RenderedISFUtils.hpp>
9#include <Gfx/Graph/VertexFallbackPlan.hpp>
10
11#include <ossia/detail/small_flat_map.hpp>
12
13#include <span>
14
15namespace score::gfx
16{
20SCORE_PLUGIN_GFX_TEST_EXPORT std::atomic<uint64_t>& iterationAttachmentAllocations() noexcept;
21
22// Used for the simple case of a single, non-persistent pass (the most common case)
23
24struct SCORE_PLUGIN_GFX_TEST_EXPORT RenderedRawRasterPipelineNode : score::gfx::NodeRenderer
25{
26 explicit RenderedRawRasterPipelineNode(const ISFNode& node) noexcept;
27
29
30 void updateInputTexture(const Port& input, QRhiTexture* tex, QRhiTexture* depthTex = nullptr) override;
31 void updateInputSamplerFilter(const Port& input, const RenderTargetSpecs& spec) override;
32 QRhiTexture* textureForOutput(const Port& output) override;
33
34 void init(RenderList& renderer, QRhiResourceUpdateBatch& res) override;
35 void update(RenderList& renderer, QRhiResourceUpdateBatch& res, Edge* edge) override;
36 bool updateMaterials(RenderList& renderer, QRhiResourceUpdateBatch& res, Edge* edge);
37 void release(RenderList& r) override;
38
39 void initState(RenderList& renderer, QRhiResourceUpdateBatch& res) override;
40 void releaseState(RenderList& renderer) override;
41 void addOutputPass(RenderList& renderer, Edge& edge, QRhiResourceUpdateBatch& res) override;
42 void removeOutputPass(RenderList& renderer, Edge& edge) override;
43 bool hasOutputPassForEdge(Edge& edge) const override;
44 void addInputEdge(RenderList& renderer, Edge& edge, QRhiResourceUpdateBatch& res) override;
45 void removeInputEdge(RenderList& renderer, Edge& edge) override;
46
47 void runInitialPasses(
48 RenderList&, QRhiCommandBuffer& commands, QRhiResourceUpdateBatch*& res,
49 Edge& edge) override;
50
51 void runRenderPass(RenderList&, QRhiCommandBuffer& commands, Edge& edge) override;
52
53 QRhiGraphicsPipeline::CompareOp depthCompare() const noexcept override;
54 bool followsRenderSize() const noexcept override;
55
56 void process(int32_t port, const ossia::transform3d& v) override;
57
58private:
59 // Resolves every image-style INPUT against the incoming geometry's
60 // auxiliary_textures list and overrides the initial texture pointer in
61 // m_inputSamplers for matches. Also builds m_auxTextureBindings so
62 // update() can cheaply re-run the lookup when the geometry changes.
63 // Must be called AFTER initInputSamplers.
64 void bindAuxTexturesInit(RenderList& renderer);
65
66 // Per-frame update hook: walks m_auxTextureBindings, re-resolves each
67 // binding's texture pointer from the current geometry's aux textures,
68 // and returns true if at least one sampler's texture pointer changed
69 // (caller will flag mustRecreatePasses).
70 bool rebindAuxTextures(RenderList& renderer);
71
72 // What the input port behind m_inputSamplers[sampler_idx] provides without
73 // any geometry override: its upstream or render-target texture, else the
74 // port's empty placeholder.
75 QRhiTexture* portTexture(RenderList& renderer, int sampler_idx) const;
76
77 void initPass(
78 const TextureRenderTarget& rt, RenderList& renderer,
79 QRhiResourceUpdateBatch& res, Edge& edge);
80 void initMRTPass(RenderList& renderer, QRhiResourceUpdateBatch& res);
81 void initMRTBlitPasses(RenderList& renderer, QRhiResourceUpdateBatch& res);
82 void initMRTBlitPass(RenderList& renderer, QRhiResourceUpdateBatch& res, Edge& edge);
83
84 // EXECUTION_MODEL=MANUAL: evaluate the COUNT expression against the
85 // live input state (first input image's $WIDTH / $HEIGHT / $DEPTH /
86 // $LAYERS, scalar input values as $<inputName>). Pure-integer literal
87 // fast path; otherwise delegate to ossia::math_expression with '$' →
88 // 'var_' rewrite — same convention as CSF STRIDE / image-size
89 // expressions. Returns >= 1; unparseable expressions degrade to 1.
90 int resolveManualInvocationCount() const;
91 bool outputSizeReadsBufferSizes() const noexcept;
93 QSize declaredOutputSize() const;
95 QSize m_declaredOutputSize;
96
97 // True when the shader renders procedurally: no VERTEX_INPUTS, driven by
98 // gl_VertexIndex, with PIPELINE_STATE.VERTEX_COUNT set. m_mesh stays null and
99 // the draw skips vertex-buffer bindings, which relaxes the "no mesh, bail out"
100 // guards for fullscreen passes, VSA-style draws and IBL precompute shaders.
101 bool isProceduralDraw() const noexcept;
102
103 // PIPELINE_STATE.VERTEX_COUNT / INSTANCE_COUNT, literal or evaluated this
104 // frame through resolveIntExpression; nullopt when undeclared.
105 std::optional<uint32_t> declaredVertexCount() const;
106 std::optional<uint32_t> declaredInstanceCount() const;
107
108 // Evaluate an integer-valued expression against the same variable
109 // surface as resolveManualInvocationCount ($WIDTH_<inp> / $HEIGHT /
110 // scalar inputs). Used for OUTPUTS.WIDTH / HEIGHT.
111 // Returns `fallback` when the expression is empty, >=1 otherwise.
112 int resolveIntExpression(const std::string& expr, int fallback) const;
113
114 template <typename F>
115 void refreshStorageBuffers(F&& refresh);
116 void bindGeometryBuffersToAllSrbs(
117 RenderList& renderer, QRhiResourceUpdateBatch& res);
118
119 // Issue the draw for the currently bound pipeline and SRB. When the input
120 // geometry carries several sub-meshes with per-mesh aux buffers, this iterates
121 // them and re-points the SRB bindings before each draw; single-sub-mesh and MDI
122 // geometries delegate to the mesh's own draw(). The SRB is left on the last
123 // sub-mesh's bindings, and the next runRenderPass rebinds from scratch.
124 //
125 // `pipeline` and `viewport` are the bound ones: when the ScenePreprocessor
126 // marks alpha-blended draws and `pipeline` blends and writes depth, those
127 // draws go last through blendPassPipeline(pipeline), which leaves the
128 // command buffer on that pipeline.
129 void drawWithPerMeshAuxRebind(
130 QRhiGraphicsPipeline& pipeline, const QRhiViewport& viewport,
131 QRhiShaderResourceBindings& srb, QRhiCommandBuffer& cb,
132 const FallbackBindingPlan& plan = {});
133
134 // `pipeline` without depth write, for the alpha-blended draws; created on
135 // first use, null when `pipeline` does not both blend and write depth.
136 QRhiGraphicsPipeline* blendPassPipeline(QRhiGraphicsPipeline& pipeline);
137 void releaseBlendPassPipeline(QRhiGraphicsPipeline* pipeline);
138 ossia::small_flat_map<QRhiGraphicsPipeline*, QRhiGraphicsPipeline*, 2>
139 m_blendPassPipelines;
140 // The pipelines' QRhi: QRhiResource::rhi() is Qt 6.6+.
141 QRhi* m_blendPassRhi{};
142
143 std::vector<Sampler> allSamplers() const noexcept;
144
145 ossia::small_vector<std::pair<Edge*, Pass>, 2> m_passes;
146
147 ISFNode& n;
148
149 std::vector<Sampler> m_inputSamplers;
150 std::vector<int> m_storageImageSamplers;
151 std::vector<Sampler> m_audioSamplers;
152 ossia::small_flat_map<Edge*, QRhiSampler*, 4> m_blitSamplersByEdge;
153
154 int64_t meshChangedIndex{-1};
155 const Mesh* m_mesh{};
156 const Mesh* currentMesh() const noexcept override { return m_mesh; }
157 MeshBuffers m_meshbufs;
158
159 // Quad mesh used for MRT blit passes (separate from the geometry mesh)
160 const Mesh* m_blitMesh{};
161 MeshBuffers m_blitMeshbufs;
162
163 QRhiBuffer* m_materialUBO{};
164 int m_materialSize{};
165
166 QRhiBuffer* m_modelUBO{};
167
168 struct AuxiliarySSBO
169 {
170 QRhiBuffer* buffer{};
171 QRhiBuffer* prev_buffer{};
172 int64_t size{};
175 int64_t offset{};
177 QString refused;
178 bool owned{true}; // false when adopted from upstream geometry / upstream port
179 bool is_uniform{false}; // true for uniform_input, false for storage_input
180 bool persistent{false};
181 std::string name;
182 std::string access;
183 // SRB binding slot assigned at pipeline build time. Needed so the per-
184 // sub-mesh draw loop can patch `per_draws` (and any other per-mesh aux)
185 // to point at mesh[i]'s buffer before drawing sub-mesh i. -1 when the
186 // aux was filtered out of the SRB (e.g. visibility==none).
187 int binding{-1};
188 // For persistent aux only: binding slot of the <name>_prev (read-only)
189 // half of the ping-pong pair. prev_binding + 1 == binding.
190 int prev_binding{-1};
195 int64_t declared_size{};
198 int64_t min_size{};
199 };
200 std::vector<AuxiliarySSBO> m_auxiliarySSBOs;
201 static void createAuxPlaceholder(
202 QRhi& rhi, QRhiResourceUpdateBatch& res, AuxiliarySSBO& aux, QSize renderSize);
203
204 // The `camera` block's buffer while a Camera is wired to the node's camera
205 // input (ISFNode::cameraInput): packed from that scene's cameras and bound in
206 // place of the `camera` auxiliary, whatever the geometry carries.
207 QRhiBuffer* m_cameraInletBuffer{};
208 int64_t m_cameraInletFrame{-1};
209 bool m_cameraInletActive{false};
210 void updateCameraInlet(RenderList& renderer, QRhiResourceUpdateBatch& res, QSize renderSize);
211 void dropCameraInletGeometry();
212
213 // Storage images and the rest of the INPUTS storage trio -- storage_input for
214 // SSBOs, csf_image_input for image2D/3D, uniform_input for UBOs -- declared in
215 // the top-level INPUTS array. Wired through the shared IsfBindingsBuilder
216 // helpers so the SRB binding type matches isf_emit_graphics_storage's GLSL.
217 // m_auxiliarySSBOs carries only the AUXILIARY-block entries; the dual
218 // population is deliberate while the AUXILIARY path still has its own dispatch.
219 GraphicsStorageResources m_storage;
220 int m_firstStorageBinding{-1};
221 int m_firstSamplerBinding{3};
222 int m_firstAuxImageBinding{3};
223
224 // Texture auxes carried on the input geometry (see
225 // ossia::geometry::auxiliary_textures). Each entry records a sampler
226 // slot in m_inputSamplers that auto-resolves its texture pointer from
227 // the incoming geometry's aux-texture list by name at init() time and
228 // again every time the geometry changes. Eliminates the need for a
229 // dedicated texture cable (base_color_array / skybox / ...).
230 struct AuxTextureBinding
231 {
232 int sampler_idx{-1}; // index into m_inputSamplers
233 std::string name; // INPUT name, matched against auxiliary_texture::name
234 // The geometry texture last written into the slot, null when the slot is
235 // the port's own.
236 QRhiTexture* applied{};
237 // Named like one of the Scene Preprocessor's deprecated per-channel
238 // texture aliases (P32), and said so once.
239 bool aliasWarned{};
240 };
241 std::vector<AuxTextureBinding> m_auxTextureBindings;
242
243 // Non-owning per-port sampler overrides published by the upstream geometry's
244 // auxiliary_texture::sampler_handle, parallel to m_inputSamplers. Kept separate
245 // because m_inputSamplers entries are owned and released with
246 // `delete sampler.sampler`, which would double-free a registry-owned sampler.
247 std::vector<QRhiSampler*> m_inputSamplerOverrides;
248
249 // Textures declared in the top-level AUXILIARY array (TYPE: image /
250 // texture / cubemap / image_cube). Do NOT create a score input port —
251 // resolved only from ossia::geometry::auxiliary_textures by name, with
252 // a placeholder bound until the first matching handle arrives.
253 struct AuxTextureAuxSampler
254 {
255 QRhiSampler* sampler{}; // Null for storage-image entries.
256 QRhiTexture* texture{};
257 // Shape-matched empty fallback. Set at init from is_cubemap / dimensions /
258 // is_array and never changes. When rebindAuxTextures stops finding a
259 // matching aux_texture upstream (producer stopped publishing the name, got
260 // disconnected, etc.) `texture` reverts to this placeholder rather
261 // than keeping the previous, possibly-freed, upstream handle.
262 // One of the RenderList-owned empty textures for a sampled entry; owned
263 // here, in the declared FORMAT, for a storage image.
264 QRhiTexture* placeholder{};
265 bool owns_placeholder{false};
266 std::string name;
267 int binding{-1};
268 // Storage-image variant: bound with imageLoad / imageStore /
269 // imageLoadStore instead of sampledTexture. `access` distinguishes
270 // which of the three — "read_only" / "write_only" / "read_write".
271 bool is_storage{false};
272 std::string access;
273 // Ladder rung, mirroring isf::…::auxiliary_texture_request. The rung with
274 // ladder_index == 0 owns two SRB slots -- a `textures()` array at
275 // `binding` and a `sampler()` at `binding + 1` -- and the other rungs are
276 // elements of that array, so they take no slot of their own and keep
277 // binding == -1. `sampler` is only allocated on the owner.
278 int ladder_index{-1};
279 int ladder_size{0};
280 bool in_ladder() const noexcept { return ladder_size > 0; }
281 bool owns_ladder() const noexcept { return ladder_index == 0 && ladder_size > 0; }
282 // The publisher's sampler for this texture (auxiliary_texture::
283 // sampler_handle), bound in place of `sampler` when set. Non-owning: the
284 // publisher owns it. Never taken for a declaration that asks for COMPARE,
285 // which is the shader's own intent rather than the texture's.
286 QRhiSampler* sampler_override{};
287 bool declares_compare{false};
288 // MIPMAP_MODE left out of the declaration: `sampler` follows the bound
289 // texture's mips (followTextureMips).
290 bool mips_follow_texture{false};
291 QRhiSampler* boundSampler() const noexcept
292 {
293 return sampler_override ? sampler_override : sampler;
294 }
295 };
296 std::vector<AuxTextureAuxSampler> m_auxTextureSamplers;
297 // Set by rebindAuxTextures when an AUXILIARY texture's bound sampler
298 // changed; the passes are rebuilt, since a hot texture swap keeps the
299 // sampler.
300 bool m_auxSamplerChanged{false};
301
304 const ossia::geometry_spec& drawGeometry();
305 ossia::geometry_spec m_primitiveGeometry;
306 ossia::geometry_spec m_primitiveSource;
307 int64_t m_primitiveSourceIndex{};
308 uint64_t m_primitiveSourceHash{};
309 std::vector<std::pair<const void*, int64_t>> m_primitiveSourceBuffers;
310 bool m_warnedPrimitiveData{false};
311
312 void applyModeTopology(
313 QRhiGraphicsPipeline& ps, int mode,
314 std::optional<QRhiGraphicsPipeline::Topology> geometry);
315 void warnModeOverridesGeometry(
316 std::optional<QRhiGraphicsPipeline::Topology> geometry,
317 QRhiGraphicsPipeline::Topology drawn);
318 int m_warnedModeTopology{-1};
319
320 // isf::raw_raster_point_quads on D3D11 / D3D12: rebuild the pipeline's
321 // vertex input to one instance per point and its topology to triangles,
322 // and mark the plan so the draw issues 6 vertices per point.
323 void applyPointQuads(
324 const RenderList& renderer, QRhiGraphicsPipeline& ps, FallbackBindingPlan& plan);
325 bool m_warnedPointQuads{false};
326
327 // Emit the SRB bindings for m_auxTextureSamplers, advancing `binding`.
328 // Shared by initPass and initMRTPass so the two can never disagree about
329 // how many slots a ladder consumes.
330 // Whether this shader cannot be built on the current backend at all; warns
331 // once.
332 bool refusesBackend(const RenderList& renderer);
333 bool m_backendRefusalLogged{false};
334
335 void requestIndirectCommandBuffers(
336 QRhiGraphicsPipeline& ps, const QRhi& rhi, const QShader& vs,
337 const QShader& fs);
338
339 void appendAuxTextureBindings(
340 ossia::small_vector<QRhiShaderResourceBinding, 4>& out, int& binding,
341 int imageBinding);
342
343 std::optional<AudioTextureUpload> m_audioTex;
344
345 // MRT: internally-owned render target with multiple attachments
346 TextureRenderTarget m_mrtRenderTarget;
347 bool m_hasMRT{false};
348 bool m_mrtRenderedThisFrame{false};
349
350 // Without the draw-count rung: the commands with their dead slots zeroed,
351 // drawn by the plain indirect rungs (MeshBuffers::clampedIndirectBuffer).
352 IndirectCountClamp m_countClamp;
353 bool m_countClampedThisFrame{false};
354 // Whether the mesh pipelines' shaders bind a texture, which declines the
355 // count rung on Metal (drawIndirectCountUsable). Until there is a pipeline,
356 // assume they do.
357 bool m_drawBindsTextures{true};
358 int m_countPathLogged{0};
359 const char* m_countClampLastRefusal{};
360 int64_t m_frameIndexFrame{-1};
361
362 // EXECUTION_MODEL (top-level, RAW_RASTER only).
363 // Single default, one invocation, no extra loop.
364 // PerMip one invocation per mip level of the TARGET output, each binding a
365 // per-mip render target so the draw writes only that mip;
366 // ProcessUBO.passIndex carries the mip index. Drives the
367 // prefiltered-GGX roughness sweep.
368 // PerLayer one invocation per array layer. Colour targets bind setLayer(i);
369 // depth targets render to a shared scratch and copyTexture into
370 // layer i after the pass, since Qt RHI 6.11 has no per-layer depth
371 // attachment. Drives shadow_cascades.frag.
372 // Manual count decided every frame by evaluating a COUNT expression through
373 // the math_expression parser, with the same variable surface as CSF
374 // STRIDE and image-size expressions. All invocations share the MRT
375 // render target and the shader branches on ProcessUBO.passIndex.
376 enum class ExecutionMode : std::uint8_t
377 {
378 Single,
379 PerMip,
380 PerCubeFace, // Iterate 6 cube faces; target = CubeMap + setLayer(i)
381 PerLayer, // Iterate N array layers; target = TextureArray + setLayer(i)
382 Manual
383 };
384 ExecutionMode m_executionMode{ExecutionMode::Single};
385
386 // PerCubeFace state. The target OUTPUT is allocated with
387 // QRhiTexture::CubeMap (6 implicit layers) and six per-face render
388 // targets are built at init; runInitialPasses iterates them in order,
389 // stamping the face index into ProcessUBO.passIndex. Shares the
390 // m_perMipOutputIndex resolution path (same "which colour output is
391 // the target" question) and reuses the m_mipRTs vector for storage
392 // — interpretation is mode-dependent (mip level vs face index).
393 int m_perCubeFaceOutputIndex{-1};
394
395 // PerMip state. When PerMip is active the MRT target texture is
396 // allocated with QRhiTexture::MipMapped and m_mipCount / m_mipRTs
397 // point at per-level render-pass views of it. m_perMipOutputIndex is
398 // the index into m_mrtRenderTarget{.texture, .additionalColorTextures}
399 // being iterated. -1 in other modes.
400 int m_perMipOutputIndex{-1};
401 int m_mipCount{0};
402 // PER_MIP on a MULTIVIEW shader whose view index is lowered to a uniform
403 // (viewIndexNeedsPassIndexFallback): no draw amplifies over the views, so
404 // every mip level is rendered once per view, into that view's layer / face.
405 // m_mipRTs then holds m_mipCount * m_perMipViews targets, mip-major.
406 int m_perMipViews{1};
409 int m_perLayerViews{0};
410 struct MipRT
411 {
412 QRhiTextureRenderTarget* renderTarget{};
413 QRhiRenderPassDescriptor* renderPass{};
414 QRhiTexture* depth{}; // per-level depth — owned here.
416 int colorCount{1};
418 std::vector<QRhiTexture*> scratch;
421 std::vector<QRhiRenderBuffer*> msaa;
422 int samples{1};
423 };
424 std::vector<MipRT> m_mipRTs;
425
426 // PerLayer state. m_perLayerOutputIndex is the raw index into
427 // descriptor().outputs[], depth-inclusive, unlike the colour-only
428 // m_perMipOutputIndex / m_perCubeFaceOutputIndex. m_perLayerIsDepth picks the
429 // path:
430 //
431 // colour: m_mipRTs holds one entry per layer with a setLayer(i) attachment,
432 // structurally PER_CUBE_FACE with a variable layer count.
433 //
434 // depth: identical, using QRhiTextureRenderTargetDescription::setDepthLayer
435 // (Qt >= 6.12) so the pass writes straight into layer i of the OUTPUT
436 // depth array. Below 6.12 that API does not exist and the mode is REFUSED
437 // with a diagnostic rather than silently producing an empty array -- see
438 // initMRTPass. m_perLayerDummyColor is the placeholder colour attachment
439 // some backends (GLES) require, shared by every layer's RT and sized to
440 // the render extent, never 1x1.
441 int m_perLayerOutputIndex{-1};
442 bool m_perLayerIsDepth{false};
443 QRhiTexture* m_perLayerDummyColor{nullptr};
444
445 // Manual state. Re-evaluated every frame in runInitialPasses.
446 int m_manualCount{1};
447
448 // Per-invocation UBO + SRB pool for PER_MIP / PER_CUBE_FACE / MANUAL.
449 //
450 // A QRhi Dynamic UBO has a single slot per frame-in-flight: several
451 // updateDynamicBuffer calls to one buffer within a frame overwrite each other,
452 // so every draw that frame reads the last value and distinct PASSINDEX values
453 // collapse to one.
454 //
455 // One UBO and one SRB per invocation, pre-built at init, lets the render loop
456 // swap which SRB it binds. Index 0 is the main pass (pass.processUBO /
457 // pass.p.srb); the vectors hold 1..N-1 and grow lazily, which MANUAL needs
458 // since its count is per-frame dynamic.
459 std::vector<QRhiBuffer*> m_perInvocationUBOs;
460 std::vector<QRhiShaderResourceBindings*> m_perInvocationSRBs;
461
462 // Transparent CUBEMAP + MULTIVIEW shim: QRhi forbids setMultiViewCount on a
463 // cube texture, so a shader declaring both renders into a hidden 2D
464 // TextureArray -- the only shape multiview accepts -- and each layer is blitted
465 // onto the matching cube face at the end of runInitialPasses. Downstream sees a
466 // real samplerCube through textureForOutput(); the shadow array never leaves
467 // this class.
468 //
469 // m_cubeCopyShadowArray 6-layer TextureArray, UsedAsTransferSource, the
470 // multiview render target
471 // m_cubeCopyCube the public CubeMap
472 // m_cubeCopyOutputIdx colour-attachment index taking the array-then-copy
473 // path, -1 otherwise; one output per shader
474 QRhiTexture* m_cubeCopyShadowArray{};
475 QRhiTexture* m_cubeCopyCube{};
476 int m_cubeCopyOutputIdx{-1};
477
478 // The part of the m_materialUBO for which changes
479 // trigger a pipeline recreation (blend status etc.)
480 static constexpr int size_of_pipeline_material = 32;
481 alignas(4) char m_prevPipelineChangingMaterial[size_of_pipeline_material]{0};
482 struct PipelineChangingMaterial
483 {
484 int32_t mode; // tri, point, line
485 int32_t enable_blend; // bool
486 QRhiGraphicsPipeline::BlendFactor src_color;
487 QRhiGraphicsPipeline::BlendFactor dst_color;
488 QRhiGraphicsPipeline::BlendOp op_color;
489 QRhiGraphicsPipeline::BlendFactor src_alpha;
490 QRhiGraphicsPipeline::BlendFactor dst_alpha;
491 QRhiGraphicsPipeline::BlendOp op_alpha;
492 };
493 static_assert(sizeof(PipelineChangingMaterial) == size_of_pipeline_material);
494
495 ossia::transform3d m_modelTransform;
496
497 // LAYER, per output edge: the draw goes into `targets` with the consumer's
498 // depth attached read-only, then `resumeTarget` reopens the consumer's pass
499 // for the resolve. `readDepthTarget` is the consumer's colour alone, for a
500 // resolve sampling the consumer's depth.
501 struct LayerTargets
502 {
503 std::vector<QRhiTexture*> targets;
504 QRhiTextureRenderTarget* renderTarget{};
505 QRhiRenderPassDescriptor* renderPass{};
506 QRhiTextureRenderTarget* resumeTarget{};
507 QRhiRenderPassDescriptor* resumePass{};
508 QRhiTextureRenderTarget* readDepthTarget{};
509 QRhiRenderPassDescriptor* readDepthPass{};
510 QRhiTexture* depthInput{};
511 QRhiTexture* depthPlaceholder{};
512 QRhiSampler* sampler{};
513 QColor clear;
514 Pipeline clearTargets;
515 Pipeline resolve;
516 Pipeline resolveDepth;
517 void release();
518 };
519 ossia::small_flat_map<Edge*, LayerTargets, 2> m_layers;
520 bool m_warnedLayerFallback{false};
521
522 TextureRenderTarget initLayerTargets(
523 RenderList& renderer, const TextureRenderTarget& inlet, Edge& edge,
524 QRhiResourceUpdateBatch& res);
525 void initLayerResolve(RenderList& renderer, LayerTargets& t, QRhiBuffer* processUBO);
526 void releaseLayerTargets(Edge* edge);
527 void releaseLayerTargets();
528 void applyLayerState(QRhiGraphicsPipeline& ps, bool depthAvailable, bool internal) const;
529};
530}
Definition ISFNode.hpp:39
The draw-count rung, emulated with compute for backends without it.
Definition IndirectCountClamp.hpp:35
Renderer for a given node.
Definition NodeRenderer.hpp:11
List of nodes to be rendered to an output.
Definition RenderList.hpp:36
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11
std::atomic< uint64_t > & iterationAttachmentAllocations() noexcept
Definition RenderedRawRasterPipelineNode.cpp:33
void updateInputSamplerFilter(std::span< Sampler > samplers, const score::gfx::Node &node, const Port &input, const RenderTargetSpecs &spec)
Give the sampler initInputSamplers() created for input, one of node's input ports,...
Definition score-plugin-gfx/Gfx/Graph/Utils.cpp:2213
Base toolkit upon which the software is built.
Definition Application.cpp:83
Connection between two score::gfx::Port.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:236
Definition VertexFallbackPlan.hpp:27
Aggregate of all graphics-visible storage resources for a node.
Definition IsfBindingsBuilder.hpp:143
Definition Mesh.hpp:95
Data model for meshes.
Definition Mesh.hpp:196
Useful abstraction for storing a graphics pipeline and associated resource bindings.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:278
Port of a score::gfx::Node.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:215
Definition score-plugin-gfx/Gfx/Graph/Node.hpp:71
Definition RenderedRawRasterPipelineNode.hpp:25
Useful abstraction for storing all the data related to a render target.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:307
Definition Uniforms.hpp:8