script/dom/webgpu/
gpubindgroup.rs1use std::borrow::Cow;
6
7use dom_struct::dom_struct;
8use webgpu_traits::{WebGPU, WebGPUBindGroup, WebGPUDevice, WebGPURequest};
9use wgpu_core::binding_model::BindGroupDescriptor;
10
11use crate::conversions::Convert;
12use crate::dom::bindings::cell::DomRefCell;
13use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
14 GPUBindGroupDescriptor, GPUBindGroupMethods,
15};
16use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
17use crate::dom::bindings::root::{Dom, DomRoot};
18use crate::dom::bindings::str::USVString;
19use crate::dom::globalscope::GlobalScope;
20use crate::dom::webgpu::gpubindgrouplayout::GPUBindGroupLayout;
21use crate::dom::webgpu::gpudevice::GPUDevice;
22use crate::script_runtime::CanGc;
23#[derive(JSTraceable, MallocSizeOf)]
24struct DroppableGPUBindGroup {
25 #[ignore_malloc_size_of = "channels are hard"]
26 #[no_trace]
27 channel: WebGPU,
28 #[no_trace]
29 bind_group: WebGPUBindGroup,
30}
31
32impl Drop for DroppableGPUBindGroup {
33 fn drop(&mut self) {
34 if let Err(e) = self
35 .channel
36 .0
37 .send(WebGPURequest::DropBindGroup(self.bind_group.0))
38 {
39 warn!(
40 "Failed to send WebGPURequest::DropBindGroup({:?}) ({})",
41 self.bind_group.0, e
42 );
43 };
44 }
45}
46
47#[dom_struct]
48pub(crate) struct GPUBindGroup {
49 reflector_: Reflector,
50 label: DomRefCell<USVString>,
51 #[no_trace]
52 device: WebGPUDevice,
53 layout: Dom<GPUBindGroupLayout>,
54 droppable: DroppableGPUBindGroup,
55}
56
57impl GPUBindGroup {
58 fn new_inherited(
59 channel: WebGPU,
60 bind_group: WebGPUBindGroup,
61 device: WebGPUDevice,
62 layout: &GPUBindGroupLayout,
63 label: USVString,
64 ) -> Self {
65 Self {
66 reflector_: Reflector::new(),
67 label: DomRefCell::new(label),
68 device,
69 layout: Dom::from_ref(layout),
70 droppable: DroppableGPUBindGroup {
71 channel,
72 bind_group,
73 },
74 }
75 }
76
77 pub(crate) fn new(
78 global: &GlobalScope,
79 channel: WebGPU,
80 bind_group: WebGPUBindGroup,
81 device: WebGPUDevice,
82 layout: &GPUBindGroupLayout,
83 label: USVString,
84 can_gc: CanGc,
85 ) -> DomRoot<Self> {
86 reflect_dom_object(
87 Box::new(GPUBindGroup::new_inherited(
88 channel, bind_group, device, layout, label,
89 )),
90 global,
91 can_gc,
92 )
93 }
94}
95
96impl GPUBindGroup {
97 pub(crate) fn id(&self) -> &WebGPUBindGroup {
98 &self.droppable.bind_group
99 }
100
101 pub(crate) fn create(
103 device: &GPUDevice,
104 descriptor: &GPUBindGroupDescriptor,
105 can_gc: CanGc,
106 ) -> DomRoot<GPUBindGroup> {
107 let entries = descriptor
108 .entries
109 .iter()
110 .map(|bind| bind.convert())
111 .collect::<Vec<_>>();
112
113 let desc = BindGroupDescriptor {
114 label: (&descriptor.parent).convert(),
115 layout: descriptor.layout.id().0,
116 entries: Cow::Owned(entries),
117 };
118
119 let bind_group_id = device.global().wgpu_id_hub().create_bind_group_id();
120 device
121 .channel()
122 .0
123 .send(WebGPURequest::CreateBindGroup {
124 device_id: device.id().0,
125 bind_group_id,
126 descriptor: desc,
127 })
128 .expect("Failed to create WebGPU BindGroup");
129
130 let bind_group = WebGPUBindGroup(bind_group_id);
131
132 GPUBindGroup::new(
133 &device.global(),
134 device.channel().clone(),
135 bind_group,
136 device.id(),
137 &descriptor.layout,
138 descriptor.parent.label.clone(),
139 can_gc,
140 )
141 }
142}
143
144impl GPUBindGroupMethods<crate::DomTypeHolder> for GPUBindGroup {
145 fn Label(&self) -> USVString {
147 self.label.borrow().clone()
148 }
149
150 fn SetLabel(&self, value: USVString) {
152 *self.label.borrow_mut() = value;
153 }
154}