From 68cacd482953968ed926c476f8d93c323245541d Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Tue, 8 Jan 2019 00:02:05 -0500 Subject: [PATCH 01/10] native: basic surface and swapchain creation --- Cargo.lock | 9 +++-- wgpu-bindings/Cargo.toml | 3 +- wgpu-native/Cargo.toml | 1 + wgpu-native/src/device.rs | 70 ++++++++++++++++++++++++++++++--- wgpu-native/src/instance.rs | 37 ++++++++++++++--- wgpu-native/src/lib.rs | 11 ++++++ wgpu-native/src/registry/mod.rs | 16 +++++--- wgpu-native/src/swap_chain.rs | 21 ++++++++++ 8 files changed, 145 insertions(+), 23 deletions(-) create mode 100644 wgpu-native/src/swap_chain.rs diff --git a/Cargo.lock b/Cargo.lock index 0eb89aebe..88e9fecea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,8 +104,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cbindgen" -version = "0.6.7" -source = "git+https://github.com/grovesNL/cbindgen?branch=associated-constants#c87c6774c9f1b9540abac4fc505ed63f0e0a0798" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1061,7 +1061,7 @@ dependencies = [ name = "wgpu-bindings" version = "0.1.0" dependencies = [ - "cbindgen 0.6.7 (git+https://github.com/grovesNL/cbindgen?branch=associated-constants)", + "cbindgen 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1077,6 +1077,7 @@ dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winit 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1180,7 +1181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" -"checksum cbindgen 0.6.7 (git+https://github.com/grovesNL/cbindgen?branch=associated-constants)" = "" +"checksum cbindgen 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "89ae8c2f780373f1842acb548fa53c7fd3acd6ca27d47966c69351719b239eae" "checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" diff --git a/wgpu-bindings/Cargo.toml b/wgpu-bindings/Cargo.toml index c6ef77ba4..72d2da4e2 100644 --- a/wgpu-bindings/Cargo.toml +++ b/wgpu-bindings/Cargo.toml @@ -11,5 +11,4 @@ edition = "2018" default = [] [dependencies] -#cbindgen = "0.6.7" -cbindgen = { git = "https://github.com/grovesNL/cbindgen", branch = "associated-constants"} +cbindgen = "0.6.8" diff --git a/wgpu-native/Cargo.toml b/wgpu-native/Cargo.toml index 9a0496e34..e96199c0a 100644 --- a/wgpu-native/Cargo.toml +++ b/wgpu-native/Cargo.toml @@ -25,3 +25,4 @@ gfx-backend-vulkan = { version = "0.1.0", optional = true } gfx-backend-dx12 = { version = "0.1.0", optional = true } gfx-backend-metal = { version = "0.1.0", optional = true } #rendy-memory = { git = "https://github.com/rustgd/rendy", rev = "ce7dd7f", features = ["gfx-hal"] } +winit = "0.18" diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index ea32968fe..14bffb8c8 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -1,15 +1,18 @@ -use crate::registry::{Items, HUB}; +use crate::{back, binding_model, command, conv, pipeline, resource, swap_chain}; +use crate::registry::{HUB, Items}; use crate::track::{BufferTracker, TextureTracker}; -use crate::{back, binding_model, command, conv, pipeline, resource}; use crate::{ - BindGroupLayoutId, BlendStateId, BufferId, CommandBuffer, CommandBufferId, DepthStencilStateId, - DeviceId, LifeGuard, PipelineLayoutId, QueueId, RefCount, RenderPipelineId, ShaderModuleId, - Stored, SubmissionIndex, TextureId, TextureUsageFlags, TextureViewId, WeaklyStored, + CommandBuffer, LifeGuard, RefCount, Stored, SubmissionIndex, WeaklyStored, + TextureUsageFlags, + BindGroupLayoutId, BlendStateId, BufferId, CommandBufferId, DepthStencilStateId, + AdapterId, DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, + TextureId, TextureViewId, + SurfaceId, SwapChainId, }; use hal::command::RawCommandBuffer; use hal::queue::RawCommandQueue; -use hal::{self, Device as _Device}; +use hal::{self, Device as _Device, Surface as _Surface}; //use rendy_memory::{allocator, Config, Heaps}; use std::collections::hash_map::{Entry, HashMap}; @@ -124,8 +127,10 @@ impl DestroyedResources { } } + pub struct Device { pub(crate) raw: B::Device, + adapter_id: WeaklyStored, queue_group: hal::QueueGroup, //mem_allocator: Heaps, pub(crate) com_allocator: command::CommandAllocator, @@ -142,6 +147,7 @@ pub struct Device { impl Device { pub(crate) fn new( raw: B::Device, + adapter_id: WeaklyStored, queue_group: hal::QueueGroup, mem_props: hal::MemoryProperties, ) -> Self { @@ -168,6 +174,7 @@ impl Device { Device { raw, + adapter_id, //mem_allocator, com_allocator: command::CommandAllocator::new(queue_group.family()), queue_group, @@ -823,3 +830,54 @@ pub extern "C" fn wgpu_device_create_render_pipeline( .write() .register(pipeline::RenderPipeline { raw: pipeline }) } + +#[no_mangle] +pub extern "C" fn wgpu_device_create_swap_chain( + device_id: DeviceId, + surface_id: SurfaceId, + desc: &swap_chain::SwapChainDescriptor, +) -> SwapChainId { + let device_guard = HUB.devices.read(); + let device = device_guard.get(device_id); + let adapter_guard = HUB.adapters.read(); + let physical_device = &adapter_guard.get(device.adapter_id.0).physical_device; + let mut surface_guard = HUB.surfaces.write(); + let surface = surface_guard.get_mut(surface_id); + + let (caps, formats, _present_modes, _composite_alphas) = surface.raw.compatibility(physical_device); + let config = hal::SwapchainConfig::from_caps( + &caps, + conv::map_texture_format(desc.format), + hal::window::Extent2D { + width: desc.width, + height: desc.height, + }, + ); + + let usage = conv::map_texture_usage(desc.usage, hal::format::Aspects::COLOR); + if let Some(formats) = formats { + assert!(formats.contains(&config.format)); + } + + let (raw, backbuffer) = unsafe { + device.raw + .create_swapchain( + &mut surface.raw, + config.with_image_usage(usage), + None, + ) + .unwrap() + }; + + let images = match backbuffer { + hal::Backbuffer::Images(images) => images, + hal::Backbuffer::Framebuffer(_) => panic!("Deprecated API detected!"), + }; + + HUB.swap_chains + .write() + .register(swap_chain::SwapChain { + raw, + images, + }) +} diff --git a/wgpu-native/src/instance.rs b/wgpu-native/src/instance.rs index 2cba38c1e..993623056 100644 --- a/wgpu-native/src/instance.rs +++ b/wgpu-native/src/instance.rs @@ -1,7 +1,13 @@ -use hal::{Instance as _Instance, PhysicalDevice as _PhysicalDevice}; +#[cfg(not(feature = "winit"))] +extern crate winit; + +use hal::{self, Instance as _Instance, PhysicalDevice as _PhysicalDevice}; + +use crate::registry::{HUB, Items}; +use crate::{WeaklyStored, Device, Surface, + AdapterId, DeviceId, InstanceId, SurfaceId, +}; -use crate::registry::{Items, HUB}; -use crate::{AdapterId, Device, DeviceId, InstanceId}; #[repr(C)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] @@ -47,6 +53,25 @@ pub extern "C" fn wgpu_create_instance() -> InstanceId { } } +#[cfg(not(feature = "remote"))] +#[no_mangle] +pub extern "C" fn wgpu_instance_create_surface_from_winit( + instance_id: InstanceId, + window: &winit::Window, +) -> SurfaceId { + let raw = HUB.instances + .read() + .get(instance_id) + .create_surface(window); + let surface = Surface { + raw, + }; + + HUB.surfaces + .write() + .register(surface) +} + #[no_mangle] pub extern "C" fn wgpu_instance_get_adapter( instance_id: InstanceId, @@ -77,9 +102,11 @@ pub extern "C" fn wgpu_adapter_create_device( ) -> DeviceId { let mut adapter_guard = HUB.adapters.write(); let adapter = adapter_guard.get_mut(adapter_id); - let (device, queue_group) = adapter.open_with::<_, hal::General>(1, |_qf| true).unwrap(); + let (raw, queue_group) = adapter.open_with::<_, hal::General>(1, |_qf| true).unwrap(); let mem_props = adapter.physical_device.memory_properties(); + let device = Device::new(raw, WeaklyStored(adapter_id), queue_group, mem_props); + HUB.devices .write() - .register(Device::new(device, queue_group, mem_props)) + .register(device) } diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index ef9b12399..a7f356775 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -1,3 +1,6 @@ +#[cfg(not(feature = "remote"))] +extern crate winit; + #[cfg(feature = "gfx-backend-dx12")] extern crate gfx_backend_dx12 as back; #[cfg(not(any( @@ -22,6 +25,7 @@ mod instance; mod pipeline; mod registry; mod resource; +mod swap_chain; mod track; pub use self::binding_model::*; @@ -30,6 +34,7 @@ pub use self::device::*; pub use self::instance::*; pub use self::pipeline::*; pub use self::resource::*; +pub use self::swap_chain::*; use back::Backend as B; pub use crate::registry::Id; @@ -214,3 +219,9 @@ pub type RenderPassId = Id; type RenderPassHandle = RenderPass; pub type ComputePassId = Id; type ComputePassHandle = ComputePass; + + +pub type SurfaceId = Id; +type SurfaceHandle = Surface; +pub type SwapChainId = Id; +type SwapChainHandle = SwapChain; diff --git a/wgpu-native/src/registry/mod.rs b/wgpu-native/src/registry/mod.rs index 5028ee6ff..9c9af2c97 100644 --- a/wgpu-native/src/registry/mod.rs +++ b/wgpu-native/src/registry/mod.rs @@ -1,16 +1,18 @@ use std::sync::Arc; +use lazy_static::lazy_static; use parking_lot::RwLock; -use lazy_static::lazy_static; - use crate::{ - AdapterHandle, BindGroupHandle, BindGroupLayoutHandle, BlendStateHandle, BufferHandle, - CommandBufferHandle, ComputePassHandle, ComputePipelineHandle, DepthStencilStateHandle, - DeviceHandle, InstanceHandle, PipelineLayoutHandle, RenderPassHandle, RenderPipelineHandle, - ShaderModuleHandle, TextureHandle, TextureViewHandle, + AdapterHandle, BindGroupLayoutHandle, BindGroupHandle, + BlendStateHandle, CommandBufferHandle, DepthStencilStateHandle, DeviceHandle, InstanceHandle, + RenderPassHandle, ComputePassHandle, + PipelineLayoutHandle, RenderPipelineHandle, ComputePipelineHandle, ShaderModuleHandle, + BufferHandle, TextureHandle, TextureViewHandle, + SurfaceHandle, SwapChainHandle, }; + #[cfg(not(feature = "remote"))] mod local; #[cfg(feature = "remote")] @@ -49,6 +51,8 @@ pub struct Hub { pub(crate) buffers: ConcreteRegistry, pub(crate) textures: ConcreteRegistry, pub(crate) texture_views: ConcreteRegistry, + pub(crate) surfaces: ConcreteRegistry, + pub(crate) swap_chains: ConcreteRegistry, } lazy_static! { diff --git a/wgpu-native/src/swap_chain.rs b/wgpu-native/src/swap_chain.rs new file mode 100644 index 000000000..597ef42f6 --- /dev/null +++ b/wgpu-native/src/swap_chain.rs @@ -0,0 +1,21 @@ +use hal; + +use crate::resource; + + +pub(crate) struct Surface { + pub raw: B::Surface, +} + +pub(crate) struct SwapChain { + pub raw: B::Swapchain, + pub images: Vec, +} + +#[repr(C)] +pub struct SwapChainDescriptor { + pub usage: resource::TextureUsageFlags, + pub format: resource::TextureFormat, + pub width: u32, + pub height: u32, +} From 1859141a99fa4a91f070af07d85d04aa2b4b89cc Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Tue, 8 Jan 2019 09:20:19 -0500 Subject: [PATCH 02/10] Rename ActiveFrame to ActiveSubmission, progress with swapchain images --- wgpu-native/src/device.rs | 73 +++++++++++++++++++++++++---------- wgpu-native/src/swap_chain.rs | 28 +++++++++++++- 2 files changed, 79 insertions(+), 22 deletions(-) diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index 14bffb8c8..ac92ab3b3 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -43,8 +43,8 @@ enum Resource { Texture(resource::Texture), } -struct ActiveFrame { - submission_index: SubmissionIndex, +struct ActiveSubmission { + index: SubmissionIndex, fence: B::Fence, resources: Vec>, } @@ -54,8 +54,8 @@ struct DestroyedResources { /// other objects or command buffers. referenced: Vec<(ResourceId, RefCount)>, /// Resources that are not referenced any more but still used by GPU. - /// Grouped by frames associated with a fence and a submission index. - active: Vec>, + /// Grouped by submissions associated with a fence and a submission index. + active: Vec>, /// Resources that are neither referenced or used, just pending /// actual deletion. free: Vec>, @@ -96,9 +96,9 @@ impl DestroyedResources { match self .active .iter_mut() - .find(|af| af.submission_index == submit_index) + .find(|a| a.index == submit_index) { - Some(af) => af.resources.push(resource), + Some(a) => a.resources.push(resource), None => self.free.push(resource), } } @@ -107,10 +107,14 @@ impl DestroyedResources { fn cleanup(&mut self, raw: &B::Device) { for i in (0..self.active.len()).rev() { - if unsafe { raw.get_fence_status(&self.active[i].fence) }.unwrap() { - let af = self.active.swap_remove(i); - self.free.extend(af.resources); - unsafe { raw.destroy_fence(af.fence) }; + if unsafe { + raw.get_fence_status(&self.active[i].fence).unwrap() + } { + let a = self.active.swap_remove(i); + self.free.extend(a.resources); + unsafe { + raw.destroy_fence(a.fence); + } } } @@ -600,8 +604,8 @@ pub extern "C" fn wgpu_queue_submit( destroyed.triage_referenced(&mut *buffer_guard, &mut *texture_guard); destroyed.cleanup(&device.raw); - destroyed.active.push(ActiveFrame { - submission_index: old_submit_index + 1, + destroyed.active.push(ActiveSubmission { + index: old_submit_index + 1, fence, resources: Vec::new(), }); @@ -843,21 +847,22 @@ pub extern "C" fn wgpu_device_create_swap_chain( let physical_device = &adapter_guard.get(device.adapter_id.0).physical_device; let mut surface_guard = HUB.surfaces.write(); let surface = surface_guard.get_mut(surface_id); + let mut texture_guard = HUB.textures.write(); let (caps, formats, _present_modes, _composite_alphas) = surface.raw.compatibility(physical_device); - let config = hal::SwapchainConfig::from_caps( - &caps, + let config = hal::SwapchainConfig::new( + desc.width, + desc.height, conv::map_texture_format(desc.format), - hal::window::Extent2D { - width: desc.width, - height: desc.height, - }, + caps.image_count.start, //TODO: configure? ); let usage = conv::map_texture_usage(desc.usage, hal::format::Aspects::COLOR); if let Some(formats) = formats { assert!(formats.contains(&config.format)); } + assert!(desc.width >= caps.extents.start.width && desc.width < caps.extents.end.width); + assert!(desc.height >= caps.extents.start.height && desc.width < caps.extents.end.height); let (raw, backbuffer) = unsafe { device.raw @@ -869,8 +874,33 @@ pub extern "C" fn wgpu_device_create_swap_chain( .unwrap() }; - let images = match backbuffer { - hal::Backbuffer::Images(images) => images, + let frames = match backbuffer { + hal::Backbuffer::Images(images) => images + .into_iter() + .map(|image| { + let texture = resource::Texture { + raw: image, + device_id: Stored { + value: device_id, + ref_count: device.life_guard.ref_count.clone(), + }, + kind: hal::image::Kind::D2(desc.width, desc.height, 1, 1), + format: desc.format, + full_range: hal::image::SubresourceRange { + aspects: hal::format::Aspects::COLOR, + levels: 0 .. 1, + layers: 0 .. 1, + }, + life_guard: LifeGuard::new(), + }; + swap_chain::Frame { + texture: Stored { + ref_count: texture.life_guard.ref_count.clone(), + value: texture_guard.register(texture), + }, + } + }) + .collect(), hal::Backbuffer::Framebuffer(_) => panic!("Deprecated API detected!"), }; @@ -878,6 +908,7 @@ pub extern "C" fn wgpu_device_create_swap_chain( .write() .register(swap_chain::SwapChain { raw, - images, + frames, + next_frame_index: 0, }) } diff --git a/wgpu-native/src/swap_chain.rs b/wgpu-native/src/swap_chain.rs index 597ef42f6..e5ad913bb 100644 --- a/wgpu-native/src/swap_chain.rs +++ b/wgpu-native/src/swap_chain.rs @@ -1,15 +1,24 @@ use hal; +use crate::registry::{HUB, Items}; use crate::resource; +use crate::{Stored, + SwapChainId, TextureId, +}; pub(crate) struct Surface { pub raw: B::Surface, } +pub(crate) struct Frame { + pub texture: Stored, +} + pub(crate) struct SwapChain { pub raw: B::Swapchain, - pub images: Vec, + pub frames: Vec, + pub next_frame_index: usize, } #[repr(C)] @@ -19,3 +28,20 @@ pub struct SwapChainDescriptor { pub width: u32, pub height: u32, } + +#[no_mangle] +pub extern "C" fn wgpu_swap_chain_get_next_texture( + swap_chain_id: SwapChainId, +) -> TextureId { + let mut swap_chain_guard = HUB.swap_chains.write(); + let swap_chain = swap_chain_guard.get_mut(swap_chain_id); + + let frame = &swap_chain.frames[swap_chain.next_frame_index]; + swap_chain.next_frame_index += 1; + if swap_chain.next_frame_index == swap_chain.frames.len() { + swap_chain.next_frame_index = 0; + } + + //TODO: actual synchronization + frame.texture.value +} From 630e86f12093aa4a57062561f1e43a5db7c6202a Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 9 Jan 2019 09:14:40 -0500 Subject: [PATCH 03/10] Link textures to swap chains --- wgpu-native/src/device.rs | 54 +++++++++++++++----------- wgpu-native/src/resource.rs | 13 ++++++- wgpu-native/src/swap_chain.rs | 73 +++++++++++++++++++++++++---------- 3 files changed, 95 insertions(+), 45 deletions(-) diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index ac92ab3b3..a34263621 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -14,11 +14,10 @@ use hal::command::RawCommandBuffer; use hal::queue::RawCommandQueue; use hal::{self, Device as _Device, Surface as _Surface}; //use rendy_memory::{allocator, Config, Heaps}; +use parking_lot::{Mutex, RwLock}; -use std::collections::hash_map::{Entry, HashMap}; use std::{ffi, slice}; - -use parking_lot::Mutex; +use std::collections::hash_map::{Entry, HashMap}; use std::sync::atomic::Ordering; #[derive(Hash, PartialEq)] @@ -257,24 +256,26 @@ pub extern "C" fn wgpu_device_create_texture( let life_guard = LifeGuard::new(); let ref_count = life_guard.ref_count.clone(); - let id = HUB.textures.write().register(resource::Texture { - raw: bound_image, - device_id: Stored { - value: device_id, - ref_count: device.life_guard.ref_count.clone(), - }, - kind, - format: desc.format, - full_range, - life_guard, - }); - let query = device.texture_tracker.lock().query( - &Stored { - value: id, - ref_count, - }, - TextureUsageFlags::WRITE_ALL, - ); + let id = HUB.textures + .write() + .register(resource::Texture { + raw: bound_image, + device_id: Stored { + value: device_id, + ref_count: device.life_guard.ref_count.clone(), + }, + kind, + format: desc.format, + full_range, + swap_chain_link: RwLock::new(None), + life_guard, + }); + let query = device.texture_tracker + .lock() + .query( + &Stored { value: id, ref_count }, + TextureUsageFlags::WRITE_ALL, + ); assert!(query.initialized); id @@ -891,6 +892,7 @@ pub extern "C" fn wgpu_device_create_swap_chain( levels: 0 .. 1, layers: 0 .. 1, }, + swap_chain_link: RwLock::new(None), life_guard: LifeGuard::new(), }; swap_chain::Frame { @@ -898,6 +900,9 @@ pub extern "C" fn wgpu_device_create_swap_chain( ref_count: texture.life_guard.ref_count.clone(), value: texture_guard.register(texture), }, + fence: device.raw.create_fence(true).unwrap(), + sem_available: device.raw.create_semaphore().unwrap(), + sem_present: device.raw.create_semaphore().unwrap(), } }) .collect(), @@ -908,7 +913,12 @@ pub extern "C" fn wgpu_device_create_swap_chain( .write() .register(swap_chain::SwapChain { raw, + device_id: Stored { + value: device_id, + ref_count: device.life_guard.ref_count.clone(), + }, frames, - next_frame_index: 0, + sem_available: device.raw.create_semaphore().unwrap(), + epoch: 1, }) } diff --git a/wgpu-native/src/resource.rs b/wgpu-native/src/resource.rs index 2677625d4..35d5102f7 100644 --- a/wgpu-native/src/resource.rs +++ b/wgpu-native/src/resource.rs @@ -1,6 +1,14 @@ -use crate::{DeviceId, Extent3d, LifeGuard, Stored, TextureId}; - use bitflags::bitflags; +use parking_lot::RwLock; + +use hal; + +use crate::{ + Extent3d, LifeGuard, Stored, + DeviceId, TextureId, +}; +use crate::swap_chain::SwapChainLink; + bitflags! { #[repr(transparent)] @@ -78,6 +86,7 @@ pub(crate) struct Texture { pub kind: hal::image::Kind, pub format: TextureFormat, pub full_range: hal::image::SubresourceRange, + pub swap_chain_link: RwLock>, pub life_guard: LifeGuard, } diff --git a/wgpu-native/src/swap_chain.rs b/wgpu-native/src/swap_chain.rs index e5ad913bb..b7ca893c3 100644 --- a/wgpu-native/src/swap_chain.rs +++ b/wgpu-native/src/swap_chain.rs @@ -1,24 +1,40 @@ -use hal; - +use crate::{Stored, WeaklyStored, + DeviceId, SwapChainId, TextureId, +}; use crate::registry::{HUB, Items}; use crate::resource; -use crate::{Stored, - SwapChainId, TextureId, -}; + +use hal; +use hal::{Device as _Device, Swapchain as _Swapchain}; + +use std::mem; -pub(crate) struct Surface { - pub raw: B::Surface, +pub type Epoch = u16; + +pub(crate) struct SwapChainLink { + swap_chain_id: WeaklyStored, //TODO: strongly + epoch: Epoch, + image_index: hal::SwapImageIndex, } -pub(crate) struct Frame { - pub texture: Stored, +pub(crate) struct Surface { + pub raw: B::Surface, +} + +pub(crate) struct Frame { + pub texture: Stored, + pub fence: B::Fence, + pub sem_available: B::Semaphore, + pub sem_present: B::Semaphore, } pub(crate) struct SwapChain { - pub raw: B::Swapchain, - pub frames: Vec, - pub next_frame_index: usize, + pub raw: B::Swapchain, + pub device_id: Stored, + pub frames: Vec>, + pub sem_available: B::Semaphore, + pub epoch: Epoch, } #[repr(C)] @@ -33,15 +49,30 @@ pub struct SwapChainDescriptor { pub extern "C" fn wgpu_swap_chain_get_next_texture( swap_chain_id: SwapChainId, ) -> TextureId { - let mut swap_chain_guard = HUB.swap_chains.write(); - let swap_chain = swap_chain_guard.get_mut(swap_chain_id); + let mut swap_chain_guard = HUB.swap_chains.write(); + let swap_chain = swap_chain_guard.get_mut(swap_chain_id); + let device_guard = HUB.devices.read(); + let device = device_guard.get(swap_chain.device_id.value); - let frame = &swap_chain.frames[swap_chain.next_frame_index]; - swap_chain.next_frame_index += 1; - if swap_chain.next_frame_index == swap_chain.frames.len() { - swap_chain.next_frame_index = 0; - } + let image_index = unsafe { + let sync = hal::FrameSync::Semaphore(&swap_chain.sem_available); + swap_chain.raw.acquire_image(!0, sync).unwrap() + }; - //TODO: actual synchronization - frame.texture.value + let frame = &mut swap_chain.frames[image_index as usize]; + unsafe { + device.raw.wait_for_fence(&frame.fence, !0).unwrap(); + } + + mem::swap(&mut frame.sem_available, &mut swap_chain.sem_available); + + let texture_guard = HUB.textures.read(); + let texture = texture_guard.get(frame.texture.value); + *texture.swap_chain_link.write() = Some(SwapChainLink { + swap_chain_id: WeaklyStored(swap_chain_id), + epoch: swap_chain.epoch, + image_index, + }); + + frame.texture.value } From b67a0bee0d36af9992f34b7095416223d2ef900a Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 14 Jan 2019 14:01:23 -0500 Subject: [PATCH 04/10] Prenentation logic and bits of frame synchronization --- wgpu-native/src/command/allocator.rs | 1 + wgpu-native/src/command/mod.rs | 3 + wgpu-native/src/device.rs | 199 +++++++++++++++++---------- wgpu-native/src/lib.rs | 2 +- wgpu-native/src/resource.rs | 4 +- wgpu-native/src/swap_chain.rs | 94 +++++++++++-- 6 files changed, 212 insertions(+), 91 deletions(-) diff --git a/wgpu-native/src/command/allocator.rs b/wgpu-native/src/command/allocator.rs index 886e4a722..65f004ad0 100644 --- a/wgpu-native/src/command/allocator.rs +++ b/wgpu-native/src/command/allocator.rs @@ -99,6 +99,7 @@ impl CommandAllocator { life_guard: LifeGuard::new(), buffer_tracker: Tracker::new(), texture_tracker: Tracker::new(), + swap_chain_links: Vec::new(), } } diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index c8673fa75..5eac089af 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -11,6 +11,7 @@ use hal::Device; use crate::device::{FramebufferKey, RenderPassKey}; use crate::registry::{Items, HUB}; +use crate::swap_chain::SwapChainLink; use crate::track::{BufferTracker, TextureTracker}; use crate::{conv, resource}; use crate::{ @@ -87,6 +88,7 @@ pub struct CommandBuffer { life_guard: LifeGuard, pub(crate) buffer_tracker: BufferTracker, pub(crate) texture_tracker: TextureTracker, + swap_chain_links: Vec, } impl CommandBuffer { @@ -162,6 +164,7 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass( let rp_key = { let tracker = &mut cmb.texture_tracker; + //let swap_chain_links = &mut cmb.swap_chain_links; let depth_stencil_key = match desc.depth_stencil_attachment { Some(ref at) => { diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index a34263621..866b4125a 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -14,7 +14,7 @@ use hal::command::RawCommandBuffer; use hal::queue::RawCommandQueue; use hal::{self, Device as _Device, Surface as _Surface}; //use rendy_memory::{allocator, Config, Heaps}; -use parking_lot::{Mutex, RwLock}; +use parking_lot::{Mutex}; use std::{ffi, slice}; use std::collections::hash_map::{Entry, HashMap}; @@ -134,12 +134,12 @@ impl DestroyedResources { pub struct Device { pub(crate) raw: B::Device, adapter_id: WeaklyStored, - queue_group: hal::QueueGroup, + pub(crate) queue_group: hal::QueueGroup, //mem_allocator: Heaps, pub(crate) com_allocator: command::CommandAllocator, life_guard: LifeGuard, buffer_tracker: Mutex, - texture_tracker: Mutex, + pub(crate) texture_tracker: Mutex, mem_props: hal::MemoryProperties, pub(crate) render_passes: Mutex>, pub(crate) framebuffers: Mutex>, @@ -267,7 +267,7 @@ pub extern "C" fn wgpu_device_create_texture( kind, format: desc.format, full_range, - swap_chain_link: RwLock::new(None), + swap_chain_link: None, life_guard, }); let query = device.texture_tracker @@ -301,26 +301,27 @@ pub extern "C" fn wgpu_texture_create_texture_view( hal::format::Swizzle::NO, hal::image::SubresourceRange { aspects: conv::map_texture_aspect_flags(desc.aspect), - levels: desc.base_mip_level as u8 - ..(desc.base_mip_level + desc.level_count) as u8, - layers: desc.base_array_layer as u16 - ..(desc.base_array_layer + desc.array_count) as u16, + levels: desc.base_mip_level as u8 .. (desc.base_mip_level + desc.level_count) as u8, + layers: desc.base_array_layer as u16 .. (desc.base_array_layer + desc.array_count) as u16, }, ) - } - .unwrap(); + .unwrap() + }; - HUB.texture_views.write().register(resource::TextureView { - raw, - texture_id: Stored { - value: texture_id, - ref_count: texture.life_guard.ref_count.clone(), - }, - format: texture.format, - extent: texture.kind.extent(), - samples: texture.kind.num_samples(), - life_guard: LifeGuard::new(), - }) + HUB.texture_views + .write() + .register(resource::TextureView { + raw, + texture_id: Stored { + value: texture_id, + ref_count: texture.life_guard.ref_count.clone(), + }, + format: texture.format, + extent: texture.kind.extent(), + samples: texture.kind.num_samples(), + is_owned_by_swap_chain: false, + life_guard: LifeGuard::new(), + }) } #[no_mangle] @@ -334,7 +335,7 @@ pub extern "C" fn wgpu_texture_create_default_texture_view(texture_id: TextureId hal::image::Kind::D3(..) => hal::image::ViewKind::D3, }; - let raw = unsafe { + let raw = unsafe{ HUB.devices .read() .get(texture.device_id.value) @@ -346,20 +347,23 @@ pub extern "C" fn wgpu_texture_create_default_texture_view(texture_id: TextureId hal::format::Swizzle::NO, texture.full_range.clone(), ) - } - .unwrap(); + .unwrap() + }; - HUB.texture_views.write().register(resource::TextureView { - raw, - texture_id: Stored { - value: texture_id, - ref_count: texture.life_guard.ref_count.clone(), - }, - format: texture.format, - extent: texture.kind.extent(), - samples: texture.kind.num_samples(), - life_guard: LifeGuard::new(), - }) + HUB.texture_views + .write() + .register(resource::TextureView { + raw, + texture_id: Stored { + value: texture_id, + ref_count: texture.life_guard.ref_count.clone(), + }, + format: texture.format, + extent: texture.kind.extent(), + samples: texture.kind.num_samples(), + is_owned_by_swap_chain: false, + life_guard: LifeGuard::new(), + }) } #[no_mangle] @@ -849,13 +853,17 @@ pub extern "C" fn wgpu_device_create_swap_chain( let mut surface_guard = HUB.surfaces.write(); let surface = surface_guard.get_mut(surface_id); let mut texture_guard = HUB.textures.write(); + let mut texture_view_guard = HUB.texture_views.write(); + let mut swap_chain_guard = HUB.swap_chains.write(); let (caps, formats, _present_modes, _composite_alphas) = surface.raw.compatibility(physical_device); + let num_frames = caps.image_count.start; //TODO: configure? + let frame_format = conv::map_texture_format(desc.format); let config = hal::SwapchainConfig::new( desc.width, desc.height, - conv::map_texture_format(desc.format), - caps.image_count.start, //TODO: configure? + frame_format, + num_frames, //TODO: configure? ); let usage = conv::map_texture_usage(desc.usage, hal::format::Aspects::COLOR); @@ -874,51 +882,94 @@ pub extern "C" fn wgpu_device_create_swap_chain( ) .unwrap() }; - - let frames = match backbuffer { - hal::Backbuffer::Images(images) => images - .into_iter() - .map(|image| { - let texture = resource::Texture { - raw: image, - device_id: Stored { - value: device_id, - ref_count: device.life_guard.ref_count.clone(), - }, - kind: hal::image::Kind::D2(desc.width, desc.height, 1, 1), - format: desc.format, - full_range: hal::image::SubresourceRange { - aspects: hal::format::Aspects::COLOR, - levels: 0 .. 1, - layers: 0 .. 1, - }, - swap_chain_link: RwLock::new(None), - life_guard: LifeGuard::new(), - }; - swap_chain::Frame { - texture: Stored { - ref_count: texture.life_guard.ref_count.clone(), - value: texture_guard.register(texture), - }, - fence: device.raw.create_fence(true).unwrap(), - sem_available: device.raw.create_semaphore().unwrap(), - sem_present: device.raw.create_semaphore().unwrap(), - } - }) - .collect(), - hal::Backbuffer::Framebuffer(_) => panic!("Deprecated API detected!"), + let command_pool = unsafe { + device.raw + .create_command_pool_typed( + &device.queue_group, + hal::pool::CommandPoolCreateFlags::RESET_INDIVIDUAL, + ) + .unwrap() }; - HUB.swap_chains - .write() + let swap_chain_id = swap_chain_guard .register(swap_chain::SwapChain { raw, device_id: Stored { value: device_id, ref_count: device.life_guard.ref_count.clone(), }, - frames, + frames: Vec::with_capacity(num_frames as usize), + acquired: Vec::with_capacity(num_frames as usize), sem_available: device.raw.create_semaphore().unwrap(), + command_pool, epoch: 1, - }) + }); + let swap_chain = swap_chain_guard.get_mut(swap_chain_id); + + let images = match backbuffer { + hal::Backbuffer::Images(images) => images, + hal::Backbuffer::Framebuffer(_) => panic!("Deprecated API detected!"), + }; + + for (i, image) in images.into_iter().enumerate() { + let kind = hal::image::Kind::D2(desc.width, desc.height, 1, 1); + let full_range = hal::image::SubresourceRange { + aspects: hal::format::Aspects::COLOR, + levels: 0 .. 1, + layers: 0 .. 1, + }; + let view_raw = unsafe { + device.raw + .create_image_view( + &image, + hal::image::ViewKind::D2, + frame_format, + hal::format::Swizzle::NO, + full_range.clone(), + ) + .unwrap() + }; + let texture = resource::Texture { + raw: image, + device_id: Stored { + value: device_id, + ref_count: device.life_guard.ref_count.clone(), + }, + kind, + format: desc.format, + full_range, + swap_chain_link: Some(swap_chain::SwapChainLink { + swap_chain_id: WeaklyStored(swap_chain_id), //TODO: strongly + epoch: Mutex::new(0), + image_index: i as hal::SwapImageIndex, + }), + life_guard: LifeGuard::new(), + }; + let texture_id = Stored { + ref_count: texture.life_guard.ref_count.clone(), + value: texture_guard.register(texture), + }; + let view = resource::TextureView { + raw: view_raw, + texture_id: texture_id.clone(), + format: desc.format, + extent: kind.extent(), + samples: kind.num_samples(), + is_owned_by_swap_chain: true, + life_guard: LifeGuard::new(), + }; + swap_chain.frames.push(swap_chain::Frame { + texture_id, + view_id: Stored { + ref_count: view.life_guard.ref_count.clone(), + value: texture_view_guard.register(view), + }, + fence: device.raw.create_fence(true).unwrap(), + sem_available: device.raw.create_semaphore().unwrap(), + sem_present: device.raw.create_semaphore().unwrap(), + comb: swap_chain.command_pool.acquire_command_buffer(), + }); + } + + swap_chain_id } diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index a7f356775..4ceaba19f 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -90,7 +90,7 @@ impl LifeGuard { } } -#[derive(Debug)] +#[derive(Clone, Debug)] struct Stored { value: T, ref_count: RefCount, diff --git a/wgpu-native/src/resource.rs b/wgpu-native/src/resource.rs index 35d5102f7..7f40bbb30 100644 --- a/wgpu-native/src/resource.rs +++ b/wgpu-native/src/resource.rs @@ -1,5 +1,4 @@ use bitflags::bitflags; -use parking_lot::RwLock; use hal; @@ -86,7 +85,7 @@ pub(crate) struct Texture { pub kind: hal::image::Kind, pub format: TextureFormat, pub full_range: hal::image::SubresourceRange, - pub swap_chain_link: RwLock>, + pub swap_chain_link: Option, pub life_guard: LifeGuard, } @@ -127,6 +126,7 @@ pub(crate) struct TextureView { pub format: TextureFormat, pub extent: hal::image::Extent, pub samples: hal::image::NumSamples, + pub is_owned_by_swap_chain: bool, pub life_guard: LifeGuard, } diff --git a/wgpu-native/src/swap_chain.rs b/wgpu-native/src/swap_chain.rs index b7ca893c3..e844d49e2 100644 --- a/wgpu-native/src/swap_chain.rs +++ b/wgpu-native/src/swap_chain.rs @@ -1,21 +1,24 @@ use crate::{Stored, WeaklyStored, - DeviceId, SwapChainId, TextureId, + DeviceId, SwapChainId, TextureId, TextureViewId, }; +use crate::{conv, resource}; use crate::registry::{HUB, Items}; -use crate::resource; +use crate::track::{Tracktion, TrackPermit}; use hal; use hal::{Device as _Device, Swapchain as _Swapchain}; -use std::mem; +use parking_lot::Mutex; + +use std::{iter, mem}; pub type Epoch = u16; pub(crate) struct SwapChainLink { - swap_chain_id: WeaklyStored, //TODO: strongly - epoch: Epoch, - image_index: hal::SwapImageIndex, + pub swap_chain_id: WeaklyStored, //TODO: strongly + pub epoch: Mutex, + pub image_index: hal::SwapImageIndex, } pub(crate) struct Surface { @@ -23,17 +26,21 @@ pub(crate) struct Surface { } pub(crate) struct Frame { - pub texture: Stored, + pub texture_id: Stored, + pub view_id: Stored, pub fence: B::Fence, pub sem_available: B::Semaphore, pub sem_present: B::Semaphore, + pub comb: hal::command::CommandBuffer, } pub(crate) struct SwapChain { pub raw: B::Swapchain, pub device_id: Stored, pub frames: Vec>, + pub acquired: Vec, pub sem_available: B::Semaphore, + pub command_pool: hal::CommandPool, pub epoch: Epoch, } @@ -59,6 +66,7 @@ pub extern "C" fn wgpu_swap_chain_get_next_texture( swap_chain.raw.acquire_image(!0, sync).unwrap() }; + swap_chain.acquired.push(image_index); let frame = &mut swap_chain.frames[image_index as usize]; unsafe { device.raw.wait_for_fence(&frame.fence, !0).unwrap(); @@ -67,12 +75,70 @@ pub extern "C" fn wgpu_swap_chain_get_next_texture( mem::swap(&mut frame.sem_available, &mut swap_chain.sem_available); let texture_guard = HUB.textures.read(); - let texture = texture_guard.get(frame.texture.value); - *texture.swap_chain_link.write() = Some(SwapChainLink { - swap_chain_id: WeaklyStored(swap_chain_id), - epoch: swap_chain.epoch, - image_index, - }); + let texture = texture_guard.get(frame.texture_id.value); + match texture.swap_chain_link { + Some(ref link) => *link.epoch.lock() = swap_chain.epoch, + None => unreachable!(), + } - frame.texture.value + frame.texture_id.value +} + +#[no_mangle] +pub extern "C" fn wgpu_swap_chain_present( + swap_chain_id: SwapChainId, +) { + let mut swap_chain_guard = HUB.swap_chains.write(); + let swap_chain = swap_chain_guard.get_mut(swap_chain_id); + let mut device_guard = HUB.devices.write(); + let device = device_guard.get_mut(swap_chain.device_id.value); + + let image_index = swap_chain.acquired.remove(0); + let frame = &mut swap_chain.frames[image_index as usize]; + + let texture_guard = HUB.textures.read(); + let texture = texture_guard.get(frame.texture_id.value); + match texture.swap_chain_link { + Some(ref link) => *link.epoch.lock() += 1, + None => unreachable!(), + } + + //trace!("transit {:?} to present", frame.texture_id.value); + let tracktion = device.texture_tracker + .lock() + .transit( + frame.texture_id.value, + &texture.life_guard.ref_count, + resource::TextureUsageFlags::PRESENT, + TrackPermit::EXTEND, + ) + .unwrap(); + + let barrier = match tracktion { + Tracktion::Keep => None, + Tracktion::Replace { old } => Some(hal::memory::Barrier::Image { + states: conv::map_texture_state(old, hal::format::Aspects::COLOR) .. + (hal::image::Access::empty(), hal::image::Layout::Present), + target: &texture.raw, + families: None, + range: texture.full_range.clone(), + }), + Tracktion::Init | + Tracktion::Extend {..} => unreachable!(), + }; + + unsafe { + frame.comb.begin(false); + frame.comb.pipeline_barrier( + hal::pso::PipelineStage::TOP_OF_PIPE .. hal::pso::PipelineStage::BOTTOM_OF_PIPE, + hal::memory::Dependencies::empty(), + barrier, + ); + frame.comb.finish(); + + // now prepare the GPU submission + device.raw.reset_fence(&frame.fence); + device.queue_group.queues[0] + .submit_nosemaphores(iter::once(&frame.comb), Some(&frame.fence)); + } } From ba8828eb5bd2b23d1bd9192dd8d37dd70bcd7607 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Tue, 15 Jan 2019 09:09:29 -0500 Subject: [PATCH 05/10] Refactor includes, collect swapchain links on RP begin --- wgpu-native/src/binding_model.rs | 1 + wgpu-native/src/command/compute.rs | 1 + wgpu-native/src/command/mod.rs | 31 +++++++++++++++++++++++------- wgpu-native/src/command/render.rs | 1 + wgpu-native/src/device.rs | 2 +- wgpu-native/src/instance.rs | 7 ++----- wgpu-native/src/lib.rs | 2 +- wgpu-native/src/pipeline.rs | 2 +- wgpu-native/src/registry/mod.rs | 10 +++++----- wgpu-native/src/resource.rs | 12 ++++++------ wgpu-native/src/swap_chain.rs | 14 ++++++-------- wgpu-native/src/track.rs | 1 + 12 files changed, 50 insertions(+), 34 deletions(-) diff --git a/wgpu-native/src/binding_model.rs b/wgpu-native/src/binding_model.rs index 47196517b..a57279f05 100644 --- a/wgpu-native/src/binding_model.rs +++ b/wgpu-native/src/binding_model.rs @@ -2,6 +2,7 @@ use crate::{BindGroupLayoutId, BufferId, SamplerId, TextureViewId}; use bitflags::bitflags; + bitflags! { #[repr(transparent)] pub struct ShaderStageFlags: u32 { diff --git a/wgpu-native/src/command/compute.rs b/wgpu-native/src/command/compute.rs index 477e29f31..1ac92b212 100644 --- a/wgpu-native/src/command/compute.rs +++ b/wgpu-native/src/command/compute.rs @@ -5,6 +5,7 @@ use hal::command::RawCommandBuffer; use std::iter; + pub struct ComputePass { raw: B::CommandBuffer, cmb_id: Stored, diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index 5eac089af..1c4a6909d 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -6,12 +6,9 @@ pub(crate) use self::allocator::CommandAllocator; pub use self::compute::*; pub use self::render::*; -use hal::command::RawCommandBuffer; -use hal::Device; - use crate::device::{FramebufferKey, RenderPassKey}; use crate::registry::{Items, HUB}; -use crate::swap_chain::SwapChainLink; +use crate::swap_chain::{SwapChainLink, SwapImageEpoch}; use crate::track::{BufferTracker, TextureTracker}; use crate::{conv, resource}; use crate::{ @@ -19,11 +16,14 @@ use crate::{ Origin3d, RenderPassId, Stored, TextureId, TextureUsageFlags, TextureViewId, WeaklyStored, B, }; +use hal::command::RawCommandBuffer; +use hal::Device; +use log::trace; + use std::collections::hash_map::Entry; use std::ops::Range; use std::thread::ThreadId; -use log::trace; #[repr(C)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] @@ -88,7 +88,7 @@ pub struct CommandBuffer { life_guard: LifeGuard, pub(crate) buffer_tracker: BufferTracker, pub(crate) texture_tracker: TextureTracker, - swap_chain_links: Vec, + swap_chain_links: Vec>, } impl CommandBuffer { @@ -164,7 +164,7 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass( let rp_key = { let tracker = &mut cmb.texture_tracker; - //let swap_chain_links = &mut cmb.swap_chain_links; + let swap_chain_links = &mut cmb.swap_chain_links; let depth_stencil_key = match desc.depth_stencil_attachment { Some(ref at) => { @@ -192,6 +192,23 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass( let color_keys = desc.color_attachments.iter().map(|at| { let view = view_guard.get(at.attachment); + + if view.is_owned_by_swap_chain { + let link = match HUB.textures + .read() + .get(view.texture_id.value) + .swap_chain_link + { + Some(ref link) => SwapChainLink { + swap_chain_id: link.swap_chain_id.clone(), + epoch: *link.epoch.lock(), + image_index: link.image_index, + }, + None => unreachable!() + }; + swap_chain_links.push(link); + } + if let Some(ex) = extent { assert_eq!(ex, view.extent); } else { diff --git a/wgpu-native/src/command/render.rs b/wgpu-native/src/command/render.rs index 4c9d8159c..32b8e97a0 100644 --- a/wgpu-native/src/command/render.rs +++ b/wgpu-native/src/command/render.rs @@ -4,6 +4,7 @@ use crate::{CommandBuffer, CommandBufferId, RenderPassId, Stored}; use hal::command::RawCommandBuffer; + pub struct RenderPass { raw: B::CommandBuffer, cmb_id: Stored, diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index 866b4125a..749baa68b 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -20,6 +20,7 @@ use std::{ffi, slice}; use std::collections::hash_map::{Entry, HashMap}; use std::sync::atomic::Ordering; + #[derive(Hash, PartialEq)] pub(crate) struct RenderPassKey { pub attachments: Vec, @@ -902,7 +903,6 @@ pub extern "C" fn wgpu_device_create_swap_chain( acquired: Vec::with_capacity(num_frames as usize), sem_available: device.raw.create_semaphore().unwrap(), command_pool, - epoch: 1, }); let swap_chain = swap_chain_guard.get_mut(swap_chain_id); diff --git a/wgpu-native/src/instance.rs b/wgpu-native/src/instance.rs index 993623056..38b84e355 100644 --- a/wgpu-native/src/instance.rs +++ b/wgpu-native/src/instance.rs @@ -1,13 +1,10 @@ -#[cfg(not(feature = "winit"))] -extern crate winit; - -use hal::{self, Instance as _Instance, PhysicalDevice as _PhysicalDevice}; - use crate::registry::{HUB, Items}; use crate::{WeaklyStored, Device, Surface, AdapterId, DeviceId, InstanceId, SurfaceId, }; +use hal::{self, Instance as _Instance, PhysicalDevice as _PhysicalDevice}; + #[repr(C)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index 4ceaba19f..c957c1dbe 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -99,7 +99,7 @@ struct Stored { unsafe impl Send for Stored {} unsafe impl Sync for Stored {} -#[derive(Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, PartialEq, Eq)] struct WeaklyStored(T); unsafe impl Send for WeaklyStored {} diff --git a/wgpu-native/src/pipeline.rs b/wgpu-native/src/pipeline.rs index eb918fd40..3d5b9b3c8 100644 --- a/wgpu-native/src/pipeline.rs +++ b/wgpu-native/src/pipeline.rs @@ -1,9 +1,9 @@ use crate::resource; - use crate::{BlendStateId, ByteArray, DepthStencilStateId, PipelineLayoutId, ShaderModuleId}; use bitflags::bitflags; + #[repr(C)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum BlendFactor { diff --git a/wgpu-native/src/registry/mod.rs b/wgpu-native/src/registry/mod.rs index 9c9af2c97..c43c46a29 100644 --- a/wgpu-native/src/registry/mod.rs +++ b/wgpu-native/src/registry/mod.rs @@ -1,8 +1,3 @@ -use std::sync::Arc; - -use lazy_static::lazy_static; -use parking_lot::RwLock; - use crate::{ AdapterHandle, BindGroupLayoutHandle, BindGroupHandle, BlendStateHandle, CommandBufferHandle, DepthStencilStateHandle, DeviceHandle, InstanceHandle, @@ -12,6 +7,11 @@ use crate::{ SurfaceHandle, SwapChainHandle, }; +use lazy_static::lazy_static; +use parking_lot::RwLock; + +use std::sync::Arc; + #[cfg(not(feature = "remote"))] mod local; diff --git a/wgpu-native/src/resource.rs b/wgpu-native/src/resource.rs index 7f40bbb30..42e4f071f 100644 --- a/wgpu-native/src/resource.rs +++ b/wgpu-native/src/resource.rs @@ -1,12 +1,12 @@ -use bitflags::bitflags; - -use hal; - use crate::{ Extent3d, LifeGuard, Stored, DeviceId, TextureId, }; -use crate::swap_chain::SwapChainLink; +use crate::swap_chain::{SwapChainLink, SwapImageEpoch}; + +use bitflags::bitflags; +use hal; +use parking_lot::Mutex; bitflags! { @@ -85,7 +85,7 @@ pub(crate) struct Texture { pub kind: hal::image::Kind, pub format: TextureFormat, pub full_range: hal::image::SubresourceRange, - pub swap_chain_link: Option, + pub swap_chain_link: Option>>, pub life_guard: LifeGuard, } diff --git a/wgpu-native/src/swap_chain.rs b/wgpu-native/src/swap_chain.rs index e844d49e2..bae5ceb88 100644 --- a/wgpu-native/src/swap_chain.rs +++ b/wgpu-native/src/swap_chain.rs @@ -7,17 +7,16 @@ use crate::track::{Tracktion, TrackPermit}; use hal; use hal::{Device as _Device, Swapchain as _Swapchain}; - -use parking_lot::Mutex; +use log::trace; use std::{iter, mem}; -pub type Epoch = u16; +pub type SwapImageEpoch = u16; -pub(crate) struct SwapChainLink { +pub(crate) struct SwapChainLink { pub swap_chain_id: WeaklyStored, //TODO: strongly - pub epoch: Mutex, + pub epoch: E, pub image_index: hal::SwapImageIndex, } @@ -41,7 +40,6 @@ pub(crate) struct SwapChain { pub acquired: Vec, pub sem_available: B::Semaphore, pub command_pool: hal::CommandPool, - pub epoch: Epoch, } #[repr(C)] @@ -77,7 +75,7 @@ pub extern "C" fn wgpu_swap_chain_get_next_texture( let texture_guard = HUB.textures.read(); let texture = texture_guard.get(frame.texture_id.value); match texture.swap_chain_link { - Some(ref link) => *link.epoch.lock() = swap_chain.epoch, + Some(ref link) => *link.epoch.lock() += 1, None => unreachable!(), } @@ -103,7 +101,7 @@ pub extern "C" fn wgpu_swap_chain_present( None => unreachable!(), } - //trace!("transit {:?} to present", frame.texture_id.value); + trace!("transit {:?} to present", frame.texture_id.value); let tracktion = device.texture_tracker .lock() .transit( diff --git a/wgpu-native/src/track.rs b/wgpu-native/src/track.rs index 9327509c9..767fa3978 100644 --- a/wgpu-native/src/track.rs +++ b/wgpu-native/src/track.rs @@ -8,6 +8,7 @@ use std::ops::{BitOr, Range}; use bitflags::bitflags; + #[derive(Clone, Debug, PartialEq)] #[allow(unused)] pub enum Tracktion { From 90154fb6f595500082ce1568983c440e4361e661 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 16 Jan 2019 08:56:35 -0500 Subject: [PATCH 06/10] Wait for swapchain semaphores --- wgpu-native/src/command/mod.rs | 2 +- wgpu-native/src/device.rs | 18 ++++++++++++++++-- wgpu-native/src/swap_chain.rs | 2 ++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index 1c4a6909d..917209262 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -88,7 +88,7 @@ pub struct CommandBuffer { life_guard: LifeGuard, pub(crate) buffer_tracker: BufferTracker, pub(crate) texture_tracker: TextureTracker, - swap_chain_links: Vec>, + pub(crate) swap_chain_links: Vec>, } impl CommandBuffer { diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index 749baa68b..3a1e7164b 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -538,6 +538,8 @@ pub extern "C" fn wgpu_queue_submit( .submission_index .fetch_add(1, Ordering::Relaxed); + let mut swap_chain_links = Vec::new(); + //TODO: if multiple command buffers are submitted, we can re-use the last // native command buffer of the previous chain instead of always creating // a temporary one, since the chains are not finished. @@ -545,6 +547,7 @@ pub extern "C" fn wgpu_queue_submit( // finish all the command buffers first for &cmb_id in command_buffer_ids { let comb = command_buffer_guard.get_mut(cmb_id); + swap_chain_links.extend(comb.swap_chain_links.drain(..)); // update submission IDs for id in comb.buffer_tracker.used() { buffer_guard @@ -589,14 +592,25 @@ pub extern "C" fn wgpu_queue_submit( // now prepare the GPU submission let fence = device.raw.create_fence(false).unwrap(); { + let swap_chain_guard = HUB.swap_chains.read(); + let wait_semaphores = swap_chain_links + .into_iter() + .map(|link| { + //TODO: check the epoch + let sem = &swap_chain_guard + .get(link.swap_chain_id.0) + .frames[link.image_index as usize] + .sem_available; + (sem, hal::pso::PipelineStage::COLOR_ATTACHMENT_OUTPUT) + }); let submission = hal::queue::Submission::<_, _, &[::Semaphore]> { //TODO: may `OneShot` be enough? command_buffers: command_buffer_ids .iter() .flat_map(|&cmb_id| &command_buffer_guard.get(cmb_id).raw), - wait_semaphores: Vec::new(), - signal_semaphores: &[], + wait_semaphores, + signal_semaphores: &[], //TODO: signal `sem_present`? }; unsafe { device.queue_group.queues[0] diff --git a/wgpu-native/src/swap_chain.rs b/wgpu-native/src/swap_chain.rs index bae5ceb88..0957f1cb1 100644 --- a/wgpu-native/src/swap_chain.rs +++ b/wgpu-native/src/swap_chain.rs @@ -33,6 +33,8 @@ pub(crate) struct Frame { pub comb: hal::command::CommandBuffer, } +//TODO: does it need a ref-counted lifetime? + pub(crate) struct SwapChain { pub raw: B::Swapchain, pub device_id: Stored, From e32112a89a389708983f550feac568cc173a919e Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 16 Jan 2019 09:15:56 -0500 Subject: [PATCH 07/10] Swapchain exposed on Rust side --- wgpu-native/src/instance.rs | 9 ++++++++- wgpu-native/src/lib.rs | 2 +- wgpu-native/src/swap_chain.rs | 13 +++++++++++-- wgpu-rs/Cargo.toml | 7 ++++--- wgpu-rs/src/lib.rs | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 7 deletions(-) diff --git a/wgpu-native/src/instance.rs b/wgpu-native/src/instance.rs index 38b84e355..8256d1dbc 100644 --- a/wgpu-native/src/instance.rs +++ b/wgpu-native/src/instance.rs @@ -50,7 +50,14 @@ pub extern "C" fn wgpu_create_instance() -> InstanceId { } } -#[cfg(not(feature = "remote"))] +#[cfg(all( + not(feature = "remote"), + any( + feature = "gfx-backend-vulkan", + feature = "gfx-backend-dx12", + feature = "gfx-backend-metal" + ) +))] #[no_mangle] pub extern "C" fn wgpu_instance_create_surface_from_winit( instance_id: InstanceId, diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index c957c1dbe..eb5728e1b 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -1,5 +1,5 @@ #[cfg(not(feature = "remote"))] -extern crate winit; +pub extern crate winit; #[cfg(feature = "gfx-backend-dx12")] extern crate gfx_backend_dx12 as back; diff --git a/wgpu-native/src/swap_chain.rs b/wgpu-native/src/swap_chain.rs index 0957f1cb1..3456b386b 100644 --- a/wgpu-native/src/swap_chain.rs +++ b/wgpu-native/src/swap_chain.rs @@ -52,10 +52,16 @@ pub struct SwapChainDescriptor { pub height: u32, } +#[repr(C)] +pub struct SwapChainOutput { + pub texture_id: TextureId, + pub view_id: TextureViewId, +} + #[no_mangle] pub extern "C" fn wgpu_swap_chain_get_next_texture( swap_chain_id: SwapChainId, -) -> TextureId { +) -> SwapChainOutput { let mut swap_chain_guard = HUB.swap_chains.write(); let swap_chain = swap_chain_guard.get_mut(swap_chain_id); let device_guard = HUB.devices.read(); @@ -81,7 +87,10 @@ pub extern "C" fn wgpu_swap_chain_get_next_texture( None => unreachable!(), } - frame.texture_id.value + SwapChainOutput { + texture_id: frame.texture_id.value, + view_id: frame.view_id.value, + } } #[no_mangle] diff --git a/wgpu-rs/Cargo.toml b/wgpu-rs/Cargo.toml index 3a64e84e2..3d421d62a 100644 --- a/wgpu-rs/Cargo.toml +++ b/wgpu-rs/Cargo.toml @@ -11,9 +11,10 @@ edition = "2018" [features] default = [] -metal = ["wgpu-native/gfx-backend-metal"] -dx12 = ["wgpu-native/gfx-backend-dx12"] -vulkan = ["wgpu-native/gfx-backend-vulkan"] +backed = [] +metal = ["wgpu-native/gfx-backend-metal", "backed"] +dx12 = ["wgpu-native/gfx-backend-dx12", "backed"] +vulkan = ["wgpu-native/gfx-backend-vulkan", "backed"] [dependencies] wgpu-native = { path = "../wgpu-native" } diff --git a/wgpu-rs/src/lib.rs b/wgpu-rs/src/lib.rs index f74343620..f0ca2af2c 100644 --- a/wgpu-rs/src/lib.rs +++ b/wgpu-rs/src/lib.rs @@ -13,6 +13,7 @@ pub use wgn::{ RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, RenderPassDescriptor, ShaderModuleDescriptor, ShaderStage, ShaderStageFlags, StoreOp, TextureDescriptor, TextureDimension, TextureFormat, TextureUsageFlags, TextureViewDescriptor, + SwapChainDescriptor, }; pub struct Instance { @@ -35,6 +36,14 @@ pub struct TextureView { id: wgn::TextureViewId, } +pub struct Surface { + id: wgn::SurfaceId, +} + +pub struct SwapChain { + id: wgn::SwapChainId, +} + pub struct BindGroupLayout { id: wgn::BindGroupLayoutId, } @@ -125,6 +134,13 @@ impl Instance { id: wgn::wgpu_instance_get_adapter(self.id, desc), } } + + #[cfg(feature = "backed")] + pub fn create_surface(&self, window: &::winit::Window) -> Surface { + Surface { + id: wgn::wgpu_instance_create_surface_from_winit(self.id, window) + } + } } impl Adapter { @@ -148,6 +164,7 @@ impl Device { } } + //TODO: borrow instead of new object? pub fn get_queue(&self) -> Queue { Queue { id: wgn::wgpu_device_get_queue(self.id), @@ -255,6 +272,12 @@ impl Device { id: wgn::wgpu_device_create_texture(self.id, &desc), } } + + pub fn create_swap_chain(&self, surface: &Surface, desc: &SwapChainDescriptor) -> SwapChain { + SwapChain { + id: wgn::wgpu_device_create_swap_chain(self.id, surface.id, desc), + } + } } impl Texture { @@ -351,3 +374,15 @@ impl Queue { ); } } + +impl SwapChain { + //TODO: borrow instead of new object? + pub fn get_next_texture(&self) -> (Texture, TextureView) { + let output = wgn::wgpu_swap_chain_get_next_texture(self.id); + (Texture { id: output.texture_id} , TextureView { id: output.view_id }) + } + + pub fn present(&self) { + wgn::wgpu_swap_chain_present(self.id); + } +} From c868db2cc70e20a9c7c3c3559f1144f761928836 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 17 Jan 2019 09:42:59 -0500 Subject: [PATCH 08/10] Windowing in the triangle example, more presentation bits --- examples/Cargo.toml | 1 + examples/hello_triangle_rust/main.rs | 109 ++++++++++++++++++++------- wgpu-native/Cargo.toml | 2 +- wgpu-native/src/device.rs | 18 ++++- wgpu-native/src/instance.rs | 15 ++-- wgpu-native/src/lib.rs | 2 +- wgpu-native/src/swap_chain.rs | 23 +++++- wgpu-rs/Cargo.toml | 8 +- wgpu-rs/src/lib.rs | 4 +- 9 files changed, 131 insertions(+), 51 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 4d4a5bf8c..426d30eda 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -14,6 +14,7 @@ path = "hello_triangle_rust/main.rs" [features] default = [] remote = ["wgpu-native/remote"] +winit = ["wgpu/winit"] metal = ["wgpu-native/gfx-backend-metal"] dx12 = ["wgpu-native/gfx-backend-dx12"] vulkan = ["wgpu-native/gfx-backend-vulkan"] diff --git a/examples/hello_triangle_rust/main.rs b/examples/hello_triangle_rust/main.rs index 402c9d01f..db5316175 100644 --- a/examples/hello_triangle_rust/main.rs +++ b/examples/hello_triangle_rust/main.rs @@ -1,4 +1,6 @@ extern crate wgpu; +extern crate wgpu_native; + fn main() { let instance = wgpu::Instance::new(); let adapter = instance.get_adapter(&wgpu::AdapterDescriptor { @@ -10,19 +12,6 @@ fn main() { }, }); - let texture = device.create_texture(&wgpu::TextureDescriptor { - size: wgpu::Extent3d { - width: 256, - height: 256, - depth: 1, - }, - array_size: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::R8g8b8a8Unorm, - usage: wgpu::TextureUsageFlags::OUTPUT_ATTACHMENT, - }); - let color_view = texture.create_default_texture_view(); - let vs_bytes = include_bytes!("./../data/hello_triangle.vert.spv"); let vs_module = device.create_shader_module(vs_bytes); let fs_bytes = include_bytes!("./../data/hello_triangle.frag.spv"); @@ -64,21 +53,89 @@ fn main() { depth_stencil_state: &depth_stencil_state, }); - let mut cmd_buf = device.create_command_buffer(&wgpu::CommandBufferDescriptor {}); - + #[cfg(feature = "winit")] { - let rpass = cmd_buf.begin_render_pass(&wgpu::RenderPassDescriptor { - color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { - attachment: &color_view, - load_op: wgpu::LoadOp::Clear, - store_op: wgpu::StoreOp::Store, - clear_color: wgpu::Color::GREEN, - }], - depth_stencil_attachment: None, + use wgpu_native::winit::{ControlFlow, Event, EventsLoop, Window, WindowEvent}; + + let mut events_loop = EventsLoop::new(); + let window = Window::new(&events_loop).unwrap(); + let size = window + .get_inner_size() + .unwrap() + .to_physical(window.get_hidpi_factor()); + + let surface = instance.create_surface(&window); + let swap_chain = device.create_swap_chain(&surface, &wgpu::SwapChainDescriptor { + usage: wgpu::TextureUsageFlags::OUTPUT_ATTACHMENT | wgpu::TextureUsageFlags::PRESENT, + format: wgpu::TextureFormat::B8g8r8a8Unorm, + width: size.width as u32, + height: size.height as u32, + }); + + events_loop.run_forever(|event| { + match event { + Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { + return ControlFlow::Break + } + _ => {} + } + + let (_, view) = swap_chain.get_next_texture(); + let mut cmd_buf = device.create_command_buffer(&wgpu::CommandBufferDescriptor {}); + { + let rpass = cmd_buf.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &view, + load_op: wgpu::LoadOp::Clear, + store_op: wgpu::StoreOp::Store, + clear_color: wgpu::Color::GREEN, + }], + depth_stencil_attachment: None, + }); + rpass.end_pass(); + } + + device + .get_queue() + .submit(&[cmd_buf]); + + swap_chain.present(); + + ControlFlow::Continue }); - rpass.end_pass(); } - let queue = device.get_queue(); - queue.submit(&[cmd_buf]); + #[cfg(not(feature = "winit"))] + { + let texture = device.create_texture(&wgpu::TextureDescriptor { + size: wgpu::Extent3d { + width: 256, + height: 256, + depth: 1, + }, + array_size: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::R8g8b8a8Unorm, + usage: wgpu::TextureUsageFlags::OUTPUT_ATTACHMENT, + }); + let color_view = texture.create_default_texture_view(); + + let mut cmd_buf = device.create_command_buffer(&wgpu::CommandBufferDescriptor {}); + { + let rpass = cmd_buf.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &color_view, + load_op: wgpu::LoadOp::Clear, + store_op: wgpu::StoreOp::Store, + clear_color: wgpu::Color::GREEN, + }], + depth_stencil_attachment: None, + }); + rpass.end_pass(); + } + + device + .get_queue() + .submit(&[cmd_buf]); + } } diff --git a/wgpu-native/Cargo.toml b/wgpu-native/Cargo.toml index e96199c0a..eeaf03c4a 100644 --- a/wgpu-native/Cargo.toml +++ b/wgpu-native/Cargo.toml @@ -25,4 +25,4 @@ gfx-backend-vulkan = { version = "0.1.0", optional = true } gfx-backend-dx12 = { version = "0.1.0", optional = true } gfx-backend-metal = { version = "0.1.0", optional = true } #rendy-memory = { git = "https://github.com/rustgd/rendy", rev = "ce7dd7f", features = ["gfx-hal"] } -winit = "0.18" +winit = { version = "0.18", optional = true } diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index 3a1e7164b..03860240d 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -539,6 +539,7 @@ pub extern "C" fn wgpu_queue_submit( .fetch_add(1, Ordering::Relaxed); let mut swap_chain_links = Vec::new(); + device.com_allocator.maintain(&device.raw); //TODO: if multiple command buffers are submitted, we can re-use the last // native command buffer of the previous chain instead of always creating @@ -883,10 +884,15 @@ pub extern "C" fn wgpu_device_create_swap_chain( let usage = conv::map_texture_usage(desc.usage, hal::format::Aspects::COLOR); if let Some(formats) = formats { - assert!(formats.contains(&config.format)); + assert!(formats.contains(&config.format), + "Requested format {:?} is not in supported list: {:?}", + config.format, formats); } - assert!(desc.width >= caps.extents.start.width && desc.width < caps.extents.end.width); - assert!(desc.height >= caps.extents.start.height && desc.width < caps.extents.end.height); + //TODO: properly exclusive range + assert!(desc.width >= caps.extents.start.width && desc.width <= caps.extents.end.width && + desc.height >= caps.extents.start.height && desc.height <= caps.extents.end.height, + "Requested size {}x{} is outside of the supported range: {:?}", + desc.width, desc.height, caps.extents); let (raw, backbuffer) = unsafe { device.raw @@ -914,7 +920,7 @@ pub extern "C" fn wgpu_device_create_swap_chain( ref_count: device.life_guard.ref_count.clone(), }, frames: Vec::with_capacity(num_frames as usize), - acquired: Vec::with_capacity(num_frames as usize), + acquired: Vec::with_capacity(1), //TODO: get it from gfx-hal? sem_available: device.raw.create_semaphore().unwrap(), command_pool, }); @@ -963,6 +969,10 @@ pub extern "C" fn wgpu_device_create_swap_chain( ref_count: texture.life_guard.ref_count.clone(), value: texture_guard.register(texture), }; + device.texture_tracker + .lock() + .query(&texture_id, TextureUsageFlags::WRITE_ALL); + let view = resource::TextureView { raw: view_raw, texture_id: texture_id.clone(), diff --git a/wgpu-native/src/instance.rs b/wgpu-native/src/instance.rs index 8256d1dbc..49fd308b2 100644 --- a/wgpu-native/src/instance.rs +++ b/wgpu-native/src/instance.rs @@ -1,7 +1,9 @@ use crate::registry::{HUB, Items}; -use crate::{WeaklyStored, Device, Surface, - AdapterId, DeviceId, InstanceId, SurfaceId, +use crate::{WeaklyStored, Device, + AdapterId, DeviceId, InstanceId, }; +#[cfg(feature = "winit")] +use crate::{Surface, SurfaceId}; use hal::{self, Instance as _Instance, PhysicalDevice as _PhysicalDevice}; @@ -50,14 +52,7 @@ pub extern "C" fn wgpu_create_instance() -> InstanceId { } } -#[cfg(all( - not(feature = "remote"), - any( - feature = "gfx-backend-vulkan", - feature = "gfx-backend-dx12", - feature = "gfx-backend-metal" - ) -))] +#[cfg(feature = "winit")] #[no_mangle] pub extern "C" fn wgpu_instance_create_surface_from_winit( instance_id: InstanceId, diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index eb5728e1b..7f4afa0e1 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -1,4 +1,4 @@ -#[cfg(not(feature = "remote"))] +#[cfg(feature = "winit")] pub extern crate winit; #[cfg(feature = "gfx-backend-dx12")] diff --git a/wgpu-native/src/swap_chain.rs b/wgpu-native/src/swap_chain.rs index 3456b386b..f822083d9 100644 --- a/wgpu-native/src/swap_chain.rs +++ b/wgpu-native/src/swap_chain.rs @@ -64,6 +64,9 @@ pub extern "C" fn wgpu_swap_chain_get_next_texture( ) -> SwapChainOutput { let mut swap_chain_guard = HUB.swap_chains.write(); let swap_chain = swap_chain_guard.get_mut(swap_chain_id); + assert_ne!(swap_chain.acquired.len(), swap_chain.acquired.capacity(), + "Unable to acquire any more swap chain images before presenting"); + let device_guard = HUB.devices.read(); let device = device_guard.get(swap_chain.device_id.value); @@ -119,7 +122,7 @@ pub extern "C" fn wgpu_swap_chain_present( frame.texture_id.value, &texture.life_guard.ref_count, resource::TextureUsageFlags::PRESENT, - TrackPermit::EXTEND, + TrackPermit::REPLACE, ) .unwrap(); @@ -146,8 +149,22 @@ pub extern "C" fn wgpu_swap_chain_present( frame.comb.finish(); // now prepare the GPU submission - device.raw.reset_fence(&frame.fence); + let submission = hal::Submission { + command_buffers: iter::once(&frame.comb), + wait_semaphores: None, + signal_semaphores: Some(&frame.sem_present), + }; + + device.raw.reset_fence(&frame.fence).unwrap(); device.queue_group.queues[0] - .submit_nosemaphores(iter::once(&frame.comb), Some(&frame.fence)); + .submit(submission, Some(&frame.fence)); + + swap_chain.raw + .present( + &mut device.queue_group.queues[0], + image_index, + iter::once(&frame.sem_present), + ) + .unwrap(); } } diff --git a/wgpu-rs/Cargo.toml b/wgpu-rs/Cargo.toml index 3d421d62a..4a6ad0efb 100644 --- a/wgpu-rs/Cargo.toml +++ b/wgpu-rs/Cargo.toml @@ -11,10 +11,10 @@ edition = "2018" [features] default = [] -backed = [] -metal = ["wgpu-native/gfx-backend-metal", "backed"] -dx12 = ["wgpu-native/gfx-backend-dx12", "backed"] -vulkan = ["wgpu-native/gfx-backend-vulkan", "backed"] +winit = ["wgpu-native/winit"] +metal = ["wgpu-native/gfx-backend-metal"] +dx12 = ["wgpu-native/gfx-backend-dx12"] +vulkan = ["wgpu-native/gfx-backend-vulkan"] [dependencies] wgpu-native = { path = "../wgpu-native" } diff --git a/wgpu-rs/src/lib.rs b/wgpu-rs/src/lib.rs index f0ca2af2c..dad8fe75a 100644 --- a/wgpu-rs/src/lib.rs +++ b/wgpu-rs/src/lib.rs @@ -135,8 +135,8 @@ impl Instance { } } - #[cfg(feature = "backed")] - pub fn create_surface(&self, window: &::winit::Window) -> Surface { + #[cfg(feature = "winit")] + pub fn create_surface(&self, window: &wgn::winit::Window) -> Surface { Surface { id: wgn::wgpu_instance_create_surface_from_winit(self.id, window) } From 2221b112c78e2189df35a49fe049f29e38820767 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 17 Jan 2019 21:11:01 -0500 Subject: [PATCH 09/10] Fix command buffer recycling --- examples/hello_triangle_rust/main.rs | 19 +++++++++++--- wgpu-native/src/command/allocator.rs | 33 ++++++++---------------- wgpu-native/src/command/mod.rs | 10 +++++--- wgpu-native/src/device.rs | 38 ++++++++++++++++++++-------- 4 files changed, 59 insertions(+), 41 deletions(-) diff --git a/examples/hello_triangle_rust/main.rs b/examples/hello_triangle_rust/main.rs index db5316175..ff298b5b5 100644 --- a/examples/hello_triangle_rust/main.rs +++ b/examples/hello_triangle_rust/main.rs @@ -55,7 +55,7 @@ fn main() { #[cfg(feature = "winit")] { - use wgpu_native::winit::{ControlFlow, Event, EventsLoop, Window, WindowEvent}; + use wgpu_native::winit::{ControlFlow, Event, ElementState, EventsLoop, KeyboardInput, Window, WindowEvent, VirtualKeyCode}; let mut events_loop = EventsLoop::new(); let window = Window::new(&events_loop).unwrap(); @@ -74,8 +74,20 @@ fn main() { events_loop.run_forever(|event| { match event { - Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { - return ControlFlow::Break + Event::WindowEvent { event, .. } => match event { + WindowEvent::KeyboardInput { + input: KeyboardInput { virtual_keycode: Some(code), state: ElementState::Pressed, .. }, + .. + } => match code { + VirtualKeyCode::Escape => { + return ControlFlow::Break + } + _ => {} + } + WindowEvent::CloseRequested => { + return ControlFlow::Break + } + _ => {} } _ => {} } @@ -100,7 +112,6 @@ fn main() { .submit(&[cmd_buf]); swap_chain.present(); - ControlFlow::Continue }); } diff --git a/wgpu-native/src/command/allocator.rs b/wgpu-native/src/command/allocator.rs index 65f004ad0..b27b8eb1c 100644 --- a/wgpu-native/src/command/allocator.rs +++ b/wgpu-native/src/command/allocator.rs @@ -1,14 +1,14 @@ use super::CommandBuffer; use crate::track::Tracker; -use crate::{DeviceId, LifeGuard, Stored}; +use crate::{DeviceId, LifeGuard, Stored, SubmissionIndex}; use hal::command::RawCommandBuffer; use hal::pool::RawCommandPool; use hal::Device; +use parking_lot::Mutex; use std::collections::HashMap; -//TODO: use `parking_lot::Mutex`? -use std::sync::Mutex; +use std::sync::atomic::Ordering; use std::thread; struct CommandPool { @@ -29,7 +29,6 @@ impl CommandPool { struct Inner { pools: HashMap>, - fences: Vec, pending: Vec>, } @@ -42,7 +41,6 @@ impl Inner { } pool.available.push(raw); } - self.fences.push(cmd_buf.fence); } } @@ -57,7 +55,6 @@ impl CommandAllocator { queue_family, inner: Mutex::new(Inner { pools: HashMap::new(), - fences: Vec::new(), pending: Vec::new(), }), } @@ -69,15 +66,7 @@ impl CommandAllocator { device: &B::Device, ) -> CommandBuffer { let thread_id = thread::current().id(); - let mut inner = self.inner.lock().unwrap(); - - let fence = match inner.fences.pop() { - Some(fence) => { - unsafe { device.reset_fence(&fence).unwrap() }; - fence - } - None => device.create_fence(false).unwrap(), - }; + let mut inner = self.inner.lock(); let pool = inner.pools.entry(thread_id).or_insert_with(|| CommandPool { raw: unsafe { @@ -93,7 +82,6 @@ impl CommandAllocator { CommandBuffer { raw: vec![init], - fence, recorded_thread_id: thread_id, device_id, life_guard: LifeGuard::new(), @@ -104,7 +92,7 @@ impl CommandAllocator { } pub fn extend(&self, cmd_buf: &CommandBuffer) -> B::CommandBuffer { - let mut inner = self.inner.lock().unwrap(); + let mut inner = self.inner.lock(); let pool = inner.pools.get_mut(&cmd_buf.recorded_thread_id).unwrap(); if pool.available.is_empty() { @@ -116,17 +104,18 @@ impl CommandAllocator { } pub fn submit(&self, cmd_buf: CommandBuffer) { - self.inner.lock().unwrap().pending.push(cmd_buf); + self.inner.lock().pending.push(cmd_buf); } pub fn recycle(&self, cmd_buf: CommandBuffer) { - self.inner.lock().unwrap().recycle(cmd_buf); + self.inner.lock().recycle(cmd_buf); } - pub fn maintain(&self, device: &B::Device) { - let mut inner = self.inner.lock().unwrap(); + pub fn maintain(&self, device: &B::Device, last_done: SubmissionIndex) { + let mut inner = self.inner.lock(); for i in (0..inner.pending.len()).rev() { - if unsafe { device.get_fence_status(&inner.pending[i].fence).unwrap() } { + let index = inner.pending[i].life_guard.submission_index.load(Ordering::Acquire); + if index <= last_done { let cmd_buf = inner.pending.swap_remove(i); inner.recycle(cmd_buf); } diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index 917209262..99de7f2ee 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -12,8 +12,11 @@ use crate::swap_chain::{SwapChainLink, SwapImageEpoch}; use crate::track::{BufferTracker, TextureTracker}; use crate::{conv, resource}; use crate::{ - BufferId, BufferUsageFlags, Color, CommandBufferId, ComputePassId, DeviceId, LifeGuard, - Origin3d, RenderPassId, Stored, TextureId, TextureUsageFlags, TextureViewId, WeaklyStored, B, + BufferId, CommandBufferId, ComputePassId, DeviceId, + RenderPassId, TextureId, TextureViewId, + BufferUsageFlags, TextureUsageFlags, Color, Origin3d, + LifeGuard, Stored, WeaklyStored, + B, }; use hal::command::RawCommandBuffer; @@ -82,10 +85,9 @@ pub struct TextureCopyView { pub struct CommandBuffer { pub(crate) raw: Vec, - fence: B::Fence, recorded_thread_id: ThreadId, device_id: Stored, - life_guard: LifeGuard, + pub(crate) life_guard: LifeGuard, pub(crate) buffer_tracker: BufferTracker, pub(crate) texture_tracker: TextureTracker, pub(crate) swap_chain_links: Vec>, diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index 03860240d..6060a0c77 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -105,12 +105,16 @@ impl DestroyedResources { } } - fn cleanup(&mut self, raw: &B::Device) { + /// Returns the last submission index that is done. + fn cleanup(&mut self, raw: &B::Device) -> SubmissionIndex { + let mut last_done = 0; + for i in (0..self.active.len()).rev() { if unsafe { raw.get_fence_status(&self.active[i].fence).unwrap() } { let a = self.active.swap_remove(i); + last_done = last_done.max(a.index); self.free.extend(a.resources); unsafe { raw.destroy_fence(a.fence); @@ -128,6 +132,8 @@ impl DestroyedResources { } } } + + last_done } } @@ -539,7 +545,6 @@ pub extern "C" fn wgpu_queue_submit( .fetch_add(1, Ordering::Relaxed); let mut swap_chain_links = Vec::new(); - device.com_allocator.maintain(&device.raw); //TODO: if multiple command buffers are submitted, we can re-use the last // native command buffer of the previous chain instead of always creating @@ -550,6 +555,8 @@ pub extern "C" fn wgpu_queue_submit( let comb = command_buffer_guard.get_mut(cmb_id); swap_chain_links.extend(comb.swap_chain_links.drain(..)); // update submission IDs + comb.life_guard.submission_index + .store(old_submit_index, Ordering::Release); for id in comb.buffer_tracker.used() { buffer_guard .get(id) @@ -620,17 +627,21 @@ pub extern "C" fn wgpu_queue_submit( } } - { + let last_done = { let mut destroyed = device.destroyed.lock(); destroyed.triage_referenced(&mut *buffer_guard, &mut *texture_guard); - destroyed.cleanup(&device.raw); + let last_done = destroyed.cleanup(&device.raw); destroyed.active.push(ActiveSubmission { index: old_submit_index + 1, fence, resources: Vec::new(), }); - } + + last_done + }; + + device.com_allocator.maintain(&device.raw, last_done); // finally, return the command buffers to the allocator for &cmb_id in command_buffer_ids { @@ -864,15 +875,15 @@ pub extern "C" fn wgpu_device_create_swap_chain( ) -> SwapChainId { let device_guard = HUB.devices.read(); let device = device_guard.get(device_id); - let adapter_guard = HUB.adapters.read(); - let physical_device = &adapter_guard.get(device.adapter_id.0).physical_device; let mut surface_guard = HUB.surfaces.write(); let surface = surface_guard.get_mut(surface_id); - let mut texture_guard = HUB.textures.write(); - let mut texture_view_guard = HUB.texture_views.write(); - let mut swap_chain_guard = HUB.swap_chains.write(); - let (caps, formats, _present_modes, _composite_alphas) = surface.raw.compatibility(physical_device); + let (caps, formats, _present_modes, _composite_alphas) = { + let adapter_guard = HUB.adapters.read(); + let adapter = adapter_guard.get(device.adapter_id.0); + assert!(surface.raw.supports_queue_family(&adapter.queue_families[0])); + surface.raw.compatibility(&adapter.physical_device) + }; let num_frames = caps.image_count.start; //TODO: configure? let frame_format = conv::map_texture_format(desc.format); let config = hal::SwapchainConfig::new( @@ -912,6 +923,8 @@ pub extern "C" fn wgpu_device_create_swap_chain( .unwrap() }; + let mut swap_chain_guard = HUB.swap_chains.write(); + let swap_chain_id = swap_chain_guard .register(swap_chain::SwapChain { raw, @@ -931,6 +944,9 @@ pub extern "C" fn wgpu_device_create_swap_chain( hal::Backbuffer::Framebuffer(_) => panic!("Deprecated API detected!"), }; + let mut texture_guard = HUB.textures.write(); + let mut texture_view_guard = HUB.texture_views.write(); + for (i, image) in images.into_iter().enumerate() { let kind = hal::image::Kind::D2(desc.width, desc.height, 1, 1); let full_range = hal::image::SubresourceRange { From 5deb6e2047103d571743816b7bbb30cc45de1138 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 17 Jan 2019 22:32:34 -0500 Subject: [PATCH 10/10] DX11 support --- Cargo.lock | 29 +++++++++++++++++++++++++++++ examples/Cargo.toml | 1 + wgpu-native/Cargo.toml | 1 + wgpu-native/src/instance.rs | 14 +++++--------- wgpu-native/src/lib.rs | 5 ++++- wgpu-rs/Cargo.toml | 1 + 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88e9fecea..a2d8f8a54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -288,6 +288,24 @@ name = "gcc" version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "gfx-backend-dx11" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derivative 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-hal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "range-alloc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "spirv_cross 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winit 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wio 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gfx-backend-dx12" version = "0.1.0" @@ -1069,6 +1087,7 @@ name = "wgpu-native" version = "0.1.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-backend-dx11 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx-backend-dx12 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx-backend-empty 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx-backend-metal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1129,6 +1148,14 @@ dependencies = [ "x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "wio" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "x11" version = "2.18.1" @@ -1202,6 +1229,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum gfx-backend-dx11 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7751e630a3472d96b1a0ce9cd6742f2e17c0f71a6e833f822b914a11f89bd7db" "checksum gfx-backend-dx12 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c373f40998da0fd605a7a90ce8d775a8cbcb06558edc2ea9740df1db2077686" "checksum gfx-backend-empty 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bb068297aed95a014abaa01738986c2ed5d08c5f9f152c992300c415e9b917c" "checksum gfx-backend-metal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68fa011e32280f7566bddbb736734291b685c812087c99bc848d6ac7ae3e0b7f" @@ -1294,6 +1322,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum winit 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c57c15bd4c0ef18dff33e263e452abe32d00e2e05771cacaa410a14cc1c0776" +"checksum wio 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8a31e8a268d6941ffb7f8d7989fc93e4692bd3e75a27d400a72b4be1dadb213" "checksum x11 2.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39697e3123f715483d311b5826e254b6f3cfebdd83cf7ef3358f579c3d68e235" "checksum x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)" = "940586acb859ea05c53971ac231685799a7ec1dee66ac0bccc0e6ad96e06b4e3" "checksum xcb 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5e917a3f24142e9ff8be2414e36c649d47d6cc2ba81f16201cdef96e533e02de" diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 426d30eda..a180fb5f2 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -16,6 +16,7 @@ default = [] remote = ["wgpu-native/remote"] winit = ["wgpu/winit"] metal = ["wgpu-native/gfx-backend-metal"] +dx11 = ["wgpu-native/gfx-backend-dx11"] dx12 = ["wgpu-native/gfx-backend-dx12"] vulkan = ["wgpu-native/gfx-backend-vulkan"] diff --git a/wgpu-native/Cargo.toml b/wgpu-native/Cargo.toml index eeaf03c4a..10091a677 100644 --- a/wgpu-native/Cargo.toml +++ b/wgpu-native/Cargo.toml @@ -22,6 +22,7 @@ parking_lot = { version = "0.7" } gfx-hal = "0.1.0" gfx-backend-empty = "0.1.0" gfx-backend-vulkan = { version = "0.1.0", optional = true } +gfx-backend-dx11 = { version = "0.1.0", optional = true } gfx-backend-dx12 = { version = "0.1.0", optional = true } gfx-backend-metal = { version = "0.1.0", optional = true } #rendy-memory = { git = "https://github.com/rustgd/rendy", rev = "ce7dd7f", features = ["gfx-hal"] } diff --git a/wgpu-native/src/instance.rs b/wgpu-native/src/instance.rs index 49fd308b2..6b8159984 100644 --- a/wgpu-native/src/instance.rs +++ b/wgpu-native/src/instance.rs @@ -35,21 +35,17 @@ pub struct DeviceDescriptor { pub extern "C" fn wgpu_create_instance() -> InstanceId { #[cfg(any( feature = "gfx-backend-vulkan", + feature = "gfx-backend-dx11", feature = "gfx-backend-dx12", feature = "gfx-backend-metal" ))] { let inst = ::back::Instance::create("wgpu", 1); - HUB.instances.write().register(inst) - } - #[cfg(not(any( - feature = "gfx-backend-vulkan", - feature = "gfx-backend-dx12", - feature = "gfx-backend-metal" - )))] - { - unimplemented!() + if true { + return HUB.instances.write().register(inst); + } } + unimplemented!() } #[cfg(feature = "winit")] diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index 7f4afa0e1..d73f1c33e 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -1,12 +1,15 @@ #[cfg(feature = "winit")] pub extern crate winit; +#[cfg(feature = "gfx-backend-dx11")] +extern crate gfx_backend_dx11 as back; #[cfg(feature = "gfx-backend-dx12")] extern crate gfx_backend_dx12 as back; #[cfg(not(any( feature = "gfx-backend-vulkan", + feature = "gfx-backend-dx11", feature = "gfx-backend-dx12", - feature = "gfx-backend-metal" + feature = "gfx-backend-metal", )))] extern crate gfx_backend_empty as back; #[cfg(feature = "gfx-backend-metal")] diff --git a/wgpu-rs/Cargo.toml b/wgpu-rs/Cargo.toml index 4a6ad0efb..0a08acb8e 100644 --- a/wgpu-rs/Cargo.toml +++ b/wgpu-rs/Cargo.toml @@ -13,6 +13,7 @@ edition = "2018" default = [] winit = ["wgpu-native/winit"] metal = ["wgpu-native/gfx-backend-metal"] +dx11 = ["wgpu-native/gfx-backend-dx11"] dx12 = ["wgpu-native/gfx-backend-dx12"] vulkan = ["wgpu-native/gfx-backend-vulkan"]