Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decouple render::mesh from GlDevice #589

Merged
merged 5 commits into from
Feb 22, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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