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