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

Impl trait functions directly on EntryCustom/Instance/Device #412

Merged
merged 4 commits into from
Apr 30, 2021

Conversation

Rua
Copy link
Contributor

@Rua Rua commented Mar 21, 2021

Depends on #400.

A possible improvement to the code structure could be to create a core module to sit alongside extensions, containing core/v1_0.rs, core/v1_1.rs and core/v1_2.rs. This would better match the way extension code is currently structured. I think it could also be good to re-export Vulkan types from each of these.

@Rua Rua changed the title Impl on instance device Impl traits directly on Instance/Device Mar 21, 2021
@Rua Rua changed the title Impl traits directly on Instance/Device Impl traits directly on EntryCustom/Instance/Device Mar 21, 2021
@Rua Rua changed the title Impl traits directly on EntryCustom/Instance/Device Impl trait functions directly on EntryCustom/Instance/Device Mar 21, 2021
Copy link
Member

@MaikKlein MaikKlein left a comment

Choose a reason for hiding this comment

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

Sorry for the late reply.

Moving the core traits into methods seems good, I am not so sure about moving the extensions into core as well. Basically this tries to load every extensions when creating a instance/device. It is also a pretty big breaking change as now all the extension structs are gone + the extension functions have a vendor extension in their name.

I am going to request a few reviews to get more opinions.

@Ralith
Copy link
Collaborator

Ralith commented Apr 11, 2021

I'm in favor of dropping the traits; I've never derived any benefit from them, it's just another thing to import, and empirically a recurring source of confusion for new users.

I'm ambivalent about folding the extensions in as well. It's a bit more convenient, but also a bit more error-prone. For extensions that I don't require (e.g. debug stuff) I quite like having an Option<Extension> that makes it very easy to ensure I don't forget to handle both cases somewhere. At minimum, we shouldn't conflate that change with the removal of traits; @Rua, if you're strongly interested in advocating for it, please split it into a separate PR.

@MarijnS95
Copy link
Collaborator

Dropping the traits is fine by me - we're only using 1_2 and as @Ralith says it's just an extra thing to import, ash::Device is already a fat struct holding on to them all. If this struct could be more lightweight for embedded purposes we might want to revisit that, but that's more likely a case of some macro magic to define and load just the functions one needs anyway.

Moving the extensions in there should definitely be done in a separate PR, if only for cleaner history and easier review/revertability - and it's a significant breaking change that should be considered carefully while allowing "normal" PRs (introducing new features) to be released first.
This struct is already pretty large (we're holding it by value in quite a few locations in our code, something that needs to be refactored on our end) and this only makes it bigger. I don't like the idea of Option<> as that means we'd have to check whether the extension is available every time it is used through the device, instead of just once at startup.
Not that that really means anything currently since any function that fails to load is substituted with a panicking stub - I'd rather have more explicit control or at least feedback over what did and did not load - but that's also for another issue/PR.
(ie. with extensions you're AFAIK supposed to get none or all of the functions, to catch errors up-front in a Rusty way through Result without panicking).

@MaikKlein
Copy link
Member

e. with extensions you're AFAIK supposed to get none or all of the functions, to catch errors up-front in a Rusty way through Result without panicking).

That is not fully true IIRC. Some functions from extensions might require other extensions to be enabled. So it is possible for some extension function pointers to not load.

@MarijnS95
Copy link
Collaborator

That is not fully true IIRC. Some functions from extensions might require other extensions to be enabled. So it is possible for some extension function pointers to not load.

Right that's true, we can't have a single Result catch-all for extensions. The XML seems to have requires= declarations for extensions as a whole but not individual functions though? Not sure how we should implement more strict function loading up-front then. Perhaps just bail if all functions are nullpointers?

@Ralith
Copy link
Collaborator

Ralith commented Apr 17, 2021

That is not fully true IIRC. Some functions from extensions might require other extensions to be enabled. So it is possible for some extension function pointers to not load.

Can you give a specific example of an extension that is valid without another extension loaded, but which defines additional functions only if it's present?

@Rua
Copy link
Contributor Author

Rua commented Apr 18, 2021

Did I misinterpret MaikKlein's reply in #408 (comment)? I thought that was giving me the go-ahead for this PR as a whole.

Anyway, I reduced this PR to only the removal of the traits. Should I implement the suggestion I originally made, to create a core subdirectory with modules for each version?

Copy link
Member

@MaikKlein MaikKlein left a comment

Choose a reason for hiding this comment

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

Did I misinterpret MaikKlein's reply in #408 (comment)? I thought that was giving me the go-ahead for this PR as a whole.

Sorry I should have been clearer.

Thank you for this PR, a much needed simplification <3. @MarijnS95 can you have a quick peek?

@MarijnS95
Copy link
Collaborator

@MaikKlein I'll queue this up for tomorrow-morning, together with some other PRs. Will also check how it fares on our existing usecases.

Copy link
Collaborator

@MarijnS95 MarijnS95 left a comment

Choose a reason for hiding this comment

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

Apologies, it took some time (a full work-week, to be precise) to get to this.

Overall this is a net-win for our codebase. All we had to do was remove the trait imports and bounds, it's actually great we're now acknowledging that all (core) function pointers were stored in ash::Device anyway, and there wasn't any extra compile/runtime checking to ensure that the (mandatory) functions could be loaded in the first place.

All in all the only thing that disappears with this PR is static visibility in what core functions are actually used by a code-base. That might be a big deal. @MaikKlein Do you perhaps remember why traits were used in the first place?

@Rua You should probably remove Fixes #408 as this only removes trait bounds but does not take care of the main issue described there: unconditionally dumping all extension function pointers in ash::Device.

Copy link
Collaborator

@MarijnS95 MarijnS95 left a comment

Choose a reason for hiding this comment

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

@Rua I do think that you need to maintain the 1.2 - 1.1 - 1.0 ordering in device.rs like you did in instance.rs. That way the diffstat is more bearable, and the resulting diff is much easier to read and git blame is still useful.

Also, conflict resolution with master seems to have gone wrong, we replaced all redundant type names with Self and fortunately enabled the clippy::use_self warning for the entire extensions module.

@Rua
Copy link
Contributor Author

Rua commented Apr 30, 2021

Ok, done. cargo test didn't run clippy for me, so maybe that's something that could be changed in Ash's configuration. Or is there another command I should be running instead?

@MarijnS95
Copy link
Collaborator

@Rua cargo test runs application-defined tests, it doesn't perform a linter (nor formatting) pass as far as I'm aware - and there's no way to configure that either.

@MarijnS95 MarijnS95 merged commit f5e7cfe into ash-rs:master Apr 30, 2021
@MarijnS95
Copy link
Collaborator

Thanks! Given that all maintainers agreed this is the way forward, and the changes look clean/small enough (now after reordering the functions again), I've just merged this to unblock some other PRs 🥳

@Rua Rua deleted the impl-on-instance-device branch April 30, 2021 15:18
MarijnS95 added a commit to MarijnS95/ash-molten that referenced this pull request Apr 30, 2021
Ash recently [dropped all traits](1) to simplify `ash::Device` usage,
but this also disallows ash-molten from overriding the `EntryV1_0` trait
to provide a static entrypoint intead.

Fortunately ash-molten can simply pass a library loading closure that
returns the static address of `vkGetInstanceProcAddr` to
`EntryCustom::new_custom`, getting rid of the copied `fn
create_instance` implementation at the same time.

[1]: ash-rs/ash#412
MarijnS95 added a commit to MarijnS95/ash-molten that referenced this pull request Apr 30, 2021
Ash recently [dropped all traits](1) to simplify `ash::Device` usage,
but this also disallows ash-molten from overriding the `EntryV1_0` trait
to provide a static entrypoint intead.

Fortunately ash-molten can simply pass a library loading closure that
returns the static address of `vkGetInstanceProcAddr` to
`EntryCustom::new_custom`, getting rid of the copied `fn
create_instance` implementation at the same time.

[1]: ash-rs/ash#412
MarijnS95 added a commit to MarijnS95/ash-molten that referenced this pull request Apr 30, 2021
Ash recently [dropped all traits](1) to simplify `ash::Device` usage,
but this also disallows ash-molten from overriding the `EntryV1_0` trait
to provide a static entrypoint intead.

Fortunately ash-molten can simply pass a library loading closure that
returns the static address of `vkGetInstanceProcAddr` to
`EntryCustom::new_custom`, getting rid of the copied `fn
create_instance` implementation at the same time.

[1]: ash-rs/ash#412
@MarijnS95
Copy link
Collaborator

MarijnS95 commented Apr 30, 2021

Looking at this again, it seems Ash-Molten cannot easily override static_fn in EntryCustom anymore: https://github.com/EmbarkStudios/ash-molten/blob/main/src/lib.rs

However, there's quite a bit of duplicated code as well and can easily get away with both problems by returning a pointer to the static vkGetInstanceProcAddr from a loader closure, problem solved: EmbarkStudios/ash-molten#56

MarijnS95 added a commit to MarijnS95/ash-molten that referenced this pull request Jul 9, 2021
Ash recently [dropped all traits](1) to simplify `ash::Device` usage,
but this also disallows ash-molten from overriding the `EntryV1_0` trait
to provide a static entrypoint intead.

Fortunately ash-molten can simply pass a library loading closure that
returns the static address of `vkGetInstanceProcAddr` to
`EntryCustom::new_custom`, getting rid of the copied `fn
create_instance` implementation at the same time.

[1]: ash-rs/ash#412
MarijnS95 added a commit to MarijnS95/ash-molten that referenced this pull request Jul 30, 2021
Ash recently [dropped all traits](1) to simplify `ash::Device` usage,
but this also disallows ash-molten from overriding the `EntryV1_0` trait
to provide a static entrypoint intead.

Fortunately ash-molten can simply pass a library loading closure that
returns the static address of `vkGetInstanceProcAddr` to
`EntryCustom::new_custom`, getting rid of the copied `fn
create_instance` implementation at the same time.

[1]: ash-rs/ash#412
MarijnS95 added a commit to MarijnS95/ash-molten that referenced this pull request Aug 3, 2021
Ash recently [dropped all traits](1) to simplify `ash::Device` usage,
but this also disallows ash-molten from overriding the `EntryV1_0` trait
to provide a static entrypoint intead.

Fortunately ash-molten can simply pass a library loading closure that
returns the static address of `vkGetInstanceProcAddr` to
`EntryCustom::new_custom`, getting rid of the copied `fn
create_instance` implementation at the same time.

[1]: ash-rs/ash#412
MarijnS95 added a commit to MarijnS95/ash-molten that referenced this pull request Aug 31, 2021
Ash recently [dropped all traits](1) to simplify `ash::Device` usage,
but this also disallows ash-molten from overriding the `EntryV1_0` trait
to provide a static entrypoint intead.

Fortunately ash-molten can simply pass a library loading closure that
returns the static address of `vkGetInstanceProcAddr` to
`EntryCustom::new_custom`, getting rid of the copied `fn
create_instance` implementation at the same time.

[1]: ash-rs/ash#412
mergify bot pushed a commit to EmbarkStudios/ash-molten that referenced this pull request Oct 14, 2021
* lib: Provide entrypoint through Ash loader w.o. implementing Entry

Ash recently [dropped all traits](1) to simplify `ash::Device` usage,
but this also disallows ash-molten from overriding the `EntryV1_0` trait
to provide a static entrypoint intead.

Fortunately ash-molten can simply pass a library loading closure that
returns the static address of `vkGetInstanceProcAddr` to
`EntryCustom::new_custom`, getting rid of the copied `fn
create_instance` implementation at the same time.

[1]: ash-rs/ash#412

* cargo: Disable unneeded `libloading` feature in Ash

The entry-point is statically linked from `MoltenVK` and does not need
any dlopen nor dlsym functionality.

* Fix some typos
MarijnS95 added a commit that referenced this pull request Jun 5, 2022
This seems to have been forgotten in #412.
Ralith pushed a commit that referenced this pull request Jun 5, 2022
This seems to have been forgotten in #412.
MarijnS95 added a commit that referenced this pull request Jun 5, 2022
This seems to have been forgotten in #412.
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.

4 participants