Implement seamless cubemap sampling. The addressing is offset by 1 to account for the border. Note that this could be avoided by locking at (0, 0) instead of (-1, -1) instead, but then negative address offsets have to be allowed and this complicates the subsequent calculations and only unsigned extension from 32-bit to 64-bit is typically for free during memory accesses. Change-Id: I5fb843401d440a9d77d141782124a9c260765830 Reviewed-on: https://swiftshader-review.googlesource.com/13289 Tested-by: Nicolas Capens <nicolascapens@google.com> Reviewed-by: Alexis Hétu <sugoi@google.com> Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Renderer/Sampler.cpp b/src/Renderer/Sampler.cpp index 71a6eaf..5862996 100644 --- a/src/Renderer/Sampler.cpp +++ b/src/Renderer/Sampler.cpp
@@ -61,6 +61,7 @@ sRGB = false; gather = false; highPrecisionFiltering = false; + border = 0; swizzleR = SWIZZLE_RED; swizzleG = SWIZZLE_GREEN; @@ -117,7 +118,8 @@ { Mipmap &mipmap = texture.mipmap[level]; - mipmap.buffer[face] = surface->lockInternal(0, 0, 0, LOCK_UNLOCKED, PRIVATE); + border = surface->getBorder(); + mipmap.buffer[face] = surface->lockInternal(-border, -border, 0, LOCK_UNLOCKED, PRIVATE); if(face == 0) { @@ -456,7 +458,7 @@ { if(textureType == TEXTURE_CUBE) { - return ADDRESSING_CLAMP; + return border ? ADDRESSING_SEAMLESS : ADDRESSING_CLAMP; } return addressingModeU; @@ -466,7 +468,7 @@ { if(textureType == TEXTURE_CUBE) { - return ADDRESSING_CLAMP; + return border ? ADDRESSING_SEAMLESS : ADDRESSING_CLAMP; } return addressingModeV;
diff --git a/src/Renderer/Sampler.hpp b/src/Renderer/Sampler.hpp index ad2145c..9918acf 100644 --- a/src/Renderer/Sampler.hpp +++ b/src/Renderer/Sampler.hpp
@@ -103,7 +103,8 @@ ADDRESSING_CLAMP, ADDRESSING_MIRROR, ADDRESSING_MIRRORONCE, - ADDRESSING_BORDER, + ADDRESSING_BORDER, // Single color + ADDRESSING_SEAMLESS, // Border of pixels ADDRESSING_LAYER, ADDRESSING_TEXELFETCH, @@ -224,6 +225,7 @@ bool sRGB; bool gather; bool highPrecisionFiltering; + int border; SwizzleType swizzleR; SwizzleType swizzleG;
diff --git a/src/Shader/SamplerCore.cpp b/src/Shader/SamplerCore.cpp index 1c97628..942cf87 100644 --- a/src/Shader/SamplerCore.cpp +++ b/src/Shader/SamplerCore.cpp
@@ -316,7 +316,8 @@ { // FIXME: YUV and sRGB are not supported by the floating point path bool forceFloatFiltering = state.highPrecisionFiltering && !state.sRGB && !hasYuvFormat() && (state.textureFilter != FILTER_POINT); - if(hasFloatTexture() || hasUnnormalizedIntegerTexture() || forceFloatFiltering) // FIXME: Mostly identical to integer sampling + bool seamlessCube = (state.addressingModeU == ADDRESSING_SEAMLESS); + if(hasFloatTexture() || hasUnnormalizedIntegerTexture() || forceFloatFiltering || seamlessCube) // FIXME: Mostly identical to integer sampling { Float4 uuuu = u; Float4 vvvv = v; @@ -1666,7 +1667,7 @@ M = Max(Max(absX, absY), absZ); - // U = xMajor ? (neg ^ -z) : (zMajor & neg) ^ x) + // U = xMajor ? (neg ^ -z) : ((zMajor & neg) ^ x) U = As<Float4>((xMajor & (n ^ As<Int4>(-z))) | (~xMajor & ((zMajor & n) ^ As<Int4>(x)))); // V = !yMajor ? -y : (n ^ z) @@ -1695,6 +1696,8 @@ break; case ADDRESSING_TEXELFETCH: break; + case AddressingMode::ADDRESSING_SEAMLESS: + ASSERT(false); // Cube sampling doesn't support offset. default: ASSERT(false); } @@ -2388,11 +2391,20 @@ const int oneBits = 0x3F7FFFFF; // Value just under 1.0f const int twoBits = 0x3FFFFFFF; // Value just under 2.0f + bool pointFilter = state.textureFilter == FILTER_POINT || + state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR || + state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT; + Float4 coord = uvw; + switch(addressingMode) { case ADDRESSING_CLAMP: case ADDRESSING_BORDER: + case ADDRESSING_SEAMLESS: + // Linear filtering of cube doesn't require clamping because the coordinates + // are already in [0, 1] range and numerical imprecision is tolerated. + if(addressingMode != ADDRESSING_SEAMLESS || pointFilter) { Float4 one = As<Float4>(Int4(oneBits)); coord = Min(Max(coord, Float4(0.0f)), one); @@ -2448,12 +2460,19 @@ xyz0 += As<Int4>(texOffset); } + if(addressingMode == ADDRESSING_SEAMLESS) + { + xyz0 += Int4(1); + } + xyz1 = xyz0 - filter; // Increment if(function.option == Offset) { switch(addressingMode) { + case ADDRESSING_SEAMLESS: + ASSERT(false); // Cube sampling doesn't support offset. case ADDRESSING_MIRROR: case ADDRESSING_MIRRORONCE: case ADDRESSING_BORDER: @@ -2473,6 +2492,8 @@ { switch(addressingMode) { + case ADDRESSING_SEAMLESS: + break; case ADDRESSING_MIRROR: case ADDRESSING_MIRRORONCE: case ADDRESSING_BORDER: