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