Commit 2cfadc68 by Nicolas Capens

Compute cube LOD from 3D cube intersection distance.

We used to compute the cube map LOD by projecting all sampling rays onto the same face (arbitrarily chosen). This changes it to intersect the rays with the cube and use the 3D distance between them. Change-Id: If90b29cb4c13e6128ce6642eb28bb92602e783df Reviewed-on: https://swiftshader-review.googlesource.com/5160Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com> Tested-by: 's avatarNicolas Capens <capn@google.com>
parent 889faf04
...@@ -89,12 +89,13 @@ namespace sw ...@@ -89,12 +89,13 @@ namespace sw
else else
{ {
Int face[4]; Int face[4];
Float4 lodU; Float4 lodX;
Float4 lodV; Float4 lodY;
Float4 lodZ;
if(state.textureType == TEXTURE_CUBE) if(state.textureType == TEXTURE_CUBE)
{ {
cubeFace(face, uuuu, vvvv, lodU, lodV, u, v, w); cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w);
} }
Float lod; Float lod;
...@@ -110,7 +111,7 @@ namespace sw ...@@ -110,7 +111,7 @@ namespace sw
} }
else else
{ {
computeLod(texture, lod, anisotropy, uDelta, vDelta, lodU, lodV, q.x, dsx, dsy, method); computeLodCube(texture, lod, lodX, lodY, lodZ, q.x, dsx, dsy, method);
} }
} }
else else
...@@ -118,12 +119,6 @@ namespace sw ...@@ -118,12 +119,6 @@ namespace sw
computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, method); computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, method);
} }
if(state.textureType == TEXTURE_CUBE)
{
uuuu += Float4(0.5f);
vvvv += Float4(0.5f);
}
if(!hasFloatTexture()) if(!hasFloatTexture())
{ {
sampleFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method); sampleFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method);
...@@ -320,12 +315,13 @@ namespace sw ...@@ -320,12 +315,13 @@ namespace sw
Float4 wwww = w; Float4 wwww = w;
Int face[4]; Int face[4];
Float4 lodU; Float4 lodX;
Float4 lodV; Float4 lodY;
Float4 lodZ;
if(state.textureType == TEXTURE_CUBE) if(state.textureType == TEXTURE_CUBE)
{ {
cubeFace(face, uuuu, vvvv, lodU, lodV, u, v, w); cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w);
} }
Float lod; Float lod;
...@@ -341,7 +337,7 @@ namespace sw ...@@ -341,7 +337,7 @@ namespace sw
} }
else else
{ {
computeLod(texture, lod, anisotropy, uDelta, vDelta, lodU, lodV, q.x, dsx, dsy, method); computeLodCube(texture, lod, lodX, lodY, lodZ, q.x, dsx, dsy, method);
} }
} }
else else
...@@ -349,12 +345,6 @@ namespace sw ...@@ -349,12 +345,6 @@ namespace sw
computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, method); computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, method);
} }
if(state.textureType == TEXTURE_CUBE)
{
uuuu += Float4(0.5f);
vvvv += Float4(0.5f);
}
sampleFloatFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method); sampleFloatFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method);
} }
else else
...@@ -1451,11 +1441,64 @@ namespace sw ...@@ -1451,11 +1441,64 @@ namespace sw
{ {
lod += lodBias; lod += lodBias;
} }
}
else
{
lod = lodBias + *Pointer<Float>(texture + OFFSET(Texture,LOD));
}
// FIXME: Hack to satisfy WHQL lod = Max(lod, 0.0f);
if(state.textureType == TEXTURE_CUBE) lod = Min(lod, Float(MIPMAP_LEVELS - 2)); // Trilinear accesses lod+1
}
void SamplerCore::computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &s, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method)
{
if(method != Lod)
{
if(method != Grad)
{ {
lod += Float(-0.15f); Float4 dudxy = u.ywyw - u;
Float4 dvdxy = v.ywyw - v;
Float4 dsdxy = s.ywyw - s;
// 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);
}
else
{
Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
Float4 duvdxy = Float4(dudxy.xz, dvdxy.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
}
// log2(sqrt(lod))
lod = Float(As<Int>(lod));
lod -= Float(0x3F800000);
lod *= As<Float>(Int(0x33800000));
if(method == Bias)
{
lod += lodBias;
} }
} }
else else
...@@ -1535,22 +1578,22 @@ namespace sw ...@@ -1535,22 +1578,22 @@ namespace sw
} }
} }
void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodU, Float4 &lodV, Float4 &x, Float4 &y, Float4 &z) void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodX, Float4 &lodY, Float4 &lodZ, Float4 &x, Float4 &y, Float4 &z)
{ {
Int4 xp = CmpNLE(x, Float4(0.0f)); // x > 0 Int4 xn = CmpLT(x, Float4(0.0f)); // x < 0
Int4 yp = CmpNLE(y, Float4(0.0f)); // y > 0 Int4 yn = CmpLT(y, Float4(0.0f)); // y < 0
Int4 zp = CmpNLE(z, Float4(0.0f)); // z > 0 Int4 zn = CmpLT(z, Float4(0.0f)); // z < 0
Float4 absX = Abs(x); Float4 absX = Abs(x);
Float4 absY = Abs(y); Float4 absY = Abs(y);
Float4 absZ = Abs(z); Float4 absZ = Abs(z);
Int4 xy = CmpNLE(absX, absY); // abs(x) > abs(y) Int4 xy = CmpNLE(absX, absY); // abs(x) > abs(y)
Int4 yz = CmpNLE(absY, absZ); // abs(y) > abs(z) Int4 yz = CmpNLE(absY, absZ); // abs(y) > abs(z)
Int4 zx = CmpNLE(absZ, absX); // abs(z) > abs(x) Int4 zx = CmpNLE(absZ, absX); // abs(z) > abs(x)
Int4 xMajor = xy & ~zx; // abs(x) > abs(y) && abs(x) > abs(z)
Int4 xyz = ~zx & xy; // abs(x) > abs(y) && abs(x) > abs(z) Int4 yMajor = yz & ~xy; // abs(y) > abs(z) && abs(y) > abs(x)
Int4 yzx = ~xy & yz; // abs(y) > abs(z) && abs(y) > abs(x) Int4 zMajor = zx & ~yz; // abs(z) > abs(x) && abs(z) > abs(y)
Int4 zxy = ~yz & zx; // abs(z) > abs(x) && abs(z) > abs(y)
// FACE_POSITIVE_X = 000b // FACE_POSITIVE_X = 000b
// FACE_NEGATIVE_X = 001b // FACE_NEGATIVE_X = 001b
...@@ -1559,10 +1602,10 @@ namespace sw ...@@ -1559,10 +1602,10 @@ namespace sw
// FACE_POSITIVE_Z = 100b // FACE_POSITIVE_Z = 100b
// FACE_NEGATIVE_Z = 101b // FACE_NEGATIVE_Z = 101b
Int yAxis = SignMask(yzx); Int yAxis = SignMask(yMajor);
Int zAxis = SignMask(zxy); Int zAxis = SignMask(zMajor);
Int4 n = (~xp & xyz) | (~yp & yzx) | (~zp & zxy); Int4 n = ((xn & xMajor) | (yn & yMajor) | (zn & zMajor)) & Int4(0x80000000);
Int negative = SignMask(n); Int negative = SignMask(n);
face[0] = *Pointer<Int>(constants + OFFSET(Constants,transposeBit0) + negative * 4); face[0] = *Pointer<Int>(constants + OFFSET(Constants,transposeBit0) + negative * 4);
...@@ -1573,40 +1616,21 @@ namespace sw ...@@ -1573,40 +1616,21 @@ namespace sw
face[3] = (face[0] >> 12) & 0x7; face[3] = (face[0] >> 12) & 0x7;
face[0] &= 0x7; face[0] &= 0x7;
// U = xyz * -z + ~xyz * (yzx * ~yp * -x + (yzx * ~yp) * x) Float4 M = Max(Max(absX, absY), absZ);
U = As<Float4>((xyz & As<Int4>(-z)) | (~xyz & (((yzx & ~yp) & Int4(0x80000000, 0x80000000, 0x80000000, 0x80000000)) ^ As<Int4>(x))));
// V = yzx * z + ~yzx * (~neg * -y + neg * y)
V = As<Float4>((~yzx & ((~n & Int4(0x80000000, 0x80000000, 0x80000000, 0x80000000)) ^ As<Int4>(y))) | (yzx & As<Int4>(z)));
// M = xyz * x + yzx * y + zxy * z
Float4 M = As<Float4>((xyz & As<Int4>(x)) | (yzx & As<Int4>(y)) | (zxy & As<Int4>(z)));
M = reciprocal(M); // U = xMajor ? (neg ^ -z) : (zMajor & neg) ^ x)
U *= M * Float4(0.5f); U = As<Float4>((xMajor & (n ^ As<Int4>(-z))) | (~xMajor & ((zMajor & n) ^ As<Int4>(x))));
V *= M * Float4(0.5f);
// Project coordinates onto one face for consistent LOD calculation // V = !yMajor ? -y : (n ^ z)
{ V = As<Float4>((~yMajor & As<Int4>(-y)) | (yMajor & (n ^ As<Int4>(z))));
yp = Swizzle(yp, 0);
n = Swizzle(n, 0);
xyz = Swizzle(xyz, 0);
yzx = Swizzle(yzx, 0);
zxy = Swizzle(zxy, 0);
// U = xyz * -z + ~xyz * (yzx * ~yp * -x + (yzx * ~yp) * x)
lodU = As<Float4>((xyz & As<Int4>(-z)) | (~xyz & (((yzx & ~yp) & Int4(0x80000000, 0x80000000, 0x80000000, 0x80000000)) ^ As<Int4>(x))));
// V = yzx * z + ~yzx * (~neg * -y + neg * y) M = reciprocal(M) * Float4(0.5f);
lodV = As<Float4>((~yzx & ((~n & Int4(0x80000000, 0x80000000, 0x80000000, 0x80000000)) ^ As<Int4>(y))) | (yzx & As<Int4>(z))); U = U * M + Float4(0.5f);
V = V * M + Float4(0.5f);
// M = xyz * x + yzx * y + zxy * z lodX = x * M;
Float4 M = As<Float4>((xyz & As<Int4>(x)) | (yzx & As<Int4>(y)) | (zxy & As<Int4>(z))); lodY = y * M;
lodZ = z * M;
M = Rcp_pp(M);
lodU *= M * Float4(0.5f);
lodV *= M * Float4(0.5f);
}
} }
void SamplerCore::computeIndices(Int index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, const Pointer<Byte> &mipmap) void SamplerCore::computeIndices(Int index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, const Pointer<Byte> &mipmap)
......
...@@ -50,8 +50,9 @@ namespace sw ...@@ -50,8 +50,9 @@ namespace sw
void sampleFloat2D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD); void sampleFloat2D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD);
void sampleFloat3D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, bool secondLOD); void sampleFloat3D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, bool secondLOD);
void computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &u, Float4 &v, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method); void computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &u, Float4 &v, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method);
void computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &x, Float4 &y, Float4 &z, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method);
void computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method); void computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method);
void cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodU, Float4 &lodV, Float4 &x, Float4 &y, Float4 &z); void cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodX, Float4 &lodY, Float4 &lodZ, Float4 &x, Float4 &y, Float4 &z);
void computeIndices(Int index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, const Pointer<Byte> &mipmap); void computeIndices(Int index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, const Pointer<Byte> &mipmap);
void sampleTexel(Vector4s &c, Short4 &u, Short4 &v, Short4 &s, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4]); void sampleTexel(Vector4s &c, Short4 &u, Short4 &v, Short4 &s, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4]);
void sampleTexel(Vector4f &c, Short4 &u, Short4 &v, Short4 &s, Float4 &z, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4]); void sampleTexel(Vector4f &c, Short4 &u, Short4 &v, Short4 &s, Float4 &z, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment