use alloc::sync::Arc; use core::cell::RefCell; use core::fmt; use wgpu_core::binding_model::{BindGroup, BindGroupLayout, PipelineLayout}; use wgpu_core::command::{ CommandBuffer, CommandEncoder, ComputePass, RenderBundle, RenderBundleEncoder, RenderPass, }; use wgpu_core::device::queue::Queue; use wgpu_core::device::Device; use wgpu_core::instance::{Adapter, Instance}; use wgpu_core::pipeline::{ComputePipeline, RenderPipeline, ShaderModule}; use wgpu_core::resource::{Buffer, ExternalTexture, QuerySet, Sampler, Texture, TextureView}; use wgpu_core_remote_types::id::{ BindGroupId, ComputePassEncoderId, ExternalTextureId, RenderBundleEncoderId, RenderBundleId, RenderPassEncoderId, SamplerId, ShaderModuleId, TextureViewId, }; use crate::hub::Hub; use crate::id::{ AdapterId, BindGroupLayoutId, BufferId, CommandBufferId, CommandEncoderId, ComputePipelineId, DeviceId, PipelineLayoutId, QuerySetId, QueueId, RenderPipelineId, TextureId, }; mod bundle; mod command_encoder; mod compute_pass; mod device; mod instance; mod queue; mod render_pass; /// Wrapper around [`Instance`] that uses [`Hub`] to store all resources created by the instance behind an [`Id`]. /// /// All resource methods are implemented on [`Global`] and accept types from [`wgpu_core_remote_types`] /// (which use [`Id`]s instead of concrete resources) and maps them into [`wgpu_core`] types /// (the process which also includes resolving the IDs). /// /// [`Id`]: crate::id::Id pub struct Global { pub(crate) hub: RefCell, // the instance must be dropped last pub instance: Arc, } impl Global { pub fn new( name: &str, instance_desc: wgt::InstanceDescriptor, telemetry: Option, ) -> Self { Self { instance: Instance::new(name, instance_desc, telemetry), hub: RefCell::new(Hub::new()), } } pub fn from_instance(instance: Arc) -> Self { Self { instance, hub: RefCell::new(Hub::new()), } } pub fn instance(&self) -> &Arc { &self.instance } } // methods to import and resolve resources in the global hub impl Global { /// Import [`Arc`] into the global hub, /// returning an [`AdapterId`] under which the adapter is stored. pub fn import_adapter(&self, adapter: Arc, id_in: AdapterId) -> AdapterId { let mut hub = self.hub.borrow_mut(); hub.adapters.assign(id_in, adapter) } /// Resolve an [`AdapterId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_adapter_id(&self, adapter_id: AdapterId) -> Arc { self.hub.borrow().adapters.get(adapter_id) } /// Import [`Arc`] into the global hub, /// returning a [`DeviceId`] under which the device is stored. pub fn import_device(&self, device: Arc, id_in: DeviceId) -> DeviceId { let mut hub = self.hub.borrow_mut(); hub.devices.assign(id_in, device) } /// Resolve a [`DeviceId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_device_id(&self, device_id: DeviceId) -> Arc { self.hub.borrow().devices.get(device_id) } /// Import [`Arc`] into the global hub, /// returning a [`QueueId`] under which the queue is stored. pub fn import_queue(&self, queue: Arc, id_in: QueueId) -> QueueId { let mut hub = self.hub.borrow_mut(); hub.queues.assign(id_in, queue) } /// Resolve a [`QueueId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_queue_id(&self, queue_id: QueueId) -> Arc { self.hub.borrow().queues.get(queue_id) } /// Import [`Arc`] into the global hub, /// returning a [`PipelineLayoutId`] under which the pipeline layout is stored. pub fn import_pipeline_layout( &self, pipeline_layout: Arc, id_in: PipelineLayoutId, ) -> PipelineLayoutId { let mut hub = self.hub.borrow_mut(); hub.pipeline_layouts.assign(id_in, pipeline_layout) } /// Resolve a [`PipelineLayoutId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_pipeline_layout_id( &self, pipeline_layout_id: PipelineLayoutId, ) -> Arc { self.hub.borrow().pipeline_layouts.get(pipeline_layout_id) } /// Import [`Arc`] into the global hub, /// returning a [`ShaderModuleId`] under which the shader module is stored. pub fn import_shader_module( &self, shader_module: Arc, id_in: ShaderModuleId, ) -> ShaderModuleId { let mut hub = self.hub.borrow_mut(); hub.shader_modules.assign(id_in, shader_module) } /// Resolve a [`ShaderModuleId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_shader_module_id(&self, shader_module_id: ShaderModuleId) -> Arc { self.hub.borrow().shader_modules.get(shader_module_id) } /// Import [`Arc`] into the global hub, /// returning a [`BindGroupLayoutId`] under which the bind group layout is stored. pub fn import_bind_group_layout( &self, bind_group_layout: Arc, id_in: BindGroupLayoutId, ) -> BindGroupLayoutId { let mut hub = self.hub.borrow_mut(); hub.bind_group_layouts.assign(id_in, bind_group_layout) } /// Resolve a [`BindGroupLayoutId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_bind_group_layout_id( &self, bind_group_layout_id: BindGroupLayoutId, ) -> Arc { self.hub .borrow() .bind_group_layouts .get(bind_group_layout_id) } /// Import [`Arc`] into the global hub, /// returning a [`BindGroupId`] under which the bind group is stored. pub fn import_bind_group(&self, bind_group: Arc, id_in: BindGroupId) -> BindGroupId { let mut hub = self.hub.borrow_mut(); hub.bind_groups.assign(id_in, bind_group) } /// Resolve a [`BindGroupId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_bind_group_id(&self, bind_group_id: BindGroupId) -> Arc { self.hub.borrow().bind_groups.get(bind_group_id) } /// Import [`Arc`] into the global hub, /// returning a [`CommandEncoderId`] under which the command encoder is stored. pub fn import_command_encoder( &self, command_encoder: Arc, id_in: CommandEncoderId, ) -> CommandEncoderId { let mut hub = self.hub.borrow_mut(); hub.command_encoders.assign(id_in, command_encoder) } /// Resolve a [`CommandEncoderId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_command_encoder_id( &self, command_encoder_id: CommandEncoderId, ) -> Arc { self.hub.borrow().command_encoders.get(command_encoder_id) } /// Import [`Arc`] into the global hub, /// returning a [`CommandBufferId`] under which the command buffer is stored. pub fn import_command_buffer( &self, command_buffer: Arc, id_in: CommandBufferId, ) -> CommandBufferId { let mut hub = self.hub.borrow_mut(); hub.command_buffers.assign(id_in, command_buffer) } /// Resolve a [`CommandBufferId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_command_buffer_id( &self, command_buffer_id: CommandBufferId, ) -> Arc { self.hub.borrow().command_buffers.get(command_buffer_id) } /// Import [`Arc`] into the global hub, /// returning a [`RenderBundleId`] under which the render bundle is stored. pub fn import_render_bundle( &self, render_bundle: Arc, id_in: RenderBundleId, ) -> RenderBundleId { let mut hub = self.hub.borrow_mut(); hub.render_bundles.assign(id_in, render_bundle) } /// Resolve a [`RenderBundleId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_render_bundle_id(&self, render_bundle_id: RenderBundleId) -> Arc { self.hub.borrow().render_bundles.get(render_bundle_id) } /// Import [`Arc`] into the global hub, /// returning a [`RenderPipelineId`] under which the render pipeline is stored. pub fn import_render_pipeline( &self, render_pipeline: Arc, id_in: RenderPipelineId, ) -> RenderPipelineId { let mut hub = self.hub.borrow_mut(); hub.render_pipelines.assign(id_in, render_pipeline) } /// Resolve a [`RenderPipelineId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_render_pipeline_id( &self, render_pipeline_id: RenderPipelineId, ) -> Arc { self.hub.borrow().render_pipelines.get(render_pipeline_id) } /// Import [`Arc`] into the global hub, /// returning a [`ComputePipelineId`] under which the compute pipeline is stored. pub fn import_compute_pipeline( &self, compute_pipeline: Arc, id_in: ComputePipelineId, ) -> ComputePipelineId { let mut hub = self.hub.borrow_mut(); hub.compute_pipelines.assign(id_in, compute_pipeline) } /// Resolve a [`ComputePipelineId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_compute_pipeline_id( &self, compute_pipeline_id: ComputePipelineId, ) -> Arc { self.hub.borrow().compute_pipelines.get(compute_pipeline_id) } /// Import [`Arc`] into the global hub, /// returning a [`QuerySetId`] under which the query set is stored. pub fn import_query_set(&self, query_set: Arc, id_in: QuerySetId) -> QuerySetId { let mut hub = self.hub.borrow_mut(); hub.query_sets.assign(id_in, query_set) } /// Resolve a [`QuerySetId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_query_set_id(&self, query_set_id: QuerySetId) -> Arc { self.hub.borrow().query_sets.get(query_set_id) } /// Import [`Arc`] into the global hub, /// returning a [`BufferId`] under which the buffer is stored. pub fn import_buffer(&self, buffer: Arc, id_in: BufferId) -> BufferId { let mut hub = self.hub.borrow_mut(); hub.buffers.assign(id_in, buffer) } /// Resolve a [`BufferId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_buffer_id(&self, buffer_id: BufferId) -> Arc { self.hub.borrow().buffers.get(buffer_id) } /// Import [`Arc`] into the global hub, /// returning a [`TextureId`] under which the texture is stored. pub fn import_texture(&self, texture: Arc, id_in: TextureId) -> TextureId { let mut hub = self.hub.borrow_mut(); hub.textures.assign(id_in, texture) } /// Resolve a [`TextureId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_texture_id(&self, texture_id: TextureId) -> Arc { self.hub.borrow().textures.get(texture_id) } /// Import [`Arc`] into the global hub, /// returning a [`TextureViewId`] under which the texture view is stored. pub fn import_texture_view( &self, texture_view: Arc, id_in: TextureViewId, ) -> TextureViewId { let mut hub = self.hub.borrow_mut(); hub.texture_views.assign(id_in, texture_view) } /// Resolve a [`TextureViewId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_texture_view_id(&self, texture_view_id: TextureViewId) -> Arc { self.hub.borrow().texture_views.get(texture_view_id) } /// Import [`Arc`] into the global hub, /// returning a [`ExternalTextureId`] under which the external texture is stored. pub fn import_external_texture( &self, external_texture: Arc, id_in: ExternalTextureId, ) -> ExternalTextureId { let mut hub = self.hub.borrow_mut(); hub.external_textures.assign(id_in, external_texture) } /// Resolve a [`ExternalTextureId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_external_texture_id( &self, external_texture_id: ExternalTextureId, ) -> Arc { self.hub.borrow().external_textures.get(external_texture_id) } /// Import [`Arc`] into the global hub, /// returning a [`SamplerId`] under which the sampler is stored. pub fn import_sampler(&self, sampler: Arc, id_in: SamplerId) -> SamplerId { let mut hub = self.hub.borrow_mut(); hub.samplers.assign(id_in, sampler) } /// Resolve a [`SamplerId`] to the corresponding [`Arc`] in the global hub. pub fn resolve_sampler_id(&self, sampler_id: SamplerId) -> Arc { self.hub.borrow().samplers.get(sampler_id) } /// Import [`RenderPass`] into the global hub, /// returning a [`RenderPassEncoderId`] under which the render pass is stored. pub fn import_render_pass( &self, render_pass: RenderPass, id_in: RenderPassEncoderId, ) -> RenderPassEncoderId { let mut hub = self.hub.borrow_mut(); hub.render_passes.assign(id_in, render_pass) } /// Import [`ComputePass`] into the global hub, /// returning a [`ComputePassEncoderId`] under which the compute pass is stored. pub fn import_compute_pass( &self, compute_pass: ComputePass, id_in: ComputePassEncoderId, ) -> ComputePassEncoderId { let mut hub = self.hub.borrow_mut(); hub.compute_passes.assign(id_in, compute_pass) } /// Import [`RenderBundleEncoder`] into the global hub, /// returning a [`RenderBundleEncoderId`] under which the render bundle encoder is stored. pub fn import_render_bundle_encoder( &self, render_bundle_encoder: RenderBundleEncoder, id_in: RenderBundleEncoderId, ) -> RenderBundleEncoderId { let mut hub = self.hub.borrow_mut(); hub.render_bundle_encoders .assign(id_in, render_bundle_encoder) } } impl fmt::Debug for Global { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Global").finish() } }