GL: implement Feature::TransientAttachments

Implement support for TransientAttachment via Renderbuffers.
This is a partial reland of https://dawn-review.googlesource.com/c/dawn/+/308775
Renderbuffers are only used for texture formats containing depth or stencil.

Bug: 462577182

Change-Id: I92090e92d6e4e1ee1d732ce97d245aae66ea2ef6
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/323915
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Stephen White <senorblanco@chromium.org>
diff --git a/src/dawn/native/opengl/CommandBufferGL.cpp b/src/dawn/native/opengl/CommandBufferGL.cpp
index e1f6122..e2a5891 100644
--- a/src/dawn/native/opengl/CommandBufferGL.cpp
+++ b/src/dawn/native/opengl/CommandBufferGL.cpp
@@ -415,7 +415,7 @@
                 },
                 [&](const TextureBindingInfo&) -> MaybeError {
                     TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex));
-                    GLuint handle = view->GetHandle();
+                    GLuint handle = view->GetTextureHandle();
                     GLenum target = view->GetGLTarget();
                     FlatBindingIndex viewIndex = indices[bindingIndex];
 
@@ -477,7 +477,7 @@
                 [&](const StorageTextureBindingInfo& layout) -> MaybeError {
                     TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex));
                     Texture* texture = ToBackend(view->GetTexture());
-                    GLuint handle = texture->GetHandle();
+                    GLuint handle = texture->GetTextureHandle();
                     FlatBindingIndex imageIndex = indices[bindingIndex];
 
                     GLenum access;
@@ -961,7 +961,7 @@
                 DAWN_TRY(texture->EnsureSubresourceContentInitialized(gl, subresources));
                 // The only way to move data from a texture to a buffer in GL is via
                 // glReadPixels with a pack buffer. Create a temporary FBO for the copy.
-                DAWN_GL_TRY(gl, BindTexture(target, texture->GetHandle()));
+                DAWN_GL_TRY(gl, BindTexture(target, texture->GetTextureHandle()));
 
                 GLuint readFBO = 0;
                 DAWN_GL_TRY(gl, GenFramebuffers(1, &readFBO));
