Loading...
Searching...
No Matches
CustomMesh.hpp
1#pragma once
2#include <Gfx/Graph/Mesh.hpp>
3#include <Gfx/Graph/VertexFallbackPlan.hpp>
4
5#include <ossia/dataflow/geometry_port.hpp>
6
7#include <QDebug>
8#include <QtGui/private/qrhi_p.h>
9
10#include <optional>
11#include <span>
12
13namespace score::gfx
14{
15
16// Opt-in (SCORE_BUFTRACE=1) trace of CustomMesh::reload, the point where a
17// geometry change reaches the GPU vertex / index buffers.
18SCORE_PLUGIN_GFX_EXPORT bool buftrace_enabled();
19#define BUFTRACE() \
20 if(!::score::gfx::buftrace_enabled()) \
21 { \
22 } \
23 else \
24 qDebug().nospace() << "[BUFTRACE] "
25
29{
30 uint32_t first{0};
31 uint32_t count{0xFFFFFFFFu};
32};
33
35{
36 ossia::mesh_list geom;
37
38 using pip = QRhiGraphicsPipeline;
39 pip::Topology topology = pip::Topology::TriangleStrip;
40 pip::CullMode cullMode = pip::CullMode::None;
41 pip::FrontFace frontFace = pip::FrontFace::CW;
42
43 ossia::small_vector<QRhiVertexInputBinding, 2> vertexBindings;
44 ossia::small_vector<QRhiVertexInputAttribute, 2> vertexAttributes;
45 ossia::small_vector<ossia::attribute_semantic, 2> attributeSemantics;
46
47 ossia::small_vector<QRhiBuffer*, 2> buffers;
48 QRhiBuffer* index{};
49
50public:
51 explicit CustomMesh(
52 const ossia::mesh_list& g, const ossia::geometry_filter_list_ptr& f);
53
54 const ossia::mesh_list& meshList() const noexcept { return geom; }
55
56 [[nodiscard]]
57 QRhiBuffer* init_vbo(const ossia::geometry::cpu_buffer& buf, QRhi& rhi) const noexcept;
58
59 [[nodiscard]]
60 QRhiBuffer* init_vbo(const ossia::geometry::gpu_buffer& buf, QRhi& rhi) const noexcept;
61 [[nodiscard]]
62 QRhiBuffer*
63 init_index(const ossia::geometry::cpu_buffer& buf, QRhi& rhi) const noexcept;
64
65 [[nodiscard]]
66 QRhiBuffer*
67 init_index(const ossia::geometry::gpu_buffer& buf, QRhi& rhi) const noexcept;
68
69 [[nodiscard]] MeshBuffers init(QRhi& rhi) const noexcept override;
70
71 void update_vbo(
72 int buffer_index, const ossia::geometry::cpu_buffer& vtx_buf, MeshBuffers& meshbuf,
73 QRhi& rhi, QRhiResourceUpdateBatch& rb) const noexcept;
74
75 void update_vbo(
76 int buffer_index, const ossia::geometry::gpu_buffer& vtx_buf, MeshBuffers& meshbuf,
77 QRhi& rhi, QRhiResourceUpdateBatch& rb) const noexcept;
78
79 void update_index(
80 int buffer_index, const ossia::geometry::cpu_buffer& idx_buf, MeshBuffers& meshbuf,
81 QRhi& rhi, QRhiResourceUpdateBatch& rb) const noexcept;
82
83 void update_index(
84 int buffer_index, const ossia::geometry::gpu_buffer& idx_buf, MeshBuffers& meshbuf,
85 QRhi& rhi, QRhiResourceUpdateBatch& rb) const noexcept;
86 void update(QRhi& rhi, MeshBuffers& output_meshbuf, QRhiResourceUpdateBatch& rb)
87 const noexcept override;
88 Flags flags() const noexcept override;
89
90 void clear();
91
92 void preparePipeline(QRhiGraphicsPipeline& pip) const noexcept override;
93 [[nodiscard]] bool hasGeometry() const noexcept override;
94
95 void reload(const ossia::mesh_list& ml, const ossia::geometry_filter_list_ptr& f);
96
97 void draw(const MeshBuffers& bufs, QRhiCommandBuffer& cb) const noexcept override;
98
99 // Fallback-aware variant: appends each `FallbackBindingPlan::Slot`
100 // buffer to the vertex-input array before issuing the draw. Used by
101 // raw-raster pipelines whose shaders declared "REQUIRED: false"
102 // VERTEX_INPUTS the upstream geometry doesn't provide. Non-virtual on
103 // purpose — only CustomMesh participates in the fallback path.
104 void drawWithFallbackBindings(
105 const MeshBuffers& bufs, QRhiCommandBuffer& cb,
106 const FallbackBindingPlan& plan) const noexcept;
107
108 // Draw a single sub-mesh (geom.meshes[mesh_index]) using the portion of
109 // `bufs.buffers` starting at `buffer_offset`. `buffer_offset` must match
110 // init()'s flat-concat layout: sum of geom.meshes[0..mesh_index-1].buffers.size().
111 // Returns true if a draw call was issued.
112 //
113 // Exposed so consumers that need per-sub-mesh state (e.g. RawRaster
114 // swapping the per_draws SSBO between meshes) can iterate sub-meshes
115 // themselves instead of invoking the fire-and-forget `draw()` above.
116 //
117 // `plan` (default empty) says which of the mesh's own bindings the
118 // pipeline kept and in what order, and carries the fallback buffers to
119 // merge in at their binding_index — those land past the surviving mesh
120 // bindings, so their indices are always contiguous after them. An
121 // un-compacted plan means "bind every geometry input in order", which
122 // is what the pipeline builders that do not emit a plan expect.
123 //
124 // `range` restricts an indirect draw to some of its commands.
126 bool drawSingleMesh(
127 std::size_t mesh_index, std::size_t buffer_offset,
128 const MeshBuffers& bufs, QRhiCommandBuffer& cb,
129 const FallbackBindingPlan& plan = {},
130 CommandRange range = {}) const noexcept;
131
134 std::optional<CommandRange> blendCommandRange() const noexcept;
135
139 bool subMeshLayoutMatchesFirst(std::size_t i) const noexcept;
140
144 bool drawsAsPlainVertexList() const noexcept;
145
146 const char* defaultVertexShader() const noexcept override;
147
148 const ossia::geometry* semanticGeometry() const noexcept override
149 {
150 if(!geom.meshes.empty())
151 return &geom.meshes[0];
152 return nullptr;
153 }
154};
155
156}
Definition CustomMesh.hpp:35
std::optional< CommandRange > blendCommandRange() const noexcept
Definition CustomMesh.cpp:622
const ossia::geometry * semanticGeometry() const noexcept override
Return the underlying semantic geometry if available.
Definition CustomMesh.hpp:148
bool subMeshLayoutMatchesFirst(std::size_t i) const noexcept
Definition CustomMesh.cpp:921
bool drawsAsPlainVertexList() const noexcept
Definition CustomMesh.cpp:952
const char * defaultVertexShader() const noexcept override
A basic vertex shader that is going to work with this mesh.
Definition CustomMesh.cpp:998
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11
Definition MIDISync.hpp:128
Definition CustomMesh.hpp:29
Definition VertexFallbackPlan.hpp:27
Definition Mesh.hpp:95
Data model for meshes.
Definition Mesh.hpp:196