script_webgpu/
gpuqueryset.rs1use std::marker::PhantomData;
5
6use dom_struct::dom_struct;
7use js::context::{JSContext, NoGC};
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 GPUDeviceMethods, GPUQuerySetDescriptor, GPUQuerySetMethods, GPUQuerySetWrap, GPUQueryType,
14};
15use script_bindings::error::{Error, Fallible};
16use script_bindings::interfaces::PromiseHelpers;
17use script_bindings::reflector::{DomGlobalGeneric, Reflector, reflect_dom_object_with_wrap};
18use script_bindings::root::DomRoot;
19use webgpu_traits::{Features, WebGPU, WebGPUQuerySet, WebGPURequest};
20
21use crate::JSTraceable;
22use crate::dom::bindings::str::USVString;
23use crate::gpuconvert::WebGPUConvert;
24use crate::traits::{Equivalence, WebGPUGlobalTrait, WebGPUPromise};
25
26#[derive(MallocSizeOf)]
27struct DroppableGPUQuerySet {
28 channel: WebGPU,
29 query_set: WebGPUQuerySet,
30}
31
32impl Drop for DroppableGPUQuerySet {
33 fn drop(&mut self) {
34 if let Err(error) = self
35 .channel
36 .0
37 .send(WebGPURequest::DropQuerySet(self.query_set.0))
38 {
39 warn!(
40 "Failed to send WebGPURequest::DropQuerySet({:?}) ({error})",
41 self.query_set.0
42 );
43 }
44 }
45}
46
47#[dom_struct]
48pub struct GPUQuerySet<D: DomTypes> {
49 reflector_: Reflector,
50 #[no_trace]
51 droppable: DroppableGPUQuerySet,
52 label: DomRefCell<USVString>,
53 r#type: GPUQueryType,
54 count: u32,
55 #[no_trace = "PhantomData does not exist"]
56 phantom: PhantomData<D>,
57}
58
59impl<D> GPUQuerySet<D>
60where
61 D: Equivalence,
62 <D::Promise as PromiseHelpers<D>>::StackRoot: WebGPUPromise<D>,
63{
64 pub(crate) fn new_inherited(
65 label: USVString,
66 channel: WebGPU,
67 query_set: WebGPUQuerySet,
68 r#type: GPUQueryType,
69 count: u32,
70 ) -> Self {
71 GPUQuerySet {
72 reflector_: Reflector::new(),
73 label: DomRefCell::new(label),
74 droppable: DroppableGPUQuerySet { channel, query_set },
75 r#type,
76 count,
77 phantom: PhantomData,
78 }
79 }
80
81 pub(crate) fn new(
82 cx: &mut JSContext,
83 global: &D::GlobalScope,
84 label: USVString,
85 channel: WebGPU,
86 query_set: WebGPUQuerySet,
87 r#type: GPUQueryType,
88 count: u32,
89 ) -> DomRoot<Self> {
90 reflect_dom_object_with_wrap::<D, _, _>(
91 cx,
92 Box::new(GPUQuerySet::new_inherited(
93 label, channel, query_set, r#type, count,
94 )),
95 global,
96 GPUQuerySetWrap::<D>,
97 )
98 }
99
100 pub(crate) fn create(
102 cx: &mut JSContext,
103 device: &D::GPUDevice,
104 descriptor: &GPUQuerySetDescriptor,
105 ) -> Fallible<DomRoot<Self>> {
106 if descriptor.type_ == GPUQueryType::Timestamp &&
108 !device
109 .Features()
110 .wgpu_features()
111 .contains(Features::TIMESTAMP_QUERY)
112 {
113 return Err(Error::Type(
115 c"The device does not support timestamp queries".to_owned(),
116 ));
117 }
118 let query_set_id = device
120 .global_from_reflector()
121 .global_wgpu_id_hub()
122 .create_query_set_id();
123 let channel = device.channel();
125 if let Err(error) = channel.0.send(WebGPURequest::CreateQuerySet {
126 device_id: device.id().0,
127 query_set_id,
128 descriptor: descriptor.convert(),
129 }) {
130 warn!("Failed to send WebGPURequest::CreateQuerySet: {error}");
131 }
132 Ok(Self::new(
134 cx,
135 &device.global_from_reflector(),
136 descriptor.parent.label.clone(),
137 channel,
138 WebGPUQuerySet(query_set_id),
139 descriptor.type_,
141 descriptor.count,
143 ))
144 }
145
146 pub(crate) fn id(&self) -> WebGPUQuerySet {
147 self.droppable.query_set
148 }
149}
150
151impl<D> GPUQuerySetMethods<D> for GPUQuerySet<D>
152where
153 D: Equivalence,
154 <D::Promise as PromiseHelpers<D>>::StackRoot: WebGPUPromise<D>,
155{
156 fn Destroy(&self) {
158 if let Err(error) = self
160 .droppable
161 .channel
162 .0
163 .send(WebGPURequest::DestroyQuerySet(self.id().0))
164 {
165 warn!(
166 "Failed to send WebGPURequest::DestroyQuerySet({:?}) ({error})",
167 self.id().0
168 );
169 }
170 }
171
172 fn Label(&self) -> USVString {
174 self.label.borrow().clone()
175 }
176
177 fn SetLabel(&self, no_gc: &NoGC, value: USVString) {
179 *self.label.safe_borrow_mut(no_gc) = value;
180 }
181
182 fn Type(&self) -> GPUQueryType {
184 self.r#type
185 }
186
187 fn Count(&self) -> u32 {
189 self.count
190 }
191}