Commit 0fe40534 by Geoff Lang

Cache sampler completeness in the Texture class.

BUG=angle:909 Change-Id: I14e06e01d111e9d5eec415f4c2d831b61dcb1e3d Reviewed-on: https://chromium-review.googlesource.com/248070Reviewed-by: 's avatarNicolas Capens <capn@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 38832d17
...@@ -56,6 +56,7 @@ Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target) ...@@ -56,6 +56,7 @@ Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
mImmutableLevelCount(0), mImmutableLevelCount(0),
mTarget(target), mTarget(target),
mImageDescs(IMPLEMENTATION_MAX_TEXTURE_LEVELS * (target == GL_TEXTURE_CUBE_MAP ? 6 : 1)), mImageDescs(IMPLEMENTATION_MAX_TEXTURE_LEVELS * (target == GL_TEXTURE_CUBE_MAP ? 6 : 1)),
mCompletenessCache(),
mBoundSurface(NULL) mBoundSurface(NULL)
{ {
} }
...@@ -113,74 +114,21 @@ GLenum Texture::getInternalFormat(GLenum target, size_t level) const ...@@ -113,74 +114,21 @@ GLenum Texture::getInternalFormat(GLenum target, size_t level) const
bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &data) const bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
{ {
const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel); const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel);
if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0)
{
return false;
}
if (mTarget == GL_TEXTURE_CUBE_MAP && baseImageDesc.size.width != baseImageDesc.size.height)
{
return false;
}
const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat); const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat);
if (!textureCaps.filterable && !IsPointSampled(samplerState)) if (!mCompletenessCache.cacheValid ||
mCompletenessCache.samplerState != samplerState ||
mCompletenessCache.filterable != textureCaps.filterable ||
mCompletenessCache.clientVersion != data.clientVersion ||
mCompletenessCache.supportsNPOT != data.extensions->textureNPOT)
{ {
return false; mCompletenessCache.cacheValid = true;
mCompletenessCache.samplerState = samplerState;
mCompletenessCache.filterable = textureCaps.filterable;
mCompletenessCache.clientVersion = data.clientVersion;
mCompletenessCache.supportsNPOT = data.extensions->textureNPOT;
mCompletenessCache.samplerComplete = computeSamplerCompleteness(samplerState, data);
} }
return mCompletenessCache.samplerComplete;
bool npotSupport = data.extensions->textureNPOT || data.clientVersion >= 3;
if (!npotSupport)
{
if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.width)) ||
(samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.height)))
{
return false;
}
}
if (IsMipmapFiltered(samplerState))
{
if (!npotSupport)
{
if (!gl::isPow2(baseImageDesc.size.width) || !gl::isPow2(baseImageDesc.size.height))
{
return false;
}
}
if (!isMipmapComplete(samplerState))
{
return false;
}
}
else
{
if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete())
{
return false;
}
}
// OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
// The internalformat specified for the texture arrays is a sized internal depth or
// depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
// MODE is NONE, and either the magnification filter is not NEAREST or the mini-
// fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(baseImageDesc.internalFormat);
if (formatInfo.depthBits > 0 && data.clientVersion > 2)
{
if (samplerState.compareMode == GL_NONE)
{
if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
samplerState.magFilter != GL_NEAREST)
{
return false;
}
}
}
return true;
} }
// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
...@@ -390,6 +338,7 @@ void Texture::setImageDesc(GLenum target, size_t level, const ImageDesc &desc) ...@@ -390,6 +338,7 @@ void Texture::setImageDesc(GLenum target, size_t level, const ImageDesc &desc)
size_t descIndex = GetImageDescIndex(target, level); size_t descIndex = GetImageDescIndex(target, level);
ASSERT(descIndex < mImageDescs.size()); ASSERT(descIndex < mImageDescs.size());
mImageDescs[descIndex] = desc; mImageDescs[descIndex] = desc;
mCompletenessCache.cacheValid = false;
} }
void Texture::clearImageDesc(GLenum target, size_t level) void Texture::clearImageDesc(GLenum target, size_t level)
...@@ -403,6 +352,7 @@ void Texture::clearImageDescs() ...@@ -403,6 +352,7 @@ void Texture::clearImageDescs()
{ {
mImageDescs[descIndex] = ImageDesc(); mImageDescs[descIndex] = ImageDesc();
} }
mCompletenessCache.cacheValid = false;
} }
void Texture::bindTexImage(egl::Surface *surface) void Texture::bindTexImage(egl::Surface *surface)
...@@ -451,7 +401,80 @@ size_t Texture::getExpectedMipLevels() const ...@@ -451,7 +401,80 @@ size_t Texture::getExpectedMipLevels() const
} }
} }
bool Texture::isMipmapComplete(const gl::SamplerState &samplerState) const bool Texture::computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const
{
const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel);
if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0)
{
return false;
}
if (mTarget == GL_TEXTURE_CUBE_MAP && baseImageDesc.size.width != baseImageDesc.size.height)
{
return false;
}
const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat);
if (!textureCaps.filterable && !IsPointSampled(samplerState))
{
return false;
}
bool npotSupport = data.extensions->textureNPOT || data.clientVersion >= 3;
if (!npotSupport)
{
if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.width)) ||
(samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.height)))
{
return false;
}
}
if (IsMipmapFiltered(samplerState))
{
if (!npotSupport)
{
if (!gl::isPow2(baseImageDesc.size.width) || !gl::isPow2(baseImageDesc.size.height))
{
return false;
}
}
if (!computeMipmapCompleteness(samplerState))
{
return false;
}
}
else
{
if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete())
{
return false;
}
}
// OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
// The internalformat specified for the texture arrays is a sized internal depth or
// depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
// MODE is NONE, and either the magnification filter is not NEAREST or the mini-
// fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(baseImageDesc.internalFormat);
if (formatInfo.depthBits > 0 && data.clientVersion > 2)
{
if (samplerState.compareMode == GL_NONE)
{
if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
samplerState.magFilter != GL_NEAREST)
{
return false;
}
}
}
return true;
}
bool Texture::computeMipmapCompleteness(const gl::SamplerState &samplerState) const
{ {
size_t expectedMipLevels = getExpectedMipLevels(); size_t expectedMipLevels = getExpectedMipLevels();
...@@ -463,7 +486,7 @@ bool Texture::isMipmapComplete(const gl::SamplerState &samplerState) const ...@@ -463,7 +486,7 @@ bool Texture::isMipmapComplete(const gl::SamplerState &samplerState) const
{ {
for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++) for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
{ {
if (!isLevelComplete(face, level, samplerState)) if (!computeLevelCompleteness(face, level, samplerState))
{ {
return false; return false;
} }
...@@ -471,7 +494,7 @@ bool Texture::isMipmapComplete(const gl::SamplerState &samplerState) const ...@@ -471,7 +494,7 @@ bool Texture::isMipmapComplete(const gl::SamplerState &samplerState) const
} }
else else
{ {
if (!isLevelComplete(mTarget, level, samplerState)) if (!computeLevelCompleteness(mTarget, level, samplerState))
{ {
return false; return false;
} }
...@@ -482,8 +505,7 @@ bool Texture::isMipmapComplete(const gl::SamplerState &samplerState) const ...@@ -482,8 +505,7 @@ bool Texture::isMipmapComplete(const gl::SamplerState &samplerState) const
} }
bool Texture::isLevelComplete(GLenum target, size_t level, bool Texture::computeLevelCompleteness(GLenum target, size_t level, const gl::SamplerState &samplerState) const
const gl::SamplerState &samplerState) const
{ {
ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS); ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
...@@ -538,4 +560,14 @@ bool Texture::isLevelComplete(GLenum target, size_t level, ...@@ -538,4 +560,14 @@ bool Texture::isLevelComplete(GLenum target, size_t level,
return true; return true;
} }
Texture::SamplerCompletenessCache::SamplerCompletenessCache()
: cacheValid(false),
samplerState(),
filterable(false),
clientVersion(0),
supportsNPOT(false),
samplerComplete(false)
{
}
} }
...@@ -120,9 +120,9 @@ class Texture final : public RefCountObject ...@@ -120,9 +120,9 @@ class Texture final : public RefCountObject
GLenum getBaseImageTarget() const; GLenum getBaseImageTarget() const;
size_t getExpectedMipLevels() const; size_t getExpectedMipLevels() const;
bool isMipmapComplete(const gl::SamplerState &samplerState) const; bool computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const;
bool isLevelComplete(GLenum target, size_t level, bool computeMipmapCompleteness(const gl::SamplerState &samplerState) const;
const gl::SamplerState &samplerState) const; bool computeLevelCompleteness(GLenum target, size_t level, const gl::SamplerState &samplerState) const;
const ImageDesc &getImageDesc(GLenum target, size_t level) const; const ImageDesc &getImageDesc(GLenum target, size_t level) const;
void setImageDesc(GLenum target, size_t level, const ImageDesc &desc); void setImageDesc(GLenum target, size_t level, const ImageDesc &desc);
...@@ -132,6 +132,24 @@ class Texture final : public RefCountObject ...@@ -132,6 +132,24 @@ class Texture final : public RefCountObject
std::vector<ImageDesc> mImageDescs; std::vector<ImageDesc> mImageDescs;
struct SamplerCompletenessCache
{
SamplerCompletenessCache();
bool cacheValid;
// All values that affect sampler completeness that are not stored within
// the texture itself
SamplerState samplerState;
bool filterable;
GLint clientVersion;
bool supportsNPOT;
// Result of the sampler completeness with the above parameters
bool samplerComplete;
};
mutable SamplerCompletenessCache mCompletenessCache;
egl::Surface *mBoundSurface; egl::Surface *mBoundSurface;
}; };
......
...@@ -40,6 +40,31 @@ bool SamplerState::swizzleRequired() const ...@@ -40,6 +40,31 @@ bool SamplerState::swizzleRequired() const
swizzleBlue != GL_BLUE || swizzleAlpha != GL_ALPHA; swizzleBlue != GL_BLUE || swizzleAlpha != GL_ALPHA;
} }
bool SamplerState::operator==(const SamplerState &other) const
{
return minFilter == other.minFilter &&
magFilter == other.magFilter &&
wrapS == other.wrapS &&
wrapT == other.wrapT &&
wrapR == other.wrapR &&
maxAnisotropy == other.maxAnisotropy &&
baseLevel == other.baseLevel &&
maxLevel == other.maxLevel &&
minLod == other.minLod &&
maxLod == other.maxLod &&
compareMode == other.compareMode &&
compareFunc == other.compareFunc &&
swizzleRed == other.swizzleRed &&
swizzleGreen == other.swizzleGreen &&
swizzleBlue == other.swizzleBlue &&
swizzleAlpha == other.swizzleAlpha;
}
bool SamplerState::operator!=(const SamplerState &other) const
{
return !(*this == other);
}
static void MinMax(int a, int b, int *minimum, int *maximum) static void MinMax(int a, int b, int *minimum, int *maximum)
{ {
if (a < b) if (a < b)
......
...@@ -178,6 +178,9 @@ struct SamplerState ...@@ -178,6 +178,9 @@ struct SamplerState
GLenum swizzleAlpha; GLenum swizzleAlpha;
bool swizzleRequired() const; bool swizzleRequired() const;
bool operator==(const SamplerState &other) const;
bool operator!=(const SamplerState &other) const;
}; };
struct ClearParameters struct ClearParameters
......
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