Skip to content

Commit

Permalink
Merge pull request #589 from bjz/associated-resources
Browse files Browse the repository at this point in the history
Decouple render::mesh from GlDevice
  • Loading branch information
kvark committed Feb 22, 2015
2 parents c045b51 + 13e3a5d commit 303cdd0
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 50 deletions.
4 changes: 2 additions & 2 deletions src/gfx/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ impl<D: device::Device> Graphics<D> {
/// Create a new ref batch.
pub fn make_batch<T: shade::ShaderParam>(&mut self,
program: &ProgramHandle<GlResources>,
mesh: &Mesh,
slice: Slice,
mesh: &Mesh<GlResources>,
slice: Slice<GlResources>,
state: &DrawState)
-> Result<batch::RefBatch<T>, batch::BatchError> {
self.context.make_batch(program, mesh, slice, state)
Expand Down
14 changes: 11 additions & 3 deletions src/gfx_macros/vertex_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,13 @@ impl ItemDecorator for VertexFormat {
path: vec!["Vec"],
lifetime: None,
params: vec![
box generic::ty::Literal(generic::ty::Path::new(
vec![super::EXTERN_CRATE_HACK, "gfx", "Attribute"])),
box generic::ty::Literal(generic::ty::Path {
path: vec![super::EXTERN_CRATE_HACK, "gfx", "Attribute"],
lifetime: None,
params: vec![box generic::ty::Literal(generic::ty::Path::new(
vec![super::EXTERN_CRATE_HACK, "gfx", "GlResources"]))],
global: false,
}),
],
global: false,
},
Expand All @@ -283,7 +288,10 @@ impl ItemDecorator for VertexFormat {
box |c, s, ss| method_body(c, s, ss, path_root)),
},
],
associated_types: Vec::new(),
associated_types: vec![
(context.ident_of("Resources"), generic::ty::Literal(generic::ty::Path::new(
vec![super::EXTERN_CRATE_HACK, "gfx", "GlResources"]))),
],
}.expand(context, meta_item, item, fixup);
}
}
24 changes: 12 additions & 12 deletions src/render/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub enum BatchError {

/// Match mesh attributes against shader inputs, produce a mesh link.
/// Exposed to public to allow external `Batch` implementations to use it.
pub fn link_mesh(mesh: &mesh::Mesh, pinfo: &ProgramInfo) -> Result<mesh::Link, MeshError> {
pub fn link_mesh(mesh: &mesh::Mesh<back::GlResources>, pinfo: &ProgramInfo) -> Result<mesh::Link, MeshError> {
let mut indices = Vec::new();
for sat in pinfo.attributes.iter() {
match mesh.attributes.iter().enumerate()
Expand All @@ -69,8 +69,8 @@ pub fn link_mesh(mesh: &mesh::Mesh, pinfo: &ProgramInfo) -> Result<mesh::Link, M
}

/// Return type for `Batch::get_data()``
pub type BatchData<'a> = (&'a mesh::Mesh, mesh::AttributeIter, &'a mesh::Slice,
&'a DrawState);
pub type BatchData<'a> = (&'a mesh::Mesh<back::GlResources>, mesh::AttributeIter,
&'a mesh::Slice<back::GlResources>, &'a DrawState);

/// Abstract batch trait
pub trait Batch {
Expand All @@ -83,7 +83,7 @@ pub trait Batch {
-> Result<&ProgramHandle<back::GlResources>, Self::Error>;
}

impl<'a, T: ShaderParam> Batch for (&'a mesh::Mesh, mesh::Slice,
impl<'a, T: ShaderParam> Batch for (&'a mesh::Mesh<back::GlResources>, mesh::Slice<back::GlResources>,
&'a ProgramHandle<back::GlResources>, &'a T, &'a DrawState) {
type Error = BatchError;

Expand All @@ -110,10 +110,10 @@ impl<'a, T: ShaderParam> Batch for (&'a mesh::Mesh, mesh::Slice,

/// Owned batch - self-contained, but has heap-allocated data
pub struct OwnedBatch<T: ShaderParam> {
mesh: mesh::Mesh,
mesh: mesh::Mesh<back::GlResources>,
mesh_link: mesh::Link,
/// Mesh slice
pub slice: mesh::Slice,
pub slice: mesh::Slice<back::GlResources>,
/// Parameter data.
pub param: T,
program: ProgramHandle<back::GlResources>,
Expand All @@ -124,7 +124,7 @@ pub struct OwnedBatch<T: ShaderParam> {

impl<T: ShaderParam> OwnedBatch<T> {
/// Create a new owned batch
pub fn new(mesh: mesh::Mesh, program: ProgramHandle<back::GlResources>, param: T)
pub fn new(mesh: mesh::Mesh<back::GlResources>, program: ProgramHandle<back::GlResources>, param: T)
-> Result<OwnedBatch<T>, BatchError> {
let slice = mesh.to_slice(PrimitiveType::TriangleList);
let mesh_link = match link_mesh(&mesh, program.get_info()) {
Expand Down Expand Up @@ -248,10 +248,10 @@ impl<T: Clone + PartialEq> Array<T> {
/// 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.
pub struct RefBatch<T: ShaderParam> {
mesh_id: Id<mesh::Mesh>,
mesh_id: Id<mesh::Mesh<back::GlResources>>,
mesh_link: mesh::Link,
/// Mesh slice
pub slice: mesh::Slice,
pub slice: mesh::Slice<back::GlResources>,
program_id: Id<ProgramHandle<back::GlResources>>,
param_link: T::Link,
state_id: Id<DrawState>,
Expand Down Expand Up @@ -306,7 +306,7 @@ impl<T: ShaderParam> RefBatch<T> {

/// Factory of ref batches, required to always be used with them.
pub struct Context {
meshes: Array<mesh::Mesh>,
meshes: Array<mesh::Mesh<back::GlResources>>,
programs: Array<ProgramHandle<back::GlResources>>,
states: Array<DrawState>,
}
Expand All @@ -326,8 +326,8 @@ impl Context {
/// Produce a new ref batch
pub fn make_batch<T: ShaderParam>(&mut self,
program: &ProgramHandle<back::GlResources>,
mesh: &mesh::Mesh,
slice: mesh::Slice,
mesh: &mesh::Mesh<back::GlResources>,
slice: mesh::Slice<back::GlResources>,
state: &DrawState)
-> Result<RefBatch<T>, BatchError> {
let mesh_link = match link_mesh(mesh, program.get_info()) {
Expand Down
7 changes: 5 additions & 2 deletions src/render/device_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ pub trait DeviceExt: device::Device {
fn create_renderer(&mut self) -> ::Renderer<Self>;
/// Create a new mesh from the given vertex data.
/// Convenience function around `create_buffer` and `Mesh::from_format`.
fn create_mesh<T: VertexFormat + Copy>(&mut self, data: &[T]) -> Mesh;
fn create_mesh<T>(&mut self, data: &[T]) -> Mesh<back::GlResources> where
T: VertexFormat<Resources = back::GlResources> + Copy;
/// Create a simple program given a vertex shader with a fragment one.
fn link_program(&mut self, vs_code: &[u8], fs_code: &[u8])
-> Result<device::ProgramHandle<back::GlResources>, ProgramError>;
Expand All @@ -87,7 +88,9 @@ impl<D: device::Device> DeviceExt for D {
}
}

fn create_mesh<T: VertexFormat + Copy>(&mut self, data: &[T]) -> Mesh {
fn create_mesh<T>(&mut self, data: &[T]) -> Mesh<back::GlResources> where
T: VertexFormat<Resources = back::GlResources> + Copy,
{
let nv = data.len();
debug_assert!(nv < {
use std::num::Int;
Expand Down
4 changes: 2 additions & 2 deletions src/render/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ impl<D: Device> Renderer<D> {
}

fn bind_mesh<I: Iterator<Item = mesh::AttributeIndex>>(&mut self,
mesh: &mesh::Mesh, attrib_iter: I, info: &ProgramInfo) {
mesh: &mesh::Mesh<back::GlResources>, attrib_iter: I, info: &ProgramInfo) {
if !self.render_state.is_array_buffer_set {
// It's Ok if the array buffer is not supported. We can just ignore it.
self.common_array_buffer.map(|ab|
Expand Down Expand Up @@ -456,7 +456,7 @@ impl<D: Device> Renderer<D> {
}
}

fn draw_slice(&mut self, slice: &mesh::Slice,
fn draw_slice(&mut self, slice: &mesh::Slice<back::GlResources>,
instances: Option<(device::InstanceCount, device::VertexCount)>) {
let mesh::Slice { start, end, prim_type, kind } = slice.clone();
match kind {
Expand Down
63 changes: 34 additions & 29 deletions src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,57 +21,62 @@
//! `Buffer`, and then use `Mesh::from`.

use device;
use device::{PrimitiveType, BufferHandle, VertexCount};
use device::{attrib, back};
use device::{PrimitiveType, BufferHandle, Resources, VertexCount};
use device::attrib;

/// Describes a single attribute of a vertex buffer, including its type, name, etc.
#[derive(Clone, Debug, PartialEq)]
pub struct Attribute {
pub struct Attribute<R: Resources> {
/// A name to match the shader input
pub name: String,
/// Vertex buffer to contain the data
pub buffer: device::RawBufferHandle<back::GlResources>,
pub buffer: device::RawBufferHandle<R>,
/// Format of the attribute
pub format: attrib::Format,
}

/// A trait implemented automatically for user vertex structure by
/// `#[vertex_format] attribute
pub trait VertexFormat {
type Resources: Resources;
/// Create the attributes for this type, using the given buffer.
fn generate(Option<Self>, buffer: device::RawBufferHandle<back::GlResources>) -> Vec<Attribute>;
fn generate(Option<Self>, buffer: device::RawBufferHandle<Self::Resources>) -> Vec<Attribute<Self::Resources>>;
}

/// Describes geometry to render.
#[derive(Clone, Debug, PartialEq)]
pub struct Mesh {
pub struct Mesh<R: Resources> {
/// Number of vertices in the mesh.
pub num_vertices: device::VertexCount,
/// Vertex attributes to use.
pub attributes: Vec<Attribute>,
pub attributes: Vec<Attribute<R>>,
}

impl Mesh {
impl<R: Resources> Mesh<R> {
/// Create a new mesh, which is a `TriangleList` with no attributes and `nv` vertices.
pub fn new(nv: device::VertexCount) -> Mesh {
pub fn new(nv: device::VertexCount) -> Mesh<R> {
Mesh {
num_vertices: nv,
attributes: Vec::new(),
}
}

/// Create a new `Mesh` from a struct that implements `VertexFormat` and a buffer.
pub fn from_format<V: VertexFormat>(buf: device::BufferHandle<back::GlResources, V>, nv: device::VertexCount) -> Mesh {
pub fn from_format<V>(buf: device::BufferHandle<R, V>, nv: device::VertexCount) -> Mesh<R> where
V: VertexFormat<Resources = R>,
{
Mesh {
num_vertices: nv,
attributes: VertexFormat::generate(None::<V>, buf.raw()),
}
}

/// Create a new intanced `Mesh` given a vertex buffer and an instance buffer.
pub fn from_format_instanced<V: VertexFormat, U: VertexFormat>(
buf: device::BufferHandle<back::GlResources, V>, nv: device::VertexCount,
inst: device::BufferHandle<back::GlResources, U>) -> Mesh {
pub fn from_format_instanced<V, U>(buf: device::BufferHandle<R, V>, nv: device::VertexCount,
inst: device::BufferHandle<R, U>) -> Mesh<R> where
V: VertexFormat<Resources = R>,
U: VertexFormat<Resources = R>,
{
let per_vertex = VertexFormat::generate(None::<V>, buf.raw());
let per_instance = VertexFormat::generate(None::<U>, inst.raw());

Expand All @@ -97,20 +102,20 @@ impl Mesh {
/// For example, `Point` typed vertex slice can be used to do shape
/// blending, while still rendereing it as an indexed `TriangleList`.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Slice {
pub struct Slice<R: Resources> {
/// Start index of vertices to draw.
pub start: VertexCount,
/// End index of vertices to draw.
pub end: VertexCount,
/// Primitive type to render collections of vertices as.
pub prim_type: PrimitiveType,
/// Source of the vertex ordering when drawing.
pub kind: SliceKind,
pub kind: SliceKind<R>,
}

/// Source of vertex ordering for a slice
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum SliceKind {
pub enum SliceKind<R: Resources> {
/// Render vertex data directly from the `Mesh`'s buffer.
Vertex,
/// The `Index*` buffer contains a list of indices into the `Mesh`
Expand All @@ -122,22 +127,22 @@ pub enum SliceKind {
/// the vertices will be identical, wasting space for the duplicated
/// attributes. Instead, the `Mesh` can store 4 vertices and an
/// `Index8` can be used instead.
Index8(BufferHandle<back::GlResources, u8>, VertexCount),
Index8(BufferHandle<R, u8>, VertexCount),
/// As `Index8` but with `u16` indices
Index16(BufferHandle<back::GlResources, u16>, VertexCount),
Index16(BufferHandle<R, u16>, VertexCount),
/// As `Index8` but with `u32` indices
Index32(BufferHandle<back::GlResources, u32>, VertexCount),
Index32(BufferHandle<R, u32>, VertexCount),
}

/// Helper methods for cleanly getting the slice of a type.
pub trait ToSlice {
pub trait ToSlice<R: Resources> {
/// Get the slice of a type.
fn to_slice(&self, pt: PrimitiveType) -> Slice;
fn to_slice(&self, pt: PrimitiveType) -> Slice<R>;
}

impl ToSlice for Mesh {
impl<R: Resources> ToSlice<R> for Mesh<R> {
/// Return a vertex slice of the whole mesh.
fn to_slice(&self, ty: PrimitiveType) -> Slice {
fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
Slice {
start: 0,
end: self.num_vertices,
Expand All @@ -147,9 +152,9 @@ impl ToSlice for Mesh {
}
}

impl ToSlice for BufferHandle<back::GlResources, u8> {
impl<R: Resources> ToSlice<R> for BufferHandle<R, u8> {
/// Return an index slice of the whole buffer.
fn to_slice(&self, ty: PrimitiveType) -> Slice {
fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
Slice {
start: 0,
end: self.len() as VertexCount,
Expand All @@ -159,9 +164,9 @@ impl ToSlice for BufferHandle<back::GlResources, u8> {
}
}

impl ToSlice for BufferHandle<back::GlResources, u16> {
impl<R: Resources> ToSlice<R> for BufferHandle<R, u16> {
/// Return an index slice of the whole buffer.
fn to_slice(&self, ty: PrimitiveType) -> Slice {
fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
Slice {
start: 0,
end: self.len() as VertexCount,
Expand All @@ -171,9 +176,9 @@ impl ToSlice for BufferHandle<back::GlResources, u16> {
}
}

impl ToSlice for BufferHandle<back::GlResources, u32> {
impl<R: Resources> ToSlice<R> for BufferHandle<R, u32> {
/// Return an index slice of the whole buffer.
fn to_slice(&self, ty: PrimitiveType) -> Slice {
fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
Slice {
start: 0,
end: self.len() as VertexCount,
Expand Down

0 comments on commit 303cdd0

Please sign in to comment.