LCOV - code coverage report
Current view: top level - xenolith/backend/vk - XLVkRenderQueueCompiler.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 237 268 88.4 %
Date: 2024-05-12 00:16:13 Functions: 44 44 100.0 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2021-2022 Roman Katuntsev <sbkarr@stappler.org>
       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 "XLVkAttachment.h"
      24             : #include "XLVkPipeline.h"
      25             : #include "XLVkRenderPass.h"
      26             : #include "XLVkRenderQueueCompiler.h"
      27             : #include "XLVkTransferQueue.h"
      28             : #include "XLVkMaterialCompiler.h"
      29             : #include "XLCoreFrameEmitter.h"
      30             : #include "XLCoreFrameQueue.h"
      31             : #include "XLCoreFrameCache.h"
      32             : #include "XLCoreFrameRequest.h"
      33             : 
      34             : namespace STAPPLER_VERSIONIZED stappler::xenolith::vk {
      35             : 
      36             : class RenderQueueAttachment : public core::GenericAttachment {
      37             : public:
      38             :         virtual ~RenderQueueAttachment();
      39             : 
      40             :         virtual Rc<core::AttachmentHandle> makeFrameHandle(const FrameQueue &) override;
      41             : };
      42             : 
      43             : class RenderQueueAttachmentHandle : public core::AttachmentHandle {
      44             : public:
      45             :         virtual ~RenderQueueAttachmentHandle();
      46             : 
      47             :         virtual bool setup(FrameQueue &handle, Function<void(bool)> &&) override;
      48             :         virtual void submitInput(FrameQueue &, Rc<core::AttachmentInputData> &&, Function<void(bool)> &&) override;
      49             : 
      50         756 :         const Rc<core::Queue> &getRenderQueue() const { return _input->queue; }
      51         189 :         const Rc<TransferResource> &getTransferResource() const { return _resource; }
      52             : 
      53             : protected:
      54             :         void runShaders(FrameHandle &frame);
      55             :         void runPipelines(FrameHandle &frame);
      56             : 
      57             :         Device *_device = nullptr;
      58             :         std::atomic<size_t> _programsInQueue = 0;
      59             :         std::atomic<size_t> _pipelinesInQueue = 0;
      60             :         Rc<TransferResource> _resource;
      61             :         Rc<RenderQueueInput> _input;
      62             : };
      63             : 
      64             : class RenderQueuePass : public QueuePass {
      65             : public:
      66             :         virtual ~RenderQueuePass();
      67             : 
      68             :         virtual bool init(QueuePassBuilder &, const AttachmentData *);
      69             : 
      70             :         virtual Rc<QueuePassHandle> makeFrameHandle(const FrameQueue &) override;
      71             : 
      72         189 :         const AttachmentData *getAttachment() const {
      73         189 :                 return _attachment;
      74             :         }
      75             : 
      76             : protected:
      77             :         using QueuePass::init;
      78             : 
      79             :         const AttachmentData *_attachment = nullptr;
      80             : };
      81             : 
      82             : class RenderQueuePassHandle : public QueuePassHandle {
      83             : public:
      84             :         virtual ~RenderQueuePassHandle();
      85             : 
      86             :         virtual bool init(QueuePass &, const FrameQueue &) override;
      87             : 
      88             :         virtual bool prepare(FrameQueue &, Function<void(bool)> &&) override;
      89             :         virtual void submit(FrameQueue &, Rc<FrameSync> &&, Function<void(bool)> &&onSubmited, Function<void(bool)> &&onComplete) override;
      90             : 
      91             :         virtual void finalize(FrameQueue &, bool successful) override;
      92             : 
      93             : protected:
      94             :         virtual bool prepareMaterials(FrameHandle &frame, VkCommandBuffer buf,
      95             :                         const Rc<core::MaterialAttachment> &attachment, Vector<VkBufferMemoryBarrier> &outputBufferBarriers);
      96             : 
      97             :         Rc<TransferResource> _resource;
      98             :         Rc<core::Queue> _queue;
      99             :         RenderQueueAttachmentHandle *_attachment;
     100             : };
     101             : 
     102          84 : RenderQueueCompiler::~RenderQueueCompiler() { }
     103             : 
     104          42 : bool RenderQueueCompiler::init(Device &dev, TransferQueue *transfer, MaterialCompiler *compiler) {
     105             :         using namespace core;
     106             : 
     107          42 :         Queue::Builder builder("RenderQueueCompiler");
     108             : 
     109          84 :         auto attachment = builder.addAttachemnt("RenderQueueAttachment", [&] (AttachmentBuilder &attachmentBuilder) -> Rc<Attachment> {
     110          42 :                 attachmentBuilder.defineAsInput();
     111          42 :                 attachmentBuilder.defineAsOutput();
     112          84 :                 return Rc<RenderQueueAttachment>::create(attachmentBuilder);
     113          42 :         });
     114             : 
     115          42 :         builder.addPass("RenderQueueRenderPass", PassType::Transfer, RenderOrdering(0), [&] (QueuePassBuilder &passBuilder) -> Rc<core::QueuePass> {
     116          84 :                 return Rc<RenderQueuePass>::create(passBuilder, attachment);
     117             :         });
     118             : 
     119          42 :         if (Queue::init(move(builder))) {
     120          42 :                 _attachment = attachment;
     121             : 
     122          42 :                 prepare(dev);
     123             : 
     124          84 :                 for (auto &it : getPasses()) {
     125          42 :                         auto pass = Rc<RenderPass>::create(dev, *it);
     126          42 :                         it->impl = pass.get();
     127          42 :                 }
     128             : 
     129          42 :                 _transfer = transfer;
     130          42 :                 _materialCompiler = compiler;
     131          42 :                 return true;
     132             :         }
     133           0 :         return false;
     134          42 : }
     135             : 
     136         189 : auto RenderQueueCompiler::makeRequest(Rc<RenderQueueInput> &&input) -> Rc<FrameRequest> {
     137         189 :         auto ret = Rc<FrameRequest>::create(this);
     138         189 :         ret->addInput(_attachment, move(input));
     139         189 :         return ret;
     140           0 : }
     141             : 
     142          84 : RenderQueueAttachment::~RenderQueueAttachment() { }
     143             : 
     144         189 : auto RenderQueueAttachment::makeFrameHandle(const FrameQueue &handle) -> Rc<AttachmentHandle> {
     145         378 :         return Rc<RenderQueueAttachmentHandle>::create(this, handle);
     146             : }
     147             : 
     148         378 : RenderQueueAttachmentHandle::~RenderQueueAttachmentHandle() { }
     149             : 
     150         189 : bool RenderQueueAttachmentHandle::setup(FrameQueue &handle, Function<void(bool)> &&) {
     151         189 :         _device = static_cast<Device *>(handle.getFrame()->getDevice());
     152         189 :         return true;
     153             : }
     154             : 
     155         189 : void RenderQueueAttachmentHandle::submitInput(FrameQueue &q, Rc<core::AttachmentInputData> &&data, Function<void(bool)> &&cb) {
     156         189 :         _input = (RenderQueueInput *)data.get();
     157         189 :         if (!_input || q.isFinalized()) {
     158           0 :                 cb(false);
     159           0 :                 return;
     160             :         }
     161             : 
     162         189 :         q.getFrame()->waitForDependencies(data->waitDependencies, [this, cb = move(cb)] (FrameHandle &handle, bool success) {
     163         189 :                 if (!success || !handle.isValidFlag()) {
     164           0 :                         cb(false);
     165           0 :                         return;
     166             :                 }
     167             : 
     168         189 :                 if (_input->queue->getInternalResource()) {
     169          84 :                         handle.performInQueue([this] (FrameHandle &frame) -> bool {
     170          42 :                                 runShaders(frame);
     171          42 :                                 _resource = Rc<TransferResource>::create(_device->getAllocator(), _input->queue->getInternalResource());
     172          42 :                                 if (_resource->initialize()) {
     173          42 :                                         return true;
     174             :                                 }
     175           0 :                                 return false;
     176          42 :                         }, [cb = move(cb)] (FrameHandle &frame, bool success) {
     177          42 :                                 cb(success);
     178          42 :                         }, nullptr, "RenderQueueAttachmentHandle::submitInput _input->queue->getInternalResource");
     179             :                 } else {
     180         147 :                         handle.performOnGlThread([this, cb = move(cb)] (FrameHandle &frame) {
     181         147 :                                 cb(true);
     182         147 :                                 runShaders(frame);
     183         147 :                         }, this, true, "RenderQueueAttachmentHandle::submitInput");
     184             :                 }
     185             :         });
     186             : }
     187             : 
     188         189 : void RenderQueueAttachmentHandle::runShaders(FrameHandle &frame) {
     189         189 :         size_t tasksCount = 0;
     190         189 :         Vector<core::ProgramData *> programs;
     191             : 
     192             :         // count phase-1 tasks
     193         189 :         _programsInQueue += _input->queue->getPasses().size();
     194         189 :         tasksCount += _input->queue->getPasses().size();
     195             : 
     196        1785 :         for (auto &it : _input->queue->getPrograms()) {
     197        1596 :                 if (auto p = _device->getProgram(it->key)) {
     198           0 :                         it->program = p;
     199             :                 } else {
     200        1596 :                         ++ tasksCount;
     201        1596 :                         ++ _programsInQueue;
     202        1596 :                         programs.emplace_back(it);
     203        1596 :                 }
     204             :         }
     205             : 
     206        1785 :         for (auto &it : programs) {
     207        1596 :                 frame.performRequiredTask([this, req = it] (FrameHandle &frame) {
     208        1596 :                         auto ret = Rc<Shader>::create(*_device, *req);
     209        1596 :                         if (!ret) {
     210           0 :                                 log::error("Gl-Device", "Fail to compile shader program ", req->key);
     211           0 :                                 return false;
     212             :                         } else {
     213        1596 :                                 req->program = _device->addProgram(ret);
     214        3192 :                                 if (_programsInQueue.fetch_sub(1) == 1) {
     215           0 :                                         runPipelines(frame);
     216             :                                 }
     217             :                         }
     218        1596 :                         return true;
     219        1596 :                 }, this, "RenderQueueAttachmentHandle::runShaders - programs");
     220             :         }
     221             : 
     222         189 :         _input->queue->prepare(*_device);
     223             : 
     224         504 :         for (auto &it : _input->queue->getPasses()) {
     225         315 :                 frame.performRequiredTask([this, req = it] (FrameHandle &frame) -> bool {
     226         315 :                         auto ret = Rc<RenderPass>::create(*_device, *req);
     227         315 :                         if (!ret) {
     228           0 :                                 log::error("Gl-Device", "Fail to compile render pass ", req->key);
     229           0 :                                 return false;
     230             :                         } else {
     231         315 :                                 req->impl = ret.get();
     232         630 :                                 if (_programsInQueue.fetch_sub(1) == 1) {
     233         189 :                                         runPipelines(frame);
     234             :                                 }
     235             :                         }
     236         315 :                         return true;
     237         315 :                 }, this, "RenderQueueAttachmentHandle::runShaders - passes");
     238             :         }
     239             : 
     240         189 :         if (tasksCount == 0) {
     241           0 :                 runPipelines(frame);
     242             :         }
     243         189 : }
     244             : 
     245         189 : void RenderQueueAttachmentHandle::runPipelines(FrameHandle &frame) {
     246         189 :         [[maybe_unused]] size_t tasksCount = _pipelinesInQueue.load();
     247         504 :         for (auto &pit : _input->queue->getPasses()) {
     248         588 :                 for (auto &sit : pit->subpasses) {
     249         273 :                         _pipelinesInQueue += sit->graphicPipelines.size() + sit->computePipelines.size();
     250         273 :                         tasksCount += sit->graphicPipelines.size() + sit->computePipelines.size();
     251             :                 }
     252             :         }
     253             : 
     254         504 :         for (auto &pit : _input->queue->getPasses()) {
     255         588 :                 for (auto &sit : pit->subpasses) {
     256         357 :                         for (auto &it : sit->graphicPipelines) {
     257          84 :                                 frame.performRequiredTask([this, pass = sit, pipeline = it] (FrameHandle &frame) -> bool {
     258          84 :                                         auto ret = Rc<GraphicPipeline>::create(*_device, *pipeline, *pass, *_input->queue);
     259          84 :                                         if (!ret) {
     260           0 :                                                 log::error("Gl-Device", "Fail to compile pipeline ", pipeline->key);
     261           0 :                                                 return false;
     262             :                                         } else {
     263          84 :                                                 pipeline->pipeline = ret.get();
     264             :                                         }
     265          84 :                                         return true;
     266          84 :                                 }, this, "RenderQueueAttachmentHandle::runPipelines");
     267             :                         }
     268        1785 :                         for (auto &it : sit->computePipelines) {
     269        1512 :                                 frame.performRequiredTask([this, pass = sit, pipeline = it] (FrameHandle &frame) -> bool {
     270        1511 :                                         auto ret = Rc<ComputePipeline>::create(*_device, *pipeline, *pass, *_input->queue);
     271        1512 :                                         if (!ret) {
     272           0 :                                                 log::error("Gl-Device", "Fail to compile pipeline ", pipeline->key);
     273           0 :                                                 return false;
     274             :                                         } else {
     275        1512 :                                                 pipeline->pipeline = ret.get();
     276             :                                         }
     277        1512 :                                         return true;
     278        1512 :                                 }, this, "RenderQueueAttachmentHandle::runPipelines");
     279             :                         }
     280             :                 }
     281             :         }
     282         189 : }
     283             : 
     284          84 : RenderQueuePass::~RenderQueuePass() { }
     285             : 
     286          42 : bool RenderQueuePass::init(QueuePassBuilder &passBuilder, const AttachmentData *attachment) {
     287          42 :         passBuilder.addAttachment(attachment);
     288             : 
     289          42 :         if (!QueuePass::init(passBuilder)) {
     290           0 :                 return false;
     291             :         }
     292             : 
     293          42 :         _attachment = attachment;
     294          42 :         return true;
     295             : }
     296             : 
     297         189 : auto RenderQueuePass::makeFrameHandle(const FrameQueue &handle) -> Rc<QueuePassHandle> {
     298         378 :         return Rc<RenderQueuePassHandle>::create(*this, handle);
     299             : }
     300             : 
     301         378 : RenderQueuePassHandle::~RenderQueuePassHandle() {
     302         189 :         if (_resource) {
     303          42 :                 _resource->invalidate(*_device);
     304             :         }
     305         378 : }
     306             : 
     307         189 : bool RenderQueuePassHandle::init(QueuePass &pass, const FrameQueue &queue) {
     308         189 :         if (!QueuePassHandle::init(pass, queue)) {
     309           0 :                 return false;
     310             :         }
     311             : 
     312         189 :         _isAsync = true;
     313         189 :         return true;
     314             : }
     315             : 
     316         189 : bool RenderQueuePassHandle::prepare(FrameQueue &frame, Function<void(bool)> &&cb) {
     317         189 :         if (auto a = frame.getAttachment(static_cast<RenderQueuePass *>(_queuePass.get())->getAttachment())) {
     318         189 :                 _attachment = static_cast<RenderQueueAttachmentHandle *>(a->handle.get());
     319             :         }
     320             : 
     321         189 :         _loop = static_cast<Loop *>(frame.getLoop());
     322         189 :         _device = static_cast<Device *>(frame.getFrame()->getDevice());
     323         189 :         _queue = _attachment->getRenderQueue();
     324             : 
     325         189 :         auto hasMaterials = false;
     326         189 :         auto &res = _attachment->getTransferResource();
     327         796 :         for (auto &it : _queue->getAttachments()) {
     328         628 :                 if (auto v = it->attachment.cast<core::MaterialAttachment>()) {
     329             : 
     330          21 :                         v->setCompiler(static_cast<RenderQueueCompiler *>(_data->queue->queue)->getMaterialCompiler());
     331             : 
     332          21 :                         if (!v->getPredefinedMaterials().empty()) {
     333          21 :                                 hasMaterials = true;
     334          21 :                                 break;
     335             :                         }
     336         628 :                 }
     337             :         }
     338             : 
     339         189 :         if (res || hasMaterials) {
     340          42 :                 _resource = res;
     341          42 :                 _pool = _device->acquireCommandPool(QueueOperations::Transfer);
     342          42 :                 if (!_pool) {
     343           0 :                         invalidate();
     344           0 :                         return false;
     345             :                 }
     346             : 
     347          84 :                 frame.getFrame()->performInQueue([this, hasMaterials] (FrameHandle &frame) {
     348          42 :                         auto buf = _pool->recordBuffer(*_device, [&, this] (CommandBuffer &buf) {
     349          42 :                                 Vector<VkImageMemoryBarrier> outputImageBarriers;
     350          42 :                                 Vector<VkBufferMemoryBarrier> outputBufferBarriers;
     351             : 
     352          42 :                                 if (_resource) {
     353          42 :                                         if (!_resource->prepareCommands(_pool->getFamilyIdx(), buf.getBuffer(), outputImageBarriers, outputBufferBarriers)) {
     354           0 :                                                 log::error("vk::RenderQueueCompiler", "Fail to compile resource for ", _queue->getName());
     355           0 :                                                 return false;
     356             :                                         }
     357          42 :                                         _resource->compile();
     358             :                                 }
     359             : 
     360          42 :                                 if (hasMaterials) {
     361         210 :                                         for (auto &it : _queue->getAttachments()) {
     362         189 :                                                 if (auto v = it->attachment.cast<core::MaterialAttachment>()) {
     363          21 :                                                         if (!prepareMaterials(frame, buf.getBuffer(), v, outputBufferBarriers)) {
     364           0 :                                                                 log::error("vk::RenderQueueCompiler", "Fail to compile predefined materials for ", _queue->getName());
     365           0 :                                                                 return false;
     366             :                                                         }
     367         189 :                                                 }
     368             :                                         }
     369             :                                 }
     370             : 
     371          84 :                                 _device->getTable()->vkCmdPipelineBarrier(buf.getBuffer(), VK_PIPELINE_STAGE_TRANSFER_BIT,
     372             :                                         VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0,
     373             :                                         0, nullptr,
     374          42 :                                         outputBufferBarriers.size(), outputBufferBarriers.data(),
     375          42 :                                         outputImageBarriers.size(), outputImageBarriers.data());
     376          42 :                                 return true;
     377          84 :                         });
     378             : 
     379          42 :                         if (buf) {
     380          42 :                                 _buffers.emplace_back(buf);
     381             :                         }
     382          42 :                         return true;
     383          42 :                 }, [this, cb = move(cb)] (FrameHandle &frame, bool success) {
     384          42 :                         if (success) {
     385          42 :                                 _commandsReady = true;
     386          42 :                                 _descriptorsReady = true;
     387             :                         } else {
     388           0 :                                 log::error("VK-Error", "Fail to doPrepareCommands");
     389             :                         }
     390          42 :                         cb(success);
     391          42 :                 }, this, "RenderPass::doPrepareCommands _attachment->getTransferResource");
     392             :         } else {
     393         147 :                 frame.getFrame()->performOnGlThread([cb = move(cb)] (FrameHandle &frame) {
     394         147 :                         cb(true);
     395         147 :                 }, this, false, "RenderPass::doPrepareCommands");
     396             :         }
     397             : 
     398         189 :         return false;
     399             : }
     400             : 
     401         189 : void RenderQueuePassHandle::submit(FrameQueue &queue, Rc<FrameSync> &&sync, Function<void(bool)> &&onSubmited, Function<void(bool)> &&onComplete) {
     402         189 :         if (_buffers.empty()) {
     403         147 :                 onSubmited(true);
     404         147 :                 onComplete(true);
     405             :         } else {
     406          42 :                 QueuePassHandle::submit(queue, move(sync), move(onSubmited), move(onComplete));
     407             :         }
     408         189 : }
     409             : 
     410         189 : void RenderQueuePassHandle::finalize(FrameQueue &frame, bool successful) {
     411         189 :         QueuePassHandle::finalize(frame, successful);
     412         189 :         Vector<uint64_t> passIds;
     413         189 :         auto &cache = frame.getLoop()->getFrameCache();
     414         504 :         for (auto &it : _attachment->getRenderQueue()->getPasses()) {
     415         315 :                 if (it->impl && it->pass->getType() != core::PassType::Generic) {
     416         293 :                         passIds.emplace_back(it->impl->getIndex());
     417         293 :                         cache->addRenderPass(it->impl->getIndex());
     418             :                 }
     419             :         }
     420             : 
     421         189 :         Vector<uint64_t> attachmentIds;
     422         903 :         for (auto &it : _attachment->getRenderQueue()->getAttachments()) {
     423         714 :                 if (it->type == core::AttachmentType::Image) {
     424         105 :                         attachmentIds.emplace_back(it->id);
     425         105 :                         cache->addAttachment(it->id);
     426             :                 }
     427             :         }
     428             : 
     429         567 :         _attachment->getRenderQueue()->setCompiled(*_device, [loop = Rc<core::Loop>(frame.getLoop()),
     430         378 :                         passIds = move(passIds), attachmentIds = move(attachmentIds)] () mutable {
     431         189 :                 loop->performOnGlThread([loop, passIds = move(passIds), attachmentIds = move(attachmentIds)] () mutable {
     432         105 :                         auto &cache = loop->getFrameCache();
     433         314 :                         for (auto &id : passIds) {
     434         209 :                                 cache->removeRenderPass(id);
     435             :                         }
     436         210 :                         for (auto &id : attachmentIds) {
     437         105 :                                 cache->removeAttachment(id);
     438             :                         }
     439         105 :                         cache->removeUnreachableFramebuffers();
     440         105 :                 });
     441         189 :         });
     442         189 : }
     443             : 
     444          21 : bool RenderQueuePassHandle::prepareMaterials(FrameHandle &iframe, VkCommandBuffer buf,
     445             :                 const Rc<core::MaterialAttachment> &attachment, Vector<VkBufferMemoryBarrier> &outputBufferBarriers) {
     446          21 :         auto table = _device->getTable();
     447          21 :         auto &initial = attachment->getPredefinedMaterials();
     448          21 :         if (initial.empty()) {
     449           0 :                 return true;
     450             :         }
     451             : 
     452          21 :         auto data = attachment->allocateSet(*_device);
     453             : 
     454          21 :         auto buffers = updateMaterials(iframe, data, initial, SpanView<core::MaterialId>(), SpanView<core::MaterialId>());
     455             : 
     456             :         VkBufferCopy indexesCopy;
     457          21 :         indexesCopy.srcOffset = 0;
     458          21 :         indexesCopy.dstOffset = 0;
     459          21 :         indexesCopy.size = buffers.stagingBuffer->getSize();
     460             : 
     461          21 :         auto stagingBuf = buffers.stagingBuffer->getBuffer();
     462          21 :         auto targetBuf = buffers.targetBuffer->getBuffer();
     463             : 
     464          21 :         Vector<VkImageMemoryBarrier> outputImageBarriers;
     465          21 :         table->vkCmdCopyBuffer(buf, stagingBuf, targetBuf, 1, &indexesCopy);
     466             : 
     467          21 :         QueueOperations ops = QueueOperations::None;
     468          42 :         for (auto &it : attachment->getRenderPasses()) {
     469          21 :                 ops |= static_cast<vk::QueuePass *>(it->pass.get())->getQueueOps();
     470          21 :         }
     471             : 
     472          21 :         if (auto q = _device->getQueueFamily(ops)) {
     473          21 :                 if (q->index == _pool->getFamilyIdx()) {
     474           0 :                         outputBufferBarriers.emplace_back(VkBufferMemoryBarrier({
     475             :                                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, nullptr,
     476             :                                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
     477             :                                 VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
     478           0 :                                 buffers.targetBuffer->getBuffer(), 0, VK_WHOLE_SIZE
     479             :                         }));
     480             :                 } else {
     481          21 :                         auto &b = outputBufferBarriers.emplace_back(VkBufferMemoryBarrier({
     482             :                                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, nullptr,
     483             :                                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
     484          21 :                                 _pool->getFamilyIdx(), q->index,
     485          21 :                                 buffers.targetBuffer->getBuffer(), 0, VK_WHOLE_SIZE
     486             :                         }));
     487          21 :                         buffers.targetBuffer->setPendingBarrier(b);
     488             :                 }
     489             : 
     490          21 :                 auto tmpBuffer = new Rc<Buffer>(move(buffers.targetBuffer));
     491          21 :                 auto tmpOrder = new HashMap<core::MaterialId, uint32_t>(move(buffers.ordering));
     492          21 :                 iframe.performOnGlThread([attachment, data, tmpBuffer, tmpOrder] (FrameHandle &) {
     493          21 :                         data->setBuffer(move(*tmpBuffer), move(*tmpOrder));
     494          21 :                         attachment->setMaterials(data);
     495          21 :                         delete tmpBuffer;
     496          21 :                         delete tmpOrder;
     497          21 :                 }, nullptr, false, "RenderQueueRenderPassHandle::prepareMaterials");
     498             : 
     499          21 :                 return true;
     500             :         }
     501           0 :         return false;
     502          21 : }
     503             : 
     504             : }

Generated by: LCOV version 1.14