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

extensions: Always return pipeline/shaders, even on error #828

Merged
merged 1 commit into from
Mar 31, 2024

Conversation

MarijnS95
Copy link
Collaborator

@MarijnS95 MarijnS95 commented Nov 22, 2023

In ash::Device create_compute_pipeline() and create_graphics_pipeline() already return the list of pipelines regardless of the error code, as documented in the Multiple Pipeline Creation chapter. Callers are expected to scan the returned array for valid pipeline handles and either use or destroy them (when handling an error). Furthermore, the caller is guaranteed that all handles will be NULL after the first returned NULL handle when VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT is set.

An upstream Khronos/Vulkan request which has since been merged to the documentation makes all pipeline creation functions across the core and extensions point to this Multiple Pipeline Creation chapter which has also been improved, clarifying that they too return impartial results. This documentation reference has been embedded in ash.

VK_EXT_shader_object is similar in nature, but has its own documentation to account for the difference in naming.

Copy link
Collaborator

@Ralith Ralith left a comment

Choose a reason for hiding this comment

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

It's tempting to push for (Vec<T>, Result<()>) here, but it does make it a lot easier to forget to check the error condition.

@MarijnS95
Copy link
Collaborator Author

It's tempting to push for (Vec<T>, Result<()>) here, but it does make it a lot easier to forget to check the error condition.

Yeah it's unfortunate that there's no lint to catch an unused Result when it is returned as part of a tuple.

@MarijnS95
Copy link
Collaborator Author

https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap10.html#pipelines-multiple

Turns out there's actually documentation for this, and the references+language are being updated upstream.

I'd still like to think of a better way to represent the validity of the return values (and necessity to clean up non-NULL handles) before merging this in.

@Ralith
Copy link
Collaborator

Ralith commented Dec 1, 2023

We could do Vec<Result<T>>? Might cause some confusion for errors due to one pipeline getting broadcast to multiple, but has a lot going for it otherwise.

@MarijnS95
Copy link
Collaborator Author

I've been contemplating that but it sets the false precedent that every pipeline individually has an error code. It seems better than the status-quo, though!

@Ralith
Copy link
Collaborator

Ralith commented Dec 1, 2023

(Vec<Option<T>>, VkResult)?

@MarijnS95
Copy link
Collaborator Author

Also considered, but that might be ambiguous with None vs Some(vk::Handle::null()) 😅

@MarijnS95
Copy link
Collaborator Author

MarijnS95 commented Dec 1, 2023

We're gonna write high-level bindings at this point, but how about an OwnedPipeline that has an fn take(self) -> vk::Pipeline, which drops itself if it wasn't taken (via std::mem::take())?

It wouldn't have access to the device to do so though if the type is #[repr(transparent)].

@Ralith
Copy link
Collaborator

Ralith commented Dec 1, 2023

Anything like RAII ownership of Vulkan objects starts feeling out of scope for ash. We could panic rather than destroy, but I'm not sure that'll do much good compared to a static mechanism.

I feel like the original proposal here (Result<Vec<T>, (Vec<T>, VkResult)>) is fine, honestly. It's weird looking but gives a pretty strong static cue that you have to do some work on error.

@MarijnS95
Copy link
Collaborator Author

Anything like RAII ownership of Vulkan objects starts feeling out of scope for ash.

It'd also start implying that similar mechanisms are available or supposed to be available on other types, which wouldn't be the case by for ash in any shape or form.

@MarijnS95 MarijnS95 force-pushed the always-return-pipelines branch from 358521c to 8e5c5b9 Compare December 1, 2023 21:30
@MarijnS95
Copy link
Collaborator Author

Upstream documentation improvements have been merged, command pages now contain this:

Pipelines are created and returned as described for Multiple Pipeline Creation.

I'll adopt and update the relevant portions of that doc here in ash on all functions, before merging this. While the function interface indeed shows that users have to do some work on error, it's better to explain and/or link what explicitly.

@MarijnS95 MarijnS95 force-pushed the always-return-pipelines branch from 8e5c5b9 to a668edb Compare December 10, 2023 16:53
@MarijnS95
Copy link
Collaborator Author

MarijnS95 commented Dec 10, 2023

Perhaps that doc is a bit excessive. I pruned it down somewhat, but we could also boil it down to just the link, or perhaps at the very least (because of the return signature) state that valid references may always be returned - corresponding to create_infos[i] - and should either be used or cleaned up.

@Ralith
Copy link
Collaborator

Ralith commented Dec 10, 2023

Yeah, I think something a lot more terse will suffice. No need to duplicate upstream docs at length. Maybe something like:

If multiple pipelines are being created in one call, a subset of pipelines might be created even in the event of an error. Care should be taken not to leak these.

In `ash::Device` `create_compute_pipeline()` and
`create_graphics_pipeline()` already return the list of pipelines
regardless of the error code, as [documented in the Multiple Pipeline
Creation chapter].  Callers are expected to scan the returned array
for valid pipeline handles and either use or destroy them (when
handling an error).  Furthermore, the caller is guaranteed that
all handles will be NULL after the first returned NULL handle when
`VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT` is set.

An upstream Khronos/Vulkan request which has since been merged to the
documentation makes all pipeline creation functions across the core and
extensions point to this `Multiple Pipeline Creation` chapter which has
also been improved, clarifying that they too return impartial results.
This documentation reference has been embedded in `ash`.

`VK_EXT_shader_object` is similar in nature, but has its own
documentation to account for the difference in naming.

[documented in the Multiple Pipeline Creation chapter]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap10.html#pipelines-multiple
@MarijnS95 MarijnS95 force-pushed the always-return-pipelines branch from a668edb to a907be8 Compare March 30, 2024 20:17
@MarijnS95 MarijnS95 requested a review from Ralith March 30, 2024 20:17
@MarijnS95 MarijnS95 merged commit 9e36403 into master Mar 31, 2024
20 checks passed
@MarijnS95 MarijnS95 deleted the always-return-pipelines branch March 31, 2024 10:06
@MarijnS95 MarijnS95 added this to the Ash 0.38 milestone Dec 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants