initial vulkan init stuff.
This commit is contained in:
commit
386b531adc
5 changed files with 770 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/target
|
||||
417
Cargo.lock
generated
Normal file
417
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,417 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "ash"
|
||||
version = "0.38.0+1.3.281"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f"
|
||||
dependencies = [
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ash-window"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52bca67b61cb81e5553babde81b8211f713cb6db79766f80168f3e5f40ea6c82"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"raw-window-handle 0.6.2",
|
||||
"raw-window-metal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cocoa"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"block",
|
||||
"cocoa-foundation",
|
||||
"core-foundation",
|
||||
"core-graphics",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa-foundation"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"block",
|
||||
"core-foundation",
|
||||
"core-graphics-types",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"core-graphics-types",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics-types"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlib"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a"
|
||||
dependencies = [
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "downcast-rs"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
|
||||
dependencies = [
|
||||
"foreign-types-macros",
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-macros"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.186"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.39.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-metal"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76e8caa82e31bb98fee12fa8f051c94a6aa36b07cddb03f0d4fc558988360ff1"
|
||||
dependencies = [
|
||||
"cocoa",
|
||||
"core-graphics",
|
||||
"objc",
|
||||
"raw-window-handle 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
||||
dependencies = [
|
||||
"bitflags 2.13.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "wayland-backend"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"downcast-rs",
|
||||
"raw-window-handle 0.5.2",
|
||||
"rustix",
|
||||
"scoped-tls",
|
||||
"smallvec",
|
||||
"wayland-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-client"
|
||||
version = "0.31.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144"
|
||||
dependencies = [
|
||||
"bitflags 2.13.0",
|
||||
"rustix",
|
||||
"wayland-backend",
|
||||
"wayland-scanner",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-scanner"
|
||||
version = "0.31.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quick-xml",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-sys"
|
||||
version = "0.31.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be"
|
||||
dependencies = [
|
||||
"dlib",
|
||||
"log",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "workshop-or-town-or-someshit"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"ash-window",
|
||||
"raw-window-handle 0.6.2",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
]
|
||||
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "workshop-or-town-or-someshit"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
ash = { version = "0.38.0", features = ["linked"] }
|
||||
ash-window = "0.13.0"
|
||||
raw-window-handle = "0.6.2"
|
||||
wayland-backend = { version = "0.3.15", features = ["client_system", "raw-window-handle"] }
|
||||
wayland-client = "0.31.14"
|
||||
230
src/main.rs
Normal file
230
src/main.rs
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
use std::{ffi::{CStr, c_void}, ptr::NonNull};
|
||||
|
||||
use ash::{Entry, Instance, khr, vk::{self, DeviceQueueCreateInfo, PhysicalDevice, PhysicalDeviceFeatures, PhysicalDeviceMemoryProperties, PhysicalDeviceProperties, PresentModeKHR, QueueFamilyProperties, SurfaceCapabilitiesKHR, SurfaceFormatKHR, SurfaceKHR}};
|
||||
use raw_window_handle::{RawDisplayHandle, RawWindowHandle, WaylandDisplayHandle, WaylandWindowHandle};
|
||||
use wayland_client::Proxy;
|
||||
|
||||
use crate::wayland::{bind_compositor, connect_to_wayland, create_surface};
|
||||
|
||||
mod wayland;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct PhysicalDeviceDetail {
|
||||
properties: PhysicalDeviceProperties,
|
||||
features: PhysicalDeviceFeatures,
|
||||
memory_properties: PhysicalDeviceMemoryProperties,
|
||||
queue_family_properties: Vec<(QueueFamilyProperties, bool)>,
|
||||
surface_capabilities: SurfaceCapabilitiesKHR,
|
||||
surface_formats: Vec<SurfaceFormatKHR>,
|
||||
surface_present_modes: Vec<PresentModeKHR>,
|
||||
}
|
||||
|
||||
impl PhysicalDeviceDetail {
|
||||
fn enumerate(instance: &ash::Instance, surface_loader: &khr::surface::Instance, surface: SurfaceKHR) -> (Vec<PhysicalDevice>, Vec<PhysicalDeviceDetail>) {
|
||||
let pds = unsafe { instance.enumerate_physical_devices().expect("Failed to enumerate physical devices") };
|
||||
pds.iter().map(|pd| (*pd, PhysicalDeviceDetail {
|
||||
properties: unsafe { instance.get_physical_device_properties(*pd) },
|
||||
features: unsafe { instance.get_physical_device_features(*pd) },
|
||||
memory_properties: unsafe { instance.get_physical_device_memory_properties(*pd) },
|
||||
queue_family_properties: unsafe { instance.get_physical_device_queue_family_properties(*pd).into_iter().enumerate().map(|(qfi,qfp)| (qfp,
|
||||
surface_loader.get_physical_device_surface_support(*pd, qfi as u32, surface).expect("Failed to get physical device surface support")
|
||||
) ).collect::<Vec<_>>() },
|
||||
surface_capabilities: unsafe { surface_loader.get_physical_device_surface_capabilities(*pd, surface).expect("Failed to get physical device surface support") },
|
||||
surface_formats: unsafe { surface_loader.get_physical_device_surface_formats(*pd, surface).expect("Failed to get physical device surface formats") },
|
||||
surface_present_modes: unsafe { surface_loader.get_physical_device_surface_present_modes(*pd, surface).expect("Failed to get physical device surface formats") },
|
||||
})).collect()
|
||||
}
|
||||
}
|
||||
|
||||
struct DeviceQueuesToCreate {
|
||||
queues: Vec<(u32, Vec<f32>)>, //family index, one priority per queue
|
||||
}
|
||||
|
||||
struct QueueFamilySelection {
|
||||
graphics: u32,
|
||||
present: u32,
|
||||
}
|
||||
|
||||
impl DeviceQueuesToCreate {
|
||||
fn for_families(families: &QueueFamilySelection) -> DeviceQueuesToCreate {
|
||||
//Vulkan rejects a queue family index appearing twice in DeviceCreateInfo.
|
||||
let mut indices = vec![families.graphics];
|
||||
if families.present != families.graphics {
|
||||
indices.push(families.present);
|
||||
}
|
||||
|
||||
DeviceQueuesToCreate {
|
||||
queues: indices.into_iter().map(|family| (family, vec![1.0])).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
//The returned infos point into self.queues, so they must not outlive it.
|
||||
fn create_infos(&self) -> Vec<DeviceQueueCreateInfo<'_>> {
|
||||
self.queues.iter().map(|q| vk::DeviceQueueCreateInfo {
|
||||
queue_family_index: q.0,
|
||||
queue_count: q.1.len() as u32,
|
||||
p_queue_priorities: q.1.as_slice().as_ptr(),
|
||||
..Default::default()
|
||||
}
|
||||
).collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let (mut wayland_state, mut event_queue) = connect_to_wayland().unwrap();
|
||||
bind_compositor(&mut wayland_state).unwrap();
|
||||
create_surface(&mut wayland_state).unwrap();
|
||||
|
||||
let entry = Entry::linked();
|
||||
|
||||
let display_handle = RawDisplayHandle::Wayland(WaylandDisplayHandle::new(NonNull::new(wayland_state.connection.backend().display_ptr() as *mut c_void).unwrap()));
|
||||
let mut instance_extensions = ash_window::enumerate_required_extensions(display_handle).expect("Failed to enumerate required instance extensions for surface").to_vec();
|
||||
|
||||
let application_name = c"Workshop or Town or Someshit";
|
||||
let engine_name = c"SomeShit Engine";
|
||||
|
||||
let instance = construct_instance(&entry, &mut instance_extensions, application_name, engine_name).unwrap();
|
||||
|
||||
let surface = construct_surface(&mut wayland_state, &entry, &instance).unwrap();
|
||||
let surface_loader = khr::surface::Instance::new(&entry, &instance);
|
||||
|
||||
let (pds, pds_detail) = PhysicalDeviceDetail::enumerate(&instance, &surface_loader, surface);
|
||||
|
||||
println!("{} physical devices.", pds.len());
|
||||
|
||||
//Now we sort through the physical devices to find one that suits.
|
||||
let (chosen_device, chosen_device_queues, chosen_device_detail) =
|
||||
choose_physical_device(&pds, &pds_detail).expect("No suitable physical device");
|
||||
|
||||
let queue_create_infos = chosen_device_queues.create_infos();
|
||||
|
||||
let enabled_extension_names = vec!(c"VK_KHR_swapchain".as_ptr());
|
||||
|
||||
let device_create_info = vk::DeviceCreateInfo {
|
||||
queue_create_info_count: queue_create_infos.len() as u32,
|
||||
p_queue_create_infos: queue_create_infos.as_ptr(),
|
||||
..Default::default()
|
||||
}.enabled_extension_names(&enabled_extension_names);
|
||||
|
||||
let device = unsafe { instance.create_device(chosen_device, &device_create_info, None).expect("failed to create device") };
|
||||
|
||||
// Ok, we have a device now. Finally.
|
||||
// What now?
|
||||
}
|
||||
|
||||
fn construct_instance(entry: &Entry, extensions: &mut Vec<*const i8>, application_name: &CStr, engine_name: &CStr) -> Result<Instance,String> {
|
||||
|
||||
for extension in [c"VK_KHR_display"] {
|
||||
//For each extension that I know I want.
|
||||
|
||||
//Check if it's already in the list
|
||||
if extensions.iter().find(|ext| extension.eq(unsafe {CStr::from_ptr(**ext)})).is_none() {
|
||||
extensions.push(extension.as_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
let app_info = vk::ApplicationInfo {
|
||||
api_version: vk::make_api_version(0, 1, 0, 0),
|
||||
application_version: 1,
|
||||
engine_version: 1,
|
||||
.. Default::default()
|
||||
}.application_name(application_name)
|
||||
.engine_name(engine_name);
|
||||
|
||||
let layers = debug_layers(entry);
|
||||
|
||||
let instance_create_info = vk::InstanceCreateInfo {
|
||||
p_application_info: &app_info,
|
||||
..Default::default()
|
||||
}.enabled_extension_names(extensions.as_slice())
|
||||
.enabled_layer_names(layers.as_slice());
|
||||
|
||||
Ok(unsafe { entry.create_instance(&instance_create_info, None)
|
||||
.expect("failed to create instance")
|
||||
})
|
||||
}
|
||||
|
||||
//Validation reports spec violations to stderr. Debug builds only: it costs
|
||||
//real performance, and a release machine may not have the layer installed.
|
||||
fn debug_layers(entry: &Entry) -> Vec<*const i8> {
|
||||
if !cfg!(debug_assertions) {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let validation = c"VK_LAYER_KHRONOS_validation";
|
||||
let available = unsafe { entry.enumerate_instance_layer_properties() }
|
||||
.expect("Failed to enumerate instance layers");
|
||||
|
||||
if available.iter().any(|l| l.layer_name_as_c_str() == Ok(validation)) {
|
||||
vec![validation.as_ptr()]
|
||||
} else {
|
||||
eprintln!("{validation:?} not installed; running without validation");
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn construct_surface(wayland_state: &mut wayland::WaylandState, entry: &Entry, instance: &Instance) -> Result<SurfaceKHR, String> {
|
||||
|
||||
let surface_ptr = wayland_state.surface.as_ref().unwrap().id().as_ptr() as *mut c_void;
|
||||
let window_handle = RawWindowHandle::Wayland(
|
||||
WaylandWindowHandle::new(NonNull::new(surface_ptr).unwrap()),
|
||||
);
|
||||
|
||||
let display_handle = RawDisplayHandle::Wayland(WaylandDisplayHandle::new(NonNull::new(wayland_state.connection.backend().display_ptr() as *mut c_void).unwrap()));
|
||||
|
||||
Ok(unsafe { ash_window::create_surface(entry, instance, display_handle, window_handle, None)
|
||||
.expect("Failed to create surface")
|
||||
})
|
||||
}
|
||||
|
||||
fn select_queue_families(detail: &PhysicalDeviceDetail) -> Option<QueueFamilySelection> {
|
||||
let graphics_families = || {
|
||||
detail
|
||||
.queue_family_properties
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, (qfp, _))| qfp.queue_flags.contains(vk::QueueFlags::GRAPHICS))
|
||||
};
|
||||
|
||||
//One family that can do both is preferable, so look for that first.
|
||||
if let Some((both, _)) = graphics_families().find(|(_, (_, present))| *present) {
|
||||
return Some(QueueFamilySelection { graphics: both as u32, present: both as u32 });
|
||||
}
|
||||
|
||||
let (graphics, _) = graphics_families().next()?;
|
||||
let (present, _) = detail
|
||||
.queue_family_properties
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, (_, present))| *present)?;
|
||||
|
||||
Some(QueueFamilySelection { graphics: graphics as u32, present: present as u32 })
|
||||
}
|
||||
|
||||
fn choose_physical_device(
|
||||
pds: &[PhysicalDevice],
|
||||
details: &[PhysicalDeviceDetail],
|
||||
) -> Option<(PhysicalDevice, DeviceQueuesToCreate, PhysicalDeviceDetail)> {
|
||||
let (pd, detail, families) = pds
|
||||
.iter()
|
||||
.zip(details)
|
||||
.filter(|(_, detail)| {
|
||||
!detail.surface_formats.is_empty() && !detail.surface_present_modes.is_empty()
|
||||
})
|
||||
.filter_map(|(pd, detail)| {
|
||||
select_queue_families(detail).map(|families| (pd, detail, families))
|
||||
})
|
||||
.max_by_key(|(_, detail, families)| {
|
||||
let device_type = match detail.properties.device_type {
|
||||
vk::PhysicalDeviceType::DISCRETE_GPU => 3,
|
||||
vk::PhysicalDeviceType::INTEGRATED_GPU => 2,
|
||||
vk::PhysicalDeviceType::VIRTUAL_GPU => 1,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
(device_type, families.graphics == families.present)
|
||||
})?;
|
||||
|
||||
Some((*pd, DeviceQueuesToCreate::for_families(&families), detail.clone()))
|
||||
}
|
||||
111
src/wayland.rs
Normal file
111
src/wayland.rs
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
use wayland_client::{ConnectError, Connection, Dispatch, EventQueue, QueueHandle, protocol::{wl_compositor::WlCompositor, wl_display::WlDisplay, wl_registry::{self, WlRegistry}, wl_surface::{self, WlSurface}}};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum WaylandError {
|
||||
Connect(ConnectError)
|
||||
}
|
||||
|
||||
pub type WaylandResult<T> = Result<T, WaylandError>;
|
||||
|
||||
pub struct WaylandState {
|
||||
pub connection: Connection,
|
||||
pub display: WlDisplay,
|
||||
pub queue_handle: QueueHandle<WaylandState>,
|
||||
pub registry: WlRegistry,
|
||||
pub globals: Vec<(u32, String, u32)>, //name, interface, version
|
||||
pub compositor: Option<WlCompositor>,
|
||||
pub surface: Option<WlSurface>,
|
||||
}
|
||||
|
||||
|
||||
impl Dispatch<WlRegistry, ()> for WaylandState {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
_: &WlRegistry,
|
||||
event: wl_registry::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<WaylandState>,
|
||||
) {
|
||||
// When receiving events from the wl_registry, we are only interested in the
|
||||
// `global` event, which signals a new available global.
|
||||
// When receiving this event, we just print its characteristics in this example.
|
||||
if let wl_registry::Event::Global { name, interface, version } = event {
|
||||
println!("[{}] {} (v{})", name, interface, version);
|
||||
state.globals.push((name, interface, version))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<WlCompositor, ()> for WaylandState {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
_: &WlCompositor,
|
||||
_: <WlCompositor as wayland_client::Proxy>::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
//wl_compositor declares no events, so this can never be called.
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<WlSurface, ()> for WaylandState {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
_: &WlSurface,
|
||||
event: <WlSurface as wayland_client::Proxy>::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
match event {
|
||||
//Which outputs we're on. Needed once we care about per-monitor scale.
|
||||
wl_surface::Event::Enter { .. } | wl_surface::Event::Leave { .. } => {}
|
||||
//Only sent on wl_surface v6+, which we don't bind yet.
|
||||
wl_surface::Event::PreferredBufferScale { .. }
|
||||
| wl_surface::Event::PreferredBufferTransform { .. } => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn connect_to_wayland() -> WaylandResult<(WaylandState, EventQueue<WaylandState>)> {
|
||||
let connection = Connection::connect_to_env().map_err(WaylandError::Connect)?;
|
||||
let display = connection.display();
|
||||
let mut event_queue = connection.new_event_queue();
|
||||
let queue_handle = event_queue.handle();
|
||||
let registry = display.get_registry(&queue_handle, ());
|
||||
println!("Advertised globals:");
|
||||
|
||||
let mut state = WaylandState {
|
||||
connection,
|
||||
display,
|
||||
queue_handle,
|
||||
registry,
|
||||
globals: Vec::new(),
|
||||
compositor: None,
|
||||
surface: None,
|
||||
};
|
||||
|
||||
event_queue.roundtrip(&mut state).unwrap();
|
||||
|
||||
Ok((state, event_queue))
|
||||
}
|
||||
|
||||
pub fn bind_compositor(state: &mut WaylandState) -> WaylandResult<()> {
|
||||
let (name, _, version) = state.globals
|
||||
.iter()
|
||||
.find(|(_, interface, _)| interface == "wl_compositor")
|
||||
.expect("compositor not advertised");
|
||||
|
||||
state.compositor = Some(state.registry.bind::<WlCompositor, _, _>(*name, (*version).min(6), &state.queue_handle, ()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn create_surface(state: &mut WaylandState) -> WaylandResult<()> {
|
||||
state.surface = Some(if let Some(ref comp) = state.compositor {comp.create_surface(&state.queue_handle, ())} else { panic!("compositor not bound")});
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Reference in a new issue