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
return;
}
if((region.srcSubresource.baseArrayLayer != 0) ||
(region.dstSubresource.baseArrayLayer != 0) ||
(region.srcSubresource.layerCount != 1) ||
(region.dstSubresource.layerCount != 1) ||
if((region.srcSubresource.layerCount != region.dstSubresource.layerCount) ||
(region.srcSubresource.aspectMask != region.dstSubresource.aspectMask))
{
UNIMPLEMENTED();
......@@ -1545,7 +1542,7 @@ namespace sw
VkImageAspectFlagBits dstAspect = static_cast<VkImageAspectFlagBits>(region.dstSubresource.aspectMask);
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) ||
(region.srcOffsets[0].y < 0) ||
(static_cast<uint32_t>(region.srcOffsets[1].x) > srcExtent.width) ||
......@@ -1583,13 +1580,50 @@ namespace sw
VkOffset3D srcOffset = { 0, 0, region.srcOffsets[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);
data.dest = dst->getTexelPointer(dstOffset, region.dstSubresource);
blitFunction(&data);
srcOffset.z++;
dstOffset.z++;
region.srcSubresource.aspectMask,
region.srcSubresource.mipLevel,
region.srcSubresource.baseArrayLayer,
1
};
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
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
......@@ -37,6 +37,7 @@ public:
void fill(VkDeviceSize dstOffset, VkDeviceSize fillSize, uint32_t data);
void update(VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData);
void* getOffsetPointer(VkDeviceSize offset) const;
uint8_t* end() const;
// DataOffset is the offset in bytes from the Buffer to the pointer to the
// buffer's data memory.
......
......@@ -129,8 +129,8 @@ void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion)
int srcBytesPerTexel = bytesPerTexel(srcAspect);
ASSERT(srcBytesPerTexel == dst->bytesPerTexel(dstAspect));
const char* srcMem = static_cast<const char*>(getTexelPointer(pRegion.srcOffset, pRegion.srcSubresource));
char* dstMem = static_cast<char*>(dst->getTexelPointer(pRegion.dstOffset, pRegion.dstSubresource));
const uint8_t* srcMem = static_cast<const uint8_t*>(getTexelPointer(pRegion.srcOffset, pRegion.srcSubresource));
uint8_t* dstMem = static_cast<uint8_t*>(dst->getTexelPointer(pRegion.dstOffset, pRegion.dstSubresource));
int srcRowPitchBytes = rowPitchBytes(srcAspect, pRegion.srcSubresource.mipLevel);
int srcSlicePitchBytes = slicePitchBytes(srcAspect, pRegion.srcSubresource.mipLevel);
......@@ -158,36 +158,53 @@ void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion)
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
{
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
{
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
{
size_t copySize = pRegion.extent.height * srcRowPitchBytes;
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
{
size_t copySize = pRegion.extent.width * srcBytesPerTexel;
for(uint32_t z = 0; z < pRegion.extent.depth; z++)
{
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) ||
(region.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
......@@ -220,67 +237,91 @@ void Image::copy(VkBuffer buffer, const VkBufferImageCopy& region, bool bufferIs
bool isEntirePlane = isEntireLine && (region.imageExtent.height == mipLevelExtent.height) &&
(imageSlicePitchBytes == bufferSlicePitchBytes);
VkDeviceSize layerSize = getLayerSize(aspect);
char* bufferMemory = static_cast<char*>(Cast(buffer)->getOffsetPointer(region.bufferOffset));
char* imageMemory = static_cast<char*>(deviceMemory->getOffsetPointer(
getMemoryOffset(aspect, region.imageSubresource.mipLevel,
region.imageSubresource.baseArrayLayer) +
texelOffsetBytesInStorage(region.imageOffset, region.imageSubresource)));
char* srcMemory = bufferIsSource ? bufferMemory : imageMemory;
char* dstMemory = bufferIsSource ? imageMemory : bufferMemory;
Buffer* buffer = Cast(buf);
uint8_t* bufferMemory = static_cast<uint8_t*>(buffer->getOffsetPointer(region.bufferOffset));
uint8_t* imageMemory = static_cast<uint8_t*>(deviceMemory->getOffsetPointer(
getMemoryOffset(aspect, region.imageSubresource.mipLevel,
region.imageSubresource.baseArrayLayer) +
texelOffsetBytesInStorage(region.imageOffset, region.imageSubresource)));
uint8_t* srcMemory = bufferIsSource ? bufferMemory : imageMemory;
uint8_t* dstMemory = bufferIsSource ? imageMemory : bufferMemory;
VkDeviceSize copySize = 0;
VkDeviceSize bufferLayerSize = 0;
if(isSingleLine)
{
copySize = region.imageExtent.width * imageBytesPerTexel;
bufferLayerSize = copySize;
}
else if(isEntireLine && isSinglePlane)
{
copySize = region.imageExtent.height * imageRowPitchBytes;
bufferLayerSize = copySize;
}
else if(isEntirePlane)
{
copySize = region.imageExtent.depth * imageSlicePitchBytes; // Copy multiple planes
bufferLayerSize = copySize;
}
else if(isEntireLine) // Copy plane by plane
{
copySize = region.imageExtent.height * imageRowPitchBytes;
bufferLayerSize = copySize * region.imageExtent.depth;
}
else // Copy line by line
{
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++)
{
if(isSingleLine || (isEntireLine && isSinglePlane) || isEntirePlane)
{
ASSERT(((bufferIsSource ? dstMemory : srcMemory) + copySize) < end());
ASSERT(((bufferIsSource ? srcMemory : dstMemory) + copySize) < buffer->end());
memcpy(dstMemory, srcMemory, copySize);
}
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++)
{
memcpy(dstMemory, srcMemory, copySize);
srcMemory += srcSlicePitchBytes;
dstMemory += dstSlicePitchBytes;
ASSERT(((bufferIsSource ? dstPlaneMemory : srcPlaneMemory) + copySize) < end());
ASSERT(((bufferIsSource ? srcPlaneMemory : dstPlaneMemory) + copySize) < buffer->end());
memcpy(dstPlaneMemory, srcPlaneMemory, copySize);
srcPlaneMemory += srcSlicePitchBytes;
dstPlaneMemory += dstSlicePitchBytes;
}
}
else // Copy line by line
{
uint8_t* srcLayerMemory = srcMemory;
uint8_t* dstLayerMemory = dstMemory;
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++)
{
memcpy(dstMemory, srcMemory, copySize);
srcMemory += srcRowPitchBytes;
dstMemory += dstRowPitchBytes;
ASSERT(((bufferIsSource ? dstPlaneMemory : srcPlaneMemory) + copySize) < end());
ASSERT(((bufferIsSource ? srcPlaneMemory : dstPlaneMemory) + copySize) < buffer->end());
memcpy(dstPlaneMemory, srcPlaneMemory, copySize);
srcPlaneMemory += srcRowPitchBytes;
dstPlaneMemory += dstRowPitchBytes;
}
srcLayerMemory += srcSlicePitchBytes;
dstLayerMemory += dstSlicePitchBytes;
}
}
srcMemory += layerSize;
dstMemory += layerSize;
srcMemory += srcLayerSize;
dstMemory += dstLayerSize;
}
}
......@@ -305,8 +346,8 @@ VkDeviceSize Image::texelOffsetBytesInStorage(const VkOffset3D& offset, const Vk
{
VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresource.aspectMask);
return offset.z * slicePitchBytes(aspect, subresource.mipLevel) +
offset.y * rowPitchBytes(aspect, subresource.mipLevel) +
offset.x * bytesPerTexel(aspect);
(offset.y + (isCube() ? 1 : 0)) * rowPitchBytes(aspect, subresource.mipLevel) +
(offset.x + (isCube() ? 1 : 0)) * bytesPerTexel(aspect);
}
VkExtent3D Image::getMipLevelExtent(uint32_t mipLevel) const
......@@ -396,6 +437,11 @@ bool Image::isCube() const
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
{
switch(format)
......
......@@ -64,6 +64,7 @@ public:
int slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
void* getTexelPointer(const VkOffset3D& offset, const VkImageSubresourceLayers& subresource) const;
bool isCube() const;
uint8_t* end() const;
private:
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