Commit 377077a7 by Alexis Hetu Committed by Alexis Hétu

CubeMap fixes

The following changes are done in this cl: - Added multilayer support in Blitter::blit() - Fixed Image::texelOffsetBytesInStorage() for cubes, since there's a 1 pixel border around it, so pixel offset (0,0,0) should be an extra line (1 pixel offset in Y) + 1 pixel (1 pixel offset in X) from the beginning of the buffer - Added a number of out of bounds memory access asserts, which helped debug this issue. Fixed failures in: dEQP-VK.api.copy_and_blit.core.blit_image.all_formats.generate_mipmaps.* Note: The only failures left in that category are related to filtering sRGB images, which most likely happens in the wrong colorspace. Tests: dEQP-VK.api.copy_and_blit.core.blit_image.all_formats.generate_mipmaps.* Bug b/119620767 Change-Id: I6f18271cb23070eb8f2de3b1d5b35b7021c0ca8b Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27229Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent 1e6a9898
...@@ -1515,10 +1515,7 @@ namespace sw ...@@ -1515,10 +1515,7 @@ namespace sw
return; return;
} }
if((region.srcSubresource.baseArrayLayer != 0) || if((region.srcSubresource.layerCount != region.dstSubresource.layerCount) ||
(region.dstSubresource.baseArrayLayer != 0) ||
(region.srcSubresource.layerCount != 1) ||
(region.dstSubresource.layerCount != 1) ||
(region.srcSubresource.aspectMask != region.dstSubresource.aspectMask)) (region.srcSubresource.aspectMask != region.dstSubresource.aspectMask))
{ {
UNIMPLEMENTED(); UNIMPLEMENTED();
...@@ -1545,7 +1542,7 @@ namespace sw ...@@ -1545,7 +1542,7 @@ namespace sw
VkImageAspectFlagBits dstAspect = static_cast<VkImageAspectFlagBits>(region.dstSubresource.aspectMask); VkImageAspectFlagBits dstAspect = static_cast<VkImageAspectFlagBits>(region.dstSubresource.aspectMask);
State state(src->getFormat(srcAspect), dst->getFormat(dstAspect), dst->getSampleCountFlagBits(), State state(src->getFormat(srcAspect), dst->getFormat(dstAspect), dst->getSampleCountFlagBits(),
{ filter != VK_FILTER_NEAREST, region.srcSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT, false }); { filter != VK_FILTER_NEAREST, srcAspect == VK_IMAGE_ASPECT_STENCIL_BIT, false });
state.clampToEdge = (region.srcOffsets[0].x < 0) || state.clampToEdge = (region.srcOffsets[0].x < 0) ||
(region.srcOffsets[0].y < 0) || (region.srcOffsets[0].y < 0) ||
(static_cast<uint32_t>(region.srcOffsets[1].x) > srcExtent.width) || (static_cast<uint32_t>(region.srcOffsets[1].x) > srcExtent.width) ||
...@@ -1583,13 +1580,50 @@ namespace sw ...@@ -1583,13 +1580,50 @@ namespace sw
VkOffset3D srcOffset = { 0, 0, region.srcOffsets[0].z }; VkOffset3D srcOffset = { 0, 0, region.srcOffsets[0].z };
VkOffset3D dstOffset = { 0, 0, region.dstOffsets[0].z }; VkOffset3D dstOffset = { 0, 0, region.dstOffsets[0].z };
for(int i = 0; i < numSlices; i++) VkImageSubresourceLayers srcSubresLayers =
{ {
data.source = src->getTexelPointer(srcOffset, region.srcSubresource); region.srcSubresource.aspectMask,
data.dest = dst->getTexelPointer(dstOffset, region.dstSubresource); region.srcSubresource.mipLevel,
blitFunction(&data); region.srcSubresource.baseArrayLayer,
srcOffset.z++; 1
dstOffset.z++; };
VkImageSubresourceLayers dstSubresLayers =
{
region.dstSubresource.aspectMask,
region.dstSubresource.mipLevel,
region.dstSubresource.baseArrayLayer,
1
};
VkImageSubresourceRange srcSubresRange =
{
region.srcSubresource.aspectMask,
region.srcSubresource.mipLevel,
1,
region.srcSubresource.baseArrayLayer,
region.srcSubresource.layerCount
};
uint32_t lastLayer = src->getLastLayerIndex(srcSubresRange);
for(; srcSubresLayers.baseArrayLayer <= lastLayer; srcSubresLayers.baseArrayLayer++, dstSubresLayers.baseArrayLayer++)
{
srcOffset.z = region.srcOffsets[0].z;
dstOffset.z = region.dstOffsets[0].z;
for(int i = 0; i < numSlices; i++)
{
data.source = src->getTexelPointer(srcOffset, srcSubresLayers);
data.dest = dst->getTexelPointer(dstOffset, dstSubresLayers);
ASSERT(data.source < src->end());
ASSERT(data.dest < dst->end());
blitFunction(&data);
srcOffset.z++;
dstOffset.z++;
}
} }
} }
} }
...@@ -107,7 +107,12 @@ void Buffer::update(VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* p ...@@ -107,7 +107,12 @@ void Buffer::update(VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* p
void* Buffer::getOffsetPointer(VkDeviceSize offset) const void* Buffer::getOffsetPointer(VkDeviceSize offset) const
{ {
return reinterpret_cast<char*>(memory) + offset; return reinterpret_cast<uint8_t*>(memory) + offset;
}
uint8_t* Buffer::end() const
{
return reinterpret_cast<uint8_t*>(getOffsetPointer(size + 1));
} }
} // namespace vk } // namespace vk
...@@ -37,6 +37,7 @@ public: ...@@ -37,6 +37,7 @@ public:
void fill(VkDeviceSize dstOffset, VkDeviceSize fillSize, uint32_t data); void fill(VkDeviceSize dstOffset, VkDeviceSize fillSize, uint32_t data);
void update(VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData); void update(VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData);
void* getOffsetPointer(VkDeviceSize offset) const; void* getOffsetPointer(VkDeviceSize offset) const;
uint8_t* end() const;
// DataOffset is the offset in bytes from the Buffer to the pointer to the // DataOffset is the offset in bytes from the Buffer to the pointer to the
// buffer's data memory. // buffer's data memory.
......
...@@ -129,8 +129,8 @@ void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion) ...@@ -129,8 +129,8 @@ void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion)
int srcBytesPerTexel = bytesPerTexel(srcAspect); int srcBytesPerTexel = bytesPerTexel(srcAspect);
ASSERT(srcBytesPerTexel == dst->bytesPerTexel(dstAspect)); ASSERT(srcBytesPerTexel == dst->bytesPerTexel(dstAspect));
const char* srcMem = static_cast<const char*>(getTexelPointer(pRegion.srcOffset, pRegion.srcSubresource)); const uint8_t* srcMem = static_cast<const uint8_t*>(getTexelPointer(pRegion.srcOffset, pRegion.srcSubresource));
char* dstMem = static_cast<char*>(dst->getTexelPointer(pRegion.dstOffset, pRegion.dstSubresource)); uint8_t* dstMem = static_cast<uint8_t*>(dst->getTexelPointer(pRegion.dstOffset, pRegion.dstSubresource));
int srcRowPitchBytes = rowPitchBytes(srcAspect, pRegion.srcSubresource.mipLevel); int srcRowPitchBytes = rowPitchBytes(srcAspect, pRegion.srcSubresource.mipLevel);
int srcSlicePitchBytes = slicePitchBytes(srcAspect, pRegion.srcSubresource.mipLevel); int srcSlicePitchBytes = slicePitchBytes(srcAspect, pRegion.srcSubresource.mipLevel);
...@@ -158,36 +158,53 @@ void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion) ...@@ -158,36 +158,53 @@ void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion)
if(isSingleLine) // Copy one line if(isSingleLine) // Copy one line
{ {
memcpy(dstMem, srcMem, pRegion.extent.width * srcBytesPerTexel); size_t copySize = pRegion.extent.width * srcBytesPerTexel;
ASSERT((srcMem + copySize) < end());
ASSERT((dstMem + copySize) < dst->end());
memcpy(dstMem, srcMem, copySize);
} }
else if(isEntireLine && isSinglePlane) // Copy one plane else if(isEntireLine && isSinglePlane) // Copy one plane
{ {
memcpy(dstMem, srcMem, pRegion.extent.height * srcRowPitchBytes); size_t copySize = pRegion.extent.height * srcRowPitchBytes;
ASSERT((srcMem + copySize) < end());
ASSERT((dstMem + copySize) < dst->end());
memcpy(dstMem, srcMem, copySize);
} }
else if(isEntirePlane) // Copy multiple planes else if(isEntirePlane) // Copy multiple planes
{ {
memcpy(dstMem, srcMem, pRegion.extent.depth * srcSlicePitchBytes); size_t copySize = pRegion.extent.depth * srcSlicePitchBytes;
ASSERT((srcMem + copySize) < end());
ASSERT((dstMem + copySize) < dst->end());
memcpy(dstMem, srcMem, copySize);
} }
else if(isEntireLine) // Copy plane by plane else if(isEntireLine) // Copy plane by plane
{ {
size_t copySize = pRegion.extent.height * srcRowPitchBytes;
for(uint32_t z = 0; z < pRegion.extent.depth; z++, dstMem += dstSlicePitchBytes, srcMem += srcSlicePitchBytes) for(uint32_t z = 0; z < pRegion.extent.depth; z++, dstMem += dstSlicePitchBytes, srcMem += srcSlicePitchBytes)
{ {
memcpy(dstMem, srcMem, pRegion.extent.height * srcRowPitchBytes); ASSERT((srcMem + copySize) < end());
ASSERT((dstMem + copySize) < dst->end());
memcpy(dstMem, srcMem, copySize);
} }
} }
else // Copy line by line else // Copy line by line
{ {
size_t copySize = pRegion.extent.width * srcBytesPerTexel;
for(uint32_t z = 0; z < pRegion.extent.depth; z++) for(uint32_t z = 0; z < pRegion.extent.depth; z++)
{ {
for(uint32_t y = 0; y < pRegion.extent.height; y++, dstMem += dstRowPitchBytes, srcMem += srcRowPitchBytes) for(uint32_t y = 0; y < pRegion.extent.height; y++, dstMem += dstRowPitchBytes, srcMem += srcRowPitchBytes)
{ {
memcpy(dstMem, srcMem, pRegion.extent.width * srcBytesPerTexel); ASSERT((srcMem + copySize) < end());
ASSERT((dstMem + copySize) < dst->end());
memcpy(dstMem, srcMem, copySize);
} }
} }
} }
} }
void Image::copy(VkBuffer buffer, const VkBufferImageCopy& region, bool bufferIsSource) void Image::copy(VkBuffer buf, const VkBufferImageCopy& region, bool bufferIsSource)
{ {
if(!((region.imageSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) || if(!((region.imageSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
(region.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) || (region.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
...@@ -220,67 +237,91 @@ void Image::copy(VkBuffer buffer, const VkBufferImageCopy& region, bool bufferIs ...@@ -220,67 +237,91 @@ void Image::copy(VkBuffer buffer, const VkBufferImageCopy& region, bool bufferIs
bool isEntirePlane = isEntireLine && (region.imageExtent.height == mipLevelExtent.height) && bool isEntirePlane = isEntireLine && (region.imageExtent.height == mipLevelExtent.height) &&
(imageSlicePitchBytes == bufferSlicePitchBytes); (imageSlicePitchBytes == bufferSlicePitchBytes);
VkDeviceSize layerSize = getLayerSize(aspect); Buffer* buffer = Cast(buf);
char* bufferMemory = static_cast<char*>(Cast(buffer)->getOffsetPointer(region.bufferOffset)); uint8_t* bufferMemory = static_cast<uint8_t*>(buffer->getOffsetPointer(region.bufferOffset));
char* imageMemory = static_cast<char*>(deviceMemory->getOffsetPointer( uint8_t* imageMemory = static_cast<uint8_t*>(deviceMemory->getOffsetPointer(
getMemoryOffset(aspect, region.imageSubresource.mipLevel, getMemoryOffset(aspect, region.imageSubresource.mipLevel,
region.imageSubresource.baseArrayLayer) + region.imageSubresource.baseArrayLayer) +
texelOffsetBytesInStorage(region.imageOffset, region.imageSubresource))); texelOffsetBytesInStorage(region.imageOffset, region.imageSubresource)));
char* srcMemory = bufferIsSource ? bufferMemory : imageMemory; uint8_t* srcMemory = bufferIsSource ? bufferMemory : imageMemory;
char* dstMemory = bufferIsSource ? imageMemory : bufferMemory; uint8_t* dstMemory = bufferIsSource ? imageMemory : bufferMemory;
VkDeviceSize copySize = 0; VkDeviceSize copySize = 0;
VkDeviceSize bufferLayerSize = 0;
if(isSingleLine) if(isSingleLine)
{ {
copySize = region.imageExtent.width * imageBytesPerTexel; copySize = region.imageExtent.width * imageBytesPerTexel;
bufferLayerSize = copySize;
} }
else if(isEntireLine && isSinglePlane) else if(isEntireLine && isSinglePlane)
{ {
copySize = region.imageExtent.height * imageRowPitchBytes; copySize = region.imageExtent.height * imageRowPitchBytes;
bufferLayerSize = copySize;
} }
else if(isEntirePlane) else if(isEntirePlane)
{ {
copySize = region.imageExtent.depth * imageSlicePitchBytes; // Copy multiple planes copySize = region.imageExtent.depth * imageSlicePitchBytes; // Copy multiple planes
bufferLayerSize = copySize;
} }
else if(isEntireLine) // Copy plane by plane else if(isEntireLine) // Copy plane by plane
{ {
copySize = region.imageExtent.height * imageRowPitchBytes; copySize = region.imageExtent.height * imageRowPitchBytes;
bufferLayerSize = copySize * region.imageExtent.depth;
} }
else // Copy line by line else // Copy line by line
{ {
copySize = region.imageExtent.width * imageBytesPerTexel; copySize = region.imageExtent.width * imageBytesPerTexel;
bufferLayerSize = copySize * region.imageExtent.depth * region.imageExtent.height;
} }
VkDeviceSize imageLayerSize = getLayerSize(aspect);
VkDeviceSize srcLayerSize = bufferIsSource ? bufferLayerSize : imageLayerSize;
VkDeviceSize dstLayerSize = bufferIsSource ? imageLayerSize : bufferLayerSize;
for(uint32_t i = 0; i < region.imageSubresource.layerCount; i++) for(uint32_t i = 0; i < region.imageSubresource.layerCount; i++)
{ {
if(isSingleLine || (isEntireLine && isSinglePlane) || isEntirePlane) if(isSingleLine || (isEntireLine && isSinglePlane) || isEntirePlane)
{ {
ASSERT(((bufferIsSource ? dstMemory : srcMemory) + copySize) < end());
ASSERT(((bufferIsSource ? srcMemory : dstMemory) + copySize) < buffer->end());
memcpy(dstMemory, srcMemory, copySize); memcpy(dstMemory, srcMemory, copySize);
} }
else if(isEntireLine) // Copy plane by plane else if(isEntireLine) // Copy plane by plane
{ {
uint8_t* srcPlaneMemory = srcMemory;
uint8_t* dstPlaneMemory = dstMemory;
for(uint32_t z = 0; z < region.imageExtent.depth; z++) for(uint32_t z = 0; z < region.imageExtent.depth; z++)
{ {
memcpy(dstMemory, srcMemory, copySize); ASSERT(((bufferIsSource ? dstPlaneMemory : srcPlaneMemory) + copySize) < end());
srcMemory += srcSlicePitchBytes; ASSERT(((bufferIsSource ? srcPlaneMemory : dstPlaneMemory) + copySize) < buffer->end());
dstMemory += dstSlicePitchBytes; memcpy(dstPlaneMemory, srcPlaneMemory, copySize);
srcPlaneMemory += srcSlicePitchBytes;
dstPlaneMemory += dstSlicePitchBytes;
} }
} }
else // Copy line by line else // Copy line by line
{ {
uint8_t* srcLayerMemory = srcMemory;
uint8_t* dstLayerMemory = dstMemory;
for(uint32_t z = 0; z < region.imageExtent.depth; z++) for(uint32_t z = 0; z < region.imageExtent.depth; z++)
{ {
uint8_t* srcPlaneMemory = srcLayerMemory;
uint8_t* dstPlaneMemory = dstLayerMemory;
for(uint32_t y = 0; y < region.imageExtent.height; y++) for(uint32_t y = 0; y < region.imageExtent.height; y++)
{ {
memcpy(dstMemory, srcMemory, copySize); ASSERT(((bufferIsSource ? dstPlaneMemory : srcPlaneMemory) + copySize) < end());
srcMemory += srcRowPitchBytes; ASSERT(((bufferIsSource ? srcPlaneMemory : dstPlaneMemory) + copySize) < buffer->end());
dstMemory += dstRowPitchBytes; memcpy(dstPlaneMemory, srcPlaneMemory, copySize);
srcPlaneMemory += srcRowPitchBytes;
dstPlaneMemory += dstRowPitchBytes;
} }
srcLayerMemory += srcSlicePitchBytes;
dstLayerMemory += dstSlicePitchBytes;
} }
} }
srcMemory += layerSize; srcMemory += srcLayerSize;
dstMemory += layerSize; dstMemory += dstLayerSize;
} }
} }
...@@ -305,8 +346,8 @@ VkDeviceSize Image::texelOffsetBytesInStorage(const VkOffset3D& offset, const Vk ...@@ -305,8 +346,8 @@ VkDeviceSize Image::texelOffsetBytesInStorage(const VkOffset3D& offset, const Vk
{ {
VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresource.aspectMask); VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresource.aspectMask);
return offset.z * slicePitchBytes(aspect, subresource.mipLevel) + return offset.z * slicePitchBytes(aspect, subresource.mipLevel) +
offset.y * rowPitchBytes(aspect, subresource.mipLevel) + (offset.y + (isCube() ? 1 : 0)) * rowPitchBytes(aspect, subresource.mipLevel) +
offset.x * bytesPerTexel(aspect); (offset.x + (isCube() ? 1 : 0)) * bytesPerTexel(aspect);
} }
VkExtent3D Image::getMipLevelExtent(uint32_t mipLevel) const VkExtent3D Image::getMipLevelExtent(uint32_t mipLevel) const
...@@ -396,6 +437,11 @@ bool Image::isCube() const ...@@ -396,6 +437,11 @@ bool Image::isCube() const
return (flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) && (imageType == VK_IMAGE_TYPE_2D); return (flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) && (imageType == VK_IMAGE_TYPE_2D);
} }
uint8_t* Image::end() const
{
return reinterpret_cast<uint8_t*>(deviceMemory->getOffsetPointer(deviceMemory->getCommittedMemoryInBytes() + 1));
}
VkDeviceSize Image::getMemoryOffset(VkImageAspectFlagBits aspect) const VkDeviceSize Image::getMemoryOffset(VkImageAspectFlagBits aspect) const
{ {
switch(format) switch(format)
......
...@@ -64,6 +64,7 @@ public: ...@@ -64,6 +64,7 @@ public:
int slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const; int slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
void* getTexelPointer(const VkOffset3D& offset, const VkImageSubresourceLayers& subresource) const; void* getTexelPointer(const VkOffset3D& offset, const VkImageSubresourceLayers& subresource) const;
bool isCube() const; bool isCube() const;
uint8_t* end() const;
private: private:
void copy(VkBuffer buffer, const VkBufferImageCopy& region, bool bufferIsSource); void copy(VkBuffer buffer, const VkBufferImageCopy& region, bool bufferIsSource);
......
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