LCOV - code coverage report
Current view: top level - xenolith/core - XLCoreFrameQueue.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 465 565 82.3 %
Date: 2024-05-12 00:16:13 Functions: 49 55 89.1 %

          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             : }

Generated by: LCOV version 1.14