-
Notifications
You must be signed in to change notification settings - Fork 250
Implement OpTypeMatrix #738
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
Conversation
I've realized that we can implement this with custom attributes and I think it's better. |
I added
These infer missing parameters from type. |
- #[spirv(matrix(ty, m, n))] Specify all of type, rows, columns. - #[spirv(matrix(ty, m))] Specify all of type, rows. Infer columns. - #[spirv(matrix(ty))] Specify all of type. Infer others. - #[spirv(matrix)] Infer all.
Please only implement |
Make sense! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe tests/ui/spirv-attr/{invalid-target.rs,multiple.rs}
need to be updated.
count: m as u32, | ||
} | ||
.def(span, cx)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't have to (and shouldn't) do this digging into field types for this, and should use the standard type translation tools on the fields instead. Also, this is missing quite a bit of validation (e.g. if fields are different types, or there are no fields - IIRC your code ICEs if there's no fields) - there should be tests for each of the three kinds of error. Something like this should work instead:
IntrinsicType::Matrix => {
let field_types = (0..ty.fields.count())
.map(|i| trans_type_impl(cx, span, ty.field(cx, i), false))
.collect::<Vec<_>>();
if field_types.is_empty() {
cx.tcx
.sess
.err("#[spirv(matrix)] type must have at least one field");
return Err(ErrorReported);
}
let elem_type = field_types[0];
if !field_types.iter().all(|&ty| ty == elem_type) {
cx.tcx
.sess
.err("#[spirv(matrix)] type fields must all be the same type");
return Err(ErrorReported);
}
match cx.lookup_type(elem_type) {
SpirvType::Vector { .. } => (),
ty => {
cx.tcx
.sess
.struct_err("#[spirv(matrix)] type fields must all be vectors")
.note(&format!("field type is {}", ty.debug(elem_type, cx)))
.emit();
return Err(ErrorReported);
}
}
Ok(SpirvType::Matrix {
element: elem_type,
count: field_types.len() as u32,
}
.def(span, cx))
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
I updated the code and change Matrix length validation since OpTypeMatrix
requires a length of at least 2.
https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#OpTypeMatrix
#[spirv(object_to_world)] _object_to_world: Affine3, | ||
#[spirv(world_to_object)] _world_to_object: Affine3, | ||
) { | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this isn't actually testing much due to the majority of it being dead code. (Also, nit, the name Affine3
is a little misleading - it's not an affine transformation - but isn't super important for a test, haha)
I would like to see field accesses/etc. tested as well, I'm nervous about just crossing our fingers and hoping that matricies behave exactly like structs in all ways and no instructions need to be modified to handle matricies specially.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I chose Affine3
because glam::f32::Affine3A
has the same layout https://docs.rs/glam/0.18.0/glam/f32/struct.Affine3A.html (Sry, I don't know about math 😨).
I feel adding more tests for field operations in tests/ui/spirv-attr/*
is not appropriate because it may should contain only about attr tests.
Is it OK? or is there any better place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh! whoops, misread it as 4 Vec4s, not 4 Vec3s, 4 Vec3s definitely is an affine transform, haha, sorry
Yeah, not totally sure about where to put tests, anywhere is probably fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added tests to matrix-type.rs
I think this is enough but are there suggestions for more cases?
Thanks for pointed out. I simply replaced But got the error
|
Looks like compiletest is just straight up broken if output is too long - it injects this into the output and then later tries to parse the output as json, tripping over its own trimmed marker. Feel free to just skip updating |
I can't reproduce the CI failure. |
I'm also unable to reproduce, even with CI's exact version of spirv-tools. hmm. I'll try rerunning tests, I guess? edit: oh, I mucked up getting CI's exact version of spirv-tools, I can reproduce locally now. Assuming linux, download/extract this tarball, put the folder on |
Was able to reproduce locally, the full error was cut off in CI:
the issue seems to be an output ( |
Thank you! |
could you add a |
I don't still understand why
failed but reverted to previous code for now. |
Ah, I think that failure is due to a similar thing as #513, which, might become more pressing to fix once people actually start using matrices. TL;DR matricies take up a handful of binding slots, so incrementing binding slot by 1 per parameter doesn't work (and results in overlapping parameter slots) |
I added failing tests. I added two test files because it seems not able to test #[(spirv(matrix))] for empty struct with others in the same file. Error messages feel unkind because it doesn't show type definition. |
Oh, oof, no, that's why we add tests, haha, I completely screwed up that prototype impl - there is a span in scope (it's passed into |
Ah, but you're right that we probably want to point the error at the struct itself, in which case, this gives you the span for the struct - you might have to re-match on the TyKind::Adt to pull it out again, I forget if there's a helper that makes it easier
|
Thanks, I choose to use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
Woo! 🎉 🎉 🎉 |
Fixes #82.
This PR adds
#[spirv(matrix(ty, m, n))]
attribute. A type with#[spirv(matrix(..))]
is expressed asOpTypeMatrix
in SPIR-V.An example usage is tests/ui/spirv-attr/matrix-type.rs.
WhileOpTypeVector
is implemented by utilizing#[repr(simd)]
, this PR implementsOpTypeMatrix
by introducing the new traitMatrix
because I couldn't find a usable attribute.When convertingTy
to SPIRV type, it usesOpTypeMatrix
if theTy
implementsMatrix
.TODO
OpMatrix
Since many operations in glam's matrices cast self to inner type, we need to add attributes to glam matrices and its inner types.
``
Currently, we can't add the attribute toglam::core::storage::Column*<V>
because we can't know its vector length at definition.We may handle it by adding `#[spirv(matrix(m, param(n)))]` syntax and refer nth generics type (e.g. glam::Vec3) and infer vector length from it...