Commit 74ba598f by Corentin Wallez Committed by Commit Bot

Fix cubemap robust resource init for GenerateMipmap

The code in gl::Texture would only check whether the first cube map face is correctly initialized but not for the others. BUG=angleproject:2169 Change-Id: Ib565579a4570e731da785b5c74c8d1a6511ebcd4 Reviewed-on: https://chromium-review.googlesource.com/960571 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 97ab26fc
...@@ -163,6 +163,19 @@ ImageIndexIterator ImageIndexIterator::Make2DMultisample() ...@@ -163,6 +163,19 @@ ImageIndexIterator ImageIndexIterator::Make2DMultisample()
nullptr); nullptr);
} }
ImageIndexIterator ImageIndexIterator::MakeGeneric(TextureType type, GLint minMip, GLint maxMip)
{
if (type == TextureType::CubeMap)
{
return MakeCube(minMip, maxMip);
}
TextureTarget target = NonCubeTextureTypeToTarget(type);
return ImageIndexIterator(type, target, target, Range<GLint>(minMip, maxMip),
Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
nullptr);
}
ImageIndexIterator::ImageIndexIterator(TextureType type, ImageIndexIterator::ImageIndexIterator(TextureType type,
angle::EnumIterator<TextureTarget> targetLow, angle::EnumIterator<TextureTarget> targetLow,
angle::EnumIterator<TextureTarget> targetHigh, angle::EnumIterator<TextureTarget> targetHigh,
......
...@@ -64,6 +64,13 @@ bool operator<(const ImageIndex &a, const ImageIndex &b); ...@@ -64,6 +64,13 @@ bool operator<(const ImageIndex &a, const ImageIndex &b);
bool operator==(const ImageIndex &a, const ImageIndex &b); bool operator==(const ImageIndex &a, const ImageIndex &b);
bool operator!=(const ImageIndex &a, const ImageIndex &b); bool operator!=(const ImageIndex &a, const ImageIndex &b);
// To be used like this:
//
// ImageIndexIterator it = ...;
// while (it.hasNext())
// {
// ImageIndex current = it.next();
// }
class ImageIndexIterator class ImageIndexIterator
{ {
public: public:
...@@ -75,6 +82,7 @@ class ImageIndexIterator ...@@ -75,6 +82,7 @@ class ImageIndexIterator
static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer); static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer);
static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts); static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts);
static ImageIndexIterator Make2DMultisample(); static ImageIndexIterator Make2DMultisample();
static ImageIndexIterator MakeGeneric(TextureType type, GLint minMip, GLint maxMip);
ImageIndex next(); ImageIndex next();
ImageIndex current() const; ImageIndex current() const;
......
...@@ -38,19 +38,6 @@ size_t GetImageDescIndex(TextureTarget target, size_t level) ...@@ -38,19 +38,6 @@ size_t GetImageDescIndex(TextureTarget target, size_t level)
: level; : level;
} }
ImageIndex GetImageIndexFromDescIndex(TextureType type, size_t descIndex)
{
if (type == TextureType::CubeMap)
{
size_t faceIndex = descIndex % 6;
size_t mipIndex = descIndex / 6;
return ImageIndex::MakeCube(CubeFaceIndexToTextureTarget(faceIndex),
static_cast<GLint>(mipIndex));
}
return ImageIndex::MakeGeneric(NonCubeTextureTypeToTarget(type), static_cast<GLint>(descIndex));
}
InitState DetermineInitState(const Context *context, const uint8_t *pixels) InitState DetermineInitState(const Context *context, const uint8_t *pixels)
{ {
// Can happen in tests. // Can happen in tests.
...@@ -1228,26 +1215,36 @@ Error Texture::generateMipmap(const Context *context) ...@@ -1228,26 +1215,36 @@ Error Texture::generateMipmap(const Context *context)
const GLuint baseLevel = mState.getEffectiveBaseLevel(); const GLuint baseLevel = mState.getEffectiveBaseLevel();
const GLuint maxLevel = mState.getMipmapMaxLevel(); const GLuint maxLevel = mState.getMipmapMaxLevel();
if (maxLevel > baseLevel) if (maxLevel <= baseLevel)
{
return NoError();
}
syncState();
// Clear the base image(s) immediately if needed
if (context->isRobustResourceInitEnabled())
{ {
syncState(); ImageIndexIterator it =
const ImageDesc &baseImageInfo = ImageIndexIterator::MakeGeneric(mState.mType, baseLevel, baseLevel + 1);
mState.getImageDesc(mState.getBaseImageTarget(), baseLevel); while (it.hasNext())
// TODO(cwallez@chromium.org): This doesn't handle cubemaps correctly.
// Clear the base image immediately if necessary.
if (context->isRobustResourceInitEnabled() &&
baseImageInfo.initState == InitState::MayNeedInit)
{ {
ANGLE_TRY( const ImageIndex index = it.next();
initializeContents(context, GetImageIndexFromDescIndex(mState.mType, baseLevel))); const ImageDesc &desc = mState.getImageDesc(index.target, index.mipIndex);
if (desc.initState == InitState::MayNeedInit)
{
ANGLE_TRY(initializeContents(context, index));
}
} }
}
ANGLE_TRY(mTexture->generateMipmap(context)); ANGLE_TRY(mTexture->generateMipmap(context));
mState.setImageDescChain(baseLevel, maxLevel, baseImageInfo.size, baseImageInfo.format, // Propagate the format and size of the bsae mip to the smaller ones. Cube maps are guaranteed
InitState::Initialized); // to have faces of the same size and format so any faces can be picked.
} const ImageDesc &baseImageInfo = mState.getImageDesc(mState.getBaseImageTarget(), baseLevel);
mState.setImageDescChain(baseLevel, maxLevel, baseImageInfo.size, baseImageInfo.format,
InitState::Initialized);
signalDirty(context, InitState::Initialized); signalDirty(context, InitState::Initialized);
...@@ -1468,16 +1465,18 @@ Error Texture::ensureInitialized(const Context *context) ...@@ -1468,16 +1465,18 @@ Error Texture::ensureInitialized(const Context *context)
bool anyDirty = false; bool anyDirty = false;
for (size_t descIndex = 0; descIndex < mState.mImageDescs.size(); ++descIndex) ImageIndexIterator it =
ImageIndexIterator::MakeGeneric(mState.mType, 0, IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1);
while (it.hasNext())
{ {
auto &imageDesc = mState.mImageDescs[descIndex]; const ImageIndex index = it.next();
if (imageDesc.initState == InitState::MayNeedInit) ImageDesc &desc = mState.mImageDescs[GetImageDescIndex(index.target, index.mipIndex)];
if (desc.initState == InitState::MayNeedInit)
{ {
ASSERT(mState.mInitState == InitState::MayNeedInit); ASSERT(mState.mInitState == InitState::MayNeedInit);
const auto &imageIndex = GetImageIndexFromDescIndex(mState.mType, descIndex); ANGLE_TRY(initializeContents(context, index));
ANGLE_TRY(initializeContents(context, imageIndex)); desc.initState = InitState::Initialized;
imageDesc.initState = InitState::Initialized; anyDirty = true;
anyDirty = true;
} }
} }
if (anyDirty) if (anyDirty)
......
...@@ -981,6 +981,43 @@ TEST_P(RobustResourceInitTestES3, GenerateMipmap) ...@@ -981,6 +981,43 @@ TEST_P(RobustResourceInitTestES3, GenerateMipmap)
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
} }
// Tests creating mipmaps for cube maps with robust resource init.
TEST_P(RobustResourceInitTestES3, GenerateMipmapCubeMap)
{
ANGLE_SKIP_TEST_IF(!hasGLExtension());
constexpr GLint kTextureSize = 16;
constexpr GLint kTextureLevels = 5;
// Initialize a 16x16 RGBA8 texture with no data.
GLTexture tex;
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
++target)
{
glTexImage2D(target, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Generate mipmaps and verify all the mips.
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
ASSERT_GL_NO_ERROR();
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
++target)
{
for (GLint level = 0; level < kTextureLevels; ++level)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, tex, level);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
}
}
}
// Test blitting a framebuffer out-of-bounds. Multiple iterations. // Test blitting a framebuffer out-of-bounds. Multiple iterations.
TEST_P(RobustResourceInitTestES3, BlitFramebufferOutOfBounds) TEST_P(RobustResourceInitTestES3, BlitFramebufferOutOfBounds)
{ {
......
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