diff --git a/deno_webgpu/src/binding.rs b/deno_webgpu/src/binding.rs index eeb78a2d93..9ecb3f5143 100644 --- a/deno_webgpu/src/binding.rs +++ b/deno_webgpu/src/binding.rs @@ -7,21 +7,38 @@ use deno_core::Resource; use deno_core::ResourceId; use serde::Deserialize; use std::borrow::Cow; +use std::rc::Rc; use super::error::WebGpuResult; -pub(crate) struct WebGpuBindGroupLayout(pub(crate) wgpu_core::id::BindGroupLayoutId); +pub(crate) struct WebGpuBindGroupLayout( + pub(crate) crate::Instance, + pub(crate) wgpu_core::id::BindGroupLayoutId, +); impl Resource for WebGpuBindGroupLayout { fn name(&self) -> Cow { "webGPUBindGroupLayout".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.bind_group_layout_drop(self.1)); + } } -pub(crate) struct WebGpuBindGroup(pub(crate) wgpu_core::id::BindGroupId); +pub(crate) struct WebGpuBindGroup( + pub(crate) crate::Instance, + pub(crate) wgpu_core::id::BindGroupId, +); impl Resource for WebGpuBindGroup { fn name(&self) -> Cow { "webGPUBindGroup".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.bind_group_drop(self.1)); + } } #[derive(Deserialize)] @@ -170,7 +187,7 @@ pub fn op_webgpu_create_bind_group_layout( let device_resource = state .resource_table .get::(device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let entries = entries .into_iter() @@ -207,13 +224,13 @@ pub fn op_webgpu_create_pipeline_layout( let device_resource = state .resource_table .get::(device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let bind_group_layouts = bind_group_layouts .into_iter() .map(|rid| { let bind_group_layout = state.resource_table.get::(rid)?; - Ok(bind_group_layout.0) + Ok(bind_group_layout.1) }) .collect::, AnyError>>()?; @@ -252,7 +269,7 @@ pub fn op_webgpu_create_bind_group( let device_resource = state .resource_table .get::(device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let entries = entries .into_iter() @@ -264,7 +281,7 @@ pub fn op_webgpu_create_bind_group( let sampler_resource = state .resource_table .get::(entry.resource)?; - wgpu_core::binding_model::BindingResource::Sampler(sampler_resource.0) + wgpu_core::binding_model::BindingResource::Sampler(sampler_resource.1) } "GPUTextureView" => { let texture_view_resource = @@ -272,7 +289,7 @@ pub fn op_webgpu_create_bind_group( .resource_table .get::(entry.resource)?; wgpu_core::binding_model::BindingResource::TextureView( - texture_view_resource.0, + texture_view_resource.1, ) } "GPUBufferBinding" => { @@ -281,7 +298,7 @@ pub fn op_webgpu_create_bind_group( .get::(entry.resource)?; wgpu_core::binding_model::BindingResource::Buffer( wgpu_core::binding_model::BufferBinding { - buffer_id: buffer_resource.0, + buffer_id: buffer_resource.1, offset: entry.offset.unwrap_or(0), size: std::num::NonZeroU64::new(entry.size.unwrap_or(0)), }, @@ -297,7 +314,7 @@ pub fn op_webgpu_create_bind_group( let descriptor = wgpu_core::binding_model::BindGroupDescriptor { label: label.map(Cow::from), - layout: bind_group_layout.0, + layout: bind_group_layout.1, entries: Cow::from(entries), }; diff --git a/deno_webgpu/src/buffer.rs b/deno_webgpu/src/buffer.rs index 34de46e6ae..7c5f9d58c2 100644 --- a/deno_webgpu/src/buffer.rs +++ b/deno_webgpu/src/buffer.rs @@ -18,11 +18,19 @@ use wgpu_core::resource::BufferAccessResult; use super::error::DomExceptionOperationError; use super::error::WebGpuResult; -pub(crate) struct WebGpuBuffer(pub(crate) wgpu_core::id::BufferId); +pub(crate) struct WebGpuBuffer( + pub(crate) super::Instance, + pub(crate) wgpu_core::id::BufferId, +); impl Resource for WebGpuBuffer { fn name(&self) -> Cow { "webGPUBuffer".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.buffer_drop(self.1, true)); + } } struct WebGpuBufferMapped(*mut u8, usize); @@ -45,7 +53,7 @@ pub fn op_webgpu_create_buffer( let device_resource = state .resource_table .get::(device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let descriptor = wgpu_core::resource::BufferDescriptor { label: label.map(Cow::from), @@ -78,11 +86,11 @@ pub async fn op_webgpu_buffer_get_map_async( let state_ = state.borrow(); let instance = state_.borrow::(); let buffer_resource = state_.resource_table.get::(buffer_rid)?; - let buffer = buffer_resource.0; + let buffer = buffer_resource.1; let device_resource = state_ .resource_table .get::(device_rid)?; - device = device_resource.0; + device = device_resource.1; let callback = Box::new(move |status| { sender.send(status).unwrap(); @@ -145,7 +153,7 @@ pub fn op_webgpu_buffer_get_mapped_range( ) -> Result { let instance = state.borrow::(); let buffer_resource = state.resource_table.get::(buffer_rid)?; - let buffer = buffer_resource.0; + let buffer = buffer_resource.1; let (slice_pointer, range_size) = gfx_select!(buffer => instance.buffer_get_mapped_range( buffer, @@ -176,7 +184,7 @@ pub fn op_webgpu_buffer_unmap( .take::(mapped_rid)?; let instance = state.borrow::(); let buffer_resource = state.resource_table.get::(buffer_rid)?; - let buffer = buffer_resource.0; + let buffer = buffer_resource.1; if let Some(buf) = buf { let slice = unsafe { std::slice::from_raw_parts_mut(mapped_resource.0, mapped_resource.1) }; diff --git a/deno_webgpu/src/bundle.rs b/deno_webgpu/src/bundle.rs index 33434b1f42..bcb321f497 100644 --- a/deno_webgpu/src/bundle.rs +++ b/deno_webgpu/src/bundle.rs @@ -1,6 +1,7 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use deno_core::error::{type_error, AnyError}; +use deno_core::error::type_error; +use deno_core::error::AnyError; use deno_core::op; use deno_core::OpState; use deno_core::Resource; @@ -20,11 +21,19 @@ impl Resource for WebGpuRenderBundleEncoder { } } -pub(crate) struct WebGpuRenderBundle(pub(crate) wgpu_core::id::RenderBundleId); +pub(crate) struct WebGpuRenderBundle( + pub(crate) super::Instance, + pub(crate) wgpu_core::id::RenderBundleId, +); impl Resource for WebGpuRenderBundle { fn name(&self) -> Cow { "webGPURenderBundle".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.render_bundle_drop(self.1)); + } } #[derive(Deserialize)] @@ -47,7 +56,7 @@ pub fn op_webgpu_create_render_bundle_encoder( let device_resource = state .resource_table .get::(args.device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let depth_stencil = args.depth_stencil_format @@ -148,7 +157,7 @@ pub fn op_webgpu_render_bundle_encoder_set_bind_group( wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_bind_group( &mut render_bundle_encoder_resource.0.borrow_mut(), index, - bind_group_resource.0, + bind_group_resource.1, dynamic_offsets_data.as_ptr(), dynamic_offsets_data.len(), ); @@ -234,7 +243,7 @@ pub fn op_webgpu_render_bundle_encoder_set_pipeline( wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_pipeline( &mut render_bundle_encoder_resource.0.borrow_mut(), - render_pipeline_resource.0, + render_pipeline_resource.1, ); Ok(WebGpuResult::empty()) @@ -262,7 +271,7 @@ pub fn op_webgpu_render_bundle_encoder_set_index_buffer( render_bundle_encoder_resource .0 .borrow_mut() - .set_index_buffer(buffer_resource.0, index_format, offset, size); + .set_index_buffer(buffer_resource.1, index_format, offset, size); Ok(WebGpuResult::empty()) } @@ -294,7 +303,7 @@ pub fn op_webgpu_render_bundle_encoder_set_vertex_buffer( wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_vertex_buffer( &mut render_bundle_encoder_resource.0.borrow_mut(), slot, - buffer_resource.0, + buffer_resource.1, offset, size, ); @@ -368,7 +377,7 @@ pub fn op_webgpu_render_bundle_encoder_draw_indirect( wgpu_core::command::bundle_ffi::wgpu_render_bundle_draw_indirect( &mut render_bundle_encoder_resource.0.borrow_mut(), - buffer_resource.0, + buffer_resource.1, indirect_offset, ); diff --git a/deno_webgpu/src/command_encoder.rs b/deno_webgpu/src/command_encoder.rs index 8d06af887c..6df0a4a93c 100644 --- a/deno_webgpu/src/command_encoder.rs +++ b/deno_webgpu/src/command_encoder.rs @@ -9,21 +9,40 @@ use serde::Deserialize; use std::borrow::Cow; use std::cell::RefCell; use std::num::NonZeroU32; +use std::rc::Rc; use super::error::WebGpuResult; -pub(crate) struct WebGpuCommandEncoder(pub(crate) wgpu_core::id::CommandEncoderId); +pub(crate) struct WebGpuCommandEncoder( + pub(crate) super::Instance, + pub(crate) wgpu_core::id::CommandEncoderId, // TODO: should maybe be option? +); impl Resource for WebGpuCommandEncoder { fn name(&self) -> Cow { "webGPUCommandEncoder".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.command_encoder_drop(self.1)); + } } -pub(crate) struct WebGpuCommandBuffer(pub(crate) wgpu_core::id::CommandBufferId); +pub(crate) struct WebGpuCommandBuffer( + pub(crate) super::Instance, + pub(crate) RefCell>, +); impl Resource for WebGpuCommandBuffer { fn name(&self) -> Cow { "webGPUCommandBuffer".into() } + + fn close(self: Rc) { + if let Some(id) = *self.1.borrow() { + let instance = &self.0; + gfx_select!(id => instance.command_buffer_drop(id)); + } + } } #[op] @@ -36,7 +55,7 @@ pub fn op_webgpu_create_command_encoder( let device_resource = state .resource_table .get::(device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let descriptor = wgpu_types::CommandEncoderDescriptor { label: label.map(Cow::from), @@ -101,10 +120,10 @@ pub fn op_webgpu_command_encoder_begin_render_pass( .get::(rid) }) .transpose()? - .map(|texture| texture.0); + .map(|texture| texture.1); Some(wgpu_core::command::RenderPassColorAttachment { - view: texture_view_resource.0, + view: texture_view_resource.1, resolve_target, channel: wgpu_core::command::PassChannel { load_op: at.load_op, @@ -129,7 +148,7 @@ pub fn op_webgpu_command_encoder_begin_render_pass( processed_depth_stencil_attachment = Some(wgpu_core::command::RenderPassDepthStencilAttachment { - view: texture_view_resource.0, + view: texture_view_resource.1, depth: wgpu_core::command::PassChannel { load_op: attachment .depth_load_op @@ -159,7 +178,7 @@ pub fn op_webgpu_command_encoder_begin_render_pass( depth_stencil_attachment: processed_depth_stencil_attachment.as_ref(), }; - let render_pass = wgpu_core::command::RenderPass::new(command_encoder_resource.0, &descriptor); + let render_pass = wgpu_core::command::RenderPass::new(command_encoder_resource.1, &descriptor); let rid = state .resource_table @@ -185,7 +204,7 @@ pub fn op_webgpu_command_encoder_begin_compute_pass( }; let compute_pass = - wgpu_core::command::ComputePass::new(command_encoder_resource.0, &descriptor); + wgpu_core::command::ComputePass::new(command_encoder_resource.1, &descriptor); let rid = state .resource_table @@ -210,15 +229,15 @@ pub fn op_webgpu_command_encoder_copy_buffer_to_buffer( let command_encoder_resource = state .resource_table .get::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; let source_buffer_resource = state .resource_table .get::(source)?; - let source_buffer = source_buffer_resource.0; + let source_buffer = source_buffer_resource.1; let destination_buffer_resource = state .resource_table .get::(destination)?; - let destination_buffer = destination_buffer_resource.0; + let destination_buffer = destination_buffer_resource.1; gfx_ok!(command_encoder => instance.command_encoder_copy_buffer_to_buffer( command_encoder, @@ -260,7 +279,7 @@ pub fn op_webgpu_command_encoder_copy_buffer_to_texture( let command_encoder_resource = state .resource_table .get::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; let source_buffer_resource = state .resource_table .get::(source.buffer)?; @@ -269,7 +288,7 @@ pub fn op_webgpu_command_encoder_copy_buffer_to_texture( .get::(destination.texture)?; let source = wgpu_core::command::ImageCopyBuffer { - buffer: source_buffer_resource.0, + buffer: source_buffer_resource.1, layout: wgpu_types::ImageDataLayout { offset: source.offset, bytes_per_row: NonZeroU32::new(source.bytes_per_row.unwrap_or(0)), @@ -277,7 +296,7 @@ pub fn op_webgpu_command_encoder_copy_buffer_to_texture( }, }; let destination = wgpu_core::command::ImageCopyTexture { - texture: destination_texture_resource.0, + texture: destination_texture_resource.id, mip_level: destination.mip_level, origin: destination.origin, aspect: destination.aspect, @@ -302,7 +321,7 @@ pub fn op_webgpu_command_encoder_copy_texture_to_buffer( let command_encoder_resource = state .resource_table .get::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; let source_texture_resource = state .resource_table .get::(source.texture)?; @@ -311,13 +330,13 @@ pub fn op_webgpu_command_encoder_copy_texture_to_buffer( .get::(destination.buffer)?; let source = wgpu_core::command::ImageCopyTexture { - texture: source_texture_resource.0, + texture: source_texture_resource.id, mip_level: source.mip_level, origin: source.origin, aspect: source.aspect, }; let destination = wgpu_core::command::ImageCopyBuffer { - buffer: destination_buffer_resource.0, + buffer: destination_buffer_resource.1, layout: wgpu_types::ImageDataLayout { offset: destination.offset, bytes_per_row: NonZeroU32::new(destination.bytes_per_row.unwrap_or(0)), @@ -344,7 +363,7 @@ pub fn op_webgpu_command_encoder_copy_texture_to_texture( let command_encoder_resource = state .resource_table .get::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; let source_texture_resource = state .resource_table .get::(source.texture)?; @@ -353,13 +372,13 @@ pub fn op_webgpu_command_encoder_copy_texture_to_texture( .get::(destination.texture)?; let source = wgpu_core::command::ImageCopyTexture { - texture: source_texture_resource.0, + texture: source_texture_resource.id, mip_level: source.mip_level, origin: source.origin, aspect: source.aspect, }; let destination = wgpu_core::command::ImageCopyTexture { - texture: destination_texture_resource.0, + texture: destination_texture_resource.id, mip_level: destination.mip_level, origin: destination.origin, aspect: destination.aspect, @@ -384,14 +403,14 @@ pub fn op_webgpu_command_encoder_clear_buffer( let command_encoder_resource = state .resource_table .get::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; let destination_resource = state .resource_table .get::(buffer_rid)?; gfx_ok!(command_encoder => instance.command_encoder_clear_buffer( command_encoder, - destination_resource.0, + destination_resource.1, offset, std::num::NonZeroU64::new(size) )) @@ -407,7 +426,7 @@ pub fn op_webgpu_command_encoder_push_debug_group( let command_encoder_resource = state .resource_table .get::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; gfx_ok!(command_encoder => instance.command_encoder_push_debug_group(command_encoder, &group_label)) } @@ -421,7 +440,7 @@ pub fn op_webgpu_command_encoder_pop_debug_group( let command_encoder_resource = state .resource_table .get::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; gfx_ok!(command_encoder => instance.command_encoder_pop_debug_group(command_encoder)) } @@ -436,7 +455,7 @@ pub fn op_webgpu_command_encoder_insert_debug_marker( let command_encoder_resource = state .resource_table .get::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; gfx_ok!(command_encoder => instance.command_encoder_insert_debug_marker( command_encoder, @@ -455,14 +474,14 @@ pub fn op_webgpu_command_encoder_write_timestamp( let command_encoder_resource = state .resource_table .get::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; let query_set_resource = state .resource_table .get::(query_set)?; gfx_ok!(command_encoder => instance.command_encoder_write_timestamp( command_encoder, - query_set_resource.0, + query_set_resource.1, query_index )) } @@ -481,7 +500,7 @@ pub fn op_webgpu_command_encoder_resolve_query_set( let command_encoder_resource = state .resource_table .get::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; let query_set_resource = state .resource_table .get::(query_set)?; @@ -491,10 +510,10 @@ pub fn op_webgpu_command_encoder_resolve_query_set( gfx_ok!(command_encoder => instance.command_encoder_resolve_query_set( command_encoder, - query_set_resource.0, + query_set_resource.1, first_query, query_count, - destination_resource.0, + destination_resource.1, destination_offset )) } @@ -508,15 +527,22 @@ pub fn op_webgpu_command_encoder_finish( let command_encoder_resource = state .resource_table .take::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; let instance = state.borrow::(); let descriptor = wgpu_types::CommandBufferDescriptor { label: label.map(Cow::from), }; - gfx_put!(command_encoder => instance.command_encoder_finish( - command_encoder, - &descriptor - ) => state, WebGpuCommandBuffer) + let (val, maybe_err) = gfx_select!(command_encoder => instance.command_encoder_finish( + command_encoder, + &descriptor + )); + + let rid = state.resource_table.add(WebGpuCommandBuffer( + instance.clone(), + RefCell::new(Some(val)), + )); + + Ok(WebGpuResult::rid_err(rid, maybe_err)) } diff --git a/deno_webgpu/src/compute_pass.rs b/deno_webgpu/src/compute_pass.rs index 012aefdcae..cc70146917 100644 --- a/deno_webgpu/src/compute_pass.rs +++ b/deno_webgpu/src/compute_pass.rs @@ -33,7 +33,7 @@ pub fn op_webgpu_compute_pass_set_pipeline( wgpu_core::command::compute_ffi::wgpu_compute_pass_set_pipeline( &mut compute_pass_resource.0.borrow_mut(), - compute_pipeline_resource.0, + compute_pipeline_resource.1, ); Ok(WebGpuResult::empty()) @@ -77,7 +77,7 @@ pub fn op_webgpu_compute_pass_dispatch_workgroups_indirect( wgpu_core::command::compute_ffi::wgpu_compute_pass_dispatch_workgroups_indirect( &mut compute_pass_resource.0.borrow_mut(), - buffer_resource.0, + buffer_resource.1, indirect_offset, ); @@ -100,7 +100,7 @@ pub fn op_webgpu_compute_pass_begin_pipeline_statistics_query( wgpu_core::command::compute_ffi::wgpu_compute_pass_begin_pipeline_statistics_query( &mut compute_pass_resource.0.borrow_mut(), - query_set_resource.0, + query_set_resource.1, query_index, ); @@ -139,7 +139,7 @@ pub fn op_webgpu_compute_pass_write_timestamp( wgpu_core::command::compute_ffi::wgpu_compute_pass_write_timestamp( &mut compute_pass_resource.0.borrow_mut(), - query_set_resource.0, + query_set_resource.1, query_index, ); @@ -156,7 +156,7 @@ pub fn op_webgpu_compute_pass_end( state .resource_table .get::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; let compute_pass_resource = state .resource_table .take::(compute_pass_rid)?; @@ -209,7 +209,7 @@ pub fn op_webgpu_compute_pass_set_bind_group( wgpu_core::command::compute_ffi::wgpu_compute_pass_set_bind_group( &mut compute_pass_resource.0.borrow_mut(), index, - bind_group_resource.0, + bind_group_resource.1, dynamic_offsets_data.as_ptr(), dynamic_offsets_data.len(), ); diff --git a/deno_webgpu/src/lib.rs b/deno_webgpu/src/lib.rs index efe04e5be2..78ce06bc42 100644 --- a/deno_webgpu/src/lib.rs +++ b/deno_webgpu/src/lib.rs @@ -52,7 +52,7 @@ mod macros { macro_rules! gfx_put { ($id:expr => $global:ident.$method:ident( $($param:expr),* ) => $state:expr, $rc:expr) => {{ let (val, maybe_err) = gfx_select!($id => $global.$method($($param),*)); - let rid = $state.resource_table.add($rc(val)); + let rid = $state.resource_table.add($rc($global.clone(), val)); Ok(WebGpuResult::rid_err(rid, maybe_err)) }}; } @@ -93,27 +93,42 @@ fn check_unstable(state: &OpState, api_name: &str) { } } -pub type Instance = wgpu_core::hub::Global; +pub type Instance = std::sync::Arc>; -struct WebGpuAdapter(wgpu_core::id::AdapterId); +struct WebGpuAdapter(Instance, wgpu_core::id::AdapterId); impl Resource for WebGpuAdapter { fn name(&self) -> Cow { "webGPUAdapter".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.adapter_drop(self.1)); + } } -struct WebGpuDevice(wgpu_core::id::DeviceId); +struct WebGpuDevice(Instance, wgpu_core::id::DeviceId); impl Resource for WebGpuDevice { fn name(&self) -> Cow { "webGPUDevice".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.device_drop(self.1)); + } } -struct WebGpuQuerySet(wgpu_core::id::QuerySetId); +struct WebGpuQuerySet(Instance, wgpu_core::id::QuerySetId); impl Resource for WebGpuQuerySet { fn name(&self) -> Cow { "webGPUQuerySet".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.query_set_drop(self.1)); + } } pub fn init(unstable: bool) -> Extension { @@ -298,14 +313,14 @@ pub async fn op_webgpu_request_adapter( let instance = if let Some(instance) = state.try_borrow::() { instance } else { - state.put(wgpu_core::hub::Global::new( + state.put(std::sync::Arc::new(wgpu_core::hub::Global::new( "webgpu", wgpu_core::hub::IdentityManagerFactory, wgpu_types::InstanceDescriptor { backends, dx12_shader_compiler: wgpu_types::Dx12Compiler::Fxc, }, - )); + ))); state.borrow::() }; @@ -331,7 +346,9 @@ pub async fn op_webgpu_request_adapter( let features = deserialize_features(&adapter_features); let adapter_limits = gfx_select!(adapter => instance.adapter_limits(adapter))?; - let rid = state.resource_table.add(WebGpuAdapter(adapter)); + let instance = instance.clone(); + + let rid = state.resource_table.add(WebGpuAdapter(instance, adapter)); Ok(GpuAdapterDeviceOrErr::Features(GpuAdapterDevice { rid, @@ -531,7 +548,7 @@ pub async fn op_webgpu_request_device( ) -> Result { let mut state = state.borrow_mut(); let adapter_resource = state.resource_table.get::(adapter_rid)?; - let adapter = adapter_resource.0; + let adapter = adapter_resource.1; let instance = state.borrow::(); let descriptor = wgpu_types::DeviceDescriptor { @@ -554,7 +571,8 @@ pub async fn op_webgpu_request_device( let features = deserialize_features(&device_features); let limits = gfx_select!(device => instance.device_limits(device))?; - let rid = state.resource_table.add(WebGpuDevice(device)); + let instance = instance.clone(); + let rid = state.resource_table.add(WebGpuDevice(instance, device)); Ok(GpuAdapterDevice { rid, @@ -581,7 +599,7 @@ pub async fn op_webgpu_request_adapter_info( ) -> Result { let state = state.borrow_mut(); let adapter_resource = state.resource_table.get::(adapter_rid)?; - let adapter = adapter_resource.0; + let adapter = adapter_resource.1; let instance = state.borrow::(); let info = gfx_select!(adapter => instance.adapter_get_info(adapter))?; @@ -655,8 +673,8 @@ pub fn op_webgpu_create_query_set( args: CreateQuerySetArgs, ) -> Result { let device_resource = state.resource_table.get::(args.device_rid)?; - let device = device_resource.0; - let instance = &state.borrow::(); + let device = device_resource.1; + let instance = state.borrow::(); let descriptor = wgpu_types::QuerySetDescriptor { label: args.label.map(Cow::from), diff --git a/deno_webgpu/src/pipeline.rs b/deno_webgpu/src/pipeline.rs index f33dc2de3f..13589df2da 100644 --- a/deno_webgpu/src/pipeline.rs +++ b/deno_webgpu/src/pipeline.rs @@ -8,31 +8,56 @@ use deno_core::ResourceId; use serde::Deserialize; use serde::Serialize; use std::borrow::Cow; +use std::rc::Rc; use super::error::WebGpuError; use super::error::WebGpuResult; const MAX_BIND_GROUPS: usize = 8; -pub(crate) struct WebGpuPipelineLayout(pub(crate) wgpu_core::id::PipelineLayoutId); +pub(crate) struct WebGpuPipelineLayout( + pub(crate) crate::Instance, + pub(crate) wgpu_core::id::PipelineLayoutId, +); impl Resource for WebGpuPipelineLayout { fn name(&self) -> Cow { "webGPUPipelineLayout".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.pipeline_layout_drop(self.1)); + } } -pub(crate) struct WebGpuComputePipeline(pub(crate) wgpu_core::id::ComputePipelineId); +pub(crate) struct WebGpuComputePipeline( + pub(crate) crate::Instance, + pub(crate) wgpu_core::id::ComputePipelineId, +); impl Resource for WebGpuComputePipeline { fn name(&self) -> Cow { "webGPUComputePipeline".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.compute_pipeline_drop(self.1)); + } } -pub(crate) struct WebGpuRenderPipeline(pub(crate) wgpu_core::id::RenderPipelineId); +pub(crate) struct WebGpuRenderPipeline( + pub(crate) crate::Instance, + pub(crate) wgpu_core::id::RenderPipelineId, +); impl Resource for WebGpuRenderPipeline { fn name(&self) -> Cow { "webGPURenderPipeline".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.render_pipeline_drop(self.1)); + } } #[derive(Deserialize)] @@ -68,12 +93,12 @@ pub fn op_webgpu_create_compute_pipeline( let device_resource = state .resource_table .get::(device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let pipeline_layout = match layout { GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(rid) => { let id = state.resource_table.get::(rid)?; - Some(id.0) + Some(id.1) } GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => None, }; @@ -86,7 +111,7 @@ pub fn op_webgpu_create_compute_pipeline( label: label.map(Cow::from), layout: pipeline_layout, stage: wgpu_core::pipeline::ProgrammableStageDescriptor { - module: compute_shader_module_resource.0, + module: compute_shader_module_resource.1, entry_point: Cow::from(compute.entry_point), // TODO(lucacasonato): support args.compute.constants }, @@ -110,7 +135,7 @@ pub fn op_webgpu_create_compute_pipeline( let rid = state .resource_table - .add(WebGpuComputePipeline(compute_pipeline)); + .add(WebGpuComputePipeline(instance.clone(), compute_pipeline)); Ok(WebGpuResult::rid_err(rid, maybe_err)) } @@ -133,7 +158,7 @@ pub fn op_webgpu_compute_pipeline_get_bind_group_layout( let compute_pipeline_resource = state .resource_table .get::(compute_pipeline_rid)?; - let compute_pipeline = compute_pipeline_resource.0; + let compute_pipeline = compute_pipeline_resource.1; let (bind_group_layout, maybe_err) = gfx_select!(compute_pipeline => instance.compute_pipeline_get_bind_group_layout(compute_pipeline, index, ())); @@ -142,7 +167,10 @@ pub fn op_webgpu_compute_pipeline_get_bind_group_layout( let rid = state .resource_table - .add(super::binding::WebGpuBindGroupLayout(bind_group_layout)); + .add(super::binding::WebGpuBindGroupLayout( + instance.clone(), + bind_group_layout, + )); Ok(PipelineLayout { rid, @@ -304,12 +332,12 @@ pub fn op_webgpu_create_render_pipeline( let device_resource = state .resource_table .get::(args.device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let layout = match args.layout { GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(rid) => { let pipeline_layout_resource = state.resource_table.get::(rid)?; - Some(pipeline_layout_resource.0) + Some(pipeline_layout_resource.1) } GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => None, }; @@ -326,7 +354,7 @@ pub fn op_webgpu_create_render_pipeline( Some(wgpu_core::pipeline::FragmentState { stage: wgpu_core::pipeline::ProgrammableStageDescriptor { - module: fragment_shader_module_resource.0, + module: fragment_shader_module_resource.1, entry_point: Cow::from(fragment.entry_point), }, targets: Cow::from(fragment.targets), @@ -348,7 +376,7 @@ pub fn op_webgpu_create_render_pipeline( layout, vertex: wgpu_core::pipeline::VertexState { stage: wgpu_core::pipeline::ProgrammableStageDescriptor { - module: vertex_shader_module_resource.0, + module: vertex_shader_module_resource.1, entry_point: Cow::Owned(args.vertex.entry_point), }, buffers: Cow::Owned(vertex_buffers), @@ -379,7 +407,7 @@ pub fn op_webgpu_create_render_pipeline( let rid = state .resource_table - .add(WebGpuRenderPipeline(render_pipeline)); + .add(WebGpuRenderPipeline(instance.clone(), render_pipeline)); Ok(WebGpuResult::rid_err(rid, maybe_err)) } @@ -394,7 +422,7 @@ pub fn op_webgpu_render_pipeline_get_bind_group_layout( let render_pipeline_resource = state .resource_table .get::(render_pipeline_rid)?; - let render_pipeline = render_pipeline_resource.0; + let render_pipeline = render_pipeline_resource.1; let (bind_group_layout, maybe_err) = gfx_select!(render_pipeline => instance.render_pipeline_get_bind_group_layout(render_pipeline, index, ())); @@ -403,7 +431,10 @@ pub fn op_webgpu_render_pipeline_get_bind_group_layout( let rid = state .resource_table - .add(super::binding::WebGpuBindGroupLayout(bind_group_layout)); + .add(super::binding::WebGpuBindGroupLayout( + instance.clone(), + bind_group_layout, + )); Ok(PipelineLayout { rid, diff --git a/deno_webgpu/src/queue.rs b/deno_webgpu/src/queue.rs index 5e310ae99c..4265d7b488 100644 --- a/deno_webgpu/src/queue.rs +++ b/deno_webgpu/src/queue.rs @@ -21,7 +21,7 @@ pub fn op_webgpu_queue_submit( ) -> Result { let instance = state.borrow::(); let queue_resource = state.resource_table.get::(queue_rid)?; - let queue = queue_resource.0; + let queue = queue_resource.1; let ids = command_buffers .iter() @@ -29,7 +29,8 @@ pub fn op_webgpu_queue_submit( let buffer_resource = state .resource_table .get::(*rid)?; - Ok(buffer_resource.0) + let mut id = buffer_resource.1.borrow_mut(); + Ok(id.take().unwrap()) }) .collect::, AnyError>>()?; @@ -74,9 +75,9 @@ pub fn op_webgpu_write_buffer( let buffer_resource = state .resource_table .get::(buffer)?; - let buffer = buffer_resource.0; + let buffer = buffer_resource.1; let queue_resource = state.resource_table.get::(queue_rid)?; - let queue = queue_resource.0; + let queue = queue_resource.1; let data = match size { Some(size) => &buf[data_offset..(data_offset + size)], @@ -107,10 +108,10 @@ pub fn op_webgpu_write_texture( .resource_table .get::(destination.texture)?; let queue_resource = state.resource_table.get::(queue_rid)?; - let queue = queue_resource.0; + let queue = queue_resource.1; let destination = wgpu_core::command::ImageCopyTexture { - texture: texture_resource.0, + texture: texture_resource.id, mip_level: destination.mip_level, origin: destination.origin, aspect: destination.aspect, diff --git a/deno_webgpu/src/render_pass.rs b/deno_webgpu/src/render_pass.rs index 4e8431e784..4b0621fc4a 100644 --- a/deno_webgpu/src/render_pass.rs +++ b/deno_webgpu/src/render_pass.rs @@ -130,7 +130,7 @@ pub fn op_webgpu_render_pass_begin_pipeline_statistics_query( wgpu_core::command::render_ffi::wgpu_render_pass_begin_pipeline_statistics_query( &mut render_pass_resource.0.borrow_mut(), - query_set_resource.0, + query_set_resource.1, query_index, ); @@ -169,7 +169,7 @@ pub fn op_webgpu_render_pass_write_timestamp( wgpu_core::command::render_ffi::wgpu_render_pass_write_timestamp( &mut render_pass_resource.0.borrow_mut(), - query_set_resource.0, + query_set_resource.1, query_index, ); @@ -188,7 +188,7 @@ pub fn op_webgpu_render_pass_execute_bundles( let render_bundle_resource = state .resource_table .get::(*rid)?; - Ok(render_bundle_resource.0) + Ok(render_bundle_resource.1) }) .collect::, AnyError>>()?; @@ -219,7 +219,7 @@ pub fn op_webgpu_render_pass_end( state .resource_table .get::(command_encoder_rid)?; - let command_encoder = command_encoder_resource.0; + let command_encoder = command_encoder_resource.1; let render_pass_resource = state .resource_table .take::(render_pass_rid)?; @@ -269,7 +269,7 @@ pub fn op_webgpu_render_pass_set_bind_group( wgpu_core::command::render_ffi::wgpu_render_pass_set_bind_group( &mut render_pass_resource.0.borrow_mut(), index, - bind_group_resource.0, + bind_group_resource.1, dynamic_offsets_data.as_ptr(), dynamic_offsets_data.len(), ); @@ -357,7 +357,7 @@ pub fn op_webgpu_render_pass_set_pipeline( wgpu_core::command::render_ffi::wgpu_render_pass_set_pipeline( &mut render_pass_resource.0.borrow_mut(), - render_pipeline_resource.0, + render_pipeline_resource.1, ); Ok(WebGpuResult::empty()) @@ -389,7 +389,7 @@ pub fn op_webgpu_render_pass_set_index_buffer( }; render_pass_resource.0.borrow_mut().set_index_buffer( - buffer_resource.0, + buffer_resource.1, index_format, offset, size, @@ -426,7 +426,7 @@ pub fn op_webgpu_render_pass_set_vertex_buffer( wgpu_core::command::render_ffi::wgpu_render_pass_set_vertex_buffer( &mut render_pass_resource.0.borrow_mut(), slot, - buffer_resource.0, + buffer_resource.1, offset, size, ); @@ -500,7 +500,7 @@ pub fn op_webgpu_render_pass_draw_indirect( wgpu_core::command::render_ffi::wgpu_render_pass_draw_indirect( &mut render_pass_resource.0.borrow_mut(), - buffer_resource.0, + buffer_resource.1, indirect_offset, ); @@ -523,7 +523,7 @@ pub fn op_webgpu_render_pass_draw_indexed_indirect( wgpu_core::command::render_ffi::wgpu_render_pass_draw_indexed_indirect( &mut render_pass_resource.0.borrow_mut(), - buffer_resource.0, + buffer_resource.1, indirect_offset, ); diff --git a/deno_webgpu/src/sampler.rs b/deno_webgpu/src/sampler.rs index 4bf1bce15d..e5f230b2dd 100644 --- a/deno_webgpu/src/sampler.rs +++ b/deno_webgpu/src/sampler.rs @@ -7,14 +7,23 @@ use deno_core::Resource; use deno_core::ResourceId; use serde::Deserialize; use std::borrow::Cow; +use std::rc::Rc; use super::error::WebGpuResult; -pub(crate) struct WebGpuSampler(pub(crate) wgpu_core::id::SamplerId); +pub(crate) struct WebGpuSampler( + pub(crate) crate::Instance, + pub(crate) wgpu_core::id::SamplerId, +); impl Resource for WebGpuSampler { fn name(&self) -> Cow { "webGPUSampler".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.sampler_drop(self.1)); + } } #[derive(Deserialize)] @@ -43,7 +52,7 @@ pub fn op_webgpu_create_sampler( let device_resource = state .resource_table .get::(args.device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let descriptor = wgpu_core::resource::SamplerDescriptor { label: args.label.map(Cow::from), diff --git a/deno_webgpu/src/shader.rs b/deno_webgpu/src/shader.rs index d4025fb95e..fb4f316926 100644 --- a/deno_webgpu/src/shader.rs +++ b/deno_webgpu/src/shader.rs @@ -6,14 +6,23 @@ use deno_core::OpState; use deno_core::Resource; use deno_core::ResourceId; use std::borrow::Cow; +use std::rc::Rc; use super::error::WebGpuResult; -pub(crate) struct WebGpuShaderModule(pub(crate) wgpu_core::id::ShaderModuleId); +pub(crate) struct WebGpuShaderModule( + pub(crate) super::Instance, + pub(crate) wgpu_core::id::ShaderModuleId, +); impl Resource for WebGpuShaderModule { fn name(&self) -> Cow { "webGPUShaderModule".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.shader_module_drop(self.1)); + } } #[op] @@ -27,7 +36,7 @@ pub fn op_webgpu_create_shader_module( let device_resource = state .resource_table .get::(device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let source = wgpu_core::pipeline::ShaderModuleSource::Wgsl(Cow::from(code)); diff --git a/deno_webgpu/src/surface.rs b/deno_webgpu/src/surface.rs index 2aa9762af9..379bf7b750 100644 --- a/deno_webgpu/src/surface.rs +++ b/deno_webgpu/src/surface.rs @@ -10,6 +10,7 @@ use deno_core::Resource; use deno_core::ResourceId; use serde::Deserialize; use std::borrow::Cow; +use std::rc::Rc; use wgpu_types::SurfaceStatus; pub fn init_surface(unstable: bool) -> Extension { @@ -36,11 +37,15 @@ pub fn init_surface(unstable: bool) -> Extension { .build() } -pub struct WebGpuSurface(pub wgpu_core::id::SurfaceId); +pub struct WebGpuSurface(pub crate::Instance, pub wgpu_core::id::SurfaceId); impl Resource for WebGpuSurface { fn name(&self) -> Cow { "webGPUSurface".into() } + + fn close(self: Rc) { + self.0.surface_drop(self.1); + } } #[derive(Deserialize)] @@ -66,11 +71,11 @@ pub fn op_webgpu_surface_configure( let device_resource = state .resource_table .get::(args.device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let surface_resource = state .resource_table .get::(args.surface_rid)?; - let surface = surface_resource.0; + let surface = surface_resource.1; let conf = wgpu_types::SurfaceConfiguration::> { usage: wgpu_types::TextureUsages::from_bits_truncate(args.usage), @@ -97,16 +102,20 @@ pub fn op_webgpu_surface_get_current_texture( let device_resource = state .resource_table .get::(device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let surface_resource = state.resource_table.get::(surface_rid)?; - let surface = surface_resource.0; + let surface = surface_resource.1; let output = gfx_select!(device => instance.surface_get_current_texture(surface, ()))?; match output.status { SurfaceStatus::Good | SurfaceStatus::Suboptimal => { let id = output.texture_id.unwrap(); - let rid = state.resource_table.add(crate::texture::WebGpuTexture(id)); + let rid = state.resource_table.add(crate::texture::WebGpuTexture { + instance: instance.clone(), + id, + owned: false, + }); Ok(WebGpuResult::rid(rid)) } _ => Err(AnyError::msg("Invalid Surface Status")), @@ -123,9 +132,9 @@ pub fn op_webgpu_surface_present( let device_resource = state .resource_table .get::(device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let surface_resource = state.resource_table.get::(surface_rid)?; - let surface = surface_resource.0; + let surface = surface_resource.1; let _ = gfx_select!(device => instance.surface_present(surface))?; diff --git a/deno_webgpu/src/texture.rs b/deno_webgpu/src/texture.rs index 1578312cef..92c8457071 100644 --- a/deno_webgpu/src/texture.rs +++ b/deno_webgpu/src/texture.rs @@ -7,20 +7,41 @@ use deno_core::Resource; use deno_core::ResourceId; use serde::Deserialize; use std::borrow::Cow; +use std::rc::Rc; use super::error::WebGpuResult; -pub(crate) struct WebGpuTexture(pub(crate) wgpu_core::id::TextureId); +pub(crate) struct WebGpuTexture { + pub(crate) instance: crate::Instance, + pub(crate) id: wgpu_core::id::TextureId, + pub(crate) owned: bool, +} + impl Resource for WebGpuTexture { fn name(&self) -> Cow { "webGPUTexture".into() } + + fn close(self: Rc) { + if self.owned { + let instance = &self.instance; + gfx_select!(self.id => instance.texture_drop(self.id, true)); + } + } } -pub(crate) struct WebGpuTextureView(pub(crate) wgpu_core::id::TextureViewId); +pub(crate) struct WebGpuTextureView( + pub(crate) crate::Instance, + pub(crate) wgpu_core::id::TextureViewId, +); impl Resource for WebGpuTextureView { fn name(&self) -> Cow { "webGPUTextureView".into() } + + fn close(self: Rc) { + let instance = &self.0; + gfx_select!(self.1 => instance.texture_view_drop(self.1, true)).unwrap(); + } } #[derive(Deserialize)] @@ -46,7 +67,7 @@ pub fn op_webgpu_create_texture( let device_resource = state .resource_table .get::(args.device_rid)?; - let device = device_resource.0; + let device = device_resource.1; let descriptor = wgpu_core::resource::TextureDescriptor { label: args.label.map(Cow::from), @@ -59,11 +80,19 @@ pub fn op_webgpu_create_texture( view_formats: args.view_formats, }; - gfx_put!(device => instance.device_create_texture( - device, - &descriptor, - () - ) => state, WebGpuTexture) + let (val, maybe_err) = gfx_select!(device => instance.device_create_texture( + device, + &descriptor, + () + )); + + let rid = state.resource_table.add(WebGpuTexture { + instance: instance.clone(), + id: val, + owned: true, + }); + + Ok(WebGpuResult::rid_err(rid, maybe_err)) } #[derive(Deserialize)] @@ -86,7 +115,7 @@ pub fn op_webgpu_create_texture_view( let texture_resource = state .resource_table .get::(args.texture_rid)?; - let texture = texture_resource.0; + let texture = texture_resource.id; let descriptor = wgpu_core::resource::TextureViewDescriptor { label: args.label.map(Cow::from),