1 use hal::{
2 command,
3 image,
4 pso,
5 pso::{Stage, Viewport},
6 };
7
8 use winapi::{
9 shared::{
10 dxgiformat,
11 minwindef::{FALSE, TRUE},
12 winerror,
13 },
14 um::{d3d11, d3dcommon},
15 };
16
17 use wio::com::ComPtr;
18
19 use std::{borrow::Borrow, mem, ptr};
20
21 use smallvec::SmallVec;
22 use spirv_cross;
23
24 use crate::{conv, shader, Buffer, Image, RenderPassCache};
25
26 #[repr(C)]
27 struct BufferCopy {
28 src: u32,
29 dst: u32,
30 _padding: [u32; 2],
31 }
32
33 #[repr(C)]
34 struct ImageCopy {
35 src: [u32; 4],
36 dst: [u32; 4],
37 }
38
39 #[repr(C)]
40 struct BufferImageCopy {
41 buffer_offset: u32,
42 buffer_size: [u32; 2],
43 _padding: u32,
44 image_offset: [u32; 4],
45 image_extent: [u32; 4],
46 // actual size of the target image
47 image_size: [u32; 4],
48 }
49
50 #[repr(C)]
51 struct BufferImageCopyInfo {
52 buffer: BufferCopy,
53 image: ImageCopy,
54 buffer_image: BufferImageCopy,
55 }
56
57 #[repr(C)]
58 struct BlitInfo {
59 offset: [f32; 2],
60 extent: [f32; 2],
61 z: f32,
62 level: f32,
63 }
64
65 #[repr(C)]
66 struct PartialClearInfo {
67 // transmute between the types, easier than juggling all different kinds of fields..
68 data: [u32; 4],
69 }
70
71 // the threadgroup count we use in our copy shaders
72 const COPY_THREAD_GROUP_X: u32 = 8;
73 const COPY_THREAD_GROUP_Y: u32 = 8;
74
75 // Holds everything we need for fallback implementations of features that are not in DX.
76 //
77 // TODO: maybe get rid of `Clone`? there's _a lot_ of refcounts here and it is used as a singleton
78 // anyway :s
79 //
80 // TODO: make struct fields more modular and group them up in structs depending on if it is a
81 // fallback version or not (eg. Option<PartialClear>), should make struct definition and
82 // `new` function smaller
83 #[derive(Clone, Debug)]
84 pub struct Internal {
85 // partial clearing
86 vs_partial_clear: ComPtr<d3d11::ID3D11VertexShader>,
87 ps_partial_clear_float: ComPtr<d3d11::ID3D11PixelShader>,
88 ps_partial_clear_uint: ComPtr<d3d11::ID3D11PixelShader>,
89 ps_partial_clear_int: ComPtr<d3d11::ID3D11PixelShader>,
90 ps_partial_clear_depth: ComPtr<d3d11::ID3D11PixelShader>,
91 ps_partial_clear_stencil: ComPtr<d3d11::ID3D11PixelShader>,
92 partial_clear_depth_stencil_state: ComPtr<d3d11::ID3D11DepthStencilState>,
93 partial_clear_depth_state: ComPtr<d3d11::ID3D11DepthStencilState>,
94 partial_clear_stencil_state: ComPtr<d3d11::ID3D11DepthStencilState>,
95
96 // blitting
97 vs_blit_2d: ComPtr<d3d11::ID3D11VertexShader>,
98
99 sampler_nearest: ComPtr<d3d11::ID3D11SamplerState>,
100 sampler_linear: ComPtr<d3d11::ID3D11SamplerState>,
101
102 ps_blit_2d_uint: ComPtr<d3d11::ID3D11PixelShader>,
103 ps_blit_2d_int: ComPtr<d3d11::ID3D11PixelShader>,
104 ps_blit_2d_float: ComPtr<d3d11::ID3D11PixelShader>,
105
106 // Image<->Image not covered by `CopySubresourceRegion`
107 cs_copy_image2d_r8g8_image2d_r16: ComPtr<d3d11::ID3D11ComputeShader>,
108 cs_copy_image2d_r16_image2d_r8g8: ComPtr<d3d11::ID3D11ComputeShader>,
109
110 cs_copy_image2d_r8g8b8a8_image2d_r32: ComPtr<d3d11::ID3D11ComputeShader>,
111 cs_copy_image2d_r8g8b8a8_image2d_r16g16: ComPtr<d3d11::ID3D11ComputeShader>,
112 cs_copy_image2d_r16g16_image2d_r32: ComPtr<d3d11::ID3D11ComputeShader>,
113 cs_copy_image2d_r16g16_image2d_r8g8b8a8: ComPtr<d3d11::ID3D11ComputeShader>,
114 cs_copy_image2d_r32_image2d_r16g16: ComPtr<d3d11::ID3D11ComputeShader>,
115 cs_copy_image2d_r32_image2d_r8g8b8a8: ComPtr<d3d11::ID3D11ComputeShader>,
116
117 // Image -> Buffer
118 cs_copy_image2d_r32g32b32a32_buffer: ComPtr<d3d11::ID3D11ComputeShader>,
119 cs_copy_image2d_r32g32_buffer: ComPtr<d3d11::ID3D11ComputeShader>,
120 cs_copy_image2d_r16g16b16a16_buffer: ComPtr<d3d11::ID3D11ComputeShader>,
121 cs_copy_image2d_r32_buffer: ComPtr<d3d11::ID3D11ComputeShader>,
122 cs_copy_image2d_r16g16_buffer: ComPtr<d3d11::ID3D11ComputeShader>,
123 cs_copy_image2d_r8g8b8a8_buffer: ComPtr<d3d11::ID3D11ComputeShader>,
124 cs_copy_image2d_r16_buffer: ComPtr<d3d11::ID3D11ComputeShader>,
125 cs_copy_image2d_r8g8_buffer: ComPtr<d3d11::ID3D11ComputeShader>,
126 cs_copy_image2d_r8_buffer: ComPtr<d3d11::ID3D11ComputeShader>,
127 cs_copy_image2d_b8g8r8a8_buffer: ComPtr<d3d11::ID3D11ComputeShader>,
128
129 // Buffer -> Image
130 cs_copy_buffer_image2d_r32g32b32a32: ComPtr<d3d11::ID3D11ComputeShader>,
131 cs_copy_buffer_image2d_r32g32: ComPtr<d3d11::ID3D11ComputeShader>,
132 cs_copy_buffer_image2d_r16g16b16a16: ComPtr<d3d11::ID3D11ComputeShader>,
133 cs_copy_buffer_image2d_r32: ComPtr<d3d11::ID3D11ComputeShader>,
134 cs_copy_buffer_image2d_r16g16: ComPtr<d3d11::ID3D11ComputeShader>,
135 cs_copy_buffer_image2d_r8g8b8a8: ComPtr<d3d11::ID3D11ComputeShader>,
136 cs_copy_buffer_image2d_r16: ComPtr<d3d11::ID3D11ComputeShader>,
137 cs_copy_buffer_image2d_r8g8: ComPtr<d3d11::ID3D11ComputeShader>,
138 cs_copy_buffer_image2d_r8: ComPtr<d3d11::ID3D11ComputeShader>,
139
140 // internal constant buffer that is used by internal shaders
141 internal_buffer: ComPtr<d3d11::ID3D11Buffer>,
142
143 // public buffer that is used as intermediate storage for some operations (memory invalidation)
144 pub working_buffer: ComPtr<d3d11::ID3D11Buffer>,
145 pub working_buffer_size: u64,
146 }
147
compile_blob(src: &[u8], entrypoint: &str, stage: Stage) -> ComPtr<d3dcommon::ID3DBlob>148 fn compile_blob(src: &[u8], entrypoint: &str, stage: Stage) -> ComPtr<d3dcommon::ID3DBlob> {
149 unsafe {
150 ComPtr::from_raw(
151 shader::compile_hlsl_shader(
152 stage,
153 spirv_cross::hlsl::ShaderModel::V5_0,
154 entrypoint,
155 src,
156 )
157 .unwrap(),
158 )
159 }
160 }
161
compile_vs( device: &ComPtr<d3d11::ID3D11Device>, src: &[u8], entrypoint: &str, ) -> ComPtr<d3d11::ID3D11VertexShader>162 fn compile_vs(
163 device: &ComPtr<d3d11::ID3D11Device>,
164 src: &[u8],
165 entrypoint: &str,
166 ) -> ComPtr<d3d11::ID3D11VertexShader> {
167 let bytecode = compile_blob(src, entrypoint, Stage::Vertex);
168 let mut shader = ptr::null_mut();
169 let hr = unsafe {
170 device.CreateVertexShader(
171 bytecode.GetBufferPointer(),
172 bytecode.GetBufferSize(),
173 ptr::null_mut(),
174 &mut shader as *mut *mut _ as *mut *mut _,
175 )
176 };
177 assert_eq!(true, winerror::SUCCEEDED(hr));
178
179 unsafe { ComPtr::from_raw(shader) }
180 }
181
compile_ps( device: &ComPtr<d3d11::ID3D11Device>, src: &[u8], entrypoint: &str, ) -> ComPtr<d3d11::ID3D11PixelShader>182 fn compile_ps(
183 device: &ComPtr<d3d11::ID3D11Device>,
184 src: &[u8],
185 entrypoint: &str,
186 ) -> ComPtr<d3d11::ID3D11PixelShader> {
187 let bytecode = compile_blob(src, entrypoint, Stage::Fragment);
188 let mut shader = ptr::null_mut();
189 let hr = unsafe {
190 device.CreatePixelShader(
191 bytecode.GetBufferPointer(),
192 bytecode.GetBufferSize(),
193 ptr::null_mut(),
194 &mut shader as *mut *mut _ as *mut *mut _,
195 )
196 };
197 assert_eq!(true, winerror::SUCCEEDED(hr));
198
199 unsafe { ComPtr::from_raw(shader) }
200 }
201
compile_cs( device: &ComPtr<d3d11::ID3D11Device>, src: &[u8], entrypoint: &str, ) -> ComPtr<d3d11::ID3D11ComputeShader>202 fn compile_cs(
203 device: &ComPtr<d3d11::ID3D11Device>,
204 src: &[u8],
205 entrypoint: &str,
206 ) -> ComPtr<d3d11::ID3D11ComputeShader> {
207 let bytecode = compile_blob(src, entrypoint, Stage::Compute);
208 let mut shader = ptr::null_mut();
209 let hr = unsafe {
210 device.CreateComputeShader(
211 bytecode.GetBufferPointer(),
212 bytecode.GetBufferSize(),
213 ptr::null_mut(),
214 &mut shader as *mut *mut _ as *mut *mut _,
215 )
216 };
217 assert_eq!(true, winerror::SUCCEEDED(hr));
218
219 unsafe { ComPtr::from_raw(shader) }
220 }
221
222 impl Internal {
new(device: &ComPtr<d3d11::ID3D11Device>) -> Self223 pub fn new(device: &ComPtr<d3d11::ID3D11Device>) -> Self {
224 let internal_buffer = {
225 let desc = d3d11::D3D11_BUFFER_DESC {
226 ByteWidth: mem::size_of::<BufferImageCopyInfo>() as _,
227 Usage: d3d11::D3D11_USAGE_DYNAMIC,
228 BindFlags: d3d11::D3D11_BIND_CONSTANT_BUFFER,
229 CPUAccessFlags: d3d11::D3D11_CPU_ACCESS_WRITE,
230 MiscFlags: 0,
231 StructureByteStride: 0,
232 };
233
234 let mut buffer = ptr::null_mut();
235 let hr = unsafe {
236 device.CreateBuffer(
237 &desc,
238 ptr::null_mut(),
239 &mut buffer as *mut *mut _ as *mut *mut _,
240 )
241 };
242 assert_eq!(true, winerror::SUCCEEDED(hr));
243
244 unsafe { ComPtr::from_raw(buffer) }
245 };
246
247 let (depth_stencil_state, depth_state, stencil_state) = {
248 let mut depth_state = ptr::null_mut();
249 let mut stencil_state = ptr::null_mut();
250 let mut depth_stencil_state = ptr::null_mut();
251
252 let mut desc = d3d11::D3D11_DEPTH_STENCIL_DESC {
253 DepthEnable: TRUE,
254 DepthWriteMask: d3d11::D3D11_DEPTH_WRITE_MASK_ALL,
255 DepthFunc: d3d11::D3D11_COMPARISON_ALWAYS,
256 StencilEnable: TRUE,
257 StencilReadMask: 0,
258 StencilWriteMask: !0,
259 FrontFace: d3d11::D3D11_DEPTH_STENCILOP_DESC {
260 StencilFailOp: d3d11::D3D11_STENCIL_OP_REPLACE,
261 StencilDepthFailOp: d3d11::D3D11_STENCIL_OP_REPLACE,
262 StencilPassOp: d3d11::D3D11_STENCIL_OP_REPLACE,
263 StencilFunc: d3d11::D3D11_COMPARISON_ALWAYS,
264 },
265 BackFace: d3d11::D3D11_DEPTH_STENCILOP_DESC {
266 StencilFailOp: d3d11::D3D11_STENCIL_OP_REPLACE,
267 StencilDepthFailOp: d3d11::D3D11_STENCIL_OP_REPLACE,
268 StencilPassOp: d3d11::D3D11_STENCIL_OP_REPLACE,
269 StencilFunc: d3d11::D3D11_COMPARISON_ALWAYS,
270 },
271 };
272
273 let hr = unsafe {
274 device.CreateDepthStencilState(
275 &desc,
276 &mut depth_stencil_state as *mut *mut _ as *mut *mut _,
277 )
278 };
279 assert_eq!(winerror::S_OK, hr);
280
281 desc.DepthEnable = TRUE;
282 desc.StencilEnable = FALSE;
283
284 let hr = unsafe {
285 device
286 .CreateDepthStencilState(&desc, &mut depth_state as *mut *mut _ as *mut *mut _)
287 };
288 assert_eq!(winerror::S_OK, hr);
289
290 desc.DepthEnable = FALSE;
291 desc.StencilEnable = TRUE;
292
293 let hr = unsafe {
294 device.CreateDepthStencilState(
295 &desc,
296 &mut stencil_state as *mut *mut _ as *mut *mut _,
297 )
298 };
299 assert_eq!(winerror::S_OK, hr);
300
301 unsafe {
302 (
303 ComPtr::from_raw(depth_stencil_state),
304 ComPtr::from_raw(depth_state),
305 ComPtr::from_raw(stencil_state),
306 )
307 }
308 };
309
310 let (sampler_nearest, sampler_linear) = {
311 let mut desc = d3d11::D3D11_SAMPLER_DESC {
312 Filter: d3d11::D3D11_FILTER_MIN_MAG_MIP_POINT,
313 AddressU: d3d11::D3D11_TEXTURE_ADDRESS_CLAMP,
314 AddressV: d3d11::D3D11_TEXTURE_ADDRESS_CLAMP,
315 AddressW: d3d11::D3D11_TEXTURE_ADDRESS_CLAMP,
316 MipLODBias: 0f32,
317 MaxAnisotropy: 0,
318 ComparisonFunc: 0,
319 BorderColor: [0f32; 4],
320 MinLOD: 0f32,
321 MaxLOD: d3d11::D3D11_FLOAT32_MAX,
322 };
323
324 let mut nearest = ptr::null_mut();
325 let mut linear = ptr::null_mut();
326
327 assert_eq!(winerror::S_OK, unsafe {
328 device.CreateSamplerState(&desc, &mut nearest as *mut *mut _ as *mut *mut _)
329 });
330
331 desc.Filter = d3d11::D3D11_FILTER_MIN_MAG_MIP_LINEAR;
332
333 assert_eq!(winerror::S_OK, unsafe {
334 device.CreateSamplerState(&desc, &mut linear as *mut *mut _ as *mut *mut _)
335 });
336
337 unsafe { (ComPtr::from_raw(nearest), ComPtr::from_raw(linear)) }
338 };
339
340 let (working_buffer, working_buffer_size) = {
341 let working_buffer_size = 1 << 16;
342
343 let desc = d3d11::D3D11_BUFFER_DESC {
344 ByteWidth: working_buffer_size,
345 Usage: d3d11::D3D11_USAGE_STAGING,
346 BindFlags: 0,
347 CPUAccessFlags: d3d11::D3D11_CPU_ACCESS_READ | d3d11::D3D11_CPU_ACCESS_WRITE,
348 MiscFlags: 0,
349 StructureByteStride: 0,
350 };
351 let mut working_buffer = ptr::null_mut();
352
353 assert_eq!(winerror::S_OK, unsafe {
354 device.CreateBuffer(
355 &desc,
356 ptr::null_mut(),
357 &mut working_buffer as *mut *mut _ as *mut *mut _,
358 )
359 });
360
361 (
362 unsafe { ComPtr::from_raw(working_buffer) },
363 working_buffer_size,
364 )
365 };
366
367 let clear_shaders = include_bytes!("../shaders/clear.hlsl");
368 let copy_shaders = include_bytes!("../shaders/copy.hlsl");
369 let blit_shaders = include_bytes!("../shaders/blit.hlsl");
370
371 Internal {
372 vs_partial_clear: compile_vs(device, clear_shaders, "vs_partial_clear"),
373 ps_partial_clear_float: compile_ps(device, clear_shaders, "ps_partial_clear_float"),
374 ps_partial_clear_uint: compile_ps(device, clear_shaders, "ps_partial_clear_uint"),
375 ps_partial_clear_int: compile_ps(device, clear_shaders, "ps_partial_clear_int"),
376 ps_partial_clear_depth: compile_ps(device, clear_shaders, "ps_partial_clear_depth"),
377 ps_partial_clear_stencil: compile_ps(device, clear_shaders, "ps_partial_clear_stencil"),
378 partial_clear_depth_stencil_state: depth_stencil_state,
379 partial_clear_depth_state: depth_state,
380 partial_clear_stencil_state: stencil_state,
381
382 vs_blit_2d: compile_vs(device, blit_shaders, "vs_blit_2d"),
383
384 sampler_nearest,
385 sampler_linear,
386
387 ps_blit_2d_uint: compile_ps(device, blit_shaders, "ps_blit_2d_uint"),
388 ps_blit_2d_int: compile_ps(device, blit_shaders, "ps_blit_2d_int"),
389 ps_blit_2d_float: compile_ps(device, blit_shaders, "ps_blit_2d_float"),
390
391 cs_copy_image2d_r8g8_image2d_r16: compile_cs(
392 device,
393 copy_shaders,
394 "cs_copy_image2d_r8g8_image2d_r16",
395 ),
396 cs_copy_image2d_r16_image2d_r8g8: compile_cs(
397 device,
398 copy_shaders,
399 "cs_copy_image2d_r16_image2d_r8g8",
400 ),
401
402 cs_copy_image2d_r8g8b8a8_image2d_r32: compile_cs(
403 device,
404 copy_shaders,
405 "cs_copy_image2d_r8g8b8a8_image2d_r32",
406 ),
407 cs_copy_image2d_r8g8b8a8_image2d_r16g16: compile_cs(
408 device,
409 copy_shaders,
410 "cs_copy_image2d_r8g8b8a8_image2d_r16g16",
411 ),
412 cs_copy_image2d_r16g16_image2d_r32: compile_cs(
413 device,
414 copy_shaders,
415 "cs_copy_image2d_r16g16_image2d_r32",
416 ),
417 cs_copy_image2d_r16g16_image2d_r8g8b8a8: compile_cs(
418 device,
419 copy_shaders,
420 "cs_copy_image2d_r16g16_image2d_r8g8b8a8",
421 ),
422 cs_copy_image2d_r32_image2d_r16g16: compile_cs(
423 device,
424 copy_shaders,
425 "cs_copy_image2d_r32_image2d_r16g16",
426 ),
427 cs_copy_image2d_r32_image2d_r8g8b8a8: compile_cs(
428 device,
429 copy_shaders,
430 "cs_copy_image2d_r32_image2d_r8g8b8a8",
431 ),
432
433 cs_copy_image2d_r32g32b32a32_buffer: compile_cs(
434 device,
435 copy_shaders,
436 "cs_copy_image2d_r32g32b32a32_buffer",
437 ),
438 cs_copy_image2d_r32g32_buffer: compile_cs(
439 device,
440 copy_shaders,
441 "cs_copy_image2d_r32g32_buffer",
442 ),
443 cs_copy_image2d_r16g16b16a16_buffer: compile_cs(
444 device,
445 copy_shaders,
446 "cs_copy_image2d_r16g16b16a16_buffer",
447 ),
448 cs_copy_image2d_r32_buffer: compile_cs(
449 device,
450 copy_shaders,
451 "cs_copy_image2d_r32_buffer",
452 ),
453 cs_copy_image2d_r16g16_buffer: compile_cs(
454 device,
455 copy_shaders,
456 "cs_copy_image2d_r16g16_buffer",
457 ),
458 cs_copy_image2d_r8g8b8a8_buffer: compile_cs(
459 device,
460 copy_shaders,
461 "cs_copy_image2d_r8g8b8a8_buffer",
462 ),
463 cs_copy_image2d_r16_buffer: compile_cs(
464 device,
465 copy_shaders,
466 "cs_copy_image2d_r16_buffer",
467 ),
468 cs_copy_image2d_r8g8_buffer: compile_cs(
469 device,
470 copy_shaders,
471 "cs_copy_image2d_r8g8_buffer",
472 ),
473 cs_copy_image2d_r8_buffer: compile_cs(
474 device,
475 copy_shaders,
476 "cs_copy_image2d_r8_buffer",
477 ),
478 cs_copy_image2d_b8g8r8a8_buffer: compile_cs(
479 device,
480 copy_shaders,
481 "cs_copy_image2d_b8g8r8a8_buffer",
482 ),
483
484 cs_copy_buffer_image2d_r32g32b32a32: compile_cs(
485 device,
486 copy_shaders,
487 "cs_copy_buffer_image2d_r32g32b32a32",
488 ),
489 cs_copy_buffer_image2d_r32g32: compile_cs(
490 device,
491 copy_shaders,
492 "cs_copy_buffer_image2d_r32g32",
493 ),
494 cs_copy_buffer_image2d_r16g16b16a16: compile_cs(
495 device,
496 copy_shaders,
497 "cs_copy_buffer_image2d_r16g16b16a16",
498 ),
499 cs_copy_buffer_image2d_r32: compile_cs(
500 device,
501 copy_shaders,
502 "cs_copy_buffer_image2d_r32",
503 ),
504 cs_copy_buffer_image2d_r16g16: compile_cs(
505 device,
506 copy_shaders,
507 "cs_copy_buffer_image2d_r16g16",
508 ),
509 cs_copy_buffer_image2d_r8g8b8a8: compile_cs(
510 device,
511 copy_shaders,
512 "cs_copy_buffer_image2d_r8g8b8a8",
513 ),
514 cs_copy_buffer_image2d_r16: compile_cs(
515 device,
516 copy_shaders,
517 "cs_copy_buffer_image2d_r16",
518 ),
519 cs_copy_buffer_image2d_r8g8: compile_cs(
520 device,
521 copy_shaders,
522 "cs_copy_buffer_image2d_r8g8",
523 ),
524 cs_copy_buffer_image2d_r8: compile_cs(
525 device,
526 copy_shaders,
527 "cs_copy_buffer_image2d_r8",
528 ),
529
530 internal_buffer,
531 working_buffer,
532 working_buffer_size: working_buffer_size as _,
533 }
534 }
535
map(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>) -> *mut u8536 fn map(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>) -> *mut u8 {
537 let mut mapped = unsafe { mem::zeroed::<d3d11::D3D11_MAPPED_SUBRESOURCE>() };
538 let hr = unsafe {
539 context.Map(
540 self.internal_buffer.as_raw() as _,
541 0,
542 d3d11::D3D11_MAP_WRITE_DISCARD,
543 0,
544 &mut mapped,
545 )
546 };
547
548 assert_eq!(winerror::S_OK, hr);
549
550 mapped.pData as _
551 }
552
unmap(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>)553 fn unmap(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>) {
554 unsafe {
555 context.Unmap(self.internal_buffer.as_raw() as _, 0);
556 }
557 }
558
update_image( &mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>, info: &command::ImageCopy, )559 fn update_image(
560 &mut self,
561 context: &ComPtr<d3d11::ID3D11DeviceContext>,
562 info: &command::ImageCopy,
563 ) {
564 unsafe {
565 ptr::copy(
566 &BufferImageCopyInfo {
567 image: ImageCopy {
568 src: [
569 info.src_offset.x as _,
570 info.src_offset.y as _,
571 info.src_offset.z as _,
572 0,
573 ],
574 dst: [
575 info.dst_offset.x as _,
576 info.dst_offset.y as _,
577 info.dst_offset.z as _,
578 0,
579 ],
580 },
581 ..mem::zeroed()
582 },
583 self.map(context) as *mut _,
584 1,
585 )
586 };
587
588 self.unmap(context);
589 }
590
update_buffer_image( &mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>, info: &command::BufferImageCopy, image: &Image, )591 fn update_buffer_image(
592 &mut self,
593 context: &ComPtr<d3d11::ID3D11DeviceContext>,
594 info: &command::BufferImageCopy,
595 image: &Image,
596 ) {
597 let size = image.kind.extent();
598
599 unsafe {
600 ptr::copy(
601 &BufferImageCopyInfo {
602 buffer_image: BufferImageCopy {
603 buffer_offset: info.buffer_offset as _,
604 buffer_size: [info.buffer_width, info.buffer_height],
605 _padding: 0,
606 image_offset: [
607 info.image_offset.x as _,
608 info.image_offset.y as _,
609 (info.image_offset.z + info.image_layers.layers.start as i32) as _,
610 0,
611 ],
612 image_extent: [
613 info.image_extent.width,
614 info.image_extent.height,
615 info.image_extent.depth,
616 0,
617 ],
618 image_size: [size.width, size.height, size.depth, 0],
619 },
620 ..mem::zeroed()
621 },
622 self.map(context) as *mut _,
623 1,
624 )
625 };
626
627 self.unmap(context);
628 }
629
update_blit( &mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>, src: &Image, info: &command::ImageBlit, )630 fn update_blit(
631 &mut self,
632 context: &ComPtr<d3d11::ID3D11DeviceContext>,
633 src: &Image,
634 info: &command::ImageBlit,
635 ) {
636 let (sx, dx) = if info.dst_bounds.start.x > info.dst_bounds.end.x {
637 (
638 info.src_bounds.end.x,
639 info.src_bounds.start.x - info.src_bounds.end.x,
640 )
641 } else {
642 (
643 info.src_bounds.start.x,
644 info.src_bounds.end.x - info.src_bounds.start.x,
645 )
646 };
647 let (sy, dy) = if info.dst_bounds.start.y > info.dst_bounds.end.y {
648 (
649 info.src_bounds.end.y,
650 info.src_bounds.start.y - info.src_bounds.end.y,
651 )
652 } else {
653 (
654 info.src_bounds.start.y,
655 info.src_bounds.end.y - info.src_bounds.start.y,
656 )
657 };
658 let image::Extent { width, height, .. } = src.kind.level_extent(info.src_subresource.level);
659
660 unsafe {
661 ptr::copy(
662 &BlitInfo {
663 offset: [sx as f32 / width as f32, sy as f32 / height as f32],
664 extent: [dx as f32 / width as f32, dy as f32 / height as f32],
665 z: 0f32, // TODO
666 level: info.src_subresource.level as _,
667 },
668 self.map(context) as *mut _,
669 1,
670 )
671 };
672
673 self.unmap(context);
674 }
675
update_clear_color( &mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>, value: command::ClearColor, )676 fn update_clear_color(
677 &mut self,
678 context: &ComPtr<d3d11::ID3D11DeviceContext>,
679 value: command::ClearColor,
680 ) {
681 unsafe {
682 ptr::copy(
683 &PartialClearInfo {
684 data: mem::transmute(value),
685 },
686 self.map(context) as *mut _,
687 1,
688 )
689 };
690
691 self.unmap(context);
692 }
693
update_clear_depth_stencil( &mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>, depth: Option<f32>, stencil: Option<u32>, )694 fn update_clear_depth_stencil(
695 &mut self,
696 context: &ComPtr<d3d11::ID3D11DeviceContext>,
697 depth: Option<f32>,
698 stencil: Option<u32>,
699 ) {
700 unsafe {
701 ptr::copy(
702 &PartialClearInfo {
703 data: [
704 mem::transmute(depth.unwrap_or(0f32)),
705 stencil.unwrap_or(0),
706 0,
707 0,
708 ],
709 },
710 self.map(context) as *mut _,
711 1,
712 );
713 }
714
715 self.unmap(context);
716 }
717
find_image_copy_shader( &self, src: &Image, dst: &Image, ) -> Option<*mut d3d11::ID3D11ComputeShader>718 fn find_image_copy_shader(
719 &self,
720 src: &Image,
721 dst: &Image,
722 ) -> Option<*mut d3d11::ID3D11ComputeShader> {
723 use dxgiformat::*;
724
725 let src_format = src.decomposed_format.copy_srv.unwrap();
726 let dst_format = dst.decomposed_format.copy_uav.unwrap();
727
728 match (src_format, dst_format) {
729 (DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R16_UINT) => {
730 Some(self.cs_copy_image2d_r8g8_image2d_r16.as_raw())
731 }
732 (DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R8G8_UINT) => {
733 Some(self.cs_copy_image2d_r16_image2d_r8g8.as_raw())
734 }
735 (DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R32_UINT) => {
736 Some(self.cs_copy_image2d_r8g8b8a8_image2d_r32.as_raw())
737 }
738 (DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R16G16_UINT) => {
739 Some(self.cs_copy_image2d_r8g8b8a8_image2d_r16g16.as_raw())
740 }
741 (DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R32_UINT) => {
742 Some(self.cs_copy_image2d_r16g16_image2d_r32.as_raw())
743 }
744 (DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R8G8B8A8_UINT) => {
745 Some(self.cs_copy_image2d_r16g16_image2d_r8g8b8a8.as_raw())
746 }
747 (DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R16G16_UINT) => {
748 Some(self.cs_copy_image2d_r32_image2d_r16g16.as_raw())
749 }
750 (DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R8G8B8A8_UINT) => {
751 Some(self.cs_copy_image2d_r32_image2d_r8g8b8a8.as_raw())
752 }
753 _ => None,
754 }
755 }
756
copy_image_2d<T>( &mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>, src: &Image, dst: &Image, regions: T, ) where T: IntoIterator, T::Item: Borrow<command::ImageCopy>,757 pub fn copy_image_2d<T>(
758 &mut self,
759 context: &ComPtr<d3d11::ID3D11DeviceContext>,
760 src: &Image,
761 dst: &Image,
762 regions: T,
763 ) where
764 T: IntoIterator,
765 T::Item: Borrow<command::ImageCopy>,
766 {
767 if let Some(shader) = self.find_image_copy_shader(src, dst) {
768 // Some formats cant go through default path, since they cant
769 // be cast between formats of different component types (eg.
770 // Rg16 <-> Rgba8)
771
772 // TODO: subresources
773 let srv = src.internal.copy_srv.clone().unwrap().as_raw();
774
775 unsafe {
776 context.CSSetShader(shader, ptr::null_mut(), 0);
777 context.CSSetConstantBuffers(0, 1, &self.internal_buffer.as_raw());
778 context.CSSetShaderResources(0, 1, [srv].as_ptr());
779
780 for region in regions.into_iter() {
781 let info = region.borrow();
782 self.update_image(context, &info);
783
784 let uav = dst.get_uav(info.dst_subresource.level, 0).unwrap().as_raw();
785 context.CSSetUnorderedAccessViews(0, 1, [uav].as_ptr(), ptr::null_mut());
786
787 context.Dispatch(info.extent.width as u32, info.extent.height as u32, 1);
788 }
789
790 // unbind external resources
791 context.CSSetShaderResources(0, 1, [ptr::null_mut(); 1].as_ptr());
792 context.CSSetUnorderedAccessViews(
793 0,
794 1,
795 [ptr::null_mut(); 1].as_ptr(),
796 ptr::null_mut(),
797 );
798 }
799 } else {
800 // Default copy path
801 for region in regions.into_iter() {
802 let info = region.borrow();
803
804 // TODO: layer subresources
805 unsafe {
806 context.CopySubresourceRegion(
807 dst.internal.raw,
808 src.calc_subresource(info.src_subresource.level as _, 0),
809 info.dst_offset.x as _,
810 info.dst_offset.y as _,
811 info.dst_offset.z as _,
812 src.internal.raw,
813 dst.calc_subresource(info.dst_subresource.level as _, 0),
814 &d3d11::D3D11_BOX {
815 left: info.src_offset.x as _,
816 top: info.src_offset.y as _,
817 front: info.src_offset.z as _,
818 right: info.src_offset.x as u32 + info.extent.width as u32,
819 bottom: info.src_offset.y as u32 + info.extent.height as u32,
820 back: info.src_offset.z as u32 + info.extent.depth as u32,
821 },
822 );
823 }
824 }
825 }
826 }
827
find_image_to_buffer_shader( &self, format: dxgiformat::DXGI_FORMAT, ) -> Option<(*mut d3d11::ID3D11ComputeShader, u32, u32)>828 fn find_image_to_buffer_shader(
829 &self,
830 format: dxgiformat::DXGI_FORMAT,
831 ) -> Option<(*mut d3d11::ID3D11ComputeShader, u32, u32)> {
832 use dxgiformat::*;
833
834 match format {
835 DXGI_FORMAT_R32G32B32A32_UINT => {
836 Some((self.cs_copy_image2d_r32g32b32a32_buffer.as_raw(), 1, 1))
837 }
838 DXGI_FORMAT_R32G32_UINT => Some((self.cs_copy_image2d_r32g32_buffer.as_raw(), 1, 1)),
839 DXGI_FORMAT_R16G16B16A16_UINT => {
840 Some((self.cs_copy_image2d_r16g16b16a16_buffer.as_raw(), 1, 1))
841 }
842 DXGI_FORMAT_R32_UINT => Some((self.cs_copy_image2d_r32_buffer.as_raw(), 1, 1)),
843 DXGI_FORMAT_R16G16_UINT => Some((self.cs_copy_image2d_r16g16_buffer.as_raw(), 1, 1)),
844 DXGI_FORMAT_R8G8B8A8_UINT => {
845 Some((self.cs_copy_image2d_r8g8b8a8_buffer.as_raw(), 1, 1))
846 }
847 DXGI_FORMAT_R16_UINT => Some((self.cs_copy_image2d_r16_buffer.as_raw(), 2, 1)),
848 DXGI_FORMAT_R8G8_UINT => Some((self.cs_copy_image2d_r8g8_buffer.as_raw(), 2, 1)),
849 DXGI_FORMAT_R8_UINT => Some((self.cs_copy_image2d_r8_buffer.as_raw(), 4, 1)),
850 DXGI_FORMAT_B8G8R8A8_UNORM => {
851 Some((self.cs_copy_image2d_b8g8r8a8_buffer.as_raw(), 1, 1))
852 }
853 _ => None,
854 }
855 }
856
copy_image_2d_to_buffer<T>( &mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>, src: &Image, dst: &Buffer, regions: T, ) where T: IntoIterator, T::Item: Borrow<command::BufferImageCopy>,857 pub fn copy_image_2d_to_buffer<T>(
858 &mut self,
859 context: &ComPtr<d3d11::ID3D11DeviceContext>,
860 src: &Image,
861 dst: &Buffer,
862 regions: T,
863 ) where
864 T: IntoIterator,
865 T::Item: Borrow<command::BufferImageCopy>,
866 {
867 let _scope = debug_scope!(
868 context,
869 "Image (format={:?},kind={:?}) => Buffer",
870 src.format,
871 src.kind
872 );
873 let (shader, scale_x, scale_y) = self
874 .find_image_to_buffer_shader(src.decomposed_format.copy_srv.unwrap())
875 .unwrap();
876
877 let srv = src.internal.copy_srv.clone().unwrap().as_raw();
878 let uav = dst.internal.uav.unwrap();
879 let format_desc = src.format.base_format().0.desc();
880 let bytes_per_texel = format_desc.bits as u32 / 8;
881
882 unsafe {
883 context.CSSetShader(shader, ptr::null_mut(), 0);
884 context.CSSetConstantBuffers(0, 1, &self.internal_buffer.as_raw());
885
886 context.CSSetShaderResources(0, 1, [srv].as_ptr());
887 context.CSSetUnorderedAccessViews(0, 1, [uav].as_ptr(), ptr::null_mut());
888
889 for copy in regions {
890 let copy = copy.borrow();
891 self.update_buffer_image(context, ©, src);
892
893 debug_marker!(context, "{:?}", copy);
894
895 context.Dispatch(
896 ((copy.image_extent.width + (COPY_THREAD_GROUP_X - 1))
897 / COPY_THREAD_GROUP_X
898 / scale_x)
899 .max(1),
900 ((copy.image_extent.height + (COPY_THREAD_GROUP_X - 1))
901 / COPY_THREAD_GROUP_Y
902 / scale_y)
903 .max(1),
904 1,
905 );
906
907 if let Some(disjoint_cb) = dst.internal.disjoint_cb {
908 let total_size = copy.image_extent.depth
909 * (copy.buffer_height * copy.buffer_width * bytes_per_texel);
910 let copy_box = d3d11::D3D11_BOX {
911 left: copy.buffer_offset as u32,
912 top: 0,
913 front: 0,
914 right: copy.buffer_offset as u32 + total_size,
915 bottom: 1,
916 back: 1,
917 };
918
919 context.CopySubresourceRegion(
920 disjoint_cb as _,
921 0,
922 copy.buffer_offset as _,
923 0,
924 0,
925 dst.internal.raw as _,
926 0,
927 ©_box,
928 );
929 }
930 }
931
932 // unbind external resources
933 context.CSSetShaderResources(0, 1, [ptr::null_mut(); 1].as_ptr());
934 context.CSSetUnorderedAccessViews(0, 1, [ptr::null_mut(); 1].as_ptr(), ptr::null_mut());
935 }
936 }
937
find_buffer_to_image_shader( &self, format: dxgiformat::DXGI_FORMAT, ) -> Option<(*mut d3d11::ID3D11ComputeShader, u32, u32)>938 fn find_buffer_to_image_shader(
939 &self,
940 format: dxgiformat::DXGI_FORMAT,
941 ) -> Option<(*mut d3d11::ID3D11ComputeShader, u32, u32)> {
942 use dxgiformat::*;
943
944 match format {
945 DXGI_FORMAT_R32G32B32A32_UINT => {
946 Some((self.cs_copy_buffer_image2d_r32g32b32a32.as_raw(), 1, 1))
947 }
948 DXGI_FORMAT_R32G32_UINT => Some((self.cs_copy_buffer_image2d_r32g32.as_raw(), 1, 1)),
949 DXGI_FORMAT_R16G16B16A16_UINT => {
950 Some((self.cs_copy_buffer_image2d_r16g16b16a16.as_raw(), 1, 1))
951 }
952 DXGI_FORMAT_R32_UINT => Some((self.cs_copy_buffer_image2d_r32.as_raw(), 1, 1)),
953 DXGI_FORMAT_R16G16_UINT => Some((self.cs_copy_buffer_image2d_r16g16.as_raw(), 1, 1)),
954 DXGI_FORMAT_R8G8B8A8_UINT => {
955 Some((self.cs_copy_buffer_image2d_r8g8b8a8.as_raw(), 1, 1))
956 }
957 DXGI_FORMAT_R16_UINT => Some((self.cs_copy_buffer_image2d_r16.as_raw(), 2, 1)),
958 DXGI_FORMAT_R8G8_UINT => Some((self.cs_copy_buffer_image2d_r8g8.as_raw(), 2, 1)),
959 DXGI_FORMAT_R8_UINT => Some((self.cs_copy_buffer_image2d_r8.as_raw(), 4, 1)),
960 _ => None,
961 }
962 }
963
copy_buffer_to_image_2d<T>( &mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>, src: &Buffer, dst: &Image, regions: T, ) where T: IntoIterator, T::Item: Borrow<command::BufferImageCopy>,964 pub fn copy_buffer_to_image_2d<T>(
965 &mut self,
966 context: &ComPtr<d3d11::ID3D11DeviceContext>,
967 src: &Buffer,
968 dst: &Image,
969 regions: T,
970 ) where
971 T: IntoIterator,
972 T::Item: Borrow<command::BufferImageCopy>,
973 {
974 let _scope = debug_scope!(
975 context,
976 "Buffer => Image (format={:?},kind={:?})",
977 dst.format,
978 dst.kind
979 );
980 // NOTE: we have two separate paths for Buffer -> Image transfers. we need to special case
981 // uploads to compressed formats through `UpdateSubresource` since we cannot get a
982 // UAV of any compressed format.
983
984 let format_desc = dst.format.base_format().0.desc();
985 if format_desc.is_compressed() {
986 // we dont really care about non-4x4 block formats..
987 assert_eq!(format_desc.dim, (4, 4));
988 assert!(!src.host_ptr.is_null());
989
990 for copy in regions {
991 let info = copy.borrow();
992
993 let bytes_per_texel = format_desc.bits as u32 / 8;
994
995 let row_pitch = bytes_per_texel * info.image_extent.width / 4;
996 let depth_pitch = row_pitch * info.image_extent.height / 4;
997
998 unsafe {
999 context.UpdateSubresource(
1000 dst.internal.raw,
1001 dst.calc_subresource(
1002 info.image_layers.level as _,
1003 info.image_layers.layers.start as _,
1004 ),
1005 &d3d11::D3D11_BOX {
1006 left: info.image_offset.x as _,
1007 top: info.image_offset.y as _,
1008 front: info.image_offset.z as _,
1009 right: info.image_offset.x as u32 + info.image_extent.width,
1010 bottom: info.image_offset.y as u32 + info.image_extent.height,
1011 back: info.image_offset.z as u32 + info.image_extent.depth,
1012 },
1013 src.host_ptr
1014 .offset(src.bound_range.start as isize + info.buffer_offset as isize)
1015 as _,
1016 row_pitch,
1017 depth_pitch,
1018 );
1019 }
1020 }
1021 } else {
1022 let (shader, scale_x, scale_y) = self
1023 .find_buffer_to_image_shader(dst.decomposed_format.copy_uav.unwrap())
1024 .unwrap();
1025
1026 let srv = src.internal.srv.unwrap();
1027
1028 unsafe {
1029 context.CSSetShader(shader, ptr::null_mut(), 0);
1030 context.CSSetConstantBuffers(0, 1, &self.internal_buffer.as_raw());
1031 context.CSSetShaderResources(0, 1, [srv].as_ptr());
1032
1033 for copy in regions {
1034 let info = copy.borrow();
1035 self.update_buffer_image(context, &info, dst);
1036
1037 debug_marker!(context, "{:?}", info);
1038
1039 // TODO: multiple layers? do we introduce a stride and do multiple dispatch
1040 // calls or handle this in the shader? (use z component in dispatch call
1041 //
1042 // NOTE: right now our copy UAV is a 2D array, and we set the layer in the
1043 // `update_buffer_image` call above
1044 let uav = dst
1045 .get_uav(
1046 info.image_layers.level,
1047 0, /*info.image_layers.layers.start*/
1048 )
1049 .unwrap()
1050 .as_raw();
1051 context.CSSetUnorderedAccessViews(0, 1, [uav].as_ptr(), ptr::null_mut());
1052
1053 context.Dispatch(
1054 ((info.image_extent.width + (COPY_THREAD_GROUP_X - 1))
1055 / COPY_THREAD_GROUP_X
1056 / scale_x)
1057 .max(1),
1058 ((info.image_extent.height + (COPY_THREAD_GROUP_X - 1))
1059 / COPY_THREAD_GROUP_Y
1060 / scale_y)
1061 .max(1),
1062 1,
1063 );
1064 }
1065
1066 // unbind external resources
1067 context.CSSetShaderResources(0, 1, [ptr::null_mut(); 1].as_ptr());
1068 context.CSSetUnorderedAccessViews(
1069 0,
1070 1,
1071 [ptr::null_mut(); 1].as_ptr(),
1072 ptr::null_mut(),
1073 );
1074 }
1075 }
1076 }
1077
find_blit_shader(&self, src: &Image) -> Option<*mut d3d11::ID3D11PixelShader>1078 fn find_blit_shader(&self, src: &Image) -> Option<*mut d3d11::ID3D11PixelShader> {
1079 use crate::format::ChannelType as Ct;
1080
1081 match src.format.base_format().1 {
1082 Ct::Uint => Some(self.ps_blit_2d_uint.as_raw()),
1083 Ct::Sint => Some(self.ps_blit_2d_int.as_raw()),
1084 Ct::Unorm | Ct::Snorm | Ct::Sfloat | Ct::Srgb => Some(self.ps_blit_2d_float.as_raw()),
1085 Ct::Ufloat | Ct::Uscaled | Ct::Sscaled => None,
1086 }
1087 }
1088
blit_2d_image<T>( &mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>, src: &Image, dst: &Image, filter: image::Filter, regions: T, ) where T: IntoIterator, T::Item: Borrow<command::ImageBlit>,1089 pub fn blit_2d_image<T>(
1090 &mut self,
1091 context: &ComPtr<d3d11::ID3D11DeviceContext>,
1092 src: &Image,
1093 dst: &Image,
1094 filter: image::Filter,
1095 regions: T,
1096 ) where
1097 T: IntoIterator,
1098 T::Item: Borrow<command::ImageBlit>,
1099 {
1100 use std::cmp;
1101
1102 let _scope = debug_scope!(
1103 context,
1104 "Blit: Image (format={:?},kind={:?}) => Image (format={:?},kind={:?})",
1105 src.format,
1106 src.kind,
1107 dst.format,
1108 dst.kind
1109 );
1110
1111 let shader = self.find_blit_shader(src).unwrap();
1112
1113 let srv = src.internal.srv.clone().unwrap().as_raw();
1114
1115 unsafe {
1116 context.IASetPrimitiveTopology(d3dcommon::D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
1117 context.VSSetShader(self.vs_blit_2d.as_raw(), ptr::null_mut(), 0);
1118 context.VSSetConstantBuffers(0, 1, [self.internal_buffer.as_raw()].as_ptr());
1119 context.PSSetShader(shader, ptr::null_mut(), 0);
1120 context.PSSetShaderResources(0, 1, [srv].as_ptr());
1121 context.PSSetSamplers(
1122 0,
1123 1,
1124 match filter {
1125 image::Filter::Nearest => [self.sampler_nearest.as_raw()],
1126 image::Filter::Linear => [self.sampler_linear.as_raw()],
1127 }
1128 .as_ptr(),
1129 );
1130
1131 for region in regions {
1132 let region = region.borrow();
1133 self.update_blit(context, src, ®ion);
1134
1135 // TODO: more layers
1136 let rtv = dst
1137 .get_rtv(
1138 region.dst_subresource.level,
1139 region.dst_subresource.layers.start,
1140 )
1141 .unwrap()
1142 .as_raw();
1143
1144 context.RSSetViewports(
1145 1,
1146 [d3d11::D3D11_VIEWPORT {
1147 TopLeftX: cmp::min(region.dst_bounds.start.x, region.dst_bounds.end.x) as _,
1148 TopLeftY: cmp::min(region.dst_bounds.start.y, region.dst_bounds.end.y) as _,
1149 Width: (region.dst_bounds.end.x - region.dst_bounds.start.x).abs() as _,
1150 Height: (region.dst_bounds.end.y - region.dst_bounds.start.y).abs() as _,
1151 MinDepth: 0.0f32,
1152 MaxDepth: 1.0f32,
1153 }]
1154 .as_ptr(),
1155 );
1156 context.OMSetRenderTargets(1, [rtv].as_ptr(), ptr::null_mut());
1157 context.Draw(3, 0);
1158 }
1159
1160 context.PSSetShaderResources(0, 1, [ptr::null_mut()].as_ptr());
1161 context.OMSetRenderTargets(1, [ptr::null_mut()].as_ptr(), ptr::null_mut());
1162 }
1163 }
1164
clear_attachments<T, U>( &mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>, clears: T, rects: U, cache: &RenderPassCache, ) where T: IntoIterator, T::Item: Borrow<command::AttachmentClear>, U: IntoIterator, U::Item: Borrow<pso::ClearRect>,1165 pub fn clear_attachments<T, U>(
1166 &mut self,
1167 context: &ComPtr<d3d11::ID3D11DeviceContext>,
1168 clears: T,
1169 rects: U,
1170 cache: &RenderPassCache,
1171 ) where
1172 T: IntoIterator,
1173 T::Item: Borrow<command::AttachmentClear>,
1174 U: IntoIterator,
1175 U::Item: Borrow<pso::ClearRect>,
1176 {
1177 use hal::format::ChannelType as Ct;
1178 let _scope = debug_scope!(context, "ClearAttachments");
1179
1180 let clear_rects: SmallVec<[pso::ClearRect; 8]> = rects
1181 .into_iter()
1182 .map(|rect| rect.borrow().clone())
1183 .collect();
1184
1185 unsafe {
1186 context.IASetPrimitiveTopology(d3dcommon::D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
1187 context.IASetInputLayout(ptr::null_mut());
1188 context.VSSetShader(self.vs_partial_clear.as_raw(), ptr::null_mut(), 0);
1189 context.PSSetConstantBuffers(0, 1, [self.internal_buffer.as_raw()].as_ptr());
1190 }
1191
1192 let subpass = &cache.render_pass.subpasses[cache.current_subpass as usize];
1193
1194 for clear in clears {
1195 let clear = clear.borrow();
1196
1197 let _scope = debug_scope!(context, "{:?}", clear);
1198
1199 match *clear {
1200 command::AttachmentClear::Color { index, value } => {
1201 self.update_clear_color(context, value);
1202
1203 let attachment = {
1204 let rtv_id = subpass.color_attachments[index];
1205 &cache.framebuffer.attachments[rtv_id.0]
1206 };
1207
1208 unsafe {
1209 context.OMSetRenderTargets(
1210 1,
1211 [attachment.rtv_handle.clone().unwrap().as_raw()].as_ptr(),
1212 ptr::null_mut(),
1213 );
1214 }
1215
1216 let shader = match attachment.format.base_format().1 {
1217 Ct::Uint => self.ps_partial_clear_uint.as_raw(),
1218 Ct::Sint => self.ps_partial_clear_int.as_raw(),
1219 _ => self.ps_partial_clear_float.as_raw(),
1220 };
1221 unsafe { context.PSSetShader(shader, ptr::null_mut(), 0) };
1222
1223 for clear_rect in &clear_rects {
1224 let viewport = conv::map_viewport(&Viewport {
1225 rect: clear_rect.rect,
1226 depth: 0f32 .. 1f32,
1227 });
1228
1229 debug_marker!(context, "{:?}", clear_rect.rect);
1230
1231 unsafe {
1232 context.RSSetViewports(1, [viewport].as_ptr());
1233 context.Draw(3, 0);
1234 }
1235 }
1236 }
1237 command::AttachmentClear::DepthStencil { depth, stencil } => {
1238 self.update_clear_depth_stencil(context, depth, stencil);
1239
1240 let attachment = {
1241 let dsv_id = subpass.depth_stencil_attachment.unwrap();
1242 &cache.framebuffer.attachments[dsv_id.0]
1243 };
1244
1245 unsafe {
1246 match (depth, stencil) {
1247 (Some(_), Some(stencil)) => {
1248 context.OMSetDepthStencilState(
1249 self.partial_clear_depth_stencil_state.as_raw(),
1250 stencil,
1251 );
1252 context.PSSetShader(
1253 self.ps_partial_clear_depth.as_raw(),
1254 ptr::null_mut(),
1255 0,
1256 );
1257 }
1258
1259 (Some(_), None) => {
1260 context.OMSetDepthStencilState(
1261 self.partial_clear_depth_state.as_raw(),
1262 0,
1263 );
1264 context.PSSetShader(
1265 self.ps_partial_clear_depth.as_raw(),
1266 ptr::null_mut(),
1267 0,
1268 );
1269 }
1270
1271 (None, Some(stencil)) => {
1272 context.OMSetDepthStencilState(
1273 self.partial_clear_stencil_state.as_raw(),
1274 stencil,
1275 );
1276 context.PSSetShader(
1277 self.ps_partial_clear_stencil.as_raw(),
1278 ptr::null_mut(),
1279 0,
1280 );
1281 }
1282 (None, None) => {}
1283 }
1284
1285 context.OMSetRenderTargets(
1286 0,
1287 ptr::null_mut(),
1288 attachment.dsv_handle.clone().unwrap().as_raw(),
1289 );
1290 context.PSSetShader(
1291 self.ps_partial_clear_depth.as_raw(),
1292 ptr::null_mut(),
1293 0,
1294 );
1295 }
1296
1297 for clear_rect in &clear_rects {
1298 let viewport = conv::map_viewport(&Viewport {
1299 rect: clear_rect.rect,
1300 depth: 0f32 .. 1f32,
1301 });
1302
1303 unsafe {
1304 context.RSSetViewports(1, [viewport].as_ptr());
1305 context.Draw(3, 0);
1306 }
1307 }
1308 }
1309 }
1310 }
1311 }
1312 }
1313