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