1 use auxil::ShaderStage;
2 use hal::{
3     format::{Aspects, Format, FormatDesc},
4     image,
5     pso::{
6         BlendDesc, BlendOp, ColorBlendDesc, Comparison, DepthBias, DepthStencilDesc, Face, Factor,
7         FrontFace, InputAssemblerDesc, Multisampling, PolygonMode, Rasterizer, Rect, Sided, State,
8         StencilFace, StencilOp, StencilValue, Viewport,
9     },
10     IndexType,
11 };
12 
13 use spirv_cross::{hlsl, spirv};
14 
15 use winapi::{
16     shared::{
17         dxgiformat::*,
18         minwindef::{FALSE, INT, TRUE},
19     },
20     um::{d3d11::*, d3dcommon::*},
21 };
22 
23 use std::mem;
24 
map_index_type(ty: IndexType) -> DXGI_FORMAT25 pub fn map_index_type(ty: IndexType) -> DXGI_FORMAT {
26     match ty {
27         IndexType::U16 => DXGI_FORMAT_R16_UINT,
28         IndexType::U32 => DXGI_FORMAT_R32_UINT,
29     }
30 }
31 
32 // TODO: add aspect parameter
viewable_format(format: DXGI_FORMAT) -> DXGI_FORMAT33 pub fn viewable_format(format: DXGI_FORMAT) -> DXGI_FORMAT {
34     match format {
35         DXGI_FORMAT_D32_FLOAT_S8X24_UINT => DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
36         DXGI_FORMAT_D32_FLOAT => DXGI_FORMAT_R32_FLOAT,
37         DXGI_FORMAT_D16_UNORM => DXGI_FORMAT_R16_UNORM,
38         _ => format,
39     }
40 }
41 
42 // TODO: stolen from d3d12 backend, maybe share function somehow?
map_format(format: Format) -> Option<DXGI_FORMAT>43 pub fn map_format(format: Format) -> Option<DXGI_FORMAT> {
44     use hal::format::Format::*;
45 
46     let format = match format {
47         R5g6b5Unorm => DXGI_FORMAT_B5G6R5_UNORM,
48         R5g5b5a1Unorm => DXGI_FORMAT_B5G5R5A1_UNORM,
49         R8Unorm => DXGI_FORMAT_R8_UNORM,
50         R8Snorm => DXGI_FORMAT_R8_SNORM,
51         R8Uint => DXGI_FORMAT_R8_UINT,
52         R8Sint => DXGI_FORMAT_R8_SINT,
53         Rg8Unorm => DXGI_FORMAT_R8G8_UNORM,
54         Rg8Snorm => DXGI_FORMAT_R8G8_SNORM,
55         Rg8Uint => DXGI_FORMAT_R8G8_UINT,
56         Rg8Sint => DXGI_FORMAT_R8G8_SINT,
57         Rgba8Unorm => DXGI_FORMAT_R8G8B8A8_UNORM,
58         Rgba8Snorm => DXGI_FORMAT_R8G8B8A8_SNORM,
59         Rgba8Uint => DXGI_FORMAT_R8G8B8A8_UINT,
60         Rgba8Sint => DXGI_FORMAT_R8G8B8A8_SINT,
61         Rgba8Srgb => DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
62         Bgra8Unorm => DXGI_FORMAT_B8G8R8A8_UNORM,
63         Bgra8Srgb => DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
64         A2b10g10r10Unorm => DXGI_FORMAT_R10G10B10A2_UNORM,
65         A2b10g10r10Uint => DXGI_FORMAT_R10G10B10A2_UINT,
66         R16Unorm => DXGI_FORMAT_R16_UNORM,
67         R16Snorm => DXGI_FORMAT_R16_SNORM,
68         R16Uint => DXGI_FORMAT_R16_UINT,
69         R16Sint => DXGI_FORMAT_R16_SINT,
70         R16Sfloat => DXGI_FORMAT_R16_FLOAT,
71         Rg16Unorm => DXGI_FORMAT_R16G16_UNORM,
72         Rg16Snorm => DXGI_FORMAT_R16G16_SNORM,
73         Rg16Uint => DXGI_FORMAT_R16G16_UINT,
74         Rg16Sint => DXGI_FORMAT_R16G16_SINT,
75         Rg16Sfloat => DXGI_FORMAT_R16G16_FLOAT,
76         Rgba16Unorm => DXGI_FORMAT_R16G16B16A16_UNORM,
77         Rgba16Snorm => DXGI_FORMAT_R16G16B16A16_SNORM,
78         Rgba16Uint => DXGI_FORMAT_R16G16B16A16_UINT,
79         Rgba16Sint => DXGI_FORMAT_R16G16B16A16_SINT,
80         Rgba16Sfloat => DXGI_FORMAT_R16G16B16A16_FLOAT,
81         R32Uint => DXGI_FORMAT_R32_UINT,
82         R32Sint => DXGI_FORMAT_R32_SINT,
83         R32Sfloat => DXGI_FORMAT_R32_FLOAT,
84         Rg32Uint => DXGI_FORMAT_R32G32_UINT,
85         Rg32Sint => DXGI_FORMAT_R32G32_SINT,
86         Rg32Sfloat => DXGI_FORMAT_R32G32_FLOAT,
87         Rgb32Uint => DXGI_FORMAT_R32G32B32_UINT,
88         Rgb32Sint => DXGI_FORMAT_R32G32B32_SINT,
89         Rgb32Sfloat => DXGI_FORMAT_R32G32B32_FLOAT,
90         Rgba32Uint => DXGI_FORMAT_R32G32B32A32_UINT,
91         Rgba32Sint => DXGI_FORMAT_R32G32B32A32_SINT,
92         Rgba32Sfloat => DXGI_FORMAT_R32G32B32A32_FLOAT,
93         B10g11r11Ufloat => DXGI_FORMAT_R11G11B10_FLOAT,
94         E5b9g9r9Ufloat => DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
95         D16Unorm => DXGI_FORMAT_D16_UNORM,
96         D32Sfloat => DXGI_FORMAT_D32_FLOAT,
97         D32SfloatS8Uint => DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
98         Bc1RgbUnorm | Bc1RgbaUnorm => DXGI_FORMAT_BC1_UNORM,
99         Bc1RgbSrgb | Bc1RgbaSrgb => DXGI_FORMAT_BC1_UNORM_SRGB,
100         Bc2Unorm => DXGI_FORMAT_BC2_UNORM,
101         Bc2Srgb => DXGI_FORMAT_BC2_UNORM_SRGB,
102         Bc3Unorm => DXGI_FORMAT_BC3_UNORM,
103         Bc3Srgb => DXGI_FORMAT_BC3_UNORM_SRGB,
104         Bc4Unorm => DXGI_FORMAT_BC4_UNORM,
105         Bc4Snorm => DXGI_FORMAT_BC4_SNORM,
106         Bc5Unorm => DXGI_FORMAT_BC5_UNORM,
107         Bc5Snorm => DXGI_FORMAT_BC5_SNORM,
108         Bc6hUfloat => DXGI_FORMAT_BC6H_UF16,
109         Bc6hSfloat => DXGI_FORMAT_BC6H_SF16,
110         Bc7Unorm => DXGI_FORMAT_BC7_UNORM,
111         Bc7Srgb => DXGI_FORMAT_BC7_UNORM_SRGB,
112 
113         _ => return None,
114     };
115 
116     Some(format)
117 }
118 
map_format_nosrgb(format: Format) -> Option<DXGI_FORMAT>119 pub fn map_format_nosrgb(format: Format) -> Option<DXGI_FORMAT> {
120     // NOTE: DXGI doesn't allow sRGB format on the swapchain, but
121     //       creating RTV of swapchain buffers with sRGB works
122     match format {
123         Format::Bgra8Srgb => Some(DXGI_FORMAT_B8G8R8A8_UNORM),
124         Format::Rgba8Srgb => Some(DXGI_FORMAT_R8G8B8A8_UNORM),
125         _ => map_format(format),
126     }
127 }
128 
129 #[derive(Debug, Clone)]
130 pub struct DecomposedDxgiFormat {
131     pub typeless: DXGI_FORMAT,
132     pub srv: Option<DXGI_FORMAT>,
133     pub rtv: Option<DXGI_FORMAT>,
134     pub uav: Option<DXGI_FORMAT>,
135     pub dsv: Option<DXGI_FORMAT>,
136     // the format we use internally for operating on textures (eg. Rgba8 uses R32 internally for
137     // copies)
138     pub copy_uav: Option<DXGI_FORMAT>,
139     pub copy_srv: Option<DXGI_FORMAT>,
140 }
141 
142 impl DecomposedDxgiFormat {
143     pub const UNKNOWN: DecomposedDxgiFormat = DecomposedDxgiFormat {
144         typeless: DXGI_FORMAT_UNKNOWN,
145         srv: None,
146         rtv: None,
147         uav: None,
148         dsv: None,
149         copy_uav: None,
150         copy_srv: None,
151     };
152 
153     // TODO: we probably want to pass in usage flags or similar to allow for our `typeless_format`
154     //       field to only contain the input format (eg. depth only rather than typeless likely
155     //       improves perf since the driver doesn't need to expose internals)
156     //
157     // TODO: we also want aspect for determining depth/stencil
from_dxgi_format(format: DXGI_FORMAT) -> DecomposedDxgiFormat158     pub fn from_dxgi_format(format: DXGI_FORMAT) -> DecomposedDxgiFormat {
159         match format {
160             DXGI_FORMAT_R8G8B8A8_UNORM
161             | DXGI_FORMAT_R8G8B8A8_SNORM
162             | DXGI_FORMAT_R8G8B8A8_UINT
163             | DXGI_FORMAT_R8G8B8A8_SINT
164             | DXGI_FORMAT_R8G8B8A8_UNORM_SRGB => DecomposedDxgiFormat {
165                 typeless: DXGI_FORMAT_R8G8B8A8_TYPELESS,
166                 srv: Some(format),
167                 rtv: Some(format),
168                 uav: Some(format),
169                 dsv: None,
170                 copy_uav: Some(DXGI_FORMAT_R32_UINT),
171                 copy_srv: Some(DXGI_FORMAT_R8G8B8A8_UINT),
172             },
173 
174             DXGI_FORMAT_B8G8R8A8_UNORM | DXGI_FORMAT_B8G8R8A8_UNORM_SRGB => DecomposedDxgiFormat {
175                 typeless: DXGI_FORMAT_B8G8R8A8_TYPELESS,
176                 srv: Some(format),
177                 rtv: Some(format),
178                 uav: Some(DXGI_FORMAT_B8G8R8A8_UNORM),
179                 dsv: None,
180                 copy_uav: Some(DXGI_FORMAT_R32_UINT),
181                 copy_srv: Some(DXGI_FORMAT_B8G8R8A8_UNORM),
182             },
183 
184             DXGI_FORMAT_A8_UNORM => DecomposedDxgiFormat {
185                 typeless: format,
186                 srv: Some(format),
187                 rtv: Some(format),
188                 uav: Some(format),
189                 dsv: None,
190                 copy_uav: Some(format),
191                 copy_srv: Some(format),
192             },
193 
194             DXGI_FORMAT_R8_UNORM | DXGI_FORMAT_R8_SNORM | DXGI_FORMAT_R8_UINT
195             | DXGI_FORMAT_R8_SINT => DecomposedDxgiFormat {
196                 typeless: DXGI_FORMAT_R8_TYPELESS,
197                 srv: Some(format),
198                 rtv: Some(format),
199                 uav: Some(format),
200                 dsv: None,
201                 copy_uav: Some(DXGI_FORMAT_R8_UINT),
202                 copy_srv: Some(DXGI_FORMAT_R8_UINT),
203             },
204 
205             DXGI_FORMAT_R8G8_UNORM
206             | DXGI_FORMAT_R8G8_SNORM
207             | DXGI_FORMAT_R8G8_UINT
208             | DXGI_FORMAT_R8G8_SINT => DecomposedDxgiFormat {
209                 typeless: DXGI_FORMAT_R8G8_TYPELESS,
210                 srv: Some(format),
211                 rtv: Some(format),
212                 uav: Some(format),
213                 dsv: None,
214                 copy_uav: Some(DXGI_FORMAT_R8G8_UINT),
215                 copy_srv: Some(DXGI_FORMAT_R8G8_UINT),
216             },
217 
218             DXGI_FORMAT_D16_UNORM => DecomposedDxgiFormat {
219                 typeless: DXGI_FORMAT_R16_TYPELESS,
220                 srv: Some(DXGI_FORMAT_R16_FLOAT),
221                 rtv: Some(DXGI_FORMAT_R16_FLOAT),
222                 uav: Some(DXGI_FORMAT_R16_FLOAT),
223                 dsv: Some(format),
224                 copy_uav: Some(DXGI_FORMAT_R16_UINT),
225                 copy_srv: Some(DXGI_FORMAT_R16_UINT),
226             },
227 
228             DXGI_FORMAT_R16_UNORM
229             | DXGI_FORMAT_R16_SNORM
230             | DXGI_FORMAT_R16_UINT
231             | DXGI_FORMAT_R16_SINT
232             | DXGI_FORMAT_R16_FLOAT => DecomposedDxgiFormat {
233                 typeless: DXGI_FORMAT_R16_TYPELESS,
234                 srv: Some(format),
235                 rtv: Some(format),
236                 uav: Some(format),
237                 dsv: Some(DXGI_FORMAT_D16_UNORM),
238                 copy_uav: Some(DXGI_FORMAT_R16_UINT),
239                 copy_srv: Some(DXGI_FORMAT_R16_UINT),
240             },
241 
242             DXGI_FORMAT_R16G16_UNORM
243             | DXGI_FORMAT_R16G16_SNORM
244             | DXGI_FORMAT_R16G16_UINT
245             | DXGI_FORMAT_R16G16_SINT
246             | DXGI_FORMAT_R16G16_FLOAT => DecomposedDxgiFormat {
247                 typeless: DXGI_FORMAT_R16G16_TYPELESS,
248                 srv: Some(format),
249                 rtv: Some(format),
250                 uav: Some(format),
251                 dsv: None,
252                 copy_uav: Some(DXGI_FORMAT_R32_UINT),
253                 copy_srv: Some(DXGI_FORMAT_R16G16_UINT),
254             },
255 
256             DXGI_FORMAT_R16G16B16A16_UNORM
257             | DXGI_FORMAT_R16G16B16A16_SNORM
258             | DXGI_FORMAT_R16G16B16A16_UINT
259             | DXGI_FORMAT_R16G16B16A16_SINT
260             | DXGI_FORMAT_R16G16B16A16_FLOAT => DecomposedDxgiFormat {
261                 typeless: DXGI_FORMAT_R16G16B16A16_TYPELESS,
262                 srv: Some(format),
263                 rtv: Some(format),
264                 uav: Some(format),
265                 dsv: None,
266                 copy_uav: Some(DXGI_FORMAT_R16G16B16A16_UINT),
267                 copy_srv: Some(DXGI_FORMAT_R16G16B16A16_UINT),
268             },
269 
270             DXGI_FORMAT_D32_FLOAT_S8X24_UINT => DecomposedDxgiFormat {
271                 typeless: DXGI_FORMAT_R32G8X24_TYPELESS,
272                 // TODO: depth or stencil?
273                 srv: Some(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS),
274                 rtv: None,
275                 uav: None,
276                 dsv: Some(format),
277                 copy_uav: None,
278                 copy_srv: Some(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS),
279             },
280 
281             DXGI_FORMAT_D32_FLOAT => DecomposedDxgiFormat {
282                 typeless: DXGI_FORMAT_R32_TYPELESS,
283                 srv: Some(DXGI_FORMAT_R32_FLOAT),
284                 rtv: None,
285                 uav: None,
286                 dsv: Some(format),
287                 copy_uav: Some(DXGI_FORMAT_R32_UINT),
288                 copy_srv: Some(DXGI_FORMAT_R32_UINT),
289             },
290 
291             DXGI_FORMAT_R32_UINT | DXGI_FORMAT_R32_SINT | DXGI_FORMAT_R32_FLOAT => {
292                 DecomposedDxgiFormat {
293                     typeless: DXGI_FORMAT_R32_TYPELESS,
294                     srv: Some(format),
295                     rtv: Some(format),
296                     uav: Some(format),
297                     dsv: Some(DXGI_FORMAT_D32_FLOAT),
298                     copy_uav: Some(DXGI_FORMAT_R32_UINT),
299                     copy_srv: Some(DXGI_FORMAT_R32_UINT),
300                 }
301             }
302 
303             DXGI_FORMAT_R32G32_UINT | DXGI_FORMAT_R32G32_SINT | DXGI_FORMAT_R32G32_FLOAT => {
304                 DecomposedDxgiFormat {
305                     typeless: DXGI_FORMAT_R32G32_TYPELESS,
306                     srv: Some(format),
307                     rtv: Some(format),
308                     uav: Some(format),
309                     dsv: None,
310                     copy_uav: Some(DXGI_FORMAT_R32G32_UINT),
311                     copy_srv: Some(DXGI_FORMAT_R32G32_UINT),
312                 }
313             }
314 
315             // TODO: should we just convert to Rgba32 internally?
316             DXGI_FORMAT_R32G32B32_UINT
317             | DXGI_FORMAT_R32G32B32_SINT
318             | DXGI_FORMAT_R32G32B32_FLOAT => DecomposedDxgiFormat {
319                 typeless: DXGI_FORMAT_R32G32_TYPELESS,
320                 srv: Some(format),
321                 rtv: None,
322                 uav: None,
323                 dsv: None,
324                 copy_uav: Some(DXGI_FORMAT_R32G32B32_UINT),
325                 copy_srv: Some(DXGI_FORMAT_R32G32B32_UINT),
326             },
327 
328             DXGI_FORMAT_R32G32B32A32_UINT
329             | DXGI_FORMAT_R32G32B32A32_SINT
330             | DXGI_FORMAT_R32G32B32A32_FLOAT => DecomposedDxgiFormat {
331                 typeless: DXGI_FORMAT_R32G32B32A32_TYPELESS,
332                 srv: Some(format),
333                 rtv: Some(format),
334                 uav: Some(format),
335                 dsv: None,
336                 copy_uav: Some(DXGI_FORMAT_R32G32B32A32_UINT),
337                 copy_srv: Some(DXGI_FORMAT_R32G32B32A32_UINT),
338             },
339 
340             DXGI_FORMAT_R10G10B10A2_UNORM | DXGI_FORMAT_R10G10B10A2_UINT => DecomposedDxgiFormat {
341                 typeless: DXGI_FORMAT_R10G10B10A2_TYPELESS,
342                 srv: Some(format),
343                 rtv: Some(format),
344                 uav: Some(format),
345                 dsv: None,
346                 copy_uav: Some(DXGI_FORMAT_R32_UINT),
347                 copy_srv: Some(DXGI_FORMAT_R10G10B10A2_UINT),
348             },
349 
350             DXGI_FORMAT_R11G11B10_FLOAT => DecomposedDxgiFormat {
351                 typeless: format,
352                 srv: Some(format),
353                 rtv: Some(format),
354                 uav: Some(format),
355                 dsv: None,
356                 copy_uav: Some(format),
357                 copy_srv: Some(format),
358             },
359 
360             DXGI_FORMAT_R9G9B9E5_SHAREDEXP => DecomposedDxgiFormat {
361                 typeless: format,
362                 srv: Some(format),
363                 rtv: None,
364                 uav: None,
365                 dsv: None,
366                 // NOTE: read only
367                 copy_uav: None,
368                 copy_srv: Some(format),
369             },
370 
371             DXGI_FORMAT_BC1_UNORM | DXGI_FORMAT_BC1_UNORM_SRGB => DecomposedDxgiFormat {
372                 typeless: DXGI_FORMAT_BC1_TYPELESS,
373                 srv: Some(format),
374                 rtv: None,
375                 uav: None,
376                 dsv: None,
377                 // NOTE: read only
378                 copy_uav: None,
379                 copy_srv: Some(format),
380             },
381 
382             DXGI_FORMAT_BC2_UNORM | DXGI_FORMAT_BC2_UNORM_SRGB => DecomposedDxgiFormat {
383                 typeless: DXGI_FORMAT_BC2_TYPELESS,
384                 srv: Some(format),
385                 rtv: None,
386                 uav: None,
387                 dsv: None,
388                 // NOTE: read only
389                 copy_uav: None,
390                 copy_srv: Some(format),
391             },
392 
393             DXGI_FORMAT_BC3_UNORM | DXGI_FORMAT_BC3_UNORM_SRGB => DecomposedDxgiFormat {
394                 typeless: DXGI_FORMAT_BC3_TYPELESS,
395                 srv: Some(format),
396                 rtv: None,
397                 uav: None,
398                 dsv: None,
399                 // NOTE: read only
400                 copy_uav: None,
401                 copy_srv: Some(format),
402             },
403 
404             DXGI_FORMAT_BC4_UNORM | DXGI_FORMAT_BC4_SNORM => DecomposedDxgiFormat {
405                 typeless: DXGI_FORMAT_BC4_TYPELESS,
406                 srv: Some(format),
407                 rtv: None,
408                 uav: None,
409                 dsv: None,
410                 // NOTE: read only
411                 copy_uav: None,
412                 copy_srv: Some(format),
413             },
414 
415             DXGI_FORMAT_BC5_UNORM | DXGI_FORMAT_BC5_SNORM => DecomposedDxgiFormat {
416                 typeless: format,
417                 srv: Some(format),
418                 rtv: None,
419                 uav: None,
420                 dsv: None,
421                 // NOTE: read only
422                 copy_uav: None,
423                 copy_srv: Some(format),
424             },
425 
426             DXGI_FORMAT_BC6H_UF16 | DXGI_FORMAT_BC6H_SF16 => DecomposedDxgiFormat {
427                 typeless: DXGI_FORMAT_BC6H_TYPELESS,
428                 srv: Some(format),
429                 rtv: None,
430                 uav: None,
431                 dsv: None,
432                 // NOTE: read only
433                 copy_uav: None,
434                 copy_srv: Some(format),
435             },
436 
437             // TODO: srgb craziness
438             DXGI_FORMAT_BC7_UNORM | DXGI_FORMAT_BC7_UNORM_SRGB => DecomposedDxgiFormat {
439                 typeless: DXGI_FORMAT_BC7_TYPELESS,
440                 srv: Some(format),
441                 rtv: None,
442                 uav: None,
443                 dsv: None,
444                 // NOTE: read only
445                 copy_uav: None,
446                 copy_srv: Some(format),
447             },
448 
449             _ => unimplemented!(),
450         }
451     }
452 }
453 
map_viewport(viewport: &Viewport) -> D3D11_VIEWPORT454 pub fn map_viewport(viewport: &Viewport) -> D3D11_VIEWPORT {
455     D3D11_VIEWPORT {
456         TopLeftX: viewport.rect.x as _,
457         TopLeftY: viewport.rect.y as _,
458         Width: viewport.rect.w as _,
459         Height: viewport.rect.h as _,
460         MinDepth: viewport.depth.start,
461         MaxDepth: viewport.depth.end,
462     }
463 }
464 
map_rect(rect: &Rect) -> D3D11_RECT465 pub fn map_rect(rect: &Rect) -> D3D11_RECT {
466     D3D11_RECT {
467         left: rect.x as _,
468         top: rect.y as _,
469         right: (rect.x + rect.w) as _,
470         bottom: (rect.y + rect.h) as _,
471     }
472 }
473 
map_topology(ia: &InputAssemblerDesc) -> D3D11_PRIMITIVE_TOPOLOGY474 pub fn map_topology(ia: &InputAssemblerDesc) -> D3D11_PRIMITIVE_TOPOLOGY {
475     use hal::pso::Primitive::*;
476     match (ia.primitive, ia.with_adjacency) {
477         (PointList, false) => D3D_PRIMITIVE_TOPOLOGY_POINTLIST,
478         (PointList, true) => panic!("Points can't have adjacency info"),
479         (LineList, false) => D3D_PRIMITIVE_TOPOLOGY_LINELIST,
480         (LineList, true) => D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ,
481         (LineStrip, false) => D3D_PRIMITIVE_TOPOLOGY_LINESTRIP,
482         (LineStrip, true) => D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ,
483         (TriangleList, false) => D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
484         (TriangleList, true) => D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ,
485         (TriangleStrip, false) => D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP,
486         (TriangleStrip, true) => D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ,
487         (PatchList(num), false) => {
488             assert!(num != 0);
489             D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (num as u32) - 1
490         }
491         (_, true) => panic!("Patches can't have adjacency info"),
492     }
493 }
494 
map_fill_mode(mode: PolygonMode) -> D3D11_FILL_MODE495 fn map_fill_mode(mode: PolygonMode) -> D3D11_FILL_MODE {
496     match mode {
497         PolygonMode::Fill => D3D11_FILL_SOLID,
498         PolygonMode::Line => D3D11_FILL_WIREFRAME,
499         // TODO: return error
500         _ => unimplemented!(),
501     }
502 }
503 
map_cull_mode(mode: Face) -> D3D11_CULL_MODE504 fn map_cull_mode(mode: Face) -> D3D11_CULL_MODE {
505     match mode {
506         Face::NONE => D3D11_CULL_NONE,
507         Face::FRONT => D3D11_CULL_FRONT,
508         Face::BACK => D3D11_CULL_BACK,
509         _ => panic!("Culling both front and back faces is not supported"),
510     }
511 }
512 
map_rasterizer_desc( desc: &Rasterizer, multisampling_desc: &Option<Multisampling>, ) -> D3D11_RASTERIZER_DESC513 pub(crate) fn map_rasterizer_desc(
514     desc: &Rasterizer,
515     multisampling_desc: &Option<Multisampling>,
516 ) -> D3D11_RASTERIZER_DESC {
517     let bias = match desc.depth_bias {
518         //TODO: support dynamic depth bias
519         Some(State::Static(db)) => db,
520         Some(_) | None => DepthBias::default(),
521     };
522     if let State::Static(w) = desc.line_width {
523         super::validate_line_width(w);
524     }
525     let multisampled = multisampling_desc.is_some();
526     D3D11_RASTERIZER_DESC {
527         FillMode: map_fill_mode(desc.polygon_mode),
528         CullMode: map_cull_mode(desc.cull_face),
529         FrontCounterClockwise: match desc.front_face {
530             FrontFace::Clockwise => FALSE,
531             FrontFace::CounterClockwise => TRUE,
532         },
533         DepthBias: bias.const_factor as INT,
534         DepthBiasClamp: bias.clamp,
535         SlopeScaledDepthBias: bias.slope_factor,
536         DepthClipEnable: !desc.depth_clamping as _,
537         // TODO:
538         ScissorEnable: TRUE,
539         MultisampleEnable: multisampled as _,
540         AntialiasedLineEnable: multisampled as _,
541         // TODO: conservative raster in >=11.x
542     }
543 }
544 
map_blend_factor(factor: Factor) -> D3D11_BLEND545 fn map_blend_factor(factor: Factor) -> D3D11_BLEND {
546     match factor {
547         Factor::Zero => D3D11_BLEND_ZERO,
548         Factor::One => D3D11_BLEND_ONE,
549         Factor::SrcColor => D3D11_BLEND_SRC_COLOR,
550         Factor::OneMinusSrcColor => D3D11_BLEND_INV_SRC_COLOR,
551         Factor::DstColor => D3D11_BLEND_DEST_COLOR,
552         Factor::OneMinusDstColor => D3D11_BLEND_INV_DEST_COLOR,
553         Factor::SrcAlpha => D3D11_BLEND_SRC_ALPHA,
554         Factor::OneMinusSrcAlpha => D3D11_BLEND_INV_SRC_ALPHA,
555         Factor::DstAlpha => D3D11_BLEND_DEST_ALPHA,
556         Factor::OneMinusDstAlpha => D3D11_BLEND_INV_DEST_ALPHA,
557         Factor::ConstColor | Factor::ConstAlpha => D3D11_BLEND_BLEND_FACTOR,
558         Factor::OneMinusConstColor | Factor::OneMinusConstAlpha => D3D11_BLEND_INV_BLEND_FACTOR,
559         Factor::SrcAlphaSaturate => D3D11_BLEND_SRC_ALPHA_SAT,
560         Factor::Src1Color => D3D11_BLEND_SRC1_COLOR,
561         Factor::OneMinusSrc1Color => D3D11_BLEND_INV_SRC1_COLOR,
562         Factor::Src1Alpha => D3D11_BLEND_SRC1_ALPHA,
563         Factor::OneMinusSrc1Alpha => D3D11_BLEND_INV_SRC1_ALPHA,
564     }
565 }
566 
map_alpha_blend_factor(factor: Factor) -> D3D11_BLEND567 fn map_alpha_blend_factor(factor: Factor) -> D3D11_BLEND {
568     match factor {
569         Factor::Zero => D3D11_BLEND_ZERO,
570         Factor::One => D3D11_BLEND_ONE,
571         Factor::SrcColor | Factor::SrcAlpha => D3D11_BLEND_SRC_ALPHA,
572         Factor::DstColor | Factor::DstAlpha => D3D11_BLEND_DEST_ALPHA,
573         Factor::OneMinusSrcColor | Factor::OneMinusSrcAlpha => D3D11_BLEND_INV_SRC_ALPHA,
574         Factor::OneMinusDstColor | Factor::OneMinusDstAlpha => D3D11_BLEND_INV_DEST_ALPHA,
575         Factor::ConstColor | Factor::ConstAlpha => D3D11_BLEND_BLEND_FACTOR,
576         Factor::OneMinusConstColor | Factor::OneMinusConstAlpha => D3D11_BLEND_INV_BLEND_FACTOR,
577         Factor::SrcAlphaSaturate => D3D11_BLEND_SRC_ALPHA_SAT,
578         Factor::Src1Color | Factor::Src1Alpha => D3D11_BLEND_SRC1_ALPHA,
579         Factor::OneMinusSrc1Color | Factor::OneMinusSrc1Alpha => D3D11_BLEND_INV_SRC1_ALPHA,
580     }
581 }
582 
map_blend_op(operation: BlendOp) -> (D3D11_BLEND_OP, D3D11_BLEND, D3D11_BLEND)583 fn map_blend_op(operation: BlendOp) -> (D3D11_BLEND_OP, D3D11_BLEND, D3D11_BLEND) {
584     match operation {
585         BlendOp::Add { src, dst } => (
586             D3D11_BLEND_OP_ADD,
587             map_blend_factor(src),
588             map_blend_factor(dst),
589         ),
590         BlendOp::Sub { src, dst } => (
591             D3D11_BLEND_OP_SUBTRACT,
592             map_blend_factor(src),
593             map_blend_factor(dst),
594         ),
595         BlendOp::RevSub { src, dst } => (
596             D3D11_BLEND_OP_REV_SUBTRACT,
597             map_blend_factor(src),
598             map_blend_factor(dst),
599         ),
600         BlendOp::Min => (D3D11_BLEND_OP_MIN, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO),
601         BlendOp::Max => (D3D11_BLEND_OP_MAX, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO),
602     }
603 }
604 
map_alpha_blend_op(operation: BlendOp) -> (D3D11_BLEND_OP, D3D11_BLEND, D3D11_BLEND)605 fn map_alpha_blend_op(operation: BlendOp) -> (D3D11_BLEND_OP, D3D11_BLEND, D3D11_BLEND) {
606     match operation {
607         BlendOp::Add { src, dst } => (
608             D3D11_BLEND_OP_ADD,
609             map_alpha_blend_factor(src),
610             map_alpha_blend_factor(dst),
611         ),
612         BlendOp::Sub { src, dst } => (
613             D3D11_BLEND_OP_SUBTRACT,
614             map_alpha_blend_factor(src),
615             map_alpha_blend_factor(dst),
616         ),
617         BlendOp::RevSub { src, dst } => (
618             D3D11_BLEND_OP_REV_SUBTRACT,
619             map_alpha_blend_factor(src),
620             map_alpha_blend_factor(dst),
621         ),
622         BlendOp::Min => (D3D11_BLEND_OP_MIN, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO),
623         BlendOp::Max => (D3D11_BLEND_OP_MAX, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO),
624     }
625 }
626 
map_blend_targets( render_target_blends: &[ColorBlendDesc], ) -> [D3D11_RENDER_TARGET_BLEND_DESC; 8]627 fn map_blend_targets(
628     render_target_blends: &[ColorBlendDesc],
629 ) -> [D3D11_RENDER_TARGET_BLEND_DESC; 8] {
630     let mut targets: [D3D11_RENDER_TARGET_BLEND_DESC; 8] = [unsafe { mem::zeroed() }; 8];
631 
632     for (mut target, color_desc) in targets.iter_mut().zip(render_target_blends.iter()) {
633         target.RenderTargetWriteMask = color_desc.mask.bits() as _;
634         if let Some(ref blend) = color_desc.blend {
635             let (color_op, color_src, color_dst) = map_blend_op(blend.color);
636             let (alpha_op, alpha_src, alpha_dst) = map_alpha_blend_op(blend.alpha);
637             target.BlendEnable = TRUE;
638             target.BlendOp = color_op;
639             target.SrcBlend = color_src;
640             target.DestBlend = color_dst;
641             target.BlendOpAlpha = alpha_op;
642             target.SrcBlendAlpha = alpha_src;
643             target.DestBlendAlpha = alpha_dst;
644         }
645     }
646 
647     targets
648 }
649 
map_blend_desc( desc: &BlendDesc, multisampling: &Option<Multisampling>, ) -> D3D11_BLEND_DESC650 pub(crate) fn map_blend_desc(
651     desc: &BlendDesc,
652     multisampling: &Option<Multisampling>,
653 ) -> D3D11_BLEND_DESC {
654     D3D11_BLEND_DESC {
655         AlphaToCoverageEnable: multisampling.as_ref().map_or(false, |m| m.alpha_coverage) as _,
656         IndependentBlendEnable: TRUE,
657         RenderTarget: map_blend_targets(&desc.targets),
658     }
659 }
660 
map_comparison(func: Comparison) -> D3D11_COMPARISON_FUNC661 pub fn map_comparison(func: Comparison) -> D3D11_COMPARISON_FUNC {
662     match func {
663         Comparison::Never => D3D11_COMPARISON_NEVER,
664         Comparison::Less => D3D11_COMPARISON_LESS,
665         Comparison::LessEqual => D3D11_COMPARISON_LESS_EQUAL,
666         Comparison::Equal => D3D11_COMPARISON_EQUAL,
667         Comparison::GreaterEqual => D3D11_COMPARISON_GREATER_EQUAL,
668         Comparison::Greater => D3D11_COMPARISON_GREATER,
669         Comparison::NotEqual => D3D11_COMPARISON_NOT_EQUAL,
670         Comparison::Always => D3D11_COMPARISON_ALWAYS,
671     }
672 }
673 
map_stencil_op(op: StencilOp) -> D3D11_STENCIL_OP674 fn map_stencil_op(op: StencilOp) -> D3D11_STENCIL_OP {
675     match op {
676         StencilOp::Keep => D3D11_STENCIL_OP_KEEP,
677         StencilOp::Zero => D3D11_STENCIL_OP_ZERO,
678         StencilOp::Replace => D3D11_STENCIL_OP_REPLACE,
679         StencilOp::IncrementClamp => D3D11_STENCIL_OP_INCR_SAT,
680         StencilOp::IncrementWrap => D3D11_STENCIL_OP_INCR,
681         StencilOp::DecrementClamp => D3D11_STENCIL_OP_DECR_SAT,
682         StencilOp::DecrementWrap => D3D11_STENCIL_OP_DECR,
683         StencilOp::Invert => D3D11_STENCIL_OP_INVERT,
684     }
685 }
686 
map_stencil_side(side: &StencilFace) -> D3D11_DEPTH_STENCILOP_DESC687 fn map_stencil_side(side: &StencilFace) -> D3D11_DEPTH_STENCILOP_DESC {
688     D3D11_DEPTH_STENCILOP_DESC {
689         StencilFailOp: map_stencil_op(side.op_fail),
690         StencilDepthFailOp: map_stencil_op(side.op_depth_fail),
691         StencilPassOp: map_stencil_op(side.op_pass),
692         StencilFunc: map_comparison(side.fun),
693     }
694 }
695 
map_depth_stencil_desc( desc: &DepthStencilDesc, ) -> (D3D11_DEPTH_STENCIL_DESC, State<StencilValue>, bool)696 pub(crate) fn map_depth_stencil_desc(
697     desc: &DepthStencilDesc,
698 ) -> (D3D11_DEPTH_STENCIL_DESC, State<StencilValue>, bool) {
699     let (depth_on, depth_write, depth_func) = match desc.depth {
700         Some(ref depth) => (TRUE, depth.write, map_comparison(depth.fun)),
701         None => unsafe { mem::zeroed() },
702     };
703 
704     let (stencil_on, front, back, read_mask, write_mask, stencil_ref) = match desc.stencil {
705         Some(ref stencil) => {
706             let read_masks = stencil.read_masks.static_or(Sided::new(!0));
707             let write_masks = stencil.read_masks.static_or(Sided::new(!0));
708             let reference_value = match stencil.reference_values {
709                 State::Static(ref values) => {
710                     if values.front != values.back {
711                         error!("Different reference values for front ({}) and back ({}) of the stencil",
712                             values.front, values.back);
713                     }
714                     State::Static(values.front)
715                 }
716                 State::Dynamic => State::Dynamic,
717             };
718             // TODO: cascade to create_pipeline
719             if read_masks.front != read_masks.back || write_masks.front != write_masks.back {
720                 error!(
721                     "Different sides are specified for read ({:?} and write ({:?}) stencil masks",
722                     read_masks, write_masks
723                 );
724             }
725             (
726                 TRUE,
727                 map_stencil_side(&stencil.faces.front),
728                 map_stencil_side(&stencil.faces.back),
729                 read_masks.front,
730                 write_masks.front,
731                 reference_value,
732             )
733         }
734         None => unsafe { mem::zeroed() },
735     };
736 
737     let stencil_read_only = write_mask == 0
738         || (front.StencilDepthFailOp == D3D11_STENCIL_OP_KEEP
739             && front.StencilFailOp == D3D11_STENCIL_OP_KEEP
740             && front.StencilPassOp == D3D11_STENCIL_OP_KEEP
741             && back.StencilDepthFailOp == D3D11_STENCIL_OP_KEEP
742             && back.StencilFailOp == D3D11_STENCIL_OP_KEEP
743             && back.StencilPassOp == D3D11_STENCIL_OP_KEEP);
744     let read_only = !depth_write && stencil_read_only;
745 
746     (
747         D3D11_DEPTH_STENCIL_DESC {
748             DepthEnable: depth_on,
749             DepthWriteMask: if depth_write {
750                 D3D11_DEPTH_WRITE_MASK_ALL
751             } else {
752                 D3D11_DEPTH_WRITE_MASK_ZERO
753             },
754             DepthFunc: depth_func,
755             StencilEnable: stencil_on,
756             StencilReadMask: read_mask as _,
757             StencilWriteMask: write_mask as _,
758             FrontFace: front,
759             BackFace: back,
760         },
761         stencil_ref,
762         read_only,
763     )
764 }
765 
_map_execution_model(model: spirv::ExecutionModel) -> ShaderStage766 pub fn _map_execution_model(model: spirv::ExecutionModel) -> ShaderStage {
767     match model {
768         spirv::ExecutionModel::Vertex => ShaderStage::Vertex,
769         spirv::ExecutionModel::Fragment => ShaderStage::Fragment,
770         spirv::ExecutionModel::Geometry => ShaderStage::Geometry,
771         spirv::ExecutionModel::GlCompute => ShaderStage::Compute,
772         spirv::ExecutionModel::TessellationControl => ShaderStage::Hull,
773         spirv::ExecutionModel::TessellationEvaluation => ShaderStage::Domain,
774         spirv::ExecutionModel::Kernel => panic!("Kernel is not a valid execution model."),
775     }
776 }
777 
map_stage(stage: ShaderStage) -> spirv::ExecutionModel778 pub fn map_stage(stage: ShaderStage) -> spirv::ExecutionModel {
779     match stage {
780         ShaderStage::Vertex => spirv::ExecutionModel::Vertex,
781         ShaderStage::Fragment => spirv::ExecutionModel::Fragment,
782         ShaderStage::Geometry => spirv::ExecutionModel::Geometry,
783         ShaderStage::Compute => spirv::ExecutionModel::GlCompute,
784         ShaderStage::Hull => spirv::ExecutionModel::TessellationControl,
785         ShaderStage::Domain => spirv::ExecutionModel::TessellationEvaluation,
786         ShaderStage::Task | ShaderStage::Mesh => {
787             panic!("{:?} shader is not supported in DirectX 11", stage)
788         }
789     }
790 }
791 
map_wrapping(wrap: image::WrapMode) -> D3D11_TEXTURE_ADDRESS_MODE792 pub fn map_wrapping(wrap: image::WrapMode) -> D3D11_TEXTURE_ADDRESS_MODE {
793     use hal::image::WrapMode as Wm;
794     match wrap {
795         Wm::Tile => D3D11_TEXTURE_ADDRESS_WRAP,
796         Wm::Mirror => D3D11_TEXTURE_ADDRESS_MIRROR,
797         Wm::Clamp => D3D11_TEXTURE_ADDRESS_CLAMP,
798         Wm::Border => D3D11_TEXTURE_ADDRESS_BORDER,
799         Wm::MirrorClamp => D3D11_TEXTURE_ADDRESS_MIRROR_ONCE,
800     }
801 }
802 
map_filter_type(filter: image::Filter) -> D3D11_FILTER_TYPE803 fn map_filter_type(filter: image::Filter) -> D3D11_FILTER_TYPE {
804     match filter {
805         image::Filter::Nearest => D3D11_FILTER_TYPE_POINT,
806         image::Filter::Linear => D3D11_FILTER_TYPE_LINEAR,
807     }
808 }
809 
810 // Hopefully works just as well in d3d11 :)
map_filter( mag_filter: image::Filter, min_filter: image::Filter, mip_filter: image::Filter, reduction: D3D11_FILTER_REDUCTION_TYPE, anisotropy_clamp: Option<u8>, ) -> D3D11_FILTER811 pub fn map_filter(
812     mag_filter: image::Filter,
813     min_filter: image::Filter,
814     mip_filter: image::Filter,
815     reduction: D3D11_FILTER_REDUCTION_TYPE,
816     anisotropy_clamp: Option<u8>,
817 ) -> D3D11_FILTER {
818     let mag = map_filter_type(mag_filter);
819     let min = map_filter_type(min_filter);
820     let mip = map_filter_type(mip_filter);
821 
822     (min & D3D11_FILTER_TYPE_MASK) << D3D11_MIN_FILTER_SHIFT
823         | (mag & D3D11_FILTER_TYPE_MASK) << D3D11_MAG_FILTER_SHIFT
824         | (mip & D3D11_FILTER_TYPE_MASK) << D3D11_MIP_FILTER_SHIFT
825         | (reduction & D3D11_FILTER_REDUCTION_TYPE_MASK) << D3D11_FILTER_REDUCTION_TYPE_SHIFT
826         | anisotropy_clamp
827             .map(|_| D3D11_FILTER_ANISOTROPIC)
828             .unwrap_or(0)
829 }
830 
map_image_usage( usage: image::Usage, format_desc: FormatDesc, feature_level: u32, ) -> D3D11_BIND_FLAG831 pub fn map_image_usage(
832     usage: image::Usage,
833     format_desc: FormatDesc,
834     feature_level: u32,
835 ) -> D3D11_BIND_FLAG {
836     let mut bind = 0;
837 
838     if usage.intersects(image::Usage::TRANSFER_SRC | image::Usage::SAMPLED | image::Usage::STORAGE)
839     {
840         bind |= D3D11_BIND_SHADER_RESOURCE;
841     }
842 
843     // we cant get RTVs or UAVs on compressed & depth formats
844     if !format_desc.is_compressed() && !format_desc.aspects.contains(Aspects::DEPTH) {
845         if usage.intersects(image::Usage::COLOR_ATTACHMENT | image::Usage::TRANSFER_DST) {
846             bind |= D3D11_BIND_RENDER_TARGET;
847         }
848 
849         // Only add unordered access on the image if we could use compute shaders to copy.
850         let transfer_compute =
851             usage.intersects(image::Usage::TRANSFER_DST) && feature_level >= D3D_FEATURE_LEVEL_11_0;
852         let storage = usage.intersects(image::Usage::STORAGE);
853         if transfer_compute || storage {
854             bind |= D3D11_BIND_UNORDERED_ACCESS;
855         }
856     }
857 
858     if usage.contains(image::Usage::DEPTH_STENCIL_ATTACHMENT) {
859         bind |= D3D11_BIND_DEPTH_STENCIL;
860     }
861 
862     bind
863 }
864 
map_feature_level_to_shader_model(feature: u32) -> hlsl::ShaderModel865 pub fn map_feature_level_to_shader_model(feature: u32) -> hlsl::ShaderModel {
866     match feature {
867         D3D_FEATURE_LEVEL_9_1 | D3D_FEATURE_LEVEL_9_2 => hlsl::ShaderModel::V4_0L9_1,
868         D3D_FEATURE_LEVEL_9_3 => hlsl::ShaderModel::V4_0L9_3,
869         D3D_FEATURE_LEVEL_10_0 => hlsl::ShaderModel::V4_0,
870         D3D_FEATURE_LEVEL_10_1 => hlsl::ShaderModel::V4_1,
871         D3D_FEATURE_LEVEL_11_0 | D3D_FEATURE_LEVEL_11_1 => hlsl::ShaderModel::V5_0,
872         _ => unimplemented!(),
873     }
874 }
875