Handle command pool creation error

This commit is contained in:
Gabriel Majeri 2020-07-28 21:34:39 +03:00
parent 9929b8719f
commit e860dd995f
6 changed files with 92 additions and 47 deletions

View File

@ -306,11 +306,13 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
.unwrap(); .unwrap();
} }
A::Submit(_index, commands) => { A::Submit(_index, commands) => {
let encoder = self.device_create_command_encoder::<B>( let encoder = self
device, .device_create_command_encoder::<B>(
&wgt::CommandEncoderDescriptor { label: ptr::null() }, device,
comb_manager.alloc(device.backend()), &wgt::CommandEncoderDescriptor { label: ptr::null() },
); comb_manager.alloc(device.backend()),
)
.unwrap();
let cmdbuf = self.encode_commands::<B>(encoder, commands); let cmdbuf = self.encode_commands::<B>(encoder, commands);
self.queue_submit::<B>(device, &[cmdbuf]).unwrap(); self.queue_submit::<B>(device, &[cmdbuf]).unwrap();
} }

View File

@ -10,6 +10,7 @@ use crate::{
use hal::{command::CommandBuffer as _, device::Device as _, pool::CommandPool as _}; use hal::{command::CommandBuffer as _, device::Device as _, pool::CommandPool as _};
use parking_lot::Mutex; use parking_lot::Mutex;
use thiserror::Error;
use std::thread; use std::thread;
@ -80,30 +81,37 @@ impl<B: GfxBackend> CommandAllocator<B> {
limits: wgt::Limits, limits: wgt::Limits,
private_features: PrivateFeatures, private_features: PrivateFeatures,
#[cfg(feature = "trace")] enable_tracing: bool, #[cfg(feature = "trace")] enable_tracing: bool,
) -> CommandBuffer<B> { ) -> Result<CommandBuffer<B>, CommandAllocatorError> {
//debug_assert_eq!(device_id.backend(), B::VARIANT); //debug_assert_eq!(device_id.backend(), B::VARIANT);
let thread_id = thread::current().id(); let thread_id = thread::current().id();
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
let init = inner use std::collections::hash_map::Entry;
.pools let pool = match inner.pools.entry(thread_id) {
.entry(thread_id) Entry::Occupied(e) => e.into_mut(),
.or_insert_with(|| CommandPool { Entry::Vacant(e) => {
raw: unsafe { tracing::info!("Starting on thread {:?}", thread_id);
tracing::info!("Starting on thread {:?}", thread_id); let raw = unsafe {
device.create_command_pool( device
self.queue_family, .create_command_pool(
hal::pool::CommandPoolCreateFlags::RESET_INDIVIDUAL, self.queue_family,
) hal::pool::CommandPoolCreateFlags::RESET_INDIVIDUAL,
} )
.unwrap(), .or(Err(CommandAllocatorError::OutOfMemory))?
total: 0, };
available: Vec::new(), let pool = CommandPool {
pending: Vec::new(), raw,
}) total: 0,
.allocate(); available: Vec::new(),
pending: Vec::new(),
};
e.insert(pool)
}
};
CommandBuffer { let init = pool.allocate();
Ok(CommandBuffer {
raw: vec![init], raw: vec![init],
is_recording: true, is_recording: true,
recorded_thread_id: thread_id, recorded_thread_id: thread_id,
@ -118,12 +126,15 @@ impl<B: GfxBackend> CommandAllocator<B> {
} else { } else {
None None
}, },
} })
} }
} }
impl<B: hal::Backend> CommandAllocator<B> { impl<B: hal::Backend> CommandAllocator<B> {
pub fn new(queue_family: hal::queue::QueueFamilyId, device: &B::Device) -> Self { pub fn new(
queue_family: hal::queue::QueueFamilyId,
device: &B::Device,
) -> Result<Self, CommandAllocatorError> {
let internal_thread_id = thread::current().id(); let internal_thread_id = thread::current().id();
tracing::info!("Starting on (internal) thread {:?}", internal_thread_id); tracing::info!("Starting on (internal) thread {:?}", internal_thread_id);
let mut pools = FastHashMap::default(); let mut pools = FastHashMap::default();
@ -136,18 +147,18 @@ impl<B: hal::Backend> CommandAllocator<B> {
queue_family, queue_family,
hal::pool::CommandPoolCreateFlags::RESET_INDIVIDUAL, hal::pool::CommandPoolCreateFlags::RESET_INDIVIDUAL,
) )
.unwrap() .or(Err(CommandAllocatorError::OutOfMemory))?
}, },
total: 0, total: 0,
available: Vec::new(), available: Vec::new(),
pending: Vec::new(), pending: Vec::new(),
}, },
); );
CommandAllocator { Ok(CommandAllocator {
queue_family, queue_family,
internal_thread_id, internal_thread_id,
inner: Mutex::new(Inner { pools }), inner: Mutex::new(Inner { pools }),
} })
} }
fn allocate_for_thread_id(&self, thread_id: thread::ThreadId) -> B::CommandBuffer { fn allocate_for_thread_id(&self, thread_id: thread::ThreadId) -> B::CommandBuffer {
@ -242,3 +253,9 @@ impl<B: hal::Backend> CommandAllocator<B> {
} }
} }
} }
#[derive(Clone, Debug, Error)]
pub enum CommandAllocatorError {
#[error("not enough memory left")]
OutOfMemory,
}

