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