-
Notifications
You must be signed in to change notification settings - Fork 192
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
Implement Send
/Sync
for all vk
structs
#869
Conversation
I think this is a justified change, though I haven't had time to review the specifics yet. As you say, every consumer is
This pattern has limited use, since it's incompatible with any use of extensions on those structs, or even any other indirection like the many assorted arrays you'll typically pass when creating a pipeline. A more future-proof scheme is to always use your own message types in this case, even if they initially closely mirror Vulkan structs. Still, that's no reason not to make the change proposed here. |
In my case this isn't exposed as part of the public API. It's simply the case that I found it more convenient to build the struct on the main thread and send the whole thing to the worker thread. Without "Send" and "Sync" I cannot do that even with the extension structs boxed. |
Merged master but still seeing one CI issue:
Rust version in CI probably needs to be updated? |
@Ralith The CI is now green |
Yep, thanks! LGTM, just leaving @MarijnS95 an opportunity to weigh in and/or merge. |
This PR does not seem to have had a compelling discussion to support this change besides @Neo-Zhixing needing this to make some shortcuts in their threading message passing implementation? Users have already had lots of trouble with lifetime safety on their references, and I fear this is only going to make things worse when struct lifetimes start to protrude a stack - not to mention thread - boundary. It sounds like @Neo-Zhixing might then also have to work around the new struct lifetimes introduced in the next version of Secondly I do wonder if there are any types in Ash that are intentionally not That is not to say that I haven't personally thought about making a similar change. Our own application has a |
generator/src/lib.rs
Outdated
return None; | ||
} | ||
let name = name_to_tokens(&struct_.name); | ||
let lifetime = has_lifetime.then(|| quote!(<'_>)); |
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.
Won't has_lifetime
always be true at this point? We know this struct has pointers, so why bother checking that flag?
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.
Good point. That was non-obvious to me. Updated.
Not completely I think, as some users may, for whatever reason (maybe they don't know better), directly manipulate the pointers through field access, therefore bypassing the struct lifetime. But then they'd be shooting themselves in the foot in much more ways than just passing a pointer over a thread boundary that they shouldn't have. I digress, as that's a more abstract discussion to be had, less related to this PR. Anyways, either way, I don't see much reason not to do this. |
@MarijnS95 Thanks for your response!
Yeah so I suppose this PR would be the perfect place for discussions!
That is true, but safeguarding users and making sure that their API calls are thread-safe is explicitly a non-goal for ash.
Like @Friz64 said, the users are always allowed to manipulate raw pointers directly. The difference between this and the recent lifetime changes is that one is a quality-of-life improvement, while the other is limiting what the user can do. And ash users are generally expected to be able to "fk around and find out".
I don't think that's the case. In Vulkan, everything is assumed to be thread-safe unless the spec says "Host access to ** must be externally synchronized". But once again, ash users are expected to respect Vulkan specification, and it's not our job to check that they do.
Having to wrap everything in
In a lot of cases this might be true, but in other cases it's easier to build the struct first and then send them across thread boundary. I do think that there's value for both cases to be supported. |
@Friz64 Yeah, that is covered in the paragraph after the one you quoted. It's good to have discussed and know that this feature will only support
Hence all these points that were brought up 😉
That doesn't mean to say that it is a goal of As a sanity-check regarding "extension structs boxed", how much extra effort is your code putting on finding non-null pointers and For the specific example of pipeline creation, we're doing that off-thread as well but without any "sending Vulkan pointer structs across a thread boundary" issue. I can look up how we do it, but I don't remember it being particularly clever or involved: not many (pointer) arguments are needed to be serialized in the first place. Alas, let's continue discussing the change at hand rather me rambling about how I don't see it being particularly useful to solve the proposed case.
Yeah, @Friz64 confirmed what I said in the next paragraph about the lifetimes no longer serving their purpose (intentionally, to support your case) when manually storing pointers to pinned boxed structs.
I agree, but it is again desired to first discuss and agree that this is the case. As said all handles are
This was a point in favour of your PR 😉. We'd be able to drop that (A |
All in all, since the other maintainers seem to be in favour of this change, and it doesn't further expose any kind of safety issues, let's clean this up and merge this, and focus on the bigger breaking tasks at hand. |
That is true, but it's a decision better left to the developer of higher-level abstractions. There's one additional point I forgot to mention - But yeah, overall it sounds like we can all agree that this change is justified. I do appreciate that we're taking our time to carefully weigh it against alternatives and making sure that the discussions are fully documented. I've rebased the PR with master and someone can click the merge button whenever. |
FYI you merged in master, which is different from a rebase, though that doesn't matter here since we'll squash it down into one commit anyway. |
Send
/Sync
for all structs
Send
/Sync
for all structsSend
/Sync
for all vk
structs
commit 1c2d954 Merge: 1c5884f f2979c8 Author: Zhixing Zhang <me@neoto.xin> Date: Tue Mar 19 16:16:16 2024 -0700 Merge branch 'master' into send-sync commit 1c5884f Author: Zhixing Zhang <me@neoto.xin> Date: Tue Mar 19 01:00:02 2024 -0700 update commit 9fd392d Merge: 812e978 1eb8725 Author: Zhixing Zhang <me@neoto.xin> Date: Fri Mar 15 17:49:59 2024 -0700 Merge branch 'master' into send-sync commit 812e978 Merge: 994133c 4449a18 Author: Zhixing Zhang <me@neoto.xin> Date: Thu Mar 7 15:21:23 2024 -0800 Merge remote-tracking branch 'upstream/master' into send-sync commit 994133c Author: Zhixing Zhang <me@neoto.xin> Date: Thu Mar 7 07:46:28 2024 -0800 Revert "update generated files" This reverts commit e260c43. commit e260c43 Author: Zhixing Zhang <me@neoto.xin> Date: Tue Mar 5 14:13:42 2024 -0800 update generated files commit 48ae041 Author: Zhixing Zhang <me@neoto.xin> Date: Tue Mar 5 14:04:09 2024 -0800 Implement Send/Sync for all the structs
Oftentimes we want to populate
vk::Create*Info
and then send this struct to a worker thread for processing. This is extremely common for pipeline objects which generally takes longer than most other commands, necessitating async processing.However, these
vk::Create*Info
structs oftentimes contain at least ap_next
pointer which makes the struct non-Send and non-Sync. This makes sending thosevk::Create*Info
structs unnecessarily complicated.As such, I propose that we implement "Send" and "Sync" by default for all the structs. Vulkan commands are unsafe anyways, so implementing "Send" and "Sync" shouldn't introduce additional unsafety.