LCOV - code coverage report
Current view: top level - xenolith/backend/vk - XLVkQueuePass.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 228 367 62.1 %
Date: 2024-05-12 00:16:13 Functions: 33 41 80.5 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2021-2022 Roman Katuntsev <sbkarr@stappler.org>
       3             :  Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       6             :  of this software and associated documentation files (the "Software"), to deal
       7             :  in the Software without restriction, including without limitation the rights
       8             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             :  copies of the Software, and to permit persons to whom the Software is
      10             :  furnished to do so, subject to the following conditions:
      11             : 
      12             :  The above copyright notice and this permission notice shall be included in
      13             :  all copies or substantial portions of the Software.
      14             : 
      15             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             :  THE SOFTWARE.
      22             :  **/
      23             : 
      24             : #include "XLVkQueuePass.h"
      25             : 
      26             : #include "XLVkAllocator.h"
      27             : #include "XLVkAttachment.h"
      28             : #include "XLVkDevice.h"
      29             : #include "XLVkDeviceQueue.h"
      30             : #include "XLVkTextureSet.h"
      31             : #include "XLVkRenderPass.h"
      32             : #include "XLVkLoop.h"
      33             : #include "XLVkPipeline.h"
      34             : #include "XLCoreFrameQueue.h"
      35             : 
      36             : namespace STAPPLER_VERSIONIZED stappler::xenolith::vk {
      37             : 
      38         357 : QueuePass::~QueuePass() { }
      39             : 
      40         357 : bool QueuePass::init(QueuePassBuilder &passBuilder) {
      41         357 :         if (core::QueuePass::init(passBuilder)) {
      42         357 :                 switch (getType()) {
      43          21 :                 case core::PassType::Graphics:
      44             :                 case core::PassType::Generic:
      45          21 :                         _queueOps = QueueOperations::Graphics;
      46          21 :                         break;
      47         168 :                 case core::PassType::Compute:
      48         168 :                         _queueOps = QueueOperations::Compute;
      49         168 :                         break;
      50         168 :                 case core::PassType::Transfer:
      51         168 :                         _queueOps = QueueOperations::Transfer;
      52         168 :                         break;
      53             :                 }
      54         357 :                 return true;
      55             :         }
      56           0 :         return false;
      57             : }
      58             : 
      59         357 : void QueuePass::invalidate() { }
      60             : 
      61        3509 : VkRect2D QueuePassHandle::rotateScissor(const core::FrameContraints &constraints, const URect &scissor) {
      62             :         VkRect2D scissorRect{
      63        3509 :                 { int32_t(scissor.x), int32_t(constraints.extent.height - scissor.y - scissor.height) },
      64        3509 :                 { scissor.width, scissor.height }
      65        3509 :         };
      66             : 
      67        3509 :         switch (core::getPureTransform(constraints.transform)) {
      68           0 :         case core::SurfaceTransformFlags::Rotate90:
      69           0 :                 scissorRect.offset.y = scissor.x;
      70           0 :                 scissorRect.offset.x = scissor.y;
      71           0 :                 std::swap(scissorRect.extent.width, scissorRect.extent.height);
      72           0 :                 break;
      73           0 :         case core::SurfaceTransformFlags::Rotate180:
      74           0 :                 scissorRect.offset.y = scissor.y;
      75           0 :                 break;
      76           0 :         case core::SurfaceTransformFlags::Rotate270:
      77           0 :                 scissorRect.offset.y = constraints.extent.height - scissor.x - scissor.width;
      78           0 :                 scissorRect.offset.x = constraints.extent.width - scissor.y - scissor.height;
      79             :                 //scissorRect.offset.x = extent.height - scissor.y;
      80           0 :                 std::swap(scissorRect.extent.width, scissorRect.extent.height);
      81           0 :                 break;
      82        3509 :         default: break;
      83             :         }
      84             : 
      85        3509 :         if (scissorRect.offset.x < 0) {
      86         756 :                 scissorRect.extent.width -= scissorRect.offset.x;
      87         756 :                 scissorRect.offset.x = 0;
      88             :         }
      89             : 
      90        3509 :         if (scissorRect.offset.y < 0) {
      91           0 :                 scissorRect.extent.height -= scissorRect.offset.y;
      92           0 :                 scissorRect.offset.y = 0;
      93             :         }
      94             : 
      95        3509 :         return scissorRect;
      96             : }
      97             : 
      98      273566 : QueuePassHandle::~QueuePassHandle() {
      99      172766 :         invalidate();
     100      273566 : }
     101             : 
     102      345343 : void QueuePassHandle::invalidate() {
     103      345343 :         if (_pool) {
     104           0 :                 _device->releaseCommandPoolUnsafe(move(_pool));
     105           0 :                 _pool = nullptr;
     106             :         }
     107             : 
     108      345343 :         if (_queue) {
     109           0 :                 _device->releaseQueue(move(_queue));
     110           0 :                 _queue = nullptr;
     111             :         }
     112             : 
     113      345343 :         _sync = nullptr;
     114      345343 : }
     115             : 
     116      172535 : bool QueuePassHandle::prepare(FrameQueue &q, Function<void(bool)> &&cb) {
     117      172535 :         _onPrepared = move(cb);
     118      172535 :         _loop = static_cast<Loop *>(q.getLoop());
     119      172535 :         _device = static_cast<Device *>(q.getFrame()->getDevice());
     120      172535 :         _pool = _device->acquireCommandPool(getQueueOps());
     121             : 
     122      172535 :         _constraints = q.getFrame()->getFrameConstraints();
     123             : 
     124      172535 :         if (!_pool) {
     125           0 :                 invalidate();
     126           0 :                 return false;
     127             :         }
     128             : 
     129      172535 :         prepareSubpasses(q);
     130             : 
     131             :         // If updateAfterBind feature supported for all renderpass bindings
     132             :         // - we can use separate thread to update them
     133             :         // (ordering of bind|update is not defined in this case)
     134             : 
     135      172535 :         if (_data->hasUpdateAfterBind) {
     136      170255 :                 q.getFrame()->performInQueue([this] (FrameHandle &frame) {
     137      416110 :                         for (uint32_t i = 0; i < _data->pipelineLayouts.size(); ++ i) {
     138      245855 :                                 if (!static_cast<RenderPass *>(_data->impl.get())->writeDescriptors(*this, i, true)) {
     139           0 :                                         return false;
     140             :                                 }
     141             :                         }
     142      170255 :                         return true;
     143      340591 :                 }, [this] (FrameHandle &frame, bool success) {
     144      170255 :                         if (!success) {
     145           0 :                                 _valid = false;
     146           0 :                                 log::error("VK-Error", "Fail to doPrepareDescriptors");
     147             :                         }
     148             : 
     149      170255 :                         _descriptorsReady = true;
     150      170255 :                         if (_commandsReady && _descriptorsReady) {
     151          27 :                                 _onPrepared(_valid);
     152          27 :                                 _onPrepared = nullptr;
     153             :                         }
     154      170255 :                 }, this, "RenderPass::doPrepareDescriptors");
     155             :         } else {
     156        2280 :                 _descriptorsReady = true;
     157             :         }
     158             : 
     159      172535 :         q.getFrame()->performInQueue([this] (FrameHandle &frame) {
     160      418390 :                 for (uint32_t i = 0; i < _data->pipelineLayouts.size(); ++ i) {
     161      245855 :                         if (!static_cast<RenderPass *>(_data->impl.get())->writeDescriptors(*this, i, false)) {
     162           0 :                                 return false;
     163             :                         }
     164             :                 }
     165             : 
     166      172535 :                 auto ret = doPrepareCommands(frame);
     167      172532 :                 if (!ret.empty()) {
     168      172532 :                         _buffers = move(ret);
     169      172526 :                         return true;
     170             :                 }
     171           0 :                 return false;
     172      172526 :         }, [this, cb] (FrameHandle &frame, bool success) {
     173      172535 :                 if (!success) {
     174           0 :                         log::error("VK-Error", "Fail to doPrepareCommands");
     175           0 :                         _valid = false;
     176             :                 }
     177             : 
     178      172535 :                 _commandsReady = true;
     179      172535 :                 if (_commandsReady && _descriptorsReady) {
     180      172508 :                         _onPrepared(_valid);
     181      172508 :                         _onPrepared = nullptr;
     182             :                 }
     183      172535 :         }, this, "RenderPass::doPrepareCommands");
     184      172535 :         return false;
     185             : }
     186             : 
     187      172577 : void QueuePassHandle::submit(FrameQueue &q, Rc<FrameSync> &&sync, Function<void(bool)> &&onSubmited, Function<void(bool)> &&onComplete) {
     188      172577 :         if (!_pool) {
     189           0 :                 onSubmited(true);
     190           0 :                 q.getFrame()->performInQueue([onComplete = move(onComplete)] (FrameHandle &frame) mutable {
     191           0 :                         onComplete(true);
     192           0 :                         return true;
     193             :                 }, this, "RenderPass::complete");
     194           0 :                 return;
     195             :         }
     196             : 
     197      172577 :         Rc<FrameHandle> f = q.getFrame(); // capture frame ref
     198             : 
     199      172577 :         _fence = _loop->acquireFence(f->getOrder());
     200             : 
     201      172577 :         _fence->setTag(getName());
     202             : 
     203      172577 :         _fence->addRelease([dev = _device, pool = _pool, loop = q.getLoop()] (bool success) {
     204      172577 :                 dev->releaseCommandPool(*loop, Rc<CommandPool>(pool));
     205      172577 :         }, nullptr, "RenderPassHandle::submit dev->releaseCommandPool");
     206      172577 :         _fence->addRelease([this, func = move(onComplete), q = &q] (bool success) mutable {
     207      172577 :                 doComplete(*q, move(func), success);
     208      172577 :         }, this, "RenderPassHandle::submit onComplete");
     209             : 
     210      172577 :         _sync = move(sync);
     211             : 
     212      172577 :         auto ops = getQueueOps();
     213             : 
     214      172577 :         _device->acquireQueue(ops, *f.get(), [this, onSubmited = move(onSubmited)]  (FrameHandle &frame, const Rc<DeviceQueue> &queue) mutable {
     215      172577 :                 _queue = queue;
     216             : 
     217      172577 :                 frame.performInQueue([this, onSubmited = move(onSubmited)] (FrameHandle &frame) mutable {
     218      172569 :                         if (!doSubmit(frame, move(onSubmited))) {
     219           0 :                                 return false;
     220             :                         }
     221      172577 :                         return true;
     222             :                 }, this, "RenderPass::submit");
     223      172577 :         }, [this] (FrameHandle &frame) {
     224           0 :                 _sync = nullptr;
     225           0 :                 invalidate();
     226           0 :         }, this);
     227      172577 : }
     228             : 
     229      172766 : void QueuePassHandle::finalize(FrameQueue &, bool success) {
     230             : 
     231      172766 : }
     232             : 
     233      342980 : QueueOperations QueuePassHandle::getQueueOps() const {
     234      342980 :         return (static_cast<vk::QueuePass *>(_queuePass.get()))->getQueueOps();
     235             : }
     236             : 
     237      100800 : Vector<const CommandBuffer *> QueuePassHandle::doPrepareCommands(FrameHandle &handle) {
     238      100800 :         auto buf = _pool->recordBuffer(*_device, [&, this] (CommandBuffer &buf) {
     239      100800 :                 auto pass = _data->impl.cast<vk::RenderPass>().get();
     240      100800 :                 auto queue = handle.getFrameQueue(_data->queue->queue);
     241      100800 :                 pass->perform(*this, buf, [&, this] {
     242      100800 :                         size_t i = 0;
     243      277200 :                         for (auto &it : _data->subpasses) {
     244      176400 :                                 if (it->commandsCallback != nullptr) {
     245      176400 :                                         it->commandsCallback(*it, *queue, buf);
     246             :                                 }
     247      176400 :                                 if (i + 2 < _data->subpasses.size()) {
     248       50400 :                                         buf.cmdNextSubpass();
     249             :                                 }
     250      176400 :                                 ++ i;
     251             :                         }
     252      100800 :                 });
     253      100800 :                 return true;
     254             :         });
     255      100800 :         return Vector<const CommandBuffer *>{buf};
     256             : }
     257             : 
     258      172568 : bool QueuePassHandle::doSubmit(FrameHandle &frame, Function<void(bool)> &&onSubmited) {
     259      172568 :         auto success = _queue->submit(*_sync, *_fence, *_pool, _buffers, _queueIdleMode);
     260      172570 :         _pool = nullptr;
     261      172570 :         frame.performOnGlThread([this, success, onSubmited = move(onSubmited), queue = move(_queue), armedTime = _fence->getArmedTime()] (FrameHandle &frame) mutable {
     262      172577 :                 _queueData->submitTime = armedTime;
     263             : 
     264      172577 :                 if (queue) {
     265      172577 :                         _device->releaseQueue(move(queue));
     266      172577 :                         queue = nullptr;
     267             :                 }
     268             : 
     269      172577 :                 doSubmitted(frame, move(onSubmited), success, move(_fence));
     270      172577 :                 _fence = nullptr;
     271      172577 :                 invalidate();
     272             : 
     273      172577 :                 if (!success) {
     274           0 :                         log::error("VK-Error", "Fail to vkQueueSubmit");
     275             :                 }
     276      172577 :                 _sync = nullptr;
     277      172577 :         }, nullptr, false, "RenderPassHandle::doSubmit");
     278      172577 :         return success;
     279             : }
     280             : 
     281      172577 : void QueuePassHandle::doSubmitted(FrameHandle &handle, Function<void(bool)> &&func, bool success, Rc<Fence> &&fence) {
     282      172577 :         auto queue = handle.getFrameQueue(_data->queue->queue);
     283      348977 :         for (auto &it : _data->submittedCallbacks) {
     284      176400 :                 it(*_data, *queue, success);
     285             :         }
     286             : 
     287      172577 :         func(success);
     288             : 
     289      172577 :         fence->schedule(*_loop);
     290      172577 : }
     291             : 
     292      172577 : void QueuePassHandle::doComplete(FrameQueue &queue, Function<void(bool)> &&func, bool success) {
     293      172577 :         for (auto &it : _data->completeCallbacks) {
     294           0 :                 it(*_data, queue, success);
     295             :         }
     296             : 
     297      172577 :         func(success);
     298      172577 : }
     299             : 
     300        9517 : void QueuePassHandle::doFinalizeTransfer(core::MaterialSet * materials,
     301             :                 Vector<ImageMemoryBarrier> &outputImageBarriers, Vector<BufferMemoryBarrier> &outputBufferBarriers) {
     302        9517 :         if (!materials) {
     303           0 :                 return;
     304             :         }
     305             : 
     306        9517 :         auto b = static_cast<Buffer *>(materials->getBuffer().get());
     307        9517 :         if (!b) {
     308           0 :                 return;
     309             :         }
     310             : 
     311        9517 :         if (auto barrier = b->getPendingBarrier()) {
     312        1130 :                 outputBufferBarriers.emplace_back(*barrier);
     313        1130 :                 b->dropPendingBarrier();
     314             :         }
     315             : 
     316       19034 :         for (auto &it : materials->getLayouts()) {
     317        9517 :                 if (it.set) {
     318        9517 :                         auto &pendingImageBarriers = (static_cast<TextureSet *>(it.set.get()))->getPendingImageBarriers();
     319       10604 :                         for (auto &barrier : pendingImageBarriers) {
     320        1087 :                                 outputImageBarriers.emplace_back(barrier);
     321             :                         }
     322        9517 :                         auto &pendingBufferBarriers = (static_cast<TextureSet *>(it.set.get()))->getPendingBufferBarriers();
     323       25013 :                         for (auto &barrier : pendingBufferBarriers) {
     324       15496 :                                 outputBufferBarriers.emplace_back(barrier);
     325             :                         }
     326        9517 :                         static_cast<TextureSet *>(it.set.get())->dropPendingBarriers();
     327             :                 } else {
     328           0 :                         log::error("MaterialRenderPassHandle", "No set for material layout");
     329             :                 }
     330             :         }
     331             : }
     332             : 
     333        1214 : auto QueuePassHandle::updateMaterials(FrameHandle &frame, const Rc<core::MaterialSet> &data, const Vector<Rc<core::Material>> &materials,
     334             :                 SpanView<core::MaterialId> dynamicMaterials, SpanView<core::MaterialId> materialsToRemove) -> MaterialBuffers {
     335        1214 :         MaterialBuffers ret;
     336        1214 :         auto &layout = _device->getTextureSetLayout();
     337             : 
     338             :         // update list of materials in set
     339        2468 :         auto updated = data->updateMaterials(materials, dynamicMaterials, materialsToRemove, [&, this] (const core::MaterialImage &image) -> Rc<core::ImageView> {
     340        2468 :                 return Rc<ImageView>::create(*_device, static_cast<Image *>(image.image->image.get()), image.info);
     341        1214 :         });
     342        1214 :         if (updated.empty()) {
     343           0 :                 return MaterialBuffers();
     344             :         }
     345             : 
     346        2428 :         for (auto &it : data->getLayouts()) {
     347        1214 :                 frame.performRequiredTask([layout, data, target = &it] (FrameHandle &handle) {
     348        1214 :                         auto dev = static_cast<Device *>(handle.getDevice());
     349             : 
     350        1214 :                         target->set = Rc<TextureSet>(layout->acquireSet(*dev));
     351        1214 :                         target->set->write(*target);
     352        1214 :                         return true;
     353             :                 }, this, "RenderPassHandle::updateMaterials");
     354             :         }
     355             : 
     356        1214 :         auto &bufferInfo = data->getInfo();
     357             : 
     358        1214 :         auto &pool = static_cast<DeviceFrameHandle &>(frame).getMemPool(&frame);
     359             : 
     360        3642 :         ret.stagingBuffer = pool->spawn(AllocationUsage::HostTransitionSource,
     361        3642 :                         BufferInfo(core::ForceBufferUsage(core::BufferUsage::TransferSrc), bufferInfo.size));
     362        1214 :         ret.targetBuffer = pool->spawnPersistent(AllocationUsage::DeviceLocal, bufferInfo);
     363             : 
     364        1214 :         ret.stagingBuffer->map([&] (uint8_t *mapped, VkDeviceSize) {
     365        1214 :                 uint32_t idx = 0;
     366        1214 :                 ret.ordering.reserve(data->getMaterials().size());
     367             : 
     368        1214 :                 uint8_t *target = mapped;
     369       10768 :                 for (auto &it : data->getMaterials()) {
     370        9554 :                         data->encode(target, it.second.get());
     371        9554 :                         target += data->getObjectSize();
     372        9554 :                         ret.ordering.emplace(it.first, idx);
     373        9554 :                         ++ idx;
     374             :                 }
     375        1214 :         });
     376        1214 :         return ret;
     377        1214 : }
     378             : 
     379           0 : vk::ComputePipeline *QueuePassHandle::getComputePipelineByName(uint32_t subpass, StringView name) const {
     380           0 :         if (_data->subpasses.size() > subpass) {
     381           0 :                 auto pipelineIt = _data->subpasses[subpass]->computePipelines.find(name);
     382           0 :                 if (pipelineIt != _data->subpasses[subpass]->computePipelines.end()) {
     383           0 :                         return static_cast<vk::ComputePipeline *>((*pipelineIt)->pipeline.get());
     384             :                 }
     385             :         }
     386           0 :         return nullptr;
     387             : }
     388             : 
     389           0 : vk::ComputePipeline *QueuePassHandle::getComputePipelineBySubName(uint32_t subpass, StringView subname) const {
     390           0 :         if (_data->subpasses.size() > subpass) {
     391           0 :                 auto pipelineIt = _data->subpasses[subpass]->computePipelines.find(toString(_data->key, "_", subname));
     392           0 :                 if (pipelineIt != _data->subpasses[subpass]->computePipelines.end()) {
     393           0 :                         return static_cast<vk::ComputePipeline *>((*pipelineIt)->pipeline.get());
     394             :                 }
     395             :         }
     396           0 :         return nullptr;
     397             : }
     398             : 
     399           0 : vk::GraphicPipeline *QueuePassHandle::getGraphicPipelineByName(uint32_t subpass, StringView name) const {
     400           0 :         if (_data->subpasses.size() > subpass) {
     401           0 :                 auto pipelineIt = _data->subpasses[subpass]->graphicPipelines.find(name);
     402           0 :                 if (pipelineIt != _data->subpasses[subpass]->graphicPipelines.end()) {
     403           0 :                         return static_cast<vk::GraphicPipeline *>((*pipelineIt)->pipeline.get());
     404             :                 }
     405             :         }
     406           0 :         return nullptr;
     407             : }
     408             : 
     409           0 : vk::GraphicPipeline *QueuePassHandle::getGraphicPipelineBySubName(uint32_t subpass, StringView subname) const {
     410           0 :         if (_data->subpasses.size() > subpass) {
     411           0 :                 auto pipelineIt = _data->subpasses[subpass]->graphicPipelines.find(toString(_data->key, "_", subname));
     412           0 :                 if (pipelineIt != _data->subpasses[subpass]->graphicPipelines.end()) {
     413           0 :                         return static_cast<vk::GraphicPipeline *>((*pipelineIt)->pipeline.get());
     414             :                 }
     415             :         }
     416           0 :         return nullptr;
     417             : }
     418             : 
     419          21 : QueuePassHandle::ImageInputOutputBarrier QueuePassHandle::getImageInputOutputBarrier(Device *dev, Image *image, ImageAttachmentHandle &handle) const {
     420          21 :         ImageInputOutputBarrier ret;
     421             : 
     422          21 :         auto attachmentData = handle.getAttachment()->getData();
     423          21 :         auto passData = _queuePass->getData();
     424             : 
     425          21 :         size_t passIdx = 0;
     426          21 :         core::AttachmentPassData *prev = nullptr;
     427          21 :         core::AttachmentPassData *current = nullptr;
     428          21 :         core::AttachmentPassData *next = nullptr;
     429             : 
     430          21 :         for (auto &it : attachmentData->passes) {
     431          21 :                 if (it->pass == passData) {
     432          21 :                         current = it;
     433          21 :                         break;
     434             :                 }
     435           0 :                 ++ passIdx;
     436             :         }
     437             : 
     438          21 :         if (passIdx > 0) {
     439           0 :                 prev = attachmentData->passes[passIdx - 1];
     440             :         }
     441          21 :         if (passIdx + 1 < attachmentData->passes.size()) {
     442           0 :                 next = attachmentData->passes[passIdx + 1];
     443             :         }
     444             : 
     445          21 :         if (prev) {
     446           0 :                 bool hasLayoutTransition = current->initialLayout != prev->finalLayout && current->initialLayout != core::AttachmentLayout::Ignored;
     447           0 :                 bool hasReadWriteTransition = false;
     448           0 :                 if (core::hasReadAccess(current->dependency.initialAccessMask) && core::hasWriteAccess(prev->dependency.finalAccessMask)) {
     449           0 :                         hasReadWriteTransition = true;
     450             :                 }
     451             : 
     452           0 :                 bool hasOwnershipTransfer = false;
     453           0 :                 if (current->pass->type != prev->pass->type) {
     454           0 :                         auto prevQueue = dev->getQueueFamily(prev->pass->type);
     455           0 :                         auto currentQueue = dev->getQueueFamily(current->pass->type);
     456           0 :                         if (prevQueue != currentQueue) {
     457           0 :                                 hasOwnershipTransfer = true;
     458           0 :                                 ret.input.familyTransfer = QueueFamilyTransfer{prevQueue->index, currentQueue->index};
     459             :                         }
     460             :                 }
     461             : 
     462           0 :                 if (hasOwnershipTransfer || hasLayoutTransition || hasReadWriteTransition) {
     463           0 :                         ret.input.image = image;
     464           0 :                         ret.input.oldLayout = VkImageLayout(prev->finalLayout);
     465           0 :                         ret.input.newLayout = VkImageLayout(current->initialLayout);
     466           0 :                         ret.input.srcAccessMask = VkAccessFlags(prev->dependency.finalAccessMask);
     467           0 :                         ret.input.dstAccessMask = VkAccessFlags(current->dependency.initialAccessMask);
     468           0 :                         ret.input.subresourceRange = VkImageSubresourceRange{
     469           0 :                                 image->getAspectMask(), 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS
     470             :                         };
     471           0 :                         ret.inputFrom = prev->dependency.finalUsageStage;
     472           0 :                         ret.inputTo = current->dependency.initialUsageStage;
     473             :                 }
     474             :         } else {
     475             :                 // initial image transition
     476          21 :                 if (current->initialLayout != core::AttachmentLayout::Undefined) {
     477          21 :                         ret.input.image = image;
     478          21 :                         ret.input.oldLayout = VkImageLayout(core::AttachmentLayout::Undefined);
     479          21 :                         ret.input.newLayout = VkImageLayout(current->initialLayout);
     480          21 :                         ret.input.srcAccessMask = 0;
     481          21 :                         ret.input.dstAccessMask = VkAccessFlags(current->dependency.initialAccessMask);
     482          21 :                         ret.input.subresourceRange = VkImageSubresourceRange{
     483          21 :                                 image->getAspectMask(), 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS
     484             :                         };
     485          21 :                         ret.inputFrom = core::PipelineStage::AllCommands;
     486          21 :                         ret.inputTo = current->dependency.initialUsageStage;
     487             :                 }
     488             :         }
     489             : 
     490          21 :         if (next) {
     491           0 :                 if (current->pass->type != next->pass->type) {
     492           0 :                         auto nextQueue = dev->getQueueFamily(next->pass->type);
     493           0 :                         auto currentQueue = dev->getQueueFamily(current->pass->type);
     494           0 :                         if (nextQueue != currentQueue) {
     495           0 :                                 ret.output.familyTransfer = QueueFamilyTransfer{currentQueue->index, nextQueue->index};
     496           0 :                                 ret.output.image = image;
     497           0 :                                 ret.output.oldLayout = VkImageLayout(current->finalLayout);
     498           0 :                                 ret.output.newLayout = VkImageLayout(next->initialLayout);
     499           0 :                                 ret.output.srcAccessMask = VkAccessFlags(current->dependency.finalAccessMask);
     500           0 :                                 ret.output.dstAccessMask = VkAccessFlags(next->dependency.initialAccessMask);
     501           0 :                                 ret.output.subresourceRange = VkImageSubresourceRange{
     502           0 :                                         image->getAspectMask(), 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS
     503             :                                 };
     504           0 :                                 ret.outputFrom = current->dependency.finalUsageStage;
     505           0 :                                 ret.outputTo = next->dependency.initialUsageStage;
     506             :                         }
     507             :                 }
     508             :         }
     509             : 
     510          21 :         return ret;
     511             : }
     512             : 
     513      201549 : QueuePassHandle::BufferInputOutputBarrier QueuePassHandle::getBufferInputOutputBarrier(Device *dev, Buffer *buffer, BufferAttachmentHandle &handle,
     514             :                 VkDeviceSize offset, VkDeviceSize size) const {
     515      201549 :         BufferInputOutputBarrier ret;
     516             : 
     517      201548 :         auto attachmentData = handle.getAttachment()->getData();
     518      201550 :         auto passData = _queuePass->getData();
     519             : 
     520      201546 :         size_t passIdx = 0;
     521      201546 :         core::AttachmentPassData *prev = nullptr;
     522      201546 :         core::AttachmentPassData *current = nullptr;
     523      201546 :         core::AttachmentPassData *next = nullptr;
     524             : 
     525      201546 :         for (auto &it : attachmentData->passes) {
     526      201540 :                 if (it->pass == passData) {
     527      201540 :                         current = it;
     528      201540 :                         break;
     529             :                 }
     530           0 :                 ++ passIdx;
     531             :         }
     532             : 
     533      201540 :         if (passIdx > 0) {
     534           0 :                 prev = attachmentData->passes[passIdx - 1];
     535             :         }
     536      201540 :         if (passIdx + 1 < attachmentData->passes.size()) {
     537       50397 :                 next = attachmentData->passes[passIdx + 1];
     538             :         }
     539             : 
     540      201544 :         if (prev) {
     541           0 :                 bool hasReadWriteTransition = false;
     542           0 :                 if (core::hasReadAccess(current->dependency.initialAccessMask) && core::hasWriteAccess(prev->dependency.finalAccessMask)) {
     543           0 :                         hasReadWriteTransition = true;
     544             :                 }
     545             : 
     546           0 :                 bool hasOwnershipTransfer = false;
     547           0 :                 if (current->pass->type != prev->pass->type) {
     548           0 :                         auto prevQueue = dev->getQueueFamily(prev->pass->type);
     549           0 :                         auto currentQueue = dev->getQueueFamily(current->pass->type);
     550           0 :                         if (prevQueue != currentQueue) {
     551           0 :                                 hasOwnershipTransfer = true;
     552           0 :                                 ret.input.familyTransfer = QueueFamilyTransfer{prevQueue->index, currentQueue->index};
     553             :                         }
     554             :                 }
     555             : 
     556           0 :                 if (hasOwnershipTransfer || hasReadWriteTransition) {
     557           0 :                         ret.input.buffer = buffer;
     558           0 :                         ret.input.srcAccessMask = VkAccessFlags(prev->dependency.finalAccessMask);
     559           0 :                         ret.input.dstAccessMask = VkAccessFlags(current->dependency.initialAccessMask);
     560           0 :                         ret.input.offset = offset;
     561           0 :                         ret.input.size = size;
     562           0 :                         ret.inputFrom = prev->dependency.finalUsageStage;
     563           0 :                         ret.inputTo = current->dependency.initialUsageStage;
     564             :                 }
     565             :         }
     566             : 
     567      201544 :         if (next) {
     568       50397 :                 if (current->pass->type != next->pass->type) {
     569           0 :                         auto nextQueue = dev->getQueueFamily(next->pass->type);
     570           0 :                         auto currentQueue = dev->getQueueFamily(current->pass->type);
     571           9 :                         if (nextQueue != currentQueue) {
     572           0 :                                 ret.output.familyTransfer = QueueFamilyTransfer{currentQueue->index, nextQueue->index};
     573           0 :                                 ret.output.buffer = buffer;
     574           0 :                                 ret.output.srcAccessMask = VkAccessFlags(current->dependency.finalAccessMask);
     575           0 :                                 ret.output.dstAccessMask = VkAccessFlags(next->dependency.initialAccessMask);
     576           0 :                                 ret.output.offset = offset;
     577           0 :                                 ret.output.size = size;
     578           0 :                                 ret.outputFrom = current->dependency.finalUsageStage;
     579           0 :                                 ret.outputTo = next->dependency.initialUsageStage;
     580             :                         }
     581             :                 }
     582             :         }
     583             : 
     584      201553 :         return ret;
     585             : }
     586             : 
     587           0 : void QueuePassHandle::setQueueIdleMode(DeviceQueue::IdleMode mode) {
     588           0 :         _queueIdleMode = mode;
     589           0 : }
     590             : 
     591             : }

Generated by: LCOV version 1.14