From bd7d03c98b188f56cf4014bc37325a20bd8092c0 Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Sun, 1 Oct 2023 10:01:17 +1100 Subject: [PATCH] vulkan initialisation --- Cargo.lock | 134 +++++++- gb-emu/Cargo.toml | 23 +- gb-emu/src/renderer/vulkan.rs | 0 gb-emu/src/renderer/vulkan/vulkan.rs | 463 +++++++++++++++++++++++++++ gb-emu/src/window.rs | 2 +- 5 files changed, 613 insertions(+), 9 deletions(-) delete mode 100644 gb-emu/src/renderer/vulkan.rs create mode 100644 gb-emu/src/renderer/vulkan/vulkan.rs diff --git a/Cargo.lock b/Cargo.lock index be066b7..07c5452 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -187,6 +187,14 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "ash" +version = "0.37.0+1.3.260" +source = "git+https://github.com/ash-rs/ash#3f5b96b3638a9ff341584e82188c3ba3aa5cb996" +dependencies = [ + "libloading 0.7.4", +] + [[package]] name = "ash" version = "0.37.3+1.3.251" @@ -196,6 +204,16 @@ dependencies = [ "libloading 0.7.4", ] +[[package]] +name = "ash-window" +version = "0.12.0" +source = "git+https://github.com/ash-rs/ash#3f5b96b3638a9ff341584e82188c3ba3aa5cb996" +dependencies = [ + "ash 0.37.0+1.3.260", + "raw-window-handle", + "raw-window-metal", +] + [[package]] name = "async-ringbuf" version = "0.1.3" @@ -326,6 +344,16 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "block-buffer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" +dependencies = [ + "arrayref", + "byte-tools", +] + [[package]] name = "block-sys" version = "0.1.0-beta.1" @@ -351,6 +379,12 @@ version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +[[package]] +name = "byte-tools" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" + [[package]] name = "bytemuck" version = "1.13.1" @@ -502,6 +536,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + [[package]] name = "cocoa" version = "0.20.2" @@ -888,6 +931,15 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" +[[package]] +name = "digest" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" +dependencies = [ + "generic-array", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -948,6 +1000,18 @@ dependencies = [ "libc", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "fdeflate" version = "0.3.0" @@ -1103,7 +1167,8 @@ dependencies = [ name = "gb-emu" version = "0.3.3" dependencies = [ - "ash", + "ash 0.37.0+1.3.260", + "ash-window", "bytemuck", "clap", "cpal", @@ -1111,8 +1176,10 @@ dependencies = [ "futures", "gb-emu-lib", "gilrs", + "glsl-to-spirv", "nokhwa", "pixels", + "raw-window-handle", "send_wrapper", "winit", "winit_input_helper", @@ -1133,6 +1200,15 @@ dependencies = [ "serde_with", ] +[[package]] +name = "generic-array" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d00328cedcac5e81c683e5620ca6a30756fc23027ebf9bff405c0e8da1fbb7e" +dependencies = [ + "typenum", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -1203,6 +1279,17 @@ dependencies = [ "web-sys", ] +[[package]] +name = "glsl-to-spirv" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28caebc98746d507603a2d3df66dcbe04e41d4febad0320f3eec1ef72b6bbef1" +dependencies = [ + "cmake", + "sha2", + "tempfile", +] + [[package]] name = "goblin" version = "0.6.1" @@ -2411,6 +2498,18 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +[[package]] +name = "raw-window-metal" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed91094d30089fc273de843cfef783f8c04cc75828277a64e0e8dc2a0cebd4dc" +dependencies = [ + "cocoa 0.24.1", + "core-graphics 0.22.3", + "objc", + "raw-window-handle", +] + [[package]] name = "redox_syscall" version = "0.3.5" @@ -2673,6 +2772,18 @@ dependencies = [ "syn 2.0.26", ] +[[package]] +name = "sha2" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" +dependencies = [ + "block-buffer", + "byte-tools", + "digest", + "fake-simd", +] + [[package]] name = "shlex" version = "1.1.0" @@ -2787,6 +2898,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if 1.0.0", + "fastrand", + "redox_syscall", + "rustix 0.38.4", + "windows-sys 0.48.0", +] + [[package]] name = "termcolor" version = "1.2.0" @@ -2920,6 +3044,12 @@ version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a464a4b34948a5f67fddd2b823c62d9d92e44be75058b99939eae6c5b6960b33" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "ultraviolet" version = "0.9.1" @@ -3256,7 +3386,7 @@ checksum = "bdcf61a283adc744bb5453dd88ea91f3f86d5ca6b027661c6c73c7734ae0288b" dependencies = [ "android_system_properties", "arrayvec", - "ash", + "ash 0.37.3+1.3.251", "bit-set", "bitflags 1.3.2", "block", diff --git a/gb-emu/Cargo.toml b/gb-emu/Cargo.toml index cb6d4e1..30091c3 100644 --- a/gb-emu/Cargo.toml +++ b/gb-emu/Cargo.toml @@ -4,10 +4,14 @@ version = "0.3.3" edition = "2021" [features] -# default = ["vulkan"] -default = ["pixels"] -pixels = ["dep:pixels"] -vulkan = ["dep:ash"] +default = ["vulkan"] +pixels = ["dep:pixels", "dep:bytemuck"] +vulkan = [ + "dep:ash", + "dep:ash-window", + "dep:raw-window-handle", + "dep:glsl-to-spirv", +] camera = ["dep:nokhwa", "dep:send_wrapper"] [dependencies] @@ -23,6 +27,13 @@ nokhwa = { version = "0.10.3", features = [ send_wrapper = { version = "0.6.0", optional = true } winit = "0.28" winit_input_helper = "0.14" -bytemuck = "1.13" +bytemuck = { version = "1.13", optional = true } pixels = { version = "0.12", optional = true } -ash = { version = "0.37", optional = true } +ash = { git = "https://github.com/ash-rs/ash", features = [ + "linked", +], optional = true } +ash-window = { git = "https://github.com/ash-rs/ash", optional = true } +raw-window-handle = { version = "0.5", optional = true } + +[build-dependencies] +glsl-to-spirv = { version = "0.1.7", optional = true } diff --git a/gb-emu/src/renderer/vulkan.rs b/gb-emu/src/renderer/vulkan.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-emu/src/renderer/vulkan/vulkan.rs b/gb-emu/src/renderer/vulkan/vulkan.rs new file mode 100644 index 0000000..c3c9628 --- /dev/null +++ b/gb-emu/src/renderer/vulkan/vulkan.rs @@ -0,0 +1,463 @@ +use ash::{ + extensions::khr::{Surface, Swapchain}, + vk, Device, Entry, Instance, +}; +use ash_window::enumerate_required_extensions; +use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; +use winit::window::Window; + +// much of this is lifted from the Ash examples +// https://github.com/ash-rs/ash/blob/master/examples/src/lib.rs +// https://github.com/ash-rs/ash/blob/master/examples/src/bin/texture.rs + +pub struct WindowData { + scale_factor: u32, + + entry: Entry, + instance: Instance, + device: Device, + surface_loader: Surface, + swapchain_loader: Swapchain, + pdevice: vk::PhysicalDevice, + device_memory_properties: vk::PhysicalDeviceMemoryProperties, + queue_family_index: u32, + present_queue: vk::Queue, + + surface: vk::SurfaceKHR, + surface_format: vk::SurfaceFormatKHR, + surface_resolution: vk::Extent2D, + swapchain: vk::SwapchainKHR, + present_images: Vec, + present_image_views: Vec, + + pool: vk::CommandPool, + draw_command_buffer: vk::CommandBuffer, + setup_command_buffer: vk::CommandBuffer, + + depth_image: vk::Image, + depth_image_view: vk::ImageView, + depth_image_memory: vk::DeviceMemory, + + present_complete_semaphore: vk::Semaphore, + rendering_complete_semaphore: vk::Semaphore, + + draw_commands_reuse_fence: vk::Fence, + setup_commands_reuse_fence: vk::Fence, +} + +impl WindowData { + pub fn new(factor: u32, window: &Window) -> Self { + let entry = Entry::linked(); + let name = std::ffi::CString::new("gameboy").unwrap(); + + let mut extension_names = enumerate_required_extensions(window.raw_display_handle()) + .unwrap() + .to_vec(); + + #[cfg(any(target_os = "macos", target_os = "ios"))] + { + extension_names.push(vk::KhrPortabilityEnumerationFn::NAME.as_ptr()); + extension_names.push(vk::KhrGetPhysicalDeviceProperties2Fn::NAME.as_ptr()); + } + + let appinfo = vk::ApplicationInfo::default() + .application_name(&name) + .engine_name(&name) + .application_version(0) + .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_extension_names(&extension_names) + .flags(create_flags); + + let instance = unsafe { entry.create_instance(&create_info, None) }.unwrap(); + + let surface = unsafe { + ash_window::create_surface( + &entry, + &instance, + window.raw_display_handle(), + window.raw_window_handle(), + None, + ) + } + .unwrap(); + let pdevices = + unsafe { instance.enumerate_physical_devices() }.expect("Physical device error"); + let surface_loader = Surface::new(&entry, &instance); + let (pdevice, queue_family_index) = pdevices + .iter() + .find_map(|pdevice| { + unsafe { instance.get_physical_device_queue_family_properties(*pdevice) } + .iter() + .enumerate() + .find_map(|(index, info)| { + let supports_graphic_and_surface = + info.queue_flags.contains(vk::QueueFlags::GRAPHICS) + && unsafe { + surface_loader.get_physical_device_surface_support( + *pdevice, + index as u32, + surface, + ) + } + .unwrap(); + if supports_graphic_and_surface { + Some((*pdevice, index)) + } else { + None + } + }) + }) + .expect("Couldn't find suitable device."); + let queue_family_index = queue_family_index as u32; + let device_extension_names_raw = [ + Swapchain::NAME.as_ptr(), + #[cfg(any(target_os = "macos", target_os = "ios"))] + vk::KhrPortabilitySubsetFn::NAME.as_ptr(), + ]; + let features = vk::PhysicalDeviceFeatures { + shader_clip_distance: 1, + ..Default::default() + }; + let priorities = [1.0]; + + let queue_info = vk::DeviceQueueCreateInfo::default() + .queue_family_index(queue_family_index) + .queue_priorities(&priorities); + + let device_create_info = vk::DeviceCreateInfo::default() + .queue_create_infos(std::slice::from_ref(&queue_info)) + .enabled_extension_names(&device_extension_names_raw) + .enabled_features(&features); + + let device = unsafe { instance.create_device(pdevice, &device_create_info, None) }.unwrap(); + + let present_queue = unsafe { device.get_device_queue(queue_family_index, 0) }; + + let surface_format = + unsafe { surface_loader.get_physical_device_surface_formats(pdevice, surface) } + .unwrap()[0]; + + let surface_capabilities = + unsafe { surface_loader.get_physical_device_surface_capabilities(pdevice, surface) } + .unwrap(); + let mut desired_image_count = surface_capabilities.min_image_count + 1; + if surface_capabilities.max_image_count > 0 + && desired_image_count > surface_capabilities.max_image_count + { + desired_image_count = surface_capabilities.max_image_count; + } + let surface_resolution = match surface_capabilities.current_extent.width { + std::u32::MAX => vk::Extent2D { + width: window.inner_size().width, + height: window.inner_size().height, + }, + _ => surface_capabilities.current_extent, + }; + let pre_transform = if surface_capabilities + .supported_transforms + .contains(vk::SurfaceTransformFlagsKHR::IDENTITY) + { + vk::SurfaceTransformFlagsKHR::IDENTITY + } else { + surface_capabilities.current_transform + }; + let present_modes = + unsafe { surface_loader.get_physical_device_surface_present_modes(pdevice, surface) } + .unwrap(); + let present_mode = present_modes + .iter() + .cloned() + .find(|&mode| mode == vk::PresentModeKHR::MAILBOX) + .unwrap_or(vk::PresentModeKHR::FIFO); + let swapchain_loader = Swapchain::new(&instance, &device); + + let swapchain_create_info = vk::SwapchainCreateInfoKHR::default() + .surface(surface) + .min_image_count(desired_image_count) + .image_color_space(surface_format.color_space) + .image_format(surface_format.format) + .image_extent(surface_resolution) + .image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT) + .image_sharing_mode(vk::SharingMode::EXCLUSIVE) + .pre_transform(pre_transform) + .composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE) + .present_mode(present_mode) + .clipped(true) + .image_array_layers(1); + + let swapchain = + unsafe { swapchain_loader.create_swapchain(&swapchain_create_info, None) }.unwrap(); + + let pool_create_info = vk::CommandPoolCreateInfo::default() + .flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER) + .queue_family_index(queue_family_index); + + let pool = unsafe { device.create_command_pool(&pool_create_info, None).unwrap() }; + + let command_buffer_allocate_info = vk::CommandBufferAllocateInfo::default() + .command_buffer_count(2) + .command_pool(pool) + .level(vk::CommandBufferLevel::PRIMARY); + + let command_buffers = + unsafe { device.allocate_command_buffers(&command_buffer_allocate_info) }.unwrap(); + let setup_command_buffer = command_buffers[0]; + let draw_command_buffer = command_buffers[1]; + + let present_images = unsafe { swapchain_loader.get_swapchain_images(swapchain) }.unwrap(); + let present_image_views: Vec = present_images + .iter() + .map(|&image| { + let create_view_info = vk::ImageViewCreateInfo::default() + .view_type(vk::ImageViewType::TYPE_2D) + .format(surface_format.format) + .components(vk::ComponentMapping { + r: vk::ComponentSwizzle::R, + g: vk::ComponentSwizzle::G, + b: vk::ComponentSwizzle::B, + a: vk::ComponentSwizzle::A, + }) + .subresource_range(vk::ImageSubresourceRange { + aspect_mask: vk::ImageAspectFlags::COLOR, + base_mip_level: 0, + level_count: 1, + base_array_layer: 0, + layer_count: 1, + }) + .image(image); + unsafe { device.create_image_view(&create_view_info, None) }.unwrap() + }) + .collect(); + let device_memory_properties = + unsafe { instance.get_physical_device_memory_properties(pdevice) }; + let depth_image_create_info = vk::ImageCreateInfo::default() + .image_type(vk::ImageType::TYPE_2D) + .format(vk::Format::D16_UNORM) + .extent(surface_resolution.into()) + .mip_levels(1) + .array_layers(1) + .samples(vk::SampleCountFlags::TYPE_1) + .tiling(vk::ImageTiling::OPTIMAL) + .usage(vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT) + .sharing_mode(vk::SharingMode::EXCLUSIVE); + + let depth_image = unsafe { device.create_image(&depth_image_create_info, None) }.unwrap(); + let depth_image_memory_req = unsafe { device.get_image_memory_requirements(depth_image) }; + let depth_image_memory_index = device_memory_properties.memory_types + [..device_memory_properties.memory_type_count as _] + .iter() + .enumerate() + .find(|(index, memory_type)| { + (1 << index) & depth_image_memory_req.memory_type_bits != 0 + && memory_type.property_flags & vk::MemoryPropertyFlags::DEVICE_LOCAL + == vk::MemoryPropertyFlags::DEVICE_LOCAL + }) + .map(|(index, _memory_type)| index as _) + .expect("Unable to find suitable memory index for depth image."); + + let depth_image_allocate_info = vk::MemoryAllocateInfo::default() + .allocation_size(depth_image_memory_req.size) + .memory_type_index(depth_image_memory_index); + + let depth_image_memory = + unsafe { device.allocate_memory(&depth_image_allocate_info, None) }.unwrap(); + + unsafe { device.bind_image_memory(depth_image, depth_image_memory, 0) } + .expect("Unable to bind depth image memory"); + + let fence_create_info = + vk::FenceCreateInfo::default().flags(vk::FenceCreateFlags::SIGNALED); + + let draw_commands_reuse_fence = + unsafe { device.create_fence(&fence_create_info, None) }.expect("Create fence failed."); + let setup_commands_reuse_fence = + unsafe { device.create_fence(&fence_create_info, None) }.expect("Create fence failed."); + + record_submit_commandbuffer( + &device, + setup_command_buffer, + setup_commands_reuse_fence, + present_queue, + &[], + &[], + &[], + |device, setup_command_buffer| { + let layout_transition_barriers = vk::ImageMemoryBarrier::default() + .image(depth_image) + .dst_access_mask( + vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ + | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, + ) + .new_layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + .old_layout(vk::ImageLayout::UNDEFINED) + .subresource_range( + vk::ImageSubresourceRange::default() + .aspect_mask(vk::ImageAspectFlags::DEPTH) + .layer_count(1) + .level_count(1), + ); + + unsafe { + device.cmd_pipeline_barrier( + setup_command_buffer, + vk::PipelineStageFlags::BOTTOM_OF_PIPE, + vk::PipelineStageFlags::LATE_FRAGMENT_TESTS, + vk::DependencyFlags::empty(), + &[], + &[], + &[layout_transition_barriers], + ); + } + }, + ); + + let depth_image_view_info = vk::ImageViewCreateInfo::default() + .subresource_range( + vk::ImageSubresourceRange::default() + .aspect_mask(vk::ImageAspectFlags::DEPTH) + .level_count(1) + .layer_count(1), + ) + .image(depth_image) + .format(depth_image_create_info.format) + .view_type(vk::ImageViewType::TYPE_2D); + + let depth_image_view = + unsafe { device.create_image_view(&depth_image_view_info, None) }.unwrap(); + + let semaphore_create_info = vk::SemaphoreCreateInfo::default(); + + let present_complete_semaphore = + unsafe { device.create_semaphore(&semaphore_create_info, None) }.unwrap(); + let rendering_complete_semaphore = + unsafe { device.create_semaphore(&semaphore_create_info, None) }.unwrap(); + + Self { + scale_factor: factor, + entry, + instance, + device, + surface_loader, + swapchain_loader, + pdevice, + device_memory_properties, + queue_family_index, + present_queue, + surface, + surface_format, + surface_resolution, + swapchain, + present_images, + present_image_views, + pool, + draw_command_buffer, + setup_command_buffer, + depth_image, + depth_image_view, + depth_image_memory, + present_complete_semaphore, + rendering_complete_semaphore, + draw_commands_reuse_fence, + setup_commands_reuse_fence, + } + } + + pub fn resize(&mut self, _width: u32, _height: u32, factor: u32, window: &Window) { + *self = Self::new(factor, window); + } + + pub fn new_frame(&mut self, buffer: &[[u8; 4]]) {} + + pub fn render(&mut self) {} +} + +impl Drop for WindowData { + fn drop(&mut self) { + unsafe { + self.device.device_wait_idle().unwrap(); + self.device + .destroy_semaphore(self.present_complete_semaphore, None); + self.device + .destroy_semaphore(self.rendering_complete_semaphore, None); + self.device + .destroy_fence(self.draw_commands_reuse_fence, None); + self.device + .destroy_fence(self.setup_commands_reuse_fence, None); + self.device.free_memory(self.depth_image_memory, None); + self.device.destroy_image_view(self.depth_image_view, None); + self.device.destroy_image(self.depth_image, None); + for &image_view in self.present_image_views.iter() { + self.device.destroy_image_view(image_view, None); + } + self.device.destroy_command_pool(self.pool, None); + self.swapchain_loader + .destroy_swapchain(self.swapchain, None); + self.device.destroy_device(None); + self.surface_loader.destroy_surface(self.surface, None); + self.instance.destroy_instance(None); + } + } +} + +#[allow(clippy::too_many_arguments)] +pub fn record_submit_commandbuffer( + device: &Device, + command_buffer: vk::CommandBuffer, + command_buffer_reuse_fence: vk::Fence, + submit_queue: vk::Queue, + wait_mask: &[vk::PipelineStageFlags], + wait_semaphores: &[vk::Semaphore], + signal_semaphores: &[vk::Semaphore], + f: F, +) { + + unsafe { + device + .wait_for_fences(&[command_buffer_reuse_fence], true, std::u64::MAX) + .expect("Wait for fence failed."); + + device + .reset_fences(&[command_buffer_reuse_fence]) + .expect("Reset fences failed."); + + device + .reset_command_buffer( + command_buffer, + vk::CommandBufferResetFlags::RELEASE_RESOURCES, + ) + .expect("Reset command buffer failed."); + + let command_buffer_begin_info = vk::CommandBufferBeginInfo::default() + .flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT); + + device + .begin_command_buffer(command_buffer, &command_buffer_begin_info) + .expect("Begin commandbuffer"); + f(device, command_buffer); + device + .end_command_buffer(command_buffer) + .expect("End commandbuffer"); + + let command_buffers = vec![command_buffer]; + + let submit_info = vk::SubmitInfo::default() + .wait_semaphores(wait_semaphores) + .wait_dst_stage_mask(wait_mask) + .command_buffers(&command_buffers) + .signal_semaphores(signal_semaphores); + + device + .queue_submit(submit_queue, &[submit_info], command_buffer_reuse_fence) + .expect("queue submit failed."); + } +} diff --git a/gb-emu/src/window.rs b/gb-emu/src/window.rs index 63866ff..c465bd8 100644 --- a/gb-emu/src/window.rs +++ b/gb-emu/src/window.rs @@ -18,7 +18,7 @@ use winit::{ use winit_input_helper::WinitInputHelper; #[cfg_attr(feature = "pixels", path = "renderer/pixels.rs")] -#[cfg_attr(feature = "vulkan", path = "renderer/vulkan.rs")] +#[cfg_attr(feature = "vulkan", path = "renderer/vulkan/vulkan.rs")] mod renderer; use renderer::WindowData;