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