script/dom/webgpu/
gpushadermodule.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use 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    /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createshadermodule>
82    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    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
123    fn Label(&self) -> USVString {
124        self.label.borrow().clone()
125    }
126
127    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
128    fn SetLabel(&self, value: USVString) {
129        *self.label.borrow_mut() = value;
130    }
131
132    /// <https://gpuweb.github.io/gpuweb/#dom-gpushadermodule-getcompilationinfo>
133    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}