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    #[no_trace]
26    channel: WebGPU,
27    #[no_trace]
28    bind_group: WebGPUBindGroup,
29}
30
31impl Drop for DroppableGPUBindGroup {
32    fn drop(&mut self) {
33        if let Err(e) = self
34            .channel
35            .0
36            .send(WebGPURequest::DropBindGroup(self.bind_group.0))
37        {
38            warn!(
39                "Failed to send WebGPURequest::DropBindGroup({:?}) ({})",
40                self.bind_group.0, e
41            );
42        };
43    }
44}
45
46#[dom_struct]
47pub(crate) struct GPUBindGroup {
48    reflector_: Reflector,
49    label: DomRefCell<USVString>,
50    #[no_trace]
51    device: WebGPUDevice,
52    layout: Dom<GPUBindGroupLayout>,
53    droppable: DroppableGPUBindGroup,
54}
55
56impl GPUBindGroup {
57    fn new_inherited(
58        channel: WebGPU,
59        bind_group: WebGPUBindGroup,
60        device: WebGPUDevice,
61        layout: &GPUBindGroupLayout,
62        label: USVString,
63    ) -> Self {
64        Self {
65            reflector_: Reflector::new(),
66            label: DomRefCell::new(label),
67            device,
68            layout: Dom::from_ref(layout),
69            droppable: DroppableGPUBindGroup {
70                channel,
71                bind_group,
72            },
73        }
74    }
75
76    pub(crate) fn new(
77        global: &GlobalScope,
78        channel: WebGPU,
79        bind_group: WebGPUBindGroup,
80        device: WebGPUDevice,
81        layout: &GPUBindGroupLayout,
82        label: USVString,
83        can_gc: CanGc,
84    ) -> DomRoot<Self> {
85        reflect_dom_object(
86            Box::new(GPUBindGroup::new_inherited(
87                channel, bind_group, device, layout, label,
88            )),
89            global,
90            can_gc,
91        )
92    }
93}
94
95impl GPUBindGroup {
96    pub(crate) fn id(&self) -> &WebGPUBindGroup {
97        &self.droppable.bind_group
98    }
99
100    /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbindgroup>
101    pub(crate) fn create(
102        device: &GPUDevice,
103        descriptor: &GPUBindGroupDescriptor,
104        can_gc: CanGc,
105    ) -> DomRoot<GPUBindGroup> {
106        let entries = descriptor
107            .entries
108            .iter()
109            .map(|bind| bind.convert())
110            .collect::<Vec<_>>();
111
112        let desc = BindGroupDescriptor {
113            label: (&descriptor.parent).convert(),
114            layout: descriptor.layout.id().0,
115            entries: Cow::Owned(entries),
116        };
117
118        let bind_group_id = device.global().wgpu_id_hub().create_bind_group_id();
119        device
120            .channel()
121            .0
122            .send(WebGPURequest::CreateBindGroup {
123                device_id: device.id().0,
124                bind_group_id,
125                descriptor: desc,
126            })
127            .expect("Failed to create WebGPU BindGroup");
128
129        let bind_group = WebGPUBindGroup(bind_group_id);
130
131        GPUBindGroup::new(
132            &device.global(),
133            device.channel().clone(),
134            bind_group,
135            device.id(),
136            &descriptor.layout,
137            descriptor.parent.label.clone(),
138            can_gc,
139        )
140    }
141}
142
143impl GPUBindGroupMethods<crate::DomTypeHolder> for GPUBindGroup {
144    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
145    fn Label(&self) -> USVString {
146        self.label.borrow().clone()
147    }
148
149    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
150    fn SetLabel(&self, value: USVString) {
151        *self.label.borrow_mut() = value;
152    }
153}