Skip to main content

script/dom/webgpu/
gpubindgroup.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use 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    /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbindgroup>
104    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    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
148    fn Label(&self) -> USVString {
149        self.label.borrow().clone()
150    }
151
152    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
153    fn SetLabel(&self, value: USVString) {
154        *self.label.borrow_mut() = value;
155    }
156}