-
Notifications
You must be signed in to change notification settings - Fork 193
Add support for zero-initializing workgroup memory #2111
Conversation
6bc913d
to
9cc3bec
Compare
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.
Not finished reviewing yet, but so far, this LGTM. I'll see if I can finish this before end-of-week.
nitpick(non-blocking): 1k LoC in a single commit is a lot. I do think there's some opportunity for breaking this up, but fortunately, the candidates for splitting commits look easy (which tends to mean that the impact isn't high, thankfully). I'll try to call them out where I can.
question: Isn't this sort of new functionality the sort of thing we'd want a CHANGELOG
entry for? I see that we don't currently have a PR template encouraging this, which might be something I can do a la wgpu
.
note: RE: the Path
warning: this warning has been fixed with 0197246, which you should catch with a rebase. 🙌🏻
@@ -65,6 +65,7 @@ impl Writer { | |||
annotations: vec![], | |||
flags: options.flags, | |||
bounds_check_policies: options.bounds_check_policies, | |||
zero_initialize_workgroup_memory: options.zero_initialize_workgroup_memory, |
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.
thought(non-blocking): I feel like using pattern destructuring for data forwarding would be a really good fit for this sort of logic in Self::new
and Self::reset
. I'm the type that doesn't trust myself without that sort of safety net, tho, so YMMV. 😅
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 don't use destructuring much as I like seeing where the var came from at first glance.
@jimblandy thoughts?
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.
In this particular case I kind of wonder if Writer
shouldn't just store an Options
directly, instead of copying out all of its members. (If someone wants to do this, let's make it a separate PR.)
In the general case, it's true that destructuring requires that every field gets mentioned, and introduces locals that rustc will complain if we don't use—whereas it can't complain about an unread struct field if it's pub
. And I definitely like to take advantage of these static safety nets - I'll often ask people to take out _ => ...
arms from match
statements just so we can be sure that newly variants get consideration at each use.
I think in this case, for Options
, it doesn't pay off, primarily because there's only one spot where the Options
value is consulted, and it's the same spot that all the other fields are used. So pretty much any implementation flow that works at all is going to arrive at the spot that needs attention. In other words, it doesn't seem especially error-prone. This wouldn't be the case for, say, a new TypeInner
variant: those are used all over the place. Or a new BoundsCheckPolicy
- those are consumed in a handful of places scattered around each backend.
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.
If I'm going to talk about things 'paying off', then I should say what the cost is: I think it takes a bit longer to read the destructuring version, there are more variables around that could be mixed with other things, and as Teo said, it's less obvious, when looking at a use, what its origin was.
That is, when I see options.bounds_check_policies
, I know exactly where it came from, but when I see just bounds_check_policies
, it could be an argument, it could have been computed, etc. and I have to guess or go find out.
These are good ideas - could you file an issue for each? |
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 haven't looked at the SPIR-V back end yet, but I do have one change I want to see, so I'll just post what I have now.
I'd also be happy to see a TypeFlags
-based revision, if you want.
Sorry, some of those comments were intended as replies to Erich's questions, but GitHub didn't see it that way so they're kind of out-of-context. |
Most changes seem to come from the test snapshots. Will move the barrier code refactor to a separate commit.
Tbh, I prefer adding the changelog entries when we do a release since I think it results in higher quality changelogs but what could also have the same effect is asking authors to add a changelog entry (same as wgpu) and doing a last pass before a release to make sure the changelog is cohesive. |
835c055
to
e57e951
Compare
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.
This changed the API for backends, so it needs a CHANGELOG.md entry.
Don't all these writes need to be limited to a single invocation? Right now we're writing to all this storage from every invocation, and that's going to be a race and a waste.
@@ -65,6 +65,7 @@ impl Writer { | |||
annotations: vec![], | |||
flags: options.flags, | |||
bounds_check_policies: options.bounds_check_policies, | |||
zero_initialize_workgroup_memory: options.zero_initialize_workgroup_memory, |
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.
In this particular case I kind of wonder if Writer
shouldn't just store an Options
directly, instead of copying out all of its members. (If someone wants to do this, let's make it a separate PR.)
In the general case, it's true that destructuring requires that every field gets mentioned, and introduces locals that rustc will complain if we don't use—whereas it can't complain about an unread struct field if it's pub
. And I definitely like to take advantage of these static safety nets - I'll often ask people to take out _ => ...
arms from match
statements just so we can be sure that newly variants get consideration at each use.
I think in this case, for Options
, it doesn't pay off, primarily because there's only one spot where the Options
value is consulted, and it's the same spot that all the other fields are used. So pretty much any implementation flow that works at all is going to arrive at the spot that needs attention. In other words, it doesn't seem especially error-prone. This wouldn't be the case for, say, a new TypeInner
variant: those are used all over the place. Or a new BoundsCheckPolicy
- those are consumed in a handful of places scattered around each backend.
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 think the only remaining question here is the one I raised above: should we restrict initialization to a single invocation?
e57e951
to
dfae06f
Compare
Yeah, the question is if we want to require updates to the changelog as part of PRs or do it ourselves before a release.
Indeed, pushed a new commit. |
dfae06f
to
5f2f940
Compare
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.
Still need to process the SPIR-V changes, but I did find something in the MSL.
5f2f940
to
3708326
Compare
@jimblandy I addressed the latest comments. |
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.
One problem in the validator changes. I'll look at this again first thing tomorrow morning.
3708326
to
623988c
Compare
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.
Looks good!
src/back/spv/writer.rs
Outdated
Instruction::variable(pointer_type_id, varying_id, class, None) | ||
.to_words(&mut self.logical_layout.declarations); | ||
|
||
self.decorate( | ||
varying_id, | ||
spirv::Decoration::BuiltIn, | ||
&[spirv::BuiltIn::GlobalInvocationId as u32], | ||
); |
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 understand why, but it's a shame that we have to replicate code like this. This is an example of a case where lowering the Naga IR to some intermediate representation before generating SPIR-V would simplify things. But that shouldn't be addressed in this PR.
0458e45
to
827512c
Compare
closes #53
Possible future optimizations: