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 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    /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbindgroup>
102    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    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
146    fn Label(&self) -> USVString {
147        self.label.borrow().clone()
148    }
149
150    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
151    fn SetLabel(&self, value: USVString) {
152        *self.label.borrow_mut() = value;
153    }
154}