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