From d961e1b290d9c43f7f8be40c308d8ce1b33f7ddb Mon Sep 17 00:00:00 2001
From: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
Date: Sat, 25 Jun 2022 00:19:11 -0400
Subject: [PATCH] Force binding sizes to be multiples of 16 on webgl

---
 wgpu-core/src/device/mod.rs  | 8 ++++++++
 wgpu-hal/src/gles/adapter.rs | 7 +++++++
 wgpu-types/src/lib.rs        | 5 +++++
 3 files changed, 20 insertions(+)

diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs
index aa8b0991a9..38366b0429 100644
--- a/wgpu-core/src/device/mod.rs
+++ b/wgpu-core/src/device/mod.rs
@@ -2807,6 +2807,14 @@ impl<A: HalApi> Device<A> {
             self.require_features(wgt::Features::MULTIVIEW)?;
         }
 
+        for size in shader_binding_sizes.values() {
+            if size.get() % 16 != 0 {
+                self.require_downlevel_flags(
+                    wgt::DownlevelFlags::BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED,
+                )?;
+            }
+        }
+
         let late_sized_buffer_groups =
             Device::make_late_sized_buffer_groups(&shader_binding_sizes, layout, &*bgl_guard);
 
diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs
index 3bd7bae5e2..a0fc40fed1 100644
--- a/wgpu-hal/src/gles/adapter.rs
+++ b/wgpu-hal/src/gles/adapter.rs
@@ -212,6 +212,9 @@ impl super::Adapter {
             naga::back::glsl::Version::Embedded(value)
         };
 
+        // ANGLE provides renderer strings like: "ANGLE (Apple, Apple M1 Pro, OpenGL 4.1)"
+        let is_angle = renderer.contains("ANGLE");
+
         let vertex_shader_storage_blocks = if supports_storage {
             gl.get_parameter_i32(glow::MAX_VERTEX_SHADER_STORAGE_BLOCKS) as u32
         } else {
@@ -289,6 +292,10 @@ impl super::Adapter {
             wgt::DownlevelFlags::ANISOTROPIC_FILTERING,
             extensions.contains("EXT_texture_filter_anisotropic"),
         );
+        downlevel_flags.set(
+            wgt::DownlevelFlags::BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED,
+            !(cfg!(target_arch = "wasm32") || is_angle),
+        );
 
         let is_ext_color_buffer_float_supported = extensions.contains("EXT_color_buffer_float");
 
diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs
index 1737c9517c..e846c684d2 100644
--- a/wgpu-types/src/lib.rs
+++ b/wgpu-types/src/lib.rs
@@ -1039,6 +1039,11 @@ bitflags::bitflags! {
         /// Supports all the texture usages described in WebGPU. If this isn't supported, you
         /// should call `get_texture_format_features` to get how you can use textures of a given format
         const WEBGPU_TEXTURE_FORMAT_SUPPORT = 1 << 14;
+
+        /// Supports buffer bindings with sizes that aren't a multiple of 16.
+        ///
+        /// WebGL doesn't support this.
+        const BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED = 1 << 15;
     }
 }