script/dom/webgpu/
gpurenderpipeline.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, WebGPURenderPipeline, WebGPURenderPipelineResponse,
11 WebGPURequest,
12};
13use wgpu_core::pipeline::RenderPipelineDescriptor;
14
15use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPURenderPipelineMethods;
16use crate::dom::bindings::error::Fallible;
17use crate::dom::bindings::reflector::DomGlobal;
18use crate::dom::bindings::root::{Dom, DomRoot};
19use crate::dom::bindings::str::USVString;
20use crate::dom::globalscope::GlobalScope;
21use crate::dom::webgpu::gpubindgrouplayout::GPUBindGroupLayout;
22use crate::dom::webgpu::gpudevice::GPUDevice;
23use crate::script_runtime::CanGc;
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 global: &GlobalScope,
75 render_pipeline: WebGPURenderPipeline,
76 label: USVString,
77 device: &GPUDevice,
78 can_gc: CanGc,
79 ) -> DomRoot<Self> {
80 reflect_dom_object(
81 Box::new(GPURenderPipeline::new_inherited(
82 render_pipeline,
83 label,
84 device,
85 )),
86 global,
87 can_gc,
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(&self, index: u32) -> Fallible<DomRoot<GPUBindGroupLayout>> {
133 let id = self.global().wgpu_id_hub().create_bind_group_layout_id();
134
135 if let Err(e) = self
136 .droppable
137 .channel
138 .0
139 .send(WebGPURequest::RenderGetBindGroupLayout {
140 device_id: self.device.id().0,
141 pipeline_id: self.id().0,
142 index,
143 id,
144 })
145 {
146 warn!("Failed to send WebGPURequest::RenderGetBindGroupLayout {e:?}");
147 }
148
149 Ok(GPUBindGroupLayout::new(
150 &self.global(),
151 self.droppable.channel.clone(),
152 WebGPUBindGroupLayout(id),
153 USVString::default(),
154 CanGc::deprecated_note(),
155 ))
156 }
157}