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