summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wgpu-hal/src/dx12/view.rs
blob: ae8e5814a8edee4ad324cfcf62c272280d3650f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
use crate::auxil;
use std::mem;
use winapi::um::d3d12 as d3d12_ty;

pub(crate) const D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING: u32 = 0x1688;

pub(super) struct ViewDescriptor {
    dimension: wgt::TextureViewDimension,
    pub aspects: crate::FormatAspects,
    pub rtv_dsv_format: d3d12::Format,
    srv_uav_format: Option<d3d12::Format>,
    multisampled: bool,
    array_layer_base: u32,
    array_layer_count: u32,
    mip_level_base: u32,
    mip_level_count: u32,
}

impl crate::TextureViewDescriptor<'_> {
    pub(super) fn to_internal(&self, texture: &super::Texture) -> ViewDescriptor {
        let aspects = crate::FormatAspects::new(texture.format, self.range.aspect);

        ViewDescriptor {
            dimension: self.dimension,
            aspects,
            rtv_dsv_format: auxil::dxgi::conv::map_texture_format(self.format),
            srv_uav_format: auxil::dxgi::conv::map_texture_format_for_srv_uav(self.format, aspects),
            multisampled: texture.sample_count > 1,
            mip_level_base: self.range.base_mip_level,
            mip_level_count: self.range.mip_level_count.unwrap_or(!0),
            array_layer_base: self.range.base_array_layer,
            array_layer_count: self.range.array_layer_count.unwrap_or(!0),
        }
    }
}

fn aspects_to_plane(aspects: crate::FormatAspects) -> u32 {
    match aspects {
        crate::FormatAspects::STENCIL => 1,
        crate::FormatAspects::PLANE_1 => 1,
        crate::FormatAspects::PLANE_2 => 2,
        _ => 0,
    }
}

impl ViewDescriptor {
    pub(crate) unsafe fn to_srv(&self) -> Option<d3d12_ty::D3D12_SHADER_RESOURCE_VIEW_DESC> {
        let mut desc = d3d12_ty::D3D12_SHADER_RESOURCE_VIEW_DESC {
            Format: self.srv_uav_format?,
            ViewDimension: 0,
            Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
            u: unsafe { mem::zeroed() },
        };

        match self.dimension {
            wgt::TextureViewDimension::D1 => {
                desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE1D;
                unsafe {
                    *desc.u.Texture1D_mut() = d3d12_ty::D3D12_TEX1D_SRV {
                        MostDetailedMip: self.mip_level_base,
                        MipLevels: self.mip_level_count,
                        ResourceMinLODClamp: 0.0,
                    }
                }
            }
            /*
            wgt::TextureViewDimension::D1Array => {
                desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE1DARRAY;
                *desc.u.Texture1DArray_mut() = d3d12_ty::D3D12_TEX1D_ARRAY_SRV {
                    MostDetailedMip: self.mip_level_base,
                    MipLevels: self.mip_level_count,
                    FirstArraySlice: self.array_layer_base,
                    ArraySize: self.array_layer_count,
                    ResourceMinLODClamp: 0.0,
                }
            }*/
            wgt::TextureViewDimension::D2 if self.multisampled && self.array_layer_base == 0 => {
                desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE2DMS;
                unsafe {
                    *desc.u.Texture2DMS_mut() = d3d12_ty::D3D12_TEX2DMS_SRV {
                        UnusedField_NothingToDefine: 0,
                    }
                }
            }
            wgt::TextureViewDimension::D2 if self.array_layer_base == 0 => {
                desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE2D;
                unsafe {
                    *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_SRV {
                        MostDetailedMip: self.mip_level_base,
                        MipLevels: self.mip_level_count,
                        PlaneSlice: aspects_to_plane(self.aspects),
                        ResourceMinLODClamp: 0.0,
                    }
                }
            }
            wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array
                if self.multisampled =>
            {
                desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;
                unsafe {
                    *desc.u.Texture2DMSArray_mut() = d3d12_ty::D3D12_TEX2DMS_ARRAY_SRV {
                        FirstArraySlice: self.array_layer_base,
                        ArraySize: self.array_layer_count,
                    }
                }
            }
            wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array => {
                desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
                unsafe {
                    *desc.u.Texture2DArray_mut() = d3d12_ty::D3D12_TEX2D_ARRAY_SRV {
                        MostDetailedMip: self.mip_level_base,
                        MipLevels: self.mip_level_count,
                        FirstArraySlice: self.array_layer_base,
                        ArraySize: self.array_layer_count,
                        PlaneSlice: aspects_to_plane(self.aspects),
                        ResourceMinLODClamp: 0.0,
                    }
                }
            }
            wgt::TextureViewDimension::D3 => {
                desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE3D;
                unsafe {
                    *desc.u.Texture3D_mut() = d3d12_ty::D3D12_TEX3D_SRV {
                        MostDetailedMip: self.mip_level_base,
                        MipLevels: self.mip_level_count,
                        ResourceMinLODClamp: 0.0,
                    }
                }
            }
            wgt::TextureViewDimension::Cube if self.array_layer_base == 0 => {
                desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURECUBE;
                unsafe {
                    *desc.u.TextureCube_mut() = d3d12_ty::D3D12_TEXCUBE_SRV {
                        MostDetailedMip: self.mip_level_base,
                        MipLevels: self.mip_level_count,
                        ResourceMinLODClamp: 0.0,
                    }
                }
            }
            wgt::TextureViewDimension::Cube | wgt::TextureViewDimension::CubeArray => {
                desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
                unsafe {
                    *desc.u.TextureCubeArray_mut() = d3d12_ty::D3D12_TEXCUBE_ARRAY_SRV {
                        MostDetailedMip: self.mip_level_base,
                        MipLevels: self.mip_level_count,
                        First2DArrayFace: self.array_layer_base,
                        NumCubes: if self.array_layer_count == !0 {
                            !0
                        } else {
                            self.array_layer_count / 6
                        },
                        ResourceMinLODClamp: 0.0,
                    }
                }
            }
        }

        Some(desc)
    }

