Skip to main content

script/dom/webgpu/
gpucomputepassencoder.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use dom_struct::dom_struct;
6use js::context::{JSContext, NoGC};
7use script_bindings::cell::DomRefCell;
8use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
9use webgpu_traits::{WebGPU, WebGPUComputePass, WebGPURequest};
10
11use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUComputePassEncoderMethods;
12use crate::dom::bindings::root::{Dom, DomRoot};
13use crate::dom::bindings::str::USVString;
14use crate::dom::globalscope::GlobalScope;
15use crate::dom::webgpu::gpubindgroup::GPUBindGroup;
16use crate::dom::webgpu::gpubuffer::GPUBuffer;
17use crate::dom::webgpu::gpucommandencoder::GPUCommandEncoder;
18use crate::dom::webgpu::gpucomputepipeline::GPUComputePipeline;
19
20#[derive(JSTraceable, MallocSizeOf)]
21struct DroppableGPUComputePassEncoder {
22    #[no_trace]
23    channel: WebGPU,
24    #[no_trace]
25    compute_pass: WebGPUComputePass,
26}
27
28impl Drop for DroppableGPUComputePassEncoder {
29    fn drop(&mut self) {
30        if let Err(e) = self
31            .channel
32            .0
33            .send(WebGPURequest::DropComputePass(self.compute_pass.0))
34        {
35            warn!("Failed to send WebGPURequest::DropComputePass with {e:?}");
36        }
37    }
38}
39
40#[dom_struct]
41pub(crate) struct GPUComputePassEncoder {
42    reflector_: Reflector,
43    label: DomRefCell<USVString>,
44    command_encoder: Dom<GPUCommandEncoder>,
45    droppable: DroppableGPUComputePassEncoder,
46}
47
48impl GPUComputePassEncoder {
49    fn new_inherited(
50        channel: WebGPU,
51        parent: &GPUCommandEncoder,
52        compute_pass: WebGPUComputePass,
53        label: USVString,
54    ) -> Self {
55        Self {
56            reflector_: Reflector::new(),
57            label: DomRefCell::new(label),
58            command_encoder: Dom::from_ref(parent),
59            droppable: DroppableGPUComputePassEncoder {
60                channel,
61                compute_pass,
62            },
63        }
64    }
65
66    pub(crate) fn new(
67        cx: &mut JSContext,
68        global: &GlobalScope,
69        channel: WebGPU,
70        parent: &GPUCommandEncoder,
71        compute_pass: WebGPUComputePass,
72        label: USVString,
73    ) -> DomRoot<Self> {
74        reflect_dom_object_with_cx(
75            Box::new(GPUComputePassEncoder::new_inherited(
76                channel,
77                parent,
78                compute_pass,
79                label,
80            )),
81            global,
82            cx,
83        )
84    }
85}
86
87impl GPUComputePassEncoderMethods<crate::DomTypeHolder> for GPUComputePassEncoder {
88    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
89    fn Label(&self) -> USVString {
90        self.label.borrow().clone()
91    }
92
93    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
94    fn SetLabel(&self, no_gc: &NoGC, value: USVString) {
95        *self.label.safe_borrow_mut(no_gc) = value;
96    }
97
98    /// <https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-dispatchworkgroups>
99    fn DispatchWorkgroups(&self, x: u32, y: u32, z: u32) {
100        if let Err(e) =
101            self.droppable
102                .channel
103                .0
104                .send(WebGPURequest::ComputePassDispatchWorkgroups {
105                    compute_pass_id: self.droppable.compute_pass.0,
106                    x,
107                    y,
108                    z,
109                    device_id: self.command_encoder.device_id().0,
110                })
111        {
112            warn!("Error sending WebGPURequest::ComputePassDispatchWorkgroups: {e:?}")
113        }
114    }
115
116    /// <https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-dispatchworkgroupsindirect>
117    fn DispatchWorkgroupsIndirect(&self, buffer: &GPUBuffer, offset: u64) {
118        if let Err(e) =
119            self.droppable
120                .channel
121                .0
122                .send(WebGPURequest::ComputePassDispatchWorkgroupsIndirect {
123                    compute_pass_id: self.droppable.compute_pass.0,
124                    buffer_id: buffer.id().0,
125                    offset,
126                    device_id: self.command_encoder.device_id().0,
127                })
128        {
129            warn!("Error sending WebGPURequest::ComputePassDispatchWorkgroupsIndirect: {e:?}")
130        }
131    }
132
133    /// <https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-endpass>
134    fn End(&self) {
135        if let Err(e) = self
136            .droppable
137            .channel
138            .0
139            .send(WebGPURequest::EndComputePass {
140                compute_pass_id: self.droppable.compute_pass.0,
141                device_id: self.command_encoder.device_id().0,
142            })
143        {
144            warn!("Failed to send WebGPURequest::EndComputePass: {e:?}");
145        }
146    }
147
148    /// <https://gpuweb.github.io/gpuweb/#dom-gpuprogrammablepassencoder-setbindgroup>
149    fn SetBindGroup(&self, index: u32, bind_group: &GPUBindGroup, offsets: Vec<u32>) {
150        if let Err(e) = self
151            .droppable
152            .channel
153            .0
154            .send(WebGPURequest::ComputePassSetBindGroup {
155                compute_pass_id: self.droppable.compute_pass.0,
156                index,
157                bind_group_id: bind_group.id().0,
158                offsets,
159                device_id: self.command_encoder.device_id().0,
160            })
161        {
162            warn!("Error sending WebGPURequest::ComputePassSetBindGroup: {e:?}")
163        }
164    }
165
166    /// <https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-setpipeline>
167    fn SetPipeline(&self, pipeline: &GPUComputePipeline) {
168        if let Err(e) = self
169            .droppable
170            .channel
171            .0
172            .send(WebGPURequest::ComputePassSetPipeline {
173                compute_pass_id: self.droppable.compute_pass.0,
174                pipeline_id: pipeline.id().0,
175                device_id: self.command_encoder.device_id().0,
176            })
177        {
178            warn!("Error sending WebGPURequest::ComputePassSetPipeline: {e:?}")
179        }
180    }
181
182    /// <https://gpuweb.github.io/gpuweb/#dom-gpudebugcommandsmixin-pushdebuggroup>
183    fn PushDebugGroup(&self, group_label: USVString) {
184        if let Err(e) = self
185            .droppable
186            .channel
187            .0
188            .send(WebGPURequest::ComputePassPushDebugGroup {
189                compute_pass_id: self.droppable.compute_pass.0,
190                label: group_label.to_string(),
191                device_id: self.command_encoder.device_id().0,
192            })
193        {
194            warn!("Error sending WebGPURequest::ComputePassPushDebugGroup: {e:?}")
195        }
196    }
197
198    /// <https://gpuweb.github.io/gpuweb/#dom-gpudebugcommandsmixin-popdebuggroup>
199    fn PopDebugGroup(&self) {
200        if let Err(e) = self
201            .droppable
202            .channel
203            .0
204            .send(WebGPURequest::ComputePassPopDebugGroup {
205                compute_pass_id: self.droppable.compute_pass.0,
206                device_id: self.command_encoder.device_id().0,
207            })
208        {
209            warn!("Error sending WebGPURequest::ComputePassPopDebugGroup: {e:?}")
210        }
211    }
212
213    /// <https://gpuweb.github.io/gpuweb/#dom-gpudebugcommandsmixin-insertdebugmarker>
214    fn InsertDebugMarker(&self, marker_label: USVString) {
215        if let Err(e) = self
216            .droppable
217            .channel
218            .0
219            .send(WebGPURequest::ComputePassInsertDebugMarker {
220                compute_pass_id: self.droppable.compute_pass.0,
221                label: marker_label.to_string(),
222                device_id: self.command_encoder.device_id().0,
223            })
224        {
225            warn!("Error sending WebGPURequest::ComputePassInsertDebugMarker: {e:?}")
226        }
227    }
228}