li_wgpu_core/
conv.rs

1use crate::resource;
2
3pub fn is_power_of_two_u16(val: u16) -> bool {
4    val != 0 && (val & (val - 1)) == 0
5}
6
7pub fn is_power_of_two_u32(val: u32) -> bool {
8    val != 0 && (val & (val - 1)) == 0
9}
10
11pub fn is_valid_copy_src_texture_format(
12    format: wgt::TextureFormat,
13    aspect: wgt::TextureAspect,
14) -> bool {
15    use wgt::TextureAspect as Ta;
16    use wgt::TextureFormat as Tf;
17    match (format, aspect) {
18        (Tf::Depth24Plus, _) | (Tf::Depth24PlusStencil8, Ta::DepthOnly) => false,
19        _ => true,
20    }
21}
22
23pub fn is_valid_copy_dst_texture_format(
24    format: wgt::TextureFormat,
25    aspect: wgt::TextureAspect,
26) -> bool {
27    use wgt::TextureAspect as Ta;
28    use wgt::TextureFormat as Tf;
29    match (format, aspect) {
30        (Tf::Depth24Plus | Tf::Depth32Float, _)
31        | (Tf::Depth24PlusStencil8 | Tf::Depth32FloatStencil8, Ta::DepthOnly) => false,
32        _ => true,
33    }
34}
35
36#[cfg_attr(
37    any(not(target_arch = "wasm32"), target_os = "emscripten"),
38    allow(unused)
39)]
40pub fn is_valid_external_image_copy_dst_texture_format(format: wgt::TextureFormat) -> bool {
41    use wgt::TextureFormat as Tf;
42    match format {
43        Tf::R8Unorm
44        | Tf::R16Float
45        | Tf::R32Float
46        | Tf::Rg8Unorm
47        | Tf::Rg16Float
48        | Tf::Rg32Float
49        | Tf::Rgba8Unorm
50        | Tf::Rgba8UnormSrgb
51        | Tf::Bgra8Unorm
52        | Tf::Bgra8UnormSrgb
53        | Tf::Rgb10a2Unorm
54        | Tf::Rgba16Float
55        | Tf::Rgba32Float => true,
56        _ => false,
57    }
58}
59
60pub fn map_buffer_usage(usage: wgt::BufferUsages) -> hal::BufferUses {
61    let mut u = hal::BufferUses::empty();
62    u.set(
63        hal::BufferUses::MAP_READ,
64        usage.contains(wgt::BufferUsages::MAP_READ),
65    );
66    u.set(
67        hal::BufferUses::MAP_WRITE,
68        usage.contains(wgt::BufferUsages::MAP_WRITE),
69    );
70    u.set(
71        hal::BufferUses::COPY_SRC,
72        usage.contains(wgt::BufferUsages::COPY_SRC),
73    );
74    u.set(
75        hal::BufferUses::COPY_DST,
76        usage.contains(wgt::BufferUsages::COPY_DST),
77    );
78    u.set(
79        hal::BufferUses::INDEX,
80        usage.contains(wgt::BufferUsages::INDEX),
81    );
82    u.set(
83        hal::BufferUses::VERTEX,
84        usage.contains(wgt::BufferUsages::VERTEX),
85    );
86    u.set(
87        hal::BufferUses::UNIFORM,
88        usage.contains(wgt::BufferUsages::UNIFORM),
89    );
90    u.set(
91        hal::BufferUses::STORAGE_READ | hal::BufferUses::STORAGE_READ_WRITE,
92        usage.contains(wgt::BufferUsages::STORAGE),
93    );
94    u.set(
95        hal::BufferUses::INDIRECT,
96        usage.contains(wgt::BufferUsages::INDIRECT),
97    );
98    u.set(
99        hal::BufferUses::QUERY_RESOLVE,
100        usage.contains(wgt::BufferUsages::QUERY_RESOLVE),
101    );
102    u
103}
104
105pub fn map_texture_usage(
106    usage: wgt::TextureUsages,
107    aspect: hal::FormatAspects,
108) -> hal::TextureUses {
109    let mut u = hal::TextureUses::empty();
110    u.set(
111        hal::TextureUses::COPY_SRC,
112        usage.contains(wgt::TextureUsages::COPY_SRC),
113    );
114    u.set(
115        hal::TextureUses::COPY_DST,
116        usage.contains(wgt::TextureUsages::COPY_DST),
117    );
118    u.set(
119        hal::TextureUses::RESOURCE,
120        usage.contains(wgt::TextureUsages::TEXTURE_BINDING),
121    );
122    u.set(
123        hal::TextureUses::STORAGE_READ | hal::TextureUses::STORAGE_READ_WRITE,
124        usage.contains(wgt::TextureUsages::STORAGE_BINDING),
125    );
126    let is_color = aspect.contains(hal::FormatAspects::COLOR);
127    u.set(
128        hal::TextureUses::COLOR_TARGET,
129        usage.contains(wgt::TextureUsages::RENDER_ATTACHMENT) && is_color,
130    );
131    u.set(
132        hal::TextureUses::DEPTH_STENCIL_READ | hal::TextureUses::DEPTH_STENCIL_WRITE,
133        usage.contains(wgt::TextureUsages::RENDER_ATTACHMENT) && !is_color,
134    );
135    u
136}
137
138pub fn map_texture_usage_from_hal(uses: hal::TextureUses) -> wgt::TextureUsages {
139    let mut u = wgt::TextureUsages::empty();
140    u.set(
141        wgt::TextureUsages::COPY_SRC,
142        uses.contains(hal::TextureUses::COPY_SRC),
143    );
144    u.set(
145        wgt::TextureUsages::COPY_DST,
146        uses.contains(hal::TextureUses::COPY_DST),
147    );
148    u.set(
149        wgt::TextureUsages::TEXTURE_BINDING,
150        uses.contains(hal::TextureUses::RESOURCE),
151    );
152    u.set(
153        wgt::TextureUsages::STORAGE_BINDING,
154        uses.contains(hal::TextureUses::STORAGE_READ | hal::TextureUses::STORAGE_READ_WRITE),
155    );
156    u.set(
157        wgt::TextureUsages::RENDER_ATTACHMENT,
158        uses.contains(hal::TextureUses::COLOR_TARGET),
159    );
160    u
161}
162
163pub fn check_texture_dimension_size(
164    dimension: wgt::TextureDimension,
165    wgt::Extent3d {
166        width,
167        height,
168        depth_or_array_layers,
169    }: wgt::Extent3d,
170    sample_size: u32,
171    limits: &wgt::Limits,
172) -> Result<(), resource::TextureDimensionError> {
173    use resource::{TextureDimensionError as Tde, TextureErrorDimension as Ted};
174    use wgt::TextureDimension::*;
175
176    let (extent_limits, sample_limit) = match dimension {
177        D1 => ([limits.max_texture_dimension_1d, 1, 1], 1),
178        D2 => (
179            [
180                limits.max_texture_dimension_2d,
181                limits.max_texture_dimension_2d,
182                limits.max_texture_array_layers,
183            ],
184            32,
185        ),
186        D3 => (
187            [
188                limits.max_texture_dimension_3d,
189                limits.max_texture_dimension_3d,
190                limits.max_texture_dimension_3d,
191            ],
192            1,
193        ),
194    };
195
196    for (&dim, (&given, &limit)) in [Ted::X, Ted::Y, Ted::Z].iter().zip(
197        [width, height, depth_or_array_layers]
198            .iter()
199            .zip(extent_limits.iter()),
200    ) {
201        if given == 0 {
202            return Err(Tde::Zero(dim));
203        }
204        if given > limit {
205            return Err(Tde::LimitExceeded { dim, given, limit });
206        }
207    }
208    if sample_size == 0 || sample_size > sample_limit || !is_power_of_two_u32(sample_size) {
209        return Err(Tde::InvalidSampleCount(sample_size));
210    }
211
212    Ok(())
213}
214
215pub fn bind_group_layout_flags(features: wgt::Features) -> hal::BindGroupLayoutFlags {
216    let mut flags = hal::BindGroupLayoutFlags::empty();
217    flags.set(
218        hal::BindGroupLayoutFlags::PARTIALLY_BOUND,
219        features.contains(wgt::Features::PARTIALLY_BOUND_BINDING_ARRAY),
220    );
221    flags
222}