script_webgpu/
gpupipelinelayout.rs1use std::borrow::Cow;
6use std::marker::PhantomData;
7
8use dom_struct::dom_struct;
9use js::context::{JSContext, NoGC};
10use log::warn;
11use malloc_size_of_derive::MallocSizeOf;
12use script_bindings::DomTypes;
13use script_bindings::cell::DomRefCell;
14use script_bindings::codegen::GenericBindings::WebGPUBinding::{
15 GPUPipelineLayoutDescriptor, GPUPipelineLayoutMethods, GPUPipelineLayoutWrap,
16};
17use script_bindings::interfaces::PromiseHelpers;
18use script_bindings::reflector::{DomGlobalGeneric, Reflector, reflect_dom_object_with_wrap};
19use webgpu_traits::{
20 PipelineLayoutDescriptor, WebGPU, WebGPUBindGroupLayout, WebGPUPipelineLayout, WebGPURequest,
21};
22
23use crate::JSTraceable;
24use crate::dom::bindings::root::DomRoot;
25use crate::dom::bindings::str::USVString;
26use crate::gpuconvert::WebGPUConvert;
27use crate::traits::{Equivalence, WebGPUGlobalTrait, WebGPUPromise};
28
29#[derive(MallocSizeOf)]
30struct DroppableGPUPipelineLayout {
31 channel: WebGPU,
32 pipeline_layout: WebGPUPipelineLayout,
33}
34
35impl Drop for DroppableGPUPipelineLayout {
36 fn drop(&mut self) {
37 if let Err(e) = self
38 .channel
39 .0
40 .send(WebGPURequest::DropPipelineLayout(self.pipeline_layout.0))
41 {
42 warn!(
43 "Failed to send DropPipelineLayout ({:?}) ({})",
44 self.pipeline_layout.0, e
45 );
46 }
47 }
48}
49
50#[dom_struct]
51pub struct GPUPipelineLayout<D: DomTypes> {
52 reflector_: Reflector,
53 label: DomRefCell<USVString>,
54 #[no_trace]
55 bind_group_layouts: Vec<WebGPUBindGroupLayout>,
56 #[no_trace]
57 droppable: DroppableGPUPipelineLayout,
58 #[no_trace = "PhantomData does not exist"]
59 phantom: PhantomData<D>,
60}
61
62impl<D> GPUPipelineLayout<D>
63where
64 D: Equivalence,
65{
66 fn new_inherited(
67 channel: WebGPU,
68 pipeline_layout: WebGPUPipelineLayout,
69 label: USVString,
70 bgls: Vec<WebGPUBindGroupLayout>,
71 ) -> Self {
72 Self {
73 reflector_: Reflector::new(),
74 label: DomRefCell::new(label),
75 bind_group_layouts: bgls,
76 droppable: DroppableGPUPipelineLayout {
77 channel,
78 pipeline_layout,
79 },
80 phantom: PhantomData,
81 }
82 }
83
84 pub(crate) fn new(
85 cx: &mut JSContext,
86 global: &D::GlobalScope,
87 channel: WebGPU,
88 pipeline_layout: WebGPUPipelineLayout,
89 label: USVString,
90 bgls: Vec<WebGPUBindGroupLayout>,
91 ) -> DomRoot<Self> {
92 reflect_dom_object_with_wrap::<D, _, _>(
93 cx,
94 Box::new(GPUPipelineLayout::new_inherited(
95 channel,
96 pipeline_layout,
97 label,
98 bgls,
99 )),
100 global,
101 GPUPipelineLayoutWrap::<D>,
102 )
103 }
104}
105
106impl<D> GPUPipelineLayout<D>
107where
108 D: Equivalence,
109 <D::Promise as PromiseHelpers<D>>::StackRoot: WebGPUPromise<D>,
110{
111 pub(crate) fn id(&self) -> WebGPUPipelineLayout {
112 self.droppable.pipeline_layout
113 }
114
115 #[expect(unused)]
116 fn bind_group_layouts(&self) -> Vec<WebGPUBindGroupLayout> {
117 self.bind_group_layouts.clone()
118 }
119
120 pub(crate) fn create(
122 cx: &mut JSContext,
123 device: &D::GPUDevice,
124 descriptor: &GPUPipelineLayoutDescriptor<D>,
125 ) -> DomRoot<GPUPipelineLayout<D>> {
126 let bgls = descriptor
127 .bindGroupLayouts
128 .iter()
129 .map(|each| each.id())
130 .collect::<Vec<_>>();
131
132 let desc = PipelineLayoutDescriptor {
133 label: (&descriptor.parent).convert(),
134 bind_group_layouts: Cow::Owned(bgls.iter().map(|l| Some(l.0)).collect::<Vec<_>>()),
136 immediate_size: 0,
137 };
138
139 let pipeline_layout_id = device
140 .global_from_reflector()
141 .global_wgpu_id_hub()
142 .create_pipeline_layout_id();
143 device
144 .channel()
145 .0
146 .send(WebGPURequest::CreatePipelineLayout {
147 device_id: device.id().0,
148 pipeline_layout_id,
149 descriptor: desc,
150 })
151 .expect("Failed to create WebGPU PipelineLayout");
152
153 let pipeline_layout = WebGPUPipelineLayout(pipeline_layout_id);
154 GPUPipelineLayout::new(
155 cx,
156 &*device.global_from_reflector(),
157 device.channel(),
158 pipeline_layout,
159 descriptor.parent.label.clone(),
160 bgls,
161 )
162 }
163}
164
165impl<D: DomTypes> GPUPipelineLayoutMethods<D> for GPUPipelineLayout<D> {
166 fn Label(&self) -> USVString {
168 self.label.borrow().clone()
169 }
170
171 fn SetLabel(&self, no_gc: &NoGC, value: USVString) {
173 *self.label.safe_borrow_mut(no_gc) = value;
174 }
175}