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