Skip to content

Commit d02cb59

Browse files
committed
Auto merge of #999 - vickenty:safe-cast-slice, r=csherratt
Make cast_slice() work only on Pod types. This makes structures defined with gfx_vertex_struct! and gfx_constant_struct! also marked as Pod which is not entirely correct. These structures should only contain Pod types, but there is no way to guarantee that. Fixes #974.
2 parents 08bf5f6 + 2470e4d commit d02cb59

File tree

7 files changed

+32
-11
lines changed

7 files changed

+32
-11
lines changed

src/core/src/factory.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use std::error::Error;
2121
use std::fmt;
2222
use std::mem;
2323
use {handle, format, mapping, pso, shade, target, tex};
24-
use {Capabilities, Resources};
24+
use {Capabilities, Resources, Pod};
2525
use {VertexShader, GeometryShader, PixelShader, ShaderSet};
2626

2727

@@ -38,7 +38,7 @@ pub trait Typed: Sized {
3838

3939

4040
/// Cast a slice from one POD type to another.
41-
pub fn cast_slice<A: Copy, B: Copy>(slice: &[A]) -> &[B] {
41+
pub fn cast_slice<A: Pod, B: Pod>(slice: &[A]) -> &[B] {
4242
use std::slice;
4343
let raw_len = mem::size_of::<A>().wrapping_mul(slice.len());
4444
let len = raw_len / mem::size_of::<B>();
@@ -326,7 +326,7 @@ pub trait Factory<R: Resources> {
326326
fn create_buffer_raw(&mut self, BufferInfo) -> Result<handle::RawBuffer<R>, BufferError>;
327327
fn create_buffer_const_raw(&mut self, data: &[u8], stride: usize, BufferRole, Bind)
328328
-> Result<handle::RawBuffer<R>, BufferError>;
329-
fn create_buffer_const<T: Copy>(&mut self, data: &[T], role: BufferRole, bind: Bind) -> Result<handle::Buffer<R, T>, BufferError> {
329+
fn create_buffer_const<T: Pod>(&mut self, data: &[T], role: BufferRole, bind: Bind) -> Result<handle::Buffer<R, T>, BufferError> {
330330
self.create_buffer_const_raw(cast_slice(data), mem::size_of::<T>(), role, bind)
331331
.map(|raw| Typed::new(raw))
332332
}

src/core/src/format.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
// ETC2_RGB, // Use the EXT2 algorithm on 3 components.
2121
// ETC2_SRGB, // Use the EXT2 algorithm on 4 components (RGBA) in the sRGB color space.
2222
// ETC2_EAC_RGBA8, // Use the EXT2 EAC algorithm on 4 components.
23-
23+
use Pod;
2424

2525
macro_rules! impl_channel_type {
2626
{ $($name:ident = $shader_type:ident [ $($imp_trait:ident),* ] ,)* } => {
@@ -184,7 +184,7 @@ pub struct Format(pub SurfaceType, pub ChannelType);
184184
/// Compile-time surface type trait.
185185
pub trait SurfaceTyped {
186186
/// The corresponding data type to be passed from CPU.
187-
type DataType: Copy;
187+
type DataType: Pod;
188188
/// Return the run-time value of the type.
189189
fn get_surface_type() -> SurfaceType;
190190
}
@@ -289,6 +289,9 @@ macro_rules! alias {
289289
$name(v)
290290
}
291291
}
292+
293+
unsafe impl Pod for $name {}
294+
292295
impl $name {
293296
/// Convert a 2-element slice.
294297
pub fn cast2(v: [$ty; 2]) -> [$name; 2] {

src/core/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,19 @@ pub trait DeviceFence<R: Resources>: Device<Resources=R> where
206206
/// the fence is satisfied
207207
fn fence_wait(&mut self, fence: &handle::Fence<R>);
208208
}
209+
210+
/// A trait for plain-old-data types.
211+
///
212+
/// A POD type does not have invalid bit patterns and can be safely
213+
/// created from arbitrary bit pattern.
214+
pub unsafe trait Pod {}
215+
216+
macro_rules! impl_pod {
217+
( ty = $($ty:ty)* ) => { $( unsafe impl Pod for $ty {} )* };
218+
( ar = $($tt:expr)* ) => { $( unsafe impl<T: Pod> Pod for [T; $tt] {} )* };
219+
}
220+
221+
impl_pod! { ty = isize usize i8 u8 i16 u16 i32 u32 i64 u64 f32 f64 }
222+
impl_pod! { ar =
223+
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
224+
}

src/render/src/encoder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use std::fmt;
2323
use std::mem;
2424

2525
use gfx_core::{Device, IndexType, Resources, VertexCount};
26-
use gfx_core::{draw, format, handle, tex};
26+
use gfx_core::{draw, format, handle, tex, Pod};
2727
use gfx_core::factory::{cast_slice, Typed};
2828
use slice;
2929
use pso;
@@ -120,7 +120,7 @@ impl<R: Resources, C: draw::CommandBuffer<R>> Encoder<R, C> {
120120
}
121121

122122
/// Update a buffer with a slice of data.
123-
pub fn update_buffer<T: Copy>(&mut self, buf: &handle::Buffer<R, T>,
123+
pub fn update_buffer<T: Pod>(&mut self, buf: &handle::Buffer<R, T>,
124124
data: &[T], offset_elements: usize)
125125
-> Result<(), UpdateError<usize>>
126126
{

src/render/src/factory.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
//! exposes extension functions and shortcuts to aid with creating and managing graphics resources.
1919
//! See the `FactoryExt` trait for more information.
2020
21-
use gfx_core::{format, handle, tex, state};
21+
use gfx_core::{format, handle, tex, state, Pod};
2222
use gfx_core::{Primitive, Resources, ShaderSet};
2323
use gfx_core::factory::{Bind, BufferRole, Factory};
2424
use gfx_core::pso::{CreationError, Descriptor};
@@ -93,7 +93,7 @@ pub trait FactoryExt<R: Resources>: Factory<R> {
9393
/// constructed.
9494
fn create_vertex_buffer<T>(&mut self, vertices: &[T])
9595
-> handle::Buffer<R, T> where
96-
T: Copy + pso::buffer::Structure<format::Format>
96+
T: Pod + pso::buffer::Structure<format::Format>
9797
{
9898
//debug_assert!(nv <= self.get_capabilities().max_vertex_count);
9999
self.create_buffer_const(vertices, BufferRole::Vertex, Bind::empty()).unwrap()
@@ -103,7 +103,7 @@ pub trait FactoryExt<R: Resources>: Factory<R> {
103103
/// `Slice` from the supplied indices.
104104
fn create_vertex_buffer_with_slice<B, V>(&mut self, vertices: &[V], indices: B)
105105
-> (handle::Buffer<R, V>, Slice<R>)
106-
where V: Copy + pso::buffer::Structure<format::Format>,
106+
where V: Pod + pso::buffer::Structure<format::Format>,
107107
B: IntoIndexBuffer<R>
108108
{
109109
let vertex_buffer = self.create_vertex_buffer(vertices);

src/render/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extern crate gfx_core;
2424

2525
/// public re-exported traits
2626
pub mod traits {
27-
pub use gfx_core::{Device, Factory, DeviceFence};
27+
pub use gfx_core::{Device, Factory, DeviceFence, Pod};
2828
pub use factory::FactoryExt;
2929
}
3030

src/render/src/macros/structure.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ macro_rules! gfx_impl_struct {
2424
$( pub $field: $ty, )*
2525
}
2626

27+
unsafe impl $crate::traits::Pod for $root {}
28+
2729
impl $crate::pso::buffer::Structure<$runtime_format> for $root {
2830
fn query(name: &str) -> Option<$crate::pso::buffer::Element<$runtime_format>> {
2931
use std::mem::size_of;

0 commit comments

Comments
 (0)