Commit e8f47137 by Geoff Lang

Work around depth texture sampling differences in GL versions.

ES3 requires that only the red channel has data when sampling from depth textures while desktop GL treats them as luminance textures. Set the swizzle state of the texture to sample 0 from the blue and green channels in TextureGL. Passes 75 new tests in dEQP-GLES3.functional.texture.format and dEQP-GLES3.functional.texture.specification. BUG=angleproject:884 Change-Id: I863472961dcbbf8af864f5e1d85a4aea41f47bda Reviewed-on: https://chromium-review.googlesource.com/298481Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 4a693565
...@@ -51,28 +51,58 @@ static bool IsLUMAFormat(GLenum format) ...@@ -51,28 +51,58 @@ static bool IsLUMAFormat(GLenum format)
return format == GL_LUMINANCE || format == GL_ALPHA || format == GL_LUMINANCE_ALPHA; return format == GL_LUMINANCE || format == GL_ALPHA || format == GL_LUMINANCE_ALPHA;
} }
static LUMAWorkaround GetLUMAWorkaroundInfo(GLenum originalFormat, GLenum destinationFormat) static LUMAWorkaroundGL GetLUMAWorkaroundInfo(const gl::InternalFormat &originalFormatInfo,
GLenum destinationFormat)
{ {
const gl::InternalFormat &originalFormatInfo = gl::GetInternalFormatInfo(originalFormat);
if (IsLUMAFormat(originalFormatInfo.format)) if (IsLUMAFormat(originalFormatInfo.format))
{ {
const gl::InternalFormat &destinationFormatInfo = const gl::InternalFormat &destinationFormatInfo =
gl::GetInternalFormatInfo(destinationFormat); gl::GetInternalFormatInfo(destinationFormat);
return LUMAWorkaround(!IsLUMAFormat(destinationFormatInfo.format), return LUMAWorkaroundGL(!IsLUMAFormat(destinationFormatInfo.format),
originalFormatInfo.format, destinationFormatInfo.format); destinationFormatInfo.format);
} }
else else
{ {
return LUMAWorkaround(false, GL_NONE, GL_NONE); return LUMAWorkaroundGL(false, GL_NONE);
} }
} }
LUMAWorkaround::LUMAWorkaround() : LUMAWorkaround(false, GL_NONE, GL_NONE) static bool IsDepthStencilFormat(GLenum format)
{
return format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL;
}
static bool GetDepthStencilWorkaround(const gl::InternalFormat &originalFormatInfo)
{
return IsDepthStencilFormat(originalFormatInfo.format);
}
static LevelInfoGL GetLevelInfo(GLenum originalFormat, GLenum destinationFormat)
{
const gl::InternalFormat &originalFormatInfo = gl::GetInternalFormatInfo(originalFormat);
return LevelInfoGL(originalFormat, GetDepthStencilWorkaround(originalFormatInfo),
GetLUMAWorkaroundInfo(originalFormatInfo, destinationFormat));
}
LUMAWorkaroundGL::LUMAWorkaroundGL() : LUMAWorkaroundGL(false, GL_NONE)
{
}
LUMAWorkaroundGL::LUMAWorkaroundGL(bool enabled_, GLenum workaroundFormat_)
: enabled(enabled_), workaroundFormat(workaroundFormat_)
{
}
LevelInfoGL::LevelInfoGL() : LevelInfoGL(GL_NONE, false, LUMAWorkaroundGL())
{ {
} }
LUMAWorkaround::LUMAWorkaround(bool enabled_, GLenum sourceFormat_, GLenum workaroundFormat_) LevelInfoGL::LevelInfoGL(GLenum sourceFormat_,
: enabled(enabled_), sourceFormat(sourceFormat_), workaroundFormat(workaroundFormat_) bool depthStencilWorkaround_,
const LUMAWorkaroundGL &lumaWorkaround_)
: sourceFormat(sourceFormat_),
depthStencilWorkaround(depthStencilWorkaround_),
lumaWorkaround(lumaWorkaround_)
{ {
} }
...@@ -87,7 +117,7 @@ TextureGL::TextureGL(GLenum type, ...@@ -87,7 +117,7 @@ TextureGL::TextureGL(GLenum type,
mWorkarounds(workarounds), mWorkarounds(workarounds),
mStateManager(stateManager), mStateManager(stateManager),
mBlitter(blitter), mBlitter(blitter),
mLUMAWorkaroundLevels(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS), mLevelInfo(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS),
mAppliedSamplerState(), mAppliedSamplerState(),
mTextureID(0) mTextureID(0)
{ {
...@@ -139,8 +169,7 @@ gl::Error TextureGL::setImage(GLenum target, size_t level, GLenum internalFormat ...@@ -139,8 +169,7 @@ gl::Error TextureGL::setImage(GLenum target, size_t level, GLenum internalFormat
UNREACHABLE(); UNREACHABLE();
} }
mLUMAWorkaroundLevels[level] = mLevelInfo[level] = GetLevelInfo(internalFormat, texImageFormat.internalFormat);
GetLUMAWorkaroundInfo(internalFormat, texImageFormat.internalFormat);
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
...@@ -172,8 +201,8 @@ gl::Error TextureGL::setSubImage(GLenum target, size_t level, const gl::Box &are ...@@ -172,8 +201,8 @@ gl::Error TextureGL::setSubImage(GLenum target, size_t level, const gl::Box &are
UNREACHABLE(); UNREACHABLE();
} }
ASSERT(mLUMAWorkaroundLevels[level].enabled == ASSERT(mLevelInfo[level].lumaWorkaround.enabled ==
GetLUMAWorkaroundInfo(format, texSubImageFormat.format).enabled); GetLevelInfo(format, texSubImageFormat.format).lumaWorkaround.enabled);
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
...@@ -205,8 +234,8 @@ gl::Error TextureGL::setCompressedImage(GLenum target, size_t level, GLenum inte ...@@ -205,8 +234,8 @@ gl::Error TextureGL::setCompressedImage(GLenum target, size_t level, GLenum inte
UNREACHABLE(); UNREACHABLE();
} }
ASSERT(!GetLUMAWorkaroundInfo(internalFormat, compressedTexImageFormat.internalFormat).enabled); mLevelInfo[level] = GetLevelInfo(internalFormat, compressedTexImageFormat.internalFormat);
mLUMAWorkaroundLevels[level].enabled = false; ASSERT(!mLevelInfo[level].lumaWorkaround.enabled);
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
...@@ -239,8 +268,8 @@ gl::Error TextureGL::setCompressedSubImage(GLenum target, size_t level, const gl ...@@ -239,8 +268,8 @@ gl::Error TextureGL::setCompressedSubImage(GLenum target, size_t level, const gl
UNREACHABLE(); UNREACHABLE();
} }
ASSERT(!mLUMAWorkaroundLevels[level].enabled && ASSERT(!mLevelInfo[level].lumaWorkaround.enabled &&
!GetLUMAWorkaroundInfo(format, compressedTexSubImageFormat.format).enabled); !GetLevelInfo(format, compressedTexSubImageFormat.format).lumaWorkaround.enabled);
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
...@@ -251,12 +280,11 @@ gl::Error TextureGL::copyImage(GLenum target, size_t level, const gl::Rectangle ...@@ -251,12 +280,11 @@ gl::Error TextureGL::copyImage(GLenum target, size_t level, const gl::Rectangle
nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat( nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat(
mFunctions, mWorkarounds, internalFormat, source->getImplementationColorReadType()); mFunctions, mWorkarounds, internalFormat, source->getImplementationColorReadType());
LUMAWorkaround lumaWorkaround = LevelInfoGL levelInfo = GetLevelInfo(internalFormat, copyTexImageFormat.internalFormat);
GetLUMAWorkaroundInfo(internalFormat, copyTexImageFormat.internalFormat); if (levelInfo.lumaWorkaround.enabled)
if (lumaWorkaround.enabled)
{ {
gl::Error error = mBlitter->copyImageToLUMAWorkaroundTexture( gl::Error error = mBlitter->copyImageToLUMAWorkaroundTexture(
mTextureID, mTextureType, target, lumaWorkaround.sourceFormat, level, sourceArea, mTextureID, mTextureType, target, levelInfo.sourceFormat, level, sourceArea,
copyTexImageFormat.internalFormat, source); copyTexImageFormat.internalFormat, source);
if (error.isError()) if (error.isError())
{ {
...@@ -283,7 +311,7 @@ gl::Error TextureGL::copyImage(GLenum target, size_t level, const gl::Rectangle ...@@ -283,7 +311,7 @@ gl::Error TextureGL::copyImage(GLenum target, size_t level, const gl::Rectangle
} }
} }
mLUMAWorkaroundLevels[level] = lumaWorkaround; mLevelInfo[level] = levelInfo;
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
...@@ -296,12 +324,12 @@ gl::Error TextureGL::copySubImage(GLenum target, size_t level, const gl::Offset ...@@ -296,12 +324,12 @@ gl::Error TextureGL::copySubImage(GLenum target, size_t level, const gl::Offset
mStateManager->bindTexture(mTextureType, mTextureID); mStateManager->bindTexture(mTextureType, mTextureID);
mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID()); mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
const LUMAWorkaround &lumaWorkaround = mLUMAWorkaroundLevels[level]; const LevelInfoGL &levelInfo = mLevelInfo[level];
if (lumaWorkaround.enabled) if (levelInfo.lumaWorkaround.enabled)
{ {
gl::Error error = mBlitter->copySubImageToLUMAWorkaroundTexture( gl::Error error = mBlitter->copySubImageToLUMAWorkaroundTexture(
mTextureID, mTextureType, target, lumaWorkaround.sourceFormat, level, destOffset, mTextureID, mTextureType, target, levelInfo.sourceFormat, level, destOffset, sourceArea,
sourceArea, source); source);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -458,11 +486,10 @@ gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFor ...@@ -458,11 +486,10 @@ gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFor
UNREACHABLE(); UNREACHABLE();
} }
LUMAWorkaround lumaWorkaround = LevelInfoGL levelInfo = GetLevelInfo(internalFormat, texStorageFormat.internalFormat);
GetLUMAWorkaroundInfo(internalFormat, texStorageFormat.internalFormat); for (size_t level = 0; level < mLevelInfo.size(); level++)
for (size_t level = 0; level < mLUMAWorkaroundLevels.size(); level++)
{ {
mLUMAWorkaroundLevels[level] = lumaWorkaround; mLevelInfo[level] = levelInfo;
} }
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
...@@ -473,9 +500,9 @@ gl::Error TextureGL::generateMipmaps(const gl::SamplerState &samplerState) ...@@ -473,9 +500,9 @@ gl::Error TextureGL::generateMipmaps(const gl::SamplerState &samplerState)
mStateManager->bindTexture(mTextureType, mTextureID); mStateManager->bindTexture(mTextureType, mTextureID);
mFunctions->generateMipmap(mTextureType); mFunctions->generateMipmap(mTextureType);
for (size_t level = samplerState.baseLevel; level < mLUMAWorkaroundLevels.size(); level++) for (size_t level = samplerState.baseLevel; level < mLevelInfo.size(); level++)
{ {
mLUMAWorkaroundLevels[level] = mLUMAWorkaroundLevels[samplerState.baseLevel]; mLevelInfo[level] = mLevelInfo[samplerState.baseLevel];
} }
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
...@@ -488,7 +515,7 @@ void TextureGL::bindTexImage(egl::Surface *surface) ...@@ -488,7 +515,7 @@ void TextureGL::bindTexImage(egl::Surface *surface)
// Make sure this texture is bound // Make sure this texture is bound
mStateManager->bindTexture(mTextureType, mTextureID); mStateManager->bindTexture(mTextureType, mTextureID);
mLUMAWorkaroundLevels[0].enabled = false; mLevelInfo[0] = LevelInfoGL();
} }
void TextureGL::releaseTexImage() void TextureGL::releaseTexImage()
...@@ -533,33 +560,35 @@ static inline void SyncSamplerStateMember(const FunctionsGL *functions, ...@@ -533,33 +560,35 @@ static inline void SyncSamplerStateMember(const FunctionsGL *functions,
template <typename T, typename ApplyTextureFuncType> template <typename T, typename ApplyTextureFuncType>
static inline void SyncSamplerStateSwizzle(const FunctionsGL *functions, static inline void SyncSamplerStateSwizzle(const FunctionsGL *functions,
ApplyTextureFuncType applyTextureFunc, ApplyTextureFuncType applyTextureFunc,
const LUMAWorkaround &lumaWorkaround, const LevelInfoGL &levelInfo,
const gl::SamplerState &newState, const gl::SamplerState &newState,
gl::SamplerState &curState, gl::SamplerState &curState,
GLenum textureType, GLenum textureType,
GLenum name, GLenum name,
T(gl::SamplerState::*samplerMember)) T(gl::SamplerState::*samplerMember))
{ {
if (lumaWorkaround.enabled) if (levelInfo.lumaWorkaround.enabled || levelInfo.depthStencilWorkaround)
{ {
UNUSED_ASSERTION_VARIABLE(lumaWorkaround.workaroundFormat);
GLenum resultSwizzle = GL_NONE; GLenum resultSwizzle = GL_NONE;
if (levelInfo.lumaWorkaround.enabled)
{
UNUSED_ASSERTION_VARIABLE(levelInfo.lumaWorkaround.workaroundFormat);
switch (newState.*samplerMember) switch (newState.*samplerMember)
{ {
case GL_RED: case GL_RED:
case GL_GREEN: case GL_GREEN:
case GL_BLUE: case GL_BLUE:
if (lumaWorkaround.sourceFormat == GL_LUMINANCE || if (levelInfo.sourceFormat == GL_LUMINANCE ||
lumaWorkaround.sourceFormat == GL_LUMINANCE_ALPHA) levelInfo.sourceFormat == GL_LUMINANCE_ALPHA)
{ {
// Texture is backed by a RED or RG texture, point all color channels at the red // Texture is backed by a RED or RG texture, point all color channels at the red
// channel. // channel.
ASSERT(lumaWorkaround.workaroundFormat == GL_RED || ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED ||
lumaWorkaround.workaroundFormat == GL_RG); levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
resultSwizzle = GL_RED; resultSwizzle = GL_RED;
} }
else if (lumaWorkaround.sourceFormat == GL_ALPHA) else if (levelInfo.sourceFormat == GL_ALPHA)
{ {
// Color channels are not supposed to exist, make them always sample 0. // Color channels are not supposed to exist, make them always sample 0.
resultSwizzle = GL_ZERO; resultSwizzle = GL_ZERO;
...@@ -571,23 +600,23 @@ static inline void SyncSamplerStateSwizzle(const FunctionsGL *functions, ...@@ -571,23 +600,23 @@ static inline void SyncSamplerStateSwizzle(const FunctionsGL *functions,
break; break;
case GL_ALPHA: case GL_ALPHA:
if (lumaWorkaround.sourceFormat == GL_LUMINANCE) if (levelInfo.sourceFormat == GL_LUMINANCE)
{ {
// Alpha channel is not supposed to exist, make it always sample 1. // Alpha channel is not supposed to exist, make it always sample 1.
resultSwizzle = GL_ONE; resultSwizzle = GL_ONE;
} }
else if (lumaWorkaround.sourceFormat == GL_ALPHA) else if (levelInfo.sourceFormat == GL_ALPHA)
{ {
// Texture is backed by a RED texture, point the alpha channel at the red // Texture is backed by a RED texture, point the alpha channel at the red
// channel. // channel.
ASSERT(lumaWorkaround.workaroundFormat == GL_RED); ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED);
resultSwizzle = GL_RED; resultSwizzle = GL_RED;
} }
else if (lumaWorkaround.sourceFormat == GL_LUMINANCE_ALPHA) else if (levelInfo.sourceFormat == GL_LUMINANCE_ALPHA)
{ {
// Texture is backed by an RG texture, point the alpha channel at the green // Texture is backed by an RG texture, point the alpha channel at the green
// channel. // channel.
ASSERT(lumaWorkaround.workaroundFormat == GL_RG); ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
resultSwizzle = GL_GREEN; resultSwizzle = GL_GREEN;
} }
else else
...@@ -606,6 +635,42 @@ static inline void SyncSamplerStateSwizzle(const FunctionsGL *functions, ...@@ -606,6 +635,42 @@ static inline void SyncSamplerStateSwizzle(const FunctionsGL *functions,
UNREACHABLE(); UNREACHABLE();
break; break;
} }
}
else if (levelInfo.depthStencilWorkaround)
{
switch (newState.*samplerMember)
{
case GL_RED:
// Don't modify the swizzle state when requesting the red channel.
resultSwizzle = newState.*samplerMember;
break;
case GL_GREEN:
case GL_BLUE:
// Depth textures should sample 0 from the green and blue channels.
resultSwizzle = GL_ZERO;
break;
case GL_ALPHA:
// Depth textures should sample 1 from the alpha channel.
resultSwizzle = GL_ONE;
break;
case GL_ZERO:
case GL_ONE:
// Don't modify the swizzle state when requesting ZERO or ONE.
resultSwizzle = newState.*samplerMember;
break;
default:
UNREACHABLE();
break;
}
}
else
{
UNREACHABLE();
}
// Apply the new swizzle state if needed // Apply the new swizzle state if needed
if (curState.*samplerMember != resultSwizzle) if (curState.*samplerMember != resultSwizzle)
...@@ -650,11 +715,11 @@ void TextureGL::syncSamplerState(size_t textureUnit, const gl::SamplerState &sam ...@@ -650,11 +715,11 @@ void TextureGL::syncSamplerState(size_t textureUnit, const gl::SamplerState &sam
SyncSamplerStateMember(mFunctions, applyTextureFunc, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode); SyncSamplerStateMember(mFunctions, applyTextureFunc, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode);
SyncSamplerStateMember(mFunctions, applyTextureFunc, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc); SyncSamplerStateMember(mFunctions, applyTextureFunc, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc);
const LUMAWorkaround &LUMAWorkaround = mLUMAWorkaroundLevels[samplerState.baseLevel]; const LevelInfoGL &levelInfo = mLevelInfo[samplerState.baseLevel];
SyncSamplerStateSwizzle(mFunctions, applyTextureFunc, LUMAWorkaround, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_R, &gl::SamplerState::swizzleRed); SyncSamplerStateSwizzle(mFunctions, applyTextureFunc, levelInfo, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_R, &gl::SamplerState::swizzleRed);
SyncSamplerStateSwizzle(mFunctions, applyTextureFunc, LUMAWorkaround, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_G, &gl::SamplerState::swizzleGreen); SyncSamplerStateSwizzle(mFunctions, applyTextureFunc, levelInfo, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_G, &gl::SamplerState::swizzleGreen);
SyncSamplerStateSwizzle(mFunctions, applyTextureFunc, LUMAWorkaround, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_B, &gl::SamplerState::swizzleBlue); SyncSamplerStateSwizzle(mFunctions, applyTextureFunc, levelInfo, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_B, &gl::SamplerState::swizzleBlue);
SyncSamplerStateSwizzle(mFunctions, applyTextureFunc, LUMAWorkaround, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_A, &gl::SamplerState::swizzleAlpha); SyncSamplerStateSwizzle(mFunctions, applyTextureFunc, levelInfo, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_A, &gl::SamplerState::swizzleAlpha);
// clang-format on // clang-format on
} }
......
...@@ -20,14 +20,32 @@ class FunctionsGL; ...@@ -20,14 +20,32 @@ class FunctionsGL;
class StateManagerGL; class StateManagerGL;
struct WorkaroundsGL; struct WorkaroundsGL;
struct LUMAWorkaround struct LUMAWorkaroundGL
{ {
bool enabled; bool enabled;
GLenum sourceFormat;
GLenum workaroundFormat; GLenum workaroundFormat;
LUMAWorkaround(); LUMAWorkaroundGL();
LUMAWorkaround(bool enabled, GLenum sourceFormat, GLenum workaroundFormat); LUMAWorkaroundGL(bool enabled, GLenum workaroundFormat);
};
// Structure containing information about format and workarounds for each mip level of the
// TextureGL.
struct LevelInfoGL
{
// Format of the data used in this mip level.
GLenum sourceFormat;
// If this mip level requires sampler-state re-writing so that only a red channel is exposed.
bool depthStencilWorkaround;
// Information about luminance alpha texture workarounds in the core profile.
LUMAWorkaroundGL lumaWorkaround;
LevelInfoGL();
LevelInfoGL(GLenum sourceFormat,
bool depthStencilWorkaround,
const LUMAWorkaroundGL &lumaWorkaround);
}; };
class TextureGL : public TextureImpl class TextureGL : public TextureImpl
...@@ -83,7 +101,7 @@ class TextureGL : public TextureImpl ...@@ -83,7 +101,7 @@ class TextureGL : public TextureImpl
StateManagerGL *mStateManager; StateManagerGL *mStateManager;
BlitGL *mBlitter; BlitGL *mBlitter;
std::vector<LUMAWorkaround> mLUMAWorkaroundLevels; std::vector<LevelInfoGL> mLevelInfo;
mutable gl::SamplerState mAppliedSamplerState; mutable gl::SamplerState mAppliedSamplerState;
GLuint mTextureID; GLuint mTextureID;
......
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