Loading...
Searching...
No Matches
TextureToBuffer.hpp
1#pragma once
2
3#include <ossia/detail/pod_vector.hpp>
4#include <Threedim/GeometryToBufferStrategies.hpp>
5
6#include <boost/container/vector.hpp>
7
8#include <halp/controls.hpp>
9#include <halp/geometry.hpp>
10#include <halp/meta.hpp>
11#include <halp/texture.hpp>
12#include <halp/buffer.hpp>
13#include <halp/texture.hpp>
14
15namespace Threedim
16{
18{
19public:
20 halp_meta(name, "Texture to buffer")
21 halp_meta(category, "Visuals/Utilities")
22 halp_meta(c_name, "texture_to_buffer")
23 halp_meta(description, "Copy texture pixel data into a GPU buffer for further processing.")
24 halp_meta(manual_url, "https://ossia.io/score-docs/processes/texture-to-buffer.html")
25 halp_meta(uuid, "fd7d6339-c745-4733-a1c2-6ebd0a25fd92")
26
27 struct ins
28 {
29 halp::texture_input<"Texture", halp::custom_variable_texture> texture;
30 } inputs;
31 struct
32 {
33 halp::gpu_buffer_output<"Buffer"> buffer;
34 } outputs;
35
36 QRhiBuffer* buf{};
37 void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res)
38 {
39 outputs.buffer.buffer.handle = nullptr;
40 outputs.buffer.buffer.byte_size = 0;
41 outputs.buffer.buffer.byte_offset = 0;
42 outputs.buffer.buffer.changed = true;
43
44 if(!inputs.texture.texture.bytes)
45 return;
46 auto bytes = inputs.texture.texture.bytesize();
47
48 if(buf)
49 renderer.releaseBuffer(buf);
50 if(bytes <= 0)
51 return;
52
53 buf = renderer.state.rhi->newBuffer(QRhiBuffer::Static, QRhiBuffer::StorageBuffer | QRhiBuffer::VertexBuffer, bytes);
54 if(!buf->create())
55 {
56 delete buf;
57 buf = nullptr;
58 return;
59 }
60
61 outputs.buffer.buffer.handle = buf;
62 outputs.buffer.buffer.byte_size = bytes;
63 outputs.buffer.buffer.byte_offset = 0;
64 outputs.buffer.buffer.changed = true;
65 }
66
67 void update(
68 score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res,
70 {
71 if(!buf || inputs.texture.texture.bytesize() != buf->size())
72 {
73 init(renderer, res);
74 return;
75 }
76 // A dropout tick (bytes == nullptr) re-inits and zeroes the
77 // published outlet while keeping `buf` alive. When the source comes
78 // back at the SAME size no re-init happens, so republish the
79 // still-live, size-matching buffer — otherwise the outlet stays
80 // null forever while runInitialPasses() uploads into a buffer
81 // downstream can no longer see.
82 if(inputs.texture.texture.bytes && outputs.buffer.buffer.handle != buf)
83 {
84 outputs.buffer.buffer.handle = buf;
85 outputs.buffer.buffer.byte_size = buf->size();
86 outputs.buffer.buffer.byte_offset = 0;
87 outputs.buffer.buffer.changed = true;
88 }
89 }
90
91 void release(score::gfx::RenderList& r)
92 {
93 // The buffer is ours: without this, every renderer release (each undo /
94 // redo that recreates the node, a QRhi teardown) leaked it, and Vulkan's
95 // allocator asserted "Some allocations were not freed" when the QRhi
96 // went away (examples/3d/extract-attribute.score).
97 if(buf)
98 r.releaseBuffer(buf);
99 buf = nullptr;
100 outputs.buffer.buffer.handle = nullptr;
101 outputs.buffer.buffer.byte_size = 0;
102 outputs.buffer.buffer.changed = true;
103 }
104
105 void runInitialPasses(
106 score::gfx::RenderList& renderer, QRhiCommandBuffer& commands,
107 QRhiResourceUpdateBatch*& res, score::gfx::Edge& edge)
108 {
109 if(!inputs.texture.texture.bytes)
110 return;
111 if(!buf)
112 return;
113 auto sz = buf->size();
114 if(inputs.texture.texture.bytesize() != sz)
115 return;
116
117
118 res->uploadStaticBuffer(
119 buf,
120 QByteArray::fromRawData((const char*)inputs.texture.texture.bytes, sz));
121 }
122};
123
124}
Definition TextureToBuffer.hpp:18
List of nodes to be rendered to an output.
Definition RenderList.hpp:36
void releaseBuffer(QRhiBuffer *buf)
Retire a buffer this render list's node owns.
Definition RenderList.cpp:1253
Definition TextureToBuffer.hpp:28
Connection between two score::gfx::Port.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:236