chore: cherry-pick 49e8ff16f1fe from angle (#33181)

* chore: cherry-pick 49e8ff16f1fe from angle

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
This commit is contained in:
Jeremy Rose
2022-03-08 07:54:31 -08:00
committed by GitHub
parent 8ec2469379
commit ce5157236c
2 changed files with 382 additions and 0 deletions

View File

@@ -7,3 +7,4 @@ vangle_change_the_default_vulkan_device_choose_logic.patch
m96_validate_samplerformat.patch
m98_vulkan_fix_vkcmdresolveimage_extents.patch
m98_vulkan_fix_vkcmdresolveimage_offsets.patch
cherry-pick-49e8ff16f1fe.patch

View File

@@ -0,0 +1,381 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shahbaz Youssefi <syoussefi@chromium.org>
Date: Tue, 25 Jan 2022 12:15:16 -0500
Subject: M99: Vulkan: Fix texture array level redefinition
When a level of a texture is redefined, all staged updates to that level
should be removed, not the ones specific to the new layers. The bug
fixed was that if the texture was redefined to have its number of layers
changed, the staged higher-layer-count update to the image was not
removed.
Bug: chromium:1289383
Change-Id: Iab79c38d846d1abbdd92e11b1b60a3adf0fbde4c
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3441309
Reviewed-by: Lingfeng Yang <lfy@google.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
index b43f41dbae29356f1ffe4f961ed83e0f0e9cdcd2..610f720b68d37aaddf142b0dca538749386cef7e 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -1553,12 +1553,25 @@ angle::Result TextureVk::redefineLevel(const gl::Context *context,
if (mImage != nullptr)
{
- // If there is any staged changes for this index, we can remove them since we're going to
+ // If there are any staged changes for this index, we can remove them since we're going to
// override them with this call.
gl::LevelIndex levelIndexGL(index.getLevelIndex());
uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
- mImage->removeSingleSubresourceStagedUpdates(contextVk, levelIndexGL, layerIndex,
- index.getLayerCount());
+ if (gl::IsArrayTextureType(index.getType()))
+ {
+ // A multi-layer texture is being redefined, remove all updates to this level; the
+ // number of layers may have changed.
+ mImage->removeStagedUpdates(contextVk, levelIndexGL, levelIndexGL);
+ }
+ else
+ {
+ // Otherwise remove only updates to this layer. For example, cube map updates can be
+ // done through glTexImage2D, one per cube face (i.e. layer) and so should not remove
+ // updates to the other layers.
+ ASSERT(index.getLayerCount() == 1);
+ mImage->removeSingleSubresourceStagedUpdates(contextVk, levelIndexGL, layerIndex,
+ index.getLayerCount());
+ }
if (mImage->valid())
{
diff --git a/src/tests/gl_tests/MipmapTest.cpp b/src/tests/gl_tests/MipmapTest.cpp
index 8a6d01ca36a84a9e294de3f6f0114ee7a54e1d9a..957a52304edc9aa245f9f21e5557cc105cbad789 100644
--- a/src/tests/gl_tests/MipmapTest.cpp
+++ b/src/tests/gl_tests/MipmapTest.cpp
@@ -1686,6 +1686,106 @@ TEST_P(MipmapTestES3, MipmapsForTexture3D)
EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
}
+// Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug
+// in the Vulkan backend where the old higher-layer-count data upload was not removed.
+TEST_P(MipmapTestES3, TextureArrayRedefineThenGenerateMipmap)
+{
+ int px = getWindowWidth() / 2;
+ int py = getWindowHeight() / 2;
+
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture);
+
+ // Fill the whole texture with red, then redefine it and fill with green
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsRed.data());
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsGreen.data());
+
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ EXPECT_GL_NO_ERROR();
+
+ // Generate mipmaps
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
+ EXPECT_GL_NO_ERROR();
+
+ glUseProgram(mArrayProgram);
+ EXPECT_GL_NO_ERROR();
+
+ // Draw the first slice
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
+ drawQuad(mArrayProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
+
+ // Draw the second slice
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
+ drawQuad(mArrayProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
+}
+
+// Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in
+// the Vulkan backend where the old higher-layer-count data upload was not removed.
+TEST_P(MipmapTestES3, TextureArrayUseThenRedefineThenGenerateMipmap)
+{
+ int px = getWindowWidth() / 2;
+ int py = getWindowHeight() / 2;
+
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture);
+
+ // Fill the whole texture with red.
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsRed.data());
+
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ EXPECT_GL_NO_ERROR();
+
+ // Generate mipmap
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
+ EXPECT_GL_NO_ERROR();
+
+ glUseProgram(mArrayProgram);
+ EXPECT_GL_NO_ERROR();
+
+ // Draw the first slice
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
+ drawQuad(mArrayProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
+
+ // Draw the fourth slice
+ glUniform1i(mTextureArraySliceUniformLocation, 3);
+ drawQuad(mArrayProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
+
+ // Redefine the image and fill with green
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsGreen.data());
+
+ // Generate mipmap
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
+ EXPECT_GL_NO_ERROR();
+
+ // Draw the first slice
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
+ drawQuad(mArrayProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
+
+ // Draw the second slice
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
+ drawQuad(mArrayProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
+}
+
// Create a 2D texture with levels 0-2, call GenerateMipmap with base level 1 so that level 0 stays
// the same, and then sample levels 0 and 2.
// GLES 3.0.4 section 3.8.10:
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
index 56bef0186234f59d370669c21f588ea9c5c356fc..772fe27daac3ac0b5f54b8319cef6aa9c980208a 100644
--- a/src/tests/gl_tests/TextureTest.cpp
+++ b/src/tests/gl_tests/TextureTest.cpp
@@ -1028,31 +1028,37 @@ class SamplerArrayAsFunctionParameterTest : public SamplerArrayTest
class Texture2DArrayTestES3 : public TexCoordDrawTest
{
protected:
- Texture2DArrayTestES3() : TexCoordDrawTest(), m2DArrayTexture(0), mTextureArrayLocation(-1) {}
+ Texture2DArrayTestES3()
+ : TexCoordDrawTest(),
+ m2DArrayTexture(0),
+ mTextureArrayLocation(-1),
+ mTextureArraySliceUniformLocation(-1)
+ {}
const char *getVertexShaderSource() override
{
- return "#version 300 es\n"
- "out vec2 texcoord;\n"
- "in vec4 position;\n"
- "void main()\n"
- "{\n"
- " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
- " texcoord = (position.xy * 0.5) + 0.5;\n"
- "}\n";
+ return R"(#version 300 es
+out vec2 texcoord;
+in vec4 position;
+void main()
+{
+ gl_Position = vec4(position.xy, 0.0, 1.0);
+ texcoord = (position.xy * 0.5) + 0.5;
+})";
}
const char *getFragmentShaderSource() override
{
- return "#version 300 es\n"
- "precision highp float;\n"
- "uniform highp sampler2DArray tex2DArray;\n"
- "in vec2 texcoord;\n"
- "out vec4 fragColor;\n"
- "void main()\n"
- "{\n"
- " fragColor = texture(tex2DArray, vec3(texcoord.x, texcoord.y, 0.0));\n"
- "}\n";
+ return R"(#version 300 es
+precision highp float;
+uniform highp sampler2DArray tex2DArray;
+uniform int slice;
+in vec2 texcoord;
+out vec4 fragColor;
+void main()
+{
+ fragColor = texture(tex2DArray, vec3(texcoord, float(slice)));
+})";
}
void testSetUp() override
@@ -1064,6 +1070,9 @@ class Texture2DArrayTestES3 : public TexCoordDrawTest
mTextureArrayLocation = glGetUniformLocation(mProgram, "tex2DArray");
ASSERT_NE(-1, mTextureArrayLocation);
+ mTextureArraySliceUniformLocation = glGetUniformLocation(mProgram, "slice");
+ ASSERT_NE(-1, mTextureArraySliceUniformLocation);
+
glGenTextures(1, &m2DArrayTexture);
ASSERT_GL_NO_ERROR();
}
@@ -1076,6 +1085,7 @@ class Texture2DArrayTestES3 : public TexCoordDrawTest
GLuint m2DArrayTexture;
GLint mTextureArrayLocation;
+ GLint mTextureArraySliceUniformLocation;
};
class TextureSizeTextureArrayTest : public TexCoordDrawTest
@@ -1718,28 +1728,28 @@ class Texture2DArrayIntegerTestES3 : public Texture2DArrayTestES3
const char *getVertexShaderSource() override
{
- return "#version 300 es\n"
- "out vec2 texcoord;\n"
- "in vec4 position;\n"
- "void main()\n"
- "{\n"
- " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
- " texcoord = (position.xy * 0.5) + 0.5;\n"
- "}\n";
+ return R"(#version 300 es
+out vec2 texcoord;
+in vec4 position;
+void main()
+{
+ gl_Position = vec4(position.xy, 0.0, 1.0);
+ texcoord = (position.xy * 0.5) + 0.5;
+})";
}
const char *getFragmentShaderSource() override
{
- return "#version 300 es\n"
- "precision highp float;\n"
- "uniform highp usampler2DArray tex2DArray;\n"
- "in vec2 texcoord;\n"
- "out vec4 fragColor;\n"
- "void main()\n"
- "{\n"
- " fragColor = vec4(texture(tex2DArray, vec3(texcoord.x, texcoord.y, "
- "0.0)))/255.0;\n"
- "}\n";
+ return R"(#version 300 es
+precision highp float;
+uniform highp usampler2DArray tex2DArray;
+uniform int slice;
+in vec2 texcoord;
+out vec4 fragColor;
+void main()
+{
+ fragColor = vec4(texture(tex2DArray, vec3(texcoord, slice)))/255.0;
+})";
}
};
@@ -5112,6 +5122,94 @@ TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensio
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
}
+// Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug
+// in the Vulkan backend where the old higher-layer-count data upload was not removed.
+TEST_P(Texture2DArrayTestES3, TextureArrayRedefineThenUse)
+{
+ int px = getWindowWidth() / 2;
+ int py = getWindowHeight() / 2;
+
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
+
+ // Fill the whole texture with red, then redefine it and fill with green
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsRed.data());
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsGreen.data());
+
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ EXPECT_GL_NO_ERROR();
+
+ glUseProgram(mProgram);
+ EXPECT_GL_NO_ERROR();
+
+ // Draw the first slice
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
+ drawQuad(mProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
+
+ // Draw the second slice
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
+ drawQuad(mProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
+}
+
+// Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in
+// the Vulkan backend where the old higher-layer-count data upload was not removed.
+TEST_P(Texture2DArrayTestES3, TextureArrayUseThenRedefineThenUse)
+{
+ int px = getWindowWidth() / 2;
+ int py = getWindowHeight() / 2;
+
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
+
+ // Fill the whole texture with red.
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsRed.data());
+
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ EXPECT_GL_NO_ERROR();
+
+ glUseProgram(mProgram);
+ EXPECT_GL_NO_ERROR();
+
+ // Draw the first slice
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
+ drawQuad(mProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
+
+ // Draw the fourth slice
+ glUniform1i(mTextureArraySliceUniformLocation, 3);
+ drawQuad(mProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
+
+ // Redefine the image and fill with green
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ pixelsGreen.data());
+
+ // Draw the first slice
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
+ drawQuad(mProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
+
+ // Draw the second slice
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
+ drawQuad(mProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
+}
+
// Test that texture completeness is updated if texture max level changes.
// GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel)