Skip to content
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

Barriers #817

Merged
merged 1 commit into from
May 5, 2021
Merged

Barriers #817

merged 1 commit into from
May 5, 2021

Conversation

kvark
Copy link
Member

@kvark kvark commented May 3, 2021

Fixes #583

@acowley
Copy link
Contributor

acowley commented May 3, 2021

I just tried out this branch rather than the barrier support I've been using, and it seems to be working well! One question: why are the WGSL built-in functions in this PR named differently than the WGSL spec?

@kvark
Copy link
Member Author

kvark commented May 3, 2021

@kvark
Copy link
Member Author

kvark commented May 3, 2021

@acowley thank you for diligence! Fixed now :)

Copy link
Collaborator

@grovesNL grovesNL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@kvark kvark merged commit 9fe75ed into gfx-rs:master May 5, 2021
@kvark kvark deleted the barrier branch May 5, 2021 02:16
Copy link
Member

@jimblandy jimblandy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good overall. Three concerns:

  • It seems like control-only barriers will be dropped in GLSL and MSL output, which is inconsistent with the handling of SPIR-V.
  • I think Statement::Barrier needs better docs. The way it's being used by the front and back ends seems inconsistent, so I wasn't confident that I could infer the intent from the code.
  • The signedness of cached index constants in SPIR-V output changed, which is a bit surprising.

Comment on lines +2071 to +2080
let mut flags = crate::Barrier::empty();
flags.set(
crate::Barrier::STORAGE,
semantics & spirv::MemorySemantics::UNIFORM_MEMORY.bits() != 0,
);
flags.set(
crate::Barrier::WORK_GROUP,
semantics & spirv::MemorySemantics::WORKGROUP_MEMORY.bits() != 0,
);
block.push(crate::Statement::Barrier(flags));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect this code to be promoting all "smaller" boundaries to the next larger boundary we support. That is, if the OpControlBarrier requests MemorySemantics::SUBGROUP_MEMORY, which I believe is a smaller subdivision than a workgroup, then that should also set Barrier::WORK_GROUP, because that's the only way we have to guarantee the sematics requested.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we definitely want a promotion like this

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, I don't know what SubgroupMemory is, and SPIR-V spec isn't clear on this

write!(self.out, "{}", INDENT.repeat(indent))?;
writeln!(self.out, "discard;")?
Statement::Kill => writeln!(self.out, "{}discard;", INDENT.repeat(indent))?,
// Just issue a memory barrier, ignoring the flags.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're not 'ignoring the flags' here, are we?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stale comment :)

Comment on lines +887 to +888
/// Synchronize accesses within the work group.
Barrier(Barrier),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the variety of barriers supported by our various target languages, I think this could use much more detailed documentation. For example, a SPIR-V OpControlBarrier instruction always generates a Statement::Barrier, but we emit no code in GLSL or MSL for a Statement::Barrier unless it has flags set, which makes it hard to someone reading the code to infer the intent. A comment here would help the reader understand which end is incorrect, or at least explain why the disagreement is acceptable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. And also, the GLSL and MSL are going to be fixed now to actually issue execution barriers.

Comment on lines +1404 to +1406
if flags.contains(crate::Barrier::WORK_GROUP) {
writeln!(self.out, "{}barrier();", INDENT.repeat(indent))?;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If none of the flags are set, this doesn't emit anything. But it seems to me that SPIR-V OpControlBarrier, which produces a Statement::Barrier with no flags set, should be a GLSL barrier();, at least.

Comment on lines +1350 to +1365
crate::Statement::Barrier(flags) => {
if flags.contains(crate::Barrier::STORAGE) {
writeln!(
self.out,
"{}{}::threadgroup_barrier({}::mem_flags::mem_device);",
level, NAMESPACE, NAMESPACE,
)?;
}
if flags.contains(crate::Barrier::WORK_GROUP) {
writeln!(
self.out,
"{}{}::threadgroup_barrier({}::mem_flags::mem_threadgroup);",
level, NAMESPACE, NAMESPACE,
)?;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, too, is inconsistent with the SPIR-V behavior. With no flags set, it seems like this should be

threadgroup_barrier(mem_flags::mem_none);

Comment on lines +986 to +992
fn get_index_constant(
&mut self,
index: Word,
types: &Arena<crate::Type>,
) -> Result<Word, Error> {
self.get_constant_scalar(crate::ScalarValue::Uint(index as _), 4, types)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes the types of indexes used as LOD selectors and OpAccessChain operands from Sint to Uint. I couldn't figure out the rules for LOD selection, but OpAccessChain says the indices are "treated as signed", so is this what we want?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SPIR-V doesn't care, basically. It will reinterpret them as signed, and it's still fine.

@kvark kvark mentioned this pull request May 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Control barriers
4 participants