@@ -1010,9 +1010,9 @@
                     case wgpu::TextureDimension::e2D: {
                         if (target == GL_TEXTURE_2D) {
                             DAWN_ASSERT(texture->GetArrayLayers() == 1);
-                            DAWN_GL_TRY(
-                                gl, FramebufferTexture2D(GL_READ_FRAMEBUFFER, glAttachment, target,
-                                                         texture->GetHandle(), src.mipLevel));
+                            DAWN_GL_TRY(gl, FramebufferTexture2D(
+                                                GL_READ_FRAMEBUFFER, glAttachment, target,
+                                                texture->GetTextureHandle(), src.mipLevel));
                             DAWN_GL_TRY(gl, ReadPixels(dchecked_cast<uint32_t>(src.origin.x),
                                                        dchecked_cast<uint32_t>(src.origin.y),
                                                        dchecked_cast<uint32_t>(copySize.width),
@@ -1026,10 +1026,10 @@
                             for (TexelCount z{0u}; z < copySize.depthOrArrayLayers; ++z) {
                                 GLenum cubeMapTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X +
                                                        dchecked_cast<uint32_t>(z + src.origin.z);
-                                DAWN_GL_TRY(
-                                    gl, FramebufferTexture2D(GL_READ_FRAMEBUFFER, glAttachment,
-                                                             cubeMapTarget, texture->GetHandle(),
-                                                             src.mipLevel));
+                                DAWN_GL_TRY(gl, FramebufferTexture2D(GL_READ_FRAMEBUFFER,
+                                                                     glAttachment, cubeMapTarget,
+                                                                     texture->GetTextureHandle(),
+                                                                     src.mipLevel));
                                 DAWN_GL_TRY(gl, ReadPixels(dchecked_cast<uint32_t>(src.origin.x),
                                                            dchecked_cast<uint32_t>(src.origin.y),
                                                            dchecked_cast<uint32_t>(copySize.width),
@@ -1047,10 +1047,10 @@
                         const uint64_t bytesPerImage =
                             blockInfo.ToBytes(dst.blocksPerRow * dst.rowsPerImage);
                         for (TexelCount z{0u}; z < copySize.depthOrArrayLayers; ++z) {
-                            DAWN_GL_TRY(
-                                gl, FramebufferTextureLayer(
-                                        GL_READ_FRAMEBUFFER, glAttachment, texture->GetHandle(),
-                                        src.mipLevel, dchecked_cast<uint32_t>(src.origin.z + z)));
+                            DAWN_GL_TRY(gl, FramebufferTextureLayer(
+                                                GL_READ_FRAMEBUFFER, glAttachment,
+                                                texture->GetTextureHandle(), src.mipLevel,
+                                                dchecked_cast<uint32_t>(src.origin.z + z)));
                             DAWN_GL_TRY(gl, ReadPixels(dchecked_cast<uint32_t>(src.origin.x),
                                                        dchecked_cast<uint32_t>(src.origin.y),
                                                        dchecked_cast<uint32_t>(copySize.width),
@@ -1104,9 +1104,9 @@
                 } else {
                     DAWN_TRY(dstTexture->EnsureSubresourceContentInitialized(gl, dstRange));
                 }
-                DAWN_TRY(CopyImageSubData(gl, src.aspect, srcTexture->GetHandle(),
+                DAWN_TRY(CopyImageSubData(gl, src.aspect, srcTexture->GetTextureHandle(),
                                           srcTexture->GetGLTarget(), src.mipLevel,
-                                          src.origin.ToOrigin3D(), dstTexture->GetHandle(),
+                                          src.origin.ToOrigin3D(), dstTexture->GetTextureHandle(),
                                           dstTexture->GetGLTarget(), dst.mipLevel,
                                           dst.origin.ToOrigin3D(), copySize.ToExtent3D()));
                 break;
@@ -1728,7 +1728,7 @@
     GLenum target = texture->GetGLTarget();
     data = DAWN_UNSAFE_TODO(static_cast<const uint8_t*>(data) + dataLayout.offset);
     DAWN_GL_TRY(gl, ActiveTexture(GL_TEXTURE0));
-    DAWN_GL_TRY(gl, BindTexture(target, texture->GetHandle()));
+    DAWN_GL_TRY(gl, BindTexture(target, texture->GetTextureHandle()));
     const TypedTexelBlockInfo& blockInfo = GetBlockInfo(destination);
     const BlockExtent3D blockCopySize = blockInfo.ToBlock(copySize);
     const uint64_t bytesPerImage = dataLayout.rowsPerImage * dataLayout.bytesPerRow;
diff --git a/src/dawn/native/opengl/PhysicalDeviceGL.cpp b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
index 426e011..1f66c9f 100644
--- a/src/dawn/native/opengl/PhysicalDeviceGL.cpp
+++ b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
@@ -310,6 +310,8 @@
     if (SupportTextureComponentSwizzle()) {
         EnableFeature(Feature::TextureComponentSwizzle);
     }
+
+    EnableFeature(Feature::TransientAttachments);
 }
 
 namespace {
diff --git a/src/dawn/native/opengl/TextureGL.cpp b/src/dawn/native/opengl/TextureGL.cpp
index f97f4f1..cbb43ba 100644
--- a/src/dawn/native/opengl/TextureGL.cpp
+++ b/src/dawn/native/opengl/TextureGL.cpp
@@ -262,28 +262,49 @@
     // Wrap the handle in a Texture class early so that it is deleted if initialization fails
     Ref<Texture> texture = AcquireRef(new Texture(device, descriptor, 0, OwnsHandle::Yes));
 
-    bool clear = device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting);
-    DAWN_TRY(device->EnqueueGL([texture, clear](const OpenGLFunctions& gl) -> MaybeError {
-        DAWN_GL_TRY(gl, GenTextures(1, &texture->mHandle));
+    if (texture->IsRenderbuffer()) {
+        DAWN_TRY(device->EnqueueGL([texture](const OpenGLFunctions& gl) -> MaybeError {
+            DAWN_GL_TRY(gl, GenRenderbuffers(1, &texture->mRenderbufferHandle));
 
-        GLenum target = texture->GetGLTarget();
-        uint32_t levels = texture->GetNumMipLevels();
-        const GLFormat& glFormat = texture->GetGLFormat();
+            const GLFormat& glFormat = texture->GetGLFormat();
 
-        DAWN_GL_TRY(gl, BindTexture(target, texture->mHandle));
-        DAWN_TRY(AllocateTexture(gl, target, texture->GetSampleCount(), levels, glFormat,
-                                 texture->GetBaseSize()));
+            DAWN_GL_TRY(gl, BindRenderbuffer(GL_RENDERBUFFER, texture->mRenderbufferHandle));
+            auto width = texture->GetBaseSize().width;
+            auto height = texture->GetBaseSize().height;
+            if (texture->GetSampleCount() > 1) {
+                DAWN_GL_TRY(
+                    gl, RenderbufferStorageMultisample(GL_RENDERBUFFER, texture->GetSampleCount(),
+                                                       glFormat.internalFormat, width, height));
+            } else {
+                DAWN_GL_TRY(gl, RenderbufferStorage(GL_RENDERBUFFER, glFormat.internalFormat, width,
+                                                    height));
+            }
+            return {};
+        }));
+    } else {
+        bool clear = device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting);
+        DAWN_TRY(device->EnqueueGL([texture, clear](const OpenGLFunctions& gl) -> MaybeError {
+            DAWN_GL_TRY(gl, GenTextures(1, &texture->mTextureHandle));
 
-        // The texture is not complete if it uses mipmapping and not all levels up to
-        // MAX_LEVEL have been defined.
-        DAWN_GL_TRY(gl, TexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels - 1));
+            GLenum target = texture->GetGLTarget();
+            uint32_t levels = texture->GetNumMipLevels();
+            const GLFormat& glFormat = texture->GetGLFormat();
 
-        if (clear) {
-            DAWN_TRY(texture->ClearTexture(gl, texture->GetAllSubresources(),
-                                           TextureBase::ClearValue::NonZero));
-        }
-        return {};
-    }));
+            DAWN_GL_TRY(gl, BindTexture(target, texture->mTextureHandle));
+            DAWN_TRY(AllocateTexture(gl, target, texture->GetSampleCount(), levels, glFormat,
+                                     texture->GetBaseSize()));
+
+            // The texture is not complete if it uses mipmapping and not all levels up to
+            // MAX_LEVEL have been defined.
+            DAWN_GL_TRY(gl, TexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels - 1));
+
+            if (clear) {
+                DAWN_TRY(texture->ClearTexture(gl, texture->GetAllSubresources(),
+                                               TextureBase::ClearValue::NonZero));
+            }
+            return {};
+        }));
+    }
     return std::move(texture);
 }
 
@@ -296,7 +317,7 @@
     Ref<Texture> texture = AcquireRef(new Texture(device, descriptor, 0, OwnsHandle::Yes));
     DAWN_TRY(device->EnqueueGL([texture, memory = Ref<SharedTextureMemory>(memory)](
                                    const OpenGLFunctions& gl) -> MaybeError {
-        DAWN_TRY_ASSIGN(texture->mHandle, memory->GenerateGLTexture(gl));
+        DAWN_TRY_ASSIGN(texture->mTextureHandle, memory->GenerateGLTexture(gl));
         return {};
     }));
 
@@ -306,30 +327,54 @@
 
 Texture::Texture(Device* device,
                  const UnpackedPtr<TextureDescriptor>& descriptor,
-                 GLuint handle,
+                 GLuint textureHandle,
                  OwnsHandle ownsHandle)
-    : TextureBase(device, descriptor), mHandle(handle), mOwnsHandle(ownsHandle) {
+    : TextureBase(device, descriptor),
+      mTextureHandle(textureHandle),
+      mRenderbufferHandle(0),
+      mOwnsHandle(ownsHandle) {
     mTarget = TargetForTextureViewDimension(GetCompatibilityTextureBindingViewDimension(),
                                             descriptor->sampleCount);
 }
 
 Texture::~Texture() {}
 
+bool Texture::IsRenderbuffer() const {
+    return ((GetUsage() & wgpu::TextureUsage::TransientAttachment) != 0) &&
+           GetFormat().HasDepthOrStencil();
+}
+
 void Texture::DestroyImpl(DestroyReason reason) {
     TextureBase::DestroyImpl(reason);
     if (mOwnsHandle == OwnsHandle::Yes) {
-        IgnoreErrors(
-            ToBackend(GetDevice())
-                ->EnqueueDestroyGL(this, &Texture::GetHandle, reason,
-                                   [](const OpenGLFunctions& gl, GLuint handle) -> MaybeError {
-                                       DAWN_GL_TRY_IGNORE_ERRORS(gl, DeleteTextures(1, &handle));
-                                       return {};
-                                   }));
+        if (IsRenderbuffer()) {
+            IgnoreErrors(ToBackend(GetDevice())
+                             ->EnqueueDestroyGL(
+                                 this, &Texture::GetRenderbufferHandle, reason,
+                                 [](const OpenGLFunctions& gl, GLuint handle) -> MaybeError {
+                                     DAWN_GL_TRY_IGNORE_ERRORS(gl, DeleteRenderbuffers(1, &handle));
+                                     return {};
+                                 }));
+        } else {
+            IgnoreErrors(ToBackend(GetDevice())
+                             ->EnqueueDestroyGL(
+                                 this, &Texture::GetTextureHandle, reason,
+                                 [](const OpenGLFunctions& gl, GLuint handle) -> MaybeError {
+                                     DAWN_GL_TRY_IGNORE_ERRORS(gl, DeleteTextures(1, &handle));
+                                     return {};
+                                 }));
+        }
     }
 }
 
-GLuint Texture::GetHandle() const {
-    return mHandle;
+GLuint Texture::GetTextureHandle() const {
+    DAWN_ASSERT(mTextureHandle != 0 && !IsRenderbuffer());
+    return mTextureHandle;
+}
+
+GLuint Texture::GetRenderbufferHandle() const {
+    DAWN_ASSERT(mRenderbufferHandle != 0 && IsRenderbuffer());
+    return mRenderbufferHandle;
 }
 
 GLenum Texture::GetGLTarget() const {
@@ -343,6 +388,7 @@
 MaybeError Texture::ClearTexture(const OpenGLFunctions& gl,
                                  const SubresourceRange& range,
                                  TextureBase::ClearValue clearValue) {
+    DAWN_ASSERT(!IsRenderbuffer());
     Device* device = ToBackend(GetDevice());
 
     uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
@@ -407,7 +453,7 @@
                         continue;
                     }
                     DAWN_TRY(FramebufferTextureHelper(gl, mTarget, GL_DRAW_FRAMEBUFFER, attachment,
-                                                      GetHandle(), level, layer));
+                                                      GetTextureHandle(), level, layer));
                     DAWN_TRY(DoClear(aspectsToClear));
                 }
             }
@@ -455,13 +501,14 @@
                         continue;
                     }
                     if (gl.IsAtLeastGL(4, 4)) {
-                        DAWN_GL_TRY(gl, ClearTexSubImage(mHandle, static_cast<GLint>(level), 0, 0,
-                                                         static_cast<GLint>(layer), mipSize.width,
-                                                         mipSize.height, mipSize.depthOrArrayLayers,
-                                                         glFormat.format, glFormat.type,
-                                                         clearValue == TextureBase::ClearValue::Zero
-                                                             ? kClearColorDataBytes0.data()
-                                                             : kClearColorDataBytes255.data()));
+                        DAWN_GL_TRY(
+                            gl, ClearTexSubImage(mTextureHandle, static_cast<GLint>(level), 0, 0,
+                                                 static_cast<GLint>(layer), mipSize.width,
+                                                 mipSize.height, mipSize.depthOrArrayLayers,
+                                                 glFormat.format, glFormat.type,
+                                                 clearValue == TextureBase::ClearValue::Zero
+                                                     ? kClearColorDataBytes0.data()
+                                                     : kClearColorDataBytes255.data()));
                         continue;
                     }
 
@@ -512,12 +559,13 @@
                                 .depthOrArrayLayers;
                         for (GLint z = 0; z < static_cast<GLint>(depth); ++z) {
                             DAWN_GL_TRY(gl, FramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attachment,
-                                                                    GetHandle(), level, z));
+                                                                    GetTextureHandle(), level, z));
                             DAWN_TRY(DoClear());
                         }
                     } else {
                         DAWN_TRY(FramebufferTextureHelper(gl, mTarget, GL_DRAW_FRAMEBUFFER,
-                                                          attachment, GetHandle(), level, layer));
+                                                          attachment, GetTextureHandle(), level,
+                                                          layer));
                         DAWN_TRY(DoClear());
                     }
 
