From 9223b89e4ef9aa9bc0207b29aac499c970f02602 Mon Sep 17 00:00:00 2001 From: Florian RICHER Date: Wed, 6 Nov 2024 22:13:46 +0100 Subject: [PATCH] Add VkInstance --- Cargo.lock | 3 - Cargo.toml | 4 +- flake.lock | 148 +++++++++++++++----------------------- flake.nix | 74 ++++++++++++------- src/display/app.rs | 51 +++++++++++++ src/display/mod.rs | 2 + src/main.rs | 11 ++- src/vulkan/mod.rs | 2 + src/vulkan/vk_instance.rs | 64 +++++++++++++++++ 9 files changed, 237 insertions(+), 122 deletions(-) create mode 100644 src/display/app.rs create mode 100644 src/display/mod.rs create mode 100644 src/vulkan/mod.rs create mode 100644 src/vulkan/vk_instance.rs diff --git a/Cargo.lock b/Cargo.lock index 823a3ad..d729efb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,9 +81,6 @@ 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" diff --git a/Cargo.toml b/Cargo.toml index a64c682..e765a81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,6 @@ authors = ["Florian RICHER "] publish = false [dependencies] -winit = { version = "0.30" } -ash = { version = "0.38", features = ["linked", "debug", "std"] } +winit = { version = "0.30", features = [ "rwh_06" ] } +ash = { version = "0.38", default-features = false, features = ["linked", "debug", "std"] } ash-window = "0.13" \ No newline at end of file diff --git a/flake.lock b/flake.lock index fda0215..bc5b28e 100644 --- a/flake.lock +++ b/flake.lock @@ -1,94 +1,6 @@ { "nodes": { - "naersk": { - "inputs": { - "nixpkgs": "nixpkgs" - }, - "locked": { - "lastModified": 1721727458, - "narHash": "sha256-r/xppY958gmZ4oTfLiHN0ZGuQ+RSTijDblVgVLFi1mw=", - "owner": "nix-community", - "repo": "naersk", - "rev": "3fb418eaf352498f6b6c30592e3beb63df42ef11", - "type": "github" - }, - "original": { - "owner": "nix-community", - "ref": "master", - "repo": "naersk", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1730831018, - "narHash": "sha256-2S0HwIFRxYp+afuoFORcZA9TjryAf512GmE0MTfEOPU=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "8c4dc69b9732f6bbe826b5fbb32184987520ff26", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, - "nixpkgs-mozilla": { - "flake": false, - "locked": { - "lastModified": 1704373101, - "narHash": "sha256-+gi59LRWRQmwROrmE1E2b3mtocwueCQqZ60CwLG+gbg=", - "owner": "mozilla", - "repo": "nixpkgs-mozilla", - "rev": "9b11a87c0cc54e308fa83aac5b4ee1816d5418a2", - "type": "github" - }, - "original": { - "owner": "mozilla", - "repo": "nixpkgs-mozilla", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1730831018, - "narHash": "sha256-2S0HwIFRxYp+afuoFORcZA9TjryAf512GmE0MTfEOPU=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "8c4dc69b9732f6bbe826b5fbb32184987520ff26", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "naersk": "naersk", - "nixpkgs": "nixpkgs_2", - "nixpkgs-mozilla": "nixpkgs-mozilla", - "utils": "utils" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "utils": { + "flake-utils": { "inputs": { "systems": "systems" }, @@ -105,6 +17,64 @@ "repo": "flake-utils", "type": "github" } + }, + "nixpkgs": { + "locked": { + "lastModified": 1730831018, + "narHash": "sha256-2S0HwIFRxYp+afuoFORcZA9TjryAf512GmE0MTfEOPU=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "8c4dc69b9732f6bbe826b5fbb32184987520ff26", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1730860036, + "narHash": "sha256-u0sfA4B65Q9cRO3xpIkQ4nldB8isfdIb3rWtsnRZ+Iw=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "b8eb3aeb21629cbe14968a5e3b1cbaefb0d1b260", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 40cf2c1..e8506cf 100644 --- a/flake.nix +++ b/flake.nix @@ -1,41 +1,61 @@ { - inputs = { - naersk.url = "github:nix-community/naersk/master"; - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - utils.url = "github:numtide/flake-utils"; + description = "Rust ASH test rust configuration"; - nixpkgs-mozilla = { - url = "github:mozilla/nixpkgs-mozilla"; - flake = false; + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; }; }; - outputs = { self, nixpkgs, utils, naersk, nixpkgs-mozilla }: - utils.lib.eachDefaultSystem (system: + outputs = { self, nixpkgs, flake-utils, rust-overlay }: + flake-utils.lib.eachSystem flake-utils.lib.allSystems (system: let + overlays = [ (import rust-overlay) ]; pkgs = import nixpkgs { - inherit system; - overlays = [ - (import nixpkgs-mozilla) - ]; + inherit system overlays; }; + rust = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; - toolchain = (pkgs.rustChannelOf { - rustToolchain = ./rust-toolchain.toml; - sha256 = "sha256-yMuSb5eQPO/bHv+Bcf/US8LVMbf/G/0MSfiPwBhiPpk="; - }).rust; - - naersk-lib = pkgs.callPackage naersk { - cargo = toolchain; - rustc = toolchain; - }; + rustPlatform = pkgs.recurseIntoAttrs (pkgs.makeRustPlatform { + rustc = rust; + cargo = rust; + }); + + libs = with pkgs; [ vulkan-headers vulkan-loader ] + ++ pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux (with pkgs; [ libxkbcommon wayland libGL ]) + ++ pkgs.lib.optionals pkgs.stdenv.hostPlatform.isDarwin (with pkgs; [ darwin.apple_sdk.frameworks.SystemConfiguration ]); in { - defaultPackage = naersk-lib.buildPackage ./.; + devShells = { + default = pkgs.mkShell { + nativeBuildInputs = with pkgs; [ + (rust.override { extensions = ["rust-src" "rust-analyzer"]; }) + pkg-config + ]; - devShell = pkgs.mkShell { - nativeBuildInputs = [ toolchain ]; + buildInputs = libs; + + LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath (with pkgs; [ libxkbcommon wayland libGL ]); + }; }; - } - ); + + packages = { + default = rustPlatform.buildRustPackage { + pname = "rust_ash_test"; + version = "0.1.0"; + + src = self; + + nativeBuildInputs = with pkgs; [ pkg-config ]; + buildInputs = libs; + + cargoLock = { + lockFile = ./Cargo.lock; + }; + }; + }; + }); } diff --git a/src/display/app.rs b/src/display/app.rs new file mode 100644 index 0000000..e7270ab --- /dev/null +++ b/src/display/app.rs @@ -0,0 +1,51 @@ +use winit::{ + application::ApplicationHandler, event::WindowEvent, event_loop::ActiveEventLoop, raw_window_handle::{HasDisplayHandle, DisplayHandle, HandleError}, window::{Window, WindowId} +}; +use crate::vulkan::VkInstance; + +#[derive(Default)] +pub struct App { + window: Option, + instance: Option, +} + +impl HasDisplayHandle for App { + fn display_handle(&self) -> Result, HandleError> { + self.window.as_ref() + .ok_or_else(|| HandleError::Unavailable)? + .display_handle() + } +} + +impl ApplicationHandler for App { + fn resumed(&mut self, event_loop: &ActiveEventLoop) { + let window_attributes = Window::default_attributes() + .with_title("Rust ASH Test") + .with_visible(true) + .with_inner_size(winit::dpi::LogicalSize::new( + f64::from(800), + f64::from(600), + )); + + self.window = event_loop + .create_window(window_attributes) + .ok(); + + self.instance = self.window + .as_ref() + .and_then(|w| Some(VkInstance::new(w))); + } + + fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) { + match event { + WindowEvent::CloseRequested => { + println!("The close button was pressed; stopping"); + event_loop.exit(); + } + WindowEvent::RedrawRequested => { + self.window.as_ref().unwrap().request_redraw(); + } + _ => (), + } + } +} diff --git a/src/display/mod.rs b/src/display/mod.rs new file mode 100644 index 0000000..dc5ff07 --- /dev/null +++ b/src/display/mod.rs @@ -0,0 +1,2 @@ +mod app; +pub use app::App; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index e7a11a9..7e8cde1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,12 @@ +use winit::event_loop::EventLoop; + +mod display; +mod vulkan; + fn main() { - println!("Hello, world!"); + let event_loop = EventLoop::new().unwrap(); + + let mut app = display::App::default(); + + let _ = event_loop.run_app(&mut app); } diff --git a/src/vulkan/mod.rs b/src/vulkan/mod.rs new file mode 100644 index 0000000..ef95c25 --- /dev/null +++ b/src/vulkan/mod.rs @@ -0,0 +1,2 @@ +mod vk_instance; +pub use vk_instance::VkInstance; \ No newline at end of file diff --git a/src/vulkan/vk_instance.rs b/src/vulkan/vk_instance.rs new file mode 100644 index 0000000..bf96269 --- /dev/null +++ b/src/vulkan/vk_instance.rs @@ -0,0 +1,64 @@ +use std::ffi; +use std::ffi::c_char; +use ash::{Instance, vk, Entry}; +use winit::raw_window_handle::{HasDisplayHandle}; + +pub struct VkInstance { + instance: Instance +} + +impl VkInstance { + pub fn new(window: &impl HasDisplayHandle) -> Self { + let entry = Entry::linked(); + let app_name = unsafe { ffi::CStr::from_bytes_with_nul_unchecked(b"VulkanTriangle\0") }; + + let layer_names = [ + unsafe { ffi::CStr::from_bytes_with_nul_unchecked(b"VK_LAYER_KHRONOS_validation\0") } + ]; + let layers_names_raw: Vec<*const c_char> = layer_names + .iter() + .map(|raw_name| raw_name.as_ptr()) + .collect(); + + let mut extension_names = + ash_window::enumerate_required_extensions(window.display_handle().expect("No display handle").as_raw()) + .unwrap() + .to_vec(); + + #[cfg(any(target_os = "macos", target_os = "ios"))] + { + extension_names.push(ash::khr::portability_enumeration::NAME.as_ptr()); + // Enabling this extension is a requirement when using `VK_KHR_portability_subset` + extension_names.push(ash::khr::get_physical_device_properties2::NAME.as_ptr()); + } + + let appinfo = vk::ApplicationInfo::default() + .application_name(app_name) + .application_version(0) + .engine_name(app_name) + .engine_version(0) + .api_version(vk::make_api_version(0, 1, 0, 0)); + + let create_flags = if cfg!(any(target_os = "macos", target_os = "ios")) { + vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR + } else { + vk::InstanceCreateFlags::default() + }; + + let create_info = vk::InstanceCreateInfo::default() + .application_info(&appinfo) + .enabled_layer_names(&layers_names_raw) + .enabled_extension_names(&extension_names) + .flags(create_flags); + + let instance: Instance = unsafe { + entry + .create_instance(&create_info, None) + .expect("Instance creation error") + }; + + Self { + instance + } + } +} \ No newline at end of file