Skip to content

Commit

Permalink
Merge pull request #614 from i509VCB/vulkan/allocator
Browse files Browse the repository at this point in the history
The Vulkan allocator
  • Loading branch information
Drakulix authored Jul 7, 2022
2 parents 710d0cd + 8991f4a commit 82308c8
Show file tree
Hide file tree
Showing 12 changed files with 2,091 additions and 1 deletion.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ jobs:
- backend_session
- backend_session_logind
- backend_session_libseat
- backend_vulkan
- backend_x11
- desktop
- renderer_gl
Expand Down
10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ members = [

[dependencies]
appendlist = "1.4"
# Intentionally pick a commit from "0.37-stable" branch since additions for 0.37.1 are used
ash = { git = "https://github.com/ash-rs/ash", rev = "62960ad680207e8496ae19ebd11f7c7ae8422e27", optional = true }
bitflags = "1"
calloop = "0.10.1"
cgmath = "0.18.0"
Expand All @@ -42,6 +44,7 @@ libloading = { version="0.7.0", optional = true }
nix = "0.22"
once_cell = "1.8.0"
rand = "0.8.4"
scopeguard = { version = "1.1.0", optional = true }
slog = "2"
slog-stdlog = { version = "4", optional = true }
tempfile = { version = "3.0", optional = true }
Expand Down Expand Up @@ -69,7 +72,7 @@ gl_generator = { version = "0.14", optional = true }
pkg-config = { version = "0.3.17", optional = true }

[features]
default = ["backend_drm", "backend_gbm", "backend_libinput", "backend_udev", "backend_session_logind", "backend_x11", "backend_winit", "desktop", "renderer_gl", "renderer_multi", "xwayland", "wayland_frontend", "slog-stdlog"]
default = ["backend_drm", "backend_gbm", "backend_libinput", "backend_udev", "backend_session_logind", "backend_x11", "backend_winit", "desktop", "renderer_gl", "renderer_multi", "xwayland", "wayland_frontend", "slog-stdlog", "backend_vulkan"]
backend_winit = ["winit", "backend_egl", "wayland-egl", "renderer_gl"]
backend_x11 = ["x11rb", "x11rb/dri3", "x11rb/xfixes", "x11rb/present", "x11rb_event_source", "backend_gbm", "backend_drm", "backend_egl"]
backend_drm = ["drm", "drm-ffi"]
Expand All @@ -78,6 +81,7 @@ backend_egl = ["gl_generator", "libloading"]
backend_libinput = ["input"]
backend_session = []
backend_udev = ["udev", "input/udev"]
backend_vulkan = ["ash", "scopeguard"]
backend_session_logind = ["dbus", "backend_session", "pkg-config"]
backend_session_elogind = ["backend_session_logind"]
backend_session_libseat = ["backend_session", "libseat"]
Expand Down Expand Up @@ -105,3 +109,7 @@ required-features = ["wayland_frontend"]
[[example]]
name = "compositor"
required-features = ["wayland_frontend"]

[[example]]
name = "vulkan"
required-features = ["backend_vulkan"]
60 changes: 60 additions & 0 deletions examples/vulkan.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use std::sync::Mutex;

use drm_fourcc::{DrmFourcc, DrmModifier};
use slog::{o, Drain};
use smithay::backend::{
allocator::{
dmabuf::AsDmabuf,
vulkan::{ImageUsageFlags, VulkanAllocator},
Allocator, Buffer,
},
vulkan::{version::Version, Instance, PhysicalDevice},
};

fn main() {
let logger = slog::Logger::root(Mutex::new(slog_term::term_full().fuse()).fuse(), o!());

println!(
"Available instance extensions: {:?}",
Instance::enumerate_extensions().unwrap().collect::<Vec<_>>()
);
println!();

let instance = Instance::new(Version::VERSION_1_3, None, logger).unwrap();

for (idx, phy) in PhysicalDevice::enumerate(&instance).unwrap().enumerate() {
println!(
"Device #{}: {} v{}, {:?}",
idx,
phy.name(),
phy.api_version(),
phy.driver()
);
}

let physical_device = PhysicalDevice::enumerate(&instance)
.unwrap()
.next()
.expect("No physical devices");

// We don't actually use any buffers created by the allocator in this example.
let mut allocator = VulkanAllocator::new(&physical_device, ImageUsageFlags::empty()).unwrap();

let image = allocator
.create_buffer(100, 200, DrmFourcc::Argb8888, &[DrmModifier::Linear])
.expect("create");

assert_eq!(image.width(), 100);
assert_eq!(image.height(), 200);

let image_dmabuf = image.export().expect("Export dmabuf");

drop(image);

let _image2 = allocator
.create_buffer(200, 200, DrmFourcc::Argb8888, &[DrmModifier::Linear])
.expect("create");

drop(allocator);
drop(image_dmabuf);
}
2 changes: 2 additions & 0 deletions src/backend/allocator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ pub mod dumb;
pub mod format;
#[cfg(feature = "backend_gbm")]
pub mod gbm;
#[cfg(feature = "backend_vulkan")]
pub mod vulkan;

mod swapchain;
use std::{
Expand Down
73 changes: 73 additions & 0 deletions src/backend/allocator/vulkan/format.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! Format conversions between Vulkan and DRM formats.
/// Macro to generate format conversions between Vulkan and FourCC format codes.
///
/// Any entry in this table may have attributes associated with a conversion. This is needed for `PACK` Vulkan
/// formats which may only have an alternative given a specific host endian.
///
/// See the module documentation for usage details.
macro_rules! vk_format_table {
(
$(
// This meta specifier is used for format conversions for PACK formats.
$(#[$conv_meta:meta])*
$fourcc: ident => $vk: ident
),* $(,)?
) => {
/// Converts a FourCC format code to a Vulkan format code.
///
/// This will return [`None`] if the format is not known.
///
/// These format conversions will return all known FourCC and Vulkan format conversions. However a
/// Vulkan implementation may not support some Vulkan format. One notable example of this are the
/// formats introduced in `VK_EXT_4444_formats`. The corresponding FourCC codes will return the
/// formats from `VK_EXT_4444_formats`, but the caller is responsible for testing that a Vulkan device
/// supports these formats.
pub const fn get_vk_format(fourcc: $crate::backend::allocator::Fourcc) -> Option<ash::vk::Format> {
// FIXME: Use reexport for ash::vk::Format
match fourcc {
$(
$(#[$conv_meta])*
$crate::backend::allocator::Fourcc::$fourcc => Some(ash::vk::Format::$vk),
)*

_ => None,
}
}

/// Returns all the known format conversions.
///
/// The list contains FourCC format codes that may be converted using [`get_vk_format`].
pub const fn known_formats() -> &'static [$crate::backend::allocator::Fourcc] {
&[
$(
$crate::backend::allocator::Fourcc::$fourcc
),*
]
}
};
}

// FIXME: SRGB format is not always correct.
//
// Vulkan classifies formats by both channel sizes and colorspace. FourCC format codes do not classify formats
// based on colorspace.
//
// To implement this correctly, it is likely that parsing vulkan.xml and classifying families of colorspaces
// would be needed since there are a lot of formats.
//
// Many of these conversions come from wsi_common_wayland.c in Mesa
vk_format_table! {
Argb8888 => B8G8R8A8_SRGB,
Xrgb8888 => B8G8R8A8_SRGB,

Abgr8888 => R8G8B8A8_SRGB,
Xbgr8888 => R8G8B8A8_SRGB,

// PACK32 formats are equivalent to u32 instead of [u8; 4] and thus depend their layout depends the host
// endian.
#[cfg(target_endian = "little")]
Rgba8888 => A8B8G8R8_SRGB_PACK32,
#[cfg(target_endian = "little")]
Rgbx8888 => A8B8G8R8_SRGB_PACK32
}
Loading

0 comments on commit 82308c8

Please sign in to comment.