use threadgroup pointers instead of references in metal#9380
use threadgroup pointers instead of references in metal#938039ali wants to merge 3 commits intogfx-rs:trunkfrom
Conversation
|
@39ali: Before we have somebody do review, this needs to be rebased, and CI errors need to be fixed. |
| }; | ||
| (coherent, space, access, "&") | ||
|
|
||
| let (suffix, reference) = if let crate::AddressSpace::WorkGroup = var.space { |
There was a problem hiding this comment.
If let is probably less clear than simply var.space == .... Also, do you know whether this should affect AddressSpace::TaskPayload, or any ray payload space? If not that warrants a comment explaining.
There was a problem hiding this comment.
just saw the mesh shader changes, i'll look into it
| // but for it to work with the rest of the code we reference it in a temp var in the function body: | ||
| // threadgroup type& temp = *temp_ptr; | ||
| for (handle, var) in module.global_variables.iter() { | ||
| if var.space == crate::AddressSpace::WorkGroup && !fun_info[handle].is_empty() { |
There was a problem hiding this comment.
Again, TaskPayload?
| // for threadgroup, we use pointer and not a reference to disable compiler reordering | ||
| // but for it to work with the rest of the code we reference it in a temp var in the function body: | ||
| // threadgroup type& temp = *temp_ptr; |
There was a problem hiding this comment.
This should probably link to an issue. "Compiler reordering" is not perfectly clear on what the problem actually is. And its not obvious why we can redeclare as a refernece later without issue.
| Ok(write!( | ||
| out, | ||
| "{}{}{}{}{}{}{} {}", | ||
| "{}{}{}{}{}{}{} {}{}", |
There was a problem hiding this comment.
This does not adequately handle cases where there might be another variable with this name. You have to use the writer's namer.
|
|
||
| writeln!( | ||
| self.out, | ||
| " threadgroup {}& {} = *{}_ptr;", |
There was a problem hiding this comment.
This _ptr will have to change according to the comment above.
|
@inner-daemons i didn't like that local reference hack so i changed it to actually use the pointer |
f8258f1 to
f615b3a
Compare
|
@39ali could you resolve the CI failures? I will take a look at the PR after. |
f615b3a to
df6ba31
Compare
df6ba31 to
a834739
Compare
|
@teoxoy done |
|
Gonna block this on my review again since it touches mesh shader stuff |
teoxoy
left a comment
There was a problem hiding this comment.
Looks good overall, but I think we can remove 2 sections.
|
@teoxoy done 👍 |
|
Thanks! |
| ) { | ||
| uint3 nagaGridSize = _ts_main(__local_invocation_index, taskPayload, workgroupData); | ||
| threadgroup float workgroupData; |
There was a problem hiding this comment.
Why did you make this change
There was a problem hiding this comment.
I'll give you some more context. There is a difference between workgroup variables declared as function parameters and those declared as variables in the function, because you have to manually allocate those declared in the function parameters (and then bind them). But there are benefits so we usually use those.
Mesh shaders don't support using this kind of workgroup variables because the grids can be dispatched by another task shader (which obviously can't allocate and bind a workgroup variable for each dispatched mesh shader grid). So mesh shaders intentionally declare them as variables in the wrapper function, but the inner function doesn't notice since it just takes a reference anyway. Task shaders don't have this limitation so they are treated like compute shaders.
There was a problem hiding this comment.
Good catch! I wonder why none of the tests failed.
There was a problem hiding this comment.
@teoxoy There was an edge case here to protect mesh shaders. It was expanded to task shaders in this change, not removed entirely. So it shouldn't have broken anything but it might've worsened performance or reduced the maximum size of the payload unexpectedly, I'm not entirely sure.
| uint __local_invocation_index | ||
| , object_data TaskPayload& taskPayload | ||
| , threadgroup float& workgroupData | ||
| , threadgroup float* workgroupData |
There was a problem hiding this comment.
Is this really necessary? Keep in mind this right here isn't actually declaring such a workgroup variable, its merely taking a reference to an existing variable
| @@ -442,7 +442,7 @@ impl TypedGlobalVariable<'_> { | |||
| }; | |||
| let (coherent, space, access, reference) = match (var.space.to_msl_name(), var.space) { | |||
| (Some(space), crate::AddressSpace::WorkGroup) => { | |||
There was a problem hiding this comment.
Should this also match for TaskPayload address space?
There was a problem hiding this comment.
I don't think it should, it doesn't map to the threadgroup address space.
wgpu/naga/src/back/msl/writer.rs
Line 688 in 253477b
There was a problem hiding this comment.
Task payload storage class is defined to be basically identical to threadgroup storage class, except that in mesh shaders it is immutable. My point here is that this fix should therefore also apply to object_data variables so that they can benefit.
inner-daemons
left a comment
There was a problem hiding this comment.
I left some comments above, didn't realize there would be so many so I didn't put it in a review. Here, I mostly want you to avoid making changes to mesh/task shaders that aren't necessary.
Another thing that came up a ton is that TaskPayload address space functions very similarly to workgroup address space (though it is only mutable in task shaders). So it would probably be best to apply all of your fixes to that too.
| match context.function.expressions[chain] { | ||
| crate::Expression::GlobalVariable(handle) => { | ||
| let var = &context.module.global_variables[handle]; | ||
| var.space == crate::AddressSpace::WorkGroup |
There was a problem hiding this comment.
Same here, should this match for task payload variables?
| _ => { | ||
| if var.space == crate::AddressSpace::WorkGroup | ||
| && ep.stage == crate::ShaderStage::Mesh | ||
| && (ep.stage == crate::ShaderStage::Mesh |
There was a problem hiding this comment.
This is the kind of stuff that I highlighted in the mesh shader ouptut but I don't know why it needed to change
| match *self { | ||
| Access::GlobalVariable(handle) => { | ||
| let var = &module.global_variables[handle]; | ||
| var.space == crate::AddressSpace::WorkGroup |
There was a problem hiding this comment.
Again here, should this match a task payload pointer
| fn root_is_workgroup_pointer(&self, module: &crate::Module) -> bool { | ||
| if let Some(&Access::GlobalVariable(handle)) = self.stack.first() { | ||
| let var = &module.global_variables[handle]; | ||
| return var.space == crate::AddressSpace::WorkGroup; |
Connections
fixes #4500
Description
threadgroups are broken in metal when referenced instead of using pointers(i suspect because of compiler reordering)
this seems to fix the issue
Testing
ran tests, and local test that uses threadgroups
Squash or Rebase?
either
Checklist
cargo fmt.taplo format.cargo clippy --tests. If applicable, add:--target wasm32-unknown-unknowncargo xtask testto run tests.CHANGELOG.mdentry.