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}