script/dom/webgpu/
gpubindgrouplayout.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, WebGPUBindGroupLayout, WebGPURequest};
9use wgpu_core::binding_model::BindGroupLayoutDescriptor;
10
11use crate::conversions::Convert;
12use crate::dom::bindings::cell::DomRefCell;
13use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
14    GPUBindGroupLayoutDescriptor, GPUBindGroupLayoutMethods,
15};
16use crate::dom::bindings::error::Fallible;
17use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
18use crate::dom::bindings::root::DomRoot;
19use crate::dom::bindings::str::USVString;
20use crate::dom::globalscope::GlobalScope;
21use crate::dom::webgpu::gpuconvert::convert_bind_group_layout_entry;
22use crate::dom::webgpu::gpudevice::GPUDevice;
23use crate::script_runtime::CanGc;
24
25#[derive(JSTraceable, MallocSizeOf)]
26struct DroppableGPUBindGroupLayout {
27    #[no_trace]
28    channel: WebGPU,
29    #[no_trace]
30    bind_group_layout: WebGPUBindGroupLayout,
31}
32
33impl Drop for DroppableGPUBindGroupLayout {
34    fn drop(&mut self) {
35        if let Err(e) = self
36            .channel
37            .0
38            .send(WebGPURequest::DropBindGroupLayout(self.bind_group_layout.0))
39        {
40            warn!(
41                "Failed to send WebGPURequest::DropBindGroupLayout({:?}) ({})",
42                self.bind_group_layout.0, e
43            );
44        };
45    }
46}
47
48#[dom_struct]
49pub(crate) struct GPUBindGroupLayout {
50    reflector_: Reflector,
51    label: DomRefCell<USVString>,
52    droppable: DroppableGPUBindGroupLayout,
53}
54
55impl GPUBindGroupLayout {
56    fn new_inherited(
57        channel: WebGPU,
58        bind_group_layout: WebGPUBindGroupLayout,
59        label: USVString,
60    ) -> Self {
61        Self {
62            reflector_: Reflector::new(),
63            label: DomRefCell::new(label),
64            droppable: DroppableGPUBindGroupLayout {
65                channel,
66                bind_group_layout,
67            },
68        }
69    }
70
71    pub(crate) fn new(
72        global: &GlobalScope,
73        channel: WebGPU,
74        bind_group_layout: WebGPUBindGroupLayout,
75        label: USVString,
76        can_gc: CanGc,
77    ) -> DomRoot<Self> {
78        reflect_dom_object(
79            Box::new(GPUBindGroupLayout::new_inherited(
80                channel,
81                bind_group_layout,
82                label,
83            )),
84            global,
85            can_gc,
86        )
87    }
88}
89
90impl GPUBindGroupLayout {
91    pub(crate) fn id(&self) -> WebGPUBindGroupLayout {
92        self.droppable.bind_group_layout
93    }
94
95    /// <https://gpuweb.github.io/gpuweb/#GPUDevice-createBindGroupLayout>
96    pub(crate) fn create(
97        device: &GPUDevice,
98        descriptor: &GPUBindGroupLayoutDescriptor,
99        can_gc: CanGc,
100    ) -> Fallible<DomRoot<GPUBindGroupLayout>> {
101        let entries = descriptor
102            .entries
103            .iter()
104            .map(|bgle| convert_bind_group_layout_entry(bgle, device))
105            .collect::<Fallible<Result<Vec<_>, _>>>()?;
106
107        let desc = match entries {
108            Ok(entries) => Some(BindGroupLayoutDescriptor {
109                label: (&descriptor.parent).convert(),
110                entries: Cow::Owned(entries),
111            }),
112            Err(error) => {
113                device.dispatch_error(error);
114                None
115            },
116        };
117
118        let bind_group_layout_id = device.global().wgpu_id_hub().create_bind_group_layout_id();
119        device
120            .channel()
121            .0
122            .send(WebGPURequest::CreateBindGroupLayout {
123                device_id: device.id().0,
124                bind_group_layout_id,
125                descriptor: desc,
126            })
127            .expect("Failed to create WebGPU BindGroupLayout");
128
129        let bgl = WebGPUBindGroupLayout(bind_group_layout_id);
130
131        Ok(GPUBindGroupLayout::new(
132            &device.global(),
133            device.channel().clone(),
134            bgl,
135            descriptor.parent.label.clone(),
136            can_gc,
137        ))
138    }
139}
140
141impl GPUBindGroupLayoutMethods<crate::DomTypeHolder> for GPUBindGroupLayout {
142    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
143    fn Label(&self) -> USVString {
144        self.label.borrow().clone()
145    }
146
147    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
148    fn SetLabel(&self, value: USVString) {
149        *self.label.borrow_mut() = value;
150    }
151}