script/dom/webgpu/
gpurenderpipeline.rs1use dom_struct::dom_struct;
6use js::context::JSContext;
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, WebGPURenderPipeline, WebGPURenderPipelineResponse,
12 WebGPURequest,
13};
14use wgpu_core::pipeline::RenderPipelineDescriptor;
15
16use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPURenderPipelineMethods;
17use crate::dom::bindings::error::Fallible;
18use crate::dom::bindings::reflector::DomGlobal;
19use crate::dom::bindings::root::{Dom, DomRoot};
20use crate::dom::bindings::str::USVString;
21use crate::dom::globalscope::GlobalScope;
22use crate::dom::webgpu::gpubindgrouplayout::GPUBindGroupLayout;
23use crate::dom::webgpu::gpudevice::GPUDevice;
24
25#[derive(JSTraceable, MallocSizeOf)]
26struct DroppableGPURenderPipeline {
27 #[no_trace]
28 channel: WebGPU,
29 #[no_trace]
30 render_pipeline: WebGPURenderPipeline,
31}
32
33impl Drop for DroppableGPURenderPipeline {
34 fn drop(&mut self) {
35 if let Err(e) = self
36 .channel
37 .0
38 .send(WebGPURequest::DropRenderPipeline(self.render_pipeline.0))
39 {
40 warn!(
41 "Failed to send WebGPURequest::DropRenderPipeline({:?}) ({})",
42 self.render_pipeline.0, e
43 );
44 };
45 }
46}
47
48#[dom_struct]
49pub(crate) struct GPURenderPipeline {
50 reflector_: Reflector,
51 label: DomRefCell<USVString>,
52 device: Dom<GPUDevice>,
53 droppable: DroppableGPURenderPipeline,
54}
55
56impl GPURenderPipeline {
57 fn new_inherited(
58 render_pipeline: WebGPURenderPipeline,
59 label: USVString,
60 device: &GPUDevice,
61 ) -> Self {
62 Self {
63 reflector_: Reflector::new(),
64 label: DomRefCell::new(label),
65 device: Dom::from_ref(device),
66 droppable: DroppableGPURenderPipeline {
67 channel: device.channel(),
68 render_pipeline,
69 },
70 }
71 }
72
73 pub(crate) fn new(
74 cx: &mut JSContext,
75 global: &GlobalScope,
76 render_pipeline: WebGPURenderPipeline,
77 label: USVString,
78 device: &GPUDevice,
79 ) -> DomRoot<Self> {
80 reflect_dom_object_with_cx(
81 Box::new(GPURenderPipeline::new_inherited(
82 render_pipeline,
83 label,
84 device,
85 )),
86 global,
87 cx,
88 )
89 }
90}
91
92impl GPURenderPipeline {
93 pub(crate) fn id(&self) -> WebGPURenderPipeline {
94 self.droppable.render_pipeline
95 }
96
97 pub(crate) fn create(
99 device: &GPUDevice,
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 async_sender,
113 })
114 .expect("Failed to create WebGPU render pipeline");
115
116 Ok(WebGPURenderPipeline(render_pipeline_id))
117 }
118}
119
120impl GPURenderPipelineMethods<crate::DomTypeHolder> for GPURenderPipeline {
121 fn Label(&self) -> USVString {
123 self.label.borrow().clone()
124 }
125
126 fn SetLabel(&self, value: USVString) {
128 *self.label.borrow_mut() = value;
129 }
130
131 fn GetBindGroupLayout(
133 &self,
134 cx: &mut JSContext,
135 index: u32,
136 ) -> Fallible<DomRoot<GPUBindGroupLayout>> {
137 let id = self.global().wgpu_id_hub().create_bind_group_layout_id();
138
139 if let Err(e) = self
140 .droppable
141 .channel
142 .0
143 .send(WebGPURequest::RenderGetBindGroupLayout {
144 device_id: self.device.id().0,
145 pipeline_id: self.id().0,
146 index,
147 id,
148 })
149 {
150 warn!("Failed to send WebGPURequest::RenderGetBindGroupLayout {e:?}");
151 }
152
153 Ok(GPUBindGroupLayout::new(
154 cx,
155 &self.global(),
156 self.droppable.channel.clone(),
157 WebGPUBindGroupLayout(id),
158 USVString::default(),
159 ))
160 }
161}