Skip to content

Commit

Permalink
[Vulkan] Initialize wgpu objects from raw handles
Browse files Browse the repository at this point in the history
  • Loading branch information
zmerp committed Jul 19, 2021
1 parent 1090110 commit 943a795
Show file tree
Hide file tree
Showing 9 changed files with 633 additions and 191 deletions.
101 changes: 85 additions & 16 deletions wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,10 +517,12 @@ impl<A: HalApi> Device<A> {
})
}

fn create_texture(
fn texture_from_hal(
&self,
hal_texture: A::Texture,
self_id: id::DeviceId,
adapter: &crate::instance::Adapter<A>,
hal_usage: hal::TextureUses,
desc: &resource::TextureDescriptor,
) -> Result<resource::Texture<A>, resource::CreateTextureError> {
debug_assert_eq!(self_id.backend(), A::VARIANT);
Expand Down Expand Up @@ -566,6 +568,29 @@ impl<A: HalApi> Device<A> {
return Err(resource::CreateTextureError::InvalidMipLevelCount(mips));
}

Ok(resource::Texture {
raw: Some(hal_texture),
device_id: Stored {
value: id::Valid(self_id),
ref_count: self.life_guard.add_ref(),
},
desc: desc.map_label(|_| ()),
hal_usage,
format_features,
full_range: TextureSelector {
levels: 0..desc.mip_level_count,
layers: 0..desc.array_layer_count(),
},
life_guard: LifeGuard::new(desc.label.borrow_or_default()),
})
}

fn create_texture(
&self,
self_id: id::DeviceId,
adapter: &crate::instance::Adapter<A>,
desc: &resource::TextureDescriptor,
) -> Result<resource::Texture<A>, resource::CreateTextureError> {
let hal_usage = conv::map_texture_usage(desc.usage, desc.format.into());
let hal_desc = hal::TextureDescriptor {
label: desc.label.borrow_option(),
Expand All @@ -583,21 +608,7 @@ impl<A: HalApi> Device<A> {
.map_err(DeviceError::from)?
};

Ok(resource::Texture {
raw: Some(raw),
device_id: Stored {
value: id::Valid(self_id),
ref_count: self.life_guard.add_ref(),
},
desc: desc.map_label(|_| ()),
hal_usage,
format_features,
full_range: TextureSelector {
levels: 0..desc.mip_level_count,
layers: 0..desc.array_layer_count(),
},
life_guard: LifeGuard::new(desc.label.borrow_or_default()),
})
self.texture_from_hal(raw, self_id, adapter, hal_usage, desc)
}

fn create_texture_view(
Expand Down Expand Up @@ -2976,6 +2987,64 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
(id, Some(error))
}

/// # Safety
///
/// - `hal_texture` must be created from `device_id` correspnding raw handle.
/// - `hal_texture` must be created respecting `desc`
pub unsafe fn texture_from_hal<A: HalApi>(
&self,
hal_texture: A::Texture,
device_id: id::DeviceId,
desc: &resource::TextureDescriptor,
id_in: Input<G, id::TextureId>,
) -> (id::TextureId, Option<resource::CreateTextureError>) {
profiling::scope!("create_texture", "Device");

let hub = A::hub(self);
let mut token = Token::root();
let fid = hub.textures.prepare(id_in);

let (adapter_guard, mut token) = hub.adapters.read(&mut token);
let (device_guard, mut token) = hub.devices.read(&mut token);
let error = loop {
let device = match device_guard.get(device_id) {
Ok(device) => device,
Err(_) => break DeviceError::Invalid.into(),
};
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace
.lock()
.add(trace::Action::CreateTexture(fid.id(), desc.clone()));
}

let adapter = &adapter_guard[device.adapter_id.value];
let hal_usage = conv::map_texture_usage(desc.usage, desc.format.into());
let texture =
match device.texture_from_hal(hal_texture, device_id, adapter, hal_usage, desc) {
Ok(texture) => texture,
Err(error) => break error,
};
let num_levels = texture.full_range.levels.end;
let num_layers = texture.full_range.layers.end;
let ref_count = texture.life_guard.add_ref();

let id = fid.assign(texture, &mut token);
log::info!("Created texture {:?} with {:?}", id, desc);

device
.trackers
.lock()
.textures
.init(id, ref_count, TextureState::new(num_levels, num_layers))
.unwrap();
return (id.0, None);
};

let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}

pub fn texture_label<A: HalApi>(&self, id: id::TextureId) -> String {
A::hub(self).textures.label_for_resource(id)
}
Expand Down
44 changes: 44 additions & 0 deletions wgpu-core/src/hub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,22 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}
}

