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:
life_tracker
is locked afterhub.devices
, enforced by the type systemself.trackers
is locked last (unenforced)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>
impl<A: HalApi> Device<A>
pub(crate) fn require_features( &self, feature: Features ) -> Result<(), MissingFeatures>
pub(crate) fn require_downlevel_flags( &self, flags: DownlevelFlags ) -> Result<(), MissingDownlevelFlags>
source§impl<A: HalApi> Device<A>
impl<A: HalApi> Device<A>
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>
pub fn is_valid(&self) -> bool
pub(super) fn lock_life<'this, 'token: 'this>( &'this self, _token: &mut Token<'token, Self> ) -> MutexGuard<'this, LifetimeTracker<A>>
sourcepub(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>
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.)
pub(super) fn untrack<'this, 'token: 'this, G: GlobalIdentityHandlerFactory>( &'this mut self, hub: &Hub<A, G>, trackers: &Tracker<A>, token: &mut Token<'token, Self> )
pub(super) fn create_buffer( &self, self_id: DeviceId, desc: &BufferDescriptor<'_>, transient: bool ) -> Result<Buffer<A>, CreateBufferError>
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>
pub fn create_buffer_from_hal( &self, hal_buffer: A::Buffer, self_id: DeviceId, desc: &BufferDescriptor<'_> ) -> Buffer<A>
pub(super) fn create_texture( &self, self_id: DeviceId, adapter: &Adapter<A>, desc: &TextureDescriptor<'_> ) -> Result<Texture<A>, CreateTextureError>
pub(super) fn create_texture_view( &self, texture: &Texture<A>, texture_id: TextureId, desc: &TextureViewDescriptor<'_> ) -> Result<TextureView<A>, CreateTextureViewError>
pub(super) fn create_sampler( &self, self_id: DeviceId, desc: &SamplerDescriptor<'_> ) -> Result<Sampler<A>, CreateSamplerError>
pub(super) fn create_shader_module<'a>( &self, self_id: DeviceId, desc: &ShaderModuleDescriptor<'a>, source: ShaderModuleSource<'a> ) -> Result<ShaderModule<A>, CreateShaderModuleError>
pub(super) unsafe fn create_shader_module_spirv<'a>( &self, self_id: DeviceId, desc: &ShaderModuleDescriptor<'a>, source: &'a [u32] ) -> Result<ShaderModule<A>, CreateShaderModuleError>
pub(super) fn deduplicate_bind_group_layout( self_id: DeviceId, entry_map: &HashMap<u32, BindGroupLayoutEntry, BuildHasherDefault<FxHasher>>, guard: &Storage<BindGroupLayout<A>, BindGroupLayoutId> ) -> Option<BindGroupLayoutId>
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 }>
sourcefn 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 }>
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.
pub(super) fn create_bind_group_layout( &self, self_id: DeviceId, label: &Label<'_>, entry_map: HashMap<u32, BindGroupLayoutEntry, BuildHasherDefault<FxHasher>> ) -> Result<BindGroupLayout<A>, CreateBindGroupLayoutError>
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>
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>
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>
fn check_array_binding( features: Features, count: Option<NonZeroU32>, num_bindings: usize ) -> Result<(), CreateBindGroupError>
fn texture_use_parameters( binding: u32, decl: &BindGroupLayoutEntry, view: &TextureView<A>, expected: &'static str ) -> Result<(TextureUsages, TextureUses), CreateBindGroupError>
pub(super) fn create_pipeline_layout( &self, self_id: DeviceId, desc: &PipelineLayoutDescriptor<'_>, bgl_guard: &Storage<BindGroupLayout<A>, BindGroupLayoutId> ) -> Result<PipelineLayout<A>, CreatePipelineLayoutError>
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>
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>
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>
pub(super) fn describe_format_features( &self, adapter: &Adapter<A>, format: TextureFormat ) -> Result<TextureFormatFeatures, MissingFeatures>
pub(super) fn wait_for_submit( &self, submission_index: FenceValue, token: &mut Token<'_, Self> ) -> Result<(), WaitIdleError>
pub(super) fn create_query_set( &self, self_id: DeviceId, desc: &QuerySetDescriptor<'_> ) -> Result<QuerySet<A>, CreateQuerySetError>
pub(crate) fn lose(&mut self, _reason: Option<&str>)
source§impl<A: HalApi> Device<A>
impl<A: HalApi> Device<A>
pub(crate) fn destroy_buffer(&self, buffer: Buffer<A>)
pub(crate) fn destroy_command_buffer(&self, cmd_buf: CommandBuffer<A>)
sourcepub(crate) fn prepare_to_die(&mut self)
pub(crate) fn prepare_to_die(&mut self)
Wait for idle and remove resources that we can, before we die.