Fixed erroneous filtering
Even if all the coordinates are within the bounds, if filtering is
enabled and the coordinates are closer to the edge than the center
of the pixel, we have to enable clamping to the edge so that the
samples used for filtering don't get invalid/negative factors.
Bug b/119620767 b/129258757
Change-Id: I0ba50fff2c2873e4a852e34878883c2e707d9886
Tests: dEQP-VK.api.copy_and_blit.core.blit_image.simple_tests.scaling_whole2.*
Tests: dEQP-VK.api.copy_and_blit.dedicated_allocation.blit_image.simple_tests.scaling_whole2.*
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27808
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Device/Blitter.cpp b/src/Device/Blitter.cpp
index 06aa87d..9f59d88 100644
--- a/src/Device/Blitter.cpp
+++ b/src/Device/Blitter.cpp
@@ -1543,12 +1543,21 @@
VkImageAspectFlagBits srcAspect = static_cast<VkImageAspectFlagBits>(region.srcSubresource.aspectMask);
VkImageAspectFlagBits dstAspect = static_cast<VkImageAspectFlagBits>(region.dstSubresource.aspectMask);
+ float widthRatio = static_cast<float>(region.srcOffsets[1].x - region.srcOffsets[0].x) /
+ static_cast<float>(region.dstOffsets[1].x - region.dstOffsets[0].x);
+ float heightRatio = static_cast<float>(region.srcOffsets[1].y - region.srcOffsets[0].y) /
+ static_cast<float>(region.dstOffsets[1].y - region.dstOffsets[0].y);
+ float x0 = region.srcOffsets[0].x + (0.5f - region.dstOffsets[0].x) * widthRatio;
+ float y0 = region.srcOffsets[0].y + (0.5f - region.dstOffsets[0].y) * heightRatio;
+
+ bool doFilter = (filter != VK_FILTER_NEAREST);
State state(src->getFormat(srcAspect), dst->getFormat(dstAspect), dst->getSampleCountFlagBits(),
- { filter != VK_FILTER_NEAREST, srcAspect == VK_IMAGE_ASPECT_STENCIL_BIT, filter != VK_FILTER_NEAREST });
+ { doFilter, srcAspect == VK_IMAGE_ASPECT_STENCIL_BIT, doFilter });
state.clampToEdge = (region.srcOffsets[0].x < 0) ||
(region.srcOffsets[0].y < 0) ||
(static_cast<uint32_t>(region.srcOffsets[1].x) > srcExtent.width) ||
- (static_cast<uint32_t>(region.srcOffsets[1].y) > srcExtent.height);
+ (static_cast<uint32_t>(region.srcOffsets[1].y) > srcExtent.height) ||
+ (doFilter && ((x0 < 0.5f) || (y0 < 0.5f)));
Routine *blitRoutine = getRoutine(state);
if(!blitRoutine)
@@ -1558,26 +1567,27 @@
void(*blitFunction)(const BlitData *data) = (void(*)(const BlitData*))blitRoutine->getEntry();
- BlitData data;
+ BlitData data =
+ {
+ nullptr, // source
+ nullptr, // dest
+ src->rowPitchBytes(srcAspect, region.srcSubresource.mipLevel), // sPitchB
+ dst->rowPitchBytes(dstAspect, region.dstSubresource.mipLevel), // dPitchB
+ dst->slicePitchBytes(dstAspect, region.dstSubresource.mipLevel), // dSliceB
- data.sPitchB = src->rowPitchBytes(srcAspect, region.srcSubresource.mipLevel);
- data.dPitchB = dst->rowPitchBytes(dstAspect, region.dstSubresource.mipLevel);
- data.dSliceB = dst->slicePitchBytes(dstAspect, region.dstSubresource.mipLevel);
+ x0,
+ y0,
+ widthRatio,
+ heightRatio,
- data.w = static_cast<float>(region.srcOffsets[1].x - region.srcOffsets[0].x) /
- static_cast<float>(region.dstOffsets[1].x - region.dstOffsets[0].x);
- data.h = static_cast<float>(region.srcOffsets[1].y - region.srcOffsets[0].y) /
- static_cast<float>(region.dstOffsets[1].y - region.dstOffsets[0].y);
- data.x0 = region.srcOffsets[0].x + (0.5f - region.dstOffsets[0].x) * data.w;
- data.y0 = region.srcOffsets[0].y + (0.5f - region.dstOffsets[0].y) * data.h;
+ region.dstOffsets[0].y, // y0d
+ region.dstOffsets[1].y, // y1d
+ region.dstOffsets[0].x, // x0d
+ region.dstOffsets[1].x, // x1d
- data.x0d = region.dstOffsets[0].x;
- data.x1d = region.dstOffsets[1].x;
- data.y0d = region.dstOffsets[0].y;
- data.y1d = region.dstOffsets[1].y;
-
- data.sWidth = srcExtent.width;
- data.sHeight = srcExtent.height;
+ static_cast<int>(srcExtent.width), // sWidth
+ static_cast<int>(srcExtent.height) // sHeight;
+ };
VkOffset3D srcOffset = { 0, 0, region.srcOffsets[0].z };
VkOffset3D dstOffset = { 0, 0, region.dstOffsets[0].z };