View File

@ -10,6 +10,7 @@ mod render;
mod transfer; mod transfer;
pub(crate) use self::allocator::CommandAllocator; pub(crate) use self::allocator::CommandAllocator;
pub use self::allocator::CommandAllocatorError;
pub use self::bundle::*; pub use self::bundle::*;
pub use self::compute::*; pub use self::compute::*;
pub use self::render::*; pub use self::render::*;

View File

@ -217,8 +217,9 @@ impl<B: GfxBackend> Device<B> {
private_features: PrivateFeatures, private_features: PrivateFeatures,
desc: &wgt::DeviceDescriptor, desc: &wgt::DeviceDescriptor,
trace_path: Option<&std::path::Path>, trace_path: Option<&std::path::Path>,
) -> Self { ) -> Result<Self, CreateDeviceError> {
let cmd_allocator = command::CommandAllocator::new(queue_group.family, &raw); let cmd_allocator = command::CommandAllocator::new(queue_group.family, &raw)
.or(Err(CreateDeviceError::OutOfMemory))?;
let heaps = unsafe { let heaps = unsafe {
Heaps::new( Heaps::new(
&mem_props, &mem_props,
@ -240,7 +241,7 @@ impl<B: GfxBackend> Device<B> {
None => (), None => (),
} }
Device { Ok(Device {
raw, raw,
adapter_id, adapter_id,
cmd_allocator, cmd_allocator,
@ -273,7 +274,7 @@ impl<B: GfxBackend> Device<B> {
limits: desc.limits.clone(), limits: desc.limits.clone(),
features: desc.features.clone(), features: desc.features.clone(),
pending_writes: queue::PendingWrites::new(), pending_writes: queue::PendingWrites::new(),
} })
} }
pub(crate) fn last_completed_submission_index(&self) -> SubmissionIndex { pub(crate) fn last_completed_submission_index(&self) -> SubmissionIndex {
@ -2031,7 +2032,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
device_id: id::DeviceId, device_id: id::DeviceId,
desc: &wgt::CommandEncoderDescriptor<Label>, desc: &wgt::CommandEncoderDescriptor<Label>,
id_in: Input<G, id::CommandEncoderId>, id_in: Input<G, id::CommandEncoderId>,
) -> id::CommandEncoderId { ) -> Result<id::CommandEncoderId, command::CommandAllocatorError> {
span!(_guard, INFO, "Device::create_command_encoder"); span!(_guard, INFO, "Device::create_command_encoder");
let hub = B::hub(self); let hub = B::hub(self);
@ -2052,7 +2053,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
device.private_features, device.private_features,
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
device.trace.is_some(), device.trace.is_some(),
); )?;
unsafe { unsafe {
let raw_command_buffer = command_buffer.raw.last_mut().unwrap(); let raw_command_buffer = command_buffer.raw.last_mut().unwrap();
@ -2065,8 +2066,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
raw_command_buffer.begin_primary(hal::command::CommandBufferFlags::ONE_TIME_SUBMIT); raw_command_buffer.begin_primary(hal::command::CommandBufferFlags::ONE_TIME_SUBMIT);
} }
hub.command_buffers let id = hub
.register_identity(id_in, command_buffer, &mut token) .command_buffers
.register_identity(id_in, command_buffer, &mut token);
Ok(id)
} }
pub fn command_encoder_destroy<B: GfxBackend>(&self, command_encoder_id: id::CommandEncoderId) { pub fn command_encoder_destroy<B: GfxBackend>(&self, command_encoder_id: id::CommandEncoderId) {
@ -3035,6 +3039,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
} }
} }
#[derive(Clone, Debug, Error)]
pub enum CreateDeviceError {
#[error("not enough memory left")]
OutOfMemory,
}
#[derive(Clone, Debug, Error)] #[derive(Clone, Debug, Error)]
pub enum CreateBufferError { pub enum CreateBufferError {
#[error("failed to map buffer while creating: {0}")] #[error("failed to map buffer while creating: {0}")]

View File

@ -423,9 +423,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let cmdbuf = &mut command_buffer_guard[cmb_id]; let cmdbuf = &mut command_buffer_guard[cmb_id];
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
match device.trace { match device.trace {
Some(ref trace) => trace Some(ref trace) => trace.lock().add(Action::Submit(
.lock() submit_index,
.add(Action::Submit(submit_index, cmdbuf.commands.take().unwrap())), cmdbuf.commands.take().unwrap(),
)),
None => (), None => (),
}; };

View File

@ -248,14 +248,18 @@ impl AdapterInfo {
#[derive(Clone, Debug, Error, PartialEq)] #[derive(Clone, Debug, Error, PartialEq)]
/// Error when requesting a device from the adaptor /// Error when requesting a device from the adaptor
pub enum RequestDeviceError { pub enum RequestDeviceError {
#[error("unsupported features were requested: {0:?}")] #[error("connection to device was lost during initialization")]
UnsupportedFeature(wgt::Features), DeviceLost,
#[error("device has no queue supporting graphics")] #[error("device initialization failed due to implementation specific errors")]
NoGraphicsQueue, Internal,
#[error(transparent)]
DeviceCreationError(#[from] hal::device::CreationError),
#[error("some of the requested device limits are not supported")] #[error("some of the requested device limits are not supported")]
LimitsExceeded, LimitsExceeded,
#[error("device has no queue supporting graphics")]
NoGraphicsQueue,
#[error("not enough memory left")]
OutOfMemory,
#[error("unsupported features were requested: {0:?}")]
UnsupportedFeature(wgt::Features),
} }
/// Supported physical device types. /// Supported physical device types.
@ -679,7 +683,16 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.iter() .iter()
.find(|family| family.queue_type().supports_graphics()) .find(|family| family.queue_type().supports_graphics())
.ok_or(RequestDeviceError::NoGraphicsQueue)?; .ok_or(RequestDeviceError::NoGraphicsQueue)?;
let mut gpu = unsafe { phd.open(&[(family, &[1.0])], 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),
}
})?;
let limits = phd.limits(); let limits = phd.limits();
assert_eq!( assert_eq!(
@ -722,6 +735,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
desc, desc,
trace_path, trace_path,
) )
.or(Err(RequestDeviceError::OutOfMemory))?
}; };
Ok(hub.devices.register_identity(id_in, device, &mut token)) Ok(hub.devices.register_identity(id_in, device, &mut token))