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