Line data Source code
1 : /**
2 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "XLCoreFrameQueue.h"
24 : #include "XLCoreFrameHandle.h"
25 : #include "XLCoreLoop.h"
26 : #include "XLCoreDevice.h"
27 : #include "XLCoreQueuePass.h"
28 :
29 : #ifndef XL_FRAME_QUEUE_LOG
30 : #define XL_FRAME_QUEUE_LOG(...)
31 : #endif
32 :
33 : namespace STAPPLER_VERSIONIZED stappler::xenolith::core {
34 :
35 56870 : FrameQueue::~FrameQueue() {
36 28435 : _frame = nullptr;
37 : XL_FRAME_QUEUE_LOG("Ended");
38 56870 : }
39 :
40 28435 : bool FrameQueue::init(const Rc<PoolRef> &p, const Rc<Queue> &q, FrameHandle &f) {
41 28435 : _pool = p;
42 28435 : _queue = q;
43 28435 : _frame = &f;
44 28435 : _loop = _frame->getLoop();
45 28435 : _order = f.getOrder();
46 : XL_FRAME_QUEUE_LOG("Started");
47 28435 : return true;
48 : }
49 :
50 28435 : bool FrameQueue::setup() {
51 28435 : bool valid = true;
52 :
53 28435 : _renderPasses.reserve(_queue->getPasses().size());
54 28435 : _renderPassesInitial.reserve(_queue->getPasses().size());
55 :
56 160208 : for (auto &it : _queue->getPasses()) {
57 131773 : auto pass = it->pass->makeFrameHandle(*this);
58 131773 : if (pass->isAvailable(*this)) {
59 263546 : auto v = _renderPasses.emplace(it, FramePassData{
60 : FrameRenderPassState::Initial,
61 : pass,
62 131773 : pass->getData()
63 131773 : }).first;
64 131773 : pass->setQueueData(v->second);
65 131773 : _renderPassesInitial.emplace(&v->second);
66 : }
67 131773 : }
68 :
69 28435 : _attachments.reserve(_queue->getAttachments().size());
70 28435 : _attachmentsInitial.reserve(_queue->getAttachments().size());
71 :
72 422790 : for (auto &it : _queue->getAttachments()) {
73 394355 : auto h = it->attachment->makeFrameHandle(*this);
74 394355 : if (h->isAvailable(*this)) {
75 394355 : auto v = _attachments.emplace(it, FrameAttachmentData({
76 : FrameAttachmentState::Initial,
77 : h
78 394355 : })).first;
79 394355 : if (it->type == AttachmentType::Image) {
80 29368 : auto img = static_cast<ImageAttachment *>(it->attachment.get());
81 29368 : v->second.info = img->getImageInfo();
82 29368 : if ((v->second.info.hints & ImageHints::FixedSize) == ImageHints::None) {
83 29368 : v->second.info.extent = _frame->getFrameConstraints().extent;
84 : }
85 : } else {
86 364987 : v->second.info.extent = _frame->getFrameConstraints().extent;
87 : }
88 :
89 394355 : h->setQueueData(v->second);
90 394355 : _attachmentsInitial.emplace(&v->second);
91 : }
92 394355 : }
93 :
94 422790 : for (auto &it : _attachments) {
95 394355 : auto passes = it.second.handle->getAttachment()->getRenderPasses();
96 394355 : it.second.passes.reserve(passes.size());
97 906724 : for (auto &pass : passes) {
98 512369 : auto passIt = _renderPasses.find(pass);
99 512369 : if (passIt != _renderPasses.end()) {
100 512369 : it.second.passes.emplace_back(&passIt->second);
101 : } else {
102 : XL_FRAME_QUEUE_LOG("RenderPass '", pass->key, "' is not available on frame");
103 0 : valid = false;
104 : }
105 : }
106 :
107 394355 : if (!it.first->passes.empty()) {
108 394355 : auto &last = it.first->passes.back();
109 394355 : it.second.final = last->dependency.requiredRenderPassState;
110 : } else {
111 0 : log::error("FrameQueue", "Attachment ", it.first->key, " not attached to any pass");
112 : }
113 394355 : }
114 :
115 160208 : for (auto &passIt : _renderPasses) {
116 644142 : for (auto &a : passIt.first->attachments) {
117 512369 : auto aIt = _attachments.find(a->attachment);
118 512369 : if (aIt != _attachments.end()) {
119 512369 : passIt.second.attachments.emplace_back(a, &aIt->second);
120 : } else {
121 : XL_FRAME_QUEUE_LOG("Attachment '", a->key, "' is not available on frame");
122 0 : valid = false;
123 : }
124 : }
125 :
126 644142 : for (auto &a : passIt.first->attachments) {
127 512369 : auto aIt = _attachments.find(a->attachment);
128 512369 : if (aIt != _attachments.end()) {
129 512369 : if (a->index == maxOf<uint32_t>()) {
130 0 : passIt.second.attachments.emplace_back(a, &aIt->second);
131 : }
132 : } else {
133 : XL_FRAME_QUEUE_LOG("Attachment '", a->key, "' is not available on frame");
134 0 : valid = false;
135 : }
136 : }
137 :
138 644142 : for (auto &a : passIt.second.attachments) {
139 512369 : passIt.second.attachmentMap.emplace(a.first->attachment, a.second);
140 : }
141 : }
142 :
143 160208 : for (auto &passIt : _renderPasses) {
144 131773 : FramePassData &passData = passIt.second;
145 235111 : for (auto &it : passData.data->required) {
146 103338 : if (auto targetPassData = const_cast<FramePassData *>(getRenderPass(it.data))) {
147 103338 : auto wIt = targetPassData->waiters.find(it.requiredState);
148 103338 : if (wIt == targetPassData->waiters.end()) {
149 103338 : wIt = targetPassData->waiters.emplace(it.requiredState, Vector<FramePassData *>()).first;
150 : }
151 103338 : wIt->second.emplace_back(&passIt.second);
152 : }
153 : }
154 : }
155 :
156 : XL_FRAME_QUEUE_LOG("Setup: ", valid);
157 28435 : return valid;
158 : }
159 :
160 98020 : void FrameQueue::update() {
161 492375 : for (auto &it : _attachmentsInitial) {
162 394355 : if (it->handle->setup(*this, [this, guard = Rc<FrameQueue>(this), attachment = it] (bool success) {
163 0 : _loop->performOnGlThread([this, attachment, success] {
164 0 : attachment->waitForResult = false;
165 0 : if (success && !_finalized) {
166 0 : onAttachmentSetupComplete(*attachment);
167 0 : _loop->performOnGlThread([this] {
168 0 : if (_frame) {
169 0 : _frame->update();
170 : }
171 0 : }, this);
172 0 : } else {
173 0 : invalidate(*attachment);
174 : }
175 0 : }, guard, true);
176 0 : })) {
177 394355 : onAttachmentSetupComplete(*it);
178 : } else {
179 0 : it->waitForResult = true;
180 : XL_FRAME_QUEUE_LOG("[Attachment:", it->handle->getName(), "] State: Setup");
181 0 : it->state = FrameAttachmentState::Setup;
182 : }
183 : }
184 98020 : _attachmentsInitial.clear();
185 :
186 : do {
187 98020 : auto it = _renderPassesInitial.begin();
188 430067 : while (it != _renderPassesInitial.end()) {
189 332047 : if ((*it)->state == FrameRenderPassState::Initial) {
190 331998 : if (isRenderPassReady(**it)) {
191 48557 : auto v = *it;
192 48557 : it = _renderPassesInitial.erase(it);
193 48557 : updateRenderPassState(*v, FrameRenderPassState::Ready);
194 : } else {
195 283441 : ++ it;
196 : }
197 : } else {
198 49 : it = _renderPassesInitial.erase(it);
199 : }
200 : }
201 : } while (0);
202 :
203 : do {
204 98020 : auto awaitPasses = move(_awaitPasses);
205 98020 : _awaitPasses.clear();
206 98020 : _awaitPasses.reserve(awaitPasses.size());
207 :
208 98020 : auto it = awaitPasses.begin();
209 98020 : while (it != awaitPasses.end()) {
210 0 : if (isRenderPassReadyForState(*it->first, FrameRenderPassState(toInt(it->second) + 1))) {
211 0 : updateRenderPassState(*it->first, it->second);
212 : } else {
213 0 : _awaitPasses.emplace_back(*it);
214 : }
215 0 : ++ it;
216 : }
217 98020 : } while (0);
218 :
219 : do {
220 98020 : auto it = _renderPassesPrepared.begin();
221 98020 : while (it != _renderPassesPrepared.end()) {
222 0 : if ((*it)->state == FrameRenderPassState::Prepared) {
223 0 : auto v = *it;
224 0 : onRenderPassPrepared(*v);
225 0 : if (v->state != FrameRenderPassState::Prepared) {
226 0 : it = _renderPassesPrepared.erase(it);
227 : } else {
228 0 : ++ it;
229 : }
230 : } else {
231 0 : it = _renderPassesPrepared.erase(it);
232 : }
233 : }
234 : } while(0);
235 98020 : }
236 :
237 16 : void FrameQueue::invalidate() {
238 16 : if (!_finalized) {
239 : XL_FRAME_QUEUE_LOG("invalidate");
240 16 : _success = false;
241 16 : _invalidated = true;
242 16 : auto f = _frame;
243 16 : onFinalized();
244 16 : if (f) {
245 16 : f->onQueueInvalidated(*this);
246 16 : tryReleaseFrame();
247 : }
248 16 : }
249 16 : }
250 :
251 263658 : Loop *FrameQueue::getLoop() const {
252 263658 : return _loop;
253 : }
254 :
255 939117 : const FrameAttachmentData *FrameQueue::getAttachment(const AttachmentData *a) const {
256 939117 : auto it = _attachments.find(a);
257 939117 : if (it != _attachments.end()) {
258 939117 : return &it->second;
259 : }
260 0 : return nullptr;
261 : }
262 :
263 1427428 : const FramePassData *FrameQueue::getRenderPass(const QueuePassData *p) const {
264 1427428 : auto it = _renderPasses.find(p);
265 1427428 : if (it != _renderPasses.end()) {
266 1427428 : return &it->second;
267 : }
268 0 : return nullptr;
269 : }
270 :
271 29304 : bool FrameQueue::isResourcePending(const FrameAttachmentData &image) {
272 29304 : if (image.image) {
273 29304 : if (!image.image->isReady()) {
274 3021 : return true;
275 : }
276 : }
277 26283 : return false;
278 : }
279 :
280 6042 : void FrameQueue::waitForResource(const FrameAttachmentData &image, Function<void(bool)> &&cb) {
281 6042 : if (image.image) {
282 6042 : image.image->waitReady(move(cb));
283 : } else {
284 0 : cb(false);
285 : }
286 6042 : }
287 :
288 7322 : bool FrameQueue::isResourcePending(const FramePassData &) {
289 7322 : return false;
290 : }
291 :
292 0 : void FrameQueue::waitForResource(const FramePassData &, Function<void()> &&) {
293 : // TODO
294 0 : }
295 :
296 394355 : void FrameQueue::onAttachmentSetupComplete(FrameAttachmentData &attachment) {
297 394355 : if (attachment.handle->isOutput()) {
298 : // do nothing for now
299 : }
300 394355 : if (attachment.handle->isInput()) {
301 : XL_FRAME_QUEUE_LOG("[Attachment:", attachment.handle->getName(), "] State: InputRequired");
302 69649 : attachment.state = FrameAttachmentState::InputRequired;
303 69649 : if (auto data = _frame->getInputData(attachment.handle->getAttachment()->getData())) {
304 40297 : attachment.waitForResult = true;
305 80594 : attachment.handle->submitInput(*this, move(data),
306 80594 : [this, guard = Rc<FrameQueue>(this), attachment = &attachment] (bool success) {
307 40297 : _loop->performOnGlThread([this, attachment, success] {
308 40297 : attachment->waitForResult = false;
309 40297 : if (success && !_finalized) {
310 40297 : onAttachmentInput(*attachment);
311 40297 : _loop->performOnGlThread([frame = _frame] {
312 40297 : if (frame) {
313 40297 : frame->update();
314 : }
315 40297 : }, _frame);
316 40297 : } else {
317 0 : invalidate(*attachment);
318 : }
319 40297 : }, guard, true);
320 40297 : });
321 : } else {
322 29352 : attachment.waitForResult = true;
323 58704 : attachment.handle->getAttachment()->acquireInput(*this, attachment.handle,
324 58704 : [this, guard = Rc<FrameQueue>(this), attachment = &attachment] (bool success) {
325 29292 : _loop->performOnGlThread([this, attachment, success] {
326 29292 : attachment->waitForResult = false;
327 29292 : if (success && !_finalized) {
328 29290 : onAttachmentInput(*attachment);
329 29290 : _loop->performOnGlThread([frame = _frame] {
330 29290 : if (frame) {
331 29290 : frame->update();
332 : }
333 29290 : }, _frame);
334 29290 : } else {
335 2 : invalidate(*attachment);
336 : }
337 29292 : }, guard, true);
338 29292 : });
339 69649 : }
340 : } else {
341 : XL_FRAME_QUEUE_LOG("[Attachment:", attachment.handle->getName(), "] State: Ready");
342 324706 : attachment.state = FrameAttachmentState::Ready;
343 : }
344 394355 : }
345 :
346 69587 : void FrameQueue::onAttachmentInput(FrameAttachmentData &attachment) {
347 : XL_FRAME_QUEUE_LOG("[Attachment:", attachment.handle->getName(), "] State: Ready");
348 69587 : attachment.state = FrameAttachmentState::Ready;
349 69587 : }
350 :
351 394211 : void FrameQueue::onAttachmentAcquire(FrameAttachmentData &attachment) {
352 394211 : if (_finalized) {
353 0 : if (attachment.state != FrameAttachmentState::Finalized) {
354 0 : finalizeAttachment(attachment);
355 : }
356 0 : return;
357 : }
358 :
359 : XL_FRAME_QUEUE_LOG("[Attachment:", attachment.handle->getName(), "] State: ResourcesPending");
360 394211 : attachment.state = FrameAttachmentState::ResourcesPending;
361 394211 : if (attachment.handle->getAttachment()->getData()->type == AttachmentType::Image) {
362 29304 : auto img = static_cast<ImageAttachment *>(attachment.handle->getAttachment().get());
363 :
364 29304 : if (img->isStatic()) {
365 0 : attachment.image = img->getStaticImageStorage();
366 : } else {
367 29304 : attachment.image = _frame->getRenderTarget(attachment.handle->getAttachment());
368 : }
369 :
370 29304 : if (!attachment.image && attachment.handle->isAvailable(*this)) {
371 21998 : if (auto spec = _frame->getImageSpecialization(img)) {
372 7322 : attachment.info = *spec;
373 : }
374 21998 : attachment.image = _loop->acquireImage(img, attachment.handle.get(), attachment.info);
375 21998 : if (!attachment.image) {
376 0 : invalidate(attachment);
377 0 : return;
378 : }
379 :
380 21998 : attachment.image->setFrameIndex(_frame->getOrder());
381 : }
382 :
383 29304 : if (attachment.image) {
384 29304 : attachment.info = attachment.image->getInfo();
385 :
386 29304 : _autorelease.emplace_front(attachment.image);
387 29304 : if (attachment.image->getSignalSem()) {
388 26283 : _autorelease.emplace_front(attachment.image->getSignalSem());
389 : }
390 29304 : if (attachment.image->getWaitSem()) {
391 26203 : _autorelease.emplace_front(attachment.image->getWaitSem());
392 : }
393 : }
394 :
395 29304 : if (isResourcePending(attachment)) {
396 3021 : waitForResource(attachment, [this, attachment = &attachment] (bool success) {
397 3021 : if (!success) {
398 0 : invalidate();
399 0 : return;
400 : }
401 : XL_FRAME_QUEUE_LOG("[Attachment:", attachment->handle->getName(), "] State: ResourcesAcquired");
402 3021 : attachment->state = FrameAttachmentState::ResourcesAcquired;
403 : });
404 : } else {
405 : XL_FRAME_QUEUE_LOG("[Attachment:", attachment.handle->getName(), "] State: ResourcesAcquired");
406 26283 : attachment.state = FrameAttachmentState::ResourcesAcquired;
407 : }
408 : } else {
409 : XL_FRAME_QUEUE_LOG("[Attachment:", attachment.handle->getName(), "] State: ResourcesAcquired");
410 364907 : attachment.state = FrameAttachmentState::ResourcesAcquired;
411 : }
412 : }
413 :
414 608444 : void FrameQueue::onAttachmentRelease(FrameAttachmentData &attachment) {
415 608444 : if (attachment.image) {
416 21966 : if (attachment.handle->getAttachment()->getData()->type == AttachmentType::Image) {
417 21966 : if (attachment.image) {
418 21966 : _loop->releaseImage(move(attachment.image));
419 21966 : attachment.image = nullptr;
420 : }
421 : }
422 :
423 21966 : if (_finalized && attachment.state != FrameAttachmentState::Finalized) {
424 0 : finalizeAttachment(attachment);
425 : } else {
426 : XL_FRAME_QUEUE_LOG("[Attachment:", attachment.handle->getName(), "] State: ResourcesReleased");
427 21966 : attachment.state = FrameAttachmentState::ResourcesReleased;
428 : }
429 : } else {
430 586478 : if (_finalized && attachment.state != FrameAttachmentState::Finalized) {
431 19344 : finalizeAttachment(attachment);
432 : } else {
433 : XL_FRAME_QUEUE_LOG("[Attachment:", attachment.handle->getName(), "] State: ResourcesReleased");
434 567134 : attachment.state = FrameAttachmentState::ResourcesReleased;
435 : }
436 : }
437 608444 : }
438 :
439 435320 : bool FrameQueue::isRenderPassReady(const FramePassData &data) const {
440 435320 : return isRenderPassReadyForState(data, FrameRenderPassState::Initial);
441 : }
442 :
443 1489136 : bool FrameQueue::isRenderPassReadyForState(const FramePassData &data, FrameRenderPassState state) const {
444 2431979 : for (auto &it : data.data->required) {
445 1228090 : if (auto d = getRenderPass(it.data)) {
446 1228090 : if (toInt(d->state) < toInt(it.requiredState) && state >= it.lockedState) {
447 285247 : return false;
448 : }
449 : }
450 : }
451 :
452 5826321 : for (auto &it : data.attachments) {
453 4640796 : if (toInt(it.second->state) < toInt(FrameAttachmentState::Ready)) {
454 18364 : return false;
455 : }
456 : }
457 :
458 1185525 : return true;
459 : }
460 :
461 1053816 : void FrameQueue::updateRenderPassState(FramePassData &data, FrameRenderPassState state) {
462 1053816 : if (_finalized && state != FrameRenderPassState::Finalized) {
463 0 : return;
464 : }
465 :
466 1053816 : if (state == FrameRenderPassState::Ready && data.handle->isAsync()) {
467 144 : state = FrameRenderPassState::Owned;
468 : }
469 :
470 1053816 : if (toInt(data.state) >= toInt(state)) {
471 0 : return;
472 : }
473 :
474 1053816 : if (!isRenderPassReadyForState(data, FrameRenderPassState(toInt(state) + 1)) && !_invalidated) {
475 0 : _awaitPasses.emplace_back(&data, state);
476 0 : return;
477 : }
478 :
479 1053816 : data.state = state;
480 :
481 1053816 : switch (state) {
482 0 : case FrameRenderPassState::Initial:
483 : XL_FRAME_QUEUE_LOG("[RenderPass:", data.handle->getName(), "] State: Initial");
484 0 : break;
485 131597 : case FrameRenderPassState::Ready:
486 : XL_FRAME_QUEUE_LOG("[RenderPass:", data.handle->getName(), "] State: Ready");
487 131597 : onRenderPassReady(data);
488 131597 : break;
489 131741 : case FrameRenderPassState::Owned:
490 : XL_FRAME_QUEUE_LOG("[RenderPass:", data.handle->getName(), "] State: Owned");
491 131741 : onRenderPassOwned(data);
492 131741 : break;
493 131741 : case FrameRenderPassState::ResourcesAcquired:
494 : XL_FRAME_QUEUE_LOG("[RenderPass:", data.handle->getName(), "] State: ResourcesAcquired");
495 131741 : onRenderPassResourcesAcquired(data);
496 131741 : break;
497 131741 : case FrameRenderPassState::Prepared:
498 : XL_FRAME_QUEUE_LOG("[RenderPass:", data.handle->getName(), "] State: Prepared");
499 131741 : onRenderPassPrepared(data);
500 131741 : break;
501 131741 : case FrameRenderPassState::Submission:
502 : XL_FRAME_QUEUE_LOG("[RenderPass:", data.handle->getName(), "] State: Submission");
503 131741 : onRenderPassSubmission(data);
504 131741 : break;
505 131741 : case FrameRenderPassState::Submitted:
506 : XL_FRAME_QUEUE_LOG("[RenderPass:", data.handle->getName(), "] State: Submitted");
507 131741 : onRenderPassSubmitted(data);
508 131741 : break;
509 131741 : case FrameRenderPassState::Complete:
510 : XL_FRAME_QUEUE_LOG("[RenderPass:", data.handle->getName(), "] State: Complete");
511 131741 : onRenderPassComplete(data);
512 131741 : break;
513 131773 : case FrameRenderPassState::Finalized:
514 : XL_FRAME_QUEUE_LOG("[RenderPass:", data.handle->getName(), "] State: Finalized");
515 131773 : data.handle->finalize(*this, _success);
516 131773 : break;
517 : }
518 :
519 1053816 : auto it = data.waiters.find(state);
520 1053816 : if (it != data.waiters.end()) {
521 206644 : for (auto &v : it->second) {
522 103322 : if (v->state == FrameRenderPassState::Initial) {
523 103322 : if (isRenderPassReady(*v)) {
524 83184 : updateRenderPassState(*v, FrameRenderPassState::Ready);
525 : }
526 : }
527 : }
528 : }
529 :
530 5151280 : for (auto &it : data.attachments) {
531 4097464 : if (!it.second->passes.empty() && it.second->passes.back() == &data && it.second->state != FrameAttachmentState::ResourcesReleased) {
532 2579131 : if (it.second->final == FrameRenderPassState::Initial) {
533 2425209 : if (toInt(state) >= toInt(FrameRenderPassState::Submitted)) {
534 564432 : onAttachmentRelease(*it.second);
535 : }
536 153922 : } else if ((toInt(state) >= toInt(it.second->final))) {
537 44012 : onAttachmentRelease(*it.second);
538 : }
539 : }
540 : }
541 :
542 1053816 : if (state >= FrameRenderPassState::Finalized) {
543 131773 : ++ _finalizedObjects;
544 131773 : tryReleaseFrame();
545 : }
546 : }
547 :
548 131597 : void FrameQueue::onRenderPassReady(FramePassData &data) {
549 131597 : if (data.handle->isAsync()) {
550 0 : updateRenderPassState(data, FrameRenderPassState::Owned);
551 : } else {
552 131597 : if (data.handle->getQueuePass()->acquireForFrame(*this, [this, data = &data] (bool success) {
553 0 : data->waitForResult = false;
554 0 : if (success && !_finalized) {
555 0 : updateRenderPassState(*data, FrameRenderPassState::Owned);
556 : } else {
557 0 : invalidate(*data);
558 : }
559 0 : })) {
560 131597 : updateRenderPassState(data, FrameRenderPassState::Owned);
561 : } else {
562 0 : data.waitForResult = true;
563 : }
564 : }
565 131597 : }
566 :
567 134762 : void FrameQueue::onRenderPassOwned(FramePassData &data) {
568 134762 : if (_finalized) {
569 0 : invalidate(data);
570 0 : return;
571 : }
572 :
573 134762 : if (data.framebuffer) {
574 0 : return;
575 : }
576 :
577 : // fill required imageViews for framebuffer
578 : // only images, that attached to subpasses, merged into framebuffer
579 : // all framebuffer images must have same extent
580 134762 : Vector<Rc<ImageView>> imageViews;
581 134762 : bool attachmentsAcquired = true;
582 134762 : bool _invalidate = false;
583 :
584 28008 : auto acquireView = [&] (const AttachmentPassData *imgDesc, const Rc<ImageStorage> &image) {
585 28008 : auto imgAttachment = (const ImageAttachment *)imgDesc->attachment->attachment.get();
586 28008 : ImageViewInfo info = imgAttachment->getImageViewInfo(image->getInfo(), *imgDesc);
587 :
588 28008 : auto view = image->getView(info);
589 28008 : if (!view) {
590 0 : view = image->makeView(info);
591 : }
592 :
593 28008 : if (view) {
594 28008 : imageViews.emplace_back(move(view));
595 : } else {
596 : XL_FRAME_QUEUE_LOG("Fail to acquire ImageView for framebuffer");
597 0 : _invalidate = true;
598 0 : attachmentsAcquired = false;
599 : }
600 28008 : };
601 :
602 134762 : data.waitForResult = true;
603 671107 : for (auto &it : data.attachments) {
604 536345 : if (it.second->handle->isOutput()) {
605 31440 : auto out = _frame->getOutputBinding(it.second->handle->getAttachment());
606 31440 : if (out) {
607 29559 : _autorelease.emplace_front((FrameOutputBinding *)out);
608 : }
609 : }
610 536345 : if (it.second->state == FrameAttachmentState::Ready) {
611 394211 : onAttachmentAcquire(*it.second);
612 394211 : if (it.second->state != FrameAttachmentState::ResourcesAcquired) {
613 3021 : attachmentsAcquired = false;
614 : XL_FRAME_QUEUE_LOG("[RenderPass:", data.handle->getName(), "] waitForResource: ", it.second->handle->getName());
615 3021 : auto refId = retain();
616 3021 : waitForResource(*it.second, [this, data = &data, refId] (bool success) {
617 3021 : if (!success) {
618 0 : invalidate();
619 0 : release(refId);
620 0 : return;
621 : }
622 3021 : onRenderPassOwned(*data);
623 3021 : release(refId);
624 : });
625 : } else {
626 391190 : if (it.second->image && !it.first->subpasses.empty()) {
627 18945 : acquireView(it.first, it.second->image);
628 : }
629 : }
630 142134 : } else if (it.second->state == FrameAttachmentState::ResourcesAcquired) {
631 142134 : if (it.second->image && !it.first->subpasses.empty()) {
632 9063 : acquireView(it.first, it.second->image);
633 : }
634 : }
635 : }
636 :
637 134762 : if (_invalidate) {
638 0 : invalidate();
639 0 : return;
640 : }
641 :
642 134762 : if (attachmentsAcquired) {
643 131741 : if (!imageViews.empty()) {
644 7322 : Extent3 extent = imageViews.front()->getFramebufferExtent();
645 7322 : auto it = imageViews.begin();
646 29288 : while (it != imageViews.end()) {
647 21966 : if ((*it)->getFramebufferExtent() != extent) {
648 0 : log::warn("FrameQueue", "Invalid extent for framebuffer image: ", (*it)->getFramebufferExtent());
649 0 : it = imageViews.erase(it);
650 : } else {
651 21966 : ++ it;
652 : }
653 : }
654 :
655 7322 : if (data.handle->isFramebufferRequired()) {
656 7322 : data.framebuffer = _loop->acquireFramebuffer(data.handle->getData(), imageViews);
657 7322 : if (!data.framebuffer) {
658 0 : invalidate();
659 : }
660 7322 : _autorelease.emplace_front(data.framebuffer);
661 : }
662 7322 : if (isResourcePending(data)) {
663 : XL_FRAME_QUEUE_LOG("[RenderPass:", data.handle->getName(), "] waitForResource (pending): ", data.handle->getName());
664 0 : waitForResource(data, [this, data = &data] {
665 0 : data->waitForResult = false;
666 0 : updateRenderPassState(*data, FrameRenderPassState::ResourcesAcquired);
667 0 : });
668 : } else {
669 7322 : data.waitForResult = false;
670 7322 : updateRenderPassState(data, FrameRenderPassState::ResourcesAcquired);
671 : }
672 : } else {
673 124419 : updateRenderPassState(data, FrameRenderPassState::ResourcesAcquired);
674 : }
675 : }
676 134762 : }
677 :
678 131741 : void FrameQueue::onRenderPassResourcesAcquired(FramePassData &data) {
679 131741 : if (_finalized) {
680 0 : invalidate(data);
681 0 : return;
682 : }
683 :
684 643918 : for (auto &it : data.attachments) {
685 512177 : if (it.second->image) {
686 36626 : if (auto img = it.second->image->getImage()) {
687 36626 : data.handle->autorelease(img);
688 36626 : }
689 : }
690 : }
691 :
692 131741 : if (data.framebuffer) {
693 7322 : data.handle->autorelease(data.framebuffer);
694 : }
695 :
696 131741 : data.handle->autorelease(_frame->getDevice());
697 :
698 326523 : for (auto &it : data.handle->getData()->subpasses) {
699 224070 : for (auto &p : it->graphicPipelines) {
700 29288 : if (p->pipeline) {
701 29288 : data.handle->autorelease(p->pipeline);
702 : }
703 : }
704 1486730 : for (auto &p : it->computePipelines) {
705 1291948 : if (p->pipeline) {
706 1291948 : data.handle->autorelease(p->pipeline);
707 : }
708 : }
709 : }
710 :
711 263482 : if (data.handle->prepare(*this,
712 263482 : [this, guard = Rc<FrameQueue>(this), data = &data] (bool success) mutable {
713 131741 : _loop->performOnGlThread([this, data, success] {
714 131741 : data->waitForResult = false;
715 131741 : if (success && !_finalized) {
716 131741 : updateRenderPassState(*data, FrameRenderPassState::Prepared);
717 : } else {
718 0 : invalidate(*data);
719 : }
720 131741 : }, guard, true);
721 131741 : })) {
722 0 : updateRenderPassState(data, FrameRenderPassState::Prepared);
723 : } else {
724 131741 : data.waitForResult = true;
725 : }
726 : }
727 :
728 131741 : void FrameQueue::onRenderPassPrepared(FramePassData &data) {
729 131741 : if (_finalized) {
730 0 : invalidate(data);
731 0 : return;
732 : }
733 :
734 131741 : if (data.handle->isAsync() || _frame->isReadyForSubmit()) {
735 131741 : updateRenderPassState(data, FrameRenderPassState::Submission);
736 : } else {
737 0 : _renderPassesPrepared.emplace(&data);
738 : }
739 : }
740 :
741 131741 : void FrameQueue::onRenderPassSubmission(FramePassData &data) {
742 131741 : if (_finalized) {
743 0 : invalidate(data);
744 0 : return;
745 : }
746 :
747 131741 : auto sync = makeRenderPassSync(data);
748 :
749 131741 : data.waitForResult = true;
750 263482 : data.handle->submit(*this, move(sync), [this, guard = Rc<FrameQueue>(this), data = &data] (bool success) {
751 131741 : _loop->performOnGlThread([this, data, success] {
752 131741 : if (success && !_finalized) {
753 131741 : updateRenderPassState(*data, FrameRenderPassState::Submitted);
754 : } else {
755 0 : data->waitForResult = false;
756 0 : invalidate(*data);
757 : }
758 131741 : }, guard, true);
759 263482 : }, [this, guard = Rc<FrameQueue>(this), data = &data] (bool success) {
760 131741 : _loop->performOnGlThread([this, data, success] {
761 131741 : data->waitForResult = false;
762 131741 : if (success && !_finalized) {
763 131741 : updateRenderPassState(*data, FrameRenderPassState::Complete);
764 : } else {
765 0 : invalidate(*data);
766 : }
767 131741 : }, guard, true);
768 131741 : });
769 131741 : }
770 :
771 131741 : void FrameQueue::onRenderPassSubmitted(FramePassData &data) {
772 : // no need to check finalization
773 :
774 131741 : ++ _renderPassSubmitted;
775 131741 : if (data.framebuffer) {
776 7322 : _loop->releaseFramebuffer(move(data.framebuffer));
777 7322 : data.framebuffer = nullptr;
778 : }
779 :
780 131741 : if (_renderPassSubmitted == _renderPasses.size()) {
781 28419 : _frame->onQueueSubmitted(*this);
782 : }
783 :
784 643918 : for (auto &it : data.attachments) {
785 512177 : if (it.second->handle->isOutput()
786 28419 : && it.second->handle->getAttachment()->getData()->outputState == FrameRenderPassState::Submitted
787 540596 : && it.first->attachment->attachment->getLastRenderPass() == data.handle->getData()) {
788 9219 : _frame->onOutputAttachment(*it.second);
789 : }
790 : }
791 :
792 131741 : data.handle->getQueuePass()->releaseForFrame(*this);
793 131741 : if (!data.submitTime) {
794 112 : data.submitTime = platform::clock(ClockType::Monotonic);
795 : }
796 131741 : }
797 :
798 131741 : void FrameQueue::onRenderPassComplete(FramePassData &data) {
799 131741 : auto t = platform::clock(ClockType::Monotonic) - data.submitTime;
800 :
801 131741 : _submissionTime += t;
802 131741 : if (_finalized) {
803 0 : invalidate(data);
804 0 : return;
805 : }
806 :
807 643918 : for (auto &it : data.attachments) {
808 512177 : if (it.second->handle->isOutput()
809 28419 : && it.second->handle->getAttachment()->getData()->outputState == FrameRenderPassState::Complete
810 540596 : && it.first->attachment->attachment->getLastRenderPass() == data.handle->getData()) {
811 19200 : _frame->onOutputAttachment(*it.second);
812 : }
813 : }
814 :
815 131741 : ++ _renderPassCompleted;
816 131741 : if (_renderPassCompleted == _renderPasses.size()) {
817 28419 : onComplete();
818 : }
819 : }
820 :
821 131741 : Rc<FrameSync> FrameQueue::makeRenderPassSync(FramePassData &data) const {
822 131741 : auto ret = Rc<FrameSync>::alloc();
823 :
824 227741 : for (auto &it : data.data->sourceQueueDependencies) {
825 : //auto handle = getAttachment(it->attachments.front());
826 96000 : auto target = getRenderPass(it->target);
827 :
828 96000 : auto sem = _loop->makeSemaphore();
829 :
830 96000 : ret->signalAttachments.emplace_back(FrameSyncAttachment{nullptr, sem, nullptr});
831 :
832 96000 : target->waitSync.emplace_back(FrameSyncAttachment{nullptr, sem, nullptr, it->stageFlags});
833 96000 : }
834 :
835 227741 : for (auto &it : data.waitSync) {
836 96000 : ret->waitAttachments.emplace_back(move(it));
837 : }
838 :
839 643918 : for (auto &it : data.attachments) {
840 : // insert wait sem when image first-time used
841 512177 : if (it.first->attachment->attachment->getFirstRenderPass() == data.handle->getData()) {
842 394211 : if (it.second->image && it.second->image->getWaitSem()) {
843 87672 : ret->waitAttachments.emplace_back(FrameSyncAttachment{it.second->handle, it.second->image->getWaitSem(),
844 58448 : it.second->image.get(), getWaitStageForAttachment(data, it.second->handle)});
845 : }
846 : }
847 :
848 : // insert signal sem when image last-time used
849 512177 : if (it.second->handle->getAttachment()->getLastRenderPass() == data.handle->getData()) {
850 394211 : if (it.second->image && it.second->image->getSignalSem()) {
851 87912 : ret->signalAttachments.emplace_back(FrameSyncAttachment{it.second->handle, it.second->image->getSignalSem(),
852 58608 : it.second->image.get()});
853 : }
854 : }
855 :
856 512177 : if (it.second->image) {
857 36626 : auto layout = it.first->finalLayout;
858 36626 : if (layout == AttachmentLayout::PresentSrc && !it.second->image->isSwapchainImage()) {
859 16 : layout = AttachmentLayout::TransferSrcOptimal;
860 : }
861 36626 : ret->images.emplace_back(FrameSyncImage{it.second->handle, it.second->image, layout});
862 : }
863 : }
864 :
865 131741 : return ret;
866 0 : }
867 :
868 29224 : PipelineStage FrameQueue::getWaitStageForAttachment(FramePassData &data, const AttachmentHandle *handle) const {
869 80366 : for (auto &it : data.handle->getData()->attachments) {
870 80366 : if (it->attachment == handle->getAttachment()->getData()) {
871 29224 : if (it->dependency.initialUsageStage == PipelineStage::None) {
872 29224 : return PipelineStage::BottomOfPipe;
873 : } else {
874 21918 : return it->dependency.initialUsageStage;
875 : }
876 : }
877 : }
878 0 : return PipelineStage::None;
879 : }
880 :
881 28419 : void FrameQueue::onComplete() {
882 28419 : if (!_finalized) {
883 : XL_FRAME_QUEUE_LOG("onComplete");
884 28419 : _success = true;
885 28419 : _frame->onQueueComplete(*this);
886 28419 : onFinalized();
887 : }
888 28419 : }
889 :
890 28435 : void FrameQueue::onFinalized() {
891 28435 : if (_finalized) {
892 0 : return;
893 : }
894 :
895 : XL_FRAME_QUEUE_LOG("onFinalized");
896 :
897 28435 : _finalized = true;
898 160208 : for (auto &pass : _renderPasses) {
899 131773 : invalidate(pass.second);
900 : }
901 :
902 422790 : for (auto &pass : _attachments) {
903 394355 : invalidate(pass.second);
904 : }
905 : }
906 :
907 394357 : void FrameQueue::invalidate(FrameAttachmentData &data) {
908 394357 : if (!_finalized) {
909 0 : invalidate();
910 0 : return;
911 : }
912 :
913 394357 : if (data.state == FrameAttachmentState::Finalized) {
914 19346 : return;
915 : }
916 :
917 375011 : if (!data.waitForResult || _invalidated) {
918 375011 : finalizeAttachment(data);
919 : }
920 : }
921 :
922 131773 : void FrameQueue::invalidate(FramePassData &data) {
923 131773 : if (!_finalized) {
924 : XL_FRAME_QUEUE_LOG("[Queue:", _queue->getName(), "] Invalidated");
925 0 : invalidate();
926 0 : return;
927 : }
928 :
929 131773 : if (data.state == FrameRenderPassState::Finalized) {
930 0 : return;
931 : }
932 :
933 131773 : if (data.state == FrameRenderPassState::Ready || data.state == FrameRenderPassState::Owned
934 263546 : || (!data.waitForResult && toInt(data.state) > toInt(FrameRenderPassState::Ready))) {
935 131741 : data.handle->getQueuePass()->releaseForFrame(*this);
936 131741 : data.waitForResult = false;
937 : }
938 :
939 131773 : if (!data.waitForResult && data.framebuffer) {
940 0 : _loop->releaseFramebuffer(move(data.framebuffer));
941 0 : data.framebuffer = nullptr;
942 : }
943 :
944 131773 : if (!data.waitForResult || _invalidated) {
945 131773 : updateRenderPassState(data, FrameRenderPassState::Finalized);
946 : }
947 : }
948 :
949 526144 : void FrameQueue::tryReleaseFrame() {
950 526144 : if (_finalizedObjects == _renderPasses.size() + _attachments.size()) {
951 28451 : _frame = nullptr;
952 : }
953 526144 : }
954 :
955 394355 : void FrameQueue::finalizeAttachment(FrameAttachmentData &attachment) {
956 394355 : attachment.handle->finalize(*this, _success);
957 : XL_FRAME_QUEUE_LOG("[Attachment:", attachment.handle->getName(), "] State: Finalized [", _success, "]");
958 394355 : attachment.state = FrameAttachmentState::Finalized;
959 394355 : if (!_success && _frame && attachment.handle->isOutput()) {
960 16 : _frame->onOutputAttachmentInvalidated(attachment);
961 : }
962 394355 : ++ _finalizedObjects;
963 394355 : tryReleaseFrame();
964 394355 : }
965 :
966 : }
|