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