├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── glsl-layout-derive ├── Cargo.toml └── src │ └── lib.rs └── src ├── align.rs ├── array.rs ├── cgmath.rs ├── glam.rs ├── lib.rs ├── mat.rs ├── nalgebra.rs ├── scalar.rs ├── uniform.rs └── vec.rs /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target 3 | **/*.rs.bk 4 | Cargo.lock 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | ## [Unreleased] 5 | 6 | ## [0.4.3] - 2022-11-NN 7 | ### Changed 8 | - Update `glam` version from `0.21` to `0.22`. 9 | - Update rust edition from `2018` to `2021`. 10 | 11 | ## [0.4.2] - 2022-08-06 12 | ### Changed 13 | - Used const generics to allow any array size. 14 | - Allow to use nalgebra types as directly as uniforms. 15 | - Allow to use cgmant types as directly as uniforms. 16 | - Allow to use glam types as directly as uniforms. 17 | 18 | ## [0.4.1] - 2022-07-25 19 | ### Added 20 | - Support for [glam](https://github.com/bitshifter/glam-rs) types. -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "glsl-layout" 3 | version = "0.5.0" 4 | authors = ["Zakarum "] 5 | description = "Provides data types and traits to build structures ready to upload into UBO." 6 | license = "MIT/Apache-2.0" 7 | repository = "https://github.com/rustgd/glsl-layout" 8 | keywords = ["graphics", "glsl", "gamedev"] 9 | edition = "2021" 10 | 11 | [features] 12 | bigger-arrays = [] 13 | 14 | [dependencies] 15 | cgmath = { version = "0.18", optional = true } 16 | nalgebra = { version = "0.31", optional = true } 17 | glam = { version = "0.22", optional = true } 18 | glsl-layout-derive = { path = "glsl-layout-derive", version = "0.4.0" } 19 | 20 | [workspace] 21 | members = ["glsl-layout-derive"] 22 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # GLSL-LAYOUT 3 | 4 | This crates provides data types and traits to build structures ready to upload into UBO. 5 | 6 | ## Usage 7 | 8 | Deriving `Uniform` with proc-macro will produce associated type `Std140` 9 | with same data layout as uniform blocks declared with `layout(std140)`. 10 | All members of structure that derives `Uniform` must implement `Uniform` as well. 11 | 12 | Implementing `Uniform` should be done via deriving. 13 | Implementing it manually is possible. 14 | It requires to provide associated type `Std140` which must implement `Std140` trait. 15 | But trait `Std140` is marked unsafe so be careful. 16 | 17 | Trait `Uniform` also requires `Copy`. 18 | 19 | Typical usage scenario is: 20 | ```rust 21 | #[derive(Copy, Clone, Uniform)] 22 | struct FragmentArgs { 23 | pos: vec3, 24 | dir: vec3, 25 | count: uint, 26 | } 27 | 28 | write_to_buffer(&FragmentArgs { 29 | pos: [0.0, 1.0, 2.0].into(), 30 | dir: [3.0, 4.0, 5.0].into(), 31 | count: 42, 32 | }.std140()); 33 | 34 | ``` 35 | 36 | ### Data types 37 | 38 | There are basic data types from glsl: 39 | * boolean (name `bool` is already occupied) 40 | * int 41 | * uint 42 | * float 43 | * double 44 | 45 | Also more complex types: 46 | * vectors - (vec2, vec3, vec4, bvec2, ivec2, uvec2, dvec2 etc) 47 | * matrices - (mat2x3, dmat4 etc) 48 | * arrays - 49 | 50 | ## License 51 | 52 | `glsl-layout` is free and open source software distributed under the terms of both 53 | the [MIT License][lm] and the [Apache License 2.0][la]. 54 | 55 | [lm]: LICENSE-MIT 56 | [la]: LICENSE-APACHE 57 | 58 | ## Contribution 59 | 60 | Unless you explicitly state otherwise, any contribution intentionally submitted 61 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any 62 | additional terms or conditions. 63 | 64 | ## Known issues 65 | 66 | ### On MacOS 67 | If uniform block contains array of structures and this array accessed with dynamic index (variable instead of literal) 68 | it may load wrong bytes for members not aligned to size of `vec4` (16 bytes). In this case manual padding can be the fix. 69 | -------------------------------------------------------------------------------- /glsl-layout-derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "glsl-layout-derive" 3 | version = "0.4.0" 4 | authors = ["Zakarum "] 5 | description = "Custom derive for `glsl-layout` crate." 6 | license = "MIT/Apache-2.0" 7 | repository = "https://github.com/rustgd/glsl-layout" 8 | keywords = ["graphics", "glsl", "gamedev"] 9 | 10 | [lib] 11 | proc-macro = true 12 | 13 | [dependencies] 14 | syn = { version = "1.0", features = ["full"] } 15 | quote = "1.0" 16 | proc-macro2 = "1.0.1" 17 | -------------------------------------------------------------------------------- /glsl-layout-derive/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![recursion_limit = "128"] 2 | 3 | extern crate proc_macro; 4 | extern crate proc_macro2; 5 | extern crate syn; 6 | #[macro_use] 7 | extern crate quote; 8 | 9 | use proc_macro2::Span; 10 | 11 | #[proc_macro_derive(Uniform)] 12 | pub fn uniform(input: proc_macro::TokenStream) -> proc_macro::TokenStream { 13 | let input = proc_macro2::TokenStream::from(input); 14 | 15 | let ast = syn::parse2(input).unwrap(); 16 | 17 | proc_macro::TokenStream::from(impl_uniform(&ast)) 18 | } 19 | 20 | fn impl_uniform(ast: &syn::DeriveInput) -> proc_macro2::TokenStream { 21 | let name = &ast.ident; 22 | 23 | let rname = format_ident!("LayoutStd140{}", name); 24 | 25 | let fields = match &ast.data { 26 | syn::Data::Struct(syn::DataStruct { 27 | fields: syn::Fields::Named(syn::FieldsNamed { named, .. }), 28 | .. 29 | }) => named, 30 | _ => panic!(), 31 | }; 32 | 33 | let aligned_fields = fields.iter().flat_map(|field| { 34 | let (a, f) = aligned_field(field); 35 | vec![a, f] 36 | }); 37 | 38 | let field_names = fields.iter().map(|field| field.ident.as_ref().unwrap()); 39 | let field_names2 = fields.iter().map(|field| field.ident.as_ref().unwrap()); 40 | 41 | let dummy = format_ident!("_GLSL_LAYOUT_{}", name); 42 | 43 | quote! { 44 | #[allow(bad_style)] 45 | const #dummy: () = { 46 | #[repr(C, align(16))] 47 | #[derive(Clone, Copy, Debug, Default)] 48 | pub struct #rname {#( 49 | #aligned_fields, 50 | )*} 51 | 52 | unsafe impl glsl_layout::Std140 for #rname {} 53 | 54 | impl glsl_layout::Uniform for #rname { 55 | type Align = glsl_layout::align::Align16; 56 | type Std140 = #rname; 57 | 58 | fn std140(&self) -> #rname { 59 | self.clone() 60 | } 61 | } 62 | 63 | impl glsl_layout::Uniform for #name { 64 | type Align = glsl_layout::align::Align16; 65 | type Std140 = #rname; 66 | 67 | fn std140(&self) -> #rname { 68 | #rname { 69 | #(#field_names: self.#field_names2.std140(),)* 70 | ..Default::default() 71 | } 72 | } 73 | } 74 | }; 75 | } 76 | } 77 | 78 | fn aligned_field(field: &syn::Field) -> (syn::Field, syn::Field) { 79 | let name = field.ident.as_ref().unwrap(); 80 | let align = syn::Field { 81 | ty: syn::Type::Path(align_type_for(&field.ty)), 82 | ident: Some(format_ident!("_align_{}", name)), 83 | attrs: Vec::new(), 84 | vis: syn::Visibility::Inherited, 85 | colon_token: Some(Default::default()), 86 | }; 87 | 88 | let std140 = syn::Field { 89 | ty: syn::Type::Path(std140_type_for(&field.ty)), 90 | ..field.clone() 91 | }; 92 | 93 | (align, std140) 94 | } 95 | 96 | fn align_type_for(aligned: &syn::Type) -> syn::TypePath { 97 | use std::iter::once; 98 | syn::TypePath { 99 | qself: Some(syn::QSelf { 100 | lt_token: Default::default(), 101 | ty: Box::new(aligned.clone()), 102 | position: 2, 103 | as_token: Some(Default::default()), 104 | gt_token: Default::default(), 105 | }), 106 | path: syn::Path { 107 | leading_colon: None, 108 | segments: once(syn::PathSegment::from(syn::Ident::new( 109 | "glsl_layout", 110 | Span::call_site(), 111 | ))) 112 | .chain(once(syn::Ident::new("Uniform", Span::call_site()).into())) 113 | .chain(once(syn::Ident::new("Align", Span::call_site()).into())) 114 | .collect(), 115 | }, 116 | } 117 | } 118 | 119 | fn std140_type_for(aligned: &syn::Type) -> syn::TypePath { 120 | use std::iter::once; 121 | syn::TypePath { 122 | qself: Some(syn::QSelf { 123 | lt_token: Default::default(), 124 | ty: Box::new(aligned.clone()), 125 | position: 2, 126 | as_token: Some(Default::default()), 127 | gt_token: Default::default(), 128 | }), 129 | path: syn::Path { 130 | leading_colon: None, 131 | segments: once(syn::PathSegment::from(syn::Ident::new( 132 | "glsl_layout", 133 | Span::call_site(), 134 | ))) 135 | .chain(once(syn::Ident::new("Uniform", Span::call_site()).into())) 136 | .chain(once(syn::Ident::new("Std140", Span::call_site()).into())) 137 | .collect(), 138 | }, 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/align.rs: -------------------------------------------------------------------------------- 1 | #[repr(align(4))] 2 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 3 | pub struct Align4; 4 | 5 | #[repr(align(8))] 6 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 7 | pub struct Align8; 8 | 9 | #[repr(align(16))] 10 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 11 | pub struct Align16; 12 | 13 | #[repr(align(32))] 14 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 15 | pub struct Align32; 16 | -------------------------------------------------------------------------------- /src/array.rs: -------------------------------------------------------------------------------- 1 | use crate::align::Align16; 2 | use crate::uniform::{Std140, Uniform}; 3 | use std::{ 4 | marker::PhantomData, 5 | slice::{Iter as SliceIter, IterMut as SliceIterMut}, 6 | }; 7 | 8 | pub(crate) trait MapArray { 9 | fn map_array(values: A, f: F) -> Self; 10 | } 11 | 12 | /// Aligning wrapper. 13 | /// Elements for array are aligned to 16 bytes (size of vec4) at least. 14 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 15 | #[repr(C, align(16))] 16 | pub struct Element(pub T, pub T::Align); 17 | 18 | impl From for Element 19 | where 20 | T: Uniform, 21 | { 22 | fn from(values: T) -> Self { 23 | Element(values, Default::default()) 24 | } 25 | } 26 | 27 | impl AsRef for Element 28 | where 29 | T: Uniform, 30 | { 31 | fn as_ref(&self) -> &T { 32 | &self.0 33 | } 34 | } 35 | 36 | impl AsMut for Element 37 | where 38 | T: Uniform, 39 | { 40 | fn as_mut(&mut self) -> &mut T { 41 | &mut self.0 42 | } 43 | } 44 | 45 | /// Array of `Element`s. 46 | /// This type implements useful traits for converting from unwrapped types. 47 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 48 | #[repr(C, align(16))] 49 | pub struct Array(pub A, pub PhantomData); 50 | 51 | impl Array { 52 | pub fn new(array: A) -> Self { 53 | Array(array, PhantomData) 54 | } 55 | } 56 | 57 | impl AsRef for Array { 58 | fn as_ref(&self) -> &A { 59 | &self.0 60 | } 61 | } 62 | 63 | impl AsMut for Array { 64 | fn as_mut(&mut self) -> &mut A { 65 | &mut self.0 66 | } 67 | } 68 | 69 | impl Array 70 | where 71 | T: Uniform, 72 | A: AsMut<[Element]> + AsRef<[Element]>, 73 | { 74 | pub fn iter(&self) -> ArrayIter>> { 75 | ArrayIter(self.0.as_ref().iter()) 76 | } 77 | 78 | pub fn iter_mut(&mut self) -> ArrayIter>> { 79 | ArrayIter(self.0.as_mut().iter_mut()) 80 | } 81 | } 82 | 83 | impl<'a, T, A> IntoIterator for &'a Array 84 | where 85 | T: Uniform, 86 | A: AsMut<[Element]> + AsRef<[Element]>, 87 | { 88 | type Item = &'a T; 89 | type IntoIter = ArrayIter>>; 90 | 91 | fn into_iter(self) -> ArrayIter>> { 92 | self.iter() 93 | } 94 | } 95 | 96 | impl<'a, T, A> IntoIterator for &'a mut Array 97 | where 98 | T: Uniform, 99 | A: AsMut<[Element]> + AsRef<[Element]>, 100 | { 101 | type Item = &'a mut T; 102 | type IntoIter = ArrayIter>>; 103 | 104 | fn into_iter(self) -> ArrayIter>> { 105 | self.iter_mut() 106 | } 107 | } 108 | 109 | /// Array ref iterator 110 | /// Iterate over references to inner values. 111 | pub struct ArrayIter(I); 112 | 113 | impl<'a, T> Iterator for ArrayIter>> 114 | where 115 | T: Uniform, 116 | { 117 | type Item = &'a T; 118 | 119 | fn next(&mut self) -> Option<&'a T> { 120 | self.0.next().map(|elem| &elem.0) 121 | } 122 | } 123 | 124 | impl<'a, T> ExactSizeIterator for ArrayIter>> 125 | where 126 | T: Uniform, 127 | { 128 | fn len(&self) -> usize { 129 | self.0.len() 130 | } 131 | } 132 | 133 | impl<'a, T> DoubleEndedIterator for ArrayIter>> 134 | where 135 | T: Uniform, 136 | { 137 | fn next_back(&mut self) -> Option<&'a T> { 138 | self.0.next_back().map(|elem| &elem.0) 139 | } 140 | } 141 | 142 | impl<'a, T> Iterator for ArrayIter>> 143 | where 144 | T: Uniform, 145 | { 146 | type Item = &'a mut T; 147 | 148 | fn next(&mut self) -> Option<&'a mut T> { 149 | self.0.next().map(|elem| &mut elem.0) 150 | } 151 | } 152 | 153 | impl<'a, T> ExactSizeIterator for ArrayIter>> 154 | where 155 | T: Uniform, 156 | { 157 | fn len(&self) -> usize { 158 | self.0.len() 159 | } 160 | } 161 | 162 | impl<'a, T> DoubleEndedIterator for ArrayIter>> 163 | where 164 | T: Uniform, 165 | { 166 | fn next_back(&mut self) -> Option<&'a mut T> { 167 | self.0.next_back().map(|elem| &mut elem.0) 168 | } 169 | } 170 | 171 | impl MapArray<[T; N], F> for [U; N] 172 | where 173 | F: FnMut(T) -> U, 174 | { 175 | fn map_array(values: [T; N], mut f: F) -> Self { 176 | use std::{ 177 | mem::{ManuallyDrop, MaybeUninit}, 178 | ptr::{read, write}, 179 | }; 180 | 181 | // Use `ManuallyDrop<_>` to guard against panic safety issue. 182 | // Upon panic in `f`, `values` isn't dropped 183 | // and thus item copied by `read()` is dropped only once. 184 | let values = ManuallyDrop::new(values); 185 | unsafe { 186 | let mut result: MaybeUninit<[U; N]> = MaybeUninit::zeroed(); 187 | for i in 0..N { 188 | write(result.as_mut_ptr().cast::().add(i), f(read(&values[i]))); 189 | } 190 | result.assume_init() 191 | } 192 | } 193 | } 194 | 195 | impl From<[T; N]> for Array 196 | where 197 | T: Into, 198 | { 199 | fn from(values: [T; N]) -> Self { 200 | Array(MapArray::map_array(values, T::into), PhantomData) 201 | } 202 | } 203 | 204 | impl From<[T; N]> for Array; N]> 205 | where 206 | T: Into, 207 | U: Uniform, 208 | { 209 | fn from(values: [T; N]) -> Self { 210 | let values: [U; N] = MapArray::map_array(values, T::into); 211 | Array(MapArray::map_array(values, U::into), PhantomData) 212 | } 213 | } 214 | 215 | impl Uniform for [T; N] 216 | where 217 | T: Uniform, 218 | { 219 | type Align = Align16; 220 | type Std140 = Array; N]>; 221 | 222 | fn std140(&self) -> Array; N]> { 223 | use std::ptr::write; 224 | unsafe { 225 | // All elements of `result` is written. 226 | let mut result: ::std::mem::MaybeUninit<[Element; N]> = 227 | ::std::mem::MaybeUninit::zeroed(); 228 | for (i, item) in self.iter().enumerate().take(N) { 229 | write( 230 | result.as_mut_ptr().cast::>().add(i), 231 | item.std140().into(), 232 | ); 233 | } 234 | Array(result.assume_init(), PhantomData) 235 | } 236 | } 237 | } 238 | 239 | impl Uniform for Array; N]> 240 | where 241 | T: Uniform, 242 | { 243 | type Align = Align16; 244 | type Std140 = Array; N]>; 245 | 246 | fn std140(&self) -> Array; N]> { 247 | use std::ptr::write; 248 | unsafe { 249 | // All elements of `result` is written. 250 | let mut result: ::std::mem::MaybeUninit<[Element; N]> = 251 | ::std::mem::MaybeUninit::zeroed(); 252 | for i in 0..N { 253 | write( 254 | result.as_mut_ptr().cast::>().add(i), 255 | self.0[i].0.std140().into(), 256 | ); 257 | } 258 | Array(result.assume_init(), PhantomData) 259 | } 260 | } 261 | } 262 | 263 | unsafe impl Std140 for Array; N]> where T: Std140 {} 264 | 265 | #[test] 266 | fn test_array() { 267 | use crate::{mat4, vec2, vec3}; 268 | 269 | let _ = [vec2::default(), vec2::default()].std140(); 270 | let _ = [ 271 | vec3::default(), 272 | vec3::default(), 273 | vec3::default(), 274 | vec3::default(), 275 | vec3::default(), 276 | vec3::default(), 277 | vec3::default(), 278 | vec3::default(), 279 | vec3::default(), 280 | vec3::default(), 281 | vec3::default(), 282 | vec3::default(), 283 | vec3::default(), 284 | vec3::default(), 285 | vec3::default(), 286 | vec3::default(), 287 | vec3::default(), 288 | vec3::default(), 289 | ] 290 | .std140(); 291 | 292 | let _ = [ 293 | mat4::default(), 294 | mat4::default(), 295 | mat4::default(), 296 | mat4::default(), 297 | mat4::default(), 298 | mat4::default(), 299 | mat4::default(), 300 | mat4::default(), 301 | mat4::default(), 302 | mat4::default(), 303 | mat4::default(), 304 | mat4::default(), 305 | mat4::default(), 306 | mat4::default(), 307 | mat4::default(), 308 | mat4::default(), 309 | mat4::default(), 310 | mat4::default(), 311 | ] 312 | .std140(); 313 | } 314 | -------------------------------------------------------------------------------- /src/cgmath.rs: -------------------------------------------------------------------------------- 1 | use crate::mat::{dmat2, dmat3, dmat4, imat2, imat3, imat4, mat2, mat3, mat4, umat2, umat3, umat4}; 2 | use crate::scalar::{double, float, int, uint}; 3 | use crate::uniform::Uniform; 4 | use crate::vec::{dvec2, dvec3, dvec4, ivec2, ivec3, ivec4, uvec2, uvec3, uvec4, vec2, vec3, vec4}; 5 | use cgmath::{Matrix2, Matrix3, Matrix4, Vector2, Vector3, Vector4}; 6 | 7 | macro_rules! impl_vec_from_cgmath { 8 | ($vec:ident : $cgmath:ident => [$type:ty; $size:tt]) => { 9 | impl From<$cgmath<$type>> for $vec { 10 | fn from(value: $cgmath<$type>) -> Self { 11 | let array: [$type; $size] = value.into(); 12 | array.into() 13 | } 14 | } 15 | 16 | impl Uniform for $cgmath<$type> { 17 | type Align = <$vec as Uniform>::Align; 18 | type Std140 = $vec; 19 | 20 | fn std140(&self) -> Self::Std140 { 21 | Self::Std140::from(*self) 22 | } 23 | } 24 | }; 25 | } 26 | 27 | macro_rules! impl_mat_from_cgmath { 28 | ($mat:ident : $cgmath:ident => [$type:ty; $size:tt]) => { 29 | impl From<$cgmath<$type>> for $mat { 30 | fn from(value: $cgmath<$type>) -> Self { 31 | let array: [[$type; $size]; $size] = value.into(); 32 | array.into() 33 | } 34 | } 35 | 36 | impl Uniform for $cgmath<$type> { 37 | type Align = <$mat as Uniform>::Align; 38 | type Std140 = $mat; 39 | 40 | fn std140(&self) -> Self::Std140 { 41 | let array: [[$type; $size]; $size] = (*self).into(); 42 | Self::Std140::from(array) 43 | } 44 | } 45 | }; 46 | } 47 | 48 | impl_vec_from_cgmath!(ivec2 : Vector2 => [int; 2]); 49 | impl_vec_from_cgmath!(ivec3 : Vector3 => [int; 3]); 50 | impl_vec_from_cgmath!(ivec4 : Vector4 => [int; 4]); 51 | impl_vec_from_cgmath!(uvec2 : Vector2 => [uint; 2]); 52 | impl_vec_from_cgmath!(uvec3 : Vector3 => [uint; 3]); 53 | impl_vec_from_cgmath!(uvec4 : Vector4 => [uint; 4]); 54 | impl_vec_from_cgmath!( vec2 : Vector2 => [float; 2]); 55 | impl_vec_from_cgmath!( vec3 : Vector3 => [float; 3]); 56 | impl_vec_from_cgmath!( vec4 : Vector4 => [float; 4]); 57 | impl_vec_from_cgmath!(dvec2 : Vector2 => [double; 2]); 58 | impl_vec_from_cgmath!(dvec3 : Vector3 => [double; 3]); 59 | impl_vec_from_cgmath!(dvec4 : Vector4 => [double; 4]); 60 | 61 | impl_mat_from_cgmath!(imat2 : Matrix2 => [int; 2]); 62 | impl_mat_from_cgmath!(imat3 : Matrix3 => [int; 3]); 63 | impl_mat_from_cgmath!(imat4 : Matrix4 => [int; 4]); 64 | impl_mat_from_cgmath!(umat2 : Matrix2 => [uint; 2]); 65 | impl_mat_from_cgmath!(umat3 : Matrix3 => [uint; 3]); 66 | impl_mat_from_cgmath!(umat4 : Matrix4 => [uint; 4]); 67 | impl_mat_from_cgmath!( mat2 : Matrix2 => [float; 2]); 68 | impl_mat_from_cgmath!( mat3 : Matrix3 => [float; 3]); 69 | impl_mat_from_cgmath!( mat4 : Matrix4 => [float; 4]); 70 | impl_mat_from_cgmath!(dmat2 : Matrix2 => [double; 2]); 71 | impl_mat_from_cgmath!(dmat3 : Matrix3 => [double; 3]); 72 | impl_mat_from_cgmath!(dmat4 : Matrix4 => [double; 4]); 73 | 74 | #[test] 75 | fn test_cgmath() { 76 | use crate::uniform::Std140; 77 | use cgmath::SquareMatrix; 78 | 79 | let v3: vec3 = [1.0f32, 2.0, 3.0].into(); 80 | let gv3_to_v3: vec3 = Vector3::new(1.0f32, 2.0, 3.0).into(); 81 | let gv3 = Vector3::new(1.0f32, 2.0, 3.0); 82 | assert_eq!(v3.std140().as_raw(), gv3.std140().as_raw()); 83 | assert_eq!(gv3.std140().as_raw(), gv3_to_v3.std140().as_raw()); 84 | 85 | let m3: mat3 = [[1.0f32, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]].into(); 86 | let gm3_to_m3: mat3 = Matrix3::::identity().into(); 87 | let gm3 = Matrix3::::identity(); 88 | assert_eq!(m3.std140(), gm3.std140()); 89 | assert_eq!(gm3.std140(), gm3_to_m3.std140()); 90 | } 91 | -------------------------------------------------------------------------------- /src/glam.rs: -------------------------------------------------------------------------------- 1 | use crate::mat::{dmat2, dmat3, dmat4, mat2, mat3, mat4}; 2 | use crate::scalar::{double, float, int, uint}; 3 | use crate::uniform::Uniform; 4 | use crate::vec::{dvec2, dvec3, dvec4, ivec2, ivec3, ivec4, uvec2, uvec3, uvec4, vec2, vec3, vec4}; 5 | use glam::{ 6 | DMat2, DMat3, DMat4, DVec2, DVec3, DVec4, IVec2, IVec3, IVec4, Mat2, Mat3, Mat4, UVec2, UVec3, 7 | UVec4, Vec2, Vec3, Vec4, 8 | }; 9 | 10 | macro_rules! impl_vec_from_glam { 11 | ($vec:ident : $glam:ident => [$type:ty; $size:tt]) => { 12 | impl From<$glam> for $vec { 13 | fn from(value: $glam) -> Self { 14 | let array: [$type; $size] = value.into(); 15 | array.into() 16 | } 17 | } 18 | 19 | impl Uniform for $glam { 20 | type Align = <$vec as Uniform>::Align; 21 | type Std140 = <$vec as Uniform>::Std140; 22 | 23 | fn std140(&self) -> Self::Std140 { 24 | Self::Std140::from(*self) 25 | } 26 | } 27 | }; 28 | } 29 | 30 | macro_rules! impl_mat_from_glam { 31 | ($mat:ident : $glam:ident => [$type:ty; $size:tt]) => { 32 | impl From<$glam> for $mat { 33 | fn from(value: $glam) -> Self { 34 | $mat::from(value.to_cols_array_2d()) 35 | } 36 | } 37 | 38 | impl Uniform for $glam { 39 | type Align = <$mat as Uniform>::Align; 40 | type Std140 = <$mat as Uniform>::Std140; 41 | 42 | fn std140(&self) -> Self::Std140 { 43 | Self::Std140::from(self.to_cols_array_2d()) 44 | } 45 | } 46 | }; 47 | } 48 | 49 | impl_vec_from_glam!(ivec2 : IVec2 => [int; 2]); 50 | impl_vec_from_glam!(ivec3 : IVec3 => [int; 3]); 51 | impl_vec_from_glam!(ivec4 : IVec4 => [int; 4]); 52 | impl_vec_from_glam!(uvec2 : UVec2 => [uint; 2]); 53 | impl_vec_from_glam!(uvec3 : UVec3 => [uint; 3]); 54 | impl_vec_from_glam!(uvec4 : UVec4 => [uint; 4]); 55 | impl_vec_from_glam!( vec2 : Vec2 => [float; 2]); 56 | impl_vec_from_glam!( vec3 : Vec3 => [float; 3]); 57 | impl_vec_from_glam!( vec4 : Vec4 => [float; 4]); 58 | impl_vec_from_glam!(dvec2 : DVec2 => [double; 2]); 59 | impl_vec_from_glam!(dvec3 : DVec3 => [double; 3]); 60 | impl_vec_from_glam!(dvec4 : DVec4 => [double; 4]); 61 | 62 | impl_mat_from_glam!( mat2 : Mat2 => [float; 2]); 63 | impl_mat_from_glam!( mat3 : Mat3 => [float; 3]); 64 | impl_mat_from_glam!( mat4 : Mat4 => [float; 4]); 65 | impl_mat_from_glam!(dmat2 : DMat2 => [double; 2]); 66 | impl_mat_from_glam!(dmat3 : DMat3 => [double; 3]); 67 | impl_mat_from_glam!(dmat4 : DMat4 => [double; 4]); 68 | 69 | #[test] 70 | pub fn test_glam() { 71 | use crate::uniform::Std140; 72 | 73 | let v3: vec3 = [1.0, 2.0, 3.0].into(); 74 | let gv3_to_v3: vec3 = Vec3::new(1.0, 2.0, 3.0).into(); 75 | let gv3 = Vec3::new(1.0, 2.0, 3.0); 76 | assert_eq!(v3.std140(), gv3.std140()); 77 | assert_eq!(gv3.std140(), gv3_to_v3.std140()); 78 | 79 | let m3: mat3 = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]].into(); 80 | let gm3_to_m3: mat3 = Mat3::IDENTITY.into(); 81 | let gm3 = Mat3::IDENTITY; 82 | assert_eq!(m3.std140(), gm3.std140()); 83 | assert_eq!(gm3.std140(), gm3_to_m3.std140()); 84 | } 85 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | //! 3 | //! This crates provides data types to build structures ready to upload into UBO. 4 | //! Data layout will match one for uniform blocks declared with `layout(std140)`. 5 | //! See [specs](https://www.khronos.org/registry/OpenGL/specs/gl/glspec45.core.pdf#page=159) for alignment rules. 6 | //! 7 | //! # Examples 8 | //! 9 | //! ```rust 10 | //! # use glsl_layout::{Uniform, int, mat4x4, vec3, float}; 11 | //! 12 | //! #[derive(Debug, Default, Clone, Copy, Uniform)] 13 | //! struct Foo { 14 | //! x: int, 15 | //! y: vec3, 16 | //! z: float, 17 | //! w: mat4x4, 18 | //! a: [f32; 3], 19 | //! b: f32, 20 | //! } 21 | //! 22 | //! type UFoo = ::Std140; 23 | //! 24 | //! assert_eq!( 25 | //! std::mem::offset_of!(UFoo, y), 26 | //! round_up_to(size_of::(), 16), // `vec3` has alignment of size `vec4` 27 | //! "Offset of field `y` must be equal of size of `x` rounded up to the alignment", 28 | //! ); 29 | //! 30 | //! assert_eq!( 31 | //! std::mem::offset_of!(UFoo, z), 32 | //! round_up_to(std::mem::offset_of!(UFoo, y) + size_of::(), 4), 33 | //! "Field `z` must follow `y`. `y` should not have padding at the end", 34 | //! ); 35 | //! 36 | //! assert_eq!( 37 | //! std::mem::offset_of!(UFoo, b), 38 | //! std::mem::offset_of!(UFoo, a) + size_of::<[[f32; 4]; 3]>(), 39 | //! "Field `b` must follow `a`. But `a` has padding at the end.", 40 | //! ); 41 | //! 42 | //! let foo_uniform = Foo { 43 | //! x: 2, 44 | //! y: [0.0; 3].into(), 45 | //! z: 0.0, 46 | //! w: [[0.0; 4]; 4].into(), 47 | //! a: [0.0; 3].into(), 48 | //! b: 0.0, 49 | //! }.std140(); 50 | //! 51 | //! # fn round_up_to(offset: usize, align: usize) -> usize { 52 | //! # if offset % align == 0 { 53 | //! # offset 54 | //! # } else { 55 | //! # (((offset - 1) / align) + 1) * align 56 | //! # } 57 | //! # } 58 | //! ``` 59 | //! 60 | 61 | #[doc(hidden)] 62 | pub mod align; 63 | mod scalar; 64 | mod vec; 65 | 66 | #[macro_use] 67 | mod array; 68 | mod mat; 69 | mod uniform; 70 | 71 | #[cfg(feature = "cgmath")] 72 | mod cgmath; 73 | 74 | #[cfg(feature = "nalgebra")] 75 | mod nalgebra; 76 | 77 | #[cfg(feature = "glam")] 78 | mod glam; 79 | 80 | pub use array::*; 81 | pub use mat::*; 82 | pub use scalar::*; 83 | pub use uniform::*; 84 | pub use vec::*; 85 | 86 | #[allow(unused_imports)] 87 | #[macro_use] 88 | extern crate glsl_layout_derive; 89 | #[doc(hidden)] 90 | pub use glsl_layout_derive::*; 91 | 92 | #[test] 93 | fn test_derive() { 94 | use crate as glsl_layout; 95 | #[derive(Copy, Clone, Uniform)] 96 | struct Test { 97 | a: [u32; 3], 98 | b: vec2, 99 | c: dmat4x3, 100 | } 101 | } 102 | 103 | #[test] 104 | fn test_array() { 105 | use crate as glsl_layout; 106 | #[derive(Copy, Clone, Uniform)] 107 | struct Test { 108 | a: [u32; 3], 109 | b: vec2, 110 | c: [dmat4x3; 32], 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/mat.rs: -------------------------------------------------------------------------------- 1 | use crate::vec::{ 2 | bvec2, bvec3, bvec4, dvec2, dvec3, dvec4, ivec2, ivec3, ivec4, uvec2, uvec3, uvec4, vec2, vec3, 3 | vec4, 4 | }; 5 | 6 | use crate::array::{Array, Element}; 7 | 8 | /// Matrix of 2 x 2 boolean values. 9 | pub type bmat2x2 = Array; 2]>; 10 | 11 | /// Matrix of 2 x 3 boolean values. 12 | pub type bmat2x3 = Array; 2]>; 13 | 14 | /// Matrix of 2 x 4 boolean values. 15 | pub type bmat2x4 = Array; 2]>; 16 | 17 | /// Matrix of 3 x 2 boolean values. 18 | pub type bmat3x2 = Array; 3]>; 19 | 20 | /// Matrix of 3 x 3 boolean values. 21 | pub type bmat3x3 = Array; 3]>; 22 | 23 | /// Matrix of 3 x 4 boolean values. 24 | pub type bmat3x4 = Array; 3]>; 25 | 26 | /// Matrix of 4 x 2 boolean values. 27 | pub type bmat4x2 = Array; 4]>; 28 | 29 | /// Matrix of 4 x 3 boolean values. 30 | pub type bmat4x3 = Array; 4]>; 31 | 32 | /// Matrix of 4 x 4 boolean values. 33 | pub type bmat4x4 = Array; 4]>; 34 | 35 | /// Matrix of 2 x 2 boolean values. 36 | pub type bmat2 = bmat2x2; 37 | 38 | /// Matrix of 3 x 3 boolean values. 39 | pub type bmat3 = bmat3x3; 40 | 41 | /// Matrix of 4 x 4 boolean values. 42 | pub type bmat4 = bmat4x4; 43 | 44 | /// Matrix of 2 x 2 signed integer values. 45 | pub type imat2x2 = Array; 2]>; 46 | 47 | /// Matrix of 2 x 3 signed integer values. 48 | pub type imat2x3 = Array; 2]>; 49 | 50 | /// Matrix of 2 x 4 signed integer values. 51 | pub type imat2x4 = Array; 2]>; 52 | 53 | /// Matrix of 3 x 2 signed integer values. 54 | pub type imat3x2 = Array; 3]>; 55 | 56 | /// Matrix of 3 x 3 signed integer values. 57 | pub type imat3x3 = Array; 3]>; 58 | 59 | /// Matrix of 3 x 4 signed integer values. 60 | pub type imat3x4 = Array; 3]>; 61 | 62 | /// Matrix of 4 x 2 signed integer values. 63 | pub type imat4x2 = Array; 4]>; 64 | 65 | /// Matrix of 4 x 3 signed integer values. 66 | pub type imat4x3 = Array; 4]>; 67 | 68 | /// Matrix of 4 x 4 signed integer values. 69 | pub type imat4x4 = Array; 4]>; 70 | 71 | /// Matrix of 2 x 2 signed integer values. 72 | pub type imat2 = imat2x2; 73 | 74 | /// Matrix of 3 x 3 signed integer values. 75 | pub type imat3 = imat3x3; 76 | 77 | /// Matrix of 4 x 4 signed integer values. 78 | pub type imat4 = imat4x4; 79 | 80 | /// Matrix of 2 x 2 unsiged integer values. 81 | pub type umat2x2 = Array; 2]>; 82 | 83 | /// Matrix of 2 x 3 unsiged integer values. 84 | pub type umat2x3 = Array; 2]>; 85 | 86 | /// Matrix of 2 x 4 unsiged integer values. 87 | pub type umat2x4 = Array; 2]>; 88 | 89 | /// Matrix of 3 x 2 unsiged integer values. 90 | pub type umat3x2 = Array; 3]>; 91 | 92 | /// Matrix of 3 x 3 unsiged integer values. 93 | pub type umat3x3 = Array; 3]>; 94 | 95 | /// Matrix of 3 x 4 unsiged integer values. 96 | pub type umat3x4 = Array; 3]>; 97 | 98 | /// Matrix of 4 x 2 unsiged integer values. 99 | pub type umat4x2 = Array; 4]>; 100 | 101 | /// Matrix of 4 x 3 unsiged integer values. 102 | pub type umat4x3 = Array; 4]>; 103 | 104 | /// Matrix of 4 x 4 unsiged integer values. 105 | pub type umat4x4 = Array; 4]>; 106 | 107 | /// Matrix of 2 x 2 unsiged integer values. 108 | pub type umat2 = umat2x2; 109 | 110 | /// Matrix of 3 x 3 unsiged integer values. 111 | pub type umat3 = umat3x3; 112 | 113 | /// Matrix of 4 x 4 unsiged integer values. 114 | pub type umat4 = umat4x4; 115 | 116 | /// Matrix of 2 x 2 floating-point values. 117 | pub type mat2x2 = Array; 2]>; 118 | 119 | /// Matrix of 2 x 3 floating-point values. 120 | pub type mat2x3 = Array; 2]>; 121 | 122 | /// Matrix of 2 x 4 floating-point values. 123 | pub type mat2x4 = Array; 2]>; 124 | 125 | /// Matrix of 3 x 2 floating-point values. 126 | pub type mat3x2 = Array; 3]>; 127 | 128 | /// Matrix of 3 x 3 floating-point values. 129 | pub type mat3x3 = Array; 3]>; 130 | 131 | /// Matrix of 3 x 4 floating-point values. 132 | pub type mat3x4 = Array; 3]>; 133 | 134 | /// Matrix of 4 x 2 floating-point values. 135 | pub type mat4x2 = Array; 4]>; 136 | 137 | /// Matrix of 4 x 3 floating-point values. 138 | pub type mat4x3 = Array; 4]>; 139 | 140 | /// Matrix of 4 x 4 floating-point values. 141 | pub type mat4x4 = Array; 4]>; 142 | 143 | /// Matrix of 2 x 2 floating-point values. 144 | pub type mat2 = mat2x2; 145 | 146 | /// Matrix of 3 x 3 floating-point values. 147 | pub type mat3 = mat3x3; 148 | 149 | /// Matrix of 4 x 4 floating-point values. 150 | pub type mat4 = mat4x4; 151 | 152 | /// Matrix of 2 x 2 double-precision floating-point values. 153 | pub type dmat2x2 = Array; 2]>; 154 | 155 | /// Matrix of 2 x 3 double-precision floating-point values. 156 | pub type dmat2x3 = Array; 2]>; 157 | 158 | /// Matrix of 2 x 4 double-precision floating-point values. 159 | pub type dmat2x4 = Array; 2]>; 160 | 161 | /// Matrix of 3 x 2 double-precision floating-point values. 162 | pub type dmat3x2 = Array; 3]>; 163 | 164 | /// Matrix of 3 x 3 double-precision floating-point values. 165 | pub type dmat3x3 = Array; 3]>; 166 | 167 | /// Matrix of 3 x 4 double-precision floating-point values. 168 | pub type dmat3x4 = Array; 3]>; 169 | 170 | /// Matrix of 4 x 2 double-precision floating-point values. 171 | pub type dmat4x2 = Array; 4]>; 172 | 173 | /// Matrix of 4 x 3 double-precision floating-point values. 174 | pub type dmat4x3 = Array; 4]>; 175 | 176 | /// Matrix of 4 x 4 double-precision floating-point values. 177 | pub type dmat4x4 = Array; 4]>; 178 | 179 | /// Matrix of 2 x 2 double-precision floating-point values. 180 | pub type dmat2 = dmat2x2; 181 | 182 | /// Matrix of 3 x 3 double-precision floating-point values. 183 | pub type dmat3 = dmat3x3; 184 | 185 | /// Matrix of 4 x 4 double-precision floating-point values. 186 | pub type dmat4 = dmat4x4; 187 | -------------------------------------------------------------------------------- /src/nalgebra.rs: -------------------------------------------------------------------------------- 1 | use crate::mat::{dmat2, dmat3, dmat4, imat2, imat3, imat4, mat2, mat3, mat4, umat2, umat3, umat4}; 2 | use crate::scalar::{double, float, int, uint}; 3 | use crate::uniform::Uniform; 4 | use crate::vec::{dvec2, dvec3, dvec4, ivec2, ivec3, ivec4, uvec2, uvec3, uvec4, vec2, vec3, vec4}; 5 | use nalgebra::{Matrix2, Matrix3, Matrix4, Vector2, Vector3, Vector4}; 6 | 7 | macro_rules! impl_vec_from_nalgebra { 8 | ($vec:ident : $nalgebra:ident => [$type:ty; $size:tt]) => { 9 | impl From<$nalgebra<$type>> for $vec { 10 | fn from(value: $nalgebra<$type>) -> Self { 11 | let array: [$type; $size] = value.into(); 12 | array.into() 13 | } 14 | } 15 | 16 | impl Uniform for $nalgebra<$type> { 17 | type Align = <$vec as Uniform>::Align; 18 | type Std140 = <$vec as Uniform>::Std140; 19 | 20 | fn std140(&self) -> Self::Std140 { 21 | Self::Std140::from(*self) 22 | } 23 | } 24 | }; 25 | } 26 | 27 | macro_rules! impl_mat_from_nalgebra { 28 | ($mat:ident : $nalgebra:ident => [$type:ty; $size:tt]) => { 29 | impl From<$nalgebra<$type>> for $mat { 30 | fn from(value: $nalgebra<$type>) -> Self { 31 | let array: [[$type; $size]; $size] = value.into(); 32 | array.into() 33 | } 34 | } 35 | 36 | impl Uniform for $nalgebra<$type> { 37 | type Align = <$mat as Uniform>::Align; 38 | type Std140 = <$mat as Uniform>::Std140; 39 | 40 | fn std140(&self) -> Self::Std140 { 41 | let array: [[$type; $size]; $size] = (*self).into(); 42 | Self::Std140::from(array) 43 | } 44 | } 45 | }; 46 | } 47 | 48 | impl_vec_from_nalgebra!(ivec2 : Vector2 => [int; 2]); 49 | impl_vec_from_nalgebra!(ivec3 : Vector3 => [int; 3]); 50 | impl_vec_from_nalgebra!(ivec4 : Vector4 => [int; 4]); 51 | impl_vec_from_nalgebra!(uvec2 : Vector2 => [uint; 2]); 52 | impl_vec_from_nalgebra!(uvec3 : Vector3 => [uint; 3]); 53 | impl_vec_from_nalgebra!(uvec4 : Vector4 => [uint; 4]); 54 | impl_vec_from_nalgebra!( vec2 : Vector2 => [float; 2]); 55 | impl_vec_from_nalgebra!( vec3 : Vector3 => [float; 3]); 56 | impl_vec_from_nalgebra!( vec4 : Vector4 => [float; 4]); 57 | impl_vec_from_nalgebra!(dvec2 : Vector2 => [double; 2]); 58 | impl_vec_from_nalgebra!(dvec3 : Vector3 => [double; 3]); 59 | impl_vec_from_nalgebra!(dvec4 : Vector4 => [double; 4]); 60 | 61 | impl_mat_from_nalgebra!(imat2 : Matrix2 => [int; 2]); 62 | impl_mat_from_nalgebra!(imat3 : Matrix3 => [int; 3]); 63 | impl_mat_from_nalgebra!(imat4 : Matrix4 => [int; 4]); 64 | impl_mat_from_nalgebra!(umat2 : Matrix2 => [uint; 2]); 65 | impl_mat_from_nalgebra!(umat3 : Matrix3 => [uint; 3]); 66 | impl_mat_from_nalgebra!(umat4 : Matrix4 => [uint; 4]); 67 | impl_mat_from_nalgebra!( mat2 : Matrix2 => [float; 2]); 68 | impl_mat_from_nalgebra!( mat3 : Matrix3 => [float; 3]); 69 | impl_mat_from_nalgebra!( mat4 : Matrix4 => [float; 4]); 70 | impl_mat_from_nalgebra!(dmat2 : Matrix2 => [double; 2]); 71 | impl_mat_from_nalgebra!(dmat3 : Matrix3 => [double; 3]); 72 | impl_mat_from_nalgebra!(dmat4 : Matrix4 => [double; 4]); 73 | 74 | #[test] 75 | fn test_nalgebra() { 76 | use crate::uniform::Std140; 77 | 78 | let v3: vec3 = [1.0f32, 2.0, 3.0].into(); 79 | let gv3_to_v3: vec3 = Vector3::new(1.0f32, 2.0, 3.0).into(); 80 | let gv3 = Vector3::new(1.0f32, 2.0, 3.0); 81 | assert_eq!(v3.std140(), gv3.std140()); 82 | assert_eq!(gv3.std140(), gv3_to_v3.std140()); 83 | 84 | let m3: mat3 = [[1.0f32, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]].into(); 85 | let gm3_to_m3: mat3 = Matrix3::::identity().into(); 86 | let gm3 = Matrix3::::identity(); 87 | assert_eq!(m3.std140(), gm3.std140()); 88 | assert_eq!(gm3.std140(), gm3_to_m3.std140()); 89 | } 90 | -------------------------------------------------------------------------------- /src/scalar.rs: -------------------------------------------------------------------------------- 1 | use crate::align::{Align4, Align8}; 2 | use crate::uniform::{Std140, Uniform}; 3 | 4 | macro_rules! impl_scalar { 5 | ($type:ty : $align:tt) => { 6 | unsafe impl Std140 for $type {} 7 | 8 | impl Uniform for $type { 9 | type Align = $align; 10 | type Std140 = $type; 11 | 12 | fn std140(&self) -> $type { 13 | *self 14 | } 15 | } 16 | }; 17 | } 18 | 19 | /// Boolean value. 20 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 21 | pub struct boolean(u32); 22 | impl_scalar!(boolean: Align4); 23 | 24 | impl boolean { 25 | /// Create `boolean` from `bool`. 26 | pub fn new(value: bool) -> Self { 27 | value.into() 28 | } 29 | } 30 | 31 | impl From for boolean { 32 | fn from(value: bool) -> Self { 33 | boolean(value as u32) 34 | } 35 | } 36 | 37 | impl From for bool { 38 | fn from(value: boolean) -> Self { 39 | value.0 != 0 40 | } 41 | } 42 | 43 | /// Signed integer value. 44 | pub type int = i32; 45 | impl_scalar!(int: Align4); 46 | 47 | /// Unsigned integer value. 48 | pub type uint = u32; 49 | impl_scalar!(uint: Align4); 50 | 51 | /// floating-point value. 52 | pub type float = f32; 53 | impl_scalar!(float: Align4); 54 | 55 | /// Double-precision floating-point value. 56 | pub type double = f64; 57 | impl_scalar!(double: Align8); 58 | -------------------------------------------------------------------------------- /src/uniform.rs: -------------------------------------------------------------------------------- 1 | /// Special marker trait implemented only for `std140` types. 2 | /// 3 | /// # Safety 4 | /// The type must not have any padding bytes 5 | pub unsafe trait Std140: Sized + Uniform { 6 | /// Convert to bytes-slice. 7 | fn as_raw(&self) -> &[u8] { 8 | use std::{mem::size_of, slice::from_raw_parts}; 9 | unsafe { from_raw_parts(self as *const Self as *const u8, size_of::()) } 10 | } 11 | } 12 | 13 | /// Structure to transform data from rust's structure to the raw data ready to upload to UBO. 14 | /// Users should prefer to use `derive(Uniform)` instead of implementing this manually. 15 | pub trait Uniform: Copy { 16 | /// ZST that enforces alignment required for this type. 17 | type Align: Copy + Default; 18 | 19 | /// Type that contain same data with memory layout matching glsl's `layout(std140)`. 20 | type Std140: Std140; 21 | 22 | /// Get aligned data from structure. 23 | fn std140(&self) -> Self::Std140; 24 | } 25 | -------------------------------------------------------------------------------- /src/vec.rs: -------------------------------------------------------------------------------- 1 | use crate::align::{Align16, Align32, Align8}; 2 | use crate::array::MapArray; 3 | use crate::scalar::{boolean, double, float, int, uint}; 4 | use crate::uniform::{Std140, Uniform}; 5 | 6 | macro_rules! implement_vec { 7 | ($vec:ident => [$type:ty; $size:tt]: $align:tt) => { 8 | impl From<[T; $size]> for $vec 9 | where 10 | T: Into<$type>, 11 | { 12 | fn from(values: [T; $size]) -> Self { 13 | $vec(MapArray::map_array(values, T::into)) 14 | } 15 | } 16 | 17 | impl AsRef<[$type; $size]> for $vec { 18 | fn as_ref(&self) -> &[$type; $size] { 19 | &self.0 20 | } 21 | } 22 | 23 | impl AsMut<[$type; $size]> for $vec { 24 | fn as_mut(&mut self) -> &mut [$type; $size] { 25 | &mut self.0 26 | } 27 | } 28 | 29 | impl AsRef<[$type]> for $vec { 30 | fn as_ref(&self) -> &[$type] { 31 | &self.0 32 | } 33 | } 34 | 35 | impl AsMut<[$type]> for $vec { 36 | fn as_mut(&mut self) -> &mut [$type] { 37 | &mut self.0 38 | } 39 | } 40 | 41 | unsafe impl Std140 for $vec {} 42 | 43 | impl Uniform for $vec { 44 | type Align = $align; 45 | type Std140 = $vec; 46 | 47 | fn std140(&self) -> $vec { 48 | *self 49 | } 50 | } 51 | }; 52 | } 53 | 54 | /// Vector of 2 `boolean` values. 55 | /// `foo: bvec2` is equivalent to glsl's `bvec2 foo;` 56 | /// 57 | /// # Examples 58 | /// 59 | /// ```rust 60 | /// # #[macro_use] extern crate glsl_layout; 61 | /// # use glsl_layout::{boolean, bvec2}; 62 | /// # fn main() { 63 | /// let x: bvec2 = [boolean::from(true); 2].into(); 64 | /// # } 65 | /// ``` 66 | /// 67 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 68 | pub struct bvec2([boolean; 2]); 69 | implement_vec!(bvec2 => [boolean; 2] : Align8); 70 | 71 | /// Vector of 3 `boolean` values. 72 | /// `foo: bvec3` is equivalent to glsl's `bvec3 foo;` 73 | /// 74 | /// # Examples 75 | /// 76 | /// ```rust 77 | /// # #[macro_use] extern crate glsl_layout; 78 | /// # use glsl_layout::{boolean, bvec3}; 79 | /// # fn main() { 80 | /// let x: bvec3 = [boolean::from(true); 3].into(); 81 | /// # } 82 | /// ``` 83 | /// 84 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 85 | pub struct bvec3([boolean; 3]); 86 | implement_vec!(bvec3 => [boolean; 3] : Align16); 87 | 88 | /// Vector of 4 `boolean` values. 89 | /// `foo: bvec4` is equivalent to glsl's `bvec4 foo;` 90 | /// 91 | /// # Examples 92 | /// 93 | /// ```rust 94 | /// # #[macro_use] extern crate glsl_layout; 95 | /// # use glsl_layout::{boolean, bvec4}; 96 | /// # fn main() { 97 | /// let x: bvec4 = [boolean::from(true); 4].into(); 98 | /// # } 99 | /// ``` 100 | /// 101 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 102 | pub struct bvec4([boolean; 4]); 103 | implement_vec!(bvec4 => [boolean; 4] : Align16); 104 | 105 | /// Vector of 2 `int` values. 106 | /// `foo: ivec2` is equivalent to glsl's `ivec2 foo;` 107 | /// 108 | /// # Examples 109 | /// 110 | /// ```rust 111 | /// # #[macro_use] extern crate glsl_layout; 112 | /// # use glsl_layout::ivec2; 113 | /// # fn main() { 114 | /// let x: ivec2 = [1i32; 2].into(); 115 | /// # } 116 | /// ``` 117 | /// 118 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 119 | pub struct ivec2([int; 2]); 120 | implement_vec!(ivec2 => [int; 2] : Align8); 121 | 122 | /// Vector of 3 `int` values. 123 | /// `foo: ivec3` is equivalent to glsl's `ivec3 foo;` 124 | /// 125 | /// # Examples 126 | /// 127 | /// ```rust 128 | /// # #[macro_use] extern crate glsl_layout; 129 | /// # use glsl_layout::ivec3; 130 | /// # fn main() { 131 | /// let x: ivec3 = [1i32; 3].into(); 132 | /// # } 133 | /// ``` 134 | /// 135 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 136 | pub struct ivec3([int; 3]); 137 | implement_vec!(ivec3 => [int; 3] : Align16); 138 | 139 | /// Vector of 4 `int` values. 140 | /// `foo: ivec4` is equivalent to glsl's `ivec4 foo;` 141 | /// 142 | /// # Examples 143 | /// 144 | /// ```rust 145 | /// # #[macro_use] extern crate glsl_layout; 146 | /// # use glsl_layout::ivec4; 147 | /// # fn main() { 148 | /// let x: ivec4 = [1i32; 4].into(); 149 | /// # } 150 | /// ``` 151 | /// 152 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 153 | pub struct ivec4([int; 4]); 154 | implement_vec!(ivec4 => [int; 4] : Align16); 155 | 156 | /// Vector of 2 `uint` values. 157 | /// `foo: uvec2` is equivalent to glsl's `uvec2 foo;` 158 | /// 159 | /// # Examples 160 | /// 161 | /// ```rust 162 | /// # #[macro_use] extern crate glsl_layout; 163 | /// # use glsl_layout::uvec2; 164 | /// # fn main() { 165 | /// let x: uvec2 = [1u32; 2].into(); 166 | /// # } 167 | /// ``` 168 | /// 169 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 170 | pub struct uvec2([uint; 2]); 171 | implement_vec!(uvec2 => [uint; 2] : Align8); 172 | 173 | /// Vector of 3 `uint` values. 174 | /// `foo: uvec3` is equivalent to glsl's `uvec3 foo;` 175 | /// 176 | /// # Examples 177 | /// 178 | /// ```rust 179 | /// # #[macro_use] extern crate glsl_layout; 180 | /// # use glsl_layout::uvec3; 181 | /// # fn main() { 182 | /// let x: uvec3 = [1u32; 3].into(); 183 | /// # } 184 | /// ``` 185 | /// 186 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 187 | pub struct uvec3([uint; 3]); 188 | implement_vec!(uvec3 => [uint; 3] : Align16); 189 | 190 | /// Vector of 4 `uint` values. 191 | /// `foo: uvec4` is equivalent to glsl's `uvec4 foo;` 192 | /// 193 | /// # Examples 194 | /// 195 | /// ```rust 196 | /// # #[macro_use] extern crate glsl_layout; 197 | /// # use glsl_layout::uvec4; 198 | /// # fn main() { 199 | /// let x: uvec4 = [1u32; 4].into(); 200 | /// # } 201 | /// ``` 202 | /// 203 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)] 204 | pub struct uvec4([uint; 4]); 205 | implement_vec!(uvec4 => [uint; 4] : Align16); 206 | 207 | /// Vector of 2 `float` values. 208 | /// `foo: vec2` is equivalent to glsl's `vec2 foo;` 209 | /// 210 | /// # Examples 211 | /// 212 | /// ```rust 213 | /// # #[macro_use] extern crate glsl_layout; 214 | /// # use glsl_layout::vec2; 215 | /// # fn main() { 216 | /// let x: vec2 = [1f32; 2].into(); 217 | /// # } 218 | /// ``` 219 | /// 220 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq)] 221 | pub struct vec2([float; 2]); 222 | implement_vec!(vec2 => [float; 2] : Align8); 223 | 224 | /// Vector of 3 `float` values. 225 | /// `foo: vec3` is equivalent to glsl's `vec3 foo;` 226 | /// 227 | /// # Examples 228 | /// 229 | /// ```rust 230 | /// # #[macro_use] extern crate glsl_layout; 231 | /// # use glsl_layout::vec3; 232 | /// # fn main() { 233 | /// let x: vec3 = [1f32; 3].into(); 234 | /// # } 235 | /// ``` 236 | /// 237 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq)] 238 | pub struct vec3([float; 3]); 239 | implement_vec!(vec3 => [float; 3] : Align16); 240 | 241 | /// Vector of 4 `float` values. 242 | /// `foo: vec4` is equivalent to glsl's `vec4 foo;` 243 | /// 244 | /// # Examples 245 | /// 246 | /// ```rust 247 | /// # #[macro_use] extern crate glsl_layout; 248 | /// # use glsl_layout::vec4; 249 | /// # fn main() { 250 | /// let x: vec4 = [1f32; 4].into(); 251 | /// # } 252 | /// ``` 253 | /// 254 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq)] 255 | pub struct vec4([float; 4]); 256 | implement_vec!(vec4 => [float; 4] : Align16); 257 | 258 | /// Vector of 2 `double` value. 259 | /// `foo: dvec2` is equivalent to glsl's `dvec2 foo;` 260 | /// 261 | /// # Examples 262 | /// 263 | /// ```rust 264 | /// # #[macro_use] extern crate glsl_layout; 265 | /// # use glsl_layout::dvec2; 266 | /// # fn main() { 267 | /// let x: dvec2 = [1f32; 2].into(); 268 | /// # } 269 | /// ``` 270 | /// 271 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq)] 272 | pub struct dvec2([double; 2]); 273 | implement_vec!(dvec2 => [double; 2] : Align16); 274 | 275 | /// Vector of 3 `double` value. 276 | /// `foo: dvec3` is equivalent to glsl's `dvec3 foo;` 277 | /// 278 | /// # Examples 279 | /// 280 | /// ```rust 281 | /// # #[macro_use] extern crate glsl_layout; 282 | /// # use glsl_layout::dvec3; 283 | /// # fn main() { 284 | /// let x: dvec3 = [1f32; 3].into(); 285 | /// # } 286 | /// ``` 287 | /// 288 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq)] 289 | pub struct dvec3([double; 3]); 290 | implement_vec!(dvec3 => [double; 3] : Align32); 291 | 292 | /// Vector of 4 `double` value. 293 | /// `foo: dvec4` is equivalent to glsl's `dvec4 foo;` 294 | /// 295 | /// # Examples 296 | /// 297 | /// ```rust 298 | /// # #[macro_use] extern crate glsl_layout; 299 | /// # use glsl_layout::dvec4; 300 | /// # fn main() { 301 | /// let x: dvec4 = [1f32; 4].into(); 302 | /// # } 303 | /// ``` 304 | /// 305 | #[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq)] 306 | pub struct dvec4([double; 4]); 307 | implement_vec!(dvec4 => [double; 4] : Align32); 308 | --------------------------------------------------------------------------------