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