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

ash-window: Add get_present_support() helper #774

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

Rob2309
Copy link

@Rob2309 Rob2309 commented Jul 21, 2023

Introduce get_present_support() to ash-window, which is a higher-level wrapper around the various platform-specific functions for querying whether a physical device queue family supports presenting to surfaces (see the Vulkan spec).

This allows choosing a physical device before creating a surface.

@Rob2309 Rob2309 changed the base branch from master to 0.37-stable July 26, 2023 20:07
@Rob2309 Rob2309 changed the base branch from 0.37-stable to master July 26, 2023 20:07
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.

Thanks, this looks really useful!

physical_device,
queue_family_index,
&mut *h.connection,
h.screen as _,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is supposed to be a visual, not a screen.

physical_device,
queue_family_index,
h.display,
h.screen as _,
Copy link
Collaborator

Choose a reason for hiding this comment

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

As above.

Copy link
Author

Choose a reason for hiding this comment

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

You're right, I think a visualID can be somehow derived from the screen, but I think this would require linking to some X library. As an alternative, the get_present_support function could require a window handle, but this would defeat the main use case.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah. We could pull in x11-dl and use it to make the necessary call (XDefaultVisualOfScreen I guess?). Bonus points for adding a cargo feature to use x11 instead, as dynamic linking is a bit tidier than runtime loading on Linux, but it can be nice to avoid a buildtime dep on a foreign lib.

Alternatively, maybe a more convenient approach would be adding a visual_id member to to raw_window_handle::XlibDisplayHandle upstream (and making sure winit populates it). This is the same motivation behind its inclusion in the window handle struct, though I'm not enough of an X11 expert to judge how weird that might be.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Bonus points for adding a cargo feature to use x11 instead, as dynamic linking is a bit tidier than runtime loading on Linux, but it can be nice to avoid a buildtime dep on a foreign lib.

Quickly scrolling through the changes, it seems that this feature is now forcibly requiring either x11 or x11-dl, or a compiler error will occur on all of unix. Same for xcb now being forced on all consumers of ash-window.

The cfg guards on those RawDisplayHandles should be refactored to contain the optional libraries as features, otherwise get_present_support() won't provide support for x11/xcb but the other functions are not affected.

Then, the module documentation and function documentation should be extended to explain these features.

ash-window/src/lib.rs Outdated Show resolved Hide resolved
ash-window/src/lib.rs Outdated Show resolved Hide resolved
/// [`VkGetPhysicalDeviceSurfaceSupportKHR`](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap34.html#vkGetPhysicalDeviceSurfaceSupportKHR),
/// which requires having an actual surface available before choosing a physical device.
///
/// For more information see [the vulkan spec on WSI integration](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap34.html#_querying_for_wsi_support).
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
/// For more information see [the vulkan spec on WSI integration](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap34.html#_querying_for_wsi_support).
/// For more information see [the Vulkan spec on WSI integration][_querying_for_wsi_support].
///
/// [_querying_for_wsi_support]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap34.html#_querying_for_wsi_support

ash-window/src/lib.rs Outdated Show resolved Hide resolved
ash-window/src/lib.rs Outdated Show resolved Hide resolved
ash-window/src/lib.rs Show resolved Hide resolved
h.screen as _,
))
},
// All other platforms mentioned in the vulkan spec are not supported by ash.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
// All other platforms mentioned in the vulkan spec are not supported by ash.
// All other platforms mentioned in the Vulkan spec are not supported by ash-window.

Because ash maps the entire Vulkan API (== supports everything), even though we might not have written a slightly-higher-level Fn wrapper for it yet the lower-level API is still available.

Though I would reword that to ... don't currently have an implementation in ash-window, as we can always expand.

@MarijnS95 MarijnS95 changed the title Added ash_window::get_present_support ash-window: Add get_present_support() helper Oct 31, 2023
@MarijnS95
Copy link
Collaborator

MarijnS95 commented Oct 31, 2023

While reviewing and refactoring the PR message, should we also mention (in the PR/commit message and the doc-comment) that it checks for support on the given Display connection? I'm not sure how much of a difference it makes beyond allowing the Vulkan driver to connect to the WSI though (perhaps for Xorg Display handles that could be networked?).

@Rob2309
Copy link
Author

Rob2309 commented Oct 31, 2023

I think I addressed everything above in this new commit.
I added x11 and x11-dl as optional dependencies, x11-dl being enabled by default. There does not seem to be a xcb-dl lib so I added xcb as a mandatory dependency for now.
The xlib code path is working on my wsl2 installation, as for xcb I am not sure, winit seems to not actually support xcb as far as I can tell.
I also changed the parameters of get_physical_device_xcb_presentation_support and get_physical_device_wayland_presentation_support to be pointers instead of references.

@Rob2309
Copy link
Author

Rob2309 commented Oct 31, 2023

I just noticed that --no-default-features seems to be ignored for running the winit example, I am not sure if I made a mistake or this is a cargo quirk.

@@ -43,7 +43,7 @@ impl WaylandSurface {
&self,
physical_device: vk::PhysicalDevice,
queue_family_index: u32,
wl_display: &mut vk::wl_display,
wl_display: *mut vk::wl_display,
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should write these down as breaking changes in the CHANGELOG (maybe via a separate PR so that it shows up properly in the commit history), though if someone passes exactly a &mut vk::wl_display it'll automatically coerce to the raw pointer.

/// surface that might be created. This function can be used to find a suitable
/// [`vk::PhysicalDevice`] and queue family for rendering before a single surface is created.
///
/// This function can be a more useful alternative for [`vkGetPhysicalDeviceSurfaceSupportKHR`],
Copy link
Collaborator

Choose a reason for hiding this comment

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

I meant to just have:

Suggested change
/// This function can be a more useful alternative for [`vkGetPhysicalDeviceSurfaceSupportKHR`],
/// This function can be a more useful alternative for [`khr::Surface::get_physical_device_surface_support()`],

We don't generally use Vulkan symbol naming in Ash.

ash-window/Cargo.toml Outdated Show resolved Hide resolved
ash-window/Cargo.toml Outdated Show resolved Hide resolved
ash-window/src/lib.rs Outdated Show resolved Hide resolved
ash-window/src/lib.rs Outdated Show resolved Hide resolved
ash-window/src/lib.rs Outdated Show resolved Hide resolved
ash-window/src/lib.rs Outdated Show resolved Hide resolved
physical_device,
queue_family_index,
h.display,
h.screen as _,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Bonus points for adding a cargo feature to use x11 instead, as dynamic linking is a bit tidier than runtime loading on Linux, but it can be nice to avoid a buildtime dep on a foreign lib.

Quickly scrolling through the changes, it seems that this feature is now forcibly requiring either x11 or x11-dl, or a compiler error will occur on all of unix. Same for xcb now being forced on all consumers of ash-window.

The cfg guards on those RawDisplayHandles should be refactored to contain the optional libraries as features, otherwise get_present_support() won't provide support for x11/xcb but the other functions are not affected.

Then, the module documentation and function documentation should be extended to explain these features.

ash-window/src/lib.rs Outdated Show resolved Hide resolved
ash-window/src/lib.rs Outdated Show resolved Hide resolved
@MarijnS95
Copy link
Collaborator

MarijnS95 commented Nov 1, 2023

I just noticed that --no-default-features seems to be ignored for running the winit example, I am not sure if I made a mistake or this is a cargo quirk.

How so? If I run this on your branch, which disables both x11 and x11-dl (which I do not care about when using Wayland), the creates are disables as expected:

$ cargo r -p ash-window --example winit --no-default-features
...
error: Exactly one of x11-dl or x11 must be enabled on unix
   --> ash-window/src/lib.rs:244:13
    |
244 |             compile_error!("Exactly one of x11-dl or x11 must be enabled on unix");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Though as said above, I don't think we should make this a compile error.

@Rob2309
Copy link
Author

Rob2309 commented Nov 1, 2023

I now made every feature optional, but made x11-dl and xcb the default, so that every platform just works without enabling any features manually. A possible problem I see is that when x11/x11-dl is not enabled, the function will just return a generic EXTENSION_NOT_PRESENT error, which might be confusing. The same goes for xcb.

@Rob2309
Copy link
Author

Rob2309 commented Nov 1, 2023

I just noticed that --no-default-features seems to be ignored for running the winit example, I am not sure if I made a mistake or this is a cargo quirk.

How so? If I run this on your branch, which disables both x11 and x11-dl (which I do not care about when using Wayland), the creates are disables as expected:

$ cargo r -p ash-window --example winit --no-default-features
...
error: Exactly one of x11-dl or x11 must be enabled on unix
   --> ash-window/src/lib.rs:244:13
    |
244 |             compile_error!("Exactly one of x11-dl or x11 must be enabled on unix");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Though as said above, I don't think we should make this a compile error.

I just found out that cargo seems to ignore --no-default-features when not explicitly specifying a package. So cargo run --example winit --no-default-features still uses default features, but cargo run -p ash-window --example winit --no-default-features does not... Weird cargo quirk I guess

@MarijnS95
Copy link
Collaborator

MarijnS95 commented Nov 1, 2023

I just found out that cargo seems to ignore --no-default-features when not explicitly specifying a package. So cargo run --example winit --no-default-features still uses default features, but cargo run -p ash-window --example winit --no-default-features does not... Weird cargo quirk I guess

I didn't expect cargo run --example to collect all examples from all members in the workspace automatically. TIL :)

EDIT: But that sounds buggy nonetheless.

@MarijnS95
Copy link
Collaborator

Cool stuff! Can we extend the example to showcase this API?

I hacked in this chunk to see the type of window handle and print the result, but we should probably come up with something a bit nicer.

        dbg!(window.raw_display_handle());

        let &pdev = instance.enumerate_physical_devices()?.first().unwrap();

        let support = ash_window::get_present_support(
            &entry,
            &instance,
            pdev,
            0,
            window.raw_display_handle(),
        );
        dbg!(support);

And on that note, Rust naming says to not use get_ prefixes; can we come up with a better name? has_present_support(for_display_handle)() perhaps?

@Rob2309
Copy link
Author

Rob2309 commented Nov 1, 2023

And on that note, Rust naming says to not use get_ prefixes; can we come up with a better name? has_present_support(for_display_handle)() perhaps?

I would probably prefer keeping the get_prefix, as all the platform specific functions used also start with a get prefix. Ash itself also leaves the get_ prefix in place for many functions. But that is just my opinion

@MarijnS95
Copy link
Collaborator

winit seems to not actually support xcb as far as I can tell.

I just ran into rust-windowing/winit#3198

@Rob2309
Copy link
Author

Rob2309 commented Nov 1, 2023

I added a simple loop to the example that prints info about every physical device.

@Rob2309
Copy link
Author

Rob2309 commented Nov 1, 2023

winit seems to not actually support xcb as far as I can tell.

I just ran into rust-windowing/winit#3198

Since I can't get winit to use xcb, I might test the xcb code by creating a window with the xcb crate directly. Might take some time to get it right though...

@Rob2309
Copy link
Author

Rob2309 commented Nov 1, 2023

I now added a basic xcb example, the xcb code seems to be working just fine. Not sure if the example should be kept though...

@MarijnS95
Copy link
Collaborator

Since I can't get winit to use xcb, I might test the xcb code by creating a window with the xcb crate directly. Might take some time to get it right though...

No need to, it's supposed to a simple winit example. We can wait for them to implement xcb.

@Rob2309
Copy link
Author

Rob2309 commented Nov 1, 2023

Since I can't get winit to use xcb, I might test the xcb code by creating a window with the xcb crate directly. Might take some time to get it right though...

No need to, it's supposed to a simple winit example. We can wait for them to implement xcb.

In that case, should I remove the example again? I used it to verify that the xcb code works, but I don't think it adds any value that the winit example does not.

@MarijnS95
Copy link
Collaborator

Hmm you have already written it, but it also adds some extra maintenance burden to keep it up-to-date and functional.

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.

Implementation LGTM overall, thanks!

xcb = { version = "1.2.2" }

[features]
default = ["x11-dl", "xcb"]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Requiring xcb by default means we need libxcb present at buildtime, right? While probably most environments will have this, disabling it will make it easier for downstream users to get CI working in minimal VMs and such.

Copy link
Author

Choose a reason for hiding this comment

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

The reason for defaulting this is to have the least surprising behavior by default. I dont think the default should be to not support a very broadly used platform.

Copy link
Collaborator

Choose a reason for hiding this comment

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

We know winit doesn't use xcb. Where in the raw-window-handle ecosystem is xcb broadly used?

Copy link
Author

Choose a reason for hiding this comment

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

Good point, however if winit at some point decides to switch to xcb, it should be defaulted again...

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think winit will want to avoid adding foreign build-time dependencies for the same reason.

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.

Looks like I forgot to submit this outstanding review. Don't forget to address https://github.com/ash-rs/ash/pull/774/files#r1378560481 :)

for dev in devices {
let props = instance.get_physical_device_properties(dev);
let queue_families = instance.get_physical_device_queue_family_properties(dev);
let dev_name = CStr::from_ptr(props.device_name.as_ptr()).to_str().unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Note to self: I should replace this in #746.


[[example]]
name = "xcb"
required-features = ["ash/linked"]
Copy link
Collaborator

Choose a reason for hiding this comment

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

This could also require the xcb feature, though always enabling it in dev-dependencies might be fine? Not sure yet.

Copy link
Author

Choose a reason for hiding this comment

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

I am not quite sure whether normal dependencies are available in examples. Will test this and change if possible.

@Rob2309
Copy link
Author

Rob2309 commented Nov 1, 2023

Looks like I forgot to submit this outstanding review. Don't forget to address https://github.com/ash-rs/ash/pull/774/files#r1378560481 :)

I can add this to the changelog, I was just hesitant because of the separate PR point.

@Rob2309
Copy link
Author

Rob2309 commented Nov 1, 2023

The forced dev-dependency is now removed, it seems to just work with the regular optional dependency.
I also added entries to both the ash-window and ash changelog reflecting the changes here. Is there any special marking that the breaking changes should have?

@Rob2309
Copy link
Author

Rob2309 commented Mar 30, 2024

Is there anything left to do here? I must admit I am not quite sure about the status of this PR anymore...

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.

None yet

3 participants