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 webgpu_traits::{WebGPU, WebGPUComputePass, WebGPURequest};
7
8use crate::dom::bindings::cell::DomRefCell;
9use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUComputePassEncoderMethods;
10use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
11use crate::dom::bindings::root::{Dom, DomRoot};
12use crate::dom::bindings::str::USVString;
13use crate::dom::globalscope::GlobalScope;
14use crate::dom::webgpu::gpubindgroup::GPUBindGroup;
15use crate::dom::webgpu::gpubuffer::GPUBuffer;
16use crate::dom::webgpu::gpucommandencoder::GPUCommandEncoder;
17use crate::dom::webgpu::gpucomputepipeline::GPUComputePipeline;
18use crate::script_runtime::CanGc;
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        global: &GlobalScope,
68        channel: WebGPU,
69        parent: &GPUCommandEncoder,
70        compute_pass: WebGPUComputePass,
71        label: USVString,
72        can_gc: CanGc,
73    ) -> DomRoot<Self> {
74        reflect_dom_object(
75            Box::new(GPUComputePassEncoder::new_inherited(
76                channel,
77                parent,
78                compute_pass,
79                label,
80            )),
81            global,
82            can_gc,
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, value: USVString) {
95        *self.label.borrow_mut() = 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                command_encoder_id: self.command_encoder.id().0,
143            })
144        {
145            warn!("Failed to send WebGPURequest::EndComputePass: {e:?}");
146        }
147    }
148
149    /// <https://gpuweb.github.io/gpuweb/#dom-gpuprogrammablepassencoder-setbindgroup>
150    fn SetBindGroup(&self, index: u32, bind_group: &GPUBindGroup, offsets: Vec<u32>) {
151        if let Err(e) = self
152            .droppable
153            .channel
154            .0
155            .send(WebGPURequest::ComputePassSetBindGroup {
156                compute_pass_id: self.droppable.compute_pass.0,
157                index,
158                bind_group_id: bind_group.id().0,
159                offsets,
160                device_id: self.command_encoder.device_id().0,
161            })
162        {
163            warn!("Error sending WebGPURequest::ComputePassSetBindGroup: {e:?}")
164        }
165    }
166
167    /// <https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-setpipeline>
168    fn SetPipeline(&self, pipeline: &GPUComputePipeline) {
169        if let Err(e) = self
170            .droppable
171            .channel
172            .0
173            .send(WebGPURequest::ComputePassSetPipeline {
174                compute_pass_id: self.droppable.compute_pass.0,
175                pipeline_id: pipeline.id().0,
176                device_id: self.command_encoder.device_id().0,
177            })
178        {
179            warn!("Error sending WebGPURequest::ComputePassSetPipeline: {e:?}")
180        }
181    }
182}