Fix cube texture gradient calculation.
Cube texture sampling functions which take explicit gradients require
the gradients to divided by the same factor used to project the texture
coordinates onto the cube. Previously we assumed they were already in
the projected coordinate space.
Change-Id: I2825df17bee74b551b8d7491c050b7766653a65c
Reviewed-on: https://swiftshader-review.googlesource.com/13552
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Shader/SamplerCore.cpp b/src/Shader/SamplerCore.cpp
index ca06b5c..e6d9d44 100644
--- a/src/Shader/SamplerCore.cpp
+++ b/src/Shader/SamplerCore.cpp
@@ -74,11 +74,6 @@
}
#endif
- Float4 uuuu = u;
- Float4 vvvv = v;
- Float4 wwww = w;
- Float4 qqqq = q;
-
if(state.textureType == TEXTURE_NULL)
{
c.x = Short4(0x0000);
@@ -96,16 +91,12 @@
}
else
{
+ Float4 uuuu = u;
+ Float4 vvvv = v;
+ Float4 wwww = w;
+ Float4 qqqq = q;
+
Int face[4];
- Float4 lodX;
- Float4 lodY;
- Float4 lodZ;
-
- if(state.textureType == TEXTURE_CUBE)
- {
- cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w);
- }
-
Float lod;
Float anisotropy;
Float4 uDelta;
@@ -119,7 +110,9 @@
}
else
{
- computeLodCube(texture, lod, lodX, lodY, lodZ, bias.x, dsx, dsy, function);
+ Float4 M;
+ cubeFace(face, uuuu, vvvv, u, v, w, M);
+ computeLodCube(texture, lod, u, v, w, bias.x, dsx, dsy, M, function);
}
}
else
@@ -331,15 +324,6 @@
Float4 qqqq = q;
Int face[4];
- Float4 lodX;
- Float4 lodY;
- Float4 lodZ;
-
- if(state.textureType == TEXTURE_CUBE)
- {
- cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w);
- }
-
Float lod;
Float anisotropy;
Float4 uDelta;
@@ -353,7 +337,9 @@
}
else
{
- computeLodCube(texture, lod, lodX, lodY, lodZ, bias.x, dsx, dsy, function);
+ Float4 M;
+ cubeFace(face, uuuu, vvvv, u, v, w, M);
+ computeLodCube(texture, lod, u, v, w, bias.x, dsx, dsy, M, function);
}
}
else
@@ -1500,46 +1486,51 @@
lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
}
- void SamplerCore::computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &s, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
+ void SamplerCore::computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, Float4 &M, SamplerFunction function)
{
if(function != Lod && function != Fetch)
{
+ Float4 dudxy, dvdxy, dsdxy;
+
if(function != Grad)
{
- Float4 dudxy = u.ywyw - u;
- Float4 dvdxy = v.ywyw - v;
- Float4 dsdxy = s.ywyw - s;
+ Float4 U = u * M;
+ Float4 V = v * M;
+ Float4 W = w * M;
- // Scale by texture dimensions and LOD
- dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
- dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
- dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
-
- dudxy *= dudxy;
- dvdxy *= dvdxy;
- dsdxy *= dsdxy;
-
- dudxy += dvdxy;
- dudxy += dsdxy;
-
- lod = Max(Float(dudxy.x), Float(dudxy.y)); // FIXME: Max(dudxy.x, dudxy.y);
+ dudxy = U.ywyw - U;
+ dvdxy = V.ywyw - V;
+ dsdxy = W.ywyw - W;
}
else
{
- Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
- Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
+ dudxy = Float4(dsx.x.xx, dsy.x.xx);
+ dvdxy = Float4(dsx.y.xx, dsy.y.xx);
+ dsdxy = Float4(dsx.z.xx, dsy.z.xx);
- Float4 duvdxy = Float4(dudxy.xz, dvdxy.xz);
+ dudxy = Float4(dudxy.xz, dudxy.xz);
+ dvdxy = Float4(dvdxy.xz, dvdxy.xz);
+ dsdxy = Float4(dsdxy.xz, dsdxy.xz);
- // Scale by texture dimensions and LOD
- Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
-
- Float4 dUV2dxy = dUVdxy * dUVdxy;
- Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
-
- lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis
+ dudxy *= Float4(M.x);
+ dvdxy *= Float4(M.x);
+ dsdxy *= Float4(M.x);
}
+ // Scale by texture dimensions and LOD
+ dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
+ dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
+ dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
+
+ dudxy *= dudxy;
+ dvdxy *= dvdxy;
+ dsdxy *= dsdxy;
+
+ dudxy += dvdxy;
+ dudxy += dsdxy;
+
+ lod = Max(Float(dudxy.x), Float(dudxy.y)); // FIXME: Max(dudxy.x, dudxy.y);
+
lod = log2sqrt(lod); // log2(sqrt(lod))
if(function == Bias)
@@ -1635,7 +1626,7 @@
}
}
- void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodX, Float4 &lodY, Float4 &lodZ, Float4 &x, Float4 &y, Float4 &z)
+ void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &x, Float4 &y, Float4 &z, Float4 &M)
{
Int4 xn = CmpLT(x, Float4(0.0f)); // x < 0
Int4 yn = CmpLT(y, Float4(0.0f)); // y < 0
@@ -1673,7 +1664,7 @@
face[3] = (face[0] >> 12) & 0x7;
face[0] &= 0x7;
- Float4 M = Max(Max(absX, absY), absZ);
+ M = Max(Max(absX, absY), absZ);
// U = xMajor ? (neg ^ -z) : (zMajor & neg) ^ x)
U = As<Float4>((xMajor & (n ^ As<Int4>(-z))) | (~xMajor & ((zMajor & n) ^ As<Int4>(x))));
@@ -1684,10 +1675,6 @@
M = reciprocal(M) * Float4(0.5f);
U = U * M + Float4(0.5f);
V = V * M + Float4(0.5f);
-
- lodX = x * M;
- lodY = y * M;
- lodZ = z * M;
}
Short4 SamplerCore::applyOffset(Short4 &uvw, Float4 &offset, const Int4 &whd, AddressingMode mode)
diff --git a/src/Shader/SamplerCore.hpp b/src/Shader/SamplerCore.hpp
index 3ad7549..c31f398 100644
--- a/src/Shader/SamplerCore.hpp
+++ b/src/Shader/SamplerCore.hpp
@@ -72,9 +72,9 @@
Vector4f sampleFloat3D(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, bool secondLOD, SamplerFunction function);
Float log2sqrt(Float lod);
void computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &u, Float4 &v, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function);
- void computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &x, Float4 &y, Float4 &z, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function);
+ void computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, Float4 &M, SamplerFunction function);
void computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function);
- void cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodX, Float4 &lodY, Float4 &lodZ, Float4 &x, Float4 &y, Float4 &z);
+ void cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &x, Float4 &y, Float4 &z, Float4 &M);
Short4 applyOffset(Short4 &uvw, Float4 &offset, const Int4 &whd, AddressingMode mode);
void computeIndices(UInt index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, Vector4f &offset, const Pointer<Byte> &mipmap, SamplerFunction function);
void computeIndices(UInt index[4], Int4& uuuu, Int4& vvvv, Int4& wwww, const Pointer<Byte> &mipmap, SamplerFunction function);