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