-
Notifications
You must be signed in to change notification settings - Fork 245
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
Allow constant references (to constant data), when they're valid SPIR-V. #586
Conversation
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.
what the fuck
[OpVariable instruction spec]: Initializer is optional. If Initializer is present, it will be the initial value of the variable’s memory content. Initializer must be an from a constant instruction or a global (module scope) OpVariable instruction.
@@ -214,15 +214,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | |||
let elem_pat = self.memset_const_pattern(&self.lookup_type(element), fill_byte); | |||
self.constant_composite( | |||
ty.clone().def(self.span(), self), | |||
vec![elem_pat; count as usize], | |||
iter::repeat(elem_pat).take(count as usize), |
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.
❤️ ty
// FIXME(eddyb) materialize this at runtime, using | ||
// `OpCompositeConstruct` (transitively, i.e. after | ||
// putting every field through `SpirvValue::def`), | ||
// if we have a `Builder` to do that in. |
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.
yeah gosh, this would be nice, been dreaming about this possibility for ages, haha - seems like with this system, we're actually kind of close to being able to do so
Ok(()) | ||
} | ||
SpirvConst::Undef => { | ||
// FIXME(eddyb) check that the type supports `OpUndef`. |
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.
Just curious, are there any types that cannot be made by OpUndef? Intuitively, there absolutely should be, but I don't think the spec actually mentions anything.
// Bidirectional maps between `SpirvConst` and the ID of the defined global | ||
// (e.g. `OpConstant...`) instruction. | ||
// NOTE(eddyb) both maps have `WithConstLegality` around their keys, which | ||
// allows getting that legality information without additional lookups. |
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.
nit: around their values?
This is trickier than it should reasonably be, because of some SPIR-V limitations.
A constant like
&&123
is valid in SPIR-V and generates something like this (types omitted for brevity):But a constant like
&(&1, &2)
isn't - its SPIR-V would have to be this, which doesn't pass validation:The problem isn't even
%ref_pair
, but%pair
itself:OpConstantComposite
must haveOpConstant...
fields, but not (global, i.e. module-scoped)OpVariable
fields (even if the storage class isPrivate
).This is pretty bizarre IMO, and I'm not 100% convinced it's intentional - it's possible the first case (with the nested
OpVariable
s) was never meant to be legal either.Regardless of whether the rules make sense or not, this PR accounts for them, and you can see in the UI tests some simple examples what is allowed and what isn't (the
==
examples were the original motivation for this PR).I've even tested that adding multiple extraneous references to the color constants in
mouse-shader
still works, but I suspect the loads get constant-folded anyway, so it's not much of a test.