wgpu_core/
conv.rs

1use wgt::TextureFormatFeatures;
2
3use crate::resource::{self, TextureDescriptor};
4
5// Some core-only texture format helpers. The helper methods on `TextureFormat`
6// defined in wgpu-types may need to be modified along with the ones here.
7
8#[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_STENCIL_READ | wgt::TextureUses::DEPTH_STENCIL_WRITE,
126        usage.contains(wgt::TextureUsages::RENDER_ATTACHMENT) && !is_color,
127    );
128    u.set(
129        wgt::TextureUses::STORAGE_ATOMIC,
130        usage.contains(wgt::TextureUsages::STORAGE_ATOMIC),
131    );
132    u.set(
133        wgt::TextureUses::TRANSIENT,
134        usage.contains(wgt::TextureUsages::TRANSIENT),
135    );
136    u
137}
138
139pub fn map_texture_usage_for_texture(
140    desc: &TextureDescriptor,
141    format_features: &TextureFormatFeatures,
142) -> wgt::TextureUses {
143    // Enforce having COPY_DST/DEPTH_STENCIL_WRITE/COLOR_TARGET otherwise we
144    // wouldn't be able to initialize the texture.
145    map_texture_usage(desc.usage, desc.format.into(), format_features.flags)
146        | if desc.format.is_depth_stencil_format() {
147            wgt::TextureUses::DEPTH_STENCIL_WRITE
148        } else if desc.usage.contains(wgt::TextureUsages::COPY_DST) {
149            wgt::TextureUses::COPY_DST // (set already)
150        } else {
151            // Use COPY_DST only if we can't use COLOR_TARGET
152            if format_features
153                .allowed_usages
154                .contains(wgt::TextureUsages::RENDER_ATTACHMENT)
155                && desc.dimension == wgt::TextureDimension::D2
156            // Render targets dimension must be 2d
157            {
158                wgt::TextureUses::COLOR_TARGET
159            } else {
160                wgt::TextureUses::COPY_DST
161            }
162        }
163}
164
165pub fn map_texture_usage_from_hal(uses: wgt::TextureUses) -> wgt::TextureUsages {
166    let mut u = wgt::TextureUsages::empty();
167    u.set(
168        wgt::TextureUsages::COPY_SRC,
169        uses.contains(wgt::TextureUses::COPY_SRC),
170    );
171    u.set(
172        wgt::TextureUsages::COPY_DST,
173        uses.contains(wgt::TextureUses::COPY_DST),
174    );
175    u.set(
176        wgt::TextureUsages::TEXTURE_BINDING,
177        uses.contains(wgt::TextureUses::RESOURCE),
178    );
179    u.set(
180        wgt::TextureUsages::STORAGE_BINDING,
181        uses.intersects(
182            wgt::TextureUses::STORAGE_READ_ONLY
183                | wgt::TextureUses::STORAGE_WRITE_ONLY
184                | wgt::TextureUses::STORAGE_READ_WRITE,
185        ),
186    );
187    u.set(
188        wgt::TextureUsages::RENDER_ATTACHMENT,
189        uses.contains(wgt::TextureUses::COLOR_TARGET),
190    );
191    u.set(
192        wgt::TextureUsages::STORAGE_ATOMIC,
193        uses.contains(wgt::TextureUses::STORAGE_ATOMIC),
194    );
195    u.set(
196        wgt::TextureUsages::TRANSIENT,
197        uses.contains(wgt::TextureUses::TRANSIENT),
198    );
199    u
200}
201
202pub fn check_texture_dimension_size(
203    dimension: wgt::TextureDimension,
204    wgt::Extent3d {
205        width,
206        height,
207        depth_or_array_layers,
208    }: wgt::Extent3d,
209    sample_size: u32,
210    limits: &wgt::Limits,
211) -> Result<(), resource::TextureDimensionError> {
212    use resource::{TextureDimensionError as Tde, TextureErrorDimension as Ted};
213    use wgt::TextureDimension::*;
214
215    let (extent_limits, sample_limit) = match dimension {
216        D1 => ([limits.max_texture_dimension_1d, 1, 1], 1),
217        D2 => (
218            [
219                limits.max_texture_dimension_2d,
220                limits.max_texture_dimension_2d,
221                limits.max_texture_array_layers,
222            ],
223            32,
224        ),
225        D3 => (
226            [
227                limits.max_texture_dimension_3d,
228                limits.max_texture_dimension_3d,
229                limits.max_texture_dimension_3d,
230            ],
231            1,
232        ),
233    };
234
235    for (&dim, (&given, &limit)) in [Ted::X, Ted::Y, Ted::Z].iter().zip(
236        [width, height, depth_or_array_layers]
237            .iter()
238            .zip(extent_limits.iter()),
239    ) {
240        if given == 0 {
241            return Err(Tde::Zero(dim));
242        }
243        if given > limit {
244            return Err(Tde::LimitExceeded { dim, given, limit });
245        }
246    }
247    if sample_size == 0 || sample_size > sample_limit || !sample_size.is_power_of_two() {
248        return Err(Tde::InvalidSampleCount(sample_size));
249    }
250
251    Ok(())
252}
253
254pub fn bind_group_layout_flags(features: wgt::Features) -> hal::BindGroupLayoutFlags {
255    let mut flags = hal::BindGroupLayoutFlags::empty();
256    flags.set(
257        hal::BindGroupLayoutFlags::PARTIALLY_BOUND,
258        features.contains(wgt::Features::PARTIALLY_BOUND_BINDING_ARRAY),
259    );
260    flags
261}