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

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2021 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 "XLVkObject.h"
      25             : 
      26             : namespace STAPPLER_VERSIONIZED stappler::xenolith::vk {
      27             : 
      28        2574 : bool DeviceMemory::init(Allocator *a, DeviceMemoryInfo info, VkDeviceMemory memory, AllocationUsage usage) {
      29        2574 :         _allocator = a;
      30        2574 :         _memory = memory;
      31        2574 :         _info = info;
      32        2574 :         _usage = usage;
      33             : 
      34        2574 :         if (memory) {
      35        2574 :                 return core::Object::init(*_allocator->getDevice(), [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *) {
      36        2574 :                         auto d = ((Device *)dev);
      37        2574 :                         d->makeApiCall([&] (const DeviceTable &table, VkDevice device) {
      38        2574 :                                 table.vkFreeMemory(device, (VkDeviceMemory)ptr.get(), nullptr);
      39        2574 :                         });
      40        7722 :                 }, core::ObjectType::DeviceMemory, ObjectHandle(_memory));
      41             :         } else {
      42           0 :                 return core::Object::init(*_allocator->getDevice(), [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *) { },
      43           0 :                         core::ObjectType::DeviceMemory, ObjectHandle(_memory));
      44             :         }
      45             : }
      46             : 
      47      695827 : bool DeviceMemory::init(DeviceMemoryPool *p, Allocator::MemBlock &&block, AllocationUsage usage) {
      48      695827 :         _allocator = p->getAllocator();
      49      695827 :         _pool = p;
      50      695827 :         _info = DeviceMemoryInfo{block.size, 1, block.type, false};
      51      695827 :         _memBlock = move(block);
      52      695827 :         _memory = _memBlock.mem;
      53      695827 :         _usage = usage;
      54             : 
      55      695827 :         if (_memBlock.ptr) {
      56             :                 // persistent mapping
      57      134422 :                 _mappedOffset = 0;
      58      134422 :                 _mappedSize = _info.size;
      59             :         }
      60             : 
      61     1391654 :         return core::Object::init(*_allocator->getDevice(), [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *thiz) {
      62      695827 :                 auto mem = static_cast<DeviceMemory *>(thiz);
      63      695827 :                 mem->_pool->free(move(mem->_memBlock));
      64     1391654 :         }, core::ObjectType::DeviceMemory, ObjectHandle::zero(), this);
      65             : }
      66             : 
      67       44850 : bool DeviceMemory::isPersistentMapped() const {
      68       44850 :         return _memBlock.ptr != nullptr;
      69             : }
      70             : 
      71       44850 : uint8_t *DeviceMemory::getPersistentMappedRegion() const {
      72       44850 :         return static_cast<uint8_t *>(_memBlock.ptr) + _memBlock.offset;
      73             : }
      74             : 
      75      215460 : bool DeviceMemory::map(const Callback<void(uint8_t *, VkDeviceSize)> &cb, VkDeviceSize offset, VkDeviceSize size, DeviceMemoryAccess access) {
      76      215460 :         auto t = _allocator->getType(_info.memoryType);
      77      215859 :         if (!t->isHostVisible()) {
      78           0 :                 return false;
      79             :         }
      80             : 
      81      215502 :         bool hostCoherent = t->isHostCoherent();
      82      215496 :         auto range = calculateMappedMemoryRange(offset, size);
      83             : 
      84      215205 :         std::unique_lock<Mutex> lock(_memBlock.mappingProtection ? *_memBlock.mappingProtection : _mappingProtectionMutex);
      85             : 
      86      218714 :         uint8_t *mapped = nullptr;
      87      218714 :         if (_memBlock.ptr) {
      88      218714 :                 mapped = static_cast<uint8_t *>(_memBlock.ptr) + _memBlock.offset + offset;
      89             :         } else {
      90           0 :                 if (_allocator->getDevice()->getTable()->vkMapMemory(_allocator->getDevice()->getDevice(),
      91           0 :                                 _memory, range.offset, range.size, 0, (void **)&mapped) != VK_SUCCESS) {
      92           0 :                         return false;
      93             :                 }
      94           0 :                 mapped += (_memBlock.offset + offset - range.offset);
      95             : 
      96           0 :                 _mappedOffset = range.offset;
      97           0 :                 _mappedSize = range.size;
      98             :         }
      99             : 
     100      218714 :         if (!hostCoherent && (access & DeviceMemoryAccess::Invalidate) != DeviceMemoryAccess::None) {
     101           0 :                 _allocator->getDevice()->getTable()->vkInvalidateMappedMemoryRanges(_allocator->getDevice()->getDevice(), 1, &range);
     102             :         }
     103             : 
     104      218714 :         cb(static_cast<uint8_t *>(mapped), std::min(_info.size - offset, size));
     105             : 
     106      218714 :         if (!hostCoherent && (access & DeviceMemoryAccess::Flush) != DeviceMemoryAccess::None) {
     107           0 :                 _allocator->getDevice()->getTable()->vkFlushMappedMemoryRanges(_allocator->getDevice()->getDevice(), 1, &range);
     108             :         }
     109             : 
     110      218714 :         if (!_memBlock.ptr) {
     111           0 :                 _mappedOffset = 0;
     112           0 :                 _mappedSize = 0;
     113             : 
     114           0 :                 _allocator->getDevice()->getTable()->vkUnmapMemory(_allocator->getDevice()->getDevice(), _memory);
     115             :         }
     116      218714 :         return true;
     117      218714 : }
     118             : 
     119       44850 : void DeviceMemory::invalidateMappedRegion(VkDeviceSize offset, VkDeviceSize size) {
     120       44850 :         auto t = _allocator->getType(_info.memoryType);
     121       44850 :         if (!t->isHostVisible() || t->isHostCoherent()) {
     122       44850 :                 return;
     123             :         }
     124             : 
     125           0 :         size = std::min(_info.size, size);
     126           0 :         offset += _memBlock.offset;
     127             : 
     128           0 :         offset = std::max(_mappedOffset, offset);
     129           0 :         size = std::min(_mappedSize, size);
     130             : 
     131           0 :         auto range = calculateMappedMemoryRange(offset, size);
     132             : 
     133           0 :         _allocator->getDevice()->getTable()->vkInvalidateMappedMemoryRanges(_allocator->getDevice()->getDevice(), 1, &range);
     134             : }
     135             : 
     136       44814 : void DeviceMemory::flushMappedRegion(VkDeviceSize offset, VkDeviceSize size) {
     137       44814 :         auto t = _allocator->getType(_info.memoryType);
     138       44815 :         if (!t->isHostVisible() || t->isHostCoherent()) {
     139       44807 :                 return;
     140             :         }
     141             : 
     142           4 :         size = std::min(_info.size, size);
     143           0 :         offset += _memBlock.offset;
     144             : 
     145           0 :         offset = std::max(_mappedOffset, offset);
     146           0 :         size = std::min(_mappedSize, size);
     147             : 
     148           0 :         auto range = calculateMappedMemoryRange(offset, size);
     149             : 
     150           0 :         _allocator->getDevice()->getTable()->vkFlushMappedMemoryRanges(_allocator->getDevice()->getDevice(), 1, &range);
     151             : }
     152             : 
     153      215217 : VkMappedMemoryRange DeviceMemory::calculateMappedMemoryRange(VkDeviceSize offset, VkDeviceSize size) const {
     154      215217 :         auto t = _allocator->getType(_info.memoryType);
     155             : 
     156      215547 :         size = std::min(_info.size, size);
     157      215362 :         offset += _memBlock.offset;
     158             : 
     159      215362 :         VkDeviceSize atomSize = t->isHostCoherent() ? 1 : _allocator->getNonCoherentAtomSize();
     160             : 
     161             :         VkMappedMemoryRange range;
     162      215393 :         range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
     163      215393 :         range.pNext = nullptr;
     164      215393 :         range.memory = _memory;
     165      215393 :         range.offset = math::align<VkDeviceSize>(offset - atomSize + 1, atomSize);
     166      215218 :         range.size = std::min(_info.size - range.offset, math::align<VkDeviceSize>(size + (offset - range.offset), atomSize));
     167      215432 :         return range;
     168             : }
     169             : 
     170         105 : bool Image::init(Device &dev, VkImage image, const ImageInfoData &info, uint32_t idx) {
     171         105 :         _info = info;
     172         105 :         _image = image;
     173             : 
     174         105 :         auto ret = core::ImageObject::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *thiz) {
     175             :                 // do nothing
     176         105 :                 static_cast<Image *>(thiz)->_memory = nullptr;
     177         210 :         }, core::ObjectType::Image, ObjectHandle(_image), this);
     178         105 :         if (ret) {
     179         105 :                 _index = idx;
     180             :         }
     181         105 :         return ret;
     182             : }
     183             : 
     184         294 : bool Image::init(Device &dev, VkImage image, const ImageInfoData &info, Rc<DeviceMemory> &&mem, Rc<core::DataAtlas> &&atlas) {
     185         294 :         _info = info;
     186         294 :         _image = image;
     187         294 :         _atlas = atlas;
     188         294 :         _memory = move(mem);
     189             : 
     190         294 :         return core::ImageObject::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *thiz) {
     191         294 :                 auto d = ((Device *)dev);
     192         294 :                 d->getTable()->vkDestroyImage(d->getDevice(), (VkImage)ptr.get(), nullptr);
     193         294 :                 static_cast<Image *>(thiz)->_memory = nullptr;
     194         882 :         }, core::ObjectType::Image, ObjectHandle(_image), this);
     195             : }
     196             : 
     197        1066 : bool Image::init(Device &dev, uint64_t idx, VkImage image, const ImageInfoData &info, Rc<DeviceMemory> &&mem, Rc<core::DataAtlas> &&atlas) {
     198        1066 :         _info = info;
     199        1066 :         _image = image;
     200        1066 :         _atlas = atlas;
     201        1066 :         _memory = move(mem);
     202             : 
     203        1066 :         return core::ImageObject::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *thiz) {
     204        1066 :                 auto d = ((Device *)dev);
     205        1066 :                 d->getTable()->vkDestroyImage(d->getDevice(), (VkImage)ptr.get(), nullptr);
     206        1066 :                 static_cast<Image *>(thiz)->_memory = nullptr;
     207        3198 :         }, core::ObjectType::Image, ObjectHandle(_image), this, idx);
     208             : }
     209             : 
     210       10688 : void Image::setPendingBarrier(const ImageMemoryBarrier &barrier) {
     211       10688 :         _barrier = barrier;
     212       10688 :         _barrier->image = this;
     213       10688 : }
     214             : 
     215       16802 : const ImageMemoryBarrier *Image::getPendingBarrier() const {
     216       16802 :         if (_barrier) {
     217       10667 :                 return &_barrier.value();
     218             :         } else {
     219        6135 :                 return nullptr;
     220             :         }
     221             : }
     222             : 
     223        1150 : void Image::dropPendingBarrier() {
     224        1150 :         _barrier.reset();
     225        1150 : }
     226             : 
     227       28880 : VkImageAspectFlags Image::getAspectMask() const {
     228       28880 :         switch (core::getImagePixelFormat(_info.format)) {
     229           0 :         case core::PixelFormat::D: return VK_IMAGE_ASPECT_DEPTH_BIT; break;
     230           0 :         case core::PixelFormat::DS: return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; break;
     231           0 :         case core::PixelFormat::S: return VK_IMAGE_ASPECT_STENCIL_BIT; break;
     232       28880 :         default: return VK_IMAGE_ASPECT_COLOR_BIT; break;
     233             :         }
     234             :         return VK_IMAGE_ASPECT_NONE_KHR;
     235             : }
     236             : 
     237        1297 : bool Image::bindMemory(Rc<DeviceMemory> &&mem, VkDeviceSize offset) {
     238        1297 :         auto dev = (Device *)_object.device;
     239        1297 :         if (dev->getTable()->vkBindImageMemory(dev->getDevice(), _image, mem->getMemory(), offset + mem->getBlockOffset()) == VK_SUCCESS) {
     240        1297 :                 _memory = move(mem);
     241        1297 :                 return true;
     242             :         }
     243           0 :         return false;
     244             : }
     245             : 
     246      699625 : bool Buffer::init(Device &dev, VkBuffer buffer, const BufferInfo &info, Rc<DeviceMemory> &&mem, VkDeviceSize memoryOffset) {
     247      699625 :         _info = info;
     248      699619 :         _buffer = buffer;
     249      699619 :         _memory = move(mem);
     250      699615 :         _memoryOffset = memoryOffset;
     251             : 
     252      699613 :         return core::BufferObject::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *thiz) {
     253      699656 :                 auto d = ((Device *)dev);
     254      699656 :                 d->getTable()->vkDestroyBuffer(d->getDevice(), (VkBuffer)ptr.get(), nullptr);
     255      699656 :                 static_cast<Buffer *>(thiz)->_memory = nullptr;
     256     2098927 :         }, core::ObjectType::Buffer, ObjectHandle(_buffer), this);
     257             : }
     258             : 
     259       13142 : void Buffer::setPendingBarrier(const BufferMemoryBarrier &barrier) {
     260       13142 :         _barrier = barrier;
     261       13142 :         _barrier->buffer = this;
     262       13142 : }
     263             : 
     264      230960 : const BufferMemoryBarrier *Buffer::getPendingBarrier() const {
     265      230960 :         if (_barrier) {
     266       12659 :                 return &_barrier.value();
     267             :         } else {
     268      218303 :                 return nullptr;
     269             :         }
     270             : }
     271             : 
     272        3389 : void Buffer::dropPendingBarrier() {
     273        3389 :         _barrier.reset();
     274        3389 : }
     275             : 
     276      699257 : bool Buffer::bindMemory(Rc<DeviceMemory> &&mem, VkDeviceSize offset) {
     277      699257 :         auto dev = (Device *)_object.device;
     278      699257 :         if (dev->getTable()->vkBindBufferMemory(dev->getDevice(), _buffer, mem->getMemory(), offset + mem->getBlockOffset()) == VK_SUCCESS) {
     279      699257 :                 _memoryOffset = offset;
     280      699257 :                 _memory = move(mem);
     281      699257 :                 return true;
     282             :         }
     283           0 :         return false;
     284             : }
     285             : 
     286       86373 : bool Buffer::map(const Callback<void(uint8_t *, VkDeviceSize)> &cb, VkDeviceSize offset, VkDeviceSize size, DeviceMemoryAccess access) {
     287       86373 :         size = std::min(_info.size - offset, size);
     288       86373 :         offset += _memoryOffset;
     289       86373 :         return _memory->map(cb, offset, size, access);
     290             : }
     291             : 
     292       44850 : uint8_t *Buffer::getPersistentMappedRegion(bool invalidate) {
     293       44850 :         if (_memory->isPersistentMapped()) {
     294       44850 :                 if (invalidate) {
     295       44850 :                         invalidateMappedRegion();
     296             :                 }
     297       44850 :                 return _memory->getPersistentMappedRegion() + _memoryOffset;
     298             :         }
     299           0 :         return nullptr;
     300             : }
     301             : 
     302       44850 : void Buffer::invalidateMappedRegion(VkDeviceSize offset, VkDeviceSize size) {
     303       44850 :         offset += _memoryOffset;
     304       44850 :         size = std::min(size, _info.size);
     305             : 
     306       44850 :         _memory->invalidateMappedRegion(offset, size);
     307       44850 : }
     308             : 
     309       44812 : void Buffer::flushMappedRegion(VkDeviceSize offset, VkDeviceSize size) {
     310       44812 :         offset += _memoryOffset;
     311       44812 :         size = std::min(size, _info.size);
     312             : 
     313       44814 :         _memory->flushMappedRegion(offset, size);
     314       44805 : }
     315             : 
     316      129990 : bool Buffer::setData(BytesView data, VkDeviceSize offset) {
     317      129990 :         auto size = std::min(size_t(_info.size - offset), data.size());
     318             : 
     319      391443 :         return _memory->map([&] (uint8_t *ptr, VkDeviceSize size) {
     320      132341 :                 ::memcpy(ptr, data.data(), size);
     321      394058 :         }, _memoryOffset + offset, size, DeviceMemoryAccess::Flush);
     322             : }
     323             : 
     324           0 : Bytes Buffer::getData(VkDeviceSize size, VkDeviceSize offset) {
     325           0 :         size = std::min(_info.size - offset, size);
     326             : 
     327           0 :         Bytes ret;
     328             : 
     329           0 :         _memory->map([&] (uint8_t *ptr, VkDeviceSize size) {
     330           0 :                 ret.resize(size);
     331           0 :                 ::memcpy(ret.data(), ptr, size);
     332           0 :         }, _memoryOffset + offset, size, DeviceMemoryAccess::Invalidate);
     333             : 
     334           0 :         return ret;
     335           0 : }
     336             : 
     337      128931 : uint64_t Buffer::reserveBlock(uint64_t blockSize, uint64_t alignment) {
     338      128931 :         auto alignedSize = math::align(uint64_t(blockSize), alignment);
     339      129019 :         auto ret = _targetOffset.fetch_add(alignedSize);
     340      129019 :         if (ret + blockSize > _info.size) {
     341           0 :                 return maxOf<uint64_t>();
     342             :         }
     343      129019 :         return ret;
     344             : }
     345             : 
     346           0 : bool ImageView::init(Device &dev, VkImage image, VkFormat format) {
     347           0 :         VkImageViewCreateInfo createInfo{}; sanitizeVkStruct(createInfo);
     348           0 :         createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
     349           0 :         createInfo.image = image;
     350           0 :         createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
     351           0 :         createInfo.format = format;
     352           0 :         createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
     353           0 :         createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
     354           0 :         createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
     355           0 :         createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
     356           0 :         createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
     357           0 :         createInfo.subresourceRange.baseMipLevel = 0;
     358           0 :         createInfo.subresourceRange.levelCount = 1;
     359           0 :         createInfo.subresourceRange.baseArrayLayer = 0;
     360           0 :         createInfo.subresourceRange.layerCount = 1;
     361             : 
     362           0 :         if (dev.getTable()->vkCreateImageView(dev.getDevice(), &createInfo, nullptr, &_imageView) == VK_SUCCESS) {
     363           0 :                 return core::ImageView::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *thiz) {
     364           0 :                         auto d = ((Device *)dev);
     365           0 :                         d->getTable()->vkDestroyImageView(d->getDevice(), (VkImageView)ptr.get(), nullptr);
     366             : 
     367           0 :                         auto obj = static_cast<ImageView *>(thiz);
     368           0 :                         if (obj->_releaseCallback) {
     369           0 :                                 obj->_releaseCallback();
     370           0 :                                 obj->_releaseCallback = nullptr;
     371             :                         }
     372           0 :                 }, core::ObjectType::ImageView, ObjectHandle(_imageView), this);
     373             :         }
     374           0 :         return false;
     375             : }
     376             : 
     377        1549 : bool ImageView::init(Device &dev, Image *image, const ImageViewInfo &info) {
     378        1549 :         VkImageViewCreateInfo createInfo{}; sanitizeVkStruct(createInfo);
     379        1549 :         createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
     380        1549 :         createInfo.image = image->getImage();
     381             : 
     382        1549 :         switch (info.type) {
     383           0 :         case core::ImageViewType::ImageView1D:
     384           0 :                 if (image->getInfo().imageType != core::ImageType::Image1D) {
     385           0 :                         log::error("Vk-ImageView", "Incompatible ImageType '", core::getImageTypeName(image->getInfo().imageType),
     386           0 :                                         "' and ImageViewType '", core::getImageViewTypeName(info.type), "'");
     387           0 :                         return false;
     388             :                 }
     389           0 :                 createInfo.viewType = VK_IMAGE_VIEW_TYPE_1D;
     390           0 :                 break;
     391           0 :         case core::ImageViewType::ImageView1DArray:
     392           0 :                 if (image->getInfo().imageType != core::ImageType::Image1D) {
     393           0 :                         log::error("Vk-ImageView", "Incompatible ImageType '", core::getImageTypeName(image->getInfo().imageType),
     394           0 :                                         "' and ImageViewType '", core::getImageViewTypeName(info.type), "'");
     395           0 :                         return false;
     396             :                 }
     397           0 :                 createInfo.viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
     398           0 :                 break;
     399        1549 :         case core::ImageViewType::ImageView2D:
     400        1549 :                 if (image->getInfo().imageType != core::ImageType::Image2D && image->getInfo().imageType != core::ImageType::Image3D) {
     401           0 :                         log::error("Vk-ImageView", "Incompatible ImageType '", core::getImageTypeName(image->getInfo().imageType),
     402           0 :                                         "' and ImageViewType '", core::getImageViewTypeName(info.type), "'");
     403           0 :                         return false;
     404             :                 }
     405        1549 :                 createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
     406        1549 :                 break;
     407           0 :         case core::ImageViewType::ImageView2DArray:
     408           0 :                 if (image->getInfo().imageType != core::ImageType::Image2D && image->getInfo().imageType != core::ImageType::Image3D) {
     409           0 :                         log::error("Vk-ImageView", "Incompatible ImageType '", core::getImageTypeName(image->getInfo().imageType),
     410           0 :                                         "' and ImageViewType '", core::getImageViewTypeName(info.type), "'");
     411           0 :                         return false;
     412             :                 }
     413           0 :                 createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
     414           0 :                 break;
     415           0 :         case core::ImageViewType::ImageView3D:
     416           0 :                 if (image->getInfo().imageType != core::ImageType::Image3D) {
     417           0 :                         log::error("Vk-ImageView", "Incompatible ImageType '", core::getImageTypeName(image->getInfo().imageType),
     418           0 :                                         "' and ImageViewType '", core::getImageViewTypeName(info.type), "'");
     419           0 :                         return false;
     420             :                 }
     421           0 :                 createInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
     422           0 :                 break;
     423           0 :         case core::ImageViewType::ImageViewCube:
     424           0 :                 if (image->getInfo().imageType != core::ImageType::Image2D) {
     425           0 :                         log::error("Vk-ImageView", "Incompatible ImageType '", core::getImageTypeName(image->getInfo().imageType),
     426           0 :                                         "' and ImageViewType '", core::getImageViewTypeName(info.type), "'");
     427           0 :                         return false;
     428             :                 }
     429           0 :                 createInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
     430           0 :                 break;
     431           0 :         case core::ImageViewType::ImageViewCubeArray:
     432           0 :                 if (image->getInfo().imageType != core::ImageType::Image2D) {
     433           0 :                         log::error("Vk-ImageView", "Incompatible ImageType '", core::getImageTypeName(image->getInfo().imageType),
     434           0 :                                         "' and ImageViewType '", core::getImageViewTypeName(info.type), "'");
     435           0 :                         return false;
     436             :                 }
     437           0 :                 createInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
     438           0 :                 break;
     439             :         }
     440             : 
     441        1549 :         auto format = info.format;
     442        1549 :         if (format == core::ImageFormat::Undefined) {
     443          84 :                 format = image->getInfo().format;
     444             :         }
     445        1549 :         createInfo.format = VkFormat(format);
     446             : 
     447        1549 :         createInfo.components.r = VkComponentSwizzle(info.r);
     448        1549 :         createInfo.components.g = VkComponentSwizzle(info.g);
     449        1549 :         createInfo.components.b = VkComponentSwizzle(info.b);
     450        1549 :         createInfo.components.a = VkComponentSwizzle(info.a);
     451             : 
     452        1549 :         switch (format) {
     453          21 :         case core::ImageFormat::D16_UNORM:
     454             :         case core::ImageFormat::X8_D24_UNORM_PACK32:
     455             :         case core::ImageFormat::D32_SFLOAT:
     456          21 :                 createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
     457          21 :                 break;
     458           0 :         case core::ImageFormat::S8_UINT:
     459           0 :                 createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
     460           0 :                 break;
     461           0 :         case core::ImageFormat::D16_UNORM_S8_UINT:
     462             :         case core::ImageFormat::D24_UNORM_S8_UINT:
     463             :         case core::ImageFormat::D32_SFLOAT_S8_UINT:
     464           0 :                 createInfo.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
     465           0 :                 break;
     466        1528 :         default:
     467        1528 :                 createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
     468        1528 :                 break;
     469             :         }
     470             : 
     471        1549 :         createInfo.subresourceRange.baseMipLevel = 0;
     472        1549 :         createInfo.subresourceRange.levelCount = image->getInfo().mipLevels.get();
     473        1549 :         createInfo.subresourceRange.baseArrayLayer = info.baseArrayLayer.get();
     474        1549 :         if (info.layerCount.get() == maxOf<uint32_t>()) {
     475          84 :                 createInfo.subresourceRange.layerCount = image->getInfo().arrayLayers.get() - info.baseArrayLayer.get();
     476             :         } else {
     477        1465 :                 createInfo.subresourceRange.layerCount = info.layerCount.get();
     478             :         }
     479             : 
     480        1549 :         if (dev.getTable()->vkCreateImageView(dev.getDevice(), &createInfo, nullptr, &_imageView) == VK_SUCCESS) {
     481        1549 :                 _info = info;
     482        1549 :                 _info.format = format;
     483        1549 :                 _info.baseArrayLayer = core::BaseArrayLayer(createInfo.subresourceRange.baseArrayLayer);
     484        1549 :                 _info.layerCount = core::ArrayLayers(createInfo.subresourceRange.layerCount);
     485             : 
     486        1549 :                 _image = image;
     487        1549 :                 return core::ImageView::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *thiz) {
     488        1549 :                         auto d = ((Device *)dev);
     489        1549 :                         d->getTable()->vkDestroyImageView(d->getDevice(), (VkImageView)ptr.get(), nullptr);
     490             : 
     491        1549 :                         auto obj = static_cast<ImageView *>(thiz);
     492        1549 :                         if (obj->_releaseCallback) {
     493           0 :                                 obj->_releaseCallback();
     494           0 :                                 obj->_releaseCallback = nullptr;
     495             :                         }
     496        3098 :                 }, core::ObjectType::ImageView, ObjectHandle(_imageView), this);
     497             :         }
     498           0 :         return false;
     499             : }
     500             : 
     501          78 : bool Sampler::init(Device &dev, const SamplerInfo &info) {
     502          78 :         VkSamplerCreateInfo createInfo; sanitizeVkStruct(createInfo);
     503          73 :         createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
     504          73 :         createInfo.pNext = nullptr;
     505          73 :         createInfo.flags = 0;
     506          73 :         createInfo.magFilter = VkFilter(info.magFilter);
     507          73 :         createInfo.minFilter = VkFilter(info.minFilter);
     508          73 :         createInfo.mipmapMode = VkSamplerMipmapMode(info.mipmapMode);
     509          73 :         createInfo.addressModeU = VkSamplerAddressMode(info.addressModeU);
     510          73 :         createInfo.addressModeV = VkSamplerAddressMode(info.addressModeV);
     511          73 :         createInfo.addressModeW = VkSamplerAddressMode(info.addressModeW);
     512          73 :         createInfo.mipLodBias = info.mipLodBias;
     513          73 :         createInfo.anisotropyEnable = info.anisotropyEnable;
     514          73 :         createInfo.maxAnisotropy = info.maxAnisotropy;
     515          73 :         createInfo.compareEnable = info.compareEnable;
     516          73 :         createInfo.compareOp = VkCompareOp(info.compareOp);
     517          73 :         createInfo.minLod = info.minLod;
     518          73 :         createInfo.maxLod = info.maxLod;
     519          73 :         createInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
     520          73 :         createInfo.unnormalizedCoordinates = false;
     521             : 
     522          73 :         if (dev.getTable()->vkCreateSampler(dev.getDevice(), &createInfo, nullptr, &_sampler) == VK_SUCCESS) {
     523          84 :                 _info = info;
     524          84 :                 return core::Object::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *) {
     525          84 :                         auto d = ((Device *)dev);
     526          84 :                         d->getTable()->vkDestroySampler(d->getDevice(), (VkSampler)ptr.get(), nullptr);
     527         168 :                 }, core::ObjectType::Sampler, ObjectHandle(_sampler));
     528             :         }
     529           0 :         return false;
     530             : }
     531             : 
     532             : }

Generated by: LCOV version 1.14