script/dom/webgpu/
gpurenderpipeline.rs1use base::generic_channel::GenericCallback;
6use dom_struct::dom_struct;
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 #[no_trace]
28 channel: WebGPU,
29 label: DomRefCell<USVString>,
30 #[no_trace]
31 render_pipeline: WebGPURenderPipeline,
32 device: Dom<GPUDevice>,
33}
34
35impl GPURenderPipeline {
36 fn new_inherited(
37 render_pipeline: WebGPURenderPipeline,
38 label: USVString,
39 device: &GPUDevice,
40 ) -> Self {
41 Self {
42 reflector_: Reflector::new(),
43 channel: device.channel(),
44 label: DomRefCell::new(label),
45 render_pipeline,
46 device: Dom::from_ref(device),
47 }
48 }
49
50 pub(crate) fn new(
51 global: &GlobalScope,
52 render_pipeline: WebGPURenderPipeline,
53 label: USVString,
54 device: &GPUDevice,
55 can_gc: CanGc,
56 ) -> DomRoot<Self> {
57 reflect_dom_object(
58 Box::new(GPURenderPipeline::new_inherited(
59 render_pipeline,
60 label,
61 device,
62 )),
63 global,
64 can_gc,
65 )
66 }
67}
68
69impl GPURenderPipeline {
70 pub(crate) fn id(&self) -> WebGPURenderPipeline {
71 self.render_pipeline
72 }
73
74 pub(crate) fn create(
76 device: &GPUDevice,
77 pipeline_layout: PipelineLayout,
78 descriptor: RenderPipelineDescriptor<'static>,
79 async_sender: Option<GenericCallback<WebGPURenderPipelineResponse>>,
80 ) -> Fallible<WebGPURenderPipeline> {
81 let render_pipeline_id = device.global().wgpu_id_hub().create_render_pipeline_id();
82
83 device
84 .channel()
85 .0
86 .send(WebGPURequest::CreateRenderPipeline {
87 device_id: device.id().0,
88 render_pipeline_id,
89 descriptor,
90 implicit_ids: pipeline_layout.implicit(),
91 async_sender,
92 })
93 .expect("Failed to create WebGPU render pipeline");
94
95 Ok(WebGPURenderPipeline(render_pipeline_id))
96 }
97}
98
99impl GPURenderPipelineMethods<crate::DomTypeHolder> for GPURenderPipeline {
100 fn Label(&self) -> USVString {
102 self.label.borrow().clone()
103 }
104
105 fn SetLabel(&self, value: USVString) {
107 *self.label.borrow_mut() = value;
108 }
109
110 fn GetBindGroupLayout(&self, index: u32) -> Fallible<DomRoot<GPUBindGroupLayout>> {
112 let id = self.global().wgpu_id_hub().create_bind_group_layout_id();
113
114 if let Err(e) = self
115 .channel
116 .0
117 .send(WebGPURequest::RenderGetBindGroupLayout {
118 device_id: self.device.id().0,
119 pipeline_id: self.render_pipeline.0,
120 index,
121 id,
122 })
123 {
124 warn!("Failed to send WebGPURequest::RenderGetBindGroupLayout {e:?}");
125 }
126
127 Ok(GPUBindGroupLayout::new(
128 &self.global(),
129 self.channel.clone(),
130 WebGPUBindGroupLayout(id),
131 USVString::default(),
132 CanGc::note(),
133 ))
134 }
135}
136
137impl Drop for GPURenderPipeline {
138 fn drop(&mut self) {
139 if let Err(e) = self
140 .channel
141 .0
142 .send(WebGPURequest::DropRenderPipeline(self.render_pipeline.0))
143 {
144 warn!(
145 "Failed to send WebGPURequest::DropRenderPipeline({:?}) ({})",
146 self.render_pipeline.0, e
147 );
148 };
149 }
150}