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();
}
A::Submit(_index, commands) => {
let encoder = self.device_create_command_encoder::<B>(
device,
&wgt::CommandEncoderDescriptor { label: ptr::null() },
comb_manager.alloc(device.backend()),
);
let encoder = self
.device_create_command_encoder::<B>(
device,
&wgt::CommandEncoderDescriptor { label: ptr::null() },
comb_manager.alloc(device.backend()),
)
.unwrap();
let cmdbuf = self.encode_commands::<B>(encoder, commands);
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 parking_lot::Mutex;
use thiserror::Error;
use std::thread;
@ -80,30 +81,37 @@ impl<B: GfxBackend> CommandAllocator<B> {
limits: wgt::Limits,
private_features: PrivateFeatures,
#[cfg(feature = "trace")] enable_tracing: bool,
) -> CommandBuffer<B> {
) -> Result<CommandBuffer<B>, CommandAllocatorError> {
//debug_assert_eq!(device_id.backend(), B::VARIANT);
let thread_id = thread::current().id();
let mut inner = self.inner.lock();
let init = inner
.pools
.entry(thread_id)
.or_insert_with(|| CommandPool {
raw: unsafe {
tracing::info!("Starting on thread {:?}", thread_id);
device.create_command_pool(
self.queue_family,
hal::pool::CommandPoolCreateFlags::RESET_INDIVIDUAL,
)
}
.unwrap(),
total: 0,
available: Vec::new(),
pending: Vec::new(),
})
.allocate();
use std::collections::hash_map::Entry;
let pool = match inner.pools.entry(thread_id) {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(e) => {
tracing::info!("Starting on thread {:?}", thread_id);
let raw = unsafe {
device
.create_command_pool(
self.queue_family,
hal::pool::CommandPoolCreateFlags::RESET_INDIVIDUAL,
)
.or(Err(CommandAllocatorError::OutOfMemory))?
};
let pool = CommandPool {
raw,
total: 0,
available: Vec::new(),
pending: Vec::new(),
};
e.insert(pool)
}
};
CommandBuffer {
let init = pool.allocate();
Ok(CommandBuffer {
raw: vec![init],
is_recording: true,
recorded_thread_id: thread_id,
@ -118,12 +126,15 @@ impl<B: GfxBackend> CommandAllocator<B> {
} else {
None
},
}
})
}
}
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();
tracing::info!("Starting on (internal) thread {:?}", internal_thread_id);
let mut pools = FastHashMap::default();
@ -136,18 +147,18 @@ impl<B: hal::Backend> CommandAllocator<B> {
queue_family,
hal::pool::CommandPoolCreateFlags::RESET_INDIVIDUAL,
)
.unwrap()
.or(Err(CommandAllocatorError::OutOfMemory))?
},
total: 0,
available: Vec::new(),
pending: Vec::new(),
},
);
CommandAllocator {
Ok(CommandAllocator {
queue_family,
internal_thread_id,
inner: Mutex::new(Inner { pools }),
}
})
}
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;
pub(crate) use self::allocator::CommandAllocator;
pub use self::allocator::CommandAllocatorError;
pub use self::bundle::*;
pub use self::compute::*;
pub use self::render::*;

View File

@ -217,8 +217,9 @@ impl<B: GfxBackend> Device<B> {
private_features: PrivateFeatures,
desc: &wgt::DeviceDescriptor,
trace_path: Option<&std::path::Path>,
) -> Self {
let cmd_allocator = command::CommandAllocator::new(queue_group.family, &raw);
) -> Result<Self, CreateDeviceError> {
let cmd_allocator = command::CommandAllocator::new(queue_group.family, &raw)
.or(Err(CreateDeviceError::OutOfMemory))?;
let heaps = unsafe {
Heaps::new(
&mem_props,
@ -240,7 +241,7 @@ impl<B: GfxBackend> Device<B> {
None => (),
}
Device {
Ok(Device {
raw,
adapter_id,
cmd_allocator,
@ -273,7 +274,7 @@ impl<B: GfxBackend> Device<B> {
limits: desc.limits.clone(),
features: desc.features.clone(),
pending_writes: queue::PendingWrites::new(),
}
})
}
pub(crate) fn last_completed_submission_index(&self) -> SubmissionIndex {
@ -2031,7 +2032,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
device_id: id::DeviceId,
desc: &wgt::CommandEncoderDescriptor<Label>,
id_in: Input<G, id::CommandEncoderId>,
) -> id::CommandEncoderId {
) -> Result<id::CommandEncoderId, command::CommandAllocatorError> {
span!(_guard, INFO, "Device::create_command_encoder");
let hub = B::hub(self);
@ -2052,7 +2053,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
device.private_features,
#[cfg(feature = "trace")]
device.trace.is_some(),
);
)?;
unsafe {
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);
}
hub.command_buffers
.register_identity(id_in, command_buffer, &mut token)
let id = hub
.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) {
@ -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)]
pub enum CreateBufferError {
#[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];
#[cfg(feature = "trace")]
match device.trace {
Some(ref trace) => trace
.lock()
.add(Action::Submit(submit_index, cmdbuf.commands.take().unwrap())),
Some(ref trace) => trace.lock().add(Action::Submit(
submit_index,
cmdbuf.commands.take().unwrap(),
)),
None => (),
};

View File

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