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