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