diff --git a/examples/triangle/main.rs b/examples/triangle/main.rs index c877f40f1eb..1afa86ecbb1 100644 --- a/examples/triangle/main.rs +++ b/examples/triangle/main.rs @@ -115,7 +115,7 @@ fn main() { .ok().expect("Failed to link program"); let mut graphics = gfx::Graphics::new(device); - let batch: gfx::batch::RefBatch<(), ()> = graphics.make_batch( + let batch: gfx::batch::RefBatch<()> = graphics.make_batch( &program, &mesh, slice, &gfx::DrawState::new()).ok().expect("Failed to make batch"); let clear_data = gfx::ClearData { diff --git a/src/gfx/lib.rs b/src/gfx/lib.rs index 3ec38e746c0..a602c9577de 100644 --- a/src/gfx/lib.rs +++ b/src/gfx/lib.rs @@ -72,12 +72,12 @@ impl Graphics { } /// Create a new ref batch. - pub fn make_batch>(&mut self, + pub fn make_batch(&mut self, program: &ProgramHandle, mesh: &Mesh, slice: Slice, state: &DrawState) - -> Result, batch::BatchError> { + -> Result, batch::BatchError> { self.context.make_batch(program, mesh, slice, state) } @@ -87,14 +87,14 @@ impl Graphics { } /// Draw a ref batch. - pub fn draw<'a, L, T: shade::ShaderParam>(&'a mut self, - batch: &'a batch::RefBatch, data: &'a T, frame: &Frame) { + pub fn draw<'a, T: shade::ShaderParam>(&'a mut self, + batch: &'a batch::RefBatch, data: &'a T, frame: &Frame) { self.renderer.draw(&(batch, data, &self.context), frame) } /// Draw a ref batch with instancing - pub fn draw_instanced<'a, L, T: shade::ShaderParam>(&'a mut self, - batch: &'a batch::RefBatch, + pub fn draw_instanced<'a, T: shade::ShaderParam>(&'a mut self, + batch: &'a batch::RefBatch, data: &'a T, count: u32, vertex_offset: u32, diff --git a/src/gfx_macros/shader_param.rs b/src/gfx_macros/shader_param.rs index c0a57e5f111..f1f33a0d8a9 100644 --- a/src/gfx_macros/shader_param.rs +++ b/src/gfx_macros/shader_param.rs @@ -236,16 +236,6 @@ fn node_to_var_type(cx: &mut ext::base::ExtCtxt, )) } -/// Extract all derive() attributes into a separate array -fn copy_derive(attribs: &[ast::Attribute]) -> Vec { - attribs.iter().filter(|at| { - match at.node.value.node { - ast::MetaList(ref s, _) => s.get() == "derive" || s.get() == "deriving", - _ => false, - } - }).map(|at| at.clone()).collect() -} - #[derive(Copy)] pub struct ShaderParam; @@ -261,7 +251,7 @@ impl ItemDecorator for ShaderParam { let (base_def, link_def) = match item.node { ast::ItemStruct(ref definition, ref generics) => { if generics.lifetimes.len() > 0 { - context.bug("Generics are not allowed in ShaderParam struct"); + context.bug("Lifetimes are not allowed in ShaderParam struct"); } (definition, ast::StructDef { fields: definition.fields.iter() @@ -282,23 +272,12 @@ impl ItemDecorator for ShaderParam { return; } }; - let link_name = format!("_{:?}Link", item.ident.as_str()); + let link_name = format!("_{}Link", item.ident.as_str()); let link_ident = context.ident_of(&link_name[]); - let link_ty = box generic::ty::Literal( + let link_ty = generic::ty::Literal( generic::ty::Path::new_local(&link_name[]) ); - // Almost `context.item_struct(span, link_ident, link_def)` but with visibility - (*push)(P(ast::Item { - ident: link_ident, - attrs: copy_derive(&item.attrs[]), - id: ast::DUMMY_NODE_ID, - node: ast::ItemStruct( - P(link_def), - ast_util::empty_generics() - ), - vis: item.vis, - span: span, - })); + (*push)(context.item_struct(span, link_ident, link_def)); // constructing the `Batch` implementation typedef match meta_item.node { ast::MetaList(_, ref items) if items.len() <= 2 => { @@ -317,7 +296,6 @@ impl ItemDecorator for ShaderParam { ], Vec::new(), vec![ - context.ty_ident(span, link_ident), context.ty_ident(span, item.ident) ], Vec::new(), @@ -345,14 +323,14 @@ impl ItemDecorator for ShaderParam { as `#[shader_param(MyLightBatch, MyHeavyBatch)]`") } } - // #[derive ShaderParam + // #[derive ShaderParam] let trait_def = generic::TraitDef { span: span, attributes: Vec::new(), path: generic::ty::Path { path: vec![super::EXTERN_CRATE_HACK, "gfx", "shade", "ShaderParam"], lifetime: None, - params: vec![link_ty.clone()], + params: Vec::new(), global: false, }, additional_bounds: Vec::new(), @@ -385,7 +363,7 @@ impl ItemDecorator for ShaderParam { path: vec!["Result"], lifetime: None, params: vec![ - link_ty.clone(), + box link_ty.clone(), box generic::ty::Literal(generic::ty::Path::new( vec![super::EXTERN_CRATE_HACK, "gfx", "shade", "ParameterError"] )) @@ -406,7 +384,7 @@ impl ItemDecorator for ShaderParam { ))), args: vec![ generic::ty::Ptr( - link_ty.clone(), + box link_ty.clone(), generic::ty::Borrowed(None, ast::MutImmutable) ), generic::ty::Literal( @@ -420,6 +398,9 @@ impl ItemDecorator for ShaderParam { ), }, ], + associated_types: vec![ + (context.ident_of("Link"), link_ty), + ], }; let fixup = |: item| { (*push)(super::fixup_extern_crate_paths(item, path_root)) diff --git a/src/gfx_macros/vertex_format.rs b/src/gfx_macros/vertex_format.rs index 388d6e5c8c0..3222f1d5b1f 100644 --- a/src/gfx_macros/vertex_format.rs +++ b/src/gfx_macros/vertex_format.rs @@ -277,6 +277,7 @@ impl ItemDecorator for VertexFormat { box |c, s, ss| method_body(c, s, ss, path_root)), }, ], + associated_types: Vec::new(), }.expand(context, meta_item, item, fixup); } } diff --git a/src/render/batch.rs b/src/render/batch.rs index af4640ae081..a840d5b0a0f 100644 --- a/src/render/batch.rs +++ b/src/render/batch.rs @@ -75,7 +75,7 @@ pub trait Batch { } /// Owned batch - self-contained, but has heap-allocated data -pub struct OwnedBatch { +pub struct OwnedBatch { mesh: mesh::Mesh, mesh_link: mesh::Link, /// Mesh slice @@ -83,15 +83,15 @@ pub struct OwnedBatch { /// Parameter data. pub param: T, program: ProgramHandle, - param_link: L, + param_link: T::Link, /// Draw state pub state: DrawState, } -impl> OwnedBatch { +impl OwnedBatch { /// Create a new owned batch pub fn new(mesh: mesh::Mesh, program: ProgramHandle, param: T) - -> Result, BatchError> { + -> Result, BatchError> { let slice = mesh.to_slice(PrimitiveType::TriangleList); let mesh_link = match link_mesh(&mesh, program.get_info()) { Ok(l) => l, @@ -113,7 +113,7 @@ impl> OwnedBatch { } } -impl> Batch for OwnedBatch { +impl Batch for OwnedBatch { fn get_data(&self) -> (&mesh::Mesh, &mesh::Link, &mesh::Slice, &ProgramHandle, &DrawState) { (&self.mesh, &self.mesh_link, &self.slice, &self.program, &self.state) } @@ -201,42 +201,43 @@ impl Array { /// Ref batch - copyable and smaller, but depends on the `Context`. /// It has references to the resources (mesh, program, state), that are held /// by the context that created the batch, so these have to be used together. -#[derive(Copy)] -pub struct RefBatch { +pub struct RefBatch { mesh_id: Id, mesh_link: mesh::Link, /// Mesh slice pub slice: mesh::Slice, program_id: Id, - param_link: L, + param_link: T::Link, state_id: Id, } -impl fmt::Debug for RefBatch { +impl Copy for RefBatch where T::Link: Copy {} + +impl fmt::Debug for RefBatch { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "RefBatch(mesh: {:?}, slice: {:?}, program: {:?}, state: {:?})", self.mesh_id, self.slice, self.program_id, self.state_id) } } -impl PartialEq for RefBatch { - fn eq(&self, other: &RefBatch) -> bool { +impl PartialEq for RefBatch { + fn eq(&self, other: &RefBatch) -> bool { self.program_id == other.program_id && self.state_id == other.state_id && self.mesh_id == other.mesh_id } } -impl Eq for RefBatch {} +impl Eq for RefBatch {} -impl PartialOrd for RefBatch { - fn partial_cmp(&self, other: &RefBatch) -> Option { +impl PartialOrd for RefBatch { + fn partial_cmp(&self, other: &RefBatch) -> Option { Some(self.cmp(other)) } } -impl Ord for RefBatch { - fn cmp(&self, other: &RefBatch) -> Ordering { +impl Ord for RefBatch { + fn cmp(&self, other: &RefBatch) -> Ordering { (&self.program_id, &self.state_id, &self.mesh_id).cmp( &(&other.program_id, &other.state_id, &other.mesh_id)) } @@ -262,12 +263,12 @@ impl Context { impl Context { /// Produce a new ref batch - pub fn make_batch>(&mut self, + pub fn make_batch(&mut self, program: &ProgramHandle, mesh: &mesh::Mesh, slice: mesh::Slice, state: &DrawState) - -> Result, BatchError> { + -> Result, BatchError> { let mesh_link = match link_mesh(mesh, program.get_info()) { Ok(l) => l, Err(e) => return Err(BatchError::Mesh(e)), @@ -300,7 +301,7 @@ impl Context { } } -impl<'a, L, T: ShaderParam> Batch for (&'a RefBatch, &'a T, &'a Context) { +impl<'a, T: ShaderParam> Batch for (&'a RefBatch, &'a T, &'a Context) { fn get_data(&self) -> (&mesh::Mesh, &mesh::Link, &mesh::Slice, &ProgramHandle, &DrawState) { let (b, _, ctx) = *self; (ctx.meshes.get(b.mesh_id), diff --git a/src/render/shade.rs b/src/render/shade.rs index 56afcf12237..893d200ffcf 100644 --- a/src/render/shade.rs +++ b/src/render/shade.rs @@ -89,14 +89,18 @@ pub enum ParameterError { } /// Abstracts the shader parameter structure, generated by the `shader_param` attribute -pub trait ShaderParam { - /// Creates a new link, self is passed as a workaround for Rust to not be lost in generics - fn create_link(Option<&Self>, &shade::ProgramInfo) -> Result; - /// Get all the contained parameter values, using a given link. - fn fill_params(&self, &L, ParamValues); +pub trait ShaderParam { + /// A helper structure to contain variable indices inside the shader + type Link; + /// Create a new link to be used with a given program + fn create_link(Option<&Self>, &shade::ProgramInfo) -> Result; + /// Get all the contained parameter values, using a given link + fn fill_params(&self, &Self::Link, ParamValues); } -impl ShaderParam<()> for () { +impl ShaderParam for () { + type Link = (); + fn create_link(_: Option<&()>, info: &shade::ProgramInfo) -> Result<(), ParameterError> { match info.uniforms[].first() { Some(u) => return Err(ParameterError::MissingUniform(u.name.clone())), @@ -136,15 +140,16 @@ pub struct ParamDictionary { pub textures: Vec>, } -/// An associated link structure for `ParamDictionary` that redirects program -/// input to the relevant dictionary cell. +/// Redirects program input to the relevant ParamDictionary cell pub struct ParamDictionaryLink { uniforms: Vec, blocks: Vec, textures: Vec, } -impl ShaderParam for ParamDictionary { +impl ShaderParam for ParamDictionary { + type Link = ParamDictionaryLink; + fn create_link(this: Option<&ParamDictionary>, info: &shade::ProgramInfo) -> Result { let this = match this {