/// # Safety
///
/// Refer to the creation of wgpu-hal Instance for every backend.
pub unsafe fn from_hal_instance<A: HalApi>(
name: &str,
factory: G,
hal_instance: A::Instance,
) -> Self {
profiling::scope!("new", "Global");
Self {
instance: A::instance_from_hal(name, hal_instance),
surfaces: Registry::without_backend(&factory, "Surface"),
hubs: Hubs::new(&factory),
}
}

pub fn clear_backend<A: HalApi>(&self, _dummy: ()) {
let mut surface_guard = self.surfaces.data.write();
let hub = A::hub(self);
Expand Down Expand Up @@ -933,13 +949,21 @@ impl<G: GlobalIdentityHandlerFactory> Drop for Global<G> {

pub trait HalApi: hal::Api {
const VARIANT: Backend;
fn instance_from_hal(name: &str, hal_instance: Self::Instance) -> Instance;
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G>;
fn get_surface_mut(surface: &mut Surface) -> &mut Self::Surface;
}

#[cfg(vulkan)]
impl HalApi for hal::api::Vulkan {
const VARIANT: Backend = Backend::Vulkan;
fn instance_from_hal(name: &str, hal_instance: Self::Instance) -> Instance {
Instance {
name: name.to_owned(),
vulkan: Some(hal_instance),
..Default::default()
}
}
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G> {
&global.hubs.vulkan
}
Expand All @@ -951,6 +975,12 @@ impl HalApi for hal::api::Vulkan {
#[cfg(metal)]
impl HalApi for hal::api::Metal {
const VARIANT: Backend = Backend::Metal;
fn instance_from_hal(name: &str, hal_instance: Self::Instance) -> Instance {
Instance {
name: name.to_owned(),
metal: Some(hal_instance),
}
}
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G> {
&global.hubs.metal
}
Expand All @@ -962,6 +992,13 @@ impl HalApi for hal::api::Metal {
#[cfg(dx12)]
impl HalApi for hal::api::Dx12 {
const VARIANT: Backend = Backend::Dx12;
fn instance_from_hal(name: &str, hal_instance: Self::Instance) -> Instance {
Instance {
name: name.to_owned(),
dx12: Some(hal_instance),
..Default::default()
}
}
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G> {
&global.hubs.dx12
}
Expand All @@ -986,6 +1023,13 @@ impl HalApi for hal::api::Dx11 {
#[cfg(gl)]
impl HalApi for hal::api::Gles {
const VARIANT: Backend = Backend::Gl;
fn instance_from_hal(name: &str, hal_instance: Self::Instance) -> Instance {
Instance {
name: name.to_owned(),
gl: Some(hal_instance),
..Default::default()
}
}
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G> {
&global.hubs.gl
}
Expand Down
91 changes: 83 additions & 8 deletions wgpu-core/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ fn downlevel_default_limits_less_than_default_limits() {
)
}

#[derive(Default)]
pub struct Instance {
#[allow(dead_code)]
name: String,
pub name: String,
#[cfg(vulkan)]
pub vulkan: Option<HalInstance<hal::api::Vulkan>>,
#[cfg(metal)]
Expand Down Expand Up @@ -248,9 +249,10 @@ impl<A: HalApi> Adapter<A> {
}
}

fn create_device(
fn device_from_open(
&self,
self_id: AdapterId,
open: hal::OpenDevice<A>,
desc: &DeviceDescriptor,
trace_path: Option<&std::path::Path>,
) -> Result<Device<A>, RequestDeviceError> {
Expand Down Expand Up @@ -281,11 +283,6 @@ impl<A: HalApi> Adapter<A> {
log::warn!("Feature MAPPABLE_PRIMARY_BUFFERS enabled on a discrete gpu. This is a massive performance footgun and likely not what you wanted");
}

let gpu = unsafe { self.raw.adapter.open(desc.features) }.map_err(|err| match err {
hal::DeviceError::Lost => RequestDeviceError::DeviceLost,
hal::DeviceError::OutOfMemory => RequestDeviceError::OutOfMemory,
})?;

if let Some(_) = desc.label {
//TODO
}
Expand All @@ -305,7 +302,7 @@ impl<A: HalApi> Adapter<A> {
}

Device::new(
gpu,
open,
Stored {
value: Valid(self_id),
ref_count: self.life_guard.add_ref(),
Expand All @@ -317,6 +314,20 @@ impl<A: HalApi> Adapter<A> {
)
.or(Err(RequestDeviceError::OutOfMemory))
}

fn create_device(
&self,
self_id: AdapterId,
desc: &DeviceDescriptor,
trace_path: Option<&std::path::Path>,
) -> Result<Device<A>, RequestDeviceError> {
let open = unsafe { self.raw.adapter.open(desc.features) }.map_err(|err| match err {
hal::DeviceError::Lost => RequestDeviceError::DeviceLost,
hal::DeviceError::OutOfMemory => RequestDeviceError::OutOfMemory,
})?;

self.device_from_open(self_id, open, desc, trace_path)
}
}

impl<A: hal::Api> crate::hub::Resource for Adapter<A> {
Expand Down Expand Up @@ -649,6 +660,34 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Err(RequestAdapterError::NotFound)
}

/// # Safety
///
/// `hal_adapter` must be created from this global internal instance handle.
pub unsafe fn adapter_from_hal<A: HalApi>(
&self,
hal_adapter: hal::ExposedAdapter<A>,
input: Input<G, AdapterId>,
) -> AdapterId {
profiling::scope!("adapter_from_hal", "Instance");

let mut token = Token::root();
let fid = A::hub(&self).adapters.prepare(input);

match A::VARIANT {
#[cfg(vulkan)]
Backend::Vulkan => fid.assign(Adapter::new(hal_adapter), &mut token).0,
#[cfg(metal)]
Backend::Metal => fid.assign(Adapter::new(hal_adapter), &mut token).0,
#[cfg(dx12)]
Backend::Dx12 => fid.assign(Adapter::new(hal_adapter), &mut token).0,
#[cfg(dx11)]
Backend::Dx11 => fid.assign(Adapter::new(hal_adapter), &mut token).0,
#[cfg(gl)]
Backend::Gl => fid.assign(Adapter::new(hal_adapter), &mut token).0,
_ => unreachable!(),
}
}

pub fn adapter_get_info<A: HalApi>(
&self,
adapter_id: AdapterId,
Expand Down Expand Up @@ -764,4 +803,40 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}

/// # Safety
///
/// - `hal_device` must be created from `adapter_id` or its internal handle.
/// - `desc` must be a subset of `hal_device` features and limits.
pub unsafe fn device_from_hal<A: HalApi>(
&self,
adapter_id: AdapterId,
hal_device: hal::OpenDevice<A>,
desc: &DeviceDescriptor,
trace_path: Option<&std::path::Path>,
id_in: Input<G, DeviceId>,
) -> (DeviceId, Option<RequestDeviceError>) {
profiling::scope!("request_device", "Adapter");

let hub = A::hub(self);
let mut token = Token::root();
let fid = hub.devices.prepare(id_in);

let error = loop {
let (adapter_guard, mut token) = hub.adapters.read(&mut token);
let adapter = match adapter_guard.get(adapter_id) {
Ok(adapter) => adapter,
Err(_) => break RequestDeviceError::InvalidAdapter,
};
let device = match adapter.device_from_open(adapter_id, hal_device, desc, trace_path) {
Ok(device) => device,
Err(e) => break e,
};
let id = fid.assign(device, &mut token);
return (id.0, None);
};

let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}
}
Loading

0 comments on commit 943a795

Please sign in to comment.