LCOV - code coverage report
Current view: top level - xenolith/backend/vk - XLVkRenderPass.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 454 624 72.8 %
Date: 2024-05-12 00:16:13 Functions: 23 27 85.2 %

          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 "XLVkDevice.h"
      25             : #include "XLVkRenderPass.h"
      26             : #include "XLVkQueuePass.h"
      27             : #include "XLVkAttachment.h"
      28             : #include "XLVkTextureSet.h"
      29             : #include "XLCoreAttachment.h"
      30             : #include "XLCoreFrameQueue.h"
      31             : #include <forward_list>
      32             : 
      33             : namespace STAPPLER_VERSIONIZED stappler::xenolith::vk {
      34             : 
      35        1113 : DescriptorBinding::~DescriptorBinding() {
      36        1113 :         data.clear();
      37        1113 : }
      38             : 
      39         441 : DescriptorBinding::DescriptorBinding(VkDescriptorType type, uint32_t count) : type(type) {
      40         441 :         data.resize(count, DescriptorData{core::ObjectHandle::zero(), nullptr});
      41         441 : }
      42             : 
      43     1581483 : Rc<Ref> DescriptorBinding::write(uint32_t idx, DescriptorBufferInfo &&info) {
      44     1581483 :         auto ret = move(data[idx].data);
      45     1581483 :         data[idx] = DescriptorData{core::ObjectHandle(info.buffer->getBuffer()), move(info.buffer)};
      46     1581483 :         return ret;
      47           0 : }
      48             : 
      49       28455 : Rc<Ref> DescriptorBinding::write(uint32_t idx, DescriptorImageInfo &&info) {
      50       28455 :         auto ret = move(data[idx].data);
      51       28469 :         data[idx] = DescriptorData{core::ObjectHandle(info.imageView->getImageView()), move(info.imageView)};
      52       28450 :         return ret;
      53           0 : }
      54             : 
      55           0 : Rc<Ref> DescriptorBinding::write(uint32_t idx, DescriptorBufferViewInfo &&info) {
      56           0 :         auto ret = move(data[idx].data);
      57           0 :         data[idx] = DescriptorData{core::ObjectHandle(info.buffer->getBuffer()), move(info.buffer)};
      58           0 :         return ret;
      59           0 : }
      60             : 
      61         117 : bool Framebuffer::init(Device &dev, RenderPass *renderPass, SpanView<Rc<core::ImageView>> imageViews) {
      62         117 :         Vector<VkImageView> views; views.reserve(imageViews.size());
      63         117 :         _viewIds.reserve(imageViews.size());
      64         117 :         _imageViews.reserve(imageViews.size());
      65         117 :         _renderPass = renderPass;
      66             : 
      67         117 :         auto extent = imageViews.front()->getFramebufferExtent();
      68             : 
      69         468 :         for (auto &it : imageViews) {
      70         351 :                 views.emplace_back(((ImageView *)it.get())->getImageView());
      71         351 :                 _viewIds.emplace_back(it->getIndex());
      72         351 :                 _imageViews.emplace_back(it);
      73             : 
      74         351 :                 if (extent != it->getFramebufferExtent()) {
      75           0 :                         log::error("Framebuffer", "Invalid extent for framebuffer image: ", it->getFramebufferExtent());
      76           0 :                         return false;
      77             :                 }
      78             :         }
      79             : 
      80         117 :         VkFramebufferCreateInfo framebufferInfo { };
      81         117 :         framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
      82         117 :         framebufferInfo.renderPass = renderPass->getRenderPass();
      83         117 :         framebufferInfo.attachmentCount = views.size();
      84         117 :         framebufferInfo.pAttachments = views.data();
      85         117 :         framebufferInfo.width = extent.width;
      86         117 :         framebufferInfo.height = extent.height;
      87         117 :         framebufferInfo.layers = extent.depth;
      88             : 
      89         117 :         if (dev.getTable()->vkCreateFramebuffer(dev.getDevice(), &framebufferInfo, nullptr, &_framebuffer) == VK_SUCCESS) {
      90         117 :                 _extent = Extent2(extent.width, extent.height);
      91         117 :                 _layerCount = extent.depth;
      92         117 :                 return core::Framebuffer::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *) {
      93         117 :                         auto d = ((Device *)dev);
      94         117 :                         d->getTable()->vkDestroyFramebuffer(d->getDevice(), (VkFramebuffer)ptr.get(), nullptr);
      95         234 :                 }, core::ObjectType::Framebuffer, ObjectHandle(_framebuffer));
      96             :         }
      97           0 :         return false;
      98         117 : }
      99             : 
     100         357 : bool RenderPass::Data::cleanup(Device &dev) {
     101         357 :         if (renderPass) {
     102          21 :                 dev.getTable()->vkDestroyRenderPass(dev.getDevice(), renderPass, nullptr);
     103          21 :                 renderPass = VK_NULL_HANDLE;
     104             :         }
     105             : 
     106         357 :         if (renderPassAlternative) {
     107          21 :                 dev.getTable()->vkDestroyRenderPass(dev.getDevice(), renderPassAlternative, nullptr);
     108          21 :                 renderPassAlternative = VK_NULL_HANDLE;
     109             :         }
     110             : 
     111         609 :         for (auto &it : layouts) {
     112         504 :                 for (VkDescriptorSetLayout &set : it.layouts) {
     113         252 :                         dev.getTable()->vkDestroyDescriptorSetLayout(dev.getDevice(), set, nullptr);
     114             :                 }
     115             : 
     116         252 :                 if (it.layout) {
     117         252 :                         dev.getTable()->vkDestroyPipelineLayout(dev.getDevice(), it.layout, nullptr);
     118             :                 }
     119             : 
     120         252 :                 if (it.descriptorPool) {
     121         252 :                         dev.getTable()->vkDestroyDescriptorPool(dev.getDevice(), it.descriptorPool, nullptr);
     122             :                 }
     123             :         }
     124             : 
     125         357 :         layouts.clear();
     126             : 
     127         357 :         return false;
     128             : }
     129             : 
     130         357 : bool RenderPass::init(Device &dev, QueuePassData &data) {
     131         357 :         _type = data.pass->getType();
     132         357 :         _name = data.key.str<Interface>();
     133         357 :         switch (_type) {
     134          21 :         case core::PassType::Graphics:
     135          21 :                 return initGraphicsPass(dev, data);
     136             :                 break;
     137         168 :         case core::PassType::Compute:
     138         168 :                 return initComputePass(dev, data);
     139             :                 break;
     140         168 :         case core::PassType::Transfer:
     141         168 :                 return initTransferPass(dev, data);
     142             :                 break;
     143           0 :         case core::PassType::Generic:
     144           0 :                 return initGenericPass(dev, data);
     145             :                 break;
     146             :         }
     147             : 
     148           0 :         return false;
     149             : }
     150             : 
     151        9718 : VkRenderPass RenderPass::getRenderPass(bool alt) const {
     152        9718 :         if (alt && _data->renderPassAlternative) {
     153          21 :                 return _data->renderPassAlternative;
     154             :         }
     155        9697 :         return _data->renderPass;
     156             : }
     157             : 
     158      488784 : bool RenderPass::writeDescriptors(const QueuePassHandle &handle, uint32_t layoutIndex, bool async) const {
     159      488784 :         auto dev = (Device *)_object.device;
     160      488784 :         auto table = dev->getTable();
     161      488598 :         auto data = handle.getData();
     162             : 
     163      488552 :         std::forward_list<Vector<VkDescriptorImageInfo>> images;
     164      488281 :         std::forward_list<Vector<VkDescriptorBufferInfo>> buffers;
     165      488132 :         std::forward_list<Vector<VkBufferView>> views;
     166             : 
     167      487839 :         Vector<VkWriteDescriptorSet> writes;
     168             : 
     169      321832 :         auto writeDescriptor = [&] (DescriptorSet *set, const PipelineDescriptor &desc, uint32_t currentDescriptor, bool external) {
     170      321832 :                 auto a = handle.getAttachmentHandle(desc.attachment->attachment);
     171      321523 :                 if (!a) {
     172           0 :                         return false;
     173             :                 }
     174             : 
     175      321523 :                 Vector<VkDescriptorImageInfo> *localImages = nullptr;
     176      321523 :                 Vector<VkDescriptorBufferInfo> *localBuffers = nullptr;
     177      321523 :                 Vector<VkBufferView> *localViews = nullptr;
     178             : 
     179             :                 VkWriteDescriptorSet writeData;
     180      321523 :                 writeData.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
     181      321523 :                 writeData.pNext = nullptr;
     182      321523 :                 writeData.dstSet = set->set;
     183      321523 :                 writeData.dstBinding = currentDescriptor;
     184      321523 :                 writeData.dstArrayElement = 0;
     185      321523 :                 writeData.descriptorCount = 0;
     186      321523 :                 writeData.descriptorType = VkDescriptorType(desc.type);
     187      321523 :                 writeData.pImageInfo = VK_NULL_HANDLE;
     188      321523 :                 writeData.pBufferInfo = VK_NULL_HANDLE;
     189      321523 :                 writeData.pTexelBufferView = VK_NULL_HANDLE;
     190             : 
     191      321523 :                 auto c = a->getDescriptorArraySize(handle, desc, external);
     192     2032877 :                 for (uint32_t i = 0; i < c; ++ i) {
     193     1711295 :                         if (a->isDescriptorDirty(handle, desc, i, external)) {
     194     1609695 :                                 switch (desc.type) {
     195       28530 :                                 case DescriptorType::Sampler:
     196             :                                 case DescriptorType::CombinedImageSampler:
     197             :                                 case DescriptorType::SampledImage:
     198             :                                 case DescriptorType::StorageImage:
     199             :                                 case DescriptorType::InputAttachment:
     200       28530 :                                         if (!localImages) {
     201       28528 :                                                 localImages = &images.emplace_front(Vector<VkDescriptorImageInfo>());
     202             :                                         }
     203       28470 :                                         if (localImages) {
     204       28469 :                                                 auto h = (ImageAttachmentHandle *)a;
     205             : 
     206       28469 :                                                 DescriptorImageInfo info(&desc, i, external);
     207       28470 :                                                 if (!h->writeDescriptor(handle, info)) {
     208           0 :                                                         return false;
     209             :                                                 } else {
     210       28487 :                                                         localImages->emplace_back(VkDescriptorImageInfo{info.sampler, info.imageView->getImageView(), info.layout});
     211       28455 :                                                         if (auto ref = set->bindings[currentDescriptor].write(i, move(info))) {
     212       28367 :                                                                 handle.autorelease(ref);
     213       28568 :                                                         }
     214             :                                                 }
     215       28569 :                                         }
     216       28565 :                                         break;
     217           0 :                                 case DescriptorType::StorageTexelBuffer:
     218             :                                 case DescriptorType::UniformTexelBuffer:
     219           0 :                                         if (!localViews) {
     220           0 :                                                 localViews = &views.emplace_front(Vector<VkBufferView>());
     221             :                                         }
     222           0 :                                         if (localViews) {
     223           0 :                                                 auto h = (TexelAttachmentHandle *)a;
     224             : 
     225           0 :                                                 DescriptorBufferViewInfo info(&desc, i, external);
     226           0 :                                                 if (h->writeDescriptor(handle, info)) {
     227           0 :                                                         localViews->emplace_back(info.target);
     228           0 :                                                         if (auto ref = set->bindings[currentDescriptor].write(i, move(info))) {
     229           0 :                                                                 handle.autorelease(ref);
     230           0 :                                                         }
     231             :                                                 } else {
     232           0 :                                                         return false;
     233             :                                                 }
     234           0 :                                         }
     235           0 :                                         break;
     236     1581483 :                                 case DescriptorType::UniformBuffer:
     237             :                                 case DescriptorType::StorageBuffer:
     238             :                                 case DescriptorType::UniformBufferDynamic:
     239             :                                 case DescriptorType::StorageBufferDynamic:
     240     1581483 :                                         if (!localBuffers) {
     241      263486 :                                                 localBuffers = &buffers.emplace_front(Vector<VkDescriptorBufferInfo>());
     242             :                                         }
     243     1581483 :                                         if (localBuffers) {
     244     1581483 :                                                 auto h = (BufferAttachmentHandle *)a;
     245             : 
     246     1581483 :                                                 DescriptorBufferInfo info(&desc, i, external);
     247     1581483 :                                                 if (!h->writeDescriptor(handle, info)) {
     248           0 :                                                         return false;
     249             :                                                 } else {
     250     1581483 :                                                         localBuffers->emplace_back(VkDescriptorBufferInfo{info.buffer->getBuffer(), info.offset, info.range});
     251     1581483 :                                                         if (auto ref = set->bindings[currentDescriptor].write(i, move(info))) {
     252     1579824 :                                                                 handle.autorelease(ref);
     253     1581483 :                                                         }
     254             :                                                 }
     255     1581483 :                                         }
     256     1581483 :                                         break;
     257           0 :                                 case DescriptorType::Unknown:
     258             :                                 case DescriptorType::Attachment:
     259           0 :                                         break;
     260             :                                 }
     261     1609730 :                                 ++ writeData.descriptorCount;
     262             :                         } else {
     263      101619 :                                 if (writeData.descriptorCount > 0) {
     264           0 :                                         if (localImages) {
     265           0 :                                                 writeData.pImageInfo = localImages->data();
     266             :                                         }
     267           0 :                                         if (localBuffers) {
     268           0 :                                                 writeData.pBufferInfo = localBuffers->data();
     269             :                                         }
     270           0 :                                         if (localViews) {
     271           0 :                                                 writeData.pTexelBufferView = localViews->data();
     272             :                                         }
     273             : 
     274           0 :                                         writes.emplace_back(move(writeData));
     275             : 
     276           0 :                                         writeData.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
     277           0 :                                         writeData.pNext = nullptr;
     278           0 :                                         writeData.dstSet = set->set;
     279           0 :                                         writeData.dstBinding = currentDescriptor;
     280           0 :                                         writeData.descriptorCount = 0;
     281           0 :                                         writeData.descriptorType = VkDescriptorType(desc.type);
     282           0 :                                         writeData.pImageInfo = VK_NULL_HANDLE;
     283           0 :                                         writeData.pBufferInfo = VK_NULL_HANDLE;
     284           0 :                                         writeData.pTexelBufferView = VK_NULL_HANDLE;
     285             : 
     286           0 :                                         localImages = nullptr;
     287           0 :                                         localBuffers = nullptr;
     288           0 :                                         localViews = nullptr;
     289             :                                 }
     290             : 
     291      101619 :                                 writeData.dstArrayElement = i + 1;
     292             :                         }
     293             :                 }
     294             : 
     295      321582 :                 if (writeData.descriptorCount > 0) {
     296      292047 :                         if (localImages) {
     297       28566 :                                 writeData.pImageInfo = localImages->data();
     298             :                         }
     299      292047 :                         if (localBuffers) {
     300      263486 :                                 writeData.pBufferInfo = localBuffers->data();
     301             :                         }
     302      292047 :                         if (localViews) {
     303           0 :                                 writeData.pTexelBufferView = localViews->data();
     304             :                         }
     305             : 
     306      292047 :                         writes.emplace_back(move(writeData));
     307             :                 }
     308      321879 :                 return true;
     309      487513 :         };
     310             : 
     311      487513 :         uint32_t currentSet = 0;
     312      977124 :         for (auto &descriptorSetData : data->pipelineLayouts[layoutIndex]->sets) {
     313      486903 :                 auto set = _data->layouts[layoutIndex].sets[currentSet];
     314      488108 :                 uint32_t currentDescriptor = 0;
     315     1131954 :                 for (auto &it : descriptorSetData->descriptors) {
     316      638553 :                         if (it->updateAfterBind != async) {
     317      321963 :                                 ++ currentDescriptor;
     318      321963 :                                 continue;
     319             :                         }
     320      316590 :                         if (!writeDescriptor(set, *it, currentDescriptor, false)) {
     321           0 :                                 return false;
     322             :                         }
     323      321883 :                         ++ currentDescriptor;
     324             :                 }
     325      489132 :                 ++ currentSet;
     326      489132 :         }
     327             : 
     328      488085 :         if (writes.empty()) {
     329      236338 :                 return true;
     330             :         }
     331             : 
     332      252544 :         table->vkUpdateDescriptorSets(dev->getDevice(), writes.size(), writes.data(), 0, nullptr);
     333      255372 :         return true;
     334      491724 : }
     335             : 
     336      170251 : void RenderPass::perform(const QueuePassHandle &handle, CommandBuffer &buf, const Callback<void()> &cb, bool writeBarriers) {
     337      170251 :         bool useAlternative = false;
     338      179747 :         for (auto &it : _variableAttachments) {
     339        9517 :                 if (auto aHandle = handle.getAttachmentHandle(it->attachment)) {
     340        9517 :                         if (aHandle->getQueueData()->image && !aHandle->getQueueData()->image->isSwapchainImage()) {
     341          21 :                                 useAlternative = true;
     342          21 :                                 break;
     343             :                         }
     344             :                 }
     345             :         }
     346             : 
     347      170253 :         Vector<QueuePassHandle::ImageInputOutputBarrier> imageBarriersData;
     348      170253 :         Vector<QueuePassHandle::BufferInputOutputBarrier> bufferBarriersData;
     349             : 
     350      170252 :         Vector<vk::ImageMemoryBarrier> imageBarriers;
     351      170252 :         Vector<vk::BufferMemoryBarrier> bufferBarriers;
     352             : 
     353      170251 :         core::PipelineStage fromStage = core::PipelineStage::None;
     354      170251 :         core::PipelineStage toStage = core::PipelineStage::None;
     355             : 
     356      170251 :         if (writeBarriers) {
     357       50417 :                 bool hasPendings = false;
     358             : 
     359      201617 :                 for (auto &it : handle.getQueueData()->attachments) {
     360      151194 :                         switch (it.first->attachment->type) {
     361          21 :                         case core::AttachmentType::Image:
     362          21 :                                 if (auto h = dynamic_cast<ImageAttachmentHandle *>(it.second->handle.get())) {
     363          21 :                                         if (auto img = static_cast<Image *>(it.second->image->getImage().get())) {
     364          21 :                                                 auto b = handle.getImageInputOutputBarrier(static_cast<Device *>(_object.device), img, *h);
     365          21 :                                                 if (auto pending = img->getPendingBarrier()) {
     366           0 :                                                         b.input = *pending;
     367           0 :                                                         img->dropPendingBarrier();
     368           0 :                                                         hasPendings = true;
     369             :                                                 }
     370          21 :                                                 if (b.input || b.output) {
     371          21 :                                                         imageBarriersData.emplace_back(move(b));
     372             :                                                 }
     373             :                                         }
     374             :                                 }
     375          21 :                                 break;
     376      151173 :                         case core::AttachmentType::Buffer:
     377      151173 :                                 if (auto h = dynamic_cast<BufferAttachmentHandle *>(it.second->handle.get())) {
     378      352739 :                                         for (auto &it : h->getBuffers()) {
     379      201556 :                                                 auto b = handle.getBufferInputOutputBarrier(static_cast<Device *>(_object.device), it.buffer, *h, it.offset, it.size);
     380      201553 :                                                 if (auto pending = it.buffer->getPendingBarrier()) {
     381           0 :                                                         b.input = *pending;
     382           0 :                                                         it.buffer->dropPendingBarrier();
     383           0 :                                                         hasPendings = true;
     384             :                                                 }
     385      201554 :                                                 if (b.input || b.output) {
     386           0 :                                                         bufferBarriersData.emplace_back(move(b));
     387             :                                                 }
     388             :                                         }
     389             :                                 }
     390      151179 :                                 break;
     391           0 :                         default:
     392           0 :                                 break;
     393             :                         }
     394             :                 }
     395             : 
     396       50403 :                 for (auto &it : imageBarriersData) {
     397          21 :                         if (it.input) {
     398          21 :                                 fromStage |= it.inputFrom;
     399          21 :                                 toStage |= it.inputTo;
     400          21 :                                 imageBarriers.emplace_back(move(it.input));
     401             :                         }
     402             :                 }
     403       50416 :                 for (auto &it : bufferBarriersData) {
     404           0 :                         if (it.input) {
     405           0 :                                 fromStage |= it.inputFrom;
     406           0 :                                 toStage |= it.inputTo;
     407           0 :                                 bufferBarriers.emplace_back(move(it.input));
     408             :                         }
     409             :                 }
     410             : 
     411       50416 :                 if (hasPendings) {
     412           0 :                         if (fromStage == core::PipelineStage::None) {
     413           0 :                                 fromStage = core::PipelineStage::AllCommands;
     414             :                         }
     415           0 :                         if (toStage == core::PipelineStage::None) {
     416           0 :                                 toStage = core::PipelineStage::AllCommands;
     417             :                         }
     418             :                 }
     419             : 
     420      100811 :                 if ((!imageBarriersData.empty() || !bufferBarriersData.empty())
     421      100810 :                                 && (fromStage != core::PipelineStage::None) && (toStage != core::PipelineStage::None)) {
     422          21 :                         buf.cmdPipelineBarrier(VkPipelineStageFlags(fromStage), VkPipelineStageFlags(toStage), 0, bufferBarriers, imageBarriers);
     423             :                 }
     424             :         }
     425             : 
     426      170249 :         if (_data->renderPass) {
     427        9517 :                 buf.cmdBeginRenderPass(this, (Framebuffer *)handle.getFramebuffer().get(), VK_SUBPASS_CONTENTS_INLINE, useAlternative);
     428             : 
     429        9517 :                 cb();
     430             : 
     431        9517 :                 buf.cmdEndRenderPass();
     432             :         } else {
     433      160732 :                 cb();
     434             :         }
     435             : 
     436      170255 :         if (writeBarriers) {
     437       50421 :                 fromStage = core::PipelineStage::None;
     438       50421 :                 toStage = core::PipelineStage::None;
     439             : 
     440       50421 :                 imageBarriersData.clear();
     441       50421 :                 bufferBarriersData.clear();
     442             : 
     443       50421 :                 for (auto &it : imageBarriersData) {
     444           0 :                         if (it.output) {
     445           0 :                                 fromStage |= it.outputFrom;
     446           0 :                                 toStage |= it.outputTo;
     447           0 :                                 imageBarriers.emplace_back(move(it.output));
     448             :                         }
     449             :                 }
     450       50421 :                 for (auto &it : bufferBarriersData) {
     451           0 :                         if (it.output) {
     452           0 :                                 fromStage |= it.outputFrom;
     453           0 :                                 toStage |= it.outputTo;
     454           0 :                                 bufferBarriers.emplace_back(move(it.output));
     455             :                         }
     456             :                 }
     457             : 
     458       50421 :                 if (!imageBarriersData.empty() || !bufferBarriersData.empty()) {
     459           0 :                         buf.cmdPipelineBarrier(VkPipelineStageFlags(fromStage), VkPipelineStageFlags(toStage), 0, bufferBarriers, imageBarriers);
     460             :                 }
     461             :         }
     462      170255 : }
     463             : 
     464          21 : bool RenderPass::initGraphicsPass(Device &dev, QueuePassData &data) {
     465          21 :         bool hasAlternative = false;
     466          21 :         Data pass;
     467             : 
     468          21 :         size_t attachmentReferences = 0;
     469         189 :         for (auto &desc : data.attachments) {
     470         168 :                 if (desc->attachment->type != core::AttachmentType::Image || desc->subpasses.empty()) {
     471         105 :                         continue;
     472             :                 }
     473             : 
     474             :                 VkAttachmentDescription attachment;
     475             :                 VkAttachmentDescription attachmentAlternative;
     476             : 
     477          63 :                 bool mayAlias = false;
     478         168 :                 for (auto &u : desc->subpasses) {
     479         105 :                         if (u->usage == core::AttachmentUsage::InputOutput || u->usage == core::AttachmentUsage::InputDepthStencil) {
     480           0 :                                 mayAlias = true;
     481             :                         }
     482             :                 }
     483             : 
     484          63 :                 auto imageAttachment = (core::ImageAttachment *)desc->attachment->attachment.get();
     485          63 :                 auto &info = imageAttachment->getImageInfo();
     486             : 
     487          63 :                 attachmentAlternative.flags = attachment.flags = (mayAlias ? VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT : 0);
     488          63 :                 attachmentAlternative.format = attachment.format = VkFormat(info.format);
     489          63 :                 attachmentAlternative.samples = attachment.samples = VkSampleCountFlagBits(info.samples);
     490          63 :                 attachmentAlternative.loadOp = attachment.loadOp = VkAttachmentLoadOp(desc->loadOp);
     491          63 :                 attachmentAlternative.storeOp = attachment.storeOp = VkAttachmentStoreOp(desc->storeOp);
     492          63 :                 attachmentAlternative.stencilLoadOp = attachment.stencilLoadOp = VkAttachmentLoadOp(desc->stencilLoadOp);
     493          63 :                 attachmentAlternative.stencilStoreOp = attachment.stencilStoreOp = VkAttachmentStoreOp(desc->stencilStoreOp);
     494          63 :                 attachmentAlternative.initialLayout = attachment.initialLayout = VkImageLayout(desc->initialLayout);
     495          63 :                 attachmentAlternative.finalLayout = attachment.finalLayout = VkImageLayout(desc->finalLayout);
     496             : 
     497          63 :                 if (desc->finalLayout == core::AttachmentLayout::PresentSrc) {
     498          21 :                         hasAlternative = true;
     499          21 :                         attachmentAlternative.finalLayout = VkImageLayout(core::AttachmentLayout::TransferSrcOptimal);
     500          21 :                         _variableAttachments.emplace(desc);
     501             :                 }
     502             : 
     503          63 :                 desc->index = _attachmentDescriptions.size();
     504             : 
     505          63 :                 _attachmentDescriptions.emplace_back(attachment);
     506          63 :                 _attachmentDescriptionsAlternative.emplace_back(attachmentAlternative);
     507             : 
     508          63 :                 auto fmt = core::getImagePixelFormat(imageAttachment->getImageInfo().format);
     509          63 :                 switch (fmt) {
     510          21 :                 case core::PixelFormat::D:
     511          21 :                         if (desc->loadOp == core::AttachmentLoadOp::Clear) {
     512          21 :                                 auto c = ((core::ImageAttachment *)desc->attachment->attachment.get())->getClearColor();
     513             :                                 VkClearValue clearValue;
     514          21 :                                 clearValue.depthStencil.depth = c.r;
     515          21 :                                 _clearValues.emplace_back(clearValue);
     516             :                         } else {
     517             :                                 VkClearValue clearValue;
     518           0 :                                 clearValue.depthStencil.depth = 0.0f;
     519           0 :                                 _clearValues.emplace_back(clearValue);
     520             :                         }
     521          21 :                         break;
     522           0 :                 case core::PixelFormat::DS:
     523           0 :                         if (desc->stencilLoadOp == core::AttachmentLoadOp::Clear
     524           0 :                                         || desc->loadOp == core::AttachmentLoadOp::Clear) {
     525           0 :                                 auto c = imageAttachment->getClearColor();
     526             :                                 VkClearValue clearValue;
     527           0 :                                 clearValue.depthStencil.depth = c.r;
     528           0 :                                 clearValue.depthStencil.stencil = 0;
     529           0 :                                 _clearValues.emplace_back(clearValue);
     530           0 :                         } else {
     531             :                                 VkClearValue clearValue;
     532           0 :                                 clearValue.depthStencil.depth = 0.0f;
     533           0 :                                 clearValue.depthStencil.stencil = 0;
     534           0 :                                 _clearValues.emplace_back(clearValue);
     535             :                         }
     536           0 :                         break;
     537           0 :                 case core::PixelFormat::S:
     538           0 :                         if (desc->stencilLoadOp == core::AttachmentLoadOp::Clear) {
     539             :                                 VkClearValue clearValue;
     540           0 :                                 clearValue.depthStencil.stencil = 0;
     541           0 :                                 _clearValues.emplace_back(clearValue);
     542             :                         } else {
     543             :                                 VkClearValue clearValue;
     544           0 :                                 clearValue.depthStencil.stencil = 0;
     545           0 :                                 _clearValues.emplace_back(clearValue);
     546             :                         }
     547           0 :                         break;
     548          42 :                 default:
     549          42 :                         if (desc->loadOp == core::AttachmentLoadOp::Clear) {
     550          42 :                                 auto c = imageAttachment->getClearColor();
     551             :                                 VkClearValue clearValue;
     552          42 :                                 clearValue.color = VkClearColorValue{{c.r, c.g, c.b, c.a}};
     553          42 :                                 _clearValues.emplace_back(clearValue);
     554             :                         } else {
     555             :                                 VkClearValue clearValue;
     556           0 :                                 clearValue.color = VkClearColorValue{{0.0f, 0.0f, 0.0f, 1.0f}};
     557           0 :                                 _clearValues.emplace_back(clearValue);
     558             :                         }
     559          42 :                         break;
     560             :                 }
     561             : 
     562          63 :                 attachmentReferences += desc->subpasses.size();
     563             : 
     564          63 :                 if (data.subpasses.size() >= 3 && desc->subpasses.size() < data.subpasses.size()) {
     565           0 :                         uint32_t initialSubpass = desc->subpasses.front()->subpass->index;
     566           0 :                         uint32_t finalSubpass = desc->subpasses.back()->subpass->index;
     567             : 
     568           0 :                         for (size_t i = initialSubpass + 1; i < finalSubpass; ++ i) {
     569           0 :                                 bool found = false;
     570           0 :                                 for (auto &u : desc->subpasses) {
     571           0 :                                         if (u->subpass->index == i) {
     572           0 :                                                 found = true;
     573             :                                         }
     574             :                                 }
     575           0 :                                 if (!found) {
     576           0 :                                         data.subpasses[i]->preserve.emplace_back(desc->index);
     577             :                                 }
     578             :                         }
     579             :                 }
     580             :         }
     581             : 
     582          21 :         _attachmentReferences.reserve(attachmentReferences);
     583             : 
     584          63 :         for (auto &it : data.subpasses) {
     585          42 :                 VkSubpassDescription subpass{};
     586          42 :                 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
     587             : 
     588          42 :                 if (!it->inputImages.empty()) {
     589          21 :                         auto off = _attachmentReferences.size();
     590             : 
     591          42 :                         for (auto &iit : it->inputImages) {
     592          21 :                                 VkAttachmentReference attachmentRef{};
     593          21 :                                 if (!iit) {
     594           0 :                                         attachmentRef.attachment = VK_ATTACHMENT_UNUSED;
     595           0 :                                         attachmentRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
     596             :                                 } else {
     597          21 :                                         attachmentRef.attachment = iit->pass->index;
     598          21 :                                         attachmentRef.layout = VkImageLayout(iit->layout);
     599             :                                 }
     600          21 :                                 _attachmentReferences.emplace_back(attachmentRef);
     601             :                         }
     602             : 
     603          21 :                         subpass.inputAttachmentCount = it->inputImages.size();
     604          21 :                         subpass.pInputAttachments = _attachmentReferences.data() + off;
     605             :                 }
     606             : 
     607          42 :                 if (!it->outputImages.empty()) {
     608          42 :                         auto off = _attachmentReferences.size();
     609             : 
     610         105 :                         for (auto &iit : it->outputImages) {
     611          63 :                                 VkAttachmentReference attachmentRef{};
     612          63 :                                 if (!iit) {
     613           0 :                                         attachmentRef.attachment = VK_ATTACHMENT_UNUSED;
     614           0 :                                         attachmentRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
     615             :                                 } else {
     616          63 :                                         attachmentRef.attachment = iit->pass->index;
     617          63 :                                         attachmentRef.layout = VkImageLayout(iit->layout);
     618             :                                 }
     619          63 :                                 _attachmentReferences.emplace_back(attachmentRef);
     620             :                         }
     621             : 
     622          42 :                         subpass.colorAttachmentCount = it->outputImages.size();
     623          42 :                         subpass.pColorAttachments = _attachmentReferences.data() + off;
     624             :                 }
     625             : 
     626          42 :                 if (!it->resolveImages.empty()) {
     627           0 :                         auto resolveImages = it->resolveImages;
     628           0 :                         if (resolveImages.size() < it->outputImages.size()) {
     629           0 :                                 resolveImages.resize(it->outputImages.size(), nullptr);
     630             :                         }
     631             : 
     632           0 :                         auto off = _attachmentReferences.size();
     633             : 
     634           0 :                         for (auto &iit : resolveImages) {
     635           0 :                                 VkAttachmentReference attachmentRef{};
     636           0 :                                 if (!iit) {
     637           0 :                                         attachmentRef.attachment = VK_ATTACHMENT_UNUSED;
     638           0 :                                         attachmentRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
     639             :                                 } else {
     640           0 :                                         attachmentRef.attachment = iit->pass->index;
     641           0 :                                         attachmentRef.layout = VkImageLayout(iit->layout);
     642             :                                 }
     643           0 :                                 _attachmentReferences.emplace_back(attachmentRef);
     644             :                         }
     645             : 
     646           0 :                         subpass.pResolveAttachments = _attachmentReferences.data() + off;
     647           0 :                 }
     648             : 
     649          42 :                 if (it->depthStencil) {
     650          21 :                         VkAttachmentReference attachmentRef{};
     651          21 :                         attachmentRef.attachment = it->depthStencil->pass->index;
     652          21 :                         attachmentRef.layout = VkImageLayout(it->depthStencil->layout);
     653          21 :                         _attachmentReferences.emplace_back(attachmentRef);
     654          21 :                         subpass.pDepthStencilAttachment = &_attachmentReferences.back();
     655             :                 }
     656             : 
     657          42 :                 if (!it->preserve.empty()) {
     658           0 :                         subpass.preserveAttachmentCount = it->preserve.size();
     659           0 :                         subpass.pPreserveAttachments = it->preserve.data();
     660             :                 }
     661             : 
     662          42 :                 _subpasses.emplace_back(subpass);
     663             :         }
     664             : 
     665          21 :         _subpassDependencies.reserve(data.dependencies.size());
     666             : 
     667             :         //  TODO: deal with internal dependencies through AttachmentDependencyInfo
     668             : 
     669          63 :         for (auto &it : data.dependencies) {
     670          42 :                 VkSubpassDependency dependency{};
     671          42 :                 dependency.srcSubpass = (it.srcSubpass == core::SubpassDependency::External) ? VK_SUBPASS_EXTERNAL : it.srcSubpass;
     672          42 :                 dependency.dstSubpass = (it.dstSubpass == core::SubpassDependency::External) ? VK_SUBPASS_EXTERNAL : it.dstSubpass;
     673          42 :                 dependency.srcStageMask = VkPipelineStageFlags(it.srcStage);
     674          42 :                 dependency.srcAccessMask = VkAccessFlags(it.srcAccess);
     675          42 :                 dependency.dstStageMask = VkPipelineStageFlags(it.dstStage);
     676          42 :                 dependency.dstAccessMask = VkAccessFlags(it.dstAccess);
     677          42 :                 dependency.dependencyFlags = 0;
     678          42 :                 if (it.byRegion) {
     679          42 :                         dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
     680             :                 }
     681             : 
     682          42 :                 _subpassDependencies.emplace_back(dependency);
     683             :         }
     684             : 
     685          21 :         VkRenderPassCreateInfo renderPassInfo{};
     686          21 :         renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
     687          21 :         renderPassInfo.attachmentCount = _attachmentDescriptions.size();
     688          21 :         renderPassInfo.pAttachments = _attachmentDescriptions.data();
     689          21 :         renderPassInfo.subpassCount = _subpasses.size();
     690          21 :         renderPassInfo.pSubpasses = _subpasses.data();
     691          21 :         renderPassInfo.dependencyCount = _subpassDependencies.size();
     692          21 :         renderPassInfo.pDependencies = _subpassDependencies.data();
     693             : 
     694          21 :         if (dev.getTable()->vkCreateRenderPass(dev.getDevice(), &renderPassInfo, nullptr, &pass.renderPass) != VK_SUCCESS) {
     695           0 :                 return pass.cleanup(dev);
     696             :         }
     697             : 
     698          21 :         if (hasAlternative) {
     699          21 :                 renderPassInfo.attachmentCount = _attachmentDescriptionsAlternative.size();
     700          21 :                 renderPassInfo.pAttachments = _attachmentDescriptionsAlternative.data();
     701             : 
     702          21 :                 if (dev.getTable()->vkCreateRenderPass(dev.getDevice(), &renderPassInfo, nullptr, &pass.renderPassAlternative) != VK_SUCCESS) {
     703           0 :                         return pass.cleanup(dev);
     704             :                 }
     705             :         }
     706             : 
     707          21 :         if (initDescriptors(dev, data, pass)) {
     708          21 :                 auto l = new Data(move(pass));
     709          21 :                 _data = l;
     710          21 :                 return core::RenderPass::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle, void *ptr) {
     711          21 :                         auto d = ((Device *)dev);
     712          21 :                         auto l = (Data *)ptr;
     713          21 :                         l->cleanup(*d);
     714          21 :                         delete l;
     715          42 :                 }, core::ObjectType::RenderPass, ObjectHandle(_data->renderPass), l);
     716             :         }
     717             : 
     718           0 :         return pass.cleanup(dev);
     719          21 : }
     720             : 
     721         168 : bool RenderPass::initComputePass(Device &dev, QueuePassData &data) {
     722         168 :         Data pass;
     723         168 :         if (initDescriptors(dev, data, pass)) {
     724         168 :                 auto l = new Data(move(pass));
     725         168 :                 _data = l;
     726         168 :                 return core::RenderPass::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle, void *ptr) {
     727         168 :                         auto d = ((Device *)dev);
     728         168 :                         auto l = (Data *)ptr;
     729         168 :                         l->cleanup(*d);
     730         168 :                         delete l;
     731         336 :                 }, core::ObjectType::RenderPass, ObjectHandle(_data->renderPass), l);
     732             :         }
     733             : 
     734           0 :         return pass.cleanup(dev);
     735         168 : }
     736             : 
     737         168 : bool RenderPass::initTransferPass(Device &dev, QueuePassData &) {
     738             :         // init nothing - no descriptors or render pass implementation needed
     739         168 :         auto l = new Data();
     740         168 :         _data = l;
     741         168 :         return core::RenderPass::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle, void *ptr) {
     742         168 :                 auto d = ((Device *)dev);
     743         168 :                 auto l = (Data *)ptr;
     744         168 :                 l->cleanup(*d);
     745         168 :                 delete l;
     746         336 :         }, core::ObjectType::RenderPass, ObjectHandle(_data->renderPass), l);
     747             : }
     748             : 
     749           0 : bool RenderPass::initGenericPass(Device &dev, QueuePassData &) {
     750             :         // init nothing - no descriptors or render pass implementation needed
     751           0 :         auto l = new Data();
     752           0 :         _data = l;
     753           0 :         return core::RenderPass::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle, void *ptr) {
     754           0 :                 auto d = ((Device *)dev);
     755           0 :                 auto l = (Data *)ptr;
     756           0 :                 l->cleanup(*d);
     757           0 :                 delete l;
     758           0 :         }, core::ObjectType::RenderPass, ObjectHandle(_data->renderPass), l);
     759             : }
     760             : 
     761         189 : bool RenderPass::initDescriptors(Device &dev, const QueuePassData &data, Data &pass) {
     762           0 :         auto cleanupLayouts = [&] {
     763           0 :                 for (auto &it : pass.layouts) {
     764           0 :                         for (VkDescriptorSetLayout &set : it.layouts) {
     765           0 :                                 dev.getTable()->vkDestroyDescriptorSetLayout(dev.getDevice(), set, nullptr);
     766             :                         }
     767             : 
     768           0 :                         if (it.layout) {
     769           0 :                                 dev.getTable()->vkDestroyPipelineLayout(dev.getDevice(), it.layout, nullptr);
     770             :                         }
     771             : 
     772           0 :                         if (it.descriptorPool) {
     773           0 :                                 dev.getTable()->vkDestroyDescriptorPool(dev.getDevice(), it.descriptorPool, nullptr);
     774             :                         }
     775             :                 }
     776           0 :                 pass.layouts.clear();
     777           0 :         };
     778             : 
     779         441 :         for (auto &it : data.pipelineLayouts) {
     780         252 :                 LayoutData &layoutData = pass.layouts.emplace_back();
     781         252 :                 if (!initDescriptors(dev, *it, pass, layoutData)) {
     782           0 :                         cleanupLayouts();
     783           0 :                         return false;
     784             :                 }
     785             :         }
     786             : 
     787         189 :         return true;
     788             : }
     789             : 
     790         252 : bool RenderPass::initDescriptors(Device &dev, const core::PipelineLayoutData &data, Data &, LayoutData &layoutData) {
     791         252 :         Vector<VkDescriptorPoolSize> sizes;
     792             : 
     793        1701 :         auto incrementSize = [&sizes] (VkDescriptorType type, uint32_t count) {
     794         441 :                 auto lb = std::lower_bound(sizes.begin(), sizes.end(), type, [] (const VkDescriptorPoolSize &l, VkDescriptorType r) {
     795         273 :                         return l.type < r;
     796             :                 });
     797         441 :                 if (lb == sizes.end()) {
     798         294 :                         sizes.emplace_back(VkDescriptorPoolSize({type, count}));
     799         147 :                 } else if (lb->type == type) {
     800          63 :                         lb->descriptorCount += count;
     801             :                 } else {
     802          84 :                         sizes.emplace(lb, VkDescriptorPoolSize({type, count}));
     803             :                 }
     804         441 :         };
     805             : 
     806         252 :         bool updateAfterBind = false;
     807             : 
     808         252 :         uint32_t maxSets = 0;
     809         504 :         for (auto &setData : data.sets) {
     810         252 :                 ++ maxSets;
     811             : 
     812         252 :                 auto descriptorSet = Rc<DescriptorSet>::alloc();
     813             : 
     814         252 :                 bool hasFlags = false;
     815         252 :                 Vector<VkDescriptorBindingFlags> flags;
     816         252 :                 VkDescriptorSetLayout setLayout = VK_NULL_HANDLE;
     817         252 :                 Vector<VkDescriptorSetLayoutBinding> bindings; bindings.reserve(setData->descriptors.size());
     818         252 :                 size_t bindingIdx = 0;
     819         693 :                 for (auto &binding : setData->descriptors) {
     820         441 :                         if (binding->updateAfterBind) {
     821         420 :                                 flags.emplace_back(VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT);
     822         420 :                                 hasFlags = true;
     823         420 :                                 updateAfterBind = true;
     824             :                         } else {
     825          21 :                                 flags.emplace_back(0);
     826             :                         }
     827             : 
     828         441 :                         binding->index = bindingIdx;
     829             : 
     830             :                         VkDescriptorSetLayoutBinding b;
     831         441 :                         b.binding = bindingIdx;
     832         441 :                         b.descriptorCount = binding->count;
     833         441 :                         b.descriptorType = VkDescriptorType(binding->type);
     834         441 :                         b.stageFlags = VkShaderStageFlags(binding->stages);
     835         441 :                         if (binding->type == DescriptorType::Sampler) {
     836             :                                 // do nothing
     837           0 :                                 log::warn("vk::RenderPass", "gl::DescriptorType::Sampler is not supported for descriptors");
     838             :                         } else {
     839         441 :                                 incrementSize(VkDescriptorType(binding->type), binding->count);
     840         441 :                                 b.pImmutableSamplers = nullptr;
     841             :                         }
     842         441 :                         bindings.emplace_back(b);
     843         441 :                         descriptorSet->bindings.emplace_back(DescriptorBinding(VkDescriptorType(binding->type), binding->count));
     844         441 :                         ++ bindingIdx;
     845             :                 }
     846         252 :                 VkDescriptorSetLayoutCreateInfo layoutInfo { };
     847         252 :                 layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
     848         252 :                 layoutInfo.pNext = nullptr;
     849         252 :                 layoutInfo.bindingCount = bindings.size();
     850         252 :                 layoutInfo.pBindings = bindings.data();
     851         252 :                 layoutInfo.flags = 0;
     852             : 
     853         252 :                 if (hasFlags) {
     854         252 :                         layoutInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
     855             : 
     856             :                         VkDescriptorSetLayoutBindingFlagsCreateInfoEXT bindingFlags;
     857         252 :                         bindingFlags.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT;
     858         252 :                         bindingFlags.pNext = nullptr;
     859         252 :                         bindingFlags.bindingCount = flags.size();
     860         252 :                         bindingFlags.pBindingFlags = flags.data();
     861         252 :                         layoutInfo.pNext = &bindingFlags;
     862             : 
     863         252 :                         if (dev.getTable()->vkCreateDescriptorSetLayout(dev.getDevice(), &layoutInfo, nullptr, &setLayout) == VK_SUCCESS) {
     864         252 :                                 layoutData.sets.emplace_back(move(descriptorSet));
     865         252 :                                 layoutData.layouts.emplace_back(setLayout);
     866             :                         } else {
     867           0 :                                 return false;
     868             :                         }
     869             :                 } else {
     870           0 :                         if (dev.getTable()->vkCreateDescriptorSetLayout(dev.getDevice(), &layoutInfo, nullptr, &setLayout) == VK_SUCCESS) {
     871           0 :                                 layoutData.sets.emplace_back(move(descriptorSet));
     872           0 :                                 layoutData.layouts.emplace_back(setLayout);
     873             :                         } else {
     874           0 :                                 return false;
     875             :                         }
     876             :                 }
     877         252 :         }
     878             : 
     879         252 :         VkDescriptorPoolCreateInfo poolInfo{};
     880         252 :         poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
     881         252 :         poolInfo.pNext = nullptr;
     882         252 :         if (updateAfterBind) {
     883         252 :                 poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT;
     884             :         } else {
     885           0 :                 poolInfo.flags = 0;
     886             :         }
     887         252 :         poolInfo.poolSizeCount = sizes.size();
     888         252 :         poolInfo.pPoolSizes = sizes.data();
     889         252 :         poolInfo.maxSets = maxSets;
     890             : 
     891         252 :         if (dev.getTable()->vkCreateDescriptorPool(dev.getDevice(), &poolInfo, nullptr, &layoutData.descriptorPool) != VK_SUCCESS) {
     892           0 :                 return false;
     893             :         }
     894             : 
     895         252 :         VkDescriptorSetAllocateInfo allocInfo{};
     896         252 :         allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
     897         252 :         allocInfo.pNext = nullptr;
     898         252 :         allocInfo.descriptorPool = layoutData.descriptorPool;
     899         252 :         allocInfo.descriptorSetCount = static_cast<uint32_t>(layoutData.layouts.size());
     900         252 :         allocInfo.pSetLayouts = layoutData.layouts.data();
     901             : 
     902         252 :         Vector<VkDescriptorSet> sets; sets.resize(layoutData.layouts.size());
     903             : 
     904         252 :         if (dev.getTable()->vkAllocateDescriptorSets(dev.getDevice(), &allocInfo, sets.data()) != VK_SUCCESS) {
     905           0 :                 layoutData.sets.clear();
     906           0 :                 return false;
     907             :         }
     908             : 
     909         504 :         for (size_t i = 0; i < sets.size(); ++ i) {
     910         252 :                 layoutData.sets[i]->set = sets[i];
     911             :         }
     912             : 
     913         252 :         Vector<VkPushConstantRange> ranges;
     914             : 
     915        1281 :         auto addRange = [&] (VkShaderStageFlags flags, uint32_t offset, uint32_t size) {
     916        1428 :                 for (auto &it : ranges) {
     917        1197 :                         if (it.stageFlags == flags) {
     918        1050 :                                 if (offset < it.offset) {
     919           0 :                                         it.size += (it.offset - offset);
     920           0 :                                         it.offset = offset;
     921             :                                 }
     922        1050 :                                 if (size > it.size) {
     923         147 :                                         it.size = size;
     924             :                                 }
     925        1050 :                                 return;
     926             :                         }
     927             :                 }
     928             : 
     929         231 :                 ranges.emplace_back(VkPushConstantRange{flags, offset, size});
     930         252 :         };
     931             : 
     932         336 :         for (auto &pipeline : data.graphicPipelines) {
     933         252 :                 for (auto &shader : pipeline->shaders) {
     934         378 :                         for (auto &constantBlock : shader.data->constants) {
     935         210 :                                 addRange(VkShaderStageFlags(shader.data->stage), constantBlock.offset, constantBlock.size);
     936             :                         }
     937             :                 }
     938             :         }
     939             : 
     940        1764 :         for (auto &pipeline : data.computePipelines) {
     941        2583 :                 for (auto &constantBlock : pipeline->shader.data->constants) {
     942        1071 :                         addRange(VkShaderStageFlags(pipeline->shader.data->stage), constantBlock.offset, constantBlock.size);
     943             :                 }
     944             :         }
     945             : 
     946         252 :         auto textureSetLayout = dev.getTextureSetLayout();
     947         252 :         Vector<VkDescriptorSetLayout> layouts(layoutData.layouts);
     948         252 :         if (data.usesTextureSet) {
     949          21 :                 layouts.emplace_back(textureSetLayout->getLayout());
     950             :         }
     951             : 
     952             :         VkPipelineLayoutCreateInfo pipelineLayoutInfo;
     953         252 :         pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
     954         252 :         pipelineLayoutInfo.pNext = nullptr;
     955         252 :         pipelineLayoutInfo.flags = 0;
     956         252 :         pipelineLayoutInfo.setLayoutCount = layouts.size();
     957         252 :         pipelineLayoutInfo.pSetLayouts = layouts.data();
     958         252 :         pipelineLayoutInfo.pushConstantRangeCount = ranges.size();
     959         252 :         pipelineLayoutInfo.pPushConstantRanges = ranges.data();
     960             : 
     961         252 :         if (dev.getTable()->vkCreatePipelineLayout(dev.getDevice(), &pipelineLayoutInfo, nullptr, &layoutData.layout) == VK_SUCCESS) {
     962         252 :                 return true;
     963             :         }
     964             : 
     965           0 :         return false;
     966         252 : }
     967             : 
     968             : }

Generated by: LCOV version 1.14