script/dom/webgpu/
gpurenderpipeline.rs1use dom_struct::dom_struct;
6use ipc_channel::ipc::IpcSender;
7use webgpu_traits::{
8 WebGPU, WebGPUBindGroupLayout, WebGPURenderPipeline, WebGPURenderPipelineResponse,
9 WebGPURequest,
10};
11use wgpu_core::pipeline::RenderPipelineDescriptor;
12
13use crate::dom::bindings::cell::DomRefCell;
14use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPURenderPipelineMethods;
15use crate::dom::bindings::error::Fallible;
16use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
17use crate::dom::bindings::root::{Dom, DomRoot};
18use crate::dom::bindings::str::USVString;
19use crate::dom::globalscope::GlobalScope;
20use crate::dom::webgpu::gpubindgrouplayout::GPUBindGroupLayout;
21use crate::dom::webgpu::gpudevice::{GPUDevice, PipelineLayout};
22use crate::script_runtime::CanGc;
23
24#[dom_struct]
25pub(crate) struct GPURenderPipeline {
26 reflector_: Reflector,
27 #[ignore_malloc_size_of = "channels are hard"]
28 #[no_trace]
29 channel: WebGPU,
30 label: DomRefCell<USVString>,
31 #[no_trace]
32 render_pipeline: WebGPURenderPipeline,
33 device: Dom<GPUDevice>,
34}
35
36impl GPURenderPipeline {
37 fn new_inherited(
38 render_pipeline: WebGPURenderPipeline,
39 label: USVString,
40 device: &GPUDevice,
41 ) -> Self {
42 Self {
43 reflector_: Reflector::new(),
44 channel: device.channel(),
45 label: DomRefCell::new(label),
46 render_pipeline,
47 device: Dom::from_ref(device),
48 }
49 }
50
51 pub(crate) fn new(
52 global: &GlobalScope,
53 render_pipeline: WebGPURenderPipeline,
54 label: USVString,
55 device: &GPUDevice,
56 can_gc: CanGc,
57 ) -> DomRoot<Self> {
58 reflect_dom_object(
59 Box::new(GPURenderPipeline::new_inherited(
60 render_pipeline,
61 label,
62 device,
63 )),
64 global,
65 can_gc,
66 )
67 }
68}
69
70impl GPURenderPipeline {
71 pub(crate) fn id(&self) -> WebGPURenderPipeline {
72 self.render_pipeline
73 }
74
75 pub(crate) fn create(
77 device: &GPUDevice,
78 pipeline_layout: PipelineLayout,
79 descriptor: RenderPipelineDescriptor<'static>,
80 async_sender: Option<IpcSender<WebGPURenderPipelineResponse>>,
81 ) -> Fallible<WebGPURenderPipeline> {
82 let render_pipeline_id = device.global().wgpu_id_hub().create_render_pipeline_id();
83
84 device
85 .channel()
86 .0
87 .send(WebGPURequest::CreateRenderPipeline {
88 device_id: device.id().0,
89 render_pipeline_id,
90 descriptor,
91 implicit_ids: pipeline_layout.implicit(),
92 async_sender,
93 })
94 .expect("Failed to create WebGPU render pipeline");
95
96 Ok(WebGPURenderPipeline(render_pipeline_id))
97 }
98}
99
100impl GPURenderPipelineMethods<crate::DomTypeHolder> for GPURenderPipeline {
101 fn Label(&self) -> USVString {
103 self.label.borrow().clone()
104 }
105
106 fn SetLabel(&self, value: USVString) {
108 *self.label.borrow_mut() = value;
109 }
110
111 fn GetBindGroupLayout(&self, index: u32) -> Fallible<DomRoot<GPUBindGroupLayout>> {
113 let id = self.global().wgpu_id_hub().create_bind_group_layout_id();
114
115 if let Err(e) = self
116 .channel
117 .0
118 .send(WebGPURequest::RenderGetBindGroupLayout {
119 device_id: self.device.id().0,
120 pipeline_id: self.render_pipeline.0,
121 index,
122 id,
123 })
124 {
125 warn!("Failed to send WebGPURequest::RenderGetBindGroupLayout {e:?}");
126 }
127
128 Ok(GPUBindGroupLayout::new(
129 &self.global(),
130 self.channel.clone(),
131 WebGPUBindGroupLayout(id),
132 USVString::default(),
133 CanGc::note(),
134 ))
135 }
136}
137
138impl Drop for GPURenderPipeline {
139 fn drop(&mut self) {
140 if let Err(e) = self
141 .channel
142 .0
143 .send(WebGPURequest::DropRenderPipeline(self.render_pipeline.0))
144 {
145 warn!(
146 "Failed to send WebGPURequest::DropRenderPipeline({:?}) ({})",
147 self.render_pipeline.0, e
148 );
149 };
150 }
151}