script/dom/webgpu/
gpusampler.rs1use dom_struct::dom_struct;
6use js::context::{JSContext, NoGC};
7use script_bindings::cell::DomRefCell;
8use script_bindings::reflector::{Reflector, reflect_dom_object};
9use script_webgpu::gpuconvert::WebGPUConvert;
10use script_webgpu::traits::GPUSamplerTrait;
11use webgpu_traits::{WebGPU, WebGPUDevice, WebGPURequest, WebGPUSampler};
12use wgpu_core::resource::SamplerDescriptor;
13
14use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
15 GPUSamplerDescriptor, GPUSamplerMethods,
16};
17use crate::dom::bindings::reflector::DomGlobal;
18use crate::dom::bindings::root::DomRoot;
19use crate::dom::bindings::str::USVString;
20use crate::dom::globalscope::GlobalScope;
21use crate::dom::webgpu::gpudevice::GPUDevice;
22
23#[derive(JSTraceable, MallocSizeOf)]
24struct DroppableGPUSampler {
25 #[no_trace]
26 channel: WebGPU,
27 #[no_trace]
28 sampler: WebGPUSampler,
29}
30
31impl Drop for DroppableGPUSampler {
32 fn drop(&mut self) {
33 if let Err(e) = self
34 .channel
35 .0
36 .send(WebGPURequest::DropSampler(self.sampler.0))
37 {
38 warn!("Failed to send DropSampler ({:?}) ({})", self.sampler.0, e);
39 }
40 }
41}
42
43#[dom_struct]
44pub(crate) struct GPUSampler {
45 reflector_: Reflector,
46 label: DomRefCell<USVString>,
47 #[no_trace]
48 device: WebGPUDevice,
49 compare_enable: bool,
50 dropppable: DroppableGPUSampler,
51}
52
53impl GPUSampler {
54 fn new_inherited(
55 channel: WebGPU,
56 device: WebGPUDevice,
57 compare_enable: bool,
58 sampler: WebGPUSampler,
59 label: USVString,
60 ) -> Self {
61 Self {
62 reflector_: Reflector::new(),
63 label: DomRefCell::new(label),
64 device,
65 compare_enable,
66 dropppable: DroppableGPUSampler { channel, sampler },
67 }
68 }
69
70 pub(crate) fn new(
71 cx: &mut JSContext,
72 global: &GlobalScope,
73 channel: WebGPU,
74 device: WebGPUDevice,
75 compare_enable: bool,
76 sampler: WebGPUSampler,
77 label: USVString,
78 ) -> DomRoot<Self> {
79 reflect_dom_object(
80 cx,
81 Box::new(GPUSampler::new_inherited(
82 channel,
83 device,
84 compare_enable,
85 sampler,
86 label,
87 )),
88 global,
89 )
90 }
91}
92
93impl GPUSampler {
94 pub(crate) fn id(&self) -> WebGPUSampler {
95 self.dropppable.sampler
96 }
97
98 pub(crate) fn create(
100 cx: &mut JSContext,
101 device: &GPUDevice,
102 descriptor: &GPUSamplerDescriptor,
103 ) -> DomRoot<GPUSampler> {
104 let sampler_id = device.global().wgpu_id_hub().create_sampler_id();
105 let compare_enable = descriptor.compare.is_some();
106 let desc = SamplerDescriptor {
107 label: (&descriptor.parent).convert(),
108 address_modes: [
109 descriptor.addressModeU.convert(),
110 descriptor.addressModeV.convert(),
111 descriptor.addressModeW.convert(),
112 ],
113 mag_filter: descriptor.magFilter.convert(),
114 min_filter: descriptor.minFilter.convert(),
115 mipmap_filter: descriptor.mipmapFilter.convert(),
116 lod_min_clamp: *descriptor.lodMinClamp,
117 lod_max_clamp: *descriptor.lodMaxClamp,
118 compare: descriptor.compare.map(WebGPUConvert::convert),
119 anisotropy_clamp: 1,
120 border_color: None,
121 };
122
123 device
124 .channel()
125 .0
126 .send(WebGPURequest::CreateSampler {
127 device_id: device.id().0,
128 sampler_id,
129 descriptor: desc,
130 })
131 .expect("Failed to create WebGPU sampler");
132
133 let sampler = WebGPUSampler(sampler_id);
134
135 GPUSampler::new(
136 cx,
137 &device.global(),
138 device.channel(),
139 device.id(),
140 compare_enable,
141 sampler,
142 descriptor.parent.label.clone(),
143 )
144 }
145}
146
147impl GPUSamplerMethods<crate::DomTypeHolder> for GPUSampler {
148 fn Label(&self) -> USVString {
150 self.label.borrow().clone()
151 }
152
153 fn SetLabel(&self, no_gc: &NoGC, value: USVString) {
155 *self.label.safe_borrow_mut(no_gc) = value;
156 }
157}
158
159impl GPUSamplerTrait for GPUSampler {
160 fn id(&self) -> WebGPUSampler {
161 self.id()
162 }
163}