diff --git a/Cargo.lock b/Cargo.lock
index 1108db7..e4d6de4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1591,11 +1591,9 @@ dependencies = [
  "bitflags 2.6.0",
  "bytemuck",
  "glslang",
- "indexmap",
  "librashader-common",
  "librashader-preprocess",
  "librashader-presets",
- "matches",
  "naga",
  "rspirv",
  "rustc-hash 2.0.0",
@@ -1687,6 +1685,7 @@ dependencies = [
 name = "librashader-runtime-gl"
 version = "0.4.5"
 dependencies = [
+ "array-init",
  "bytemuck",
  "glfw 0.47.0",
  "glow 0.14.1",
@@ -1842,12 +1841,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "matches"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
-
 [[package]]
 name = "memchr"
 version = "2.7.4"
diff --git a/librashader-reflect/Cargo.toml b/librashader-reflect/Cargo.toml
index d19c25d..50112a0 100644
--- a/librashader-reflect/Cargo.toml
+++ b/librashader-reflect/Cargo.toml
@@ -29,9 +29,6 @@ rspirv = { version = "0.12.0", optional = true }
 spirv = { version = "0.3.0", optional = true}
 
 serde = { version = "1.0", features = ["derive"], optional = true }
-
-indexmap = { version = "2.1.0", features = [] }
-matches = { version = "0.1.10", features = [] }
 rustc-hash = "2.0.0"
 
 [target.'cfg(windows)'.dependencies.spirv-to-dxil]
diff --git a/librashader-runtime-gl/Cargo.toml b/librashader-runtime-gl/Cargo.toml
index 86afa29..7d5d604 100644
--- a/librashader-runtime-gl/Cargo.toml
+++ b/librashader-runtime-gl/Cargo.toml
@@ -24,6 +24,7 @@ glow = { workspace = true}
 bytemuck = { version = "1.12.3", features = ["derive"] }
 thiserror = "1.0.37"
 rayon = "1.6.1"
+array-init = "2.1.0"
 
 [features]
 stable = ["librashader-reflect/stable"]
diff --git a/librashader-runtime-gl/src/gl/gl3/ubo_ring.rs b/librashader-runtime-gl/src/gl/gl3/ubo_ring.rs
index e4731b5..e0c3a41 100644
--- a/librashader-runtime-gl/src/gl/gl3/ubo_ring.rs
+++ b/librashader-runtime-gl/src/gl/gl3/ubo_ring.rs
@@ -7,50 +7,29 @@ use librashader_reflect::reflect::semantics::BufferReflection;
 use librashader_runtime::ringbuffer::InlineRingBuffer;
 use librashader_runtime::ringbuffer::RingBuffer;
 use librashader_runtime::uniforms::UniformStorageAccess;
-use std::mem::MaybeUninit;
 
 pub struct Gl3UboRing<const SIZE: usize> {
     ring: InlineRingBuffer<glow::Buffer, SIZE>,
 }
 
-impl<const SIZE: usize> Gl3UboRing<SIZE> {
-    const _ASSERT_TRANSMUTABLE: () = assert!(
-        std::mem::size_of::<[glow::Buffer; SIZE]>()
-            == std::mem::size_of::<[MaybeUninit<glow::Buffer>; SIZE]>()
-    );
-}
-
 impl<const SIZE: usize> UboRing<SIZE> for Gl3UboRing<SIZE> {
     fn new(ctx: &glow::Context, buffer_size: u32) -> error::Result<Self> {
-        // TODO: array::try_from_fn whenever that gets stabilized
-        //       this is basically blocking on try_trait_v2
-        let mut items: [MaybeUninit<glow::Buffer>; SIZE] = [MaybeUninit::zeroed(); SIZE];
-        for items in items.iter_mut() {
-            unsafe {
-                let buffer = ctx
-                    .create_buffer()
-                    .map(|buffer| {
-                        ctx.bind_buffer(glow::UNIFORM_BUFFER, Some(buffer));
-                        ctx.buffer_data_size(
-                            glow::UNIFORM_BUFFER,
-                            buffer_size as i32,
-                            glow::STREAM_DRAW,
-                        );
-                        ctx.bind_buffer(glow::UNIFORM_BUFFER, None);
-                        buffer
-                    })
-                    .map_err(FilterChainError::GlError)?;
-
-                *items = MaybeUninit::new(buffer)
-            }
-        }
-
-        // SAFETY: everything was initialized above.
-        // MaybeUninit<glow::Buffer> and glow::Buffer have the same size.
-        let items: [glow::Buffer; SIZE] = unsafe { std::mem::transmute_copy(&items) };
+        let items: [glow::Buffer; SIZE] = array_init::try_array_init(|_| unsafe {
+            ctx
+                .create_buffer()
+                .map(|buffer| {
+                    ctx.bind_buffer(glow::UNIFORM_BUFFER, Some(buffer));
+                    ctx.buffer_data_size(
+                        glow::UNIFORM_BUFFER,
+                        buffer_size as i32,
+                        glow::STREAM_DRAW,
+                    );
+                    ctx.bind_buffer(glow::UNIFORM_BUFFER, None);
+                    buffer
+                })
+        }).map_err(FilterChainError::GlError)?;
 
         let ring: InlineRingBuffer<glow::Buffer, SIZE> = InlineRingBuffer::from_array(items);
-
         Ok(Gl3UboRing { ring })
     }
 
diff --git a/librashader-runtime-gl/src/gl/gl46/ubo_ring.rs b/librashader-runtime-gl/src/gl/gl46/ubo_ring.rs
index 9e02bfc..c50c95d 100644
--- a/librashader-runtime-gl/src/gl/gl46/ubo_ring.rs
+++ b/librashader-runtime-gl/src/gl/gl46/ubo_ring.rs
@@ -7,46 +7,27 @@ use librashader_reflect::reflect::semantics::BufferReflection;
 use librashader_runtime::ringbuffer::InlineRingBuffer;
 use librashader_runtime::ringbuffer::RingBuffer;
 use librashader_runtime::uniforms::UniformStorageAccess;
-use std::mem::MaybeUninit;
 
 pub struct Gl46UboRing<const SIZE: usize> {
     ring: InlineRingBuffer<glow::Buffer, SIZE>,
 }
 
-impl<const SIZE: usize> Gl46UboRing<SIZE> {
-    const _ASSERT_TRANSMUTABLE: () = assert!(
-        std::mem::size_of::<[glow::Buffer; SIZE]>()
-            == std::mem::size_of::<[MaybeUninit<glow::Buffer>; SIZE]>()
-    );
-}
-
 impl<const SIZE: usize> UboRing<SIZE> for Gl46UboRing<SIZE> {
     fn new(context: &glow::Context, buffer_size: u32) -> error::Result<Self> {
-        // TODO: array::try_from_fn whenever that gets stabilized
-        //       this is basically blocking on try_trait_v2
-        let mut items: [MaybeUninit<glow::Buffer>; SIZE] = [MaybeUninit::zeroed(); SIZE];
-        for items in items.iter_mut() {
-            unsafe {
-                let buffer = context
-                    .create_named_buffer()
-                    .map(|buffer| {
-                        context.named_buffer_data_size(
-                            buffer,
-                            buffer_size as i32,
-                            glow::STREAM_DRAW,
-                        );
-                        buffer
-                    })
-                    .map_err(FilterChainError::GlError)?;
+        let items: [glow::Buffer; SIZE] = array_init::try_array_init(|_| unsafe {
+            context
+                .create_named_buffer()
+                .map(|buffer| {
+                    context.named_buffer_data_size(
+                        buffer,
+                        buffer_size as i32,
+                        glow::STREAM_DRAW,
+                    );
+                    buffer
+                })
+        }).map_err(FilterChainError::GlError)?;
 
-                *items = MaybeUninit::new(buffer)
-            }
-        }
-
-        // SAFETY: everything was initialized above.
-        let items: [glow::Buffer; SIZE] = unsafe { std::mem::transmute_copy(&items) };
         let ring: InlineRingBuffer<glow::Buffer, SIZE> = InlineRingBuffer::from_array(items);
-
         Ok(Gl46UboRing { ring })
     }