    pub(crate) unsafe fn to_uav(&self) -> Option<d3d12_ty::D3D12_UNORDERED_ACCESS_VIEW_DESC> {
        let mut desc = d3d12_ty::D3D12_UNORDERED_ACCESS_VIEW_DESC {
            Format: self.srv_uav_format?,
            ViewDimension: 0,
            u: unsafe { mem::zeroed() },
        };

        match self.dimension {
            wgt::TextureViewDimension::D1 => {
                desc.ViewDimension = d3d12_ty::D3D12_UAV_DIMENSION_TEXTURE1D;
                unsafe {
                    *desc.u.Texture1D_mut() = d3d12_ty::D3D12_TEX1D_UAV {
                        MipSlice: self.mip_level_base,
                    }
                }
            }
            /*
            wgt::TextureViewDimension::D1Array => {
                desc.ViewDimension = d3d12_ty::D3D12_UAV_DIMENSION_TEXTURE1DARRAY;
                *desc.u.Texture1DArray_mut() = d3d12_ty::D3D12_TEX1D_ARRAY_UAV {
                    MipSlice: self.mip_level_base,
                    FirstArraySlice: self.array_layer_base,
                    ArraySize,
                }
            }*/
            wgt::TextureViewDimension::D2 if self.array_layer_base == 0 => {
                desc.ViewDimension = d3d12_ty::D3D12_UAV_DIMENSION_TEXTURE2D;
                unsafe {
                    *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_UAV {
                        MipSlice: self.mip_level_base,
                        PlaneSlice: aspects_to_plane(self.aspects),
                    }
                }
            }
            wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array => {
                desc.ViewDimension = d3d12_ty::D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
                unsafe {
                    *desc.u.Texture2DArray_mut() = d3d12_ty::D3D12_TEX2D_ARRAY_UAV {
                        MipSlice: self.mip_level_base,
                        FirstArraySlice: self.array_layer_base,
                        ArraySize: self.array_layer_count,
                        PlaneSlice: aspects_to_plane(self.aspects),
                    }
                }
            }
            wgt::TextureViewDimension::D3 => {
                desc.ViewDimension = d3d12_ty::D3D12_UAV_DIMENSION_TEXTURE3D;
                unsafe {
                    *desc.u.Texture3D_mut() = d3d12_ty::D3D12_TEX3D_UAV {
                        MipSlice: self.mip_level_base,
                        FirstWSlice: self.array_layer_base,
                        WSize: self.array_layer_count,
                    }
                }
            }
            wgt::TextureViewDimension::Cube | wgt::TextureViewDimension::CubeArray => {
                panic!("Unable to view texture as cube UAV")
            }
        }

        Some(desc)
    }

    pub(crate) unsafe fn to_rtv(&self) -> d3d12_ty::D3D12_RENDER_TARGET_VIEW_DESC {
        let mut desc = d3d12_ty::D3D12_RENDER_TARGET_VIEW_DESC {
            Format: self.rtv_dsv_format,
            ViewDimension: 0,
            u: unsafe { mem::zeroed() },
        };

        match self.dimension {
            wgt::TextureViewDimension::D1 => {
                desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE1D;
                unsafe {
                    *desc.u.Texture1D_mut() = d3d12_ty::D3D12_TEX1D_RTV {
                        MipSlice: self.mip_level_base,
                    }
                }
            }
            /*
            wgt::TextureViewDimension::D1Array => {
                desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE1DARRAY;
                *desc.u.Texture1DArray_mut() = d3d12_ty::D3D12_TEX1D_ARRAY_RTV {
                    MipSlice: self.mip_level_base,
                    FirstArraySlice: self.array_layer_base,
                    ArraySize,
                }
            }*/
            wgt::TextureViewDimension::D2 if self.multisampled && self.array_layer_base == 0 => {
                desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE2DMS;
                unsafe {
                    *desc.u.Texture2DMS_mut() = d3d12_ty::D3D12_TEX2DMS_RTV {
                        UnusedField_NothingToDefine: 0,
                    }
                }
            }
            wgt::TextureViewDimension::D2 if self.array_layer_base == 0 => {
                desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE2D;
                unsafe {
                    *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_RTV {
                        MipSlice: self.mip_level_base,
                        PlaneSlice: aspects_to_plane(self.aspects),
                    }
                }
            }
            wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array
                if self.multisampled =>
            {
                desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;
                unsafe {
                    *desc.u.Texture2DMSArray_mut() = d3d12_ty::D3D12_TEX2DMS_ARRAY_RTV {
                        FirstArraySlice: self.array_layer_base,
                        ArraySize: self.array_layer_count,
                    }
                }
            }
            wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array => {
                desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
                unsafe {
                    *desc.u.Texture2DArray_mut() = d3d12_ty::D3D12_TEX2D_ARRAY_RTV {
                        MipSlice: self.mip_level_base,
                        FirstArraySlice: self.array_layer_base,
                        ArraySize: self.array_layer_count,
                        PlaneSlice: aspects_to_plane(self.aspects),
                    }
                }
            }
            wgt::TextureViewDimension::D3 => {
                desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE3D;
                unsafe {
                    *desc.u.Texture3D_mut() = d3d12_ty::D3D12_TEX3D_RTV {
                        MipSlice: self.mip_level_base,
                        FirstWSlice: self.array_layer_base,
                        WSize: self.array_layer_count,
                    }
                }
            }
            wgt::TextureViewDimension::Cube | wgt::TextureViewDimension::CubeArray => {
                panic!("Unable to view texture as cube RTV")
            }
        }

        desc
    }

    pub(crate) unsafe fn to_dsv(&self, read_only: bool) -> d3d12_ty::D3D12_DEPTH_STENCIL_VIEW_DESC {
        let mut desc = d3d12_ty::D3D12_DEPTH_STENCIL_VIEW_DESC {
            Format: self.rtv_dsv_format,
            ViewDimension: 0,
            Flags: {
                let mut flags = d3d12_ty::D3D12_DSV_FLAG_NONE;
                if read_only {
                    if self.aspects.contains(crate::FormatAspects::DEPTH) {
                        flags |= d3d12_ty::D3D12_DSV_FLAG_READ_ONLY_DEPTH;
                    }
                    if self.aspects.contains(crate::FormatAspects::STENCIL) {
                        flags |= d3d12_ty::D3D12_DSV_FLAG_READ_ONLY_STENCIL;
                    }
                }
                flags
            },
            u: unsafe { mem::zeroed() },
        };

        match self.dimension {
            wgt::TextureViewDimension::D1 => {
                desc.ViewDimension = d3d12_ty::D3D12_DSV_DIMENSION_TEXTURE1D;
                unsafe {
                    *desc.u.Texture1D_mut() = d3d12_ty::D3D12_TEX1D_DSV {
                        MipSlice: self.mip_level_base,
                    }
                }
            }
            /*
            wgt::TextureViewDimension::D1Array => {
                desc.ViewDimension = d3d12_ty::D3D12_DSV_DIMENSION_TEXTURE1DARRAY;
                *desc.u.Texture1DArray_mut() = d3d12_ty::D3D12_TEX1D_ARRAY_DSV {
                    MipSlice: self.mip_level_base,
                    FirstArraySlice: self.array_layer_base,
                    ArraySize,
                }
            }*/
            wgt::TextureViewDimension::D2 if self.multisampled && self.array_layer_base == 0 => {
                desc.ViewDimension = d3d12_ty::D3D12_DSV_DIMENSION_TEXTURE2DMS;
                unsafe {
                    *desc.u.Texture2DMS_mut() = d3d12_ty::D3D12_TEX2DMS_DSV {
                        UnusedField_NothingToDefine: 0,
                    }
                }
            }
            wgt::TextureViewDimension::D2 if self.array_layer_base == 0 => {
                desc.ViewDimension = d3d12_ty::D3D12_DSV_DIMENSION_TEXTURE2D;
                unsafe {
                    *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_DSV {
                        MipSlice: self.mip_level_base,
                    }
                }
            }
            wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array
                if self.multisampled =>
            {
                desc.ViewDimension = d3d12_ty::D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY;
                unsafe {
                    *desc.u.Texture2DMSArray_mut() = d3d12_ty::D3D12_TEX2DMS_ARRAY_DSV {
                        FirstArraySlice: self.array_layer_base,
                        ArraySize: self.array_layer_count,
                    }
                }
            }
            wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array => {
                desc.ViewDimension = d3d12_ty::D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
                unsafe {
                    *desc.u.Texture2DArray_mut() = d3d12_ty::D3D12_TEX2D_ARRAY_DSV {
                        MipSlice: self.mip_level_base,
                        FirstArraySlice: self.array_layer_base,
                        ArraySize: self.array_layer_count,
                    }
                }
            }
            wgt::TextureViewDimension::D3
            | wgt::TextureViewDimension::Cube
            | wgt::TextureViewDimension::CubeArray => {
                panic!("Unable to view texture as cube or 3D RTV")
            }
        }

        desc
    }
}