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