OSDN Git Service

CubeMap fixes
[android-x86/external-swiftshader.git] / src / Vulkan / VkImage.cpp
1 // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "VkDeviceMemory.hpp"
16 #include "VkBuffer.hpp"
17 #include "VkDevice.hpp"
18 #include "VkImage.hpp"
19 #include "Device/Blitter.hpp"
20 #include <cstring>
21
22 namespace
23 {
24         VkImageAspectFlags GetAspects(vk::Format format)
25         {
26                 // TODO: probably just flatten this out to a full format list, and alter
27                 // isDepth / isStencil etc to check for their aspect
28
29                 VkImageAspectFlags aspects = 0;
30                 if (format.isDepth()) aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
31                 if (format.isStencil()) aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
32
33                 // TODO: YCbCr planar formats have different aspects
34
35                 // Anything else is "color".
36                 if (!aspects) aspects |= VK_IMAGE_ASPECT_COLOR_BIT;
37                 return aspects;
38         }
39 }
40
41 namespace vk
42 {
43
44 Image::Image(const Image::CreateInfo* pCreateInfo, void* mem) :
45         device(Cast(pCreateInfo->device)),
46         flags(pCreateInfo->pCreateInfo->flags),
47         imageType(pCreateInfo->pCreateInfo->imageType),
48         format(pCreateInfo->pCreateInfo->format),
49         extent(pCreateInfo->pCreateInfo->extent),
50         mipLevels(pCreateInfo->pCreateInfo->mipLevels),
51         arrayLayers(pCreateInfo->pCreateInfo->arrayLayers),
52         samples(pCreateInfo->pCreateInfo->samples),
53         tiling(pCreateInfo->pCreateInfo->tiling)
54 {
55         if (samples != VK_SAMPLE_COUNT_1_BIT)
56         {
57                 UNIMPLEMENTED("Multisample images not yet supported");
58         }
59 }
60
61 void Image::destroy(const VkAllocationCallbacks* pAllocator)
62 {
63 }
64
65 size_t Image::ComputeRequiredAllocationSize(const Image::CreateInfo* pCreateInfo)
66 {
67         return 0;
68 }
69
70 const VkMemoryRequirements Image::getMemoryRequirements() const
71 {
72         VkMemoryRequirements memoryRequirements;
73         memoryRequirements.alignment = vk::REQUIRED_MEMORY_ALIGNMENT;
74         memoryRequirements.memoryTypeBits = vk::MEMORY_TYPE_GENERIC_BIT;
75         memoryRequirements.size = getStorageSize(GetAspects(format));
76         return memoryRequirements;
77 }
78
79 void Image::bind(VkDeviceMemory pDeviceMemory, VkDeviceSize pMemoryOffset)
80 {
81         deviceMemory = Cast(pDeviceMemory);
82         memoryOffset = pMemoryOffset;
83 }
84
85 void Image::getSubresourceLayout(const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) const
86 {
87         // By spec, aspectMask has a single bit set.
88         if (!((pSubresource->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
89                   (pSubresource->aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
90                   (pSubresource->aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)))
91         {
92                 UNIMPLEMENTED();
93         }
94         auto aspect = static_cast<VkImageAspectFlagBits>(pSubresource->aspectMask);
95         pLayout->offset = getMemoryOffset(aspect, pSubresource->mipLevel, pSubresource->arrayLayer);
96         pLayout->size = getMipLevelSize(aspect, pSubresource->mipLevel);
97         pLayout->rowPitch = rowPitchBytes(aspect, pSubresource->mipLevel);
98         pLayout->depthPitch = slicePitchBytes(aspect, pSubresource->mipLevel);
99         pLayout->arrayPitch = getLayerSize(aspect);
100 }
101
102 void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion)
103 {
104         // Image copy does not perform any conversion, it simply copies memory from
105         // an image to another image that has the same number of bytes per pixel.
106         Image* dst = Cast(dstImage);
107
108         if(!((pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
109                  (pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
110                  (pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) ||
111                  (pRegion.srcSubresource.baseArrayLayer != 0) ||
112                  (pRegion.srcSubresource.layerCount != 1))
113         {
114                 UNIMPLEMENTED();
115         }
116
117         if(!((pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
118                  (pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
119                  (pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) ||
120                  (pRegion.dstSubresource.baseArrayLayer != 0) ||
121                  (pRegion.dstSubresource.layerCount != 1))
122         {
123                 UNIMPLEMENTED();
124         }
125
126         VkImageAspectFlagBits srcAspect = static_cast<VkImageAspectFlagBits>(pRegion.srcSubresource.aspectMask);
127         VkImageAspectFlagBits dstAspect = static_cast<VkImageAspectFlagBits>(pRegion.dstSubresource.aspectMask);
128
129         int srcBytesPerTexel = bytesPerTexel(srcAspect);
130         ASSERT(srcBytesPerTexel == dst->bytesPerTexel(dstAspect));
131
132         const uint8_t* srcMem = static_cast<const uint8_t*>(getTexelPointer(pRegion.srcOffset, pRegion.srcSubresource));
133         uint8_t* dstMem = static_cast<uint8_t*>(dst->getTexelPointer(pRegion.dstOffset, pRegion.dstSubresource));
134
135         int srcRowPitchBytes = rowPitchBytes(srcAspect, pRegion.srcSubresource.mipLevel);
136         int srcSlicePitchBytes = slicePitchBytes(srcAspect, pRegion.srcSubresource.mipLevel);
137         int dstRowPitchBytes = dst->rowPitchBytes(dstAspect, pRegion.dstSubresource.mipLevel);
138         int dstSlicePitchBytes = dst->slicePitchBytes(dstAspect, pRegion.dstSubresource.mipLevel);
139
140         VkExtent3D srcExtent = getMipLevelExtent(pRegion.srcSubresource.mipLevel);
141         VkExtent3D dstExtent = dst->getMipLevelExtent(pRegion.dstSubresource.mipLevel);
142
143         bool isSinglePlane = (pRegion.extent.depth == 1);
144         bool isSingleLine  = (pRegion.extent.height == 1) && isSinglePlane;
145         // In order to copy multiple lines using a single memcpy call, we
146         // have to make sure that we need to copy the entire line and that
147         // both source and destination lines have the same length in bytes
148         bool isEntireLine  = (pRegion.extent.width == srcExtent.width) &&
149                              (pRegion.extent.width == dstExtent.width) &&
150                              (srcRowPitchBytes == dstRowPitchBytes);
151         // In order to copy multiple planes using a single memcpy call, we
152         // have to make sure that we need to copy the entire plane and that
153         // both source and destination planes have the same length in bytes
154         bool isEntirePlane = isEntireLine &&
155                              (pRegion.extent.height == srcExtent.height) &&
156                              (pRegion.extent.height == dstExtent.height) &&
157                              (srcSlicePitchBytes == dstSlicePitchBytes);
158
159         if(isSingleLine) // Copy one line
160         {
161                 size_t copySize = pRegion.extent.width * srcBytesPerTexel;
162                 ASSERT((srcMem + copySize) < end());
163                 ASSERT((dstMem + copySize) < dst->end());
164                 memcpy(dstMem, srcMem, copySize);
165         }
166         else if(isEntireLine && isSinglePlane) // Copy one plane
167         {
168                 size_t copySize = pRegion.extent.height * srcRowPitchBytes;
169                 ASSERT((srcMem + copySize) < end());
170                 ASSERT((dstMem + copySize) < dst->end());
171                 memcpy(dstMem, srcMem, copySize);
172         }
173         else if(isEntirePlane) // Copy multiple planes
174         {
175                 size_t copySize = pRegion.extent.depth * srcSlicePitchBytes;
176                 ASSERT((srcMem + copySize) < end());
177                 ASSERT((dstMem + copySize) < dst->end());
178                 memcpy(dstMem, srcMem, copySize);
179         }
180         else if(isEntireLine) // Copy plane by plane
181         {
182                 size_t copySize = pRegion.extent.height * srcRowPitchBytes;
183
184                 for(uint32_t z = 0; z < pRegion.extent.depth; z++, dstMem += dstSlicePitchBytes, srcMem += srcSlicePitchBytes)
185                 {
186                         ASSERT((srcMem + copySize) < end());
187                         ASSERT((dstMem + copySize) < dst->end());
188                         memcpy(dstMem, srcMem, copySize);
189                 }
190         }
191         else // Copy line by line
192         {
193                 size_t copySize = pRegion.extent.width * srcBytesPerTexel;
194
195                 for(uint32_t z = 0; z < pRegion.extent.depth; z++)
196                 {
197                         for(uint32_t y = 0; y < pRegion.extent.height; y++, dstMem += dstRowPitchBytes, srcMem += srcRowPitchBytes)
198                         {
199                                 ASSERT((srcMem + copySize) < end());
200                                 ASSERT((dstMem + copySize) < dst->end());
201                                 memcpy(dstMem, srcMem, copySize);
202                         }
203                 }
204         }
205 }
206
207 void Image::copy(VkBuffer buf, const VkBufferImageCopy& region, bool bufferIsSource)
208 {
209         if(!((region.imageSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
210              (region.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
211              (region.imageSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)))
212         {
213                 UNIMPLEMENTED();
214         }
215
216         VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(region.imageSubresource.aspectMask);
217
218         VkExtent3D mipLevelExtent = getMipLevelExtent(region.imageSubresource.mipLevel);
219         int imageBytesPerTexel = bytesPerTexel(aspect);
220         int imageRowPitchBytes = rowPitchBytes(aspect, region.imageSubresource.mipLevel);
221         int imageSlicePitchBytes = slicePitchBytes(aspect, region.imageSubresource.mipLevel);
222         int bufferRowPitchBytes = ((region.bufferRowLength == 0) ? region.imageExtent.width : region.bufferRowLength) *
223                                   imageBytesPerTexel;
224         int bufferSlicePitchBytes = (((region.bufferImageHeight == 0) || (region.bufferRowLength == 0))) ?
225                                 region.imageExtent.height * bufferRowPitchBytes :
226                                     (region.bufferImageHeight * region.bufferRowLength) * imageBytesPerTexel;
227
228         int srcSlicePitchBytes = bufferIsSource ? bufferSlicePitchBytes : imageSlicePitchBytes;
229         int dstSlicePitchBytes = bufferIsSource ? imageSlicePitchBytes : bufferSlicePitchBytes;
230         int srcRowPitchBytes = bufferIsSource ? bufferRowPitchBytes : imageRowPitchBytes;
231         int dstRowPitchBytes = bufferIsSource ? imageRowPitchBytes : bufferRowPitchBytes;
232
233         bool isSinglePlane = (region.imageExtent.depth == 1);
234         bool isSingleLine  = (region.imageExtent.height == 1) && isSinglePlane;
235         bool isEntireLine  = (region.imageExtent.width == mipLevelExtent.width) &&
236                              (imageRowPitchBytes == bufferRowPitchBytes);
237         bool isEntirePlane = isEntireLine && (region.imageExtent.height == mipLevelExtent.height) &&
238                              (imageSlicePitchBytes == bufferSlicePitchBytes);
239
240         Buffer* buffer = Cast(buf);
241         uint8_t* bufferMemory = static_cast<uint8_t*>(buffer->getOffsetPointer(region.bufferOffset));
242         uint8_t* imageMemory = static_cast<uint8_t*>(deviceMemory->getOffsetPointer(
243                                getMemoryOffset(aspect, region.imageSubresource.mipLevel,
244                                                region.imageSubresource.baseArrayLayer) +
245                                texelOffsetBytesInStorage(region.imageOffset, region.imageSubresource)));
246         uint8_t* srcMemory = bufferIsSource ? bufferMemory : imageMemory;
247         uint8_t* dstMemory = bufferIsSource ? imageMemory : bufferMemory;
248
249         VkDeviceSize copySize = 0;
250         VkDeviceSize bufferLayerSize = 0;
251         if(isSingleLine)
252         {
253                 copySize = region.imageExtent.width * imageBytesPerTexel;
254                 bufferLayerSize = copySize;
255         }
256         else if(isEntireLine && isSinglePlane)
257         {
258                 copySize = region.imageExtent.height * imageRowPitchBytes;
259                 bufferLayerSize = copySize;
260         }
261         else if(isEntirePlane)
262         {
263                 copySize = region.imageExtent.depth * imageSlicePitchBytes; // Copy multiple planes
264                 bufferLayerSize = copySize;
265         }
266         else if(isEntireLine) // Copy plane by plane
267         {
268                 copySize = region.imageExtent.height * imageRowPitchBytes;
269                 bufferLayerSize = copySize * region.imageExtent.depth;
270         }
271         else // Copy line by line
272         {
273                 copySize = region.imageExtent.width * imageBytesPerTexel;
274                 bufferLayerSize = copySize * region.imageExtent.depth * region.imageExtent.height;
275         }
276
277         VkDeviceSize imageLayerSize = getLayerSize(aspect);
278         VkDeviceSize srcLayerSize = bufferIsSource ? bufferLayerSize : imageLayerSize;
279         VkDeviceSize dstLayerSize = bufferIsSource ? imageLayerSize : bufferLayerSize;
280
281         for(uint32_t i = 0; i < region.imageSubresource.layerCount; i++)
282         {
283                 if(isSingleLine || (isEntireLine && isSinglePlane) || isEntirePlane)
284                 {
285                         ASSERT(((bufferIsSource ? dstMemory : srcMemory) + copySize) < end());
286                         ASSERT(((bufferIsSource ? srcMemory : dstMemory) + copySize) < buffer->end());
287                         memcpy(dstMemory, srcMemory, copySize);
288                 }
289                 else if(isEntireLine) // Copy plane by plane
290                 {
291                         uint8_t* srcPlaneMemory = srcMemory;
292                         uint8_t* dstPlaneMemory = dstMemory;
293                         for(uint32_t z = 0; z < region.imageExtent.depth; z++)
294                         {
295                                 ASSERT(((bufferIsSource ? dstPlaneMemory : srcPlaneMemory) + copySize) < end());
296                                 ASSERT(((bufferIsSource ? srcPlaneMemory : dstPlaneMemory) + copySize) < buffer->end());
297                                 memcpy(dstPlaneMemory, srcPlaneMemory, copySize);
298                                 srcPlaneMemory += srcSlicePitchBytes;
299                                 dstPlaneMemory += dstSlicePitchBytes;
300                         }
301                 }
302                 else // Copy line by line
303                 {
304                         uint8_t* srcLayerMemory = srcMemory;
305                         uint8_t* dstLayerMemory = dstMemory;
306                         for(uint32_t z = 0; z < region.imageExtent.depth; z++)
307                         {
308                                 uint8_t* srcPlaneMemory = srcLayerMemory;
309                                 uint8_t* dstPlaneMemory = dstLayerMemory;
310                                 for(uint32_t y = 0; y < region.imageExtent.height; y++)
311                                 {
312                                         ASSERT(((bufferIsSource ? dstPlaneMemory : srcPlaneMemory) + copySize) < end());
313                                         ASSERT(((bufferIsSource ? srcPlaneMemory : dstPlaneMemory) + copySize) < buffer->end());
314                                         memcpy(dstPlaneMemory, srcPlaneMemory, copySize);
315                                         srcPlaneMemory += srcRowPitchBytes;
316                                         dstPlaneMemory += dstRowPitchBytes;
317                                 }
318                                 srcLayerMemory += srcSlicePitchBytes;
319                                 dstLayerMemory += dstSlicePitchBytes;
320                         }
321                 }
322
323                 srcMemory += srcLayerSize;
324                 dstMemory += dstLayerSize;
325         }
326 }
327
328 void Image::copyTo(VkBuffer dstBuffer, const VkBufferImageCopy& region)
329 {
330         copy(dstBuffer, region, false);
331 }
332
333 void Image::copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& region)
334 {
335         copy(srcBuffer, region, true);
336 }
337
338 void* Image::getTexelPointer(const VkOffset3D& offset, const VkImageSubresourceLayers& subresource) const
339 {
340         VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresource.aspectMask);
341         return deviceMemory->getOffsetPointer(texelOffsetBytesInStorage(offset, subresource) +
342                getMemoryOffset(aspect, subresource.mipLevel, subresource.baseArrayLayer));
343 }
344
345 VkDeviceSize Image::texelOffsetBytesInStorage(const VkOffset3D& offset, const VkImageSubresourceLayers& subresource) const
346 {
347         VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresource.aspectMask);
348         return offset.z * slicePitchBytes(aspect, subresource.mipLevel) +
349                (offset.y + (isCube() ? 1 : 0)) * rowPitchBytes(aspect, subresource.mipLevel) +
350                (offset.x + (isCube() ? 1 : 0)) * bytesPerTexel(aspect);
351 }
352
353 VkExtent3D Image::getMipLevelExtent(uint32_t mipLevel) const
354 {
355         VkExtent3D mipLevelExtent;
356         mipLevelExtent.width = extent.width >> mipLevel;
357         mipLevelExtent.height = extent.height >> mipLevel;
358         mipLevelExtent.depth = extent.depth >> mipLevel;
359
360         if(mipLevelExtent.width == 0)
361         {
362                 mipLevelExtent.width = 1;
363         }
364         if(mipLevelExtent.height == 0)
365         {
366                 mipLevelExtent.height = 1;
367         }
368         if(mipLevelExtent.depth == 0)
369         {
370                 mipLevelExtent.depth = 1;
371         }
372         return mipLevelExtent;
373 }
374
375 int Image::rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
376 {
377         // Depth and Stencil pitch should be computed separately
378         ASSERT((aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) !=
379                         (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
380         return getFormat(aspect).pitchB(getMipLevelExtent(mipLevel).width, isCube() ? 1 : 0, false);
381 }
382
383 int Image::slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
384 {
385         // Depth and Stencil slice should be computed separately
386         ASSERT((aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) !=
387                         (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
388         VkExtent3D mipLevelExtent = getMipLevelExtent(mipLevel);
389         return getFormat(aspect).sliceB(mipLevelExtent.width, mipLevelExtent.height, isCube() ? 1 : 0, false);
390 }
391
392 int Image::bytesPerTexel(VkImageAspectFlagBits aspect) const
393 {
394         // Depth and Stencil bytes should be computed separately
395         ASSERT((aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) !=
396                         (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
397         return getFormat(aspect).bytes();
398 }
399
400 Format Image::getFormat(VkImageAspectFlagBits aspect) const
401 {
402         switch(aspect)
403         {
404         case VK_IMAGE_ASPECT_DEPTH_BIT:
405                 switch(format)
406                 {
407                 case VK_FORMAT_D16_UNORM_S8_UINT:
408                         return VK_FORMAT_D16_UNORM;
409                 case VK_FORMAT_D24_UNORM_S8_UINT:
410                         return VK_FORMAT_X8_D24_UNORM_PACK32; // FIXME: This will allocate an extra byte per pixel
411                 case VK_FORMAT_D32_SFLOAT_S8_UINT:
412                         return VK_FORMAT_D32_SFLOAT;
413                 default:
414                         break;
415                 }
416                 break;
417         case VK_IMAGE_ASPECT_STENCIL_BIT:
418                 switch(format)
419                 {
420                 case VK_FORMAT_D16_UNORM_S8_UINT:
421                 case VK_FORMAT_D24_UNORM_S8_UINT:
422                 case VK_FORMAT_D32_SFLOAT_S8_UINT:
423                         return VK_FORMAT_S8_UINT;
424                 default:
425                         break;
426                 }
427                 break;
428         default:
429                 break;
430         }
431
432         return format;
433 }
434
435 bool Image::isCube() const
436 {
437         return (flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) && (imageType == VK_IMAGE_TYPE_2D);
438 }
439
440 uint8_t* Image::end() const
441 {
442         return reinterpret_cast<uint8_t*>(deviceMemory->getOffsetPointer(deviceMemory->getCommittedMemoryInBytes() + 1));
443 }
444
445 VkDeviceSize Image::getMemoryOffset(VkImageAspectFlagBits aspect) const
446 {
447         switch(format)
448         {
449         case VK_FORMAT_D16_UNORM_S8_UINT:
450         case VK_FORMAT_D24_UNORM_S8_UINT:
451         case VK_FORMAT_D32_SFLOAT_S8_UINT:
452                 if(aspect == VK_IMAGE_ASPECT_STENCIL_BIT)
453                 {
454                         // Offset by depth buffer to get to stencil buffer
455                         return memoryOffset + getStorageSize(VK_IMAGE_ASPECT_DEPTH_BIT);
456                 }
457                 break;
458         default:
459                 break;
460         }
461
462         return memoryOffset;
463 }
464
465 VkDeviceSize Image::getMemoryOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
466 {
467         VkDeviceSize offset = getMemoryOffset(aspect);
468         for(uint32_t i = 0; i < mipLevel; ++i)
469         {
470                 offset += getMipLevelSize(aspect, i);
471         }
472         return offset;
473 }
474
475 VkDeviceSize Image::getMemoryOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer) const
476 {
477         return layer * getLayerSize(aspect) + getMemoryOffset(aspect, mipLevel);
478 }
479
480 VkDeviceSize Image::getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
481 {
482         return getMipLevelExtent(mipLevel).depth * slicePitchBytes(aspect, mipLevel);
483 }
484
485 VkDeviceSize Image::getLayerSize(VkImageAspectFlagBits aspect) const
486 {
487         VkDeviceSize layerSize = 0;
488
489         for(uint32_t mipLevel = 0; mipLevel < mipLevels; ++mipLevel)
490         {
491                 layerSize += getMipLevelSize(aspect, mipLevel);
492         }
493
494         return layerSize;
495 }
496
497 VkDeviceSize Image::getStorageSize(VkImageAspectFlags aspectMask) const
498 {
499         if (aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT))
500         {
501                 return arrayLayers * (getLayerSize(VK_IMAGE_ASPECT_DEPTH_BIT) + getLayerSize(VK_IMAGE_ASPECT_STENCIL_BIT));
502         }
503         return arrayLayers * getLayerSize(static_cast<VkImageAspectFlagBits>(aspectMask));
504 }
505
506 void Image::blit(VkImage dstImage, const VkImageBlit& region, VkFilter filter)
507 {
508         device->getBlitter()->blit(this, Cast(dstImage), region, filter);
509 }
510
511 VkFormat Image::getClearFormat() const
512 {
513         // Set the proper format for the clear value, as described here:
514         // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#clears-values
515         if(format.isSignedNonNormalizedInteger())
516         {
517                 return VK_FORMAT_R32G32B32A32_SINT;
518         }
519         else if(format.isUnsignedNonNormalizedInteger())
520         {
521                 return VK_FORMAT_R32G32B32A32_UINT;
522         }
523
524         return VK_FORMAT_R32G32B32A32_SFLOAT;
525 }
526
527 uint32_t Image::getLastLayerIndex(const VkImageSubresourceRange& subresourceRange) const
528 {
529         return ((subresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS) ?
530                 arrayLayers : (subresourceRange.baseArrayLayer + subresourceRange.layerCount)) - 1;
531 }
532
533 uint32_t Image::getLastMipLevel(const VkImageSubresourceRange& subresourceRange) const
534 {
535         return ((subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS) ?
536                 mipLevels : (subresourceRange.baseMipLevel + subresourceRange.levelCount)) - 1;
537 }
538
539 void Image::clear(void* pixelData, VkFormat format, const VkImageSubresourceRange& subresourceRange, const VkRect2D& renderArea)
540 {
541         if((subresourceRange.baseMipLevel != 0) ||
542            (subresourceRange.levelCount != 1))
543         {
544                 UNIMPLEMENTED();
545         }
546
547         device->getBlitter()->clear(pixelData, format, this, subresourceRange, &renderArea);
548 }
549
550 void Image::clear(const VkClearColorValue& color, const VkImageSubresourceRange& subresourceRange)
551 {
552         if(!(subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT))
553         {
554                 UNIMPLEMENTED();
555         }
556
557         device->getBlitter()->clear((void*)color.float32, getClearFormat(), this, subresourceRange);
558 }
559
560 void Image::clear(const VkClearDepthStencilValue& color, const VkImageSubresourceRange& subresourceRange)
561 {
562         if((subresourceRange.aspectMask & ~(VK_IMAGE_ASPECT_DEPTH_BIT |
563                                             VK_IMAGE_ASPECT_STENCIL_BIT)) != 0)
564         {
565                 UNIMPLEMENTED();
566         }
567
568         if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
569         {
570                 VkImageSubresourceRange depthSubresourceRange = subresourceRange;
571                 depthSubresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
572                 device->getBlitter()->clear((void*)(&color.depth), VK_FORMAT_D32_SFLOAT, this, depthSubresourceRange);
573         }
574
575         if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
576         {
577                 VkImageSubresourceRange stencilSubresourceRange = subresourceRange;
578                 stencilSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
579                 device->getBlitter()->clear((void*)(&color.stencil), VK_FORMAT_S8_UINT, this, stencilSubresourceRange);
580         }
581 }
582
583 void Image::clear(const VkClearValue& clearValue, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange)
584 {
585         if(!((subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
586              (subresourceRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT |
587                                              VK_IMAGE_ASPECT_STENCIL_BIT))) ||
588            (subresourceRange.baseMipLevel != 0) ||
589            (subresourceRange.levelCount != 1))
590         {
591                 UNIMPLEMENTED();
592         }
593
594         if(subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
595         {
596                 clear((void*)(clearValue.color.float32), getClearFormat(), subresourceRange, renderArea);
597         }
598         else
599         {
600                 if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
601                 {
602                         VkImageSubresourceRange depthSubresourceRange = subresourceRange;
603                         depthSubresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
604                         clear((void*)(&clearValue.depthStencil.depth), VK_FORMAT_D32_SFLOAT, depthSubresourceRange, renderArea);
605                 }
606
607                 if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
608                 {
609                         VkImageSubresourceRange stencilSubresourceRange = subresourceRange;
610                         stencilSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
611                         clear((void*)(&clearValue.depthStencil.stencil), VK_FORMAT_S8_UINT, stencilSubresourceRange, renderArea);
612                 }
613         }
614 }
615
616 } // namespace vk