Implement mipmap base/max level.
Change-Id: I611815fb0dcbba97e67f3c146dffb463f133447e
Reviewed-on: https://swiftshader-review.googlesource.com/15248
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/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 8590b54..6d6be82 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -3172,7 +3172,7 @@
}
else UNREACHABLE(type);
- sw::Resource *resource = 0;
+ sw::Resource *resource = nullptr;
if(baseTexture && textureUsed)
{
@@ -3183,7 +3183,8 @@
if(baseTexture && textureUsed)
{
- int topLevel = baseTexture->getTopLevel();
+ int baseLevel = baseTexture->getBaseLevel();
+ int maxLevel = std::min(baseTexture->getTopLevel(), baseTexture->getMaxLevel());
if(baseTexture->getTarget() == GL_TEXTURE_2D || baseTexture->getTarget() == GL_TEXTURE_EXTERNAL_OES)
{
@@ -3193,13 +3194,13 @@
{
int surfaceLevel = mipmapLevel;
- if(surfaceLevel < 0)
+ if(surfaceLevel < baseLevel)
{
- surfaceLevel = 0;
+ surfaceLevel = baseLevel;
}
- else if(surfaceLevel > topLevel)
+ else if(surfaceLevel > maxLevel)
{
- surfaceLevel = topLevel;
+ surfaceLevel = maxLevel;
}
egl::Image *surface = texture->getImage(surfaceLevel);
@@ -3214,13 +3215,13 @@
{
int surfaceLevel = mipmapLevel;
- if(surfaceLevel < 0)
+ if(surfaceLevel < baseLevel)
{
- surfaceLevel = 0;
+ surfaceLevel = baseLevel;
}
- else if(surfaceLevel > topLevel)
+ else if(surfaceLevel > maxLevel)
{
- surfaceLevel = topLevel;
+ surfaceLevel = maxLevel;
}
egl::Image *surface = texture->getImage(surfaceLevel);
@@ -3235,13 +3236,13 @@
{
int surfaceLevel = mipmapLevel;
- if(surfaceLevel < 0)
+ if(surfaceLevel < baseLevel)
{
- surfaceLevel = 0;
+ surfaceLevel = baseLevel;
}
- else if(surfaceLevel > topLevel)
+ else if(surfaceLevel > maxLevel)
{
- surfaceLevel = topLevel;
+ surfaceLevel = maxLevel;
}
egl::Image *surface = texture->getImage(surfaceLevel);
@@ -3260,13 +3261,13 @@
{
int surfaceLevel = mipmapLevel;
- if(surfaceLevel < 0)
+ if(surfaceLevel < baseLevel)
{
- surfaceLevel = 0;
+ surfaceLevel = baseLevel;
}
- else if(surfaceLevel > topLevel)
+ else if(surfaceLevel > maxLevel)
{
- surfaceLevel = topLevel;
+ surfaceLevel = maxLevel;
}
egl::Image *surface = cubeTexture->getImage(face, surfaceLevel);
diff --git a/src/OpenGL/libGLESv2/Texture.cpp b/src/OpenGL/libGLESv2/Texture.cpp
index fa5817d..e5202a2 100644
--- a/src/OpenGL/libGLESv2/Texture.cpp
+++ b/src/OpenGL/libGLESv2/Texture.cpp
@@ -182,6 +182,11 @@
bool Texture::setBaseLevel(GLint baseLevel)
{
+ if(baseLevel < 0)
+ {
+ return false;
+ }
+
mBaseLevel = baseLevel;
return true;
}
@@ -844,12 +849,14 @@
return false;
}
- if(image[level]->getWidth() != std::max(1, width >> level))
+ int i = level - mBaseLevel;
+
+ if(image[level]->getWidth() != std::max(1, width >> i))
{
return false;
}
- if(image[level]->getHeight() != std::max(1, height >> level))
+ if(image[level]->getHeight() != std::max(1, height >> i))
{
return false;
}
@@ -1213,7 +1220,9 @@
return false;
}
- if(image[face][level]->getWidth() != std::max(1, size >> level))
+ int i = level - mBaseLevel;
+
+ if(image[face][level]->getWidth() != std::max(1, size >> i))
{
return false;
}
@@ -1833,17 +1842,19 @@
return false;
}
- if(image[level]->getWidth() != std::max(1, width >> level))
+ int i = level - mBaseLevel;
+
+ if(image[level]->getWidth() != std::max(1, width >> i))
{
return false;
}
- if(image[level]->getHeight() != std::max(1, height >> level))
+ if(image[level]->getHeight() != std::max(1, height >> i))
{
return false;
}
- int levelDepth = isTexture2DArray ? depth : std::max(1, depth >> level);
+ int levelDepth = isTexture2DArray ? depth : std::max(1, depth >> i);
if(image[level]->getDepth() != levelDepth)
{
return false;
diff --git a/src/Shader/SamplerCore.cpp b/src/Shader/SamplerCore.cpp
index 8aebbd8..53383cd 100644
--- a/src/Shader/SamplerCore.cpp
+++ b/src/Shader/SamplerCore.cpp
@@ -525,17 +525,17 @@
mask = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
}
- Short4 SamplerCore::offsetSample(Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod)
+ Short4 SamplerCore::offsetSample(Pointer<Byte> &texture, Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod)
{
Short4 offset = *Pointer<Short4>(mipmap + halfOffset);
if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
{
- offset &= Short4(CmpNLE(Float4(lod), Float4(0.0f)));
+ offset &= Short4(CmpNLE(Float4(lod), Float4(Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel))))));
}
else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
{
- offset &= Short4(CmpLE(Float4(lod), Float4(0.0f)));
+ offset &= Short4(CmpLE(Float4(lod), Float4(Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel))))));
}
if(wrap)
@@ -759,10 +759,10 @@
}
else
{
- Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod);
- Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod);
- Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod);
- Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod);
+ Short4 uuuu0 = offsetSample(texture, uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod);
+ Short4 vvvv0 = offsetSample(texture, vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod);
+ Short4 uuuu1 = offsetSample(texture, uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod);
+ Short4 vvvv1 = offsetSample(texture, vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod);
Vector4s c0 = sampleTexel(uuuu0, vvvv0, wwww, offset, mipmap, buffer, function);
Vector4s c1 = sampleTexel(uuuu1, vvvv0, wwww, offset, mipmap, buffer, function);
@@ -966,9 +966,9 @@
{
for(int k = 0; k < 2; k++)
{
- u[i][j][k] = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, i * 2 - 1, lod);
- v[i][j][k] = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, j * 2 - 1, lod);
- s[i][j][k] = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, k * 2 - 1, lod);
+ u[i][j][k] = offsetSample(texture, uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, i * 2 - 1, lod);
+ v[i][j][k] = offsetSample(texture, vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, j * 2 - 1, lod);
+ s[i][j][k] = offsetSample(texture, wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, k * 2 - 1, lod);
}
}
}
@@ -1219,7 +1219,7 @@
Int4 x0, x1, y0, y1, z0;
Float4 fu, fv;
- Int4 filter = computeFilterOffset(lod);
+ Int4 filter = computeFilterOffset(texture, lod);
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);
@@ -1288,7 +1288,7 @@
Int4 x0, x1, y0, y1, z0, z1;
Float4 fu, fv, fw;
- Int4 filter = computeFilterOffset(lod);
+ Int4 filter = computeFilterOffset(texture, lod);
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, z1, fw, mipmap, offset.z, filter, OFFSET(Mipmap, depth), state.addressingModeW, function);
@@ -1431,19 +1431,22 @@
}
else if(function == Lod)
{
- lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+ lod = lodBias;
}
else if(function == Fetch)
{
// TODO: Eliminate int-float-int conversion.
- lod = Float(As<Int>(lodBias)) + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+ lod = Float(As<Int>(lodBias));
}
else if(function == Base)
{
- lod = Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+ lod = Float(0);
}
else assert(false);
+ // TODO: Avoid float conversion.
+ lod += Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+
lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
}
@@ -1497,19 +1500,22 @@
}
else if(function == Lod)
{
- lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+ lod = lodBias;
}
else if(function == Fetch)
{
// TODO: Eliminate int-float-int conversion.
- lod = Float(As<Int>(lodBias)) + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+ lod = Float(As<Int>(lodBias));
}
else if(function == Base)
{
- lod = Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+ lod = Float(0);
}
else assert(false);
+ // TODO: Avoid float conversion.
+ lod += Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+
lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
}
@@ -1561,19 +1567,22 @@
}
else if(function == Lod)
{
- lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+ lod = lodBias;
}
else if(function == Fetch)
{
// TODO: Eliminate int-float-int conversion.
- lod = Float(As<Int>(lodBias)) + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+ lod = Float(As<Int>(lodBias));
}
else if(function == Base)
{
- lod = Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+ lod = Float(0);
}
else assert(false);
+ // TODO: Avoid float conversion.
+ lod += Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+
lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
}
@@ -2277,7 +2286,7 @@
}
}
- Int4 SamplerCore::computeFilterOffset(Float &lod)
+ Int4 SamplerCore::computeFilterOffset(Pointer<Byte> &texture, Float &lod)
{
Int4 filter = -1;
@@ -2287,11 +2296,11 @@
}
else if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
{
- filter = CmpNLE(Float4(lod), Float4(0.0f));
+ filter = CmpNLE(Float4(lod), Float4(Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)))));
}
else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
{
- filter = CmpLE(Float4(lod), Float4(0.0f));
+ filter = CmpLE(Float4(lod), Float4(Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)))));
}
return filter;
diff --git a/src/Shader/SamplerCore.hpp b/src/Shader/SamplerCore.hpp
index 684c1a7..31d6668 100644
--- a/src/Shader/SamplerCore.hpp
+++ b/src/Shader/SamplerCore.hpp
@@ -59,7 +59,7 @@
void border(Short4 &mask, Float4 &coordinates);
void border(Int4 &mask, Float4 &coordinates);
- Short4 offsetSample(Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod);
+ Short4 offsetSample(Pointer<Byte> &texture, Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod);
Vector4s sampleFilter(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerFunction function);
Vector4s sampleAniso(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerFunction function);
Vector4s sampleQuad(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Int face[4], bool secondLOD, SamplerFunction function);
@@ -85,7 +85,7 @@
void selectMipmap(Pointer<Byte> &texture, Pointer<Byte> buffer[4], Pointer<Byte> &mipmap, Float &lod, Int face[4], bool secondLOD);
Short4 address(Float4 &uw, AddressingMode addressingMode, Pointer<Byte>& mipmap);
void address(Float4 &uw, Int4& xyz0, Int4& xyz1, Float4& f, Pointer<Byte>& mipmap, Float4 &texOffset, Int4 &filter, int whd, AddressingMode addressingMode, SamplerFunction function);
- Int4 computeFilterOffset(Float &lod);
+ Int4 computeFilterOffset(Pointer<Byte> &texture, Float &lod);
void convertFixed12(Short4 &ci, Float4 &cf);
void convertFixed12(Vector4s &cs, Vector4f &cf);