pub struct Device<A: HalApi> {
Show 20 fields pub(crate) raw: A::Device, pub(crate) adapter_id: Stored<AdapterId>, pub(crate) queue: A::Queue, pub(crate) zero_buffer: A::Buffer, pub(crate) life_guard: LifeGuard, pub(super) ref_count: RefCount, pub(super) command_allocator: Mutex<CommandAllocator<A>>, pub(crate) active_submission_index: FenceValue, pub(super) fence: A::Fence, pub(crate) valid: bool, pub(crate) trackers: Mutex<Tracker<A>>, life_tracker: Mutex<LifetimeTracker<A>>, pub(super) temp_suspected: SuspectedResources, pub(crate) alignments: Alignments, pub(crate) limits: Limits, pub(crate) features: Features, pub(crate) downlevel: DownlevelCapabilities, pub(crate) instance_flags: InstanceFlags, pub(super) pending_writes: PendingWrites<A>, pub(crate) trace: Option<Mutex<Trace>>,
}
Expand description

Structure describing a logical device. Some members are internally mutable, stored behind mutexes.

TODO: establish clear order of locking for these: mem_allocator, desc_allocator, life_tracker, trackers, render_passes, pending_writes, trace.

Currently, the rules are:

  1. life_tracker is locked after hub.devices, enforced by the type system
  2. self.trackers is locked last (unenforced)
  3. self.trace is locked last (unenforced)

Fields§

§raw: A::Device§adapter_id: Stored<AdapterId>§queue: A::Queue§zero_buffer: A::Buffer§life_guard: LifeGuard§ref_count: RefCount

A clone of life_guard.ref_count.

Holding a separate clone of the RefCount here lets us tell whether the device is referenced by other resources, even if life_guard.ref_count was set to None by a call to device_drop.

§command_allocator: Mutex<CommandAllocator<A>>§active_submission_index: FenceValue§fence: A::Fence§valid: bool

Is this device valid? Valid is closely associated with “lose the device”, which can be triggered by various methods, including at the end of device destroy, and by any GPU errors that cause us to no longer trust the state of the device. Ideally we would like to fold valid into the storage of the device itself (for example as an Error enum), but unfortunately we need to continue to be able to retrieve the device in poll_devices to determine if it can be dropped. If our internal accesses of devices were done through ref-counted references and external accesses checked for Error enums, we wouldn’t need this. For now, we need it. All the call sites where we check it are areas that should be revisited if we start using ref-counted references for internal access.

§trackers: Mutex<Tracker<A>>

All live resources allocated with this Device.

Has to be locked temporarily only (locked last)

§life_tracker: Mutex<LifetimeTracker<A>>§temp_suspected: SuspectedResources

Temporary storage for resource management functions. Cleared at the end of every call (unless an error occurs).

§alignments: Alignments§limits: Limits§features: Features§downlevel: DownlevelCapabilities§instance_flags: InstanceFlags§pending_writes: PendingWrites<A>§trace: Option<Mutex<Trace>>

Implementations§

source§

impl<A: HalApi> Device<A>

source§

impl<A: HalApi> Device<A>

source

