1 use std::iter;
2 use winapi::{
3     shared::{dxgi1_2, dxgiformat},
4     um::{d3d12, d3dcommon},
5 };
6 
map_texture_format(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT7 pub(super) fn map_texture_format(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
8     use wgt::TextureFormat as Tf;
9     use winapi::shared::dxgiformat::*;
10 
11     match format {
12         Tf::R8Unorm => DXGI_FORMAT_R8_UNORM,
13         Tf::R8Snorm => DXGI_FORMAT_R8_SNORM,
14         Tf::R8Uint => DXGI_FORMAT_R8_UINT,
15         Tf::R8Sint => DXGI_FORMAT_R8_SINT,
16         Tf::R16Uint => DXGI_FORMAT_R16_UINT,
17         Tf::R16Sint => DXGI_FORMAT_R16_SINT,
18         Tf::R16Unorm => DXGI_FORMAT_R16_UNORM,
19         Tf::R16Snorm => DXGI_FORMAT_R16_SNORM,
20         Tf::R16Float => DXGI_FORMAT_R16_FLOAT,
21         Tf::Rg8Unorm => DXGI_FORMAT_R8G8_UNORM,
22         Tf::Rg8Snorm => DXGI_FORMAT_R8G8_SNORM,
23         Tf::Rg8Uint => DXGI_FORMAT_R8G8_UINT,
24         Tf::Rg8Sint => DXGI_FORMAT_R8G8_SINT,
25         Tf::Rg16Unorm => DXGI_FORMAT_R16G16_UNORM,
26         Tf::Rg16Snorm => DXGI_FORMAT_R16G16_SNORM,
27         Tf::R32Uint => DXGI_FORMAT_R32_UINT,
28         Tf::R32Sint => DXGI_FORMAT_R32_SINT,
29         Tf::R32Float => DXGI_FORMAT_R32_FLOAT,
30         Tf::Rg16Uint => DXGI_FORMAT_R16G16_UINT,
31         Tf::Rg16Sint => DXGI_FORMAT_R16G16_SINT,
32         Tf::Rg16Float => DXGI_FORMAT_R16G16_FLOAT,
33         Tf::Rgba8Unorm => DXGI_FORMAT_R8G8B8A8_UNORM,
34         Tf::Rgba8UnormSrgb => DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
35         Tf::Bgra8UnormSrgb => DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
36         Tf::Rgba8Snorm => DXGI_FORMAT_R8G8B8A8_SNORM,
37         Tf::Bgra8Unorm => DXGI_FORMAT_B8G8R8A8_UNORM,
38         Tf::Rgba8Uint => DXGI_FORMAT_R8G8B8A8_UINT,
39         Tf::Rgba8Sint => DXGI_FORMAT_R8G8B8A8_SINT,
40         Tf::Rgb10a2Unorm => DXGI_FORMAT_R10G10B10A2_UNORM,
41         Tf::Rg11b10Float => DXGI_FORMAT_R11G11B10_FLOAT,
42         Tf::Rg32Uint => DXGI_FORMAT_R32G32_UINT,
43         Tf::Rg32Sint => DXGI_FORMAT_R32G32_SINT,
44         Tf::Rg32Float => DXGI_FORMAT_R32G32_FLOAT,
45         Tf::Rgba16Uint => DXGI_FORMAT_R16G16B16A16_UINT,
46         Tf::Rgba16Sint => DXGI_FORMAT_R16G16B16A16_SINT,
47         Tf::Rgba16Unorm => DXGI_FORMAT_R16G16B16A16_UNORM,
48         Tf::Rgba16Snorm => DXGI_FORMAT_R16G16B16A16_SNORM,
49         Tf::Rgba16Float => DXGI_FORMAT_R16G16B16A16_FLOAT,
50         Tf::Rgba32Uint => DXGI_FORMAT_R32G32B32A32_UINT,
51         Tf::Rgba32Sint => DXGI_FORMAT_R32G32B32A32_SINT,
52         Tf::Rgba32Float => DXGI_FORMAT_R32G32B32A32_FLOAT,
53         Tf::Depth32Float => DXGI_FORMAT_D32_FLOAT,
54         Tf::Depth24Plus => DXGI_FORMAT_D24_UNORM_S8_UINT,
55         Tf::Depth24PlusStencil8 => DXGI_FORMAT_D24_UNORM_S8_UINT,
56         Tf::Rgb9e5Ufloat => DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
57         Tf::Bc1RgbaUnorm => DXGI_FORMAT_BC1_UNORM,
58         Tf::Bc1RgbaUnormSrgb => DXGI_FORMAT_BC1_UNORM_SRGB,
59         Tf::Bc2RgbaUnorm => DXGI_FORMAT_BC2_UNORM,
60         Tf::Bc2RgbaUnormSrgb => DXGI_FORMAT_BC2_UNORM_SRGB,
61         Tf::Bc3RgbaUnorm => DXGI_FORMAT_BC3_UNORM,
62         Tf::Bc3RgbaUnormSrgb => DXGI_FORMAT_BC3_UNORM_SRGB,
63         Tf::Bc4RUnorm => DXGI_FORMAT_BC4_UNORM,
64         Tf::Bc4RSnorm => DXGI_FORMAT_BC4_SNORM,
65         Tf::Bc5RgUnorm => DXGI_FORMAT_BC5_UNORM,
66         Tf::Bc5RgSnorm => DXGI_FORMAT_BC5_SNORM,
67         Tf::Bc6hRgbUfloat => DXGI_FORMAT_BC6H_UF16,
68         Tf::Bc6hRgbSfloat => DXGI_FORMAT_BC6H_SF16,
69         Tf::Bc7RgbaUnorm => DXGI_FORMAT_BC7_UNORM,
70         Tf::Bc7RgbaUnormSrgb => DXGI_FORMAT_BC7_UNORM_SRGB,
71         Tf::Etc2Rgb8Unorm
72         | Tf::Etc2Rgb8UnormSrgb
73         | Tf::Etc2Rgb8A1Unorm
74         | Tf::Etc2Rgb8A1UnormSrgb
75         | Tf::Etc2Rgba8Unorm
76         | Tf::Etc2Rgba8UnormSrgb
77         | Tf::EacR11Unorm
78         | Tf::EacR11Snorm
79         | Tf::EacRg11Unorm
80         | Tf::EacRg11Snorm
81         | Tf::Astc4x4RgbaUnorm
82         | Tf::Astc4x4RgbaUnormSrgb
83         | Tf::Astc5x4RgbaUnorm
84         | Tf::Astc5x4RgbaUnormSrgb
85         | Tf::Astc5x5RgbaUnorm
86         | Tf::Astc5x5RgbaUnormSrgb
87         | Tf::Astc6x5RgbaUnorm
88         | Tf::Astc6x5RgbaUnormSrgb
89         | Tf::Astc6x6RgbaUnorm
90         | Tf::Astc6x6RgbaUnormSrgb
91         | Tf::Astc8x5RgbaUnorm
92         | Tf::Astc8x5RgbaUnormSrgb
93         | Tf::Astc8x6RgbaUnorm
94         | Tf::Astc8x6RgbaUnormSrgb
95         | Tf::Astc10x5RgbaUnorm
96         | Tf::Astc10x5RgbaUnormSrgb
97         | Tf::Astc10x6RgbaUnorm
98         | Tf::Astc10x6RgbaUnormSrgb
99         | Tf::Astc8x8RgbaUnorm
100         | Tf::Astc8x8RgbaUnormSrgb
101         | Tf::Astc10x8RgbaUnorm
102         | Tf::Astc10x8RgbaUnormSrgb
103         | Tf::Astc10x10RgbaUnorm
104         | Tf::Astc10x10RgbaUnormSrgb
105         | Tf::Astc12x10RgbaUnorm
106         | Tf::Astc12x10RgbaUnormSrgb
107         | Tf::Astc12x12RgbaUnorm
108         | Tf::Astc12x12RgbaUnormSrgb => unreachable!(),
109     }
110 }
111 
112 //Note: DXGI doesn't allow sRGB format on the swapchain,
113 // but creating RTV of swapchain buffers with sRGB works.
map_texture_format_nosrgb(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT114 pub fn map_texture_format_nosrgb(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
115     match format {
116         wgt::TextureFormat::Bgra8UnormSrgb => dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM,
117         wgt::TextureFormat::Rgba8UnormSrgb => dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM,
118         _ => map_texture_format(format),
119     }
120 }
121 
122 //Note: SRV and UAV can't use the depth formats directly
123 //TODO: stencil views?
map_texture_format_nodepth(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT124 pub fn map_texture_format_nodepth(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
125     match format {
126         wgt::TextureFormat::Depth32Float => dxgiformat::DXGI_FORMAT_R32_FLOAT,
127         wgt::TextureFormat::Depth24Plus | wgt::TextureFormat::Depth24PlusStencil8 => {
128             dxgiformat::DXGI_FORMAT_R24_UNORM_X8_TYPELESS
129         }
130         _ => {
131             assert_eq!(
132                 crate::FormatAspects::from(format),
133                 crate::FormatAspects::COLOR
134             );
135             map_texture_format(format)
136         }
137     }
138 }
139 
map_texture_format_depth_typeless(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT140 pub fn map_texture_format_depth_typeless(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
141     match format {
142         wgt::TextureFormat::Depth32Float => dxgiformat::DXGI_FORMAT_R32_TYPELESS,
143         wgt::TextureFormat::Depth24Plus | wgt::TextureFormat::Depth24PlusStencil8 => {
144             dxgiformat::DXGI_FORMAT_R24G8_TYPELESS
145         }
146         _ => unreachable!(),
147     }
148 }
149 
map_index_format(format: wgt::IndexFormat) -> dxgiformat::DXGI_FORMAT150 pub fn map_index_format(format: wgt::IndexFormat) -> dxgiformat::DXGI_FORMAT {
151     match format {
152         wgt::IndexFormat::Uint16 => dxgiformat::DXGI_FORMAT_R16_UINT,
153         wgt::IndexFormat::Uint32 => dxgiformat::DXGI_FORMAT_R32_UINT,
154     }
155 }
156 
map_vertex_format(format: wgt::VertexFormat) -> dxgiformat::DXGI_FORMAT157 pub fn map_vertex_format(format: wgt::VertexFormat) -> dxgiformat::DXGI_FORMAT {
158     use wgt::VertexFormat as Vf;
159     use winapi::shared::dxgiformat::*;
160 
161     match format {
162         Vf::Unorm8x2 => DXGI_FORMAT_R8G8_UNORM,
163         Vf::Snorm8x2 => DXGI_FORMAT_R8G8_SNORM,
164         Vf::Uint8x2 => DXGI_FORMAT_R8G8_UINT,
165         Vf::Sint8x2 => DXGI_FORMAT_R8G8_SINT,
166         Vf::Unorm8x4 => DXGI_FORMAT_R8G8B8A8_UNORM,
167         Vf::Snorm8x4 => DXGI_FORMAT_R8G8B8A8_SNORM,
168         Vf::Uint8x4 => DXGI_FORMAT_R8G8B8A8_UINT,
169         Vf::Sint8x4 => DXGI_FORMAT_R8G8B8A8_SINT,
170         Vf::Unorm16x2 => DXGI_FORMAT_R16G16_UNORM,
171         Vf::Snorm16x2 => DXGI_FORMAT_R16G16_SNORM,
172         Vf::Uint16x2 => DXGI_FORMAT_R16G16_UINT,
173         Vf::Sint16x2 => DXGI_FORMAT_R16G16_SINT,
174         Vf::Float16x2 => DXGI_FORMAT_R16G16_FLOAT,
175         Vf::Unorm16x4 => DXGI_FORMAT_R16G16B16A16_UNORM,
176         Vf::Snorm16x4 => DXGI_FORMAT_R16G16B16A16_SNORM,
177         Vf::Uint16x4 => DXGI_FORMAT_R16G16B16A16_UINT,
178         Vf::Sint16x4 => DXGI_FORMAT_R16G16B16A16_SINT,
179         Vf::Float16x4 => DXGI_FORMAT_R16G16B16A16_FLOAT,
180         Vf::Uint32 => DXGI_FORMAT_R32_UINT,
181         Vf::Sint32 => DXGI_FORMAT_R32_SINT,
182         Vf::Float32 => DXGI_FORMAT_R32_FLOAT,
183         Vf::Uint32x2 => DXGI_FORMAT_R32G32_UINT,
184         Vf::Sint32x2 => DXGI_FORMAT_R32G32_SINT,
185         Vf::Float32x2 => DXGI_FORMAT_R32G32_FLOAT,
186         Vf::Uint32x3 => DXGI_FORMAT_R32G32B32_UINT,
187         Vf::Sint32x3 => DXGI_FORMAT_R32G32B32_SINT,
188         Vf::Float32x3 => DXGI_FORMAT_R32G32B32_FLOAT,
189         Vf::Uint32x4 => DXGI_FORMAT_R32G32B32A32_UINT,
190         Vf::Sint32x4 => DXGI_FORMAT_R32G32B32A32_SINT,
191         Vf::Float32x4 => DXGI_FORMAT_R32G32B32A32_FLOAT,
192         Vf::Float64 | Vf::Float64x2 | Vf::Float64x3 | Vf::Float64x4 => unimplemented!(),
193     }
194 }
195 
map_acomposite_alpha_mode(mode: crate::CompositeAlphaMode) -> dxgi1_2::DXGI_ALPHA_MODE196 pub fn map_acomposite_alpha_mode(mode: crate::CompositeAlphaMode) -> dxgi1_2::DXGI_ALPHA_MODE {
197     use crate::CompositeAlphaMode as Cam;
198     match mode {
199         Cam::Opaque => dxgi1_2::DXGI_ALPHA_MODE_IGNORE,
200         Cam::PreMultiplied => dxgi1_2::DXGI_ALPHA_MODE_PREMULTIPLIED,
201         Cam::PostMultiplied => dxgi1_2::DXGI_ALPHA_MODE_STRAIGHT,
202     }
203 }
204 
map_buffer_usage_to_resource_flags(usage: crate::BufferUses) -> d3d12::D3D12_RESOURCE_FLAGS205 pub fn map_buffer_usage_to_resource_flags(usage: crate::BufferUses) -> d3d12::D3D12_RESOURCE_FLAGS {
206     let mut flags = 0;
207     if usage.contains(crate::BufferUses::STORAGE_WRITE) {
208         flags |= d3d12::D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
209     }
210     flags
211 }
212 
map_texture_dimension(dim: wgt::TextureDimension) -> d3d12::D3D12_RESOURCE_DIMENSION213 pub fn map_texture_dimension(dim: wgt::TextureDimension) -> d3d12::D3D12_RESOURCE_DIMENSION {
214     match dim {
215         wgt::TextureDimension::D1 => d3d12::D3D12_RESOURCE_DIMENSION_TEXTURE1D,
216         wgt::TextureDimension::D2 => d3d12::D3D12_RESOURCE_DIMENSION_TEXTURE2D,
217         wgt::TextureDimension::D3 => d3d12::D3D12_RESOURCE_DIMENSION_TEXTURE3D,
218     }
219 }
220 
map_texture_usage_to_resource_flags( usage: crate::TextureUses, ) -> d3d12::D3D12_RESOURCE_FLAGS221 pub fn map_texture_usage_to_resource_flags(
222     usage: crate::TextureUses,
223 ) -> d3d12::D3D12_RESOURCE_FLAGS {
224     let mut flags = 0;
225 
226     if usage.contains(crate::TextureUses::COLOR_TARGET) {
227         flags |= d3d12::D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
228     }
229     if usage.intersects(
230         crate::TextureUses::DEPTH_STENCIL_READ | crate::TextureUses::DEPTH_STENCIL_WRITE,
231     ) {
232         flags |= d3d12::D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
233         if !usage.contains(crate::TextureUses::RESOURCE) {
234             flags |= d3d12::D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
235         }
236     }
237     if usage.contains(crate::TextureUses::STORAGE_WRITE) {
238         flags |= d3d12::D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
239     }
240 
241     flags
242 }
243 
map_address_mode(mode: wgt::AddressMode) -> d3d12::D3D12_TEXTURE_ADDRESS_MODE244 pub fn map_address_mode(mode: wgt::AddressMode) -> d3d12::D3D12_TEXTURE_ADDRESS_MODE {
245     use wgt::AddressMode as Am;
246     match mode {
247         Am::Repeat => d3d12::D3D12_TEXTURE_ADDRESS_MODE_WRAP,
248         Am::MirrorRepeat => d3d12::D3D12_TEXTURE_ADDRESS_MODE_MIRROR,
249         Am::ClampToEdge => d3d12::D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
250         Am::ClampToBorder => d3d12::D3D12_TEXTURE_ADDRESS_MODE_BORDER,
251         //Am::MirrorClamp => d3d12::D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE,
252     }
253 }
254 
map_filter_mode(mode: wgt::FilterMode) -> d3d12::D3D12_FILTER_TYPE255 pub fn map_filter_mode(mode: wgt::FilterMode) -> d3d12::D3D12_FILTER_TYPE {
256     match mode {
257         wgt::FilterMode::Nearest => d3d12::D3D12_FILTER_TYPE_POINT,
258         wgt::FilterMode::Linear => d3d12::D3D12_FILTER_TYPE_LINEAR,
259     }
260 }
261 
map_comparison(func: wgt::CompareFunction) -> d3d12::D3D12_COMPARISON_FUNC262 pub fn map_comparison(func: wgt::CompareFunction) -> d3d12::D3D12_COMPARISON_FUNC {
263     use wgt::CompareFunction as Cf;
264     match func {
265         Cf::Never => d3d12::D3D12_COMPARISON_FUNC_NEVER,
266         Cf::Less => d3d12::D3D12_COMPARISON_FUNC_LESS,
267         Cf::LessEqual => d3d12::D3D12_COMPARISON_FUNC_LESS_EQUAL,
268         Cf::Equal => d3d12::D3D12_COMPARISON_FUNC_EQUAL,
269         Cf::GreaterEqual => d3d12::D3D12_COMPARISON_FUNC_GREATER_EQUAL,
270         Cf::Greater => d3d12::D3D12_COMPARISON_FUNC_GREATER,
271         Cf::NotEqual => d3d12::D3D12_COMPARISON_FUNC_NOT_EQUAL,
272         Cf::Always => d3d12::D3D12_COMPARISON_FUNC_ALWAYS,
273     }
274 }
275 
map_border_color(border_color: Option<wgt::SamplerBorderColor>) -> [f32; 4]276 pub fn map_border_color(border_color: Option<wgt::SamplerBorderColor>) -> [f32; 4] {
277     use wgt::SamplerBorderColor as Sbc;
278     match border_color {
279         Some(Sbc::TransparentBlack) | None => [0.0; 4],
280         Some(Sbc::OpaqueBlack) => [0.0, 0.0, 0.0, 1.0],
281         Some(Sbc::OpaqueWhite) => [1.0; 4],
282     }
283 }
284 
map_visibility(visibility: wgt::ShaderStages) -> native::ShaderVisibility285 pub fn map_visibility(visibility: wgt::ShaderStages) -> native::ShaderVisibility {
286     match visibility {
287         wgt::ShaderStages::VERTEX => native::ShaderVisibility::VS,
288         wgt::ShaderStages::FRAGMENT => native::ShaderVisibility::PS,
289         _ => native::ShaderVisibility::All,
290     }
291 }
292 
map_binding_type(ty: &wgt::BindingType) -> native::DescriptorRangeType293 pub fn map_binding_type(ty: &wgt::BindingType) -> native::DescriptorRangeType {
294     use wgt::BindingType as Bt;
295     match *ty {
296         Bt::Sampler { .. } => native::DescriptorRangeType::Sampler,
297         Bt::Buffer {
298             ty: wgt::BufferBindingType::Uniform,
299             ..
300         } => native::DescriptorRangeType::CBV,
301         Bt::Buffer {
302             ty: wgt::BufferBindingType::Storage { read_only: true },
303             ..
304         }
305         | Bt::Texture { .. } => native::DescriptorRangeType::SRV,
306         Bt::Buffer {
307             ty: wgt::BufferBindingType::Storage { read_only: false },
308             ..
309         }
310         | Bt::StorageTexture { .. } => native::DescriptorRangeType::UAV,
311     }
312 }
313 
map_label(name: &str) -> Vec<u16>314 pub fn map_label(name: &str) -> Vec<u16> {
315     name.encode_utf16().chain(iter::once(0)).collect()
316 }
317 
map_buffer_usage_to_state(usage: crate::BufferUses) -> d3d12::D3D12_RESOURCE_STATES318 pub fn map_buffer_usage_to_state(usage: crate::BufferUses) -> d3d12::D3D12_RESOURCE_STATES {
319     use crate::BufferUses as Bu;
320     let mut state = d3d12::D3D12_RESOURCE_STATE_COMMON;
321 
322     if usage.intersects(Bu::COPY_SRC) {
323         state |= d3d12::D3D12_RESOURCE_STATE_COPY_SOURCE;
324     }
325     if usage.intersects(Bu::COPY_DST) {
326         state |= d3d12::D3D12_RESOURCE_STATE_COPY_DEST;
327     }
328     if usage.intersects(Bu::INDEX) {
329         state |= d3d12::D3D12_RESOURCE_STATE_INDEX_BUFFER;
330     }
331     if usage.intersects(Bu::VERTEX | Bu::UNIFORM) {
332         state |= d3d12::D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
333     }
334     if usage.intersects(Bu::STORAGE_WRITE) {
335         state |= d3d12::D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
336     } else if usage.intersects(Bu::STORAGE_READ) {
337         state |= d3d12::D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
338             | d3d12::D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
339     }
340     if usage.intersects(Bu::INDIRECT) {
341         state |= d3d12::D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT;
342     }
343     state
344 }
345 
map_texture_usage_to_state(usage: crate::TextureUses) -> d3d12::D3D12_RESOURCE_STATES346 pub fn map_texture_usage_to_state(usage: crate::TextureUses) -> d3d12::D3D12_RESOURCE_STATES {
347     use crate::TextureUses as Tu;
348     let mut state = d3d12::D3D12_RESOURCE_STATE_COMMON;
349     //Note: `RESOLVE_SOURCE` and `RESOLVE_DEST` are not used here
350     //Note: `PRESENT` is the same as `COMMON`
351     if usage == crate::TextureUses::UNINITIALIZED {
352         return state;
353     }
354 
355     if usage.intersects(Tu::COPY_SRC) {
356         state |= d3d12::D3D12_RESOURCE_STATE_COPY_SOURCE;
357     }
358     if usage.intersects(Tu::COPY_DST) {
359         state |= d3d12::D3D12_RESOURCE_STATE_COPY_DEST;
360     }
361     if usage.intersects(Tu::RESOURCE) {
362         state |= d3d12::D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
363             | d3d12::D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
364     }
365     if usage.intersects(Tu::COLOR_TARGET) {
366         state |= d3d12::D3D12_RESOURCE_STATE_RENDER_TARGET;
367     }
368     if usage.intersects(Tu::DEPTH_STENCIL_READ) {
369         state |= d3d12::D3D12_RESOURCE_STATE_DEPTH_READ;
370     }
371     if usage.intersects(Tu::DEPTH_STENCIL_WRITE) {
372         state |= d3d12::D3D12_RESOURCE_STATE_DEPTH_WRITE;
373     }
374     if usage.intersects(Tu::STORAGE_READ | Tu::STORAGE_WRITE) {
375         state |= d3d12::D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
376     }
377     state
378 }
379 
map_topology( topology: wgt::PrimitiveTopology, ) -> ( d3d12::D3D12_PRIMITIVE_TOPOLOGY_TYPE, d3d12::D3D12_PRIMITIVE_TOPOLOGY, )380 pub fn map_topology(
381     topology: wgt::PrimitiveTopology,
382 ) -> (
383     d3d12::D3D12_PRIMITIVE_TOPOLOGY_TYPE,
384     d3d12::D3D12_PRIMITIVE_TOPOLOGY,
385 ) {
386     match topology {
387         wgt::PrimitiveTopology::PointList => (
388             d3d12::D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT,
389             d3dcommon::D3D_PRIMITIVE_TOPOLOGY_POINTLIST,
390         ),
391         wgt::PrimitiveTopology::LineList => (
392             d3d12::D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE,
393             d3dcommon::D3D_PRIMITIVE_TOPOLOGY_LINELIST,
394         ),
395         wgt::PrimitiveTopology::LineStrip => (
396             d3d12::D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE,
397             d3dcommon::D3D_PRIMITIVE_TOPOLOGY_LINESTRIP,
398         ),
399         wgt::PrimitiveTopology::TriangleList => (
400             d3d12::D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
401             d3dcommon::D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
402         ),
403         wgt::PrimitiveTopology::TriangleStrip => (
404             d3d12::D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
405             d3dcommon::D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP,
406         ),
407     }
408 }
409 
map_polygon_mode(mode: wgt::PolygonMode) -> d3d12::D3D12_FILL_MODE410 pub fn map_polygon_mode(mode: wgt::PolygonMode) -> d3d12::D3D12_FILL_MODE {
411     match mode {
412         wgt::PolygonMode::Point => {
413             log::error!("Point rasterization is not supported");
414             d3d12::D3D12_FILL_MODE_WIREFRAME
415         }
416         wgt::PolygonMode::Line => d3d12::D3D12_FILL_MODE_WIREFRAME,
417         wgt::PolygonMode::Fill => d3d12::D3D12_FILL_MODE_SOLID,
418     }
419 }
420 
map_blend_factor(factor: wgt::BlendFactor, is_alpha: bool) -> d3d12::D3D12_BLEND421 fn map_blend_factor(factor: wgt::BlendFactor, is_alpha: bool) -> d3d12::D3D12_BLEND {
422     use wgt::BlendFactor as Bf;
423     match factor {
424         Bf::Zero => d3d12::D3D12_BLEND_ZERO,
425         Bf::One => d3d12::D3D12_BLEND_ONE,
426         Bf::Src if is_alpha => d3d12::D3D12_BLEND_SRC_ALPHA,
427         Bf::Src => d3d12::D3D12_BLEND_SRC_COLOR,
428         Bf::OneMinusSrc if is_alpha => d3d12::D3D12_BLEND_INV_SRC_ALPHA,
429         Bf::OneMinusSrc => d3d12::D3D12_BLEND_INV_SRC_COLOR,
430         Bf::Dst if is_alpha => d3d12::D3D12_BLEND_DEST_ALPHA,
431         Bf::Dst => d3d12::D3D12_BLEND_DEST_COLOR,
432         Bf::OneMinusDst if is_alpha => d3d12::D3D12_BLEND_INV_DEST_ALPHA,
433         Bf::OneMinusDst => d3d12::D3D12_BLEND_INV_DEST_COLOR,
434         Bf::SrcAlpha => d3d12::D3D12_BLEND_SRC_ALPHA,
435         Bf::OneMinusSrcAlpha => d3d12::D3D12_BLEND_INV_SRC_ALPHA,
436         Bf::DstAlpha => d3d12::D3D12_BLEND_DEST_ALPHA,
437         Bf::OneMinusDstAlpha => d3d12::D3D12_BLEND_INV_DEST_ALPHA,
438         Bf::Constant => d3d12::D3D12_BLEND_BLEND_FACTOR,
439         Bf::OneMinusConstant => d3d12::D3D12_BLEND_INV_BLEND_FACTOR,
440         Bf::SrcAlphaSaturated => d3d12::D3D12_BLEND_SRC_ALPHA_SAT,
441         //Bf::Src1Color if is_alpha => d3d12::D3D12_BLEND_SRC1_ALPHA,
442         //Bf::Src1Color => d3d12::D3D12_BLEND_SRC1_COLOR,
443         //Bf::OneMinusSrc1Color if is_alpha => d3d12::D3D12_BLEND_INV_SRC1_ALPHA,
444         //Bf::OneMinusSrc1Color => d3d12::D3D12_BLEND_INV_SRC1_COLOR,
445         //Bf::Src1Alpha => d3d12::D3D12_BLEND_SRC1_ALPHA,
446         //Bf::OneMinusSrc1Alpha => d3d12::D3D12_BLEND_INV_SRC1_ALPHA,
447     }
448 }
449 
map_blend_component( component: &wgt::BlendComponent, is_alpha: bool, ) -> ( d3d12::D3D12_BLEND_OP, d3d12::D3D12_BLEND, d3d12::D3D12_BLEND, )450 fn map_blend_component(
451     component: &wgt::BlendComponent,
452     is_alpha: bool,
453 ) -> (
454     d3d12::D3D12_BLEND_OP,
455     d3d12::D3D12_BLEND,
456     d3d12::D3D12_BLEND,
457 ) {
458     let raw_op = match component.operation {
459         wgt::BlendOperation::Add => d3d12::D3D12_BLEND_OP_ADD,
460         wgt::BlendOperation::Subtract => d3d12::D3D12_BLEND_OP_SUBTRACT,
461         wgt::BlendOperation::ReverseSubtract => d3d12::D3D12_BLEND_OP_REV_SUBTRACT,
462         wgt::BlendOperation::Min => d3d12::D3D12_BLEND_OP_MIN,
463         wgt::BlendOperation::Max => d3d12::D3D12_BLEND_OP_MAX,
464     };
465     let raw_src = map_blend_factor(component.src_factor, is_alpha);
466     let raw_dst = map_blend_factor(component.dst_factor, is_alpha);
467     (raw_op, raw_src, raw_dst)
468 }
469 
map_render_targets( color_targets: &[wgt::ColorTargetState], ) -> [d3d12::D3D12_RENDER_TARGET_BLEND_DESC; d3d12::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize]470 pub fn map_render_targets(
471     color_targets: &[wgt::ColorTargetState],
472 ) -> [d3d12::D3D12_RENDER_TARGET_BLEND_DESC; d3d12::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize]
473 {
474     let dummy_target = d3d12::D3D12_RENDER_TARGET_BLEND_DESC {
475         BlendEnable: 0,
476         LogicOpEnable: 0,
477         SrcBlend: d3d12::D3D12_BLEND_ZERO,
478         DestBlend: d3d12::D3D12_BLEND_ZERO,
479         BlendOp: d3d12::D3D12_BLEND_OP_ADD,
480         SrcBlendAlpha: d3d12::D3D12_BLEND_ZERO,
481         DestBlendAlpha: d3d12::D3D12_BLEND_ZERO,
482         BlendOpAlpha: d3d12::D3D12_BLEND_OP_ADD,
483         LogicOp: d3d12::D3D12_LOGIC_OP_CLEAR,
484         RenderTargetWriteMask: 0,
485     };
486     let mut raw_targets = [dummy_target; d3d12::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize];
487 
488     for (raw, ct) in raw_targets.iter_mut().zip(color_targets.iter()) {
489         raw.RenderTargetWriteMask = ct.write_mask.bits() as u8;
490         if let Some(ref blend) = ct.blend {
491             let (color_op, color_src, color_dst) = map_blend_component(&blend.color, false);
492             let (alpha_op, alpha_src, alpha_dst) = map_blend_component(&blend.alpha, true);
493             raw.BlendEnable = 1;
494             raw.BlendOp = color_op;
495             raw.SrcBlend = color_src;
496             raw.DestBlend = color_dst;
497             raw.BlendOpAlpha = alpha_op;
498             raw.SrcBlendAlpha = alpha_src;
499             raw.DestBlendAlpha = alpha_dst;
500         }
501     }
502 
503     raw_targets
504 }
505 
map_stencil_op(op: wgt::StencilOperation) -> d3d12::D3D12_STENCIL_OP506 fn map_stencil_op(op: wgt::StencilOperation) -> d3d12::D3D12_STENCIL_OP {
507     use wgt::StencilOperation as So;
508     match op {
509         So::Keep => d3d12::D3D12_STENCIL_OP_KEEP,
510         So::Zero => d3d12::D3D12_STENCIL_OP_ZERO,
511         So::Replace => d3d12::D3D12_STENCIL_OP_REPLACE,
512         So::IncrementClamp => d3d12::D3D12_STENCIL_OP_INCR_SAT,
513         So::IncrementWrap => d3d12::D3D12_STENCIL_OP_INCR,
514         So::DecrementClamp => d3d12::D3D12_STENCIL_OP_DECR_SAT,
515         So::DecrementWrap => d3d12::D3D12_STENCIL_OP_DECR,
516         So::Invert => d3d12::D3D12_STENCIL_OP_INVERT,
517     }
518 }
519 
map_stencil_face(face: &wgt::StencilFaceState) -> d3d12::D3D12_DEPTH_STENCILOP_DESC520 fn map_stencil_face(face: &wgt::StencilFaceState) -> d3d12::D3D12_DEPTH_STENCILOP_DESC {
521     d3d12::D3D12_DEPTH_STENCILOP_DESC {
522         StencilFailOp: map_stencil_op(face.fail_op),
523         StencilDepthFailOp: map_stencil_op(face.depth_fail_op),
524         StencilPassOp: map_stencil_op(face.pass_op),
525         StencilFunc: map_comparison(face.compare),
526     }
527 }
528 
map_depth_stencil(ds: &wgt::DepthStencilState) -> d3d12::D3D12_DEPTH_STENCIL_DESC529 pub fn map_depth_stencil(ds: &wgt::DepthStencilState) -> d3d12::D3D12_DEPTH_STENCIL_DESC {
530     d3d12::D3D12_DEPTH_STENCIL_DESC {
531         DepthEnable: if ds.is_depth_enabled() { 1 } else { 0 },
532         DepthWriteMask: if ds.depth_write_enabled {
533             d3d12::D3D12_DEPTH_WRITE_MASK_ALL
534         } else {
535             d3d12::D3D12_DEPTH_WRITE_MASK_ZERO
536         },
537         DepthFunc: map_comparison(ds.depth_compare),
538         StencilEnable: if ds.stencil.is_enabled() { 1 } else { 0 },
539         StencilReadMask: ds.stencil.read_mask as u8,
540         StencilWriteMask: ds.stencil.write_mask as u8,
541         FrontFace: map_stencil_face(&ds.stencil.front),
542         BackFace: map_stencil_face(&ds.stencil.back),
543     }
544 }
545