diff --git a/Cargo.lock b/Cargo.lock index 2e200e78dd..a7be12ee2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -457,7 +457,7 @@ dependencies = [ [[package]] name = "gfx-auxil" version = "0.9.0" -source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" +source = "git+https://github.com/gfx-rs/gfx?rev=7a60e1c13abef5973c22f2194c539403871f1085#7a60e1c13abef5973c22f2194c539403871f1085" dependencies = [ "fxhash", "gfx-hal", @@ -467,12 +467,13 @@ dependencies = [ [[package]] name = "gfx-backend-dx11" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" +source = "git+https://github.com/gfx-rs/gfx?rev=7a60e1c13abef5973c22f2194c539403871f1085#7a60e1c13abef5973c22f2194c539403871f1085" dependencies = [ "arrayvec", "bitflags", "gfx-auxil", "gfx-hal", + "gfx-renderdoc", "libloading 0.7.0", "log", "parking_lot", @@ -488,7 +489,7 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" +source = "git+https://github.com/gfx-rs/gfx?rev=7a60e1c13abef5973c22f2194c539403871f1085#7a60e1c13abef5973c22f2194c539403871f1085" dependencies = [ "arrayvec", "bit-set", @@ -496,6 +497,7 @@ dependencies = [ "d3d12", "gfx-auxil", "gfx-hal", + "gfx-renderdoc", "log", "parking_lot", "range-alloc", @@ -509,7 +511,7 @@ dependencies = [ [[package]] name = "gfx-backend-empty" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" +source = "git+https://github.com/gfx-rs/gfx?rev=7a60e1c13abef5973c22f2194c539403871f1085#7a60e1c13abef5973c22f2194c539403871f1085" dependencies = [ "gfx-hal", "log", @@ -519,7 +521,7 @@ dependencies = [ [[package]] name = "gfx-backend-gl" version = "0.8.1" -source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" +source = "git+https://github.com/gfx-rs/gfx?rev=7a60e1c13abef5973c22f2194c539403871f1085#7a60e1c13abef5973c22f2194c539403871f1085" dependencies = [ "arrayvec", "bitflags", @@ -542,7 +544,7 @@ dependencies = [ [[package]] name = "gfx-backend-metal" version = "0.8.1" -source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" +source = "git+https://github.com/gfx-rs/gfx?rev=7a60e1c13abef5973c22f2194c539403871f1085#7a60e1c13abef5973c22f2194c539403871f1085" dependencies = [ "arrayvec", "bitflags", @@ -568,21 +570,20 @@ dependencies = [ [[package]] name = "gfx-backend-vulkan" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" +source = "git+https://github.com/gfx-rs/gfx?rev=7a60e1c13abef5973c22f2194c539403871f1085#7a60e1c13abef5973c22f2194c539403871f1085" dependencies = [ "arrayvec", "ash", "byteorder", "core-graphics-types", "gfx-hal", + "gfx-renderdoc", "inplace_it", - "libloading 0.7.0", "log", "naga", "objc", "parking_lot", "raw-window-handle", - "renderdoc-sys", "smallvec", "winapi 0.3.9", ] @@ -590,7 +591,7 @@ dependencies = [ [[package]] name = "gfx-hal" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" +source = "git+https://github.com/gfx-rs/gfx?rev=7a60e1c13abef5973c22f2194c539403871f1085#7a60e1c13abef5973c22f2194c539403871f1085" dependencies = [ "bitflags", "naga", @@ -598,6 +599,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "gfx-renderdoc" +version = "0.1.0" +source = "git+https://github.com/gfx-rs/gfx?rev=7a60e1c13abef5973c22f2194c539403871f1085#7a60e1c13abef5973c22f2194c539403871f1085" +dependencies = [ + "libloading 0.7.0", + "log", + "renderdoc-sys", +] + [[package]] name = "glow" version = "0.9.0" @@ -1169,7 +1180,7 @@ dependencies = [ [[package]] name = "range-alloc" version = "0.1.2" -source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" +source = "git+https://github.com/gfx-rs/gfx?rev=7a60e1c13abef5973c22f2194c539403871f1085#7a60e1c13abef5973c22f2194c539403871f1085" [[package]] name = "raw-window-handle" @@ -1619,6 +1630,7 @@ name = "wgpu-core" version = "0.8.0" dependencies = [ "arrayvec", + "ash", "bitflags", "cfg_aliases", "copyless", diff --git a/wgpu-core/Cargo.toml b/wgpu-core/Cargo.toml index 1772bd4d0a..57fbf6f623 100644 --- a/wgpu-core/Cargo.toml +++ b/wgpu-core/Cargo.toml @@ -39,24 +39,26 @@ thiserror = "1" gpu-alloc = "0.4" gpu-descriptor = "0.1" -hal = { package = "gfx-hal", git = "https://github.com/gfx-rs/gfx", rev = "27a1dae3796d33d23812f2bb8c7e3b5aea18b521" } -gfx-backend-empty = { git = "https://github.com/gfx-rs/gfx", rev = "27a1dae3796d33d23812f2bb8c7e3b5aea18b521" } +hal = { package = "gfx-hal", git = "https://github.com/gfx-rs/gfx", rev = "7a60e1c13abef5973c22f2194c539403871f1085" } +gfx-backend-empty = { git = "https://github.com/gfx-rs/gfx", rev = "7a60e1c13abef5973c22f2194c539403871f1085" } [target.'cfg(all(not(target_arch = "wasm32"), all(unix, not(target_os = "ios"), not(target_os = "macos"))))'.dependencies] -gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "27a1dae3796d33d23812f2bb8c7e3b5aea18b521", features = ["naga"] } -gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx", rev = "27a1dae3796d33d23812f2bb8c7e3b5aea18b521" } +gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "7a60e1c13abef5973c22f2194c539403871f1085", features = ["naga"] } +gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx", rev = "7a60e1c13abef5973c22f2194c539403871f1085" } +ash = "0.32" [target.'cfg(all(not(target_arch = "wasm32"), any(target_os = "ios", target_os = "macos")))'.dependencies] -gfx-backend-metal = { git = "https://github.com/gfx-rs/gfx", rev = "27a1dae3796d33d23812f2bb8c7e3b5aea18b521" } +gfx-backend-metal = { git = "https://github.com/gfx-rs/gfx", rev = "7a60e1c13abef5973c22f2194c539403871f1085" } #TODO: could also depend on gfx-backend-vulkan for Vulkan Portability [target.'cfg(all(not(target_arch = "wasm32"), windows))'.dependencies] -gfx-backend-dx12 = { git = "https://github.com/gfx-rs/gfx", rev = "27a1dae3796d33d23812f2bb8c7e3b5aea18b521" } -gfx-backend-dx11 = { git = "https://github.com/gfx-rs/gfx", rev = "27a1dae3796d33d23812f2bb8c7e3b5aea18b521" } -gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "27a1dae3796d33d23812f2bb8c7e3b5aea18b521", features = ["naga"] } +gfx-backend-dx12 = { git = "https://github.com/gfx-rs/gfx", rev = "7a60e1c13abef5973c22f2194c539403871f1085" } +gfx-backend-dx11 = { git = "https://github.com/gfx-rs/gfx", rev = "7a60e1c13abef5973c22f2194c539403871f1085" } +gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "7a60e1c13abef5973c22f2194c539403871f1085", features = ["naga"] } +ash = "0.32" [target.'cfg(target_arch = "wasm32")'.dependencies] -gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx", rev = "27a1dae3796d33d23812f2bb8c7e3b5aea18b521" } +gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx", rev = "7a60e1c13abef5973c22f2194c539403871f1085" } [dependencies.naga] git = "https://github.com/gfx-rs/naga" diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index 79526de1e5..ace0c444cc 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -496,7 +496,7 @@ fn check_device_features( } struct RenderAttachment<'a> { - texture_id: &'a Stored, + texture_id: Option<&'a Stored>, selector: &'a TextureSelector, previous_use: Option, new_use: TextureUse, @@ -582,6 +582,9 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { TextureViewInner::SwapChain { .. } => { return Err(RenderPassErrorInner::SwapChainImageAsDepthStencil); } + TextureViewInner::Raw { .. } => { + return Err(RenderPassErrorInner::SwapChainImageAsDepthStencil); + } }; // Using render pass for transition. @@ -596,7 +599,7 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { TextureUse::ATTACHMENT_WRITE }; render_attachments.push(RenderAttachment { - texture_id: source_id, + texture_id: Some(source_id), selector: &view.selector, previous_use, new_use, @@ -647,7 +650,7 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { .query(source_id.value, view.selector.clone()); let new_use = TextureUse::ATTACHMENT_WRITE; render_attachments.push(RenderAttachment { - texture_id: source_id, + texture_id: Some(source_id), selector: &view.selector, previous_use, new_use, @@ -674,6 +677,31 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { }; start..end } + TextureViewInner::Raw { .. } => { + /* TODO: + let previous_use = cmd_buf + .trackers + .textures + .query(source_id.value, view.selector.clone());*/ + let previous_use = None; + let new_use = TextureUse::ATTACHMENT_WRITE; + render_attachments.push(RenderAttachment { + texture_id: None, + selector: &view.selector, + previous_use, + new_use, + }); + + let new_layout = + conv::map_texture_state(new_use, hal::format::Aspects::COLOR).1; + let old_layout = match previous_use { + Some(usage) => { + conv::map_texture_state(usage, hal::format::Aspects::COLOR).1 + } + None => new_layout, + }; + old_layout..new_layout + } }; let color_at = hal::pass::Attachment { @@ -715,7 +743,7 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { .query(source_id.value, view.selector.clone()); let new_use = TextureUse::ATTACHMENT_WRITE; render_attachments.push(RenderAttachment { - texture_id: source_id, + texture_id: Some(source_id), selector: &view.selector, previous_use, new_use, @@ -736,6 +764,10 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { used_swap_chain = Some(source_id.clone()); hal::image::Layout::Undefined..hal::image::Layout::Present } + TextureViewInner::Raw { .. } => { + // TODO: This is only valid for OpenXR + hal::image::Layout::ColorAttachmentOptimal..hal::image::Layout::ColorAttachmentOptimal + } }; let resolve_at = hal::pass::Attachment { @@ -880,6 +912,7 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { let raw_views = view_data.map(|view| match view.inner { TextureViewInner::Native { ref raw, .. } => raw, TextureViewInner::SwapChain { ref image, .. } => Borrow::borrow(image), + TextureViewInner::Raw { ref raw } => raw, }); //Note: the order of iteration has to match `AttachmentData::all()` @@ -977,15 +1010,17 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { profiling::scope!("finish", "RenderPassInfo"); for ra in self.render_attachments { - let texture = &texture_guard[ra.texture_id.value]; + let texture_id = if let Some(id) = ra.texture_id { id } else { continue }; + + let texture = &texture_guard[texture_id.value]; check_texture_usage(texture.usage, TextureUsage::RENDER_ATTACHMENT)?; // the tracker set of the pass is always in "extend" mode self.trackers .textures .change_extend( - ra.texture_id.value, - &ra.texture_id.ref_count, + texture_id.value, + &texture_id.ref_count, ra.selector.clone(), ra.new_use, ) @@ -998,8 +1033,8 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { self.trackers .textures .prepend( - ra.texture_id.value, - &ra.texture_id.ref_count, + texture_id.value, + &texture_id.ref_count, ra.selector.clone(), usage, ) diff --git a/wgpu-core/src/device/life.rs b/wgpu-core/src/device/life.rs index 2a7d3b1b35..af2deb62b8 100644 --- a/wgpu-core/src/device/life.rs +++ b/wgpu-core/src/device/life.rs @@ -448,6 +448,7 @@ impl LifetimeTracker { raw } resource::TextureViewInner::SwapChain { .. } => unreachable!(), + resource::TextureViewInner::Raw { .. } => unreachable!(), }; let submit_index = res.life_guard.submission_index.load(Ordering::Acquire); diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index de2795e839..9c3de66698 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -29,6 +29,7 @@ use thiserror::Error; use wgt::{BufferAddress, InputStepMode, TextureDimension, TextureFormat, TextureViewDimension}; use std::{ + any::Any, borrow::Cow, collections::{hash_map::Entry, BTreeMap}, iter, @@ -36,7 +37,7 @@ use std::{ mem, ops::Range, ptr, - sync::atomic::Ordering, + sync::{atomic::Ordering, Arc}, }; pub mod alloc; @@ -291,6 +292,7 @@ pub struct Device { pending_writes: queue::PendingWrites, #[cfg(feature = "trace")] pub(crate) trace: Option>, + guard: Option>, } #[derive(Clone, Debug, Error)] @@ -311,6 +313,7 @@ impl Device { downlevel: wgt::DownlevelProperties, desc: &DeviceDescriptor, trace_path: Option<&std::path::Path>, + guard: Option>, ) -> Result { let cmd_allocator = command::CommandAllocator::new(queue_group.family, &raw) .or(Err(CreateDeviceError::OutOfMemory))?; @@ -389,6 +392,7 @@ impl Device { downlevel, spv_options, pending_writes: queue::PendingWrites::new(), + guard, }) } @@ -1695,6 +1699,9 @@ impl Device { resource::TextureViewInner::SwapChain { .. } => { return Err(Error::SwapChainImage); } + resource::TextureViewInner::Raw { .. } => { + return Err(Error::SwapChainImage); + } } } Br::TextureViewArray(ref bindings_array) => { @@ -1754,6 +1761,9 @@ impl Device { resource::TextureViewInner::SwapChain { .. } => { Err(Error::SwapChainImage) } + resource::TextureViewInner::Raw { .. } => { + Err(Error::SwapChainImage) + } } }) .collect::>()? @@ -2626,6 +2636,66 @@ impl Device { } } +impl Device { + unsafe fn create_raw_vulkan_texture_view( + &self, + adapter: &crate::instance::Adapter, + raw_image: ash::vk::Image, + view_type: ash::vk::ImageViewType, + desc: &resource::TextureViewDescriptor, + extent: wgt::Extent3d, + ) -> resource::TextureView { + let format = desc.format.unwrap(); + let raw_format = conv::map_texture_format(format, self.private_features); + let format_features = adapter.get_texture_format_features(format); + + let aspects = raw_format.surface_desc().aspects; + let range = hal::image::SubresourceRange { + aspects, + level_start: desc.base_mip_level as _, + level_count: desc.mip_level_count.map(|v| v.get() as _), + layer_start: desc.base_array_layer as _, + layer_count: desc.array_layer_count.map(|v| v.get() as _), + }; + + let view_dim = desc.dimension.unwrap(); + + let level_end = desc.mip_level_count.unwrap().get() as u8; + let layer_end = desc.array_layer_count.unwrap().get() as u16; + let selector = TextureSelector { + levels: desc.base_mip_level as u8..level_end, + layers: desc.base_array_layer as u16..layer_end, + }; + + let raw = self.raw.image_view_from_raw( + raw_image, + view_type, + raw_format, + hal::format::Swizzle::NO, + hal::image::Usage::COLOR_ATTACHMENT, + range, + ).unwrap(); + + resource::TextureView { + inner: resource::TextureViewInner::Raw { raw }, + aspects, + format, + format_features, + dimension: view_dim, + extent, + samples: 1, + framebuffer_attachment: hal::image::FramebufferAttachment { + usage: hal::image::Usage::COLOR_ATTACHMENT, + view_caps: hal::image::ViewCapabilities::empty(), + format: raw_format, + }, + sampled_internal_use: resource::TextureUse::SAMPLED, + selector, + life_guard: LifeGuard::new(desc.label.borrow_or_default()), + } + } +} + impl Device { pub(crate) fn destroy_bind_group(&self, bind_group: binding_model::BindGroup) { self.desc_allocator @@ -3199,6 +3269,46 @@ impl Global { (id, Some(error)) } + pub unsafe fn device_create_raw_vulkan_texture_view( + &self, + device_id: id::DeviceId, + raw_image: ash::vk::Image, + view_type: ash::vk::ImageViewType, + desc: &resource::TextureViewDescriptor, + extent: wgt::Extent3d, + id_in: Input, + ) -> id::TextureViewId { + profiling::scope!("create_raw_vulkan_texture_view", "Device"); + + let hub = crate::backend::Vulkan::hub(self); + let mut token = Token::root(); + let fid = hub.texture_views.prepare(id_in); + + let (adapter_guard, mut token) = hub.adapters.read(&mut token); + let (device_guard, mut token) = hub.devices.read(&mut token); + + let device = device_guard.get(device_id).unwrap(); + let adapter = &adapter_guard[device.adapter_id.value]; + + let view = device.create_raw_vulkan_texture_view( + adapter, + raw_image, + view_type, + desc, + extent, + ); + let ref_count = view.life_guard.add_ref(); + let id = fid.assign(view, &mut token); + + device + .trackers + .lock() + .views + .init(id, ref_count, PhantomData) + .unwrap(); + return id.0; + } + pub fn texture_label(&self, id: id::TextureId) -> String { B::hub(self).textures.label_for_resource(id) } @@ -3377,6 +3487,9 @@ impl Global { resource::TextureViewInner::SwapChain { .. } => { return Err(resource::TextureViewDestroyError::SwapChainImage) } + resource::TextureViewInner::Raw { .. } => { + return Err(resource::TextureViewDestroyError::SwapChainImage) + } }; (last_submit_index, device_id) } diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 3d92bfeb63..d2ff8db685 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -26,7 +26,7 @@ use crate::id::QuerySetId; use crate::resource::QuerySet; #[cfg(debug_assertions)] use std::cell::Cell; -use std::{fmt::Debug, marker::PhantomData, ops}; +use std::{any::Any, sync::Arc, fmt::Debug, marker::PhantomData, ops}; /// A simple structure to manage identities of objects. #[derive(Debug)] @@ -615,6 +615,7 @@ impl Hub { } } TextureViewInner::SwapChain { .. } => {} //TODO + TextureViewInner::Raw { .. } => {} //TODO } } } @@ -756,11 +757,20 @@ impl Hubs { } } +struct NoDebug(T); + +impl Debug for NoDebug { + fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Result::Ok(()) + } +} + #[derive(Debug)] pub struct Global { pub instance: Instance, pub surfaces: Registry, hubs: Hubs, + guard: NoDebug>>, } impl Global { @@ -770,6 +780,27 @@ impl Global { instance: Instance::new(name, 1, backends), surfaces: Registry::without_backend(&factory, "Surface"), hubs: Hubs::new(&factory), + guard: NoDebug(None), + } + } + + pub unsafe fn required_vulkan_extensions(entry: &ash::Entry) -> Vec<&'static std::ffi::CStr> { + Instance::required_vulkan_extensions(entry) + } + + pub unsafe fn new_raw_vulkan( + entry: ash::Entry, + instance: ash::Instance, + extensions: Vec<&'static std::ffi::CStr>, + parent_context: Arc, + factory: G, + ) -> Self { + profiling::scope!("new_raw_vulkan", "Global"); + Self { + instance: Instance::new_raw_vulkan(entry, instance, extensions), + surfaces: Registry::without_backend(&factory, "Surface"), + hubs: Hubs::new(&factory), + guard: NoDebug(Some(parent_context)), } } diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 0f2c2b318b..3976fa608a 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -10,6 +10,7 @@ use crate::{ LabelHelpers, LifeGuard, PrivateFeatures, Stored, DOWNLEVEL_WARNING_MESSAGE, MAX_BIND_GROUPS, }; +use std::{any::Any, sync::Arc}; use wgt::{Backend, BackendBit, PowerPreference, BIND_BUFFER_ALIGNMENT}; use hal::{ @@ -64,6 +65,34 @@ impl Instance { } } + pub unsafe fn required_vulkan_extensions(entry: &ash::Entry) -> Vec<&'static std::ffi::CStr> { + gfx_backend_vulkan::Instance::required_extensions( + &entry, + gfx_backend_vulkan::Version::V1_1, + ).unwrap() + } + + pub unsafe fn new_raw_vulkan( + entry: ash::Entry, + instance: ash::Instance, + extensions: Vec<&'static std::ffi::CStr>, + ) -> Self { + Self { + #[cfg(vulkan)] + vulkan: gfx_backend_vulkan::Instance::from_raw( + entry, instance, gfx_backend_vulkan::Version::V1_1, extensions + ).ok(), + #[cfg(metal)] + metal: None, + #[cfg(dx12)] + dx12: None, + #[cfg(dx11)] + dx11: None, + #[cfg(gl)] + gl: None, + } + } + pub(crate) fn destroy_surface(&self, surface: Surface) { backends_map! { let map = |(surface_backend, self_backend)| { @@ -432,6 +461,33 @@ impl Adapter { desc: &DeviceDescriptor, trace_path: Option<&std::path::Path>, ) -> Result, RequestDeviceError> { + self.verify(desc)?; + + let phd = &self.raw.physical_device; + let enabled_features = Self::get_features(phd, desc); + + let family = self + .raw + .queue_families + .iter() + .find(|family| family.queue_type().supports_graphics()) + .ok_or(RequestDeviceError::NoGraphicsQueue)?; + + let gpu = + unsafe { phd.open(&[(family, &[1.0])], enabled_features) }.map_err(|err| { + use hal::device::CreationError::*; + match err { + DeviceLost => RequestDeviceError::DeviceLost, + InitializationFailed => RequestDeviceError::Internal, + OutOfMemory(_) => RequestDeviceError::OutOfMemory, + _ => panic!("failed to create `gfx-hal` device: {}", err), + } + })?; + + self.device_from_gpu(self_id, gpu, desc, trace_path, None) + } + + fn verify(&self, desc: &DeviceDescriptor) -> Result<(), RequestDeviceError> { // Verify all features were exposed by the adapter if !self.features.contains(desc.features) { return Err(RequestDeviceError::UnsupportedFeature( @@ -452,7 +508,10 @@ impl Adapter { log::warn!("Feature MAPPABLE_PRIMARY_BUFFERS enabled on a discrete gpu. This is a massive performance footgun and likely not what you wanted"); } - let phd = &self.raw.physical_device; + Ok(()) + } + + fn get_features(phd: &B::PhysicalDevice, desc: &DeviceDescriptor) -> hal::Features { let available_features = phd.features(); // Check features that are always needed @@ -476,23 +535,18 @@ impl Adapter { enabled_features.set(lo, desc.features.contains(hi)); } - let family = self - .raw - .queue_families - .iter() - .find(|family| family.queue_type().supports_graphics()) - .ok_or(RequestDeviceError::NoGraphicsQueue)?; + enabled_features + } - let mut gpu = - unsafe { phd.open(&[(family, &[1.0])], enabled_features) }.map_err(|err| { - use hal::device::CreationError::*; - match err { - DeviceLost => RequestDeviceError::DeviceLost, - InitializationFailed => RequestDeviceError::Internal, - OutOfMemory(_) => RequestDeviceError::OutOfMemory, - _ => panic!("failed to create `gfx-hal` device: {}", err), - } - })?; + fn device_from_gpu( + &self, + self_id: AdapterId, + mut gpu: hal::adapter::Gpu, + desc: &DeviceDescriptor, + trace_path: Option<&std::path::Path>, + guard: Option>, + ) -> Result, RequestDeviceError> { + let phd = &self.raw.physical_device; if let Some(_) = desc.label { //TODO @@ -528,11 +582,50 @@ impl Adapter { self.downlevel, desc, trace_path, + guard, ) .or(Err(RequestDeviceError::OutOfMemory)) } } +impl Adapter { + fn required_vulkan_device_extensions( + &self, + desc: &DeviceDescriptor, + ) -> Vec<&'static std::ffi::CStr> { + let phd = &self.raw.physical_device; + let features = Self::get_features(phd, desc); + phd.enabled_extensions(features).unwrap() + } + + unsafe fn device_from_raw_vulkan( + &self, + self_id: AdapterId, + device: ash::Device, + queue_family_index: u32, + desc: &DeviceDescriptor, + trace_path: Option<&std::path::Path>, + guard: Arc, + ) -> Device { + self.verify(desc).unwrap(); + + let family = self + .raw + .queue_families + .get(queue_family_index as usize) + .ok_or(RequestDeviceError::NoGraphicsQueue) + .unwrap(); + + // TODO: Verify family supports graphics + + let phd = &self.raw.physical_device; + let enabled_features = Self::get_features(phd, desc); + let gpu = phd.gpu_from_raw(device, &[(family, &[1.0])], enabled_features).unwrap(); + + self.device_from_gpu(self_id, gpu, desc, trace_path, Some(guard)).unwrap() + } +} + impl crate::hub::Resource for Adapter { const TYPE: &'static str = "Adapter"; @@ -710,6 +803,25 @@ impl Global { adapters } + pub unsafe fn adapter_from_raw_vulkan( + &self, + physical_device: ash::vk::PhysicalDevice, + id_in: Input, + ) -> AdapterId { + let vulkan = self.instance.vulkan.as_ref().unwrap(); + + let raw = vulkan.adapter_from_raw(physical_device); + let adapter = Adapter::new(raw); + log::info!("Adapter Vulkan {:?}", adapter.raw.info); + + let mut token = Token::root(); + let id = backend::Vulkan::hub(self).adapters + .prepare(id_in) + .assign(adapter, &mut token); + + id.0 + } + pub fn request_adapter( &self, desc: &RequestAdapterOptions, @@ -981,4 +1093,44 @@ impl Global { let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, Some(error)) } + + pub fn adapter_required_vulkan_device_extensions( + &self, + adapter_id: AdapterId, + desc: &DeviceDescriptor, + ) -> Vec<&'static std::ffi::CStr> { + let hub = backend::Vulkan::hub(self); + let mut token = Token::root(); + + let (adapter_guard, _token) = hub.adapters.read(&mut token); + let adapter = adapter_guard.get(adapter_id).unwrap(); + adapter.required_vulkan_device_extensions(desc) + } + + pub unsafe fn adapter_device_from_raw_vulkan( + &self, + adapter_id: AdapterId, + device: ash::Device, + queue_family_index: u32, + desc: &DeviceDescriptor, + trace_path: Option<&std::path::Path>, + guard: Arc, + id_in: Input, + ) -> DeviceId { + let hub = backend::Vulkan::hub(self); + let mut token = Token::root(); + let fid = hub.devices.prepare(id_in); + + let (adapter_guard, mut token) = hub.adapters.read(&mut token); + let adapter = adapter_guard.get(adapter_id).unwrap(); + let device = adapter.device_from_raw_vulkan( + adapter_id, + device, + queue_family_index, + desc, + trace_path, + guard, + ); + fid.assign(device, &mut token).0 + } } diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 802033ba2d..b6d4d54a5b 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -323,6 +323,9 @@ pub(crate) enum TextureViewInner { image: >::SwapchainImage, source_id: Stored, }, + Raw { + raw: B::ImageView, + } } #[derive(Debug)] diff --git a/wgpu-core/src/swap_chain.rs b/wgpu-core/src/swap_chain.rs index 8156efd5a6..7d39242506 100644 --- a/wgpu-core/src/swap_chain.rs +++ b/wgpu-core/src/swap_chain.rs @@ -277,6 +277,7 @@ impl Global { let image = match view.inner { resource::TextureViewInner::Native { .. } => unreachable!(), resource::TextureViewInner::SwapChain { image, .. } => image, + resource::TextureViewInner::Raw { .. } => unreachable!(), }; let sem = if sc.active_submission_index > device.last_completed_submission_index() {