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