script/dom/webgpu/
gpucomputepipeline.rs1use base::generic_channel::GenericCallback;
6use dom_struct::dom_struct;
7use webgpu_traits::{
8 WebGPU, WebGPUBindGroupLayout, WebGPUComputePipeline, WebGPUComputePipelineResponse,
9 WebGPURequest,
10};
11use wgpu_core::pipeline::ComputePipelineDescriptor;
12
13use crate::conversions::Convert;
14use crate::dom::bindings::cell::DomRefCell;
15use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
16 GPUComputePipelineDescriptor, GPUComputePipelineMethods,
17};
18use crate::dom::bindings::error::Fallible;
19use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
20use crate::dom::bindings::root::{Dom, DomRoot};
21use crate::dom::bindings::str::USVString;
22use crate::dom::globalscope::GlobalScope;
23use crate::dom::webgpu::gpubindgrouplayout::GPUBindGroupLayout;
24use crate::dom::webgpu::gpudevice::GPUDevice;
25use crate::script_runtime::CanGc;
26
27#[derive(JSTraceable, MallocSizeOf)]
28struct DroppableGPUComputePipeline {
29 #[no_trace]
30 channel: WebGPU,
31 #[no_trace]
32 compute_pipeline: WebGPUComputePipeline,
33}
34
35impl Drop for DroppableGPUComputePipeline {
36 fn drop(&mut self) {
37 if let Err(e) = self
38 .channel
39 .0
40 .send(WebGPURequest::DropComputePipeline(self.compute_pipeline.0))
41 {
42 warn!(
43 "Failed to send WebGPURequest::DropComputePipeline({:?}) ({})",
44 self.compute_pipeline.0, e
45 );
46 };
47 }
48}
49
50#[dom_struct]
51pub(crate) struct GPUComputePipeline {
52 reflector_: Reflector,
53 label: DomRefCell<USVString>,
54 device: Dom<GPUDevice>,
55 droppable: DroppableGPUComputePipeline,
56}
57
58impl GPUComputePipeline {
59 fn new_inherited(
60 compute_pipeline: WebGPUComputePipeline,
61 label: USVString,
62 device: &GPUDevice,
63 ) -> Self {
64 Self {
65 reflector_: Reflector::new(),
66 label: DomRefCell::new(label),
67 device: Dom::from_ref(device),
68 droppable: DroppableGPUComputePipeline {
69 channel: device.channel(),
70 compute_pipeline,
71 },
72 }
73 }
74
75 pub(crate) fn new(
76 global: &GlobalScope,
77 compute_pipeline: WebGPUComputePipeline,
78 label: USVString,
79 device: &GPUDevice,
80 can_gc: CanGc,
81 ) -> DomRoot<Self> {
82 reflect_dom_object(
83 Box::new(GPUComputePipeline::new_inherited(
84 compute_pipeline,
85 label,
86 device,
87 )),
88 global,
89 can_gc,
90 )
91 }
92}
93
94impl GPUComputePipeline {
95 pub(crate) fn id(&self) -> &WebGPUComputePipeline {
96 &self.droppable.compute_pipeline
97 }
98
99 pub(crate) fn create(
101 device: &GPUDevice,
102 descriptor: &GPUComputePipelineDescriptor,
103 async_sender: Option<GenericCallback<WebGPUComputePipelineResponse>>,
104 ) -> WebGPUComputePipeline {
105 let compute_pipeline_id = device.global().wgpu_id_hub().create_compute_pipeline_id();
106
107 let pipeline_layout = device.get_pipeline_layout_data(&descriptor.parent.layout);
108
109 let desc = ComputePipelineDescriptor {
110 label: (&descriptor.parent.parent).convert(),
111 layout: pipeline_layout.explicit(),
112 stage: (&descriptor.compute).convert(),
113 cache: None,
114 };
115
116 device
117 .channel()
118 .0
119 .send(WebGPURequest::CreateComputePipeline {
120 device_id: device.id().0,
121 compute_pipeline_id,
122 descriptor: desc,
123 implicit_ids: pipeline_layout.implicit(),
124 async_sender,
125 })
126 .expect("Failed to create WebGPU ComputePipeline");
127
128 WebGPUComputePipeline(compute_pipeline_id)
129 }
130}
131
132impl GPUComputePipelineMethods<crate::DomTypeHolder> for GPUComputePipeline {
133 fn Label(&self) -> USVString {
135 self.label.borrow().clone()
136 }
137
138 fn SetLabel(&self, value: USVString) {
140 *self.label.borrow_mut() = value;
141 }
142
143 fn GetBindGroupLayout(&self, index: u32) -> Fallible<DomRoot<GPUBindGroupLayout>> {
145 let id = self.global().wgpu_id_hub().create_bind_group_layout_id();
146
147 if let Err(e) = self
148 .droppable
149 .channel
150 .0
151 .send(WebGPURequest::ComputeGetBindGroupLayout {
152 device_id: self.device.id().0,
153 pipeline_id: self.id().0,
154 index,
155 id,
156 })
157 {
158 warn!("Failed to send WebGPURequest::ComputeGetBindGroupLayout {e:?}");
159 }
160
161 Ok(GPUBindGroupLayout::new(
162 &self.global(),
163 self.droppable.channel.clone(),
164 WebGPUBindGroupLayout(id),
165 USVString::default(),
166 CanGc::note(),
167 ))
168 }
169}