From 5419947095853ee3b91c04f74f0e4193d0d061a8 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 16 Jul 2021 01:27:30 -0400 Subject: [PATCH] hal/vk: relay semaphore --- wgpu-core/src/device/mod.rs | 2 +- wgpu-hal/examples/halmark/main.rs | 3 +- wgpu-hal/src/dx12/device.rs | 3 +- wgpu-hal/src/empty.rs | 2 +- wgpu-hal/src/gles/device.rs | 5 +++- wgpu-hal/src/lib.rs | 2 +- wgpu-hal/src/metal/device.rs | 2 +- wgpu-hal/src/vulkan/adapter.rs | 4 +++ wgpu-hal/src/vulkan/device.rs | 5 +++- wgpu-hal/src/vulkan/mod.rs | 47 +++++++++++++++++++++++-------- 10 files changed, 55 insertions(+), 20 deletions(-) diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index d554353ad5..1fd38bb342 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -2446,7 +2446,7 @@ impl Device { self.command_allocator.into_inner().dispose(&self.raw); unsafe { self.raw.destroy_fence(self.fence); - self.raw.exit(); + self.raw.exit(self.queue); } } } diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index 9e762bb3a8..10c47a96e8 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -518,10 +518,9 @@ impl Example { self.device.destroy_pipeline_layout(self.pipeline_layout); self.surface.unconfigure(&self.device); - self.device.exit(); + self.device.exit(self.queue); self.instance.destroy_surface(self.surface); drop(self.adapter); - drop(self.queue); } } diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 27e3b37bbb..731c8a3deb 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -592,13 +592,14 @@ impl super::Device { } impl crate::Device for super::Device { - unsafe fn exit(self) { + unsafe fn exit(self, queue: super::Queue) { self.rtv_pool.into_inner().destroy(); self.dsv_pool.into_inner().destroy(); self.srv_uav_pool.into_inner().destroy(); self.sampler_pool.into_inner().destroy(); self.shared.destroy(); self.idler.destroy(); + queue.raw.destroy(); // Debug tracking alive objects if !thread::panicking() { diff --git a/wgpu-hal/src/empty.rs b/wgpu-hal/src/empty.rs index c2710e4532..e98ab94aa1 100644 --- a/wgpu-hal/src/empty.rs +++ b/wgpu-hal/src/empty.rs @@ -106,7 +106,7 @@ impl crate::Queue for Context { } impl crate::Device for Context { - unsafe fn exit(self) {} + unsafe fn exit(self, queue: Context) {} unsafe fn create_buffer(&self, desc: &crate::BufferDescriptor) -> DeviceResult { Ok(Resource) } diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index 926e9ae168..9b6b378909 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -289,9 +289,12 @@ impl super::Device { } impl crate::Device for super::Device { - unsafe fn exit(self) { + unsafe fn exit(self, queue: super::Queue) { let gl = &self.shared.context; gl.delete_vertex_array(self.main_vao); + gl.delete_framebuffer(queue.draw_fbo); + gl.delete_framebuffer(queue.copy_fbo); + gl.delete_buffer(queue.zero_buffer); } unsafe fn create_buffer( diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index 80737c8d72..67cb905270 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -204,7 +204,7 @@ pub trait Adapter: Send + Sync { pub trait Device: Send + Sync { /// Exit connection to this logical device. - unsafe fn exit(self); + unsafe fn exit(self, queue: A::Queue); /// Creates a new buffer. /// /// The initial usage is `BufferUses::empty()`. diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index 0e68ceac2b..ede0a038a6 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -161,7 +161,7 @@ impl super::Device { } impl crate::Device for super::Device { - unsafe fn exit(self) {} + unsafe fn exit(self, _queue: super::Queue) {} unsafe fn create_buffer(&self, desc: &crate::BufferDescriptor) -> DeviceResult { let map_read = desc.usage.contains(crate::BufferUses::MAP_READ); diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 9ab56c1ddd..0f8a95daaa 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -860,6 +860,10 @@ impl crate::Adapter for super::Adapter { swapchain_fn, device: Arc::clone(&shared), family_index, + relay_semaphore: shared + .raw + .create_semaphore(&vk::SemaphoreCreateInfo::builder(), None)?, + relay_active: false, }; let mem_allocator = { diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 0b4bb129b1..8333e09652 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -538,9 +538,12 @@ impl super::Device { } impl crate::Device for super::Device { - unsafe fn exit(self) { + unsafe fn exit(self, queue: super::Queue) { self.mem_allocator.into_inner().cleanup(&*self.shared); self.desc_allocator.into_inner().cleanup(&*self.shared); + self.shared + .raw + .destroy_semaphore(queue.relay_semaphore, None); self.shared.free_resources(); } diff --git a/wgpu-hal/src/vulkan/mod.rs b/wgpu-hal/src/vulkan/mod.rs index 8171dc3ce4..7818b5460d 100644 --- a/wgpu-hal/src/vulkan/mod.rs +++ b/wgpu-hal/src/vulkan/mod.rs @@ -240,6 +240,12 @@ pub struct Queue { swapchain_fn: khr::Swapchain, device: Arc, family_index: u32, + /// This special semaphore is used to synchronize GPU work of + /// everything on a queue with... itself. Yikes! + /// It's required by the confusing portion of the spec to be signalled + /// by last submission and waited by the present. + relay_semaphore: vk::Semaphore, + relay_active: bool, } #[derive(Debug)] @@ -444,19 +450,18 @@ impl crate::Queue for Queue { let mut fence_raw = vk::Fence::null(); let mut vk_timeline_info; + let mut semaphores = [self.relay_semaphore, vk::Semaphore::null()]; let signal_values; - let signal_semaphores; + if let Some((fence, value)) = signal_fence { fence.maintain(&self.device.raw)?; match *fence { Fence::TimelineSemaphore(raw) => { - signal_values = [value]; - signal_semaphores = [raw]; + signal_values = [!0, value]; + semaphores[1] = raw; vk_timeline_info = vk::TimelineSemaphoreSubmitInfo::builder() .signal_semaphore_values(&signal_values); - vk_info = vk_info - .signal_semaphores(&signal_semaphores) - .push_next(&mut vk_timeline_info); + vk_info = vk_info.push_next(&mut vk_timeline_info); } Fence::FencePool { ref mut active, @@ -465,16 +470,30 @@ impl crate::Queue for Queue { } => { fence_raw = match free.pop() { Some(raw) => raw, - None => { - let vk_info = vk::FenceCreateInfo::builder().build(); - self.device.raw.create_fence(&vk_info, None)? - } + None => self + .device + .raw + .create_fence(&vk::FenceCreateInfo::builder(), None)?, }; active.push((value, fence_raw)); } } } + let wait_stage_mask = [vk::PipelineStageFlags::TOP_OF_PIPE]; + if self.relay_active { + vk_info = vk_info + .wait_semaphores(&semaphores[..1]) + .wait_dst_stage_mask(&wait_stage_mask); + } + self.relay_active = true; + let signal_count = if semaphores[1] == vk::Semaphore::null() { + 1 + } else { + 2 + }; + vk_info = vk_info.signal_semaphores(&semaphores[..signal_count]); + self.device .raw .queue_submit(self.raw, &[vk_info.build()], fence_raw)?; @@ -490,10 +509,16 @@ impl crate::Queue for Queue { let swapchains = [ssc.raw]; let image_indices = [texture.index]; - let vk_info = vk::PresentInfoKHR::builder() + let semaphores = [self.relay_semaphore]; + let mut vk_info = vk::PresentInfoKHR::builder() .swapchains(&swapchains) .image_indices(&image_indices); + if self.relay_active { + vk_info = vk_info.wait_semaphores(&semaphores); + self.relay_active = false; + } + let suboptimal = self .swapchain_fn .queue_present(self.raw, &vk_info)