OSDN Git Service

Prevent floating-point error accumulation during blitting.
authorNicolas Capens <capn@google.com>
Fri, 1 Jun 2018 14:39:50 +0000 (10:39 -0400)
committerNicolas Capens <nicolascapens@google.com>
Sat, 2 Jun 2018 01:11:57 +0000 (01:11 +0000)
The numeric imprecision can accumulate quickly and cause visible
sampling errors.

Bug chromium:848238

Change-Id: Ie41c10a0462e5b5e5c3ed5f7329ece00dab3f7f9
Reviewed-on: https://swiftshader-review.googlesource.com/19148
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
src/Common/Version.h
src/Renderer/Blitter.cpp

index ea9a476..9a28e1b 100644 (file)
@@ -15,7 +15,7 @@
 #define MAJOR_VERSION 4
 #define MINOR_VERSION 0
 #define BUILD_VERSION 0
-#define BUILD_REVISION 5
+#define BUILD_REVISION 6
 
 #define STRINGIFY(x) #x
 #define MACRO_STRINGIFY(x) STRINGIFY(x)
index c77491c..17c7199 100644 (file)
@@ -163,28 +163,26 @@ namespace sw
                        swap(sRect.y0, sRect.y1);
                }
 
-               source->lockInternal((int)sRect.x0, (int)sRect.y0, sRect.slice, sw::LOCK_READONLY, sw::PUBLIC);
-               dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, sw::LOCK_WRITEONLY, sw::PUBLIC);
+               source->lockInternal(0, 0, sRect.slice, sw::LOCK_READONLY, sw::PUBLIC);
+               dest->lockInternal(0, 0, dRect.slice, sw::LOCK_WRITEONLY, sw::PUBLIC);
 
                float w = sRect.width() / dRect.width();
                float h = sRect.height() / dRect.height();
 
-               const float xStart = sRect.x0 + 0.5f * w;
-               float y = sRect.y0 + 0.5f * h;
+               float xStart = sRect.x0 + (0.5f - dRect.x0) * w;
+               float yStart = sRect.y0 + (0.5f - dRect.y0) * h;
 
                for(int j = dRect.y0; j < dRect.y1; j++)
                {
-                       float x = xStart;
+                       float y = yStart + j * h;
 
                        for(int i = dRect.x0; i < dRect.x1; i++)
                        {
+                               float x = xStart + i * w;
+
                                // FIXME: Support RGBA mask
                                dest->copyInternal(source, i, j, x, y, options.filter);
-
-                               x += w;
                        }
-
-                       y += h;
                }
 
                source->unlockInternal();
@@ -200,21 +198,21 @@ namespace sw
                float h = static_cast<float>(source->getHeight()) / static_cast<float>(dest->getHeight());
                float d = static_cast<float>(source->getDepth())  / static_cast<float>(dest->getDepth());
 
-               float z = 0.5f * d;
                for(int k = 0; k < dest->getDepth(); k++)
                {
-                       float y = 0.5f * h;
+                       float z = (k + 0.5f) * d;
+
                        for(int j = 0; j < dest->getHeight(); j++)
                        {
-                               float x = 0.5f * w;
+                               float y = (j + 0.5f) * h;
+
                                for(int i = 0; i < dest->getWidth(); i++)
                                {
+                                       float x = (i + 0.5f) * w;
+
                                        dest->copyInternal(source, i, j, k, x, y, z, true);
-                                       x += w;
                                }
-                               y += h;
                        }
-                       z += d;
                }
 
                source->unlockInternal();
@@ -1237,15 +1235,14 @@ namespace sw
                                }
                        }
 
-                       Float y = y0;
-
                        For(Int j = y0d, j < y1d, j++)
                        {
-                               Float x = x0;
+                               Float y = state.clearOperation ? y0 : y0 + Float(j) * h;
                                Pointer<Byte> destLine = dest + (dstQuadLayout ? j & Int(~1) : RValue<Int>(j)) * dPitchB;
 
                                For(Int i = x0d, i < x1d, i++)
                                {
+                                       Float x = state.clearOperation ? x0 : x0 + Float(i) * w;
                                        Pointer<Byte> d = destLine + (dstQuadLayout ? (((j & Int(1)) << 1) + (i * 2) - (i & Int(1))) : RValue<Int>(i)) * dstBytes;
 
                                        if(hasConstantColorI)
@@ -1379,11 +1376,7 @@ namespace sw
                                                        d += *Pointer<Int>(blit + OFFSET(BlitData,dSliceB));
                                                }
                                        }
-
-                                       if(!state.clearOperation) { x += w; }
                                }
-
-                               if(!state.clearOperation) { y += h; }
                        }
                }
 
@@ -1456,8 +1449,8 @@ namespace sw
 
                data.w = sRect.width() / dRect.width();
                data.h = sRect.height() / dRect.height();
-               data.x0 = sRect.x0 + 0.5f * data.w;
-               data.y0 = sRect.y0 + 0.5f * data.h;
+               data.x0 = sRect.x0 + (0.5f - dRect.x0) * data.w;
+               data.y0 = sRect.y0 + (0.5f - dRect.y0) * data.h;
 
                data.x0d = dRect.x0;
                data.x1d = dRect.x1;