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