OpenGL ES: implement support for BGRA textures and reads.
ES requires GL_EXT_texture_format_BGRA8888 or GL_APPLE_texture_format_BGRA8888 to create BGRA8 internalFormat textures, and GL_EXT_read_format_bgra to read from them. Desktop GL can swizzle back and forth from RGBA8, so keep using RGBA8 if the extension is unavailable.
Intel's implementation of GL_EXT_texture_format_BGRA8888 on ES is broken, and won't create GL_BGRA8_EXT or GL_BGRA internalFormat textures, so disable the test there and modify another test to not use BGRA textures.
Change-Id: Ia81d9ff20e2849b00379f8e01fb5d2ecfa34bd53
Bug: dawn:596, dawn:1393
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/86744
Commit-Queue: Stephen White <senorblanco@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/dawn/native/Toggles.cpp b/src/dawn/native/Toggles.cpp
index eb473c2..b193214 100644
--- a/src/dawn/native/Toggles.cpp
+++ b/src/dawn/native/Toggles.cpp
@@ -147,6 +147,10 @@
"Disables reading from depth/stencil textures which is unsupported on some "
"platforms.",
"https://crbug.com/dawn/667"}},
+ {Toggle::DisableBGRARead,
+ {"disable_bgra_read",
+ "Disables reading from BGRA textures which is unsupported on some platforms.",
+ "https://crbug.com/dawn/1393"}},
{Toggle::DisableSampleVariables,
{"disable_sample_variables",
"Disables gl_SampleMask and related functionality which is unsupported on some "
diff --git a/src/dawn/native/Toggles.h b/src/dawn/native/Toggles.h
index 6e6c90f..988a991 100644
--- a/src/dawn/native/Toggles.h
+++ b/src/dawn/native/Toggles.h
@@ -45,6 +45,7 @@
DisableIndexedDrawBuffers,
DisableSnormRead,
DisableDepthStencilRead,
+ DisableBGRARead,
DisableSampleVariables,
UseD3D12SmallShaderVisibleHeapForTesting,
UseDXC,
diff --git a/src/dawn/native/opengl/DeviceGL.cpp b/src/dawn/native/opengl/DeviceGL.cpp
index b3a8442..3d95b1b 100644
--- a/src/dawn/native/opengl/DeviceGL.cpp
+++ b/src/dawn/native/opengl/DeviceGL.cpp
@@ -55,7 +55,7 @@
MaybeError Device::Initialize(const DeviceDescriptor* descriptor) {
InitTogglesFromDriver();
- mFormatTable = BuildGLFormatTable();
+ mFormatTable = BuildGLFormatTable(GetBGRAInternalFormat());
return DeviceBase::Initialize(AcquireRef(new Queue(this, &descriptor->defaultQueue)));
}
@@ -74,6 +74,10 @@
bool supportsDepthStencilRead =
gl.IsAtLeastGL(3, 0) || gl.IsGLExtensionSupported("GL_NV_read_depth_stencil");
+ // Desktop GL supports BGRA textures via swizzling in the driver; ES requires an extension.
+ bool supportsBGRARead =
+ gl.GetVersion().IsDesktop() || gl.IsGLExtensionSupported("GL_EXT_read_format_bgra");
+
bool supportsSampleVariables = gl.IsAtLeastGL(4, 0) || gl.IsAtLeastGLES(3, 2) ||
gl.IsGLExtensionSupported("GL_OES_sample_variables");
@@ -97,6 +101,7 @@
SetToggle(Toggle::DisableIndexedDrawBuffers, !supportsIndexedDrawBuffers);
SetToggle(Toggle::DisableSnormRead, !supportsSnormRead);
SetToggle(Toggle::DisableDepthStencilRead, !supportsDepthStencilRead);
+ SetToggle(Toggle::DisableBGRARead, !supportsBGRARead);
SetToggle(Toggle::DisableSampleVariables, !supportsSampleVariables);
SetToggle(Toggle::FlushBeforeClientWaitSync, gl.GetVersion().IsES());
// For OpenGL ES, we must use a placeholder fragment shader for vertex-only render pipeline.
@@ -112,6 +117,16 @@
return result;
}
+ GLenum Device::GetBGRAInternalFormat() const {
+ if (gl.IsGLExtensionSupported("GL_EXT_texture_format_BGRA8888") ||
+ gl.IsGLExtensionSupported("GL_APPLE_texture_format_BGRA8888")) {
+ return GL_BGRA8_EXT;
+ } else {
+ // Desktop GL will swizzle to/from RGBA8 for BGRA formats.
+ return GL_RGBA8;
+ }
+ }
+
ResultOrError<Ref<BindGroupBase>> Device::CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) {
DAWN_TRY(ValidateGLBindGroupDescriptor(descriptor));
diff --git a/src/dawn/native/opengl/DeviceGL.h b/src/dawn/native/opengl/DeviceGL.h
index cb7c8cb..52ea056 100644
--- a/src/dawn/native/opengl/DeviceGL.h
+++ b/src/dawn/native/opengl/DeviceGL.h
@@ -119,6 +119,7 @@
const RenderPipelineDescriptor* descriptor) override;
void InitTogglesFromDriver();
+ GLenum GetBGRAInternalFormat() const;
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
void DestroyImpl() override;
MaybeError WaitForIdleForDestruction() override;
diff --git a/src/dawn/native/opengl/GLFormat.cpp b/src/dawn/native/opengl/GLFormat.cpp
index dac02a6..2d54426 100644
--- a/src/dawn/native/opengl/GLFormat.cpp
+++ b/src/dawn/native/opengl/GLFormat.cpp
@@ -16,7 +16,7 @@
namespace dawn::native::opengl {
- GLFormatTable BuildGLFormatTable() {
+ GLFormatTable BuildGLFormatTable(GLenum internalFormatForBGRA) {
GLFormatTable table;
using Type = GLFormat::ComponentType;
@@ -71,8 +71,7 @@
AddFormat(wgpu::TextureFormat::RGBA8Uint, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, Type::Uint);
AddFormat(wgpu::TextureFormat::RGBA8Sint, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, Type::Int);
- // This doesn't have an enum for the internal format in OpenGL, so use RGBA8.
- AddFormat(wgpu::TextureFormat::BGRA8Unorm, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(wgpu::TextureFormat::BGRA8Unorm, internalFormatForBGRA, GL_BGRA, GL_UNSIGNED_BYTE, Type::Float);
AddFormat(wgpu::TextureFormat::RGB10A2Unorm, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, Type::Float);
AddFormat(wgpu::TextureFormat::RG11B10Ufloat, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, Type::Float);
AddFormat(wgpu::TextureFormat::RGB9E5Ufloat, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, Type::Float);
diff --git a/src/dawn/native/opengl/GLFormat.h b/src/dawn/native/opengl/GLFormat.h
index 292fb4a..a76f989 100644
--- a/src/dawn/native/opengl/GLFormat.h
+++ b/src/dawn/native/opengl/GLFormat.h
@@ -35,7 +35,7 @@
};
using GLFormatTable = ityp::array<FormatIndex, GLFormat, kKnownFormatCount>;
- GLFormatTable BuildGLFormatTable();
+ GLFormatTable BuildGLFormatTable(GLenum internalFormatForBGRA);
} // namespace dawn::native::opengl
diff --git a/src/dawn/native/opengl/supported_extensions.json b/src/dawn/native/opengl/supported_extensions.json
index 8e00633..8c110d0 100644
--- a/src/dawn/native/opengl/supported_extensions.json
+++ b/src/dawn/native/opengl/supported_extensions.json
@@ -18,6 +18,8 @@
"supported_extensions": [
"GL_EXT_texture_compression_s3tc",
"GL_EXT_texture_compression_s3tc_srgb",
- "GL_OES_EGL_image"
+ "GL_OES_EGL_image",
+ "GL_EXT_texture_format_BGRA8888",
+ "GL_APPLE_texture_format_BGRA8888"
]
}
diff --git a/src/dawn/tests/end2end/BindGroupTests.cpp b/src/dawn/tests/end2end/BindGroupTests.cpp
index fa5e011..837e071 100644
--- a/src/dawn/tests/end2end/BindGroupTests.cpp
+++ b/src/dawn/tests/end2end/BindGroupTests.cpp
@@ -1601,7 +1601,7 @@
wgpu::TextureDescriptor textureDesc;
textureDesc.usage = wgpu::TextureUsage::TextureBinding;
textureDesc.size = {1, 1, 1};
- textureDesc.format = wgpu::TextureFormat::BGRA8Unorm;
+ textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
// Create view, then destroy.
{
diff --git a/src/dawn/tests/end2end/TextureFormatTests.cpp b/src/dawn/tests/end2end/TextureFormatTests.cpp
index 7260ac6..ca875bc 100644
--- a/src/dawn/tests/end2end/TextureFormatTests.cpp
+++ b/src/dawn/tests/end2end/TextureFormatTests.cpp
@@ -458,8 +458,12 @@
// Test the BGRA8Unorm format
TEST_P(TextureFormatTest, BGRA8Unorm) {
- // TODO(crbug.com/dawn/596): BGRA is unsupported on OpenGL ES; add workaround or validation
- DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
+ DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("disable_bgra_read"));
+
+ // Intel's implementation of BGRA on ES is broken: it claims to support
+ // GL_EXT_texture_format_BGRA8888, but won't accept GL_BGRA or GL_BGRA8_EXT as internalFormat.
+ DAWN_SUPPRESS_TEST_IF(IsIntel() && IsOpenGLES() && IsLinux());
+
uint8_t maxValue = std::numeric_limits<uint8_t>::max();
std::vector<uint8_t> textureData = {maxValue, 1, 0, maxValue};
std::vector<float> uncompressedData = {0.0f, 1.0f / maxValue, 1.0f, 1.0f};