From 4a048462e156668e2515ad47d8ce7a22e13a53c4 Mon Sep 17 00:00:00 2001 From: Shrek Shao Date: Tue, 17 Dec 2024 23:17:06 -0800 Subject: [PATCH] [Compat] Add toggle to add egl attrib to use min gles version and no extension We can config bot to run end2endtests with `--enable-toggles=gl_force_es_31_and_no_extensions` to add test coverage of compat mode support on devices without certain extensions. Bug: 382084196 Change-Id: I7bb3877abf41c13abedb9f243cc02c58d854f019 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/217974 Reviewed-by: Stephen White Auto-Submit: Shrek Shao Reviewed-by: Kai Ninomiya Commit-Queue: Kai Ninomiya --- src/dawn/native/Toggles.cpp | 6 ++ src/dawn/native/Toggles.h | 1 + src/dawn/native/opengl/BackendGL.cpp | 12 +++- src/dawn/native/opengl/ContextEGL.cpp | 28 +++++++- src/dawn/native/opengl/ContextEGL.h | 6 +- src/dawn/native/opengl/EGLFunctions.cpp | 5 ++ src/dawn/native/opengl/EGLFunctions.h | 4 ++ src/dawn/native/opengl/PhysicalDeviceGL.cpp | 16 +++-- src/dawn/native/opengl/PhysicalDeviceGL.h | 3 +- src/dawn/tests/BUILD.gn | 10 ++- .../end2end/GLExplicitExtensionsTests.cpp | 68 +++++++++++++++++++ 11 files changed, 144 insertions(+), 15 deletions(-) create mode 100644 src/dawn/tests/end2end/GLExplicitExtensionsTests.cpp diff --git a/src/dawn/native/Toggles.cpp b/src/dawn/native/Toggles.cpp index 8248c177127..2a8ca231092 100644 --- a/src/dawn/native/Toggles.cpp +++ b/src/dawn/native/Toggles.cpp @@ -564,6 +564,12 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{ "while the WebGPU CTS is expecting n. Scale the depth bias value by multiple 0.5 on certain " "backends to achieve conformant result.", "https://crbug.com/42241017", ToggleStage::Device}}, + {Toggle::GLForceES31AndNoExtensions, + {"gl_force_es_31_and_no_extensions", + "Force EGLContext creation with the minimal ES version and no extensions required by the " + "Compat spec, which for OpenGLES is version 3.1 with no extensions. This toggle is used by " + "end2end testing.", + "crbug.com/382084196", ToggleStage::Adapter}}, {Toggle::VulkanMonolithicPipelineCache, {"vulkan_monolithic_pipeline_cache", "Use a monolithic VkPipelineCache per device. The embedder is responsible for calling " diff --git a/src/dawn/native/Toggles.h b/src/dawn/native/Toggles.h index 0993ef9f1ef..5a80e6aecaf 100644 --- a/src/dawn/native/Toggles.h +++ b/src/dawn/native/Toggles.h @@ -136,6 +136,7 @@ enum class Toggle { D3D12ForceStencilComponentReplicateSwizzle, D3D12ExpandShaderResourceStateTransitionsToCopySource, GLDepthBiasModifier, + GLForceES31AndNoExtensions, VulkanMonolithicPipelineCache, MetalSerializeTimestampGenerationAndResolution, D3D12RelaxMinSubgroupSizeTo8, diff --git a/src/dawn/native/opengl/BackendGL.cpp b/src/dawn/native/opengl/BackendGL.cpp index 5eb4db7b885..5ec72f5492f 100644 --- a/src/dawn/native/opengl/BackendGL.cpp +++ b/src/dawn/native/opengl/BackendGL.cpp @@ -63,6 +63,15 @@ std::vector> Backend::DiscoverPhysicalDevices( return {}; } + bool forceES31AndNoExtensions = false; + if (auto* togglesDesc = options.Get()) { + TogglesState toggles = + TogglesState::CreateFromTogglesDescriptor(togglesDesc, ToggleStage::Adapter); + if (toggles.IsEnabled(Toggle::GLForceES31AndNoExtensions)) { + forceES31AndNoExtensions = true; + } + } + std::vector> devices; // A helper function performing checks on the display we're trying to use, and adding the @@ -80,7 +89,8 @@ std::vector> Backend::DiscoverPhysicalDevices( } Ref device; - DAWN_TRY_ASSIGN(device, PhysicalDevice::Create(GetType(), std::move(display))); + DAWN_TRY_ASSIGN(device, PhysicalDevice::Create(GetType(), std::move(display), + forceES31AndNoExtensions)); devices.push_back(device); return {}; diff --git a/src/dawn/native/opengl/ContextEGL.cpp b/src/dawn/native/opengl/ContextEGL.cpp index a7d753e404d..db9704c3fdc 100644 --- a/src/dawn/native/opengl/ContextEGL.cpp +++ b/src/dawn/native/opengl/ContextEGL.cpp @@ -39,15 +39,27 @@ #define EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE 0x33AF #endif +// https://chromium.googlesource.com/angle/angle/+/main/extensions/EGL_ANGLE_create_context_backwards_compatible.txt +#ifndef EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE +#define EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE 0x3483 +#endif + +// https://chromium.googlesource.com/angle/angle.git/+/refs/heads/chromium/5996/extensions/EGL_ANGLE_create_context_extensions_enabled.txt +#ifndef EGL_EXTENSIONS_ENABLED_ANGLE +#define EGL_EXTENSIONS_ENABLED_ANGLE 0x345F +#endif + namespace dawn::native::opengl { // static ResultOrError> ContextEGL::Create(Ref display, wgpu::BackendType backend, bool useRobustness, - bool useANGLETextureSharing) { + bool useANGLETextureSharing, + bool forceES31AndNoExtensionss) { auto context = std::make_unique(std::move(display)); - DAWN_TRY(context->Initialize(backend, useRobustness, useANGLETextureSharing)); + DAWN_TRY(context->Initialize(backend, useRobustness, useANGLETextureSharing, + forceES31AndNoExtensionss)); return std::move(context); } @@ -66,7 +78,8 @@ ContextEGL::~ContextEGL() { MaybeError ContextEGL::Initialize(wgpu::BackendType backend, bool useRobustness, - bool useANGLETextureSharing) { + bool useANGLETextureSharing, + bool forceES31AndNoExtensionss) { const EGLFunctions& egl = mDisplay->egl; // Unless EGL_KHR_no_config is present, we need to choose an EGLConfig on context creation that @@ -126,6 +139,15 @@ MaybeError ContextEGL::Initialize(wgpu::BackendType backend, AddAttrib(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_TRUE); } + if (forceES31AndNoExtensionss) { + if (egl.HasExt(EGLExt::ANGLECreateContextBackwardsCompatible)) { + AddAttrib(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_FALSE); + } + if (egl.HasExt(EGLExt::ANGLECreateContextExtensionsEnabled)) { + AddAttrib(EGL_EXTENSIONS_ENABLED_ANGLE, EGL_FALSE); + } + } + // The attrib list is finished with an EGL_NONE tag. attribs.push_back(EGL_NONE); diff --git a/src/dawn/native/opengl/ContextEGL.h b/src/dawn/native/opengl/ContextEGL.h index 6cfff8f83cb..77f3b40a418 100644 --- a/src/dawn/native/opengl/ContextEGL.h +++ b/src/dawn/native/opengl/ContextEGL.h @@ -46,14 +46,16 @@ class ContextEGL : NonMovable { static ResultOrError> Create(Ref display, wgpu::BackendType backend, bool useRobustness, - bool useANGLETextureSharing); + bool useANGLETextureSharing, + bool forceES31AndNoExtensionss); explicit ContextEGL(Ref display); ~ContextEGL(); MaybeError Initialize(wgpu::BackendType backend, bool useRobustness, - bool useANGLETextureSharing); + bool useANGLETextureSharing, + bool forceES31AndNoExtensionss); // Make the surface used by all MakeCurrent until the scoper gets out of scope. class ScopedMakeSurfaceCurrent : NonMovable { diff --git a/src/dawn/native/opengl/EGLFunctions.cpp b/src/dawn/native/opengl/EGLFunctions.cpp index 128c9f170f2..3b9c87f5112 100644 --- a/src/dawn/native/opengl/EGLFunctions.cpp +++ b/src/dawn/native/opengl/EGLFunctions.cpp @@ -90,6 +90,11 @@ static constexpr std::array kExtensionInfos{{ {EGLExt::ImageNativeBuffer, "EGL_ANDROID_image_native_buffer", NeverPromoted, ExtType::Display}, {EGLExt::GetNativeClientBuffer, "EGL_ANDROID_get_native_client_buffer", NeverPromoted, ExtType::Display}, + + {EGLExt::ANGLECreateContextBackwardsCompatible, "EGL_ANGLE_create_context_backwards_compatible", + NeverPromoted, ExtType::Display}, + {EGLExt::ANGLECreateContextExtensionsEnabled, "EGL_ANGLE_create_context_extensions_enabled", + NeverPromoted, ExtType::Display}, // }}; diff --git a/src/dawn/native/opengl/EGLFunctions.h b/src/dawn/native/opengl/EGLFunctions.h index eb1538e7317..b3b58298301 100644 --- a/src/dawn/native/opengl/EGLFunctions.h +++ b/src/dawn/native/opengl/EGLFunctions.h @@ -66,6 +66,10 @@ enum class EGLExt { ImageNativeBuffer, // EGL_ANDROID_image_native_buffer GetNativeClientBuffer, // EGL_ANDROID_get_native_client_buffer + // ANGLE specific + ANGLECreateContextBackwardsCompatible, // EGL_ANGLE_create_context_backwards_compatible + ANGLECreateContextExtensionsEnabled, // EGL_ANGLE_create_context_extensions_enabled + EnumCount, }; diff --git a/src/dawn/native/opengl/PhysicalDeviceGL.cpp b/src/dawn/native/opengl/PhysicalDeviceGL.cpp index 73b3bbc210b..dd944fe710e 100644 --- a/src/dawn/native/opengl/PhysicalDeviceGL.cpp +++ b/src/dawn/native/opengl/PhysicalDeviceGL.cpp @@ -89,13 +89,13 @@ uint32_t GetDeviceIdFromRender(std::string_view render) { return deviceId; } -bool IsANGLEDesktopGL(std::string renderer) { +bool IsANGLEDesktopGL(std::string_view renderer) { return renderer.find("ANGLE") != std::string::npos && renderer.find("OpenGL") != std::string::npos && renderer.find("OpenGL ES") == std::string::npos; } -bool IsSwiftShader(std::string renderer) { +bool IsSwiftShader(std::string_view renderer) { return renderer.find("SwiftShader") != std::string::npos; } @@ -103,7 +103,8 @@ bool IsSwiftShader(std::string renderer) { // static ResultOrError> PhysicalDevice::Create(wgpu::BackendType backendType, - Ref display) { + Ref display, + bool forceES31AndNoExtensions) { const EGLFunctions& egl = display->egl; EGLDisplay eglDisplay = display->GetDisplay(); @@ -111,8 +112,10 @@ ResultOrError> PhysicalDevice::Create(wgpu::BackendType back // that we can query the limits and other properties. Assumes that the limit are the same // irrespective of the context creation options. std::unique_ptr context; - DAWN_TRY_ASSIGN(context, ContextEGL::Create(display, backendType, /*useRobustness*/ false, - /*useANGLETextureSharing*/ false)); + DAWN_TRY_ASSIGN(context, + ContextEGL::Create(display, backendType, /*useRobustness*/ false, + /*useANGLETextureSharing*/ false, + /*forceES31AndNoExtensions*/ forceES31AndNoExtensions)); EGLSurface prevDrawSurface = egl.GetCurrentSurface(EGL_DRAW); EGLSurface prevReadSurface = egl.GetCurrentSurface(EGL_READ); @@ -449,10 +452,11 @@ ResultOrError> PhysicalDevice::CreateDeviceImpl( } bool useRobustness = !deviceToggles.IsEnabled(Toggle::DisableRobustness); + bool forceES31AndNoExtensions = deviceToggles.IsEnabled(Toggle::GLForceES31AndNoExtensions); std::unique_ptr context; DAWN_TRY_ASSIGN(context, ContextEGL::Create(mDisplay, GetBackendType(), useRobustness, - useANGLETextureSharing)); + useANGLETextureSharing, forceES31AndNoExtensions)); return Device::Create(adapter, descriptor, mFunctions, std::move(context), deviceToggles, std::move(lostEvent)); diff --git a/src/dawn/native/opengl/PhysicalDeviceGL.h b/src/dawn/native/opengl/PhysicalDeviceGL.h index 84c0f93e693..8d8d66189e3 100644 --- a/src/dawn/native/opengl/PhysicalDeviceGL.h +++ b/src/dawn/native/opengl/PhysicalDeviceGL.h @@ -41,7 +41,8 @@ class DisplayEGL; class PhysicalDevice : public PhysicalDeviceBase { public: static ResultOrError> Create(wgpu::BackendType backendType, - Ref display); + Ref display, + bool forceES31AndNoExtensions); ~PhysicalDevice() override = default; diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn index 1eed546ef96..4a597c46fed 100644 --- a/src/dawn/tests/BUILD.gn +++ b/src/dawn/tests/BUILD.gn @@ -741,6 +741,10 @@ source_set("end2end_tests_sources") { if (dawn_enable_vulkan && is_chromeos) { sources += [ "end2end/VideoViewsTests_gbm.cpp" ] } + + if (dawn_enable_opengles) { + sources += [ "end2end/GLExplicitExtensionsTests.cpp" ] + } } source_set("white_box_tests_sources") { @@ -849,8 +853,10 @@ source_set("white_box_tests_sources") { } if (dawn_enable_opengles) { - sources += [ "white_box/EGLImageWrappingTests.cpp" ] - sources += [ "white_box/GLTextureWrappingTests.cpp" ] + sources += [ + "white_box/EGLImageWrappingTests.cpp", + "white_box/GLTextureWrappingTests.cpp", + ] include_dirs = [ "//third_party/khronos" ] } } diff --git a/src/dawn/tests/end2end/GLExplicitExtensionsTests.cpp b/src/dawn/tests/end2end/GLExplicitExtensionsTests.cpp new file mode 100644 index 00000000000..aa057868186 --- /dev/null +++ b/src/dawn/tests/end2end/GLExplicitExtensionsTests.cpp @@ -0,0 +1,68 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "dawn/tests/DawnTest.h" +namespace dawn { +namespace { + +class GLExplicitExtensionsTests : public DawnTest { + protected: + void SetUp() override { + DawnTest::SetUp(); + // Without ANGLE we cannot have a GL context requesting extensions explicitly. + DAWN_TEST_UNSUPPORTED_IF(!IsANGLE()); + } +}; + +TEST_P(GLExplicitExtensionsTests, Features) { + // Make sure this toggle is inherited correctly during re-initialization + EXPECT_EQ(HasToggleEnabled("gl_force_es_31_and_no_extensions"), true); + + // GL_KHR_texture_compression_astc_ldr + EXPECT_EQ(device.HasFeature(wgpu::FeatureName::TextureCompressionASTC), false); + // GL_AMD_gpu_shader_half_float + EXPECT_EQ(device.HasFeature(wgpu::FeatureName::ShaderF16), false); + // GL_EXT_float_blend + EXPECT_EQ(device.HasFeature(wgpu::FeatureName::Float32Blendable), false); +} + +TEST_P(GLExplicitExtensionsTests, Toggles) { + // Make sure this toggle is inherited correctly during re-initialization + EXPECT_EQ(HasToggleEnabled("gl_force_es_31_and_no_extensions"), true); + + // GL_OES_texture_stencil8 + EXPECT_EQ(HasToggleEnabled("use_blit_for_stencil_texture_write"), true); + // GL_EXT_read_format_bgra + EXPECT_EQ(HasToggleEnabled("use_blit_for_bgra8unorm_texture_to_buffer_copy"), true); +} + +DAWN_INSTANTIATE_TEST(GLExplicitExtensionsTests, + // Force GLES 3.1 context with fewest extensions requested. + OpenGLESBackend({"gl_force_es_31_and_no_extensions"})); + +} // anonymous namespace +} // namespace dawn