Browse Source

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>
Jeremy Rose 3 years ago
parent
commit
ce5157236c
2 changed files with 382 additions and 0 deletions
  1. 1 0
      patches/angle/.patches
  2. 381 0
      patches/angle/cherry-pick-49e8ff16f1fe.patch

+ 1 - 0
patches/angle/.patches

@@ -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

+ 381 - 0
patches/angle/cherry-pick-49e8ff16f1fe.patch

@@ -0,0 +1,381 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Shahbaz Youssefi <[email protected]>
+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 <[email protected]>
+Reviewed-by: Jamie Madill <[email protected]>
+
+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)