pub(crate) fn new( open: OpenDevice<A>, adapter_id: Stored<AdapterId>, alignments: Alignments, downlevel: DownlevelCapabilities, desc: &DeviceDescriptor<'_>, trace_path: Option<&Path>, instance_flags: InstanceFlags ) -> Result<Self, CreateDeviceError>

source

pub fn is_valid(&self) -> bool

source

pub(super) fn lock_life<'this, 'token: 'this>( &'this self, _token: &mut Token<'token, Self> ) -> MutexGuard<'this, LifetimeTracker<A>>

source

pub(super) fn maintain<'this, 'token: 'this, G: GlobalIdentityHandlerFactory>( &'this self, hub: &Hub<A, G>, maintain: Maintain<WrappedSubmissionIndex>, token: &mut Token<'token, Self> ) -> Result<(UserClosures, bool), WaitIdleError>

Check this device for completed commands.

The maintain argument tells how the maintence function should behave, either blocking or just polling the current state of the gpu.

Return a pair (closures, queue_empty), where:

  • closures is a list of actions to take: mapping buffers, notifying the user

  • queue_empty is a boolean indicating whether there are more queue submissions still in flight. (We have to take the locks needed to produce this information for other reasons, so we might as well just return it to our callers.)

source

pub(super) fn untrack<'this, 'token: 'this, G: GlobalIdentityHandlerFactory>( &'this mut self, hub: &Hub<A, G>, trackers: &Tracker<A>, token: &mut Token<'token, Self> )

source

pub(super) fn create_buffer( &self, self_id: DeviceId, desc: &BufferDescriptor<'_>, transient: bool ) -> Result<Buffer<A>, CreateBufferError>

source

pub(super) fn create_texture_from_hal( &self, hal_texture: A::Texture, hal_usage: TextureUses, self_id: DeviceId, desc: &TextureDescriptor<'_>, format_features: TextureFormatFeatures, clear_mode: TextureClearMode<A> ) -> Texture<A>

source

pub fn create_buffer_from_hal( &self, hal_buffer: A::Buffer, self_id: DeviceId, desc: &BufferDescriptor<'_> ) -> Buffer<A>

source

pub(super) fn create_texture( &self, self_id: DeviceId, adapter: &Adapter<A>, desc: &TextureDescriptor<'_> ) -> Result<Texture<A>, CreateTextureError>

source

pub(super) fn create_texture_view( &self, texture: &Texture<A>, texture_id: TextureId, desc: &TextureViewDescriptor<'_> ) -> Result<TextureView<A>, CreateTextureViewError>

source

pub(super) fn create_sampler( &self, self_id: DeviceId, desc: &SamplerDescriptor<'_> ) -> Result<Sampler<A>, CreateSamplerError>

source

pub(super) fn create_shader_module<'a>( &self, self_id: DeviceId, desc: &ShaderModuleDescriptor<'a>, source: ShaderModuleSource<'a> ) -> Result<ShaderModule<A>, CreateShaderModuleError>

source

pub(super) unsafe fn create_shader_module_spirv<'a>( &self, self_id: DeviceId, desc: &ShaderModuleDescriptor<'a>, source: &'a [u32] ) -> Result<ShaderModule<A>, CreateShaderModuleError>

source

pub(super) fn deduplicate_bind_group_layout( self_id: DeviceId, entry_map: &HashMap<u32, BindGroupLayoutEntry, BuildHasherDefault<FxHasher>>, guard: &Storage<BindGroupLayout<A>, BindGroupLayoutId> ) -> Option<BindGroupLayoutId>

source

fn get_introspection_bind_group_layouts<'a>( pipeline_layout: &PipelineLayout<A>, bgl_guard: &'a Storage<BindGroupLayout<A>, BindGroupLayoutId> ) -> ArrayVec<&'a HashMap<u32, BindGroupLayoutEntry, BuildHasherDefault<FxHasher>>, { hal::MAX_BIND_GROUPS }>

source

fn make_late_sized_buffer_groups<'a>( shader_binding_sizes: &HashMap<ResourceBinding, BufferSize, BuildHasherDefault<FxHasher>>, layout: &PipelineLayout<A>, bgl_guard: &'a Storage<BindGroupLayout<A>, BindGroupLayoutId> ) -> ArrayVec<LateSizedBufferGroup, { hal::MAX_BIND_GROUPS }>

Generate information about late-validated buffer bindings for pipelines.

source

pub(super) fn create_bind_group_layout( &self, self_id: DeviceId, label: &Label<'_>, entry_map: HashMap<u32, BindGroupLayoutEntry, BuildHasherDefault<FxHasher>> ) -> Result<BindGroupLayout<A>, CreateBindGroupLayoutError>

source

fn create_buffer_binding<'a>( device_id: DeviceId, bb: &BufferBinding, binding: u32, decl: &BindGroupLayoutEntry, used_buffer_ranges: &mut Vec<BufferInitTrackerAction>, dynamic_binding_info: &mut Vec<BindGroupDynamicBindingData>, late_buffer_binding_sizes: &mut HashMap<u32, BufferSize, BuildHasherDefault<FxHasher>>, used: &mut BindGroupStates<A>, storage: &'a Storage<Buffer<A>, BufferId>, limits: &Limits ) -> Result<BufferBinding<'a, A>, CreateBindGroupError>

source

fn create_texture_binding( device_id: DeviceId, view: &TextureView<A>, texture_guard: &Storage<Texture<A>, TextureId>, internal_use: TextureUses, pub_usage: TextureUsages, used: &mut BindGroupStates<A>, used_texture_ranges: &mut Vec<TextureInitTrackerAction> ) -> Result<(), CreateBindGroupError>

source

pub(super) fn create_bind_group<G: GlobalIdentityHandlerFactory>( &self, self_id: DeviceId, layout: &BindGroupLayout<A>, layout_id: Valid<BindGroupLayoutId>, desc: &BindGroupDescriptor<'_>, hub: &Hub<A, G>, token: &mut Token<'_, BindGroupLayout<A>> ) -> Result<BindGroup<A>, CreateBindGroupError>

source

fn check_array_binding( features: Features, count: Option<NonZeroU32>, num_bindings: usize ) -> Result<(), CreateBindGroupError>

source

fn texture_use_parameters( binding: u32, decl: &BindGroupLayoutEntry, view: &TextureView<A>, expected: &'static str ) -> Result<(TextureUsages, TextureUses), CreateBindGroupError>

source

pub(super) fn create_pipeline_layout( &self, self_id: DeviceId, desc: &PipelineLayoutDescriptor<'_>, bgl_guard: &Storage<BindGroupLayout<A>, BindGroupLayoutId> ) -> Result<PipelineLayout<A>, CreatePipelineLayoutError>

source

fn derive_pipeline_layout( &self, self_id: DeviceId, implicit_context: Option<ImplicitPipelineContext>, derived_group_layouts: ArrayVec<HashMap<u32, BindGroupLayoutEntry, BuildHasherDefault<FxHasher>>, { hal::MAX_BIND_GROUPS }>, bgl_guard: &mut Storage<BindGroupLayout<A>, BindGroupLayoutId>, pipeline_layout_guard: &mut Storage<PipelineLayout<A>, PipelineLayoutId> ) -> Result<PipelineLayoutId, ImplicitLayoutError>

source

pub(super) fn create_compute_pipeline<G: GlobalIdentityHandlerFactory>( &self, self_id: DeviceId, desc: &ComputePipelineDescriptor<'_>, implicit_context: Option<ImplicitPipelineContext>, hub: &Hub<A, G>, token: &mut Token<'_, Self> ) -> Result<ComputePipeline<A>, CreateComputePipelineError>

source

pub(super) fn create_render_pipeline<G: GlobalIdentityHandlerFactory>( &self, self_id: DeviceId, adapter: &Adapter<A>, desc: &RenderPipelineDescriptor<'_>, implicit_context: Option<ImplicitPipelineContext>, hub: &Hub<A, G>, token: &mut Token<'_, Self> ) -> Result<RenderPipeline<A>, CreateRenderPipelineError>

source

pub(super) fn describe_format_features( &self, adapter: &Adapter<A>, format: TextureFormat ) -> Result<TextureFormatFeatures, MissingFeatures>

source

pub(super) fn wait_for_submit( &self, submission_index: FenceValue, token: &mut Token<'_, Self> ) -> Result<(), WaitIdleError>

source

pub(super) fn create_query_set( &self, self_id: DeviceId, desc: &QuerySetDescriptor<'_> ) -> Result<QuerySet<A>, CreateQuerySetError>

source

pub(crate) fn lose(&mut self, _reason: Option<&str>)

source§

impl<A: HalApi> Device<A>

source

pub(crate) fn destroy_buffer(&self, buffer: Buffer<A>)

source

pub(crate) fn destroy_command_buffer(&self, cmd_buf: CommandBuffer<A>)

source

pub(crate) fn prepare_to_die(&mut self)

Wait for idle and remove resources that we can, before we die.

source

pub(crate) fn dispose(self)

Trait Implementations§

Auto Trait Implementations§

§

impl<A> !RefUnwindSafe for Device<A>

§

impl<A> Send for Device<A>where A: Send,

§

impl<A> Sync for Device<A>where A: Send,

§

impl<A> Unpin for Device<A>where A: Unpin, <A as Api>::BindGroup: Unpin, <A as Api>::BindGroupLayout: Unpin, <A as Api>::Buffer: Unpin, <A as Api>::CommandBuffer: Unpin, <A as Api>::CommandEncoder: Unpin, <A as Api>::ComputePipeline: Unpin, <A as Api>::Device: Unpin, <A as Api>::Fence: Unpin, <A as Api>::PipelineLayout: Unpin, <A as Api>::QuerySet: Unpin, <A as Api>::Queue: Unpin, <A as Api>::RenderPipeline: Unpin, <A as Api>::Sampler: Unpin, <A as Api>::Texture: Unpin, <A as Api>::TextureView: Unpin,

§

impl<A> !UnwindSafe for Device<A>

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WasmNotSend for Twhere T: Send,

source§

impl<T> WasmNotSync for Twhere T: Sync,