Skip to content

Commit

Permalink
Added support for location binding in 'implement_vertex' (#2013)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrndinn committed Jun 12, 2022
1 parent 3fe4d23 commit a851037
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 15 deletions.
59 changes: 57 additions & 2 deletions src/macros.rs
Expand Up @@ -97,10 +97,28 @@ macro_rules! uniform {
///
/// ## Naming convention
///
/// When it comes to using to using your vertex array in a shader you must make sure that all your attribute variables *match* the field names in the struct you are calling calling this macro for.
/// If not using the location option, when it comes to using to using your vertex array in a shader you must make sure that all your attribute variables *match* the field names in the struct you are calling calling this macro for.
///
/// So, if you have a `vertex_position` atribute/input in your shader, a field named `vertex_position` must be present in the struct. Ohterwise the drawing functions will panic.
/// So, if you have a `vertex_position` attribute/input in your shader, a field named `vertex_position` must be present in the struct. Otherwise the drawing functions will panic.
///
/// ## Normalize option
///
/// You can specify a normalize option for attributes.
/// ```
/// # use glium::implement_vertex;
/// # fn main() {
/// implement_vertex!(Vertex, position normalize(false), tex_coords normalize(false));
/// # }
/// ```
/// ## Location option
///
/// You can specify a location option for attributes.
/// ```
/// # use glium::implement_vertex;
/// # fn main() {
/// implement_vertex!(Vertex, position location(0), tex_coords location(1));
/// # }
/// ```
#[macro_export]
macro_rules! implement_vertex {
($struct_name:ident, $($field_name:ident),+) => (
Expand All @@ -116,6 +134,7 @@ macro_rules! implement_vertex {
(
Cow::Borrowed(stringify!($field_name)),
$crate::__glium_offset_of!($struct_name, $field_name),
-1,
{
// Obtain the type of the $field_name field of $struct_name and
// call get_type on it.
Expand Down Expand Up @@ -148,6 +167,7 @@ macro_rules! implement_vertex {
(
Cow::Borrowed(stringify!($field_name)),
$crate::__glium_offset_of!($struct_name, $field_name),
-1,
{
// Obtain the type of the $field_name field of $struct_name and
// call get_type on it.
Expand All @@ -169,6 +189,41 @@ macro_rules! implement_vertex {
}
};

($struct_name:ident, $($field_name:ident location($location:expr)),+) => {
impl $crate::vertex::Vertex for $struct_name {
#[inline]
fn build_bindings() -> $crate::vertex::VertexFormat {
use std::borrow::Cow;

// TODO: use a &'static [] if possible

Cow::Owned(vec![
$(
(
Cow::Borrowed(stringify!($field_name)),
$crate::__glium_offset_of!($struct_name, $field_name),
{
$location
},
{
// Obtain the type of the $field_name field of $struct_name and
// call get_type on it.
fn attr_type_of_val<T: $crate::vertex::Attribute>(_: Option<&T>)
-> $crate::vertex::AttributeType
{
<T as $crate::vertex::Attribute>::get_type()
}
let field_option = None::<&$struct_name>.map(|v| &v.$field_name);
attr_type_of_val(field_option)
},
false
)
),+
])
}
}
};

($struct_name:ident, $($field_name:ident),+,) => (
$crate::implement_vertex!($struct_name, $($field_name),+);
);
Expand Down
2 changes: 1 addition & 1 deletion src/program/raw.rs
Expand Up @@ -428,7 +428,7 @@ impl RawProgram {
}

for elem in buf.elements.iter() {
if format.iter().find(|e| e.1 == elem.offset && e.2 == elem.ty)
if format.iter().find(|e| e.1 == elem.offset && e.3 == elem.ty)
.is_none()
{
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/vertex/format.rs
Expand Up @@ -410,7 +410,7 @@ impl AttributeType {
/// third element is the type and the fourth element indicates whether
/// or not the element should use fixed-point normalization when
/// binding in a VAO.
pub type VertexFormat = Cow<'static, [(Cow<'static, str>, usize, AttributeType, bool)]>;
pub type VertexFormat = Cow<'static, [(Cow<'static, str>, usize, i32, AttributeType, bool)]>;

unsafe impl Attribute for i8 {
#[inline]
Expand Down
2 changes: 1 addition & 1 deletion src/vertex/mod.rs
Expand Up @@ -290,7 +290,7 @@ pub trait Vertex: Copy + Sized {
fn is_supported<C: ?Sized>(caps: &C) -> bool where C: CapabilitiesSource {
let format = Self::build_bindings();

for &(_, _, ref ty, _) in format.iter() {
for &(_, _, _, ref ty, _) in format.iter() {
if !ty.is_supported(caps) {
return false;
}
Expand Down
56 changes: 46 additions & 10 deletions src/vertex_array_object.rs
Expand Up @@ -259,10 +259,22 @@ impl VertexArrayObject {
{
// checking the attributes types
for &(_, ref bindings, _, _, _) in vertex_buffers {
for &(ref name, _, ty, _) in bindings.iter() {
let attribute = match program.get_attribute(Borrow::<str>::borrow(name)) {
Some(a) => a,
None => continue
for &(ref name, _, location, ty, _) in bindings.iter() {
let attribute = match location {
-1 => {
// No location specified in Vertex Format. Check name instead
match program.get_attribute(Borrow::<str>::borrow(name)) {
Some(a) => a,
None => continue,
}
}
_ => {
match program.attributes().into_iter()
.find(|(_, a)| a.location == location) {
Some((_, a)) => a,
None => continue,
}
}
};

if ty.get_num_components() != attribute.ty.get_num_components() ||
Expand All @@ -274,11 +286,23 @@ impl VertexArrayObject {
}
}

// checking for duplicate attribute locations
for &(_, ref bindings, _, _, _) in vertex_buffers {
for (i, bi) in bindings.iter().enumerate() {
for (o, bo) in bindings.iter().enumerate() {
if i != o && bi.2 == bo.2 {
panic!("The program attribute `{}` has the same binding location as program attribute `{}` (binding location {})",
bi.0, bo.0, bi.2)
}
}
}
}

// checking for missing attributes
for (&ref name, _) in program.attributes() {
for (&ref name, attribute) in program.attributes() {
let mut found = false;
for &(_, ref bindings, _, _, _) in vertex_buffers {
if bindings.iter().any(|&(ref n, _, _, _)| n == name) {
if bindings.iter().any(|&(ref n, _, location, _, _)| (location != -1 && location == attribute.location) || n == name) {
found = true;
break;
}
Expand Down Expand Up @@ -520,12 +544,24 @@ unsafe fn bind_attribute(ctxt: &mut CommandContext<'_>, program: &Program,
}

// binding attributes
for &(ref name, offset, ty, normalize) in bindings.iter() {
for &(ref name, offset, location, ty, normalize) in bindings.iter() {
let (data_type, elements_count, instances_count) = vertex_binding_type_to_gl(ty);

let attribute = match program.get_attribute(Borrow::<str>::borrow(name)) {
Some(a) => a,
None => continue
let attribute = match location {
-1 => {
// No location specified in Vertex Format. Check name instead
match program.get_attribute(Borrow::<str>::borrow(name)) {
Some(a) => a,
None => continue,
}
}
_ => {
match program.attributes().into_iter()
.find(|(_, a)| a.location == location) {
Some((_, a)) => a,
None => continue,
}
}
};

if attribute.location != -1 {
Expand Down

0 comments on commit a851037

Please sign in to comment.