GL/Vulkan: handle depth texture discrepancy

In GLES 3.0, depth textures where changed to behave like RED textures,
but in GLES 2.0 with ARB/OES_depth_texture, they were treated as
luminance textures.
This change produces the expected behavior on GLES 2.0 for the GL
backend and on GLES 3.0 for the Vulkan backend.

Bug: angleproject:3540
Change-Id: Iad6b4e03cf947b27eb97dbb10419bc8bcdb11024
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1666363
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: James Dong <dongja@google.com>
diff --git a/src/libANGLE/renderer/gl/TextureGL.cpp b/src/libANGLE/renderer/gl/TextureGL.cpp
index e52a267..6d02550 100644
--- a/src/libANGLE/renderer/gl/TextureGL.cpp
+++ b/src/libANGLE/renderer/gl/TextureGL.cpp
@@ -1261,22 +1261,22 @@
 
             // Texture state
             case gl::Texture::DIRTY_BIT_SWIZZLE_RED:
-                syncTextureStateSwizzle(functions, GL_TEXTURE_SWIZZLE_R,
+                syncTextureStateSwizzle(context, functions, GL_TEXTURE_SWIZZLE_R,
                                         mState.getSwizzleState().swizzleRed,
                                         &mAppliedSwizzle.swizzleRed);
                 break;
             case gl::Texture::DIRTY_BIT_SWIZZLE_GREEN:
-                syncTextureStateSwizzle(functions, GL_TEXTURE_SWIZZLE_G,
+                syncTextureStateSwizzle(context, functions, GL_TEXTURE_SWIZZLE_G,
                                         mState.getSwizzleState().swizzleGreen,
                                         &mAppliedSwizzle.swizzleGreen);
                 break;
             case gl::Texture::DIRTY_BIT_SWIZZLE_BLUE:
-                syncTextureStateSwizzle(functions, GL_TEXTURE_SWIZZLE_B,
+                syncTextureStateSwizzle(context, functions, GL_TEXTURE_SWIZZLE_B,
                                         mState.getSwizzleState().swizzleBlue,
                                         &mAppliedSwizzle.swizzleBlue);
                 break;
             case gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA:
-                syncTextureStateSwizzle(functions, GL_TEXTURE_SWIZZLE_A,
+                syncTextureStateSwizzle(context, functions, GL_TEXTURE_SWIZZLE_A,
                                         mState.getSwizzleState().swizzleAlpha,
                                         &mAppliedSwizzle.swizzleAlpha);
                 break;
@@ -1404,7 +1404,8 @@
     return getLevelInfo(index.getTarget(), index.getLevelIndex()).nativeInternalFormat;
 }
 
-void TextureGL::syncTextureStateSwizzle(const FunctionsGL *functions,
+void TextureGL::syncTextureStateSwizzle(const gl::Context *context,
+                                        const FunctionsGL *functions,
                                         GLenum name,
                                         GLenum value,
                                         GLenum *outValue)
@@ -1483,8 +1484,18 @@
 
                 case GL_GREEN:
                 case GL_BLUE:
-                    // Depth textures should sample 0 from the green and blue channels.
-                    resultSwizzle = GL_ZERO;
+                    if (context->getClientMajorVersion() <= 2)
+                    {
+                        // In OES_depth_texture/ARB_depth_texture, depth
+                        // textures are treated as luminance.
+                        resultSwizzle = GL_RED;
+                    }
+                    else
+                    {
+                        // In GLES 3.0, depth textures are treated as RED
+                        // textures, so green and blue should be 0.
+                        resultSwizzle = GL_ZERO;
+                    }
                     break;
 
                 case GL_ALPHA:
diff --git a/src/libANGLE/renderer/gl/TextureGL.h b/src/libANGLE/renderer/gl/TextureGL.h
index e4a7342..786ac86 100644
--- a/src/libANGLE/renderer/gl/TextureGL.h
+++ b/src/libANGLE/renderer/gl/TextureGL.h
@@ -40,6 +40,8 @@
     GLenum nativeInternalFormat;
 
     // If this mip level requires sampler-state re-writing so that only a red channel is exposed.
+    // In GLES 2.0, depth textures are treated as luminance, so we check the
+    // context's major version when applying the depth swizzle.
     bool depthStencilWorkaround;
 
     // Information about luminance alpha texture workarounds in the core profile.
@@ -234,7 +236,8 @@
                                                const gl::Buffer *unpackBuffer,
                                                const uint8_t *pixels);
 
-    void syncTextureStateSwizzle(const FunctionsGL *functions,
+    void syncTextureStateSwizzle(const gl::Context *context,
+                                 const FunctionsGL *functions,
                                  GLenum name,
                                  GLenum value,
                                  GLenum *outValue);
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
index 7ce9fa5..48b7b09 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -1153,7 +1153,7 @@
         // Users of the render target expect the views to directly view the desired layer, so we
         // need create a fetch view for each layer as well.
         gl::SwizzleState mappedSwizzle;
-        MapSwizzleState(mImage->getFormat(), mState.getSwizzleState(), &mappedSwizzle);
+        MapSwizzleState(contextVk, mImage->getFormat(), mState.getSwizzleState(), &mappedSwizzle);
         gl::TextureType arrayType = vk::Get2DTextureType(gl::kCubeFaceCount, mImage->getSamples());
         ANGLE_TRY(mImage->initLayerImageView(contextVk, arrayType, mImage->getAspectFlags(),
                                              mappedSwizzle, &mLayerFetchImageView[cubeMapFaceIndex],
@@ -1394,7 +1394,7 @@
     ASSERT(mImage != nullptr);
 
     gl::SwizzleState mappedSwizzle;
-    MapSwizzleState(format, mState.getSwizzleState(), &mappedSwizzle);
+    MapSwizzleState(contextVk, format, mState.getSwizzleState(), &mappedSwizzle);
 
     // TODO: Support non-zero base level for ES 3.0 by passing it to getNativeImageLevel.
     // http://anglebug.com/3148
diff --git a/src/libANGLE/renderer/vulkan/vk_format_utils.cpp b/src/libANGLE/renderer/vulkan/vk_format_utils.cpp
index d0be06c..5628aae 100644
--- a/src/libANGLE/renderer/vulkan/vk_format_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_format_utils.cpp
@@ -11,6 +11,7 @@
 #include "libANGLE/Texture.h"
 #include "libANGLE/formatutils.h"
 #include "libANGLE/renderer/load_functions_table.h"
+#include "libANGLE/renderer/vulkan/ContextVk.h"
 #include "libANGLE/renderer/vulkan/RendererVk.h"
 #include "libANGLE/renderer/vulkan/vk_caps_utils.h"
 
@@ -297,7 +298,8 @@
     out->swizzleAlpha = GetSwizzleStateComponent(first, second.swizzleAlpha);
 }
 
-void MapSwizzleState(const vk::Format &format,
+void MapSwizzleState(const ContextVk *contextVk,
+                     const vk::Format &format,
                      const gl::SwizzleState &swizzleState,
                      gl::SwizzleState *swizzleStateOut)
 {
@@ -328,9 +330,14 @@
         default:
             if (angleFormat.hasDepthOrStencilBits())
             {
-                internalSwizzle.swizzleRed   = angleFormat.depthBits > 0 ? GL_RED : GL_ZERO;
-                internalSwizzle.swizzleGreen = angleFormat.depthBits > 0 ? GL_RED : GL_ZERO;
-                internalSwizzle.swizzleBlue  = angleFormat.depthBits > 0 ? GL_RED : GL_ZERO;
+                bool hasRed = angleFormat.depthBits > 0;
+                // In OES_depth_texture/ARB_depth_texture, depth
+                // textures are treated as luminance.
+                bool hasGB = hasRed && contextVk->getClientMajorVersion() <= 2;
+
+                internalSwizzle.swizzleRed   = hasRed ? GL_RED : GL_ZERO;
+                internalSwizzle.swizzleGreen = hasGB ? GL_RED : GL_ZERO;
+                internalSwizzle.swizzleBlue  = hasGB ? GL_RED : GL_ZERO;
                 internalSwizzle.swizzleAlpha = GL_ONE;
             }
             else
diff --git a/src/libANGLE/renderer/vulkan/vk_format_utils.h b/src/libANGLE/renderer/vulkan/vk_format_utils.h
index 0050e8a..b0efc48 100644
--- a/src/libANGLE/renderer/vulkan/vk_format_utils.h
+++ b/src/libANGLE/renderer/vulkan/vk_format_utils.h
@@ -28,6 +28,7 @@
 namespace rx
 {
 class RendererVk;
+class ContextVk;
 
 namespace vk
 {
@@ -148,7 +149,8 @@
 // calculation is listed in the Vulkan spec at the end of the section 'Vertex Input Description'.
 size_t GetVertexInputAlignment(const vk::Format &format);
 
-void MapSwizzleState(const vk::Format &format,
+void MapSwizzleState(const ContextVk *contextVk,
+                     const vk::Format &format,
                      const gl::SwizzleState &swizzleState,
                      gl::SwizzleState *swizzleStateOut);
 }  // namespace rx