@@ -646,19 +694,24 @@
                  ->EnqueueGL([view, texture = Ref<Texture>(ToBackend(texture))](
                                  const OpenGLFunctions& gl) -> MaybeError {
                      if (texture->IsDestroyed()) {
-                         view->mHandle = 0;
+                         view->mTextureHandle = 0;
+                         view->mRenderbufferHandle = 0;
                      } else if (view->mOwnsHandle == OwnsHandle::Yes) {
                          GLuint handle = 0;
                          DAWN_ASSERT(gl.IsAtLeastGL(4, 3));
                          DAWN_GL_TRY(gl, GenTextures(1, &handle));
-                         DAWN_GL_TRY(gl,
-                                     TextureView(handle, view->GetGLTarget(), texture->GetHandle(),
-                                                 view->GetInternalFormat(), view->GetBaseMipLevel(),
-                                                 view->GetLevelCount(), view->GetBaseArrayLayer(),
-                                                 view->GetLayerCount()));
-                         view->mHandle = handle;
+                         DAWN_GL_TRY(
+                             gl, TextureView(handle, view->GetGLTarget(),
+                                             texture->GetTextureHandle(), view->GetInternalFormat(),
+                                             view->GetBaseMipLevel(), view->GetLevelCount(),
+                                             view->GetBaseArrayLayer(), view->GetLayerCount()));
+                         view->mTextureHandle = handle;
                      } else {
-                         view->mHandle = texture->GetHandle();
+                         if (texture->IsRenderbuffer()) {
+                             view->mRenderbufferHandle = texture->GetRenderbufferHandle();
+                         } else {
+                             view->mTextureHandle = texture->GetTextureHandle();
+                         }
                      }
                      return {};
                  }));
@@ -677,7 +730,7 @@
     if (mOwnsHandle == OwnsHandle::Yes) {
         IgnoreErrors(
             ToBackend(GetDevice())
-                ->EnqueueDestroyGL(this, &TextureView::GetHandle, reason,
+                ->EnqueueDestroyGL(this, &TextureView::GetTextureHandle, reason,
                                    [](const OpenGLFunctions& gl, GLuint handle) -> MaybeError {
                                        DAWN_GL_TRY_IGNORE_ERRORS(gl, DeleteTextures(1, &handle));
                                        return {};
@@ -685,9 +738,14 @@
     }
 }
 
-GLuint TextureView::GetHandle() const {
-    DAWN_ASSERT(mHandle != 0);
-    return mHandle;
+GLuint TextureView::GetTextureHandle() const {
+    DAWN_ASSERT(mTextureHandle != 0);
+    return mTextureHandle;
+}
+
+GLuint TextureView::GetRenderbufferHandle() const {
+    DAWN_ASSERT(mRenderbufferHandle != 0);
+    return mRenderbufferHandle;
 }
 
 GLenum TextureView::GetGLTarget() const {
@@ -701,6 +759,16 @@
     DAWN_ASSERT(depthSlice <
                 static_cast<GLuint>(GetSingleSubresourceVirtualSize().depthOrArrayLayers));
 
+    if (ToBackend(GetTexture())->IsRenderbuffer()) {
+        DAWN_ASSERT(GetDimension() == wgpu::TextureViewDimension::e2D);
+        DAWN_ASSERT(GetBaseMipLevel() == 0 && GetLevelCount() == 1);
+        DAWN_ASSERT(GetBaseArrayLayer() == 0 && GetLayerCount() == 1);
+
+        GLuint handle = ToBackend(GetTexture())->GetRenderbufferHandle();
+        DAWN_GL_TRY(gl, FramebufferRenderbuffer(target, attachment, GL_RENDERBUFFER, handle));
+        return {};
+    }
+
     // Use the base texture where possible to minimize the amount of copying required on GLES.
     bool useOwnView = GetFormat().format != GetTexture()->GetFormat().format &&
                       !GetTexture()->GetFormat().HasDepthOrStencil();
@@ -710,14 +778,14 @@
     if (useOwnView) {
         // Use our own texture handle and target which points to a subset of the texture's
         // subresources.
-        textureHandle = GetHandle();
+        textureHandle = GetTextureHandle();
         textarget = GetGLTarget();
         mipLevel = 0;
         arrayLayer = 0;
     } else {
         // Use the texture's handle and target, with the view's base mip level and base array
 
-        textureHandle = ToBackend(GetTexture())->GetHandle();
+        textureHandle = ToBackend(GetTexture())->GetTextureHandle();
         textarget = ToBackend(GetTexture())->GetGLTarget();
         mipLevel = GetBaseMipLevel();
         // We have validated that the depthSlice in render pass's colorAttachments must be undefined
diff --git a/src/dawn/native/opengl/TextureGL.h b/src/dawn/native/opengl/TextureGL.h
index 3fd3604..04cefe0 100644
--- a/src/dawn/native/opengl/TextureGL.h
+++ b/src/dawn/native/opengl/TextureGL.h
@@ -56,7 +56,8 @@
             GLuint handle,
             OwnsHandle ownsHandle);
 
-    GLuint GetHandle() const;
+    GLuint GetTextureHandle() const;
+    GLuint GetRenderbufferHandle() const;
     GLenum GetGLTarget() const;
     const GLFormat& GetGLFormat() const;
 
@@ -64,6 +65,7 @@
                                                    const SubresourceRange& range);
 
     MaybeError SynchronizeTextureBeforeUse();
+    bool IsRenderbuffer() const;
 
   private:
     ~Texture() override;
@@ -73,7 +75,8 @@
                             const SubresourceRange& range,
                             TextureBase::ClearValue clearValue);
 
-    GLuint mHandle;
+    GLuint mTextureHandle;
+    GLuint mRenderbufferHandle;
     OwnsHandle mOwnsHandle = OwnsHandle::No;
     GLenum mTarget;
 };
@@ -84,7 +87,8 @@
         TextureBase* texture,
         const UnpackedPtr<TextureViewDescriptor>& descriptor);
 
-    GLuint GetHandle() const;
+    GLuint GetTextureHandle() const;
+    GLuint GetRenderbufferHandle() const;
     GLenum GetGLTarget() const;
     MaybeError BindToFramebuffer(const OpenGLFunctions& gl,
                                  GLenum target,
@@ -98,8 +102,8 @@
     void DestroyImpl(DestroyReason reason) override;
     GLenum GetInternalFormat() const;
 
-    // TODO(crbug.com/dawn/1355): Delete this handle on texture destroy.
-    GLuint mHandle;
+    GLuint mTextureHandle;
+    GLuint mRenderbufferHandle;
     GLenum mTarget;
     OwnsHandle mOwnsHandle = OwnsHandle::No;
 };
diff --git a/src/dawn/tests/end2end/ArchTierLimitsExhaustive.cpp b/src/dawn/tests/end2end/ArchTierLimitsExhaustive.cpp
index 8bb5c63..4932041 100644
--- a/src/dawn/tests/end2end/ArchTierLimitsExhaustive.cpp
+++ b/src/dawn/tests/end2end/ArchTierLimitsExhaustive.cpp
@@ -514,8 +514,8 @@
 AddDevice({1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1}, "Vulkan_Qualcomm_R__Adreno_TM__X1_85_GPU");
 
 // SwiftShader
-AddDevice({0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "OpenGLES_ANGLE__Google__Vulkan_1_3_0__SwiftShader_Device__Subzero___0x0000C0DE____SwiftShader_driver_5_0_0__compat");
-AddDevice({0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "OpenGLES_ANGLE__Google__Vulkan_1_3_0__SwiftShader_Device__Subzero___0x0000C0DE____SwiftShader_driver_5_0_0__compat");
+AddDevice({0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "OpenGLES_ANGLE__Google__Vulkan_1_3_0__SwiftShader_Device__Subzero___0x0000C0DE____SwiftShader_driver_5_0_0__compat");
+AddDevice({0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "OpenGLES_ANGLE__Google__Vulkan_1_3_0__SwiftShader_Device__Subzero___0x0000C0DE____SwiftShader_driver_5_0_0__compat");
     }
     // clang-format on