Loading...
Searching...
No Matches
GppCoroutines.hpp
1#pragma once
2#include "Gfx/Graph/Utils.hpp"
3#include <QString>
4#include <QtGui/private/qrhi_p.h>
5namespace gpp::qrhi
6{
7
9{
10 struct layout
11 {
12 enum
13 {
14 graphics
15 };
17 {
18 struct
19 {
20 static constexpr auto name() { return "position"; }
21 static constexpr int location() { return 0; }
22 float data[2];
23 } pos;
24 };
26 {
27 };
29 {
30 };
31 struct bindings
32 {
33 };
34 };
35
36 static QString vertex()
37 {
38 return R"_(#version 450
39layout(location = 0) in vec2 position;
40out gl_PerVertex { vec4 gl_Position; };
41void main() {
42 gl_Position = vec4( position, 0.0, 1.0 );
43}
44)_";
45 }
46};
47
48template <typename C>
49constexpr auto usage()
50{
51 if constexpr(requires { C::vertex; })
52 return QRhiBuffer::VertexBuffer;
53 else if constexpr(requires { C::index; })
54 return QRhiBuffer::IndexBuffer;
55 else if constexpr(requires { C::ubo; })
56 return QRhiBuffer::UniformBuffer;
57 else if constexpr(requires { C::storage; })
58 return QRhiBuffer::StorageBuffer;
59 else
60 {
61 static_assert(C::unhandled);
62 throw;
63 }
64}
65
66template <typename C>
67constexpr auto buffer_type()
68{
69 if constexpr(requires { C::immutable; })
70 return QRhiBuffer::Immutable;
71 else if constexpr(requires { C::static_; })
72 return QRhiBuffer::Static;
73 else if constexpr(requires { C::dynamic; })
74 return QRhiBuffer::Dynamic;
75 else
76 {
77 static_assert(C::unhandled);
78 throw;
79 }
80}
81
82template <typename C>
83auto samples(C c)
84{
85 if constexpr(requires { C::samples; })
86 return c.samples;
87 else
88 return -1;
89}
90
92{
93 QRhi& rhi;
94 template <typename C>
95 void operator()(C command)
96 {
97 if constexpr(requires { C::deallocation; })
98 {
99 if constexpr(
100 requires { C::vertex; } || requires { C::index; } || requires { C::ubo; })
101 {
102 auto buf = reinterpret_cast<QRhiBuffer*>(command.handle);
103 buf->deleteLater();
104 }
105 else if constexpr(requires { C::sampler; })
106 {
107 auto buf = reinterpret_cast<QRhiSampler*>(command.handle);
108 buf->deleteLater();
109 }
110 else if constexpr(requires { C::texture; })
111 {
112 auto buf = reinterpret_cast<QRhiTexture*>(command.handle);
113 buf->deleteLater();
114 }
115 else
116 {
117 static_assert(C::unhandled);
118 }
119 }
120 else
121 {
122 static_assert(C::unhandled);
123 }
124 }
125};
126
127template <typename Self, typename Res>
129{
130 Self& self;
131 QRhi& rhi;
132 QRhiCommandBuffer& cb;
133 QRhiResourceUpdateBatch*& res;
134 QRhiComputePipeline& pip;
135 template <typename C>
136 Res operator()(C command)
137 {
138 if constexpr(requires { C::compute; })
139 {
140 if constexpr(requires { C::dispatch; })
141 {
142 cb.dispatch(command.x, command.y, command.z);
143 return {};
144 }
145 else if constexpr(requires { C::begin; })
146 {
147 cb.beginComputePass(res);
148 res = nullptr;
149 cb.setComputePipeline(&pip);
150 cb.setShaderResources(pip.shaderResourceBindings());
151
152 return {};
153 }
154 else if constexpr(requires { C::end; })
155 {
156 cb.endComputePass(res);
157 res = nullptr;
158 rhi.finish();
159 return {};
160 }
161 else
162 {
163 static_assert(C::unhandled);
164 return {};
165 }
166 }
167 else if constexpr(requires { C::readback; })
168 {
169 // First handle the readback request
170 if constexpr(requires { C::request; })
171 {
172 if constexpr(requires { C::buffer; })
173 {
174 using ret = typename C::return_type;
175
176#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
177 auto readback = new QRhiBufferReadbackResult;
178#else
179 auto readback = new QRhiReadbackResult;
180#endif
181 self.addReadback(readback);
182
183 // this is e.g. a buffer_awaiter
184 ret user_rb{.handle = reinterpret_cast<decltype(ret::handle)>(readback)};
185
186 // TODO: do it with coroutines like this for peak asyncess
187 // ret must be a coroutine type.
188 // When the GPU completes the work, "completed" is called:
189 // this will cause the coroutine to be filled with the data
190 // readback->completed = [=] {
191 // qDebug() << "alhamdullilah he will be baked";
192 // // store "data" in the coroutine
193 // };
194
195 auto next = rhi.nextResourceUpdateBatch();
196 auto buf = reinterpret_cast<QRhiBuffer*>(command.handle);
197
198 next->readBackBuffer(buf, command.offset, command.size, readback);
199 res = next;
200
201 return user_rb;
202 }
203 else if constexpr(requires { C::texture; })
204 {
205 using ret = typename C::return_type;
206 QRhiReadbackResult readback;
207 return ret{};
208 }
209 else
210 {
211 static_assert(C::unhandled);
212 return {};
213 }
214 }
215 else if constexpr(requires { C::await; })
216 {
217 if constexpr(requires { C::buffer; })
218 {
219 using ret = typename C::return_type;
220
221#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
222 auto readback = reinterpret_cast<QRhiBufferReadbackResult*>(command.handle);
223#else
224 auto readback = reinterpret_cast<QRhiReadbackResult*>(command.handle);
225#endif
226
227 return ret{
228 .data = readback->data.data(), .size = (std::size_t)readback->data.size()};
229 }
230 else if constexpr(requires { C::texture; })
231 {
232 using ret = typename C::return_type;
233
234 auto readback = reinterpret_cast<QRhiReadbackResult*>(command.handle);
235
236 return ret{
237 .data = readback->data.data(), .size = (std::size_t)readback->data.size()};
238 }
239 }
240 }
241 else
242 {
243 static_assert(C::unhandled);
244 return {};
245 }
246
247 return {};
248 }
249};
250
251template <typename Self, typename Ret>
253{
254 Self& self;
255 QRhi& rhi;
256 QRhiResourceUpdateBatch& res;
257 std::vector<QRhiShaderResourceBinding>& srb;
258 bool& srb_touched;
259
260 template <typename C>
261 Ret operator()(C command)
262 {
263 if constexpr(requires { C::allocation; })
264 {
265 if constexpr(
266 requires { C::vertex; } || requires { C::index; })
267 {
268 auto buf = rhi.newBuffer(buffer_type<C>(), usage<C>(), command.size);
269 buf->setName("GppCoroutines::vbuf_or_ibuf");
270 buf->create();
271 return reinterpret_cast<typename C::return_type>(buf);
272 }
273 else if constexpr(requires { C::sampler; })
274 {
275 auto buf = rhi.newSampler({}, {}, {}, {}, {});
276 buf->create();
277 return reinterpret_cast<typename C::return_type>(buf);
278 }
279 else if constexpr(
280 requires { C::ubo; } || requires { C::storage; })
281 {
282 auto buf = rhi.newBuffer(buffer_type<C>(), usage<C>(), command.size);
283 buf->setName("GppCoroutines::ubo_or_ssbo");
284 buf->create();
285
286 // Replace it in our bindings
287 score::gfx::replaceBuffer(srb, command.binding, buf);
288 srb_touched = true;
289 return reinterpret_cast<typename C::return_type>(buf);
290 }
291 else if constexpr(requires { C::texture; })
292 {
293 // FIXME format
294 auto tex = rhi.newTexture(
295 QRhiTexture::RGBA8, QSize{command.width, command.height}, samples(command));
296 tex->create();
297
298 score::gfx::replaceTexture(srb, command.binding, tex);
299 srb_touched = true;
300 return reinterpret_cast<typename C::return_type>(tex);
301 }
302 else
303 {
304 static_assert(C::unhandled);
305 return {};
306 }
307 }
308 else if constexpr(requires { C::upload; })
309 {
310 if constexpr(requires { C::texture; })
311 {
312 QRhiTextureSubresourceUploadDescription sub(command.data, command.size);
313 res.uploadTexture(
314 reinterpret_cast<QRhiTexture*>(command.handle),
315 QRhiTextureUploadDescription{{0, 0, sub}});
316 }
317 else
318 {
319 auto buf = reinterpret_cast<QRhiBuffer*>(command.handle);
320 if constexpr(requires { C::dynamic; })
321 res.updateDynamicBuffer(buf, command.offset, command.size, command.data);
322 else if constexpr(
323 requires { C::static_; } || requires { C::immutable; })
324 res.uploadStaticBuffer(buf, command.offset, command.size, command.data);
325 else
326 {
327 static_assert(C::unhandled);
328 return {};
329 }
330 }
331 }
332 else if constexpr(requires { C::getter; })
333 {
334 if constexpr(requires { C::ubo; })
335 {
336 auto buf = self.createdUbos.at(command.binding);
337 return reinterpret_cast<typename C::return_type>(buf);
338 }
339 else
340 {
341 static_assert(C::unhandled);
342 return {};
343 }
344 }
345 else
346 {
347 handle_release{rhi}(command);
348 return {};
349 }
350 return {};
351 }
352};
353
354}
Definition GppCoroutines.hpp:32
Definition GppCoroutines.hpp:11
Definition GppCoroutines.hpp:9
Definition GppCoroutines.hpp:129
Definition GppCoroutines.hpp:92
Definition GppCoroutines.hpp:253