diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d564bb08..fc094bcfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -126,6 +126,7 @@ By @bradwerth [#6216](https://github.com/gfx-rs/wgpu/pull/6216). #### GLES / OpenGL - Fix GL debug message callbacks not being properly cleaned up (causing UB). By @Imberflur in [#6114](https://github.com/gfx-rs/wgpu/pull/6114) +- Fix calling `slice::from_raw_parts` with unaligned pointers in push constant handling. By @Imberflur in [#6341](https://github.com/gfx-rs/wgpu/pull/6341) #### WebGPU diff --git a/Cargo.lock b/Cargo.lock index 3c8d1aacc..74910d929 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3681,6 +3681,7 @@ dependencies = [ "bit-set", "bitflags 2.6.0", "block", + "bytemuck", "cfg-if", "cfg_aliases", "core-graphics-types", diff --git a/Cargo.toml b/Cargo.toml index fbf06524c..68c29b671 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,7 +76,7 @@ arrayvec = "0.7" bincode = "1" bit-vec = "0.8" bitflags = "2.6" -bytemuck = { version = "1.18", features = ["derive"] } +bytemuck = { version = "1.18" } cfg_aliases = "0.1" cfg-if = "1" criterion = "0.5" diff --git a/examples/Cargo.toml b/examples/Cargo.toml index f5beed1d2..1f4d4951f 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -29,7 +29,7 @@ webgl = ["wgpu/webgl"] webgpu = ["wgpu/webgpu"] [dependencies] -bytemuck.workspace = true +bytemuck = { workspace = true, features = ["derive"] } cfg-if.workspace = true encase = { workspace = true, features = ["glam"] } flume.workspace = true diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index d3a05f079..03af10b96 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -56,6 +56,7 @@ vulkan = [ ] gles = [ "naga/glsl-out", + "dep:bytemuck", "dep:glow", "dep:glutin_wgl_sys", "dep:khronos-egl", @@ -126,6 +127,7 @@ rustc-hash.workspace = true log.workspace = true # backend: Gles +bytemuck = { workspace = true, optional = true } glow = { workspace = true, optional = true } [dependencies.wgt] diff --git a/wgpu-hal/src/gles/queue.rs b/wgpu-hal/src/gles/queue.rs index 39315f72b..fc106eb23 100644 --- a/wgpu-hal/src/gles/queue.rs +++ b/wgpu-hal/src/gles/queue.rs @@ -1603,19 +1603,13 @@ impl super::Queue { ref uniform, offset, } => { - // T must be POD - // - // This function is absolutely sketchy and we really should be using bytemuck. - unsafe fn get_data(data: &[u8], offset: u32) -> &[T; COUNT] { + fn get_data(data: &[u8], offset: u32) -> [T; COUNT] + where + [T; COUNT]: bytemuck::AnyBitPattern, + { let data_required = size_of::() * COUNT; - let raw = &data[(offset as usize)..][..data_required]; - - debug_assert_eq!(data_required, raw.len()); - - let slice: &[T] = unsafe { slice::from_raw_parts(raw.as_ptr().cast(), COUNT) }; - - slice.try_into().unwrap() + bytemuck::pod_read_unaligned(raw) } let location = Some(&uniform.location); @@ -1625,28 +1619,28 @@ impl super::Queue { // --- Float 1-4 Component --- // naga::TypeInner::Scalar(naga::Scalar::F32) => { - let data = unsafe { get_data::(data_bytes, offset)[0] }; + let data = get_data::(data_bytes, offset)[0]; unsafe { gl.uniform_1_f32(location, data) }; } naga::TypeInner::Vector { size: naga::VectorSize::Bi, scalar: naga::Scalar::F32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_2_f32_slice(location, data) }; } naga::TypeInner::Vector { size: naga::VectorSize::Tri, scalar: naga::Scalar::F32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_3_f32_slice(location, data) }; } naga::TypeInner::Vector { size: naga::VectorSize::Quad, scalar: naga::Scalar::F32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_4_f32_slice(location, data) }; } @@ -1654,28 +1648,28 @@ impl super::Queue { // --- Int 1-4 Component --- // naga::TypeInner::Scalar(naga::Scalar::I32) => { - let data = unsafe { get_data::(data_bytes, offset)[0] }; + let data = get_data::(data_bytes, offset)[0]; unsafe { gl.uniform_1_i32(location, data) }; } naga::TypeInner::Vector { size: naga::VectorSize::Bi, scalar: naga::Scalar::I32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_2_i32_slice(location, data) }; } naga::TypeInner::Vector { size: naga::VectorSize::Tri, scalar: naga::Scalar::I32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_3_i32_slice(location, data) }; } naga::TypeInner::Vector { size: naga::VectorSize::Quad, scalar: naga::Scalar::I32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_4_i32_slice(location, data) }; } @@ -1683,28 +1677,28 @@ impl super::Queue { // --- Uint 1-4 Component --- // naga::TypeInner::Scalar(naga::Scalar::U32) => { - let data = unsafe { get_data::(data_bytes, offset)[0] }; + let data = get_data::(data_bytes, offset)[0]; unsafe { gl.uniform_1_u32(location, data) }; } naga::TypeInner::Vector { size: naga::VectorSize::Bi, scalar: naga::Scalar::U32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_2_u32_slice(location, data) }; } naga::TypeInner::Vector { size: naga::VectorSize::Tri, scalar: naga::Scalar::U32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_3_u32_slice(location, data) }; } naga::TypeInner::Vector { size: naga::VectorSize::Quad, scalar: naga::Scalar::U32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_4_u32_slice(location, data) }; } @@ -1716,7 +1710,7 @@ impl super::Queue { rows: naga::VectorSize::Bi, scalar: naga::Scalar::F32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_matrix_2_f32_slice(location, false, data) }; } naga::TypeInner::Matrix { @@ -1725,7 +1719,7 @@ impl super::Queue { scalar: naga::Scalar::F32, } => { // repack 2 vec3s into 6 values. - let unpacked_data = unsafe { get_data::(data_bytes, offset) }; + let unpacked_data = &get_data::(data_bytes, offset); #[rustfmt::skip] let packed_data = [ unpacked_data[0], unpacked_data[1], unpacked_data[2], @@ -1738,7 +1732,7 @@ impl super::Queue { rows: naga::VectorSize::Quad, scalar: naga::Scalar::F32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_matrix_2x4_f32_slice(location, false, data) }; } @@ -1750,7 +1744,7 @@ impl super::Queue { rows: naga::VectorSize::Bi, scalar: naga::Scalar::F32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_matrix_3x2_f32_slice(location, false, data) }; } naga::TypeInner::Matrix { @@ -1759,7 +1753,7 @@ impl super::Queue { scalar: naga::Scalar::F32, } => { // repack 3 vec3s into 9 values. - let unpacked_data = unsafe { get_data::(data_bytes, offset) }; + let unpacked_data = &get_data::(data_bytes, offset); #[rustfmt::skip] let packed_data = [ unpacked_data[0], unpacked_data[1], unpacked_data[2], @@ -1773,7 +1767,7 @@ impl super::Queue { rows: naga::VectorSize::Quad, scalar: naga::Scalar::F32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_matrix_3x4_f32_slice(location, false, data) }; } @@ -1785,7 +1779,7 @@ impl super::Queue { rows: naga::VectorSize::Bi, scalar: naga::Scalar::F32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_matrix_4x2_f32_slice(location, false, data) }; } naga::TypeInner::Matrix { @@ -1794,7 +1788,7 @@ impl super::Queue { scalar: naga::Scalar::F32, } => { // repack 4 vec3s into 12 values. - let unpacked_data = unsafe { get_data::(data_bytes, offset) }; + let unpacked_data = &get_data::(data_bytes, offset); #[rustfmt::skip] let packed_data = [ unpacked_data[0], unpacked_data[1], unpacked_data[2], @@ -1809,7 +1803,7 @@ impl super::Queue { rows: naga::VectorSize::Quad, scalar: naga::Scalar::F32, } => { - let data = unsafe { get_data::(data_bytes, offset) }; + let data = &get_data::(data_bytes, offset); unsafe { gl.uniform_matrix_4_f32_slice(location, false, data) }; } _ => panic!("Unsupported uniform datatype: {:?}!", uniform.ty),