Commit 0459596b by Alexis Hetu Committed by Alexis Hétu

Support for array layers in Image objects

Added basic support for array layers in Image objects. This allows allocating the memory for multiple layers, copying between a 2D image with multiple layers to and from a 3D image. Passes all tests in: dEQP-VK.api.copy_and_blit.core.image_to_image.3d_images.* Bug b/119620767 Change-Id: I305650ba89f90dcd527b484fc3ed095a309506d1 Reviewed-on: https://swiftshader-review.googlesource.com/c/23208Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com>
parent af3c1022
...@@ -54,7 +54,7 @@ const VkMemoryRequirements Image::getMemoryRequirements() const ...@@ -54,7 +54,7 @@ const VkMemoryRequirements Image::getMemoryRequirements() const
void Image::bind(VkDeviceMemory pDeviceMemory, VkDeviceSize pMemoryOffset) void Image::bind(VkDeviceMemory pDeviceMemory, VkDeviceSize pMemoryOffset)
{ {
deviceMemory = pDeviceMemory; deviceMemory = Cast(pDeviceMemory);
memoryOffset = pMemoryOffset; memoryOffset = pMemoryOffset;
} }
...@@ -69,8 +69,6 @@ void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion) ...@@ -69,8 +69,6 @@ void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion)
if(!((pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) || if(!((pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
(pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) || (pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
(pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) || (pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) ||
(pRegion.srcSubresource.baseArrayLayer != 0) ||
(pRegion.srcSubresource.layerCount != 1) ||
(pRegion.srcSubresource.mipLevel != 0)) (pRegion.srcSubresource.mipLevel != 0))
{ {
UNIMPLEMENTED(); UNIMPLEMENTED();
...@@ -79,25 +77,28 @@ void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion) ...@@ -79,25 +77,28 @@ void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion)
if(!((pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) || if(!((pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
(pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) || (pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
(pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) || (pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) ||
(pRegion.dstSubresource.baseArrayLayer != 0) ||
(pRegion.dstSubresource.layerCount != 1) ||
(pRegion.dstSubresource.mipLevel != 0)) (pRegion.dstSubresource.mipLevel != 0))
{ {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
const char* srcMem = static_cast<const char*>(getTexelPointer(pRegion.srcOffset)); const char* srcMem = static_cast<const char*>(getTexelPointer(pRegion.srcOffset, pRegion.srcSubresource.baseArrayLayer));
char* dstMem = static_cast<char*>(dst->getTexelPointer(pRegion.dstOffset)); char* dstMem = static_cast<char*>(dst->getTexelPointer(pRegion.dstOffset, pRegion.dstSubresource.baseArrayLayer));
int srcRowPitchBytes = rowPitchBytes(); int srcRowPitchBytes = rowPitchBytes();
int srcSlicePitchBytes = slicePitchBytes(); int srcSlicePitchBytes = slicePitchBytes();
int dstRowPitchBytes = dst->rowPitchBytes(); int dstRowPitchBytes = dst->rowPitchBytes();
int dstSlicePitchBytes = dst->slicePitchBytes(); int dstSlicePitchBytes = dst->slicePitchBytes();
bool isSingleLine = (pRegion.extent.height == 1) && (pRegion.extent.depth == 1);
bool isEntireLine = (pRegion.extent.width == extent.width) && (pRegion.extent.width == dst->extent.width) && (srcRowPitchBytes == dstRowPitchBytes);
bool isSinglePlane = (pRegion.extent.depth == 1); bool isSinglePlane = (pRegion.extent.depth == 1);
bool isEntirePlane = isEntireLine && (pRegion.extent.height == extent.height) && (pRegion.extent.height == dst->extent.height) && (srcSlicePitchBytes == dstSlicePitchBytes); bool isSingleLine = (pRegion.extent.height == 1) && isSinglePlane;
bool isEntireLine = (pRegion.extent.width == extent.width) &&
(pRegion.extent.width == dst->extent.width) &&
(srcRowPitchBytes == dstRowPitchBytes);
bool isEntirePlane = isEntireLine &&
(pRegion.extent.height == extent.height) &&
(pRegion.extent.height == dst->extent.height) &&
(srcSlicePitchBytes == dstSlicePitchBytes);
if(isSingleLine) if(isSingleLine)
{ {
...@@ -107,7 +108,7 @@ void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion) ...@@ -107,7 +108,7 @@ void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion)
{ {
memcpy(dstMem, srcMem, pRegion.extent.height * srcRowPitchBytes); // Copy one plane memcpy(dstMem, srcMem, pRegion.extent.height * srcRowPitchBytes); // Copy one plane
} }
else if(isEntireLine && isEntirePlane) else if(isEntirePlane)
{ {
memcpy(dstMem, srcMem, pRegion.extent.depth * srcSlicePitchBytes); // Copy multiple planes memcpy(dstMem, srcMem, pRegion.extent.depth * srcSlicePitchBytes); // Copy multiple planes
} }
...@@ -138,8 +139,6 @@ void Image::copyTo(VkBuffer dstBuffer, const VkBufferImageCopy& pRegion) ...@@ -138,8 +139,6 @@ void Image::copyTo(VkBuffer dstBuffer, const VkBufferImageCopy& pRegion)
!((pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) || !((pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
(pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) || (pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
(pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) || (pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) ||
(pRegion.imageSubresource.baseArrayLayer != 0) ||
(pRegion.imageSubresource.layerCount != 1) ||
(pRegion.imageSubresource.mipLevel != 0) || (pRegion.imageSubresource.mipLevel != 0) ||
(pRegion.imageOffset.x != 0) || (pRegion.imageOffset.x != 0) ||
(pRegion.imageOffset.y != 0) || (pRegion.imageOffset.y != 0) ||
...@@ -150,10 +149,20 @@ void Image::copyTo(VkBuffer dstBuffer, const VkBufferImageCopy& pRegion) ...@@ -150,10 +149,20 @@ void Image::copyTo(VkBuffer dstBuffer, const VkBufferImageCopy& pRegion)
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
Cast(dstBuffer)->copyFrom(Cast(deviceMemory)->getOffsetPointer(memoryOffset), Buffer* dst = Cast(dstBuffer);
sw::Surface::sliceB(pRegion.imageExtent.width, pRegion.imageExtent.height, VkDeviceSize copySize = slicePitchBytes() * pRegion.imageExtent.depth;
getBorder(), format, false) * pRegion.imageExtent.depth, VkDeviceSize layerSize = slicePitchBytes() * extent.depth;
pRegion.bufferOffset); VkDeviceSize srcOffset = memoryOffset;
VkDeviceSize dstOffset = pRegion.bufferOffset;
uint32_t firstLayer = pRegion.imageSubresource.baseArrayLayer;
uint32_t lastLayer = firstLayer + pRegion.imageSubresource.layerCount - 1;
for(uint32_t layer = firstLayer; layer <= lastLayer; layer++)
{
dst->copyFrom(deviceMemory->getOffsetPointer(srcOffset), copySize, dstOffset);
srcOffset += layerSize;
dstOffset += layerSize;
}
} }
void Image::copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& pRegion) void Image::copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& pRegion)
...@@ -164,8 +173,6 @@ void Image::copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& pRegion) ...@@ -164,8 +173,6 @@ void Image::copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& pRegion)
!((pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) || !((pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
(pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) || (pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
(pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) || (pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) ||
(pRegion.imageSubresource.baseArrayLayer != 0) ||
(pRegion.imageSubresource.layerCount != 1) ||
(pRegion.imageSubresource.mipLevel != 0) || (pRegion.imageSubresource.mipLevel != 0) ||
(pRegion.imageOffset.x != 0) || (pRegion.imageOffset.x != 0) ||
(pRegion.imageOffset.y != 0) || (pRegion.imageOffset.y != 0) ||
...@@ -176,20 +183,29 @@ void Image::copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& pRegion) ...@@ -176,20 +183,29 @@ void Image::copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& pRegion)
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
Cast(srcBuffer)->copyTo(Cast(deviceMemory)->getOffsetPointer(memoryOffset), Buffer* src = Cast(srcBuffer);
sw::Surface::sliceB(pRegion.imageExtent.width, pRegion.imageExtent.height, VkDeviceSize copySize = slicePitchBytes() * pRegion.imageExtent.depth;
getBorder(), format, false) * pRegion.imageExtent.depth, VkDeviceSize layerSize = slicePitchBytes() * extent.depth;
pRegion.bufferOffset); VkDeviceSize srcOffset = pRegion.bufferOffset;
VkDeviceSize dstOffset = memoryOffset;
uint32_t lastLayer = pRegion.imageSubresource.baseArrayLayer + pRegion.imageSubresource.layerCount - 1;
for(uint32_t layer = pRegion.imageSubresource.baseArrayLayer; layer <= lastLayer; layer++)
{
src->copyTo(deviceMemory->getOffsetPointer(dstOffset), copySize, srcOffset);
srcOffset += layerSize;
dstOffset += layerSize;
}
} }
void* Image::getTexelPointer(const VkOffset3D& offset) const void* Image::getTexelPointer(const VkOffset3D& offset, uint32_t baseArrayLayer) const
{ {
return Cast(deviceMemory)->getOffsetPointer(texelOffsetBytesInStorage(offset) + memoryOffset); return deviceMemory->getOffsetPointer(texelOffsetBytesInStorage(offset, baseArrayLayer) + memoryOffset);
} }
VkDeviceSize Image::texelOffsetBytesInStorage(const VkOffset3D& offset) const VkDeviceSize Image::texelOffsetBytesInStorage(const VkOffset3D& offset, uint32_t baseArrayLayer) const
{ {
return offset.z * slicePitchBytes() + offset.y * rowPitchBytes() + offset.x * bytesPerTexel(); return (baseArrayLayer * extent.depth + offset.z) * slicePitchBytes() + offset.y * rowPitchBytes() + offset.x * bytesPerTexel();
} }
int Image::rowPitchBytes() const int Image::rowPitchBytes() const
...@@ -219,7 +235,7 @@ VkDeviceSize Image::getStorageSize() const ...@@ -219,7 +235,7 @@ VkDeviceSize Image::getStorageSize() const
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
return extent.depth * slicePitchBytes(); return arrayLayers * extent.depth * slicePitchBytes();
} }
void Image::clear(const VkClearValue& clearValue, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange) void Image::clear(const VkClearValue& clearValue, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange)
...@@ -251,7 +267,7 @@ void Image::clear(const VkClearValue& clearValue, const VkRect2D& renderArea, co ...@@ -251,7 +267,7 @@ void Image::clear(const VkClearValue& clearValue, const VkRect2D& renderArea, co
const sw::SliceRect dRect(rect); const sw::SliceRect dRect(rect);
sw::Surface* surface = sw::Surface::create(extent.width, extent.height, extent.depth, format, sw::Surface* surface = sw::Surface::create(extent.width, extent.height, extent.depth, format,
Cast(deviceMemory)->getOffsetPointer(memoryOffset), rowPitchBytes(), slicePitchBytes()); deviceMemory->getOffsetPointer(memoryOffset), rowPitchBytes(), slicePitchBytes());
sw::Blitter blitter; sw::Blitter blitter;
blitter.clear((void*)clearValue.color.float32, clearFormat, surface, dRect, 0xF); blitter.clear((void*)clearValue.color.float32, clearFormat, surface, dRect, 0xF);
delete surface; delete surface;
......
...@@ -25,6 +25,8 @@ namespace sw ...@@ -25,6 +25,8 @@ namespace sw
namespace vk namespace vk
{ {
class DeviceMemory;
class Image : public Object<Image, VkImage> class Image : public Object<Image, VkImage>
{ {
public: public:
...@@ -34,7 +36,6 @@ public: ...@@ -34,7 +36,6 @@ public:
static size_t ComputeRequiredAllocationSize(const VkImageCreateInfo* pCreateInfo); static size_t ComputeRequiredAllocationSize(const VkImageCreateInfo* pCreateInfo);
VkDeviceSize getStorageSize() const;
const VkMemoryRequirements getMemoryRequirements() const; const VkMemoryRequirements getMemoryRequirements() const;
void bind(VkDeviceMemory pDeviceMemory, VkDeviceSize pMemoryOffset); void bind(VkDeviceMemory pDeviceMemory, VkDeviceSize pMemoryOffset);
void copyTo(VkImage dstImage, const VkImageCopy& pRegion); void copyTo(VkImage dstImage, const VkImageCopy& pRegion);
...@@ -47,14 +48,15 @@ public: ...@@ -47,14 +48,15 @@ public:
VkFormat getFormat() const { return format; } VkFormat getFormat() const { return format; }
private: private:
void* getTexelPointer(const VkOffset3D& offset) const; VkDeviceSize getStorageSize() const;
VkDeviceSize texelOffsetBytesInStorage(const VkOffset3D& offset) const; void* getTexelPointer(const VkOffset3D& offset, uint32_t baseArrayLayer) const;
VkDeviceSize texelOffsetBytesInStorage(const VkOffset3D& offset, uint32_t baseArrayLayer) const;
int rowPitchBytes() const; int rowPitchBytes() const;
int slicePitchBytes() const; int slicePitchBytes() const;
int bytesPerTexel() const; int bytesPerTexel() const;
int getBorder() const; int getBorder() const;
VkDeviceMemory deviceMemory = nullptr; DeviceMemory* deviceMemory = nullptr;
VkDeviceSize memoryOffset = 0; VkDeviceSize memoryOffset = 0;
VkImageCreateFlags flags = 0; VkImageCreateFlags flags = 0;
VkImageType imageType = VK_IMAGE_TYPE_2D; VkImageType imageType = VK_IMAGE_TYPE_2D;
......
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