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

metal: Migrate to objc2 architecture with objc2-metal bindings #225

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

MarijnS95
Copy link
Member

The current objc crate stack is completely unmaintained and has severely fallen out of date with no updates for over 4 years. The metal-rs crate, built on top of this architecture, is completely written by hand which is tedious to keep up-to-date, not to mention has inconsistencies in its implementation.

All of this is superseded by the new objc2 crate stack built by @madsmtm. Beyond providing what seems like a better, safer abstraction over Objective-C, all bindings are completely autogenerated meaning we'll no longer lag behind upstream bindings (requiring painstaking manual patching) or have inconsistencies in the implementations, as long as the generator is properly able to represent the bindings.


This PR is a draft to allow me to get a better understanding of Objective-C, as well as for @madsmtm to chime in on the current use of Metal bindings. Who also helpfully provided me a branch with planned future improvements, including changing the generated bindings to be closer to metal-rs to make other migrations easier to manage.

One important thing that is missing from this PR is interop with older metal-rs types. objc2(-metal) has the typical Id::from_raw() interop that could allow us to upgrade gpu-allocator here while still using metal-rs for a little while longer in our own codebase. Such interop could be provided like the public-winapi optional feature, or hand-rolled in our codebase if so desired.

Cargo.toml Outdated Show resolved Hide resolved
src/metal/mod.rs Outdated
location: MemoryLocation,
) -> AllocationCreateDesc<'a> {
let size_and_align = device.heap_acceleration_structure_size_and_align_with_size(size);
// TODO: Why is this one unsafe?
Copy link

Choose a reason for hiding this comment

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

Likely just because no-one has marked it as safe.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh that's interesting. How much manual work is involved in improving the representation of the Metal API (or anything objc in general)?

I never want my implementations to be one way, and would love to aid in contributing back upstream bindings improvements. Is there some documentation or guidance in what goes into deducing that a function is safe (or any other thing that I might want to change), and how/where to ultimately mark it as such?

I'll look into your crate documentation meanwhile!

Copy link
Member Author

Choose a reason for hiding this comment

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

https://github.com/madsmtm/objc2/blob/master/crates/header-translator/src/data/Metal.rs looks like this is where I'll want to start making changes.

Copy link

Choose a reason for hiding this comment

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

That is the place, yeah. I've been considering designing an "auto-safe" system where you could mark an entire class as being safe, and then all the methods on that class that take references and not e.g. pointers would be marked safe.

But it's a tough issue, and not a burden I wanted to tackle right now, especially in the political sense (I cannot really afford for objc2 to be seen as something that plays quick and dirty with unsafe).

Copy link
Member Author

Choose a reason for hiding this comment

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

I saw some of these methods were likely commented out and marked as unsafe because of possibly going out of bounds? E.g. setWidth: and friends, how do you deduce what happens here? And heapAccelerationStructureSizeAndAlignWithSize: too?

Copy link

Choose a reason for hiding this comment

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

how do you deduce what happens here

In reality, I don't really - the issue here is that I don't know enough about Metal to know what's safe and what isn't, the only reason that a lot of things are marked safe is mostly to retain approximate feature-compatibility with the metal crate, I haven't actually done a thorough review of everything there.

In the case of indexes I went with being overly cautious, they looked like something that might very easily run into UB if you passed Metal some buffer and then set the size of the buffer to something else, but it's very probable that Metal protects against this internally, and that it isn't actually an issue.

Copy link
Member Author

@MarijnS95 MarijnS95 May 19, 2024

Choose a reason for hiding this comment

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

That sounds very sensible. Sounds like the combination of common-sense and maybe runtime-testing (if I pass an invalid value: does Metal prevent me from (ab)using it by returning an error or otherwise)?

More importantly this might be something to document in the header-translator files directly (if not already done so), maybe serving a double purpose as # Safety docs when deducing that a function is explicitly unsafe (or maybe also why it would be "safe" if deduced as such).


the only reason that a lot of things are marked safe is mostly to retain approximate feature-compatibility with the metal crate

Ouch; I hope any failures there to not mark things unsafe when they really are unsafe don't trickle down into your crates. I think that's the kind of compatibility you shouldn't retain, to demonstrate that there's an obvious safety benefit in using objc2.

The current `objc` crate stack is completely unmaintained and has
severely fallen out of date with no updates for over 4 years.  The
`metal-rs` crate, built on top of this architecture, is completely
written by hand which is tedious to keep up-to-date, not to mention
has inconsistencies in its implementation.

All of this is superseded by the new `objc2` crate stack built by
@madsmtm.  Beyond providing what seems like a better, safer abstraction
over Objective-C, _all_ bindings are completely autogenerated meaning
we'll no longer lag behind upstream bindings (requiring painstaking
manual patching) or have inconsistencies in the implementations, as long
as the generator is properly able to represent the bindings.
Copy link

@madsmtm madsmtm left a comment

Choose a reason for hiding this comment

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

Glad to see that you're progressing here! I can't really help with the correctness of using the Metal API itself, am not experienced enough with it to do so, but I'll be happy to continue answering questions if you're using objc2-specific APIs that are confusing (this also goes for future PRs in this and other repos).

Cargo.toml Outdated Show resolved Hide resolved
@madsmtm madsmtm mentioned this pull request May 23, 2024
4 tasks
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.

None yet

2 participants