Commit 87fc71c4 by Olli Etuaho Committed by Commit Bot

D3D: Reallocate storage when texture format changes with base level

Different levels of the same texture may have different formats, so changing the base level may affect the format that should be used for the storage. Take this into account in the D3D backend. The added test fails on some GL drivers. TEST=angle_end2end_tests BUG=angleproject:596 Change-Id: I5380e942694a75685ebb510edb01c0489e0d5179 Reviewed-on: https://chromium-review.googlesource.com/344230Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 77ae8d57
...@@ -649,6 +649,7 @@ void TextureD3D::setBaseLevel(GLuint baseLevel) ...@@ -649,6 +649,7 @@ void TextureD3D::setBaseLevel(GLuint baseLevel)
const int oldStorageWidth = std::max(1, getLevelZeroWidth()); const int oldStorageWidth = std::max(1, getLevelZeroWidth());
const int oldStorageHeight = std::max(1, getLevelZeroHeight()); const int oldStorageHeight = std::max(1, getLevelZeroHeight());
const int oldStorageDepth = std::max(1, getLevelZeroDepth()); const int oldStorageDepth = std::max(1, getLevelZeroDepth());
const int oldStorageFormat = getBaseLevelInternalFormat();
mBaseLevel = baseLevel; mBaseLevel = baseLevel;
// When the base level changes, the texture storage might not be valid anymore, since it could // When the base level changes, the texture storage might not be valid anymore, since it could
...@@ -656,8 +657,10 @@ void TextureD3D::setBaseLevel(GLuint baseLevel) ...@@ -656,8 +657,10 @@ void TextureD3D::setBaseLevel(GLuint baseLevel)
const int newStorageWidth = std::max(1, getLevelZeroWidth()); const int newStorageWidth = std::max(1, getLevelZeroWidth());
const int newStorageHeight = std::max(1, getLevelZeroHeight()); const int newStorageHeight = std::max(1, getLevelZeroHeight());
const int newStorageDepth = std::max(1, getLevelZeroDepth()); const int newStorageDepth = std::max(1, getLevelZeroDepth());
if (mTexStorage && (newStorageWidth != oldStorageWidth || const int newStorageFormat = getBaseLevelInternalFormat();
newStorageHeight != oldStorageHeight || newStorageDepth != oldStorageDepth)) if (mTexStorage &&
(newStorageWidth != oldStorageWidth || newStorageHeight != oldStorageHeight ||
newStorageDepth != oldStorageDepth || newStorageFormat != oldStorageFormat))
{ {
markAllImagesDirty(); markAllImagesDirty();
SafeDelete(mTexStorage); SafeDelete(mTexStorage);
......
...@@ -2171,6 +2171,65 @@ TEST_P(Texture2DTestES3, ImmutableTextureBaseLevelOutOfRange) ...@@ -2171,6 +2171,65 @@ TEST_P(Texture2DTestES3, ImmutableTextureBaseLevelOutOfRange)
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
} }
// Test that changing base level works when it affects the format of the texture.
TEST_P(Texture2DTestES3, TextureFormatChangesWithBaseLevel)
{
if (IsNVIDIA() && (isOpenGL() || isGLES()))
{
// Observed rendering corruption on NVIDIA OpenGL.
std::cout << "Test skipped on NVIDIA OpenGL." << std::endl;
return;
}
if (IsIntel() && isOpenGL())
{
// Observed incorrect rendering on Intel OpenGL.
std::cout << "Test skipped on Intel OpenGL." << std::endl;
return;
}
if (IsAMD() && isOpenGL())
{
// Observed incorrect rendering on AMD OpenGL.
std::cout << "Test skipped on AMD OpenGL." << std::endl;
return;
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTexture2D);
std::vector<GLColor> texDataCyan(4u * 4u, GLColor::cyan);
std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// RGBA8 level that's initially unused.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
texDataCyan.data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
// RG8 level that's initially used, with consistent dimensions with level 0 but a different
// format. It reads green channel data from the green and alpha channels of texDataGreen
// (this is a bit hacky but works).
glTexImage2D(GL_TEXTURE_2D, 1, GL_RG8, 2, 2, 0, GL_RG, GL_UNSIGNED_BYTE, texDataGreen.data());
EXPECT_GL_NO_ERROR();
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
// Switch the texture to use the cyan level 0 with the RGBA format.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
EXPECT_GL_NO_ERROR();
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
}
// Test that setting a texture image works when base level is out of range. // Test that setting a texture image works when base level is out of range.
TEST_P(Texture2DTestES3, SetImageWhenBaseLevelOutOfRange) TEST_P(Texture2DTestES3, SetImageWhenBaseLevelOutOfRange)
{ {
......
...@@ -615,6 +615,11 @@ bool ANGLETest::isOpenGL() const ...@@ -615,6 +615,11 @@ bool ANGLETest::isOpenGL() const
return getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE; return getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
} }
bool ANGLETest::isGLES() const
{
return getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
}
EGLint ANGLETest::getPlatformRenderer() const EGLint ANGLETest::getPlatformRenderer() const
{ {
assert(mEGLWindow); assert(mEGLWindow);
......
...@@ -171,6 +171,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters> ...@@ -171,6 +171,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
bool isMultisampleEnabled() const; bool isMultisampleEnabled() const;
bool isOpenGL() const; bool isOpenGL() const;
bool isGLES() const;
EGLint getPlatformRenderer() const; EGLint getPlatformRenderer() const;
void ignoreD3D11SDKLayersWarnings(); void ignoreD3D11SDKLayersWarnings();
......
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