1use wgt::TextureFormatFeatures;
2
3use crate::resource::{self, TextureDescriptor};
4
5pub fn is_valid_copy_src_texture_format(
9 format: wgt::TextureFormat,
10 aspect: wgt::TextureAspect,
11) -> bool {
12 use wgt::TextureAspect as Ta;
13 use wgt::TextureFormat as Tf;
14 match (format, aspect) {
15 (Tf::Depth24Plus, _) | (Tf::Depth24PlusStencil8, Ta::DepthOnly) => false,
16 _ => true,
17 }
18}
19
20pub fn is_valid_copy_dst_texture_format(
21 format: wgt::TextureFormat,
22 aspect: wgt::TextureAspect,
23) -> bool {
24 use wgt::TextureAspect as Ta;
25 use wgt::TextureFormat as Tf;
26 match (format, aspect) {
27 (Tf::Depth24Plus | Tf::Depth32Float, _)
28 | (Tf::Depth24PlusStencil8 | Tf::Depth32FloatStencil8, Ta::DepthOnly) => false,
29 _ => true,
30 }
31}
32
33#[cfg_attr(any(not(webgl)), expect(unused))]
34pub fn is_valid_external_image_copy_dst_texture_format(format: wgt::TextureFormat) -> bool {
35 use wgt::TextureFormat as Tf;
36 match format {
37 Tf::R8Unorm
38 | Tf::R16Float
39 | Tf::R32Float
40 | Tf::Rg8Unorm
41 | Tf::Rg16Float
42 | Tf::Rg32Float
43 | Tf::Rgba8Unorm
44 | Tf::Rgba8UnormSrgb
45 | Tf::Bgra8Unorm
46 | Tf::Bgra8UnormSrgb
47 | Tf::Rgb10a2Unorm
48 | Tf::Rgba16Float
49 | Tf::Rgba32Float => true,
50 _ => false,
51 }
52}
53
54pub fn map_buffer_usage(usage: wgt::BufferUsages) -> wgt::BufferUses {
55 let mut u = wgt::BufferUses::empty();
56 u.set(
57 wgt::BufferUses::MAP_READ,
58 usage.contains(wgt::BufferUsages::MAP_READ),
59 );
60 u.set(
61 wgt::BufferUses::MAP_WRITE,
62 usage.contains(wgt::BufferUsages::MAP_WRITE),
63 );
64 u.set(
65 wgt::BufferUses::COPY_SRC,
66 usage.contains(wgt::BufferUsages::COPY_SRC),
67 );
68 u.set(
69 wgt::BufferUses::COPY_DST,
70 usage.contains(wgt::BufferUsages::COPY_DST),
71 );
72 u.set(
73 wgt::BufferUses::INDEX,
74 usage.contains(wgt::BufferUsages::INDEX),
75 );
76 u.set(
77 wgt::BufferUses::VERTEX,
78 usage.contains(wgt::BufferUsages::VERTEX),
79 );
80 u.set(
81 wgt::BufferUses::UNIFORM,
82 usage.contains(wgt::BufferUsages::UNIFORM),
83 );
84 u.set(
85 wgt::BufferUses::STORAGE_READ_ONLY | wgt::BufferUses::STORAGE_READ_WRITE,
86 usage.contains(wgt::BufferUsages::STORAGE),
87 );
88 u.set(
89 wgt::BufferUses::INDIRECT,
90 usage.contains(wgt::BufferUsages::INDIRECT),
91 );
92 u.set(
93 wgt::BufferUses::QUERY_RESOLVE,
94 usage.contains(wgt::BufferUsages::QUERY_RESOLVE),
95 );
96 u.set(
97 wgt::BufferUses::BOTTOM_LEVEL_ACCELERATION_STRUCTURE_INPUT,
98 usage.contains(wgt::BufferUsages::BLAS_INPUT),
99 );
100 u.set(
101 wgt::BufferUses::TOP_LEVEL_ACCELERATION_STRUCTURE_INPUT,
102 usage.contains(wgt::BufferUsages::TLAS_INPUT),
103 );
104 u
105}
106
107pub fn map_texture_usage(
108 usage: wgt::TextureUsages,
109 aspect: hal::FormatAspects,
110 flags: wgt::TextureFormatFeatureFlags,
111) -> wgt::TextureUses {
112 let mut u = wgt::TextureUses::empty();
113 u.set(
114 wgt::TextureUses::COPY_SRC,
115 usage.contains(wgt::TextureUsages::COPY_SRC),
116 );
117 u.set(
118 wgt::TextureUses::COPY_DST,
119 usage.contains(wgt::TextureUsages::COPY_DST),
120 );
121 u.set(
122 wgt::TextureUses::RESOURCE,
123 usage.contains(wgt::TextureUsages::TEXTURE_BINDING),
124 );
125 if usage.contains(wgt::TextureUsages::STORAGE_BINDING) {
126 u.set(
127 wgt::TextureUses::STORAGE_READ_ONLY,
128 flags.contains(wgt::TextureFormatFeatureFlags::STORAGE_READ_ONLY),
129 );
130 u.set(
131 wgt::TextureUses::STORAGE_WRITE_ONLY,
132 flags.contains(wgt::TextureFormatFeatureFlags::STORAGE_WRITE_ONLY),
133 );
134 u.set(
135 wgt::TextureUses::STORAGE_READ_WRITE,
136 flags.contains(wgt::TextureFormatFeatureFlags::STORAGE_READ_WRITE),
137 );
138 }
139 let is_color = aspect.contains(hal::FormatAspects::COLOR);
140 u.set(
141 wgt::TextureUses::COLOR_TARGET,
142 usage.contains(wgt::TextureUsages::RENDER_ATTACHMENT) && is_color,
143 );
144 u.set(
145 wgt::TextureUses::DEPTH_STENCIL_READ | wgt::TextureUses::DEPTH_STENCIL_WRITE,
146 usage.contains(wgt::TextureUsages::RENDER_ATTACHMENT) && !is_color,
147 );
148 u.set(
149 wgt::TextureUses::STORAGE_ATOMIC,
150 usage.contains(wgt::TextureUsages::STORAGE_ATOMIC),
151 );
152 u
153}
154
155pub fn map_texture_usage_for_texture(
156 desc: &TextureDescriptor,
157 format_features: &TextureFormatFeatures,
158) -> wgt::TextureUses {
159 map_texture_usage(desc.usage, desc.format.into(), format_features.flags)
162 | if desc.format.is_depth_stencil_format() {
163 wgt::TextureUses::DEPTH_STENCIL_WRITE
164 } else if desc.usage.contains(wgt::TextureUsages::COPY_DST) {
165 wgt::TextureUses::COPY_DST } else {
167 if format_features
169 .allowed_usages
170 .contains(wgt::TextureUsages::RENDER_ATTACHMENT)
171 && desc.dimension == wgt::TextureDimension::D2
172 {
174 wgt::TextureUses::COLOR_TARGET
175 } else {
176 wgt::TextureUses::COPY_DST
177 }
178 }
179}
180
181pub fn map_texture_usage_from_hal(uses: wgt::TextureUses) -> wgt::TextureUsages {
182 let mut u = wgt::TextureUsages::empty();
183 u.set(
184 wgt::TextureUsages::COPY_SRC,
185 uses.contains(wgt::TextureUses::COPY_SRC),
186 );
187 u.set(
188 wgt::TextureUsages::COPY_DST,
189 uses.contains(wgt::TextureUses::COPY_DST),
190 );
191 u.set(
192 wgt::TextureUsages::TEXTURE_BINDING,
193 uses.contains(wgt::TextureUses::RESOURCE),
194 );
195 u.set(
196 wgt::TextureUsages::STORAGE_BINDING,
197 uses.intersects(
198 wgt::TextureUses::STORAGE_READ_ONLY
199 | wgt::TextureUses::STORAGE_WRITE_ONLY
200 | wgt::TextureUses::STORAGE_READ_WRITE,
201 ),
202 );
203 u.set(
204 wgt::TextureUsages::RENDER_ATTACHMENT,
205 uses.contains(wgt::TextureUses::COLOR_TARGET),
206 );
207 u.set(
208 wgt::TextureUsages::STORAGE_ATOMIC,
209 uses.contains(wgt::TextureUses::STORAGE_ATOMIC),
210 );
211 u
212}
213
214pub fn check_texture_dimension_size(
215 dimension: wgt::TextureDimension,
216 wgt::Extent3d {
217 width,
218 height,
219 depth_or_array_layers,
220 }: wgt::Extent3d,
221 sample_size: u32,
222 limits: &wgt::Limits,
223) -> Result<(), resource::TextureDimensionError> {
224 use resource::{TextureDimensionError as Tde, TextureErrorDimension as Ted};
225 use wgt::TextureDimension::*;
226
227 let (extent_limits, sample_limit) = match dimension {
228 D1 => ([limits.max_texture_dimension_1d, 1, 1], 1),
229 D2 => (
230 [
231 limits.max_texture_dimension_2d,
232 limits.max_texture_dimension_2d,
233 limits.max_texture_array_layers,
234 ],
235 32,
236 ),
237 D3 => (
238 [
239 limits.max_texture_dimension_3d,
240 limits.max_texture_dimension_3d,
241 limits.max_texture_dimension_3d,
242 ],
243 1,
244 ),
245 };
246
247 for (&dim, (&given, &limit)) in [Ted::X, Ted::Y, Ted::Z].iter().zip(
248 [width, height, depth_or_array_layers]
249 .iter()
250 .zip(extent_limits.iter()),
251 ) {
252 if given == 0 {
253 return Err(Tde::Zero(dim));
254 }
255 if given > limit {
256 return Err(Tde::LimitExceeded { dim, given, limit });
257 }
258 }
259 if sample_size == 0 || sample_size > sample_limit || !sample_size.is_power_of_two() {
260 return Err(Tde::InvalidSampleCount(sample_size));
261 }
262
263 Ok(())
264}
265
266pub fn bind_group_layout_flags(features: wgt::Features) -> hal::BindGroupLayoutFlags {
267 let mut flags = hal::BindGroupLayoutFlags::empty();
268 flags.set(
269 hal::BindGroupLayoutFlags::PARTIALLY_BOUND,
270 features.contains(wgt::Features::PARTIALLY_BOUND_BINDING_ARRAY),
271 );
272 flags
273}