script_webgpu/
gpushadermodule.rs1use dom_struct::dom_struct;
6use js::context::{JSContext, NoGC};
7use js::realm::CurrentRealm;
8use log::warn;
9use malloc_size_of_derive::MallocSizeOf;
10use script_bindings::DomTypes;
11use script_bindings::cell::DomRefCell;
12use script_bindings::codegen::GenericBindings::WebGPUBinding::{
13 GPUShaderModuleDescriptor, GPUShaderModuleMethods, GPUShaderModuleWrap,
14};
15use script_bindings::interfaces::{
16 HeapTracedPromiseHelpers, PromiseHelpers, StackRootPromiseHelpers,
17};
18use script_bindings::reflector::{DomGlobalGeneric, Reflector, reflect_dom_object_with_wrap};
19use webgpu_traits::{WebGPU, WebGPURequest, WebGPUShaderModule};
20
21use crate::JSTraceable;
22use crate::dom::bindings::root::DomRoot;
23use crate::dom::bindings::str::USVString;
24use crate::dom::bindings::trace::RootedTraceableBox;
25use crate::traits::{Equivalence, GPUDeviceTrait, WebGPUGlobalTrait, WebGPUPromiseTrait};
26
27#[derive(JSTraceable, MallocSizeOf)]
28struct DroppableGPUShaderModule {
29 #[no_trace]
30 channel: WebGPU,
31 #[no_trace]
32 shader_module: WebGPUShaderModule,
33}
34
35impl Drop for DroppableGPUShaderModule {
36 fn drop(&mut self) {
37 if let Err(e) = self
38 .channel
39 .0
40 .send(WebGPURequest::DropShaderModule(self.shader_module.0))
41 {
42 warn!(
43 "Failed to send DropShaderModule ({:?}) ({})",
44 self.shader_module.0, e
45 );
46 }
47 }
48}
49
50#[dom_struct]
51pub struct GPUShaderModule<D: DomTypes> {
52 reflector_: Reflector,
53 label: DomRefCell<USVString>,
54 compilation_info_promise: <D::Promise as PromiseHelpers<D>>::HeapTraced,
55 droppable: DroppableGPUShaderModule,
56}
57
58impl<D: Equivalence> GPUShaderModule<D> {
59 fn new_inherited(
60 channel: WebGPU,
61 shader_module: WebGPUShaderModule,
62 label: USVString,
63 promise: &<D::Promise as PromiseHelpers<D>>::StackRoot,
64 ) -> Self {
65 Self {
66 reflector_: Reflector::new(),
67 label: DomRefCell::new(label),
68 compilation_info_promise: promise.to_traced(),
69 droppable: DroppableGPUShaderModule {
70 channel,
71 shader_module,
72 },
73 }
74 }
75
76 pub(crate) fn new(
77 cx: &mut JSContext,
78 global: &D::GlobalScope,
79 channel: WebGPU,
80 shader_module: WebGPUShaderModule,
81 label: USVString,
82 promise: &<D::Promise as PromiseHelpers<D>>::StackRoot,
83 ) -> DomRoot<Self> {
84 reflect_dom_object_with_wrap::<D, _, _>(
85 Box::new(GPUShaderModule::new_inherited(
86 channel,
87 shader_module,
88 label,
89 promise,
90 )),
91 global,
92 cx,
93 GPUShaderModuleWrap::<D>,
94 )
95 }
96}
97
98impl<D> GPUShaderModule<D>
99where
100 D: Equivalence,
101 D::Promise: PromiseHelpers<D>,
102 <D::Promise as PromiseHelpers<D>>::StackRoot: WebGPUPromiseTrait<D>,
103 D::GlobalScope: WebGPUGlobalTrait,
104 D::GPUDevice: GPUDeviceTrait<D>,
105{
106 pub(crate) fn id(&self) -> WebGPUShaderModule {
107 self.droppable.shader_module
108 }
109
110 pub fn create(
112 cx: &mut CurrentRealm<'_>,
113 device: &D::GPUDevice,
114 descriptor: RootedTraceableBox<GPUShaderModuleDescriptor>,
115 ) -> DomRoot<GPUShaderModule<D>> {
116 let program_id = device
117 .global_from_reflector()
118 .global_wgpu_id_hub()
119 .create_shader_module_id();
120 let promise = D::Promise::new_in_realm_rooted(cx);
121 let shader_module = GPUShaderModule::new(
122 cx,
123 &*device.global_from_reflector(),
124 device.channel(),
125 WebGPUShaderModule(program_id),
126 descriptor.parent.label.clone(),
127 &promise,
128 );
129 let callback = promise.callback_promise_gpushadermodule(&*shader_module);
130 device
131 .channel()
132 .0
133 .send(WebGPURequest::CreateShaderModule {
134 device_id: device.id().0,
135 program_id,
136 program: descriptor.code.0.clone(),
137 label: None,
138 callback,
139 })
140 .expect("Failed to create WebGPU ShaderModule");
141 shader_module
142 }
143}
144
145impl<D: DomTypes> GPUShaderModuleMethods<D> for GPUShaderModule<D> {
146 fn Label(&self) -> USVString {
148 self.label.borrow().clone()
149 }
150
151 fn SetLabel(&self, no_gc: &NoGC, value: USVString) {
153 *self.label.safe_borrow_mut(no_gc) = value;
154 }
155
156 fn GetCompilationInfo(&self) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
158 self.compilation_info_promise.root()
159 }
160}