Refactor high-precision texture coordinate addressing. Uses 0, -1 offsets instead of 0, 1 to be able to use it as a mask. Optimize calculation of the integer coordinates and fraction by always having xyz1 = xyz0 + 1 (before wrap). Optimize the clamping/wrapping of the integer coordinates. Skip addressing operation of the third component for cube sampling (since already projected to 2D face). Change-Id: If2e7c74aac9ae923a0c1ffc278fcdfec00f216f3 Reviewed-on: https://swiftshader-review.googlesource.com/14269 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 5bf11c8..71a6eaf 100644 --- a/src/Renderer/Sampler.cpp +++ b/src/Renderer/Sampler.cpp
@@ -454,7 +454,7 @@ AddressingMode Sampler::getAddressingModeU() const { - if(hasCubeTexture()) + if(textureType == TEXTURE_CUBE) { return ADDRESSING_CLAMP; } @@ -464,7 +464,7 @@ AddressingMode Sampler::getAddressingModeV() const { - if(hasCubeTexture()) + if(textureType == TEXTURE_CUBE) { return ADDRESSING_CLAMP; } @@ -474,12 +474,9 @@ AddressingMode Sampler::getAddressingModeW() const { - if(hasCubeTexture()) - { - return ADDRESSING_CLAMP; - } - - if(textureType == TEXTURE_2D_ARRAY || textureType == TEXTURE_2D) + if(textureType == TEXTURE_2D_ARRAY || + textureType == TEXTURE_2D || + textureType == TEXTURE_CUBE) { return ADDRESSING_LAYER; }
diff --git a/src/Shader/SamplerCore.cpp b/src/Shader/SamplerCore.cpp index 4255f80..b2da001 100644 --- a/src/Shader/SamplerCore.cpp +++ b/src/Shader/SamplerCore.cpp
@@ -1267,9 +1267,9 @@ Int4 x0, x1, y0, y1, z0; Float4 fu, fv; Int4 filter = computeFilterOffset(lod); - address(w, z0, z0, fv, mipmap, offset.z, filter, OFFSET(Mipmap, depth), state.addressingModeW, function); - address(v, y0, y1, fv, mipmap, offset.y, filter, OFFSET(Mipmap, height), state.addressingModeV, function); address(u, x0, x1, fu, mipmap, offset.x, filter, OFFSET(Mipmap, width), state.addressingModeU, function); + address(v, y0, y1, fv, mipmap, offset.y, filter, OFFSET(Mipmap, height), state.addressingModeV, function); + address(w, z0, z0, fv, mipmap, offset.z, filter, OFFSET(Mipmap, depth), state.addressingModeW, function); Int4 pitchP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, pitchP), 16); y0 *= pitchP; @@ -2304,20 +2304,25 @@ Int4 SamplerCore::computeFilterOffset(Float &lod) { - Int4 filtering((state.textureFilter == FILTER_POINT) ? 0 : 1); - if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT) + Int4 filter = -1; + + if(state.textureFilter == FILTER_POINT) { - filtering &= CmpNLE(Float4(lod), Float4(0.0f)); + filter = 0; + } + else if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT) + { + filter = CmpNLE(Float4(lod), Float4(0.0f)); } else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR) { - filtering &= CmpLE(Float4(lod), Float4(0.0f)); + filter = CmpLE(Float4(lod), Float4(0.0f)); } - return filtering; + return filter; } - Short4 SamplerCore::address(Float4 &uw, AddressingMode addressingMode, Pointer<Byte>& mipmap) + Short4 SamplerCore::address(Float4 &uw, AddressingMode addressingMode, Pointer<Byte> &mipmap) { if(addressingMode == ADDRESSING_LAYER && state.textureType != TEXTURE_2D_ARRAY) { @@ -2359,11 +2364,11 @@ } } - void SamplerCore::address(Float4 &uvw, Int4& xyz0, Int4& xyz1, Float4& f, Pointer<Byte>& mipmap, Float4 &texOffset, Int4 &filter, int whd, AddressingMode addressingMode, SamplerFunction function) + void SamplerCore::address(Float4 &uvw, Int4 &xyz0, Int4 &xyz1, Float4 &f, Pointer<Byte> &mipmap, Float4 &texOffset, Int4 &filter, int whd, AddressingMode addressingMode, SamplerFunction function) { if(addressingMode == ADDRESSING_LAYER && state.textureType != TEXTURE_2D_ARRAY) { - return; // Unused + return; // Unused } Int4 dim = Int4(*Pointer<Short4>(mipmap + whd, 16)); @@ -2373,23 +2378,23 @@ { xyz0 = Min(Max(((function.option == Offset) && (addressingMode != ADDRESSING_LAYER)) ? As<Int4>(uvw) + As<Int4>(texOffset) : As<Int4>(uvw), Int4(0)), maxXYZ); } - else if(addressingMode == ADDRESSING_LAYER && state.textureType == TEXTURE_2D_ARRAY) // Note: Offset does not apply to array layers + else if(addressingMode == ADDRESSING_LAYER && state.textureType == TEXTURE_2D_ARRAY) // Note: Offset does not apply to array layers { xyz0 = Min(Max(RoundInt(uvw), Int4(0)), maxXYZ); } else { - const int halfBits = 0x3effffff; // Value just under 0.5f - const int oneBits = 0x3f7fffff; // Value just under 1.0f - const int twoBits = 0x3fffffff; // Value just under 2.0f + const int halfBits = 0x3EFFFFFF; // Value just under 0.5f + const int oneBits = 0x3F7FFFFF; // Value just under 1.0f + const int twoBits = 0x3FFFFFFF; // Value just under 2.0f - Float4 coord = Float4(dim); + Float4 coord = uvw; switch(addressingMode) { case ADDRESSING_CLAMP: { Float4 one = As<Float4>(Int4(oneBits)); - coord *= Min(Max(uvw, Float4(0.0f)), one); + coord = Min(Max(coord, Float4(0.0f)), one); } break; case ADDRESSING_MIRROR: @@ -2397,7 +2402,7 @@ Float4 half = As<Float4>(Int4(halfBits)); Float4 one = As<Float4>(Int4(oneBits)); Float4 two = As<Float4>(Int4(twoBits)); - coord *= one - Abs(two * Frac(uvw * half) - one); + coord = one - Abs(two * Frac(coord * half) - one); } break; case ADDRESSING_MIRRORONCE: @@ -2405,66 +2410,82 @@ Float4 half = As<Float4>(Int4(halfBits)); Float4 one = As<Float4>(Int4(oneBits)); Float4 two = As<Float4>(Int4(twoBits)); - coord *= one - Abs(two * Frac(Min(Max(uvw, -one), two) * half) - one); + coord = one - Abs(two * Frac(Min(Max(coord, -one), two) * half) - one); } break; default: // Wrap (or border) - coord *= Frac(uvw); + coord = Frac(coord); break; } - xyz0 = Int4(coord); + coord = coord * Float4(dim); + + if(state.textureFilter == FILTER_POINT || + state.textureFilter == FILTER_GATHER) + { + xyz0 = Int4(coord); + } + else + { + if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR || + state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT) + { + coord -= As<Float4>(As<Int4>(Float4(0.5f)) & filter); + } + else + { + coord -= Float4(0.5f); + } + + Float4 floor = Floor(coord); + xyz0 = Int4(floor); + f = coord - floor; + } if(function.option == Offset) { xyz0 += As<Int4>(texOffset); + } + + xyz1 = xyz0 - filter; // Increment + + if(function.option == Offset) + { switch(addressingMode) { case ADDRESSING_MIRROR: case ADDRESSING_MIRRORONCE: case ADDRESSING_BORDER: - // FIXME: Implement ADDRESSING_MIRROR, ADDRESSING_MIRRORONCE and ADDRESSING_BORDER. Fall through to Clamp. + // FIXME: Implement ADDRESSING_MIRROR, ADDRESSING_MIRRORONCE, and ADDRESSING_BORDER. + // Fall through to Clamp. case ADDRESSING_CLAMP: xyz0 = Min(Max(xyz0, Int4(0)), maxXYZ); + xyz1 = Min(Max(xyz1, Int4(0)), maxXYZ); break; default: // Wrap xyz0 = (xyz0 + dim * Int4(-MIN_PROGRAM_TEXEL_OFFSET)) % dim; + xyz1 = (xyz1 + dim * Int4(-MIN_PROGRAM_TEXEL_OFFSET)) % dim; break; } } - - if(state.textureFilter != FILTER_POINT) // Compute 2nd coordinate, if needed + else if(state.textureFilter != FILTER_POINT) { - bool gather = state.textureFilter == FILTER_GATHER; - - xyz1 = xyz0 + filter; // Increment - - if(!gather) - { - Float4 frac = Frac(coord); - f = Abs(frac - Float4(0.5f)); - xyz1 -= CmpLT(frac, Float4(0.5f)) & (filter + filter); // Decrement xyz if necessary - } - switch(addressingMode) { case ADDRESSING_MIRROR: case ADDRESSING_MIRRORONCE: case ADDRESSING_BORDER: - // FIXME: Implement ADDRESSING_MIRROR, ADDRESSING_MIRRORONCE and ADDRESSING_BORDER. Fall through to Clamp. case ADDRESSING_CLAMP: - xyz1 = gather ? Min(xyz1, maxXYZ) : Min(Max(xyz1, Int4(0)), maxXYZ); + xyz0 = Max(xyz0, Int4(0)); + xyz1 = Min(xyz1, maxXYZ); break; default: // Wrap { - // The coordinates overflow or underflow by at most 1 - Int4 over = CmpNLT(xyz1, dim); - xyz1 = (over & Int4(0)) | (~over & xyz1); // xyz >= dim ? 0 : xyz - if(!gather) - { - Int4 under = CmpLT(xyz1, Int4(0)); - xyz1 = (under & maxXYZ) | (~under & xyz1); // xyz < 0 ? dim - 1 : xyz - } + Int4 under = CmpLT(xyz0, Int4(0)); + xyz0 = (under & maxXYZ) | (~under & xyz0); // xyz < 0 ? dim - 1 : xyz // FIXME: IfThenElse() + + Int4 nover = CmpLT(xyz1, dim); + xyz1 = nover & xyz1; // xyz >= dim ? 0 : xyz } break; }