script/dom/webgpu/
gpucomputepipeline.rs1use dom_struct::dom_struct;
6use script_bindings::cell::DomRefCell;
7use script_bindings::reflector::{Reflector, reflect_dom_object};
8use servo_base::generic_channel::GenericCallback;
9use webgpu_traits::{
10 WebGPU, WebGPUBindGroupLayout, WebGPUComputePipeline, WebGPUComputePipelineResponse,
11 WebGPURequest,
12};
13use wgpu_core::pipeline::ComputePipelineDescriptor;
14
15use crate::conversions::Convert;
16use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
17 GPUComputePipelineDescriptor, GPUComputePipelineMethods,
18};
19use crate::dom::bindings::error::Fallible;
20use crate::dom::bindings::reflector::DomGlobal;
21use crate::dom::bindings::root::{Dom, DomRoot};
22use crate::dom::bindings::str::USVString;
23use crate::dom::globalscope::GlobalScope;
24use crate::dom::webgpu::gpubindgrouplayout::GPUBindGroupLayout;
25use crate::dom::webgpu::gpudevice::GPUDevice;
26use crate::script_runtime::CanGc;
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 global: &GlobalScope,
78 compute_pipeline: WebGPUComputePipeline,
79 label: USVString,
80 device: &GPUDevice,
81 can_gc: CanGc,
82 ) -> DomRoot<Self> {
83 reflect_dom_object(
84 Box::new(GPUComputePipeline::new_inherited(
85 compute_pipeline,
86 label,
87 device,
88 )),
89 global,
90 can_gc,
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, 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::deprecated_note(),
167 ))
168 }
169}