script/dom/webgpu/
gpushadermodule.rs1use std::rc::Rc;
6
7use dom_struct::dom_struct;
8use webgpu_traits::{ShaderCompilationInfo, WebGPU, WebGPURequest, WebGPUShaderModule};
9
10use super::gpucompilationinfo::GPUCompilationInfo;
11use crate::dom::bindings::cell::DomRefCell;
12use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
13 GPUShaderModuleDescriptor, GPUShaderModuleMethods,
14};
15use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
16use crate::dom::bindings::root::DomRoot;
17use crate::dom::bindings::str::USVString;
18use crate::dom::bindings::trace::RootedTraceableBox;
19use crate::dom::globalscope::GlobalScope;
20use crate::dom::promise::Promise;
21use crate::dom::types::GPUDevice;
22use crate::realms::InRealm;
23use crate::routed_promise::{RoutedPromiseListener, route_promise};
24use crate::script_runtime::CanGc;
25
26#[dom_struct]
27pub(crate) struct GPUShaderModule {
28 reflector_: Reflector,
29 #[ignore_malloc_size_of = "defined in webgpu"]
30 #[no_trace]
31 channel: WebGPU,
32 label: DomRefCell<USVString>,
33 #[no_trace]
34 shader_module: WebGPUShaderModule,
35 #[ignore_malloc_size_of = "promise"]
36 compilation_info_promise: Rc<Promise>,
37}
38
39impl GPUShaderModule {
40 fn new_inherited(
41 channel: WebGPU,
42 shader_module: WebGPUShaderModule,
43 label: USVString,
44 promise: Rc<Promise>,
45 ) -> Self {
46 Self {
47 reflector_: Reflector::new(),
48 channel,
49 label: DomRefCell::new(label),
50 shader_module,
51 compilation_info_promise: promise,
52 }
53 }
54
55 pub(crate) fn new(
56 global: &GlobalScope,
57 channel: WebGPU,
58 shader_module: WebGPUShaderModule,
59 label: USVString,
60 promise: Rc<Promise>,
61 can_gc: CanGc,
62 ) -> DomRoot<Self> {
63 reflect_dom_object(
64 Box::new(GPUShaderModule::new_inherited(
65 channel,
66 shader_module,
67 label,
68 promise,
69 )),
70 global,
71 can_gc,
72 )
73 }
74}
75
76impl GPUShaderModule {
77 pub(crate) fn id(&self) -> WebGPUShaderModule {
78 self.shader_module
79 }
80
81 pub(crate) fn create(
83 device: &GPUDevice,
84 descriptor: RootedTraceableBox<GPUShaderModuleDescriptor>,
85 comp: InRealm,
86 can_gc: CanGc,
87 ) -> DomRoot<GPUShaderModule> {
88 let program_id = device.global().wgpu_id_hub().create_shader_module_id();
89 let promise = Promise::new_in_current_realm(comp, can_gc);
90 let shader_module = GPUShaderModule::new(
91 &device.global(),
92 device.channel().clone(),
93 WebGPUShaderModule(program_id),
94 descriptor.parent.label.clone(),
95 promise.clone(),
96 can_gc,
97 );
98 let sender = route_promise(
99 &promise,
100 &*shader_module,
101 device
102 .global()
103 .task_manager()
104 .dom_manipulation_task_source(),
105 );
106 device
107 .channel()
108 .0
109 .send(WebGPURequest::CreateShaderModule {
110 device_id: device.id().0,
111 program_id,
112 program: descriptor.code.0.clone(),
113 label: None,
114 sender,
115 })
116 .expect("Failed to create WebGPU ShaderModule");
117 shader_module
118 }
119}
120
121impl GPUShaderModuleMethods<crate::DomTypeHolder> for GPUShaderModule {
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 GetCompilationInfo(&self) -> Rc<Promise> {
134 self.compilation_info_promise.clone()
135 }
136}
137
138impl RoutedPromiseListener<Option<ShaderCompilationInfo>> for GPUShaderModule {
139 fn handle_response(
140 &self,
141 response: Option<ShaderCompilationInfo>,
142 promise: &Rc<Promise>,
143 can_gc: CanGc,
144 ) {
145 let info = GPUCompilationInfo::from(&self.global(), response, can_gc);
146 promise.resolve_native(&info, can_gc);
147 }
148}
149
150impl Drop for GPUShaderModule {
151 fn drop(&mut self) {
152 if let Err(e) = self
153 .channel
154 .0
155 .send(WebGPURequest::DropShaderModule(self.shader_module.0))
156 {
157 warn!(
158 "Failed to send DropShaderModule ({:?}) ({})",
159 self.shader_module.0, e
160 );
161 }
162 }
163}