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, 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    /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createshadermodule>
81    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    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
122    fn Label(&self) -> USVString {
123        self.label.borrow().clone()
124    }
125
126    /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
127    fn SetLabel(&self, value: USVString) {
128        *self.label.borrow_mut() = value;
129    }
130
131    /// <https://gpuweb.github.io/gpuweb/#dom-gpushadermodule-getcompilationinfo>
132    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}