-
Notifications
You must be signed in to change notification settings - Fork 161
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
Alternate Vec3 that's actually 12 bytes #36
Comments
I'm not sure what the best thing to do here - I'm still not totally convinced the performance advantage of the SIMD In any case. I did try and make it easier to deal with unaligned data by providing conversions to and from It would be interesting to see some sample code of hoops you are having to jump through, or are you just avoiding the |
The case that made me write this was implementing GLTF loading, and wanting to use slices/vectors of Vec3 as temporaries before writing to GPU memory. It would obviously work just as well with [f32; 3] but it makes the code nicer to use Vec3 (since I compute bounding volumes and stuff during load, and for that computation I like stuff like Vec3::length and Vec3::min/max instead of open-coding the float operations). Though the easy conversion from/to [f32;3] might look okay I guess. I'm also unconvinced by the benefits of keeping Vec3 in a SIMD register, I think three floats is just fine for most cases. If you have something that takes a ton of CPU time, you can manually use Vec4 instead without too much trouble if that is beneficial. And if it's something really intense you'll want to use intrinsics anyway probably, or move it to the GPU. |
If you try the I have a feature flag Might take a bit of time before I get it done though. |
I'll try it, sure. Yeah there's no rush here, I'm more thinking about the long-term API design. And for that, having vec3 and mat3 non-padded is probably the right thing, or at least the right default. My real goal is really that I simply want all new game library authors in the Rust world to prefer glam over nalgebra's bloat... |
Related to this, in 0.8.6 I added the |
Yes we use these, and they do help, but one of the bigger annoyances with the lack of a 12-byte Vec3 is that we can't use it in structures that need to have the binary layout without padding, such as FFI structures, which we have A LOT of. So I think I would also be be in favor of having an explicit say |
This is definitely still in my radar, I've been mulling it over in the background trying to figure out how to do it without too much code duplication. Worst case I can just copy and paste vec3 and come up with something better later :) I'm definitely leaning towards Vec3 being 12 bytes and adding a new type for SIMD, probably Vec3A16 or something. Moving house this week though so not much will happen for a little while. |
Think that would be the cleanest as well. And no hurry :) |
I hit the same issues mentioned above and I would also prefer 12-byte to be the default 😄 |
I started on this in a branch https://github.com/bitshifter/glam-rs/tree/vec3a16. I'm not quite done but let me know if you have any feedback. |
Just circling back here: I actually now want the current SIMD layout for my project. I just realized GLSL uniform buffer objects force vec3s to be 16 bytes, so the current layout is convenient for memcpy. That being said, I still stand by the idea that 12 bytes should be the default. I'm just hoping 16 bytes is still an option |
@cart I'm definitely keeping the SIMD type. I have something working on the branch I linked above and I'm currently switching a couple of my projects over to use it just to see if the API feels OK. The main thing I am not sure about as usual is naming :) At the moment the regular |
Personally, my ideal math library would be two crates:
In DirectXMath, they use the type XMVECTOR for all vectorized values and XMFLOAT3/XMFLOAT4/XMFLOAT4x4 etc. for non-vectorized. I think providing both vectorized and non-vectorized structs is the right idea and I like the general naming approach they take. In particular, I like the idea of using vector/float in the name to be explicit. Such as Vec3 vs. Float3. Maybe a Float3A for Float3 aligned on a 16-byte boundary. (Which I believe is another DirectXMath naming convention.). Another option would be to post-fix V or F, i.e. Vec3V vs. Vec3F |
@aclysma I do like the idea of doing something similar eventually. Not so much porting DirectXMath, it's a large library from my point of view, but having a low level and high level APIs for glam. A bit like DirectXMath and SimpleMath. It's a bit down my todo list though. I have a couple of concerns that may or may not be unfounded:
One way of avoiding both of the above issues is to use macros for everything. This would reduce readability of the code a bit although the macros themselves would be quite straight forward. I'm already using macros in some places anyway. I would rather use function calls over macros for readability but I suspect I'll run into some issues. None of these things are really major issues, I just want to focus on the high level API first. Edit: I like the |
I think changing the default for Vec3 is going to cause quite a bit of trouble for various crates now as some expect Vec3 to be 16 bytes. It's a bit of an unnecessary breaking change IMO. I think different suffixes is a fine convention, but I'd appreciate keeping Vec3 the SIMD default by aliasing to Vec3A, and adding Vec3F or something as the scalar version. |
I agree with @kabergstrom - I don't have positive feelings about glam::Vec3 doing different things in different crates depending on what version they pull in. I like the idea of separate explicit types (vectorized = Vec3V or Vec3A vs. float = Vec3F) and then aliasing Vec3 so that updating is easy. |
Well this is awkward as I've now published the change in 0.9.0. @kabergstrom are there any specific crates you think this will cause problems for? @aclysma do you think this would be a problem in practice? I would think crates trying to mix different While I realise this is an annoying breaking change for existing users I think a 12 byte I have been pleasantly surprised by the uptake of glam but it is still early in glam's life. I think the time to make a breaking change like this is now. Unfortunately with this particular change there is no easy way to communicate it with people via Rust's deprecation mechanism. There are a few reasons I don't want to get rid of Suffix wise it is possible that I will add support for That's my rational for making this change. Perhaps if more users come out of the woodwork I say this is a bad idea I guess I could be convinced otherwise. Specifically @hrydgard or @repi since they opened this issue in the first place and put it on the Embark issues list. Given all that if there is anything I can do to assist with migration I can try and oblige. For example adding a feature flag that exports [edit] I also wanted to add, I can't think of anything else in glam that will necessitate a breaking change on this scale in the future. Even the |
I do like the new naming, it is IMO easier to understand for new users and a better default, and do think that if one does such a change, now is an excellent time to do it as it is only going to be harder and more people affected later on. Do hope we all can continue to collaborate and figure out best naming and features in this crate and eventually do a 1.0 release (later in the year?). I did a quick check across our internal and public crates and it looked like this change won't break anything for us and just work, but @hrydgard will do a proper upgrade tomorrow and we'll see where we are at. But we are perfectly fine upgrading and fixing up usages after this. Due to the ambiguity of the storage size of the previous |
I think at this point, the most important thing to do is communicate it well so that people know about this change. I agree with you in practice, existing code will work because symver will not drop this change on people without their consent, and mixing the code should fail to compile. But it's something we'll have to all be mindful of when pulling in new crates since this is a major change that won't be very obvious. When I mentioned multiple impls in the same codebase, I meant upstream crates using it internally. Again, it's not a technical/doesn't-work problem but it's just another thing to think about when reading upstream code. (This is off-topic and was something I was thinking about well before this change, mostly spurred by this thread: rust-gamedev/wg#25) One of the reasons I think a two-layered math library could be useful is that the controversy on math libraries is almost completely down to API design (naming and if SIMD should be the "default" or not are great examples :D ) As you say, DirectXMath is huge and as a community we are probably all best off avoiding doing the same work. Given that I don't think everyone will ever agree on every single API decision in a math library, sharing a "sys" level crate would be the next best thing. Especially if we want to move beyond SSE2 for ARM or AVX support. (In fact, I would try to keep such a crate structured as closely as possible to DirectXMath so that we can port across any improvements they make, such as support for new instructions.) |
I've found that when dealing with mesh data files and meshes in memory and similar, you sometimes really want a Vec3 type that's guaranteed to actually be 12 bytes (3*mem::size_of()) in size.
I could of course implement my own Vec3 and have it by the side, but I think this need might be common enough that it might be worth including (since glam's SIMD Vec3 is stuck at 16 bytes, for pretty good reasons).
One idea might want to be to export a RawVec3 type or something that's essentially equivalent to the current non-SIMD fallback, even if SIMD is enabled. What do you think?
The text was updated successfully, but these errors were encountered: