Commit b1670ed4 by Nicolas Capens Committed by Nicolas Capens

Refactor duplicate mipmap LOD calculation

Bug: b/129523279 Change-Id: If4dfa5900ac73643cc8a8052867434d62fa1aa1e Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30430 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com>
parent 7179935f
...@@ -74,23 +74,55 @@ namespace sw ...@@ -74,23 +74,55 @@ namespace sw
Float anisotropy; Float anisotropy;
Float4 uDelta; Float4 uDelta;
Float4 vDelta; Float4 vDelta;
Float4 M; // Major axis
if(state.textureType != TEXTURE_3D) if(state.textureType == TEXTURE_CUBE)
{
cubeFace(face, uuuu, vvvv, u, v, w, M);
}
if(function == Implicit || function == Bias || function == Grad)
{ {
if(state.textureType != TEXTURE_CUBE) if(state.textureType != TEXTURE_3D)
{ {
computeLod(texture, sampler, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, lodOrBias.x, dsx, dsy, function); if(state.textureType != TEXTURE_CUBE)
{
computeLod(texture, sampler, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, lodOrBias.x, dsx, dsy, function);
}
else
{
computeLodCube(texture, sampler, lod, u, v, w, lodOrBias.x, dsx, dsy, M, function);
}
} }
else else
{ {
Float4 M; computeLod3D(texture, sampler, lod, uuuu, vvvv, wwww, lodOrBias.x, dsx, dsy, function);
cubeFace(face, uuuu, vvvv, u, v, w, M); }
computeLodCube(texture, sampler, lod, u, v, w, lodOrBias.x, dsx, dsy, M, function);
if(function == Bias)
{
lod += lodOrBias.x;
} }
} }
else else if(function == Lod)
{
lod = lodOrBias.x;
}
else if(function == Fetch)
{
// TODO: Eliminate int-float-int conversion.
lod = Float(As<Int>(Float(lodOrBias.x)));
}
else if(function == Base)
{ {
computeLod3D(texture, sampler, lod, uuuu, vvvv, wwww, lodOrBias.x, dsx, dsy, function); lod = Float(0);
}
else UNREACHABLE("Sampler function %d", int(function));
if(function != Base)
{
lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod)));
lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod)));
} }
// FIXME: YUV is not supported by the floating point path // FIXME: YUV is not supported by the floating point path
...@@ -1156,198 +1188,123 @@ namespace sw ...@@ -1156,198 +1188,123 @@ namespace sw
void SamplerCore::computeLod(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &uuuu, Float4 &vvvv, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function) void SamplerCore::computeLod(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &uuuu, Float4 &vvvv, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
{ {
if(function != Lod && function != Fetch) Float4 duvdxy;
{
Float4 duvdxy;
if(function != Grad) // Implicit if(function != Grad) // Implicit
{ {
duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx); duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx);
} }
else else
{ {
Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx); Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx); Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
duvdxy = Float4(dudxy.xz, dvdxy.xz);
}
// Scale by texture dimensions.
Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture, widthWidthHeightHeight));
Float4 dUV2dxy = dUVdxy * dUVdxy; duvdxy = Float4(dudxy.xz, dvdxy.xz);
Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw; }
lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis // Scale by texture dimensions.
Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture, widthWidthHeightHeight));
if(state.textureFilter == FILTER_ANISOTROPIC) Float4 dUV2dxy = dUVdxy * dUVdxy;
{ Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
Float det = Abs(Float(dUVdxy.x) * Float(dUVdxy.w) - Float(dUVdxy.y) * Float(dUVdxy.z));
Float4 dudx = duvdxy.xxxx; lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis
Float4 dudy = duvdxy.yyyy;
Float4 dvdx = duvdxy.zzzz;
Float4 dvdy = duvdxy.wwww;
Int4 mask = As<Int4>(CmpNLT(dUV2.x, dUV2.y)); if(state.textureFilter == FILTER_ANISOTROPIC)
uDelta = As<Float4>((As<Int4>(dudx) & mask) | ((As<Int4>(dudy) & ~mask))); {
vDelta = As<Float4>((As<Int4>(dvdx) & mask) | ((As<Int4>(dvdy) & ~mask))); Float det = Abs(Float(dUVdxy.x) * Float(dUVdxy.w) - Float(dUVdxy.y) * Float(dUVdxy.z));
anisotropy = lod * Rcp_pp(det); Float4 dudx = duvdxy.xxxx;
anisotropy = Min(anisotropy, *Pointer<Float>(sampler + OFFSET(vk::Sampler,maxAnisotropy))); Float4 dudy = duvdxy.yyyy;
Float4 dvdx = duvdxy.zzzz;
Float4 dvdy = duvdxy.wwww;
lod *= Rcp_pp(anisotropy * anisotropy); Int4 mask = As<Int4>(CmpNLT(dUV2.x, dUV2.y));
} uDelta = As<Float4>((As<Int4>(dudx) & mask) | ((As<Int4>(dudy) & ~mask)));
vDelta = As<Float4>((As<Int4>(dvdx) & mask) | ((As<Int4>(dvdy) & ~mask)));
lod = log2sqrt(lod); // log2(sqrt(lod)) anisotropy = lod * Rcp_pp(det);
anisotropy = Min(anisotropy, *Pointer<Float>(sampler + OFFSET(vk::Sampler,maxAnisotropy)));
if(function == Bias) lod *= Rcp_pp(anisotropy * anisotropy);
{
lod += lodOrBias;
}
}
else if(function == Lod)
{
lod = lodOrBias;
}
else if(function == Fetch)
{
// TODO: Eliminate int-float-int conversion.
lod = Float(As<Int>(lodOrBias));
}
else if(function == Base)
{
lod = Float(0);
} }
else assert(false);
lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod))); lod = log2sqrt(lod); // log2(sqrt(lod))
lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod)));
} }
void SamplerCore::computeLodCube(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, Float4 &M, SamplerFunction function) void SamplerCore::computeLodCube(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, Float4 &M, SamplerFunction function)
{ {
if(function != Lod && function != Fetch) Float4 dudxy, dvdxy, dsdxy;
if(function != Grad) // Implicit
{ {
Float4 dudxy, dvdxy, dsdxy; Float4 U = u * M;
Float4 V = v * M;
Float4 W = w * M;
if(function != Grad) // Implicit dudxy = Abs(U - U.xxxx);
{ dvdxy = Abs(V - V.xxxx);
Float4 U = u * M; dsdxy = Abs(W - W.xxxx);
Float4 V = v * M; }
Float4 W = w * M; else
{
dudxy = Float4(dsx.x.xx, dsy.x.xx);
dvdxy = Float4(dsx.y.xx, dsy.y.xx);
dsdxy = Float4(dsx.z.xx, dsy.z.xx);
dudxy = Abs(U - U.xxxx); dudxy = Abs(dudxy * Float4(M.x));
dvdxy = Abs(V - V.xxxx); dvdxy = Abs(dvdxy * Float4(M.x));
dsdxy = Abs(W - W.xxxx); dsdxy = Abs(dsdxy * Float4(M.x));
} }
else
{
dudxy = Float4(dsx.x.xx, dsy.x.xx);
dvdxy = Float4(dsx.y.xx, dsy.y.xx);
dsdxy = Float4(dsx.z.xx, dsy.z.xx);
dudxy = Abs(dudxy * Float4(M.x)); // Compute the largest Manhattan distance in two dimensions.
dvdxy = Abs(dvdxy * Float4(M.x)); // This takes the footprint across adjacent faces into account.
dsdxy = Abs(dsdxy * Float4(M.x)); Float4 duvdxy = dudxy + dvdxy;
} Float4 dusdxy = dudxy + dsdxy;
Float4 dvsdxy = dvdxy + dsdxy;
// Compute the largest Manhattan distance in two dimensions. dudxy = Max(Max(duvdxy, dusdxy), dvsdxy);
// This takes the footprint across adjacent faces into account.
Float4 duvdxy = dudxy + dvdxy;
Float4 dusdxy = dudxy + dsdxy;
Float4 dvsdxy = dvdxy + dsdxy;
dudxy = Max(Max(duvdxy, dusdxy), dvsdxy); lod = Max(Float(dudxy.y), Float(dudxy.z)); // FIXME: Max(dudxy.y, dudxy.z);
lod = Max(Float(dudxy.y), Float(dudxy.z)); // FIXME: Max(dudxy.y, dudxy.z); // Scale by texture dimension.
lod *= *Pointer<Float>(texture + OFFSET(Texture,width));
// Scale by texture dimension and global LOD. lod = log2(lod);
lod *= *Pointer<Float>(texture + OFFSET(Texture,width)); }
lod = log2(lod); void SamplerCore::computeLod3D(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
{
Float4 dudxy, dvdxy, dsdxy;
if(function == Bias) if(function != Grad) // Implicit
{
lod += lodOrBias;
}
}
else if(function == Lod)
{
lod = lodOrBias;
}
else if(function == Fetch)
{ {
// TODO: Eliminate int-float-int conversion. dudxy = uuuu - uuuu.xxxx;
lod = Float(As<Int>(lodOrBias)); dvdxy = vvvv - vvvv.xxxx;
dsdxy = wwww - wwww.xxxx;
} }
else if(function == Base) else
{ {
lod = Float(0); dudxy = Float4(dsx.x.xx, dsy.x.xx);
dvdxy = Float4(dsx.y.xx, dsy.y.xx);
dsdxy = Float4(dsx.z.xx, dsy.z.xx);
} }
else assert(false);
lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod))); // Scale by texture dimensions.
lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod))); dudxy *= *Pointer<Float4>(texture + OFFSET(Texture, width));
} dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture, height));
dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture, depth));
void SamplerCore::computeLod3D(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function) dudxy *= dudxy;
{ dvdxy *= dvdxy;
if(function != Lod && function != Fetch) dsdxy *= dsdxy;
{
Float4 dudxy, dvdxy, dsdxy;
if(function != Grad) // Implicit
{
dudxy = uuuu - uuuu.xxxx;
dvdxy = vvvv - vvvv.xxxx;
dsdxy = wwww - wwww.xxxx;
}
else
{
dudxy = Float4(dsx.x.xx, dsy.x.xx);
dvdxy = Float4(dsx.y.xx, dsy.y.xx);
dsdxy = Float4(dsx.z.xx, dsy.z.xx);
}
// Scale by texture dimensions and global LOD.
dudxy *= *Pointer<Float4>(texture + OFFSET(Texture, width));
dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture, height));
dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture, depth));
dudxy *= dudxy;
dvdxy *= dvdxy;
dsdxy *= dsdxy;
dudxy += dvdxy;
dudxy += dsdxy;
lod = Max(Float(dudxy.y), Float(dudxy.z)); // FIXME: Max(dudxy.y, dudxy.z); dudxy += dvdxy;
dudxy += dsdxy;
lod = log2sqrt(lod); // log2(sqrt(lod)) lod = Max(Float(dudxy.y), Float(dudxy.z)); // FIXME: Max(dudxy.y, dudxy.z);
if(function == Bias)
{
lod += lodOrBias;
}
}
else if(function == Lod)
{
lod = lodOrBias;
}
else if(function == Fetch)
{
// TODO: Eliminate int-float-int conversion.
lod = Float(As<Int>(lodOrBias));
}
else if(function == Base)
{
lod = Float(0);
}
else assert(false);
lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod))); lod = log2sqrt(lod); // log2(sqrt(lod))
lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod)));
} }
void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &x, Float4 &y, Float4 &z, Float4 &M) void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &x, Float4 &y, Float4 &z, Float4 &M)
......
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