1use crate::cx_win32::*;
2use crate::cx::*;
3
4use winapi::shared::guiddef::GUID;
5use winapi::shared::minwindef::{TRUE, FALSE};
6use winapi::shared::{dxgi, dxgi1_2, dxgitype, dxgiformat, winerror};
7use winapi::um::{d3d11, d3dcommon, d3dcompiler};
8use winapi::Interface;
9use wio::com::ComPtr;
10use std::mem;
11use std::ptr;
12use std::ffi;
13impl Cx {
17
18 pub fn render_view(
19 &mut self,
20 pass_id: usize,
21 view_id: usize,
22 scroll: Vec2,
23 clip: (Vec2, Vec2),
24 repaint_id: u64,
25 d3d11_cx: &D3d11Cx,
26 zbias: &mut f32,
27 zbias_step: f32
28 ) {
29
30 let draw_calls_len = self.views[view_id].draw_calls_len;
32
33 self.views[view_id].uniform_view_transform(&Mat4::identity());
34 self.views[view_id].parent_scroll = scroll;
35
36 let local_scroll = self.views[view_id].get_local_scroll();
37 let clip = self.views[view_id].intersect_clip(clip);
38
39 let cxview = &mut self.views[view_id];
40 cxview.platform.view_uniforms.update_with_f32_constant_data(d3d11_cx, cxview.view_uniforms.as_slice());
41
42 for draw_call_id in 0..draw_calls_len {
43 let sub_view_id = self.views[view_id].draw_calls[draw_call_id].sub_view_id;
44 if sub_view_id != 0 {
45 self.render_view(
46 pass_id,
47 sub_view_id,
48 Vec2 {x: local_scroll.x + scroll.x, y: local_scroll.y + scroll.y},
49 clip,
50 repaint_id,
51 d3d11_cx,
52 zbias,
53 zbias_step
54 );
55 }
56 else {
57 let cxview = &mut self.views[view_id];
58
59 let draw_call = &mut cxview.draw_calls[draw_call_id];
60 let sh = &self.shaders[draw_call.shader_id];
61 let shp = sh.platform.as_ref().unwrap();
62
63 if draw_call.instance_dirty {
64 draw_call.instance_dirty = false;
65 if draw_call.instance.len() == 0 {
66 continue;
67 }
68 draw_call.platform.inst_vbuf.update_with_f32_vertex_data(d3d11_cx, &draw_call.instance);
70 }
71
72 draw_call.set_zbias(*zbias);
74 draw_call.set_local_scroll(scroll, local_scroll);
75 draw_call.set_clip(clip);
76 *zbias += zbias_step;
77
78 draw_call.platform.draw_uniforms.update_with_f32_constant_data(d3d11_cx, draw_call.draw_uniforms.as_slice());
79
80 if draw_call.uniforms_dirty {
81 draw_call.uniforms_dirty = false;
82 if draw_call.uniforms.len() != 0 {
83 draw_call.platform.uniforms.update_with_f32_constant_data(d3d11_cx, &mut draw_call.uniforms);
84 }
85 }
86
87 let instances = (draw_call.instance.len() / sh.mapping.instance_slots) as usize;
88
89 if instances == 0 {
90 continue;
91 }
92
93 d3d11_cx.set_shaders(&shp.vertex_shader, &shp.pixel_shader);
94
95 d3d11_cx.set_primitive_topology();
96
97 d3d11_cx.set_input_layout(&shp.input_layout);
98
99 d3d11_cx.set_index_buffer(&shp.geom_ibuf);
100
101 d3d11_cx.set_vertex_buffers(&shp.geom_vbuf, sh.mapping.geometry_slots, &draw_call.platform.inst_vbuf, sh.mapping.instance_slots);
102
103 d3d11_cx.set_constant_buffers(
104 &self.passes[pass_id].platform.pass_uniforms,
105 &cxview.platform.view_uniforms,
106 &draw_call.platform.draw_uniforms,
107 &draw_call.platform.uniforms
108 );
109
110 for (i, texture_id) in draw_call.textures_2d.iter().enumerate() {
111 let cxtexture = &mut self.textures[*texture_id as usize];
112 match cxtexture.desc.format { TextureFormat::Default | TextureFormat::ImageBGRA => {
114 if cxtexture.update_image {
115 cxtexture.update_image = false;
116 d3d11_cx.update_platform_texture_image_bgra(
117 &mut cxtexture.platform,
118 cxtexture.desc.width.unwrap(),
119 cxtexture.desc.height.unwrap(),
120 &cxtexture.image_u32,
121 );
122 }
123 d3d11_cx.set_shader_resource(i, &cxtexture.platform.shader_resource);
124 },
125
126 TextureFormat::RenderBGRA | TextureFormat::RenderBGRAf16 | TextureFormat::RenderBGRAf32 => {
127 d3d11_cx.set_shader_resource(i, &cxtexture.platform.shader_resource);
128 },
129 _ => ()
130 }
131 }
132 d3d11_cx.draw_indexed_instanced(sh.shader_gen.geometry_indices.len(), instances);
133 }
134 }
135 }
136
137 pub fn setup_pass_render_targets(&mut self, pass_id: usize, inherit_dpi_factor: f32, first_target: Option<&ComPtr<d3d11::ID3D11RenderTargetView>>, d3d11_cx: &D3d11Cx) {
138
139 let pass_size = self.passes[pass_id].pass_size;
140
141 self.passes[pass_id].set_ortho_matrix(Vec2::default(), pass_size);
142 self.passes[pass_id].uniform_camera_view(&Mat4::identity());
143 self.passes[pass_id].paint_dirty = false;
144 let dpi_factor = if let Some(override_dpi_factor) = self.passes[pass_id].override_dpi_factor {
145 override_dpi_factor
146 }
147 else {
148 inherit_dpi_factor
149 };
150 self.passes[pass_id].set_dpi_factor(dpi_factor);
151
152 d3d11_cx.set_viewport(pass_size.x * dpi_factor, pass_size.y * dpi_factor);
154
155 let mut color_textures = Vec::<*mut d3d11::ID3D11RenderTargetView>::new();
157 for (index, color_texture) in self.passes[pass_id].color_textures.iter().enumerate() {
158 let render_target;
159 let is_initial;
160 if index == 0 && first_target.is_some() {
161 render_target = first_target.unwrap();
162 is_initial = true;
163 }
164 else {
165 let cxtexture = &mut self.textures[color_texture.texture_id];
166 is_initial = d3d11_cx.update_render_target(cxtexture, dpi_factor, pass_size);
167 render_target = cxtexture.platform.render_target_view.as_ref().unwrap();
168 }
169 color_textures.push(render_target.as_raw() as *mut _);
170 match color_texture.clear_color {
172 ClearColor::InitWith(color) => {
173 if is_initial {
174 d3d11_cx.clear_render_target_view(&render_target, color); }
176 },
177 ClearColor::ClearWith(color) => {
178 d3d11_cx.clear_render_target_view(&render_target, color); }
180 }
181 }
182
183 if let Some(depth_texture_id) = self.passes[pass_id].depth_texture {
185 let cxtexture = &mut self.textures[depth_texture_id];
186 let is_initial = d3d11_cx.update_depth_stencil(cxtexture, dpi_factor, pass_size);
187 match self.passes[pass_id].clear_depth {
188 ClearDepth::InitWith(depth_clear) => {
189 if is_initial {
190 d3d11_cx.clear_depth_stencil_view(cxtexture.platform.depth_stencil_view.as_ref().unwrap(), depth_clear as f32);
191 }
192 },
193 ClearDepth::ClearWith(depth_clear) => {
194 d3d11_cx.clear_depth_stencil_view(cxtexture.platform.depth_stencil_view.as_ref().unwrap(), depth_clear as f32);
195 }
196 }
197 unsafe {d3d11_cx.context.OMSetRenderTargets(
198 color_textures.len() as u32,
199 color_textures.as_ptr(),
200 cxtexture.platform.depth_stencil_view.as_ref().unwrap().as_raw() as *mut _
201 )}
202 }
203 else {
204 unsafe {d3d11_cx.context.OMSetRenderTargets(
205 color_textures.len() as u32,
206 color_textures.as_ptr(),
207 ptr::null_mut()
208 )}
209 }
210
211 if self.passes[pass_id].platform.blend_state.is_none() {
213 self.passes[pass_id].platform.blend_state = Some(
214 d3d11_cx.create_blend_state().expect("Cannot create blend state")
215 )
216 }
217
218 if self.passes[pass_id].platform.raster_state.is_none() {
219 self.passes[pass_id].platform.raster_state = Some(
220 d3d11_cx.create_raster_state().expect("Cannot create raster state")
221 )
222 }
223
224 d3d11_cx.set_raster_state(self.passes[pass_id].platform.raster_state.as_ref().unwrap());
225 d3d11_cx.set_blend_state(self.passes[pass_id].platform.blend_state.as_ref().unwrap());
226 let cxpass = &mut self.passes[pass_id];
227 cxpass.platform.pass_uniforms.update_with_f32_constant_data(&d3d11_cx, cxpass.pass_uniforms.as_slice());
228 }
229
230 pub fn draw_pass_to_window(&mut self, pass_id: usize, vsync: bool, dpi_factor: f32, d3d11_window: &mut D3d11Window, d3d11_cx: &D3d11Cx) {
231 let view_id = self.passes[pass_id].main_view_id.unwrap();
233
234 self.setup_pass_render_targets(pass_id, dpi_factor, d3d11_window.render_target_view.as_ref(), d3d11_cx);
235 let mut zbias = 0.0;
236 let zbias_step = self.passes[pass_id].zbias_step;
237 self.render_view(
238 pass_id,
239 view_id,
240 Vec2::default(),
241 (Vec2 {x: -50000., y: -50000.}, Vec2 {x: 50000., y: 50000.}),
242 self.repaint_id,
243 &d3d11_cx,
244 &mut zbias,
245 zbias_step
246 );
247 d3d11_window.present(vsync);
248 }
250
251 pub fn draw_pass_to_texture(&mut self, pass_id: usize, dpi_factor: f32, d3d11_cx: &D3d11Cx) {
252 let view_id = self.passes[pass_id].main_view_id.unwrap();
254 self.setup_pass_render_targets(pass_id, dpi_factor, None, d3d11_cx);
255 let mut zbias = 0.0;
256 let zbias_step = self.passes[pass_id].zbias_step;
257 self.render_view(
258 pass_id,
259 view_id,
260 Vec2::default(),
261 (Vec2{x:-50000.,y:-50000.},Vec2{x:50000.,y:50000.}),
262 self.repaint_id,
263 &d3d11_cx,
264 &mut zbias,
265 zbias_step
266 );
267 }
268}
269
270
271pub struct D3d11RenderTarget {
272 pub render_target_view: Option<ComPtr<d3d11::ID3D11RenderTargetView>>,
273 }
276
277pub struct D3d11Window {
300 pub window_id: usize,
301 pub is_in_resize: bool,
302 pub window_geom: WindowGeom,
303 pub win32_window: Win32Window,
304 pub render_target_view: Option<ComPtr<d3d11::ID3D11RenderTargetView>>,
305 pub swap_texture: Option<ComPtr<d3d11::ID3D11Texture2D>>,
309 pub alloc_size: Vec2,
312 pub first_draw: bool,
313 pub swap_chain: ComPtr<dxgi1_2::IDXGISwapChain1>,
314}
315
316impl D3d11Window {
317 pub fn new(window_id: usize, d3d11_cx: &D3d11Cx, win32_app: &mut Win32App, inner_size: Vec2, position: Option<Vec2>, title: &str) -> D3d11Window {
318 let mut win32_window = Win32Window::new(win32_app, window_id);
319
320 win32_window.init(title, inner_size, position);
321 let window_geom = win32_window.get_window_geom();
322
323 let swap_chain = d3d11_cx.create_swap_chain_for_hwnd(&window_geom, &win32_window).expect("Cannot create_swap_chain_for_hwnd");
324
325 let swap_texture = D3d11Cx::get_swap_texture(&swap_chain).expect("Cannot get swap texture");
326
327 let render_target_view = Some(d3d11_cx.create_render_target_view(&swap_texture).expect("Cannot create_render_target_view"));
328
329 D3d11Window {
339 first_draw: true,
340 is_in_resize: false,
341 window_id: window_id,
342 alloc_size: window_geom.inner_size,
343 window_geom: window_geom,
344 win32_window: win32_window,
345 swap_texture: Some(swap_texture),
346 render_target_view: render_target_view,
347 swap_chain: swap_chain,
353 }
356 }
357
358 pub fn start_resize(&mut self) {
359 self.is_in_resize = true;
360 }
361
362 pub fn stop_resize(&mut self) {
364 self.is_in_resize = false;
365 self.alloc_size = Vec2::default();
366 }
367
368 pub fn resize_buffers(&mut self, d3d11_cx: &D3d11Cx) {
380 if self.alloc_size == self.window_geom.inner_size {
381 return
382 }
383 self.alloc_size = self.window_geom.inner_size;
384 self.swap_texture = None;
385 self.render_target_view = None;
386
387 d3d11_cx.resize_swap_chain(&self.window_geom, &self.swap_chain);
388
389 let swap_texture = D3d11Cx::get_swap_texture(&self.swap_chain).expect("Cannot get swap texture");
390
391 self.render_target_view = Some(d3d11_cx.create_render_target_view(&swap_texture).expect("Cannot create_render_target_view"));
392
393 self.swap_texture = Some(swap_texture);
394 }
395
396 pub fn present(&mut self, vsync: bool) {
397 unsafe {self.swap_chain.Present(if vsync {1}else {0}, 0)};
398 }
399
400}
401
402#[derive(Clone)]
403pub struct D3d11Cx {
404 pub device: ComPtr<d3d11::ID3D11Device>,
405 pub context: ComPtr<d3d11::ID3D11DeviceContext>,
406 pub factory: ComPtr<dxgi1_2::IDXGIFactory2>,
407 }
409
410impl D3d11Cx {
411
412 pub fn new() -> D3d11Cx {
413 let factory = D3d11Cx::create_dxgi_factory1(&dxgi1_2::IDXGIFactory2::uuidof()).expect("cannot create_dxgi_factory1");
414 let adapter = D3d11Cx::enum_adapters(&factory).expect("cannot enum_adapters");
415 let (device, context) = D3d11Cx::create_d3d11_device(&adapter).expect("cannot create_d3d11_device");
416 D3d11Cx {
418 device: device,
419 context: context,
420 factory: factory,
421 }
423 }
424
425 pub fn disconnect_rendertargets(&self) {
426 unsafe {self.context.OMSetRenderTargets(0, ptr::null(), ptr::null_mut())}
427 }
428
429 pub fn set_viewport(&self, width: f32, height: f32) {
430 let viewport = d3d11::D3D11_VIEWPORT {
431 Width: width,
432 Height: height,
433 MinDepth: 0.,
434 MaxDepth: 1.,
435 TopLeftX: 0.0,
436 TopLeftY: 0.0
437 };
438 unsafe {self.context.RSSetViewports(1, &viewport)}
439 }
440
441 pub fn clear_render_target_view(&self, render_target_view: &ComPtr<d3d11::ID3D11RenderTargetView>, color: Color) {
450 let color = [color.r, color.g, color.b, color.a];
451 unsafe {self.context.ClearRenderTargetView(render_target_view.as_raw() as *mut _, &color)}
452 }
453
454 pub fn clear_depth_stencil_view(&self, depth_stencil_view: &ComPtr<d3d11::ID3D11DepthStencilView>, depth: f32) {
455 unsafe {self.context.ClearDepthStencilView(depth_stencil_view.as_raw() as *mut _, d3d11::D3D11_CLEAR_DEPTH | d3d11::D3D11_CLEAR_STENCIL, depth, 0)}
456 }
457
458 pub fn set_raster_state(&self, raster_state: &ComPtr<d3d11::ID3D11RasterizerState>,) {
463 unsafe {self.context.RSSetState(raster_state.as_raw() as *mut _)}
464 }
465
466 pub fn set_blend_state(&self, blend_state: &ComPtr<d3d11::ID3D11BlendState>,) {
467 let blend_factor = [0., 0., 0., 0.];
468 unsafe {self.context.OMSetBlendState(blend_state.as_raw() as *mut _, &blend_factor, 0xffffffff)}
469 }
470
471 pub fn set_input_layout(&self, input_layout: &ComPtr<d3d11::ID3D11InputLayout>) {
472 unsafe {self.context.IASetInputLayout(input_layout.as_raw() as *mut _)}
473 }
474
475 pub fn set_index_buffer(&self, index_buffer: &D3d11Buffer) {
476 if let Some(buf) = &index_buffer.buffer {
477 unsafe {self.context.IASetIndexBuffer(buf.as_raw() as *mut _, dxgiformat::DXGI_FORMAT_R32_UINT, 0)}
478 }
479 }
480
481 pub fn set_shaders(&self, vertex_shader: &ComPtr<d3d11::ID3D11VertexShader>, pixel_shader: &ComPtr<d3d11::ID3D11PixelShader>) {
482 unsafe {self.context.VSSetShader(vertex_shader.as_raw() as *mut _, ptr::null(), 0)}
483 unsafe {self.context.PSSetShader(pixel_shader.as_raw() as *mut _, ptr::null(), 0)}
484 }
485
486 pub fn set_shader_resource(&self, index: usize, texture: &Option<ComPtr<d3d11::ID3D11ShaderResourceView>>) {
487 if let Some(texture) = texture {
488 let raw = [texture.as_raw() as *const std::ffi::c_void];
489 unsafe {self.context.PSSetShaderResources(index as u32, 1, raw.as_ptr() as *const *mut _)}
490 unsafe {self.context.VSSetShaderResources(index as u32, 1, raw.as_ptr() as *const *mut _)}
491 }
492 }
493
494 pub fn set_primitive_topology(&self) {
499 unsafe {self.context.IASetPrimitiveTopology(d3dcommon::D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST)}
500 }
501
502 pub fn set_vertex_buffers(&self, geom_buf: &D3d11Buffer, geom_slots: usize, inst_buf: &D3d11Buffer, inst_slots: usize) {
503 let geom_buf = geom_buf.buffer.as_ref().unwrap();
504 let inst_buf = inst_buf.buffer.as_ref().unwrap();
505
506 let strides = [(geom_slots * 4) as u32, (inst_slots * 4) as u32];
507 let offsets = [0u32, 0u32];
508 let buffers = [geom_buf.as_raw() as *const std::ffi::c_void, inst_buf.as_raw() as *const std::ffi::c_void];
509 unsafe {self.context.IASetVertexBuffers(
510 0,
511 2,
512 buffers.as_ptr() as *const *mut _,
513 strides.as_ptr() as *const _,
514 offsets.as_ptr() as *const _
515 )};
516 }
517
518 pub fn set_constant_buffers(&self, pass_uni: &D3d11Buffer, view_uni: &D3d11Buffer, draw_uni: &D3d11Buffer, uni: &D3d11Buffer) {
519 let pass_uni = pass_uni.buffer.as_ref().unwrap();
520 let view_uni = view_uni.buffer.as_ref().unwrap();
521 let draw_uni = draw_uni.buffer.as_ref().unwrap();
522 if let Some(uni) = uni.buffer.as_ref() {
523 let buffers = [
524 pass_uni.as_raw() as *const std::ffi::c_void,
525 view_uni.as_raw() as *const std::ffi::c_void,
526 draw_uni.as_raw() as *const std::ffi::c_void,
527 uni.as_raw() as *const std::ffi::c_void,
528 ];
529 unsafe {self.context.VSSetConstantBuffers(
530 0,
531 4,
532 buffers.as_ptr() as *const *mut _,
533 )};
534 unsafe {self.context.PSSetConstantBuffers(
535 0,
536 4,
537 buffers.as_ptr() as *const *mut _,
538 )};
539 }
540 else {
541 let buffers = [
542 pass_uni.as_raw() as *const std::ffi::c_void,
543 view_uni.as_raw() as *const std::ffi::c_void,
544 draw_uni.as_raw() as *const std::ffi::c_void,
545 ];
546 unsafe {self.context.VSSetConstantBuffers(
547 0,
548 3,
549 buffers.as_ptr() as *const *mut _,
550 )};
551 unsafe {self.context.PSSetConstantBuffers(
552 0,
553 3,
554 buffers.as_ptr() as *const *mut _,
555 )};
556 }
557 }
558
559 pub fn draw_indexed_instanced(&self, num_vertices: usize, num_instances: usize) {
560
561
562 unsafe {self.context.DrawIndexedInstanced(
563 num_vertices as u32,
564 num_instances as u32,
565 0,
566 0,
567 0
568 )};
569 }
570
571 pub fn compile_shader(&self, stage: &str, entry: &[u8], shader: &[u8])
572 -> Result<ComPtr<d3dcommon::ID3DBlob>, SlErr> {
573
574 let mut blob = ptr::null_mut();
575 let mut error = ptr::null_mut();
576 let entry = ffi::CString::new(entry).unwrap();
577 let stage = format!("{}_5_0\0", stage);
578 let hr = unsafe {d3dcompiler::D3DCompile(
579 shader.as_ptr() as *const _,
580 shader.len(),
581 ptr::null(),
582 ptr::null(),
583 ptr::null_mut(),
584 entry.as_ptr() as *const _,
585 stage.as_ptr() as *const i8,
586 1,
587 0,
588 &mut blob as *mut *mut _,
589 &mut error as *mut *mut _
590 )};
591 if !winerror::SUCCEEDED(hr) {
592 let error = unsafe {ComPtr::<d3dcommon::ID3DBlob>::from_raw(error)};
593 let message = unsafe {
594 let pointer = error.GetBufferPointer();
595 let size = error.GetBufferSize();
596 let slice = std::slice::from_raw_parts(pointer as *const u8, size as usize);
597 String::from_utf8_lossy(slice).into_owned()
598 };
599
600 Err(SlErr {msg: message})
601 } else {
602 Ok(unsafe {ComPtr::<d3dcommon::ID3DBlob>::from_raw(blob)})
603 }
604 }
605
606 pub fn create_input_layout(&self, vs: &ComPtr<d3dcommon::ID3DBlob>, layout_desc: &Vec<d3d11::D3D11_INPUT_ELEMENT_DESC>)
607 -> Result<ComPtr<d3d11::ID3D11InputLayout>, SlErr> {
608 let mut input_layout = ptr::null_mut();
609 let hr = unsafe {self.device.CreateInputLayout(
610 layout_desc.as_ptr(),
611 layout_desc.len() as u32,
612 vs.GetBufferPointer(),
613 vs.GetBufferSize(),
614 &mut input_layout as *mut *mut _
615 )};
616 if winerror::SUCCEEDED(hr) {
617 Ok(unsafe {ComPtr::from_raw(input_layout as *mut _)})
618 }
619 else {
620 Err(SlErr {msg: format!("create_input_layout failed {}", hr)})
621 }
622 }
623
624 pub fn create_pixel_shader(&self, ps: &ComPtr<d3dcommon::ID3DBlob>)
625 -> Result<ComPtr<d3d11::ID3D11PixelShader>, SlErr> {
626 let mut pixel_shader = ptr::null_mut();
627 let hr = unsafe {self.device.CreatePixelShader(
628 ps.GetBufferPointer(),
629 ps.GetBufferSize(),
630 ptr::null_mut(),
631 &mut pixel_shader as *mut *mut _
632 )};
633 if winerror::SUCCEEDED(hr) {
634 Ok(unsafe {ComPtr::from_raw(pixel_shader as *mut _)})
635 }
636 else {
637 Err(SlErr {msg: format!("create_pixel_shader failed {}", hr)})
638 }
639 }
640
641
642 pub fn create_vertex_shader(&self, vs: &ComPtr<d3dcommon::ID3DBlob>)
643 -> Result<ComPtr<d3d11::ID3D11VertexShader>, SlErr> {
644 let mut vertex_shader = ptr::null_mut();
645 let hr = unsafe {self.device.CreateVertexShader(
646 vs.GetBufferPointer(),
647 vs.GetBufferSize(),
648 ptr::null_mut(),
649 &mut vertex_shader as *mut *mut _
650 )};
651 if winerror::SUCCEEDED(hr) {
652 Ok(unsafe {ComPtr::from_raw(vertex_shader as *mut _)})
653 }
654 else {
655 Err(SlErr {msg: format!("create_vertex_shader failed {}", hr)})
656 }
657 }
658
659
660 pub fn create_raster_state(&self)
661 -> Result<ComPtr<d3d11::ID3D11RasterizerState>, winerror::HRESULT> {
662 let mut raster_state = ptr::null_mut();
663 let raster_desc = d3d11::D3D11_RASTERIZER_DESC {
664 AntialiasedLineEnable: FALSE,
665 CullMode: d3d11::D3D11_CULL_NONE,
666 DepthBias: 0,
667 DepthBiasClamp: 0.0,
668 DepthClipEnable: TRUE,
669 FillMode: d3d11::D3D11_FILL_SOLID,
670 FrontCounterClockwise: FALSE,
671 MultisampleEnable: FALSE,
672 ScissorEnable: FALSE,
673 SlopeScaledDepthBias: 0.0,
674 };
675 let hr = unsafe {self.device.CreateRasterizerState(&raster_desc, &mut raster_state as *mut *mut _)};
676 if winerror::SUCCEEDED(hr) {
677 Ok(unsafe {ComPtr::from_raw(raster_state as *mut _)})
678 }
679 else {
680 Err(hr)
681 }
682 }
683
684 pub fn create_blend_state(&self)
685 -> Result<ComPtr<d3d11::ID3D11BlendState>, winerror::HRESULT> {
686 let mut blend_state = ptr::null_mut();
687 let mut blend_desc: d3d11::D3D11_BLEND_DESC = unsafe {mem::zeroed()};
688 blend_desc.AlphaToCoverageEnable = FALSE;
689 blend_desc.RenderTarget[0] = d3d11::D3D11_RENDER_TARGET_BLEND_DESC {
690 BlendEnable: TRUE,
691 SrcBlend: d3d11::D3D11_BLEND_ONE,
692 SrcBlendAlpha: d3d11::D3D11_BLEND_ONE,
693 DestBlend: d3d11::D3D11_BLEND_INV_SRC_ALPHA,
694 DestBlendAlpha: d3d11::D3D11_BLEND_INV_SRC_ALPHA,
695 BlendOp: d3d11::D3D11_BLEND_OP_ADD,
696 BlendOpAlpha: d3d11::D3D11_BLEND_OP_ADD,
697 RenderTargetWriteMask: d3d11::D3D11_COLOR_WRITE_ENABLE_ALL as u8,
698 };
699 let hr = unsafe {self.device.CreateBlendState(&blend_desc, &mut blend_state as *mut *mut _)};
700 if winerror::SUCCEEDED(hr) {
701 Ok(unsafe {ComPtr::from_raw(blend_state as *mut _)})
702 }
703 else {
704 Err(hr)
705 }
706 }
707
708 pub fn create_depth_stencil_view(&self, buffer: &ComPtr<d3d11::ID3D11Texture2D>)
709 -> Result<ComPtr<d3d11::ID3D11DepthStencilView>, winerror::HRESULT> {
710 let mut depth_stencil_view = ptr::null_mut();
711 let mut dsv_desc: d3d11::D3D11_DEPTH_STENCIL_VIEW_DESC = unsafe {mem::zeroed()};
712 dsv_desc.Format = dxgiformat::DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
713 dsv_desc.ViewDimension = d3d11::D3D11_DSV_DIMENSION_TEXTURE2D;
714 *unsafe {dsv_desc.u.Texture2D_mut()} = d3d11::D3D11_TEX2D_DSV {
715 MipSlice: 0,
716 };
717 let hr = unsafe {self.device.CreateDepthStencilView(buffer.as_raw() as *mut _, &dsv_desc, &mut depth_stencil_view as *mut *mut _)};
718 if winerror::SUCCEEDED(hr) {
719 Ok(unsafe {ComPtr::from_raw(depth_stencil_view as *mut _)})
720 }
721 else {
722 Err(hr)
723 }
724 }
725
726 pub fn create_depth_stencil_state(&self)
727 -> Result<ComPtr<d3d11::ID3D11DepthStencilState>, winerror::HRESULT> {
728 let mut depth_stencil_state = ptr::null_mut();
729 let ds_desc = d3d11::D3D11_DEPTH_STENCIL_DESC {
730 DepthEnable: TRUE,
731 DepthWriteMask: d3d11::D3D11_DEPTH_WRITE_MASK_ALL,
732 DepthFunc: d3d11::D3D11_COMPARISON_LESS_EQUAL,
733 StencilEnable: FALSE,
734 StencilReadMask: 0xff,
735 StencilWriteMask: 0xff,
736 FrontFace: d3d11::D3D11_DEPTH_STENCILOP_DESC {
737 StencilFailOp: d3d11::D3D11_STENCIL_OP_REPLACE,
738 StencilDepthFailOp: d3d11::D3D11_STENCIL_OP_REPLACE,
739 StencilPassOp: d3d11::D3D11_STENCIL_OP_REPLACE,
740 StencilFunc: d3d11::D3D11_COMPARISON_ALWAYS,
741 },
742 BackFace: d3d11::D3D11_DEPTH_STENCILOP_DESC {
743 StencilFailOp: d3d11::D3D11_STENCIL_OP_REPLACE,
744 StencilDepthFailOp: d3d11::D3D11_STENCIL_OP_REPLACE,
745 StencilPassOp: d3d11::D3D11_STENCIL_OP_REPLACE,
746 StencilFunc: d3d11::D3D11_COMPARISON_ALWAYS,
747 },
748 };
749
750 let hr = unsafe {self.device.CreateDepthStencilState(&ds_desc, &mut depth_stencil_state as *mut *mut _)};
751 if winerror::SUCCEEDED(hr) {
752 Ok(unsafe {ComPtr::from_raw(depth_stencil_state as *mut _)})
753 }
754 else {
755 Err(hr)
756 }
757 }
758
759 pub fn create_render_target_view(&self, texture: &ComPtr<d3d11::ID3D11Texture2D>)
760 -> Result<ComPtr<d3d11::ID3D11RenderTargetView>, winerror::HRESULT> {
761 let mut render_target_view = ptr::null_mut();
763 let hr = unsafe {self.device.CreateRenderTargetView(
764 texture.as_raw() as *mut _,
765 ptr::null(),
766 &mut render_target_view as *mut *mut _
767 )};
768 if winerror::SUCCEEDED(hr) {
769 Ok(unsafe {ComPtr::from_raw(render_target_view as *mut _)})
770 }
771 else {
772 Err(hr)
773 }
774 }
775
776 pub fn get_swap_texture(swap_chain: &ComPtr<dxgi1_2::IDXGISwapChain1>)
777 -> Result<ComPtr<d3d11::ID3D11Texture2D>, winerror::HRESULT> {
778 let mut texture = ptr::null_mut();
779 let hr = unsafe {swap_chain.GetBuffer(
780 0,
781 &d3d11::ID3D11Texture2D::uuidof(),
782 &mut texture as *mut *mut _
783 )};
784 if winerror::SUCCEEDED(hr) {
785 Ok(unsafe {ComPtr::from_raw(texture as *mut _)})
786 }
787 else {
788 Err(hr)
789 }
790 }
791
792 pub fn create_swap_chain_for_hwnd(
793 &self,
794 wg: &WindowGeom,
795 win32_window: &Win32Window,
796 )
797 -> Result<ComPtr<dxgi1_2::IDXGISwapChain1>, winerror::HRESULT> {
798 let mut swap_chain1 = ptr::null_mut();
799 let sc_desc = dxgi1_2::DXGI_SWAP_CHAIN_DESC1 {
800 AlphaMode: dxgi1_2::DXGI_ALPHA_MODE_IGNORE,
801 BufferCount: 2,
802 Width: (wg.inner_size.x * wg.dpi_factor) as u32,
803 Height: (wg.inner_size.y * wg.dpi_factor) as u32,
804 Format: dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM,
805 Flags: 0,
806 BufferUsage: dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT,
807 SampleDesc: dxgitype::DXGI_SAMPLE_DESC {Count: 1, Quality: 0,},
808 Scaling: dxgi1_2::DXGI_SCALING_NONE,
809 Stereo: FALSE,
810 SwapEffect: dxgi::DXGI_SWAP_EFFECT_FLIP_DISCARD,
811 };
812
813 let hr = unsafe {self.factory.CreateSwapChainForHwnd(
814 self.device.as_raw() as *mut _,
815 win32_window.hwnd.unwrap(),
816 &sc_desc,
817 ptr::null(),
818 ptr::null_mut(),
819 &mut swap_chain1 as *mut *mut _
820 )};
821 if winerror::SUCCEEDED(hr) {
822 Ok(unsafe {ComPtr::from_raw(swap_chain1 as *mut _)})
823 }
824 else {
825 Err(hr)
826 }
827 }
828
829 pub fn resize_swap_chain(
830 &self,
831 wg: &WindowGeom,
832 swap_chain: &ComPtr<dxgi1_2::IDXGISwapChain1>,
833 ) {
834 unsafe {
835 let hr = swap_chain.ResizeBuffers(
836 2,
837 (wg.inner_size.x * wg.dpi_factor) as u32,
838 (wg.inner_size.y * wg.dpi_factor) as u32,
839 dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM,
840 0
841 );
842 if !winerror::SUCCEEDED(hr) {
843 panic!("Could not resize swapchain");
844 }
845 }
846 }
847
848 pub fn create_d3d11_device(adapter: &ComPtr<dxgi::IDXGIAdapter>)
849 -> Result<(ComPtr<d3d11::ID3D11Device>, ComPtr<d3d11::ID3D11DeviceContext>), winerror::HRESULT> {
850 let mut device = ptr::null_mut();
851 let mut device_context = ptr::null_mut();
852 let hr = unsafe {d3d11::D3D11CreateDevice(
853 adapter.as_raw() as *mut _,
854 d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
855 ptr::null_mut(),
856 0,[d3dcommon::D3D_FEATURE_LEVEL_11_0].as_ptr(),
858 1,
859 d3d11::D3D11_SDK_VERSION,
860 &mut device as *mut *mut _,
861 ptr::null_mut(),
862 &mut device_context as *mut *mut _,
863 )};
864 if winerror::SUCCEEDED(hr) {
865 Ok((unsafe {ComPtr::from_raw(device as *mut _)}, unsafe {ComPtr::from_raw(device_context as *mut _)}))
866 }
867 else {
868 Err(hr)
869 }
870 }
871
872 pub fn create_dxgi_factory1(guid: &GUID)
873 -> Result<ComPtr<dxgi1_2::IDXGIFactory2>, winerror::HRESULT> {
874 let mut factory = ptr::null_mut();
875 let hr = unsafe {dxgi::CreateDXGIFactory1(
876 guid,
877 &mut factory as *mut *mut _
878 )};
879 if winerror::SUCCEEDED(hr) {
880 Ok(unsafe {ComPtr::from_raw(factory as *mut _)})
881 }
882 else {
883 Err(hr)
884 }
885 }
886
887
888 pub fn enum_adapters(factory: &ComPtr<dxgi1_2::IDXGIFactory2>)
889 -> Result<ComPtr<dxgi::IDXGIAdapter>, winerror::HRESULT> {
890 let mut adapter = ptr::null_mut();
891 let hr = unsafe {factory.EnumAdapters(
892 0,
893 &mut adapter as *mut *mut _
894 )};
895 if winerror::SUCCEEDED(hr) {
896 Ok(unsafe {ComPtr::from_raw(adapter as *mut _)})
897 }
898 else {
899 Err(hr)
900 }
901 }
902
903 pub fn update_render_target(&self, cxtexture: &mut CxTexture, dpi_factor: f32, size: Vec2) -> bool {
904
905 let width = if let Some(width) = cxtexture.desc.width {width as usize} else {(size.x * dpi_factor) as usize};
906 let height = if let Some(height) = cxtexture.desc.height {height as usize} else {(size.y * dpi_factor) as usize};
907
908 if cxtexture.platform.width == width && cxtexture.platform.height == height {
909 return false
910 }
911
912 let format;
913 match cxtexture.desc.format {
914 TextureFormat::Default | TextureFormat::RenderBGRA => {
915 format = dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM;
916 }
917 TextureFormat::RenderBGRAf16 => {
918 format = dxgiformat::DXGI_FORMAT_R32G32B32A32_FLOAT;
919 }
920 TextureFormat::RenderBGRAf32 => {
921 format = dxgiformat::DXGI_FORMAT_R32G32B32A32_FLOAT;
922 },
923 _ => {
924 panic!("Wrong format for update_render_target");
925 }
926 }
927 let texture_desc = d3d11::D3D11_TEXTURE2D_DESC {
928 Width: width as u32,
929 Height: height as u32,
930 MipLevels: 1,
931 ArraySize: 1,
932 Format: format,
933 SampleDesc: dxgitype::DXGI_SAMPLE_DESC {Count: 1, Quality: 0},
934 Usage: d3d11::D3D11_USAGE_DEFAULT,
935 BindFlags: d3d11::D3D11_BIND_RENDER_TARGET | d3d11::D3D11_BIND_SHADER_RESOURCE,
936 CPUAccessFlags: 0,
937 MiscFlags: 0,
938 };
939
940 let mut texture = ptr::null_mut();
941 let hr = unsafe {self.device.CreateTexture2D(&texture_desc, ptr::null(), &mut texture as *mut *mut _)};
942
943 if winerror::SUCCEEDED(hr) {
944 let mut shader_resource = ptr::null_mut();
945 unsafe {self.device.CreateShaderResourceView(texture as *mut _, ptr::null(), &mut shader_resource as *mut *mut _)};
946 cxtexture.platform.width = width;
947 cxtexture.platform.height = height;
948 cxtexture.platform.texture = Some(unsafe {ComPtr::from_raw(texture as *mut _)});
949 let mut shader_resource = ptr::null_mut();
950 unsafe {self.device.CreateShaderResourceView(texture as *mut _, ptr::null(), &mut shader_resource as *mut *mut _)};
951 cxtexture.platform.shader_resource = Some(unsafe {ComPtr::from_raw(shader_resource as *mut _)});
952
953 cxtexture.platform.render_target_view = Some(
954 self.create_render_target_view(
955 cxtexture.platform.texture.as_ref().unwrap()
956 ).expect("Cannot create_render_target_view")
957 );
958 }
959 else {
960 panic!("update_render_target failed");
961 }
962 return true
963 }
964
965 pub fn update_depth_stencil(&self, cxtexture: &mut CxTexture, dpi_factor: f32, size: Vec2) -> bool {
966
967 let width = if let Some(width) = cxtexture.desc.width {width as usize} else {(size.x * dpi_factor) as usize};
968 let height = if let Some(height) = cxtexture.desc.height {height as usize} else {(size.y * dpi_factor) as usize};
969
970 if cxtexture.platform.width == width && cxtexture.platform.height == height {
971 return false
972 }
973
974 let format;
975 match cxtexture.desc.format {
976 TextureFormat::Default | TextureFormat::Depth32Stencil8 => {
977 format = dxgiformat::DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
978 }
979 _ => {
980 panic!("Wrong format for update_depth_stencil");
981 }
982 }
983 let texture_desc = d3d11::D3D11_TEXTURE2D_DESC {
984 Width: width as u32,
985 Height: height as u32,
986 MipLevels: 1,
987 ArraySize: 1,
988 Format: format,
989 SampleDesc: dxgitype::DXGI_SAMPLE_DESC {Count: 1, Quality: 0},
990 Usage: d3d11::D3D11_USAGE_DEFAULT,
991 BindFlags: d3d11::D3D11_BIND_DEPTH_STENCIL, CPUAccessFlags: 0,
993 MiscFlags: 0,
994 };
995
996 let mut texture = ptr::null_mut();
997 let hr = unsafe {self.device.CreateTexture2D(&texture_desc, ptr::null(), &mut texture as *mut *mut _)};
998
999 if winerror::SUCCEEDED(hr) {
1000 let mut shader_resource = ptr::null_mut();
1001 unsafe {self.device.CreateShaderResourceView(texture as *mut _, ptr::null(), &mut shader_resource as *mut *mut _)};
1002 cxtexture.platform.width = width;
1003 cxtexture.platform.height = height;
1004 cxtexture.platform.texture = Some(unsafe {ComPtr::from_raw(texture as *mut _)});
1005
1006 if let Ok(dsview) = self.create_depth_stencil_view(cxtexture.platform.texture.as_ref().unwrap()) {
1012 cxtexture.platform.depth_stencil_view = Some(dsview);
1013 }
1014 else {
1015 panic!("create_depth_stencil_view failed");
1016 }
1017 }
1018 else {
1019 panic!("update_render_target failed");
1020 }
1021 return true
1022 }
1023
1024 pub fn update_platform_texture_image_bgra(&self, res: &mut CxPlatformTexture, width: usize, height: usize, image_u32: &Vec<u32>) {
1025
1026 if image_u32.len() != width * height {
1027 println!("update_platform_texture_image_bgra with wrong buffer_u32 size!");
1028 return;
1029 }
1030
1031 let sub_data = d3d11::D3D11_SUBRESOURCE_DATA {
1032 pSysMem: image_u32.as_ptr() as *const _,
1033 SysMemPitch: (width * 4) as u32,
1034 SysMemSlicePitch: 0
1035 };
1036
1037 let texture_desc = d3d11::D3D11_TEXTURE2D_DESC {
1038 Width: width as u32,
1039 Height: height as u32,
1040 MipLevels: 1,
1041 ArraySize: 1,
1042 Format: dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM,
1043 SampleDesc: dxgitype::DXGI_SAMPLE_DESC {
1044 Count: 1,
1045 Quality: 0
1046 },
1047 Usage: d3d11::D3D11_USAGE_DEFAULT,
1048 BindFlags: d3d11::D3D11_BIND_SHADER_RESOURCE,
1049 CPUAccessFlags: 0,
1050 MiscFlags: 0,
1051 };
1052 let mut texture = ptr::null_mut();
1053 let hr = unsafe {self.device.CreateTexture2D(&texture_desc, &sub_data, &mut texture as *mut *mut _)};
1054 if winerror::SUCCEEDED(hr) {
1055 let mut shader_resource = ptr::null_mut();
1056 unsafe {self.device.CreateShaderResourceView(
1057 texture as *mut _,
1058 ptr::null(),
1059 &mut shader_resource as *mut *mut _
1060 )};
1061 res.width = width;
1062 res.height = height;
1063 res.texture = Some(unsafe {ComPtr::from_raw(texture as *mut _)});
1064 res.shader_resource = Some(unsafe {ComPtr::from_raw(shader_resource as *mut _)});
1065 }
1066 else {
1067 panic!("update_platform_texture_image_bgra failed");
1068 }
1069 }
1070
1071 }
1331
1332#[derive(Clone, Default)]
1333pub struct CxPlatformView {
1334 pub view_uniforms: D3d11Buffer
1335}
1336
1337#[derive(Default, Clone)]
1338pub struct CxPlatformDrawCall {
1339 pub draw_uniforms: D3d11Buffer,
1340 pub uniforms: D3d11Buffer,
1341 pub inst_vbuf: D3d11Buffer
1342}
1343
1344#[derive(Default, Clone)]
1345pub struct D3d11Buffer {
1346 pub last_size: usize,
1347 pub buffer: Option<ComPtr<d3d11::ID3D11Buffer>>
1348}
1349
1350impl D3d11Buffer {
1351 pub fn update_with_data(&mut self, d3d11_cx: &D3d11Cx, bind_flags: u32, len_slots: usize, data: *const std::ffi::c_void) {
1352 let mut buffer = ptr::null_mut();
1353
1354 let buffer_desc = d3d11::D3D11_BUFFER_DESC {
1355 Usage: d3d11::D3D11_USAGE_DEFAULT,
1356 ByteWidth: (len_slots * 4) as u32,
1357 BindFlags: bind_flags,
1358 CPUAccessFlags: 0,
1359 MiscFlags: 0,
1360 StructureByteStride: 0
1361 };
1362
1363 let sub_data = d3d11::D3D11_SUBRESOURCE_DATA {
1364 pSysMem: data,
1365 SysMemPitch: 0,
1366 SysMemSlicePitch: 0
1367 };
1368
1369 let hr = unsafe {d3d11_cx.device.CreateBuffer(&buffer_desc, &sub_data, &mut buffer as *mut *mut _)};
1370 if winerror::SUCCEEDED(hr) {
1371 self.last_size = len_slots;
1372 self.buffer = Some(unsafe {ComPtr::from_raw(buffer as *mut _)});
1373 }
1374 else {
1375 panic!("Buffer create failed {}", len_slots);
1376 }
1377 }
1378
1379 pub fn update_with_u32_index_data(&mut self, d3d11_cx: &D3d11Cx, data: &[u32]) {
1380 self.update_with_data(d3d11_cx, d3d11::D3D11_BIND_INDEX_BUFFER, data.len(), data.as_ptr() as *const _);
1381 }
1382
1383 pub fn update_with_f32_vertex_data(&mut self, d3d11_cx: &D3d11Cx, data: &[f32]) {
1384 self.update_with_data(d3d11_cx, d3d11::D3D11_BIND_VERTEX_BUFFER, data.len(), data.as_ptr() as *const _);
1385 }
1386
1387 pub fn update_with_f32_constant_data(&mut self, d3d11_cx: &D3d11Cx, data: &[f32]) {
1388 let mut buffer = ptr::null_mut();
1389 if (data.len() & 3) != 0 { let mut new_data = data.to_vec();
1391 let steps = 4 - (data.len() & 3);
1392 for _ in 0..steps {
1393 new_data.push(0.0);
1394 };
1395 return self.update_with_f32_constant_data(d3d11_cx, &new_data);
1396 }
1397 let sub_data = d3d11::D3D11_SUBRESOURCE_DATA {
1398 pSysMem: data.as_ptr() as *const _,
1399 SysMemPitch: 0,
1400 SysMemSlicePitch: 0
1401 };
1402 let len_slots = data.len();
1403
1404 let buffer_desc = d3d11::D3D11_BUFFER_DESC {
1405 Usage: d3d11::D3D11_USAGE_DEFAULT,
1406 ByteWidth: (len_slots * 4) as u32,
1407 BindFlags: d3d11::D3D11_BIND_CONSTANT_BUFFER,
1408 CPUAccessFlags: 0,
1409 MiscFlags: 0,
1410 StructureByteStride: 0
1411 };
1412
1413 let hr = unsafe {d3d11_cx.device.CreateBuffer(&buffer_desc, &sub_data, &mut buffer as *mut *mut _)};
1414 if winerror::SUCCEEDED(hr) {
1415 self.last_size = len_slots;
1417 self.buffer = Some(unsafe {ComPtr::from_raw(buffer as *mut _)});
1418 }
1419 else {
1420 panic!("Buffer create failed {}", len_slots);
1421 }
1422 }
1423}
1424
1425
1426
1427#[derive(Default)]
1428pub struct CxPlatformTexture {
1429 width: usize,
1430 height: usize,
1431 slots_per_pixel: usize,
1432 texture: Option<ComPtr<d3d11::ID3D11Texture2D>>,
1433 shader_resource: Option<ComPtr<d3d11::ID3D11ShaderResourceView>>,
1434 d3d11_resource: Option<ComPtr<d3d11::ID3D11Resource>>,
1435 render_target_view: Option<ComPtr<d3d11::ID3D11RenderTargetView>>,
1438 depth_stencil_view: Option<ComPtr<d3d11::ID3D11DepthStencilView>>
1439}
1440
1441#[derive(Default, Clone)]
1442pub struct CxPlatformPass {
1443 pass_uniforms: D3d11Buffer,
1444 blend_state: Option<ComPtr<d3d11::ID3D11BlendState>>,
1445 raster_state: Option<ComPtr<d3d11::ID3D11RasterizerState>>,
1446 depth_stencil_state: Option<ComPtr<d3d11::ID3D11DepthStencilState>>
1447}
1448
1449