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->create();
270 return reinterpret_cast<typename C::return_type>(buf);
271 }
272 else if constexpr(requires { C::sampler; })
273 {
274 auto buf = rhi.newSampler({}, {}, {}, {}, {});
275 buf->create();
276 return reinterpret_cast<typename C::return_type>(buf);
277 }
278 else if constexpr(
279 requires { C::ubo; } || requires { C::storage; })
280 {
281 auto buf = rhi.newBuffer(buffer_type<C>(), usage<C>(), command.size);
282 buf->create();
283
284 // Replace it in our bindings
285 score::gfx::replaceBuffer(srb, command.binding, buf);
286 srb_touched = true;
287 return reinterpret_cast<typename C::return_type>(buf);
288 }
289 else if constexpr(requires { C::texture; })
290 {
291 // FIXME format
292 auto tex = rhi.newTexture(
293 QRhiTexture::RGBA8, QSize{command.width, command.height}, samples(command));
294 tex->create();
295
296 score::gfx::replaceTexture(srb, command.binding, tex);
297 srb_touched = true;
298 return reinterpret_cast<typename C::return_type>(tex);
299 }
300 else
301 {
302 static_assert(C::unhandled);
303 return {};
304 }
305 }
306 else if constexpr(requires { C::upload; })
307 {
308 if constexpr(requires { C::texture; })
309 {
310 QRhiTextureSubresourceUploadDescription sub(command.data, command.size);
311 res.uploadTexture(
312 reinterpret_cast<QRhiTexture*>(command.handle),
313 QRhiTextureUploadDescription{{0, 0, sub}});
314 }
315 else
316 {
317 auto buf = reinterpret_cast<QRhiBuffer*>(command.handle);
318 if constexpr(requires { C::dynamic; })
319 res.updateDynamicBuffer(buf, command.offset, command.size, command.data);
320 else if constexpr(
321 requires { C::static_; } || requires { C::immutable; })
322 res.uploadStaticBuffer(buf, command.offset, command.size, command.data);
323 else
324 {
325 static_assert(C::unhandled);
326 return {};
327 }
328 }
329 }
330 else if constexpr(requires { C::getter; })
331 {
332 if constexpr(requires { C::ubo; })
333 {
334 auto buf = self.createdUbos.at(command.binding);
335 return reinterpret_cast<typename C::return_type>(buf);
336 }
337 else
338 {
339 static_assert(C::unhandled);
340 return {};
341 }
342 }
343 else
344 {
345 handle_release{rhi}(command);
346 return {};
347 }
348 return {};
349 }
350};
351
352}
Definition GppCoroutines.hpp:32
Definition GppCoroutines.hpp:11
Definition GppCoroutines.hpp:9
Definition GppCoroutines.hpp:129
Definition GppCoroutines.hpp:92
Definition GppCoroutines.hpp:253