1 // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include "VkDeviceMemory.hpp"
16 #include "VkBuffer.hpp"
17 #include "VkDevice.hpp"
18 #include "VkImage.hpp"
19 #include "Device/Blitter.hpp"
24 VkImageAspectFlags GetAspects(vk::Format format)
26 // TODO: probably just flatten this out to a full format list, and alter
27 // isDepth / isStencil etc to check for their aspect
29 VkImageAspectFlags aspects = 0;
30 if (format.isDepth()) aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
31 if (format.isStencil()) aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
33 // TODO: YCbCr planar formats have different aspects
35 // Anything else is "color".
36 if (!aspects) aspects |= VK_IMAGE_ASPECT_COLOR_BIT;
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)
55 if (samples != VK_SAMPLE_COUNT_1_BIT)
57 UNIMPLEMENTED("Multisample images not yet supported");
61 void Image::destroy(const VkAllocationCallbacks* pAllocator)
65 size_t Image::ComputeRequiredAllocationSize(const Image::CreateInfo* pCreateInfo)
70 const VkMemoryRequirements Image::getMemoryRequirements() const
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;
79 void Image::bind(VkDeviceMemory pDeviceMemory, VkDeviceSize pMemoryOffset)
81 deviceMemory = Cast(pDeviceMemory);
82 memoryOffset = pMemoryOffset;
85 void Image::getSubresourceLayout(const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) const
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)))
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);
102 void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion)
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);
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))
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))
126 VkImageAspectFlagBits srcAspect = static_cast<VkImageAspectFlagBits>(pRegion.srcSubresource.aspectMask);
127 VkImageAspectFlagBits dstAspect = static_cast<VkImageAspectFlagBits>(pRegion.dstSubresource.aspectMask);
129 int srcBytesPerTexel = bytesPerTexel(srcAspect);
130 ASSERT(srcBytesPerTexel == dst->bytesPerTexel(dstAspect));
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));
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);
140 VkExtent3D srcExtent = getMipLevelExtent(pRegion.srcSubresource.mipLevel);
141 VkExtent3D dstExtent = dst->getMipLevelExtent(pRegion.dstSubresource.mipLevel);
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);
159 if(isSingleLine) // Copy one line
161 size_t copySize = pRegion.extent.width * srcBytesPerTexel;
162 ASSERT((srcMem + copySize) < end());
163 ASSERT((dstMem + copySize) < dst->end());
164 memcpy(dstMem, srcMem, copySize);
166 else if(isEntireLine && isSinglePlane) // Copy one plane
168 size_t copySize = pRegion.extent.height * srcRowPitchBytes;
169 ASSERT((srcMem + copySize) < end());
170 ASSERT((dstMem + copySize) < dst->end());
171 memcpy(dstMem, srcMem, copySize);
173 else if(isEntirePlane) // Copy multiple planes
175 size_t copySize = pRegion.extent.depth * srcSlicePitchBytes;
176 ASSERT((srcMem + copySize) < end());
177 ASSERT((dstMem + copySize) < dst->end());
178 memcpy(dstMem, srcMem, copySize);
180 else if(isEntireLine) // Copy plane by plane
182 size_t copySize = pRegion.extent.height * srcRowPitchBytes;
184 for(uint32_t z = 0; z < pRegion.extent.depth; z++, dstMem += dstSlicePitchBytes, srcMem += srcSlicePitchBytes)
186 ASSERT((srcMem + copySize) < end());
187 ASSERT((dstMem + copySize) < dst->end());
188 memcpy(dstMem, srcMem, copySize);
191 else // Copy line by line
193 size_t copySize = pRegion.extent.width * srcBytesPerTexel;
195 for(uint32_t z = 0; z < pRegion.extent.depth; z++)
197 for(uint32_t y = 0; y < pRegion.extent.height; y++, dstMem += dstRowPitchBytes, srcMem += srcRowPitchBytes)
199 ASSERT((srcMem + copySize) < end());
200 ASSERT((dstMem + copySize) < dst->end());
201 memcpy(dstMem, srcMem, copySize);
207 void Image::copy(VkBuffer buf, const VkBufferImageCopy& region, bool bufferIsSource)
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)))
216 VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(region.imageSubresource.aspectMask);
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) *
224 int bufferSlicePitchBytes = (((region.bufferImageHeight == 0) || (region.bufferRowLength == 0))) ?
225 region.imageExtent.height * bufferRowPitchBytes :
226 (region.bufferImageHeight * region.bufferRowLength) * imageBytesPerTexel;
228 int srcSlicePitchBytes = bufferIsSource ? bufferSlicePitchBytes : imageSlicePitchBytes;
229 int dstSlicePitchBytes = bufferIsSource ? imageSlicePitchBytes : bufferSlicePitchBytes;
230 int srcRowPitchBytes = bufferIsSource ? bufferRowPitchBytes : imageRowPitchBytes;
231 int dstRowPitchBytes = bufferIsSource ? imageRowPitchBytes : bufferRowPitchBytes;
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);
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;
249 VkDeviceSize copySize = 0;
250 VkDeviceSize bufferLayerSize = 0;
253 copySize = region.imageExtent.width * imageBytesPerTexel;
254 bufferLayerSize = copySize;
256 else if(isEntireLine && isSinglePlane)
258 copySize = region.imageExtent.height * imageRowPitchBytes;
259 bufferLayerSize = copySize;
261 else if(isEntirePlane)
263 copySize = region.imageExtent.depth * imageSlicePitchBytes; // Copy multiple planes
264 bufferLayerSize = copySize;
266 else if(isEntireLine) // Copy plane by plane
268 copySize = region.imageExtent.height * imageRowPitchBytes;
269 bufferLayerSize = copySize * region.imageExtent.depth;
271 else // Copy line by line
273 copySize = region.imageExtent.width * imageBytesPerTexel;
274 bufferLayerSize = copySize * region.imageExtent.depth * region.imageExtent.height;
277 VkDeviceSize imageLayerSize = getLayerSize(aspect);
278 VkDeviceSize srcLayerSize = bufferIsSource ? bufferLayerSize : imageLayerSize;
279 VkDeviceSize dstLayerSize = bufferIsSource ? imageLayerSize : bufferLayerSize;
281 for(uint32_t i = 0; i < region.imageSubresource.layerCount; i++)
283 if(isSingleLine || (isEntireLine && isSinglePlane) || isEntirePlane)
285 ASSERT(((bufferIsSource ? dstMemory : srcMemory) + copySize) < end());
286 ASSERT(((bufferIsSource ? srcMemory : dstMemory) + copySize) < buffer->end());
287 memcpy(dstMemory, srcMemory, copySize);
289 else if(isEntireLine) // Copy plane by plane
291 uint8_t* srcPlaneMemory = srcMemory;
292 uint8_t* dstPlaneMemory = dstMemory;
293 for(uint32_t z = 0; z < region.imageExtent.depth; z++)
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;
302 else // Copy line by line
304 uint8_t* srcLayerMemory = srcMemory;
305 uint8_t* dstLayerMemory = dstMemory;
306 for(uint32_t z = 0; z < region.imageExtent.depth; z++)
308 uint8_t* srcPlaneMemory = srcLayerMemory;
309 uint8_t* dstPlaneMemory = dstLayerMemory;
310 for(uint32_t y = 0; y < region.imageExtent.height; y++)
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;
318 srcLayerMemory += srcSlicePitchBytes;
319 dstLayerMemory += dstSlicePitchBytes;
323 srcMemory += srcLayerSize;
324 dstMemory += dstLayerSize;
328 void Image::copyTo(VkBuffer dstBuffer, const VkBufferImageCopy& region)
330 copy(dstBuffer, region, false);
333 void Image::copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& region)
335 copy(srcBuffer, region, true);
338 void* Image::getTexelPointer(const VkOffset3D& offset, const VkImageSubresourceLayers& subresource) const
340 VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresource.aspectMask);
341 return deviceMemory->getOffsetPointer(texelOffsetBytesInStorage(offset, subresource) +
342 getMemoryOffset(aspect, subresource.mipLevel, subresource.baseArrayLayer));
345 VkDeviceSize Image::texelOffsetBytesInStorage(const VkOffset3D& offset, const VkImageSubresourceLayers& subresource) const
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);
353 VkExtent3D Image::getMipLevelExtent(uint32_t mipLevel) const
355 VkExtent3D mipLevelExtent;
356 mipLevelExtent.width = extent.width >> mipLevel;
357 mipLevelExtent.height = extent.height >> mipLevel;
358 mipLevelExtent.depth = extent.depth >> mipLevel;
360 if(mipLevelExtent.width == 0)
362 mipLevelExtent.width = 1;
364 if(mipLevelExtent.height == 0)
366 mipLevelExtent.height = 1;
368 if(mipLevelExtent.depth == 0)
370 mipLevelExtent.depth = 1;
372 return mipLevelExtent;
375 int Image::rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
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);
383 int Image::slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
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);
392 int Image::bytesPerTexel(VkImageAspectFlagBits aspect) const
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();
400 Format Image::getFormat(VkImageAspectFlagBits aspect) const
404 case VK_IMAGE_ASPECT_DEPTH_BIT:
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;
417 case VK_IMAGE_ASPECT_STENCIL_BIT:
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;
435 bool Image::isCube() const
437 return (flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) && (imageType == VK_IMAGE_TYPE_2D);
440 uint8_t* Image::end() const
442 return reinterpret_cast<uint8_t*>(deviceMemory->getOffsetPointer(deviceMemory->getCommittedMemoryInBytes() + 1));
445 VkDeviceSize Image::getMemoryOffset(VkImageAspectFlagBits aspect) const
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)
454 // Offset by depth buffer to get to stencil buffer
455 return memoryOffset + getStorageSize(VK_IMAGE_ASPECT_DEPTH_BIT);
465 VkDeviceSize Image::getMemoryOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
467 VkDeviceSize offset = getMemoryOffset(aspect);
468 for(uint32_t i = 0; i < mipLevel; ++i)
470 offset += getMipLevelSize(aspect, i);
475 VkDeviceSize Image::getMemoryOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer) const
477 return layer * getLayerSize(aspect) + getMemoryOffset(aspect, mipLevel);
480 VkDeviceSize Image::getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
482 return getMipLevelExtent(mipLevel).depth * slicePitchBytes(aspect, mipLevel);
485 VkDeviceSize Image::getLayerSize(VkImageAspectFlagBits aspect) const
487 VkDeviceSize layerSize = 0;
489 for(uint32_t mipLevel = 0; mipLevel < mipLevels; ++mipLevel)
491 layerSize += getMipLevelSize(aspect, mipLevel);
497 VkDeviceSize Image::getStorageSize(VkImageAspectFlags aspectMask) const
499 if (aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT))
501 return arrayLayers * (getLayerSize(VK_IMAGE_ASPECT_DEPTH_BIT) + getLayerSize(VK_IMAGE_ASPECT_STENCIL_BIT));
503 return arrayLayers * getLayerSize(static_cast<VkImageAspectFlagBits>(aspectMask));
506 void Image::blit(VkImage dstImage, const VkImageBlit& region, VkFilter filter)
508 device->getBlitter()->blit(this, Cast(dstImage), region, filter);
511 VkFormat Image::getClearFormat() const
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())
517 return VK_FORMAT_R32G32B32A32_SINT;
519 else if(format.isUnsignedNonNormalizedInteger())
521 return VK_FORMAT_R32G32B32A32_UINT;
524 return VK_FORMAT_R32G32B32A32_SFLOAT;
527 uint32_t Image::getLastLayerIndex(const VkImageSubresourceRange& subresourceRange) const
529 return ((subresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS) ?
530 arrayLayers : (subresourceRange.baseArrayLayer + subresourceRange.layerCount)) - 1;
533 uint32_t Image::getLastMipLevel(const VkImageSubresourceRange& subresourceRange) const
535 return ((subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS) ?
536 mipLevels : (subresourceRange.baseMipLevel + subresourceRange.levelCount)) - 1;
539 void Image::clear(void* pixelData, VkFormat format, const VkImageSubresourceRange& subresourceRange, const VkRect2D& renderArea)
541 if((subresourceRange.baseMipLevel != 0) ||
542 (subresourceRange.levelCount != 1))
547 device->getBlitter()->clear(pixelData, format, this, subresourceRange, &renderArea);
550 void Image::clear(const VkClearColorValue& color, const VkImageSubresourceRange& subresourceRange)
552 if(!(subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT))
557 device->getBlitter()->clear((void*)color.float32, getClearFormat(), this, subresourceRange);
560 void Image::clear(const VkClearDepthStencilValue& color, const VkImageSubresourceRange& subresourceRange)
562 if((subresourceRange.aspectMask & ~(VK_IMAGE_ASPECT_DEPTH_BIT |
563 VK_IMAGE_ASPECT_STENCIL_BIT)) != 0)
568 if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
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);
575 if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
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);
583 void Image::clear(const VkClearValue& clearValue, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange)
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))
594 if(subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
596 clear((void*)(clearValue.color.float32), getClearFormat(), subresourceRange, renderArea);
600 if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
602 VkImageSubresourceRange depthSubresourceRange = subresourceRange;
603 depthSubresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
604 clear((void*)(&clearValue.depthStencil.depth), VK_FORMAT_D32_SFLOAT, depthSubresourceRange, renderArea);
607 if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
609 VkImageSubresourceRange stencilSubresourceRange = subresourceRange;
610 stencilSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
611 clear((void*)(&clearValue.depthStencil.stencil), VK_FORMAT_S8_UINT, stencilSubresourceRange, renderArea);