Commit 0774188d by Alexis Hetu Committed by Alexis Hétu

Fix ImageView size computation

Erroneous ImageView size computation was causing out of bounds memory accesses whenever an ImageView only represents a subsection of an Image. The getSizeInBytes() function now only returns the size in bytes within the Image object from the beginning to the end of the bytes used by the ImageView. Bug: b/150464740 Change-Id: I0985af9cdfbb85b10336a7691f76009496bb2ae5 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/43329 Presubmit-Ready: Alexis Hétu <sugoi@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarAlexis Hétu <sugoi@google.com>
parent cb586623
......@@ -449,7 +449,7 @@ void DescriptorSetLayout::WriteDescriptorSet(Device *device, DescriptorSet *dstS
descriptor[i].slicePitchBytes = descriptor[i].samplePitchBytes * imageView->getSampleCount();
descriptor[i].arrayLayers = imageView->getSubresourceRange().layerCount;
descriptor[i].sampleCount = imageView->getSampleCount();
descriptor[i].sizeInBytes = static_cast<int>(imageView->getImageSizeInBytes());
descriptor[i].sizeInBytes = static_cast<int>(imageView->getSizeInBytes());
if(imageView->getFormat().isStencil())
{
......
......@@ -178,6 +178,42 @@ const VkMemoryRequirements Image::getMemoryRequirements() const
return memoryRequirements;
}
size_t Image::getSizeInBytes(const VkImageSubresourceRange &subresourceRange) const
{
size_t size = 0;
uint32_t lastLayer = getLastLayerIndex(subresourceRange);
uint32_t lastMipLevel = getLastMipLevel(subresourceRange);
uint32_t layerCount = lastLayer - subresourceRange.baseArrayLayer + 1;
uint32_t mipLevelCount = lastMipLevel - subresourceRange.baseMipLevel + 1;
auto aspect = static_cast<VkImageAspectFlagBits>(subresourceRange.aspectMask);
if(layerCount > 1)
{
if(mipLevelCount < mipLevels) // Compute size for all layers except the last one, then add relevant mip level sizes only for last layer
{
size = (layerCount - 1) * getLayerSize(aspect);
for(uint32_t mipLevel = subresourceRange.baseMipLevel; mipLevel <= lastMipLevel; ++mipLevel)
{
size += getMultiSampledLevelSize(aspect, mipLevel);
}
}
else // All mip levels used, compute full layer sizes
{
size = layerCount * getLayerSize(aspect);
}
}
else // Single layer, add all mip levels in the subresource range
{
for(uint32_t mipLevel = subresourceRange.baseMipLevel; mipLevel <= lastMipLevel; ++mipLevel)
{
size += getMultiSampledLevelSize(aspect, mipLevel);
}
}
return size;
}
bool Image::canBindToMemory(DeviceMemory *pDeviceMemory) const
{
return pDeviceMemory->checkExternalMemoryHandleType(supportedExternalMemoryHandleTypes);
......
......@@ -51,6 +51,7 @@ public:
static size_t ComputeRequiredAllocationSize(const VkImageCreateInfo *pCreateInfo);
const VkMemoryRequirements getMemoryRequirements() const;
size_t getSizeInBytes(const VkImageSubresourceRange &subresourceRange) const;
void getSubresourceLayout(const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout) const;
void bind(DeviceMemory *pDeviceMemory, VkDeviceSize pMemoryOffset);
void copyTo(Image *dstImage, const VkImageCopy &pRegion) const;
......
......@@ -110,7 +110,7 @@ public:
const VkComponentMapping &getComponentMapping() const { return components; }
const VkImageSubresourceRange &getSubresourceRange() const { return subresourceRange; }
size_t getImageSizeInBytes() const { return image->getMemoryRequirements().size; }
size_t getSizeInBytes() const { return image->getSizeInBytes(subresourceRange); }
private:
bool imageTypesMatch(VkImageType imageType) const;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment