makepad_platform/os/windows/
d3d11.rs

1use crate::{
2    makepad_shader_compiler::generate_hlsl,
3    makepad_math::*,
4    os::{
5        windows::win32_app::{TRUE, FALSE,},
6        windows::win32_window::Win32Window,
7    },
8    texture::Texture,
9    draw_list::DrawListId,
10    event::WindowGeom,
11    cx::Cx,
12    draw_shader::CxDrawShaderMapping,
13    pass::{PassClearColor, PassClearDepth, PassId},
14    window::WindowId,
15    texture::{ 
16        TextureFormat,
17        TexturePixel,
18        TextureId,
19        CxTexture
20    },  
21    windows::{
22        core::{
23            PCSTR,
24            //ComInterface,
25            Interface,
26        },
27        Win32::{
28            Foundation::{
29                HINSTANCE,
30                HANDLE,
31                S_FALSE,
32            },
33            Graphics::{
34                Direct3D11::{
35                    D3D11_BIND_INDEX_BUFFER,
36                    D3D11_BIND_VERTEX_BUFFER,
37                    D3D11_VIEWPORT,
38                    D3D11_BUFFER_DESC,
39                    D3D11_USAGE_DEFAULT,
40                    D3D11_BIND_CONSTANT_BUFFER,
41                    D3D11_RESOURCE_MISC_FLAG,
42                    D3D11_SUBRESOURCE_DATA,
43                    D3D11_CREATE_DEVICE_FLAG,
44                    D3D11_SDK_VERSION,
45                    D3D11_BIND_FLAG,
46                    D3D11_BIND_SHADER_RESOURCE,
47                    D3D11_TEXTURE2D_DESC,
48                    D3D11_BIND_RENDER_TARGET,
49                    D3D11_BIND_DEPTH_STENCIL,
50                    D3D11_DEPTH_STENCIL_DESC,
51                    D3D11_DEPTH_WRITE_MASK_ALL,
52                    D3D11_COMPARISON_LESS_EQUAL,
53                    D3D11_DEPTH_STENCILOP_DESC,
54                    D3D11_STENCIL_OP_REPLACE,
55                    D3D11_COMPARISON_ALWAYS,
56                    D3D11_DEPTH_STENCIL_VIEW_DESC,
57                    D3D11_DSV_DIMENSION_TEXTURE2D,
58                    D3D11_CLEAR_DEPTH,
59                    D3D11_CLEAR_STENCIL,
60                    D3D11_BLEND_DESC,
61                    D3D11_RENDER_TARGET_BLEND_DESC,
62                    D3D11_BLEND_ONE,
63                    D3D11_BLEND_INV_SRC_ALPHA,
64                    D3D11_BLEND_OP_ADD,
65                    D3D11_COLOR_WRITE_ENABLE_ALL,
66                    D3D11_RASTERIZER_DESC,
67                    D3D11_CULL_NONE,
68                    D3D11_FILL_SOLID,
69                    D3D11_INPUT_ELEMENT_DESC,
70                    D3D11_INPUT_PER_VERTEX_DATA,
71                    D3D11_INPUT_PER_INSTANCE_DATA,
72                    D3D11_MAPPED_SUBRESOURCE,
73                    D3D11_USAGE_DYNAMIC,
74                    D3D11_CPU_ACCESS_WRITE,
75                    D3D11_MAP_WRITE_DISCARD,
76                    D3D11_QUERY_DESC,
77                    D3D11_QUERY_EVENT,
78                    ID3D11Device,
79                    ID3D11DeviceContext,
80                    ID3D11RenderTargetView,
81                    ID3D11Texture2D,
82                    ID3D11ShaderResourceView,
83                    ID3D11DepthStencilView,
84                    ID3D11BlendState,
85                    ID3D11RasterizerState,
86                    ID3D11DepthStencilState,
87                    ID3D11PixelShader,
88                    ID3D11VertexShader,
89                    ID3D11InputLayout,
90                    ID3D11Buffer,
91                    D3D11CreateDevice,
92                    ID3D11Resource,
93                    ID3D11Query,
94                },
95                Direct3D::{
96                    Fxc::D3DCompile,
97                    ID3DBlob,
98                    D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
99                    D3D_DRIVER_TYPE_UNKNOWN,
100                    D3D_FEATURE_LEVEL_11_0,
101                },
102                Dxgi::{
103                    IDXGIFactory2,
104                    IDXGIResource,
105                    IDXGISwapChain1,
106                    CreateDXGIFactory2,
107                    DXGI_SWAP_CHAIN_DESC1,
108                    DXGI_USAGE_RENDER_TARGET_OUTPUT,
109                    DXGI_SCALING_NONE,
110                    DXGI_SWAP_EFFECT_FLIP_DISCARD,
111                    DXGI_RGBA,
112                    Common::{
113                        DXGI_FORMAT,
114                        DXGI_ALPHA_MODE_IGNORE,
115                        DXGI_FORMAT_R8_UNORM, 
116                        DXGI_FORMAT_R8G8_UNORM,
117                        DXGI_FORMAT_B8G8R8A8_UNORM,
118                        DXGI_SAMPLE_DESC,
119                        DXGI_FORMAT_R32G32B32A32_FLOAT,
120                        DXGI_FORMAT_R16_FLOAT, 
121                        //DXGI_FORMAT_D32_FLOAT_S8X 24_UINT,
122                        DXGI_FORMAT_D32_FLOAT,
123                        DXGI_FORMAT_R32_UINT,
124                        DXGI_FORMAT_R32_FLOAT,
125                        DXGI_FORMAT_R32G32_FLOAT,
126                        DXGI_FORMAT_R32G32B32_FLOAT,
127                    },
128                },
129            },
130        },
131    },
132};
133
134impl Cx {
135    
136    fn render_view(
137        &mut self,
138        pass_id: PassId,
139        draw_list_id: DrawListId,
140        zbias: &mut f32,
141        zbias_step: f32,
142        d3d11_cx: &D3d11Cx
143    ) {
144        // tad ugly otherwise the borrow checker locks 'self' and we can't recur
145        let draw_items_len = self.draw_lists[draw_list_id].draw_items.len();
146        
147        {
148            let draw_list = &mut self.draw_lists[draw_list_id];
149            draw_list.os.draw_list_uniforms.update_with_f32_constant_data(d3d11_cx, draw_list.draw_list_uniforms.as_slice());
150        }
151        
152        for draw_item_id in 0..draw_items_len {
153            if let Some(sub_list_id) = self.draw_lists[draw_list_id].draw_items[draw_item_id].kind.sub_list() {
154                self.render_view(
155                    pass_id,
156                    sub_list_id,
157                    zbias,
158                    zbias_step,
159                    d3d11_cx,
160                );
161            }
162            else {
163                let draw_list = &mut self.draw_lists[draw_list_id];
164                let draw_item = &mut draw_list.draw_items[draw_item_id];
165                let draw_call = if let Some(draw_call) = draw_item.kind.draw_call_mut() {
166                    draw_call
167                } else {
168                    continue;
169                };
170                let sh = &self.draw_shaders[draw_call.draw_shader.draw_shader_id];
171                if sh.os_shader_id.is_none() { // shader didnt compile somehow
172                    continue;
173                }
174                if sh.mapping.uses_time {
175                    self.demo_time_repaint = true;
176                }
177                let shp = &self.draw_shaders.os_shaders[sh.os_shader_id.unwrap()];
178
179                if draw_call.instance_dirty {
180                    draw_call.instance_dirty = false;
181                    if draw_item.instances.as_ref().unwrap().len() == 0 {
182                        continue;
183                    }
184                    // update the instance buffer data
185                    draw_item.os.inst_vbuf.update_with_f32_vertex_data(d3d11_cx, draw_item.instances.as_ref().unwrap());
186                }
187                
188                // update the zbias uniform if we have it.
189                draw_call.draw_call_uniforms.set_zbias(*zbias);
190                *zbias += zbias_step;
191                
192                if draw_call.uniforms_dirty {
193                    draw_call.uniforms_dirty = false;
194                    draw_item.os.draw_call_uniforms.update_with_f32_constant_data(d3d11_cx, draw_call.draw_call_uniforms.as_slice());
195                    
196                }
197                if draw_call.user_uniforms.len() != 0 {
198                    draw_item.os.user_uniforms.update_with_f32_constant_data(d3d11_cx, &mut draw_call.user_uniforms);
199                }
200                
201                let instances = (draw_item.instances.as_ref().unwrap().len() / sh.mapping.instances.total_slots) as u64;
202                
203                if instances == 0 {
204                    continue;
205                }
206                
207                let geometry_id = if let Some(geometry_id) = draw_call.geometry_id {geometry_id}
208                else {
209                    continue;
210                };
211                
212                let geometry = &mut self.geometries[geometry_id];
213                
214                if geometry.dirty {
215                    geometry.os.geom_ibuf.update_with_u32_index_data(d3d11_cx, &geometry.indices);
216                    geometry.os.geom_vbuf.update_with_f32_vertex_data(d3d11_cx, &geometry.vertices);
217                    geometry.dirty = false;
218                }
219                
220                unsafe {
221                    d3d11_cx.context.VSSetShader(&shp.vertex_shader, None);
222                    d3d11_cx.context.PSSetShader(&shp.pixel_shader, None);
223                    d3d11_cx.context.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
224                    d3d11_cx.context.IASetInputLayout(&shp.input_layout);
225                    
226                    let geom_ibuf = geometry.os.geom_ibuf.buffer.as_ref().unwrap();
227                    d3d11_cx.context.IASetIndexBuffer(geom_ibuf, DXGI_FORMAT_R32_UINT, 0);
228                    
229                    let geom_slots = sh.mapping.geometries.total_slots;
230                    let inst_slots = sh.mapping.instances.total_slots;
231                    let strides = [(geom_slots * 4) as u32, (inst_slots * 4) as u32];
232                    let offsets = [0u32, 0u32];
233                    let buffers = [geometry.os.geom_vbuf.buffer.clone(), draw_item.os.inst_vbuf.buffer.clone()];
234                    d3d11_cx.context.IASetVertexBuffers(0, 2, Some(buffers.as_ptr()), Some(strides.as_ptr()), Some(offsets.as_ptr()));
235                    
236                    fn buffer_slot(d3d11_cx: &D3d11Cx, index: u32, buffer: &Option<ID3D11Buffer>) {
237                        unsafe {
238                            if let Some(buffer) = buffer.clone() {
239                                let buffers = [Some(buffer)];
240                                d3d11_cx.context.VSSetConstantBuffers(index, Some(&buffers));
241                                d3d11_cx.context.PSSetConstantBuffers(index, Some(&buffers));
242                            }
243                            else {
244                                d3d11_cx.context.VSSetConstantBuffers(index, None);
245                                d3d11_cx.context.PSSetConstantBuffers(index, None);
246                            }
247                        }
248                    }
249                    buffer_slot(d3d11_cx, 0, &shp.live_uniforms.buffer);
250                    buffer_slot(d3d11_cx, 1, &shp.const_table_uniforms.buffer);
251                    buffer_slot(d3d11_cx, 2, &draw_item.os.draw_call_uniforms.buffer);
252                    buffer_slot(d3d11_cx, 3, &self.passes[pass_id].os.pass_uniforms.buffer);
253                    buffer_slot(d3d11_cx, 4, &draw_list.os.draw_list_uniforms.buffer);
254                    buffer_slot(d3d11_cx, 5, &draw_item.os.user_uniforms.buffer);
255                }
256                
257                for i in 0..sh.mapping.textures.len() {
258                    
259                    let texture_id = if let Some(texture) = &draw_call.texture_slots[i] {
260                        texture.texture_id()
261                    } else {
262                        continue;
263                    };
264                    
265                    let cxtexture = &mut self.textures[texture_id];
266                    
267                    if cxtexture.format.is_shared() {
268                        cxtexture.update_shared_texture(
269                            &d3d11_cx.device,
270                        );
271                    }
272                    else if cxtexture.format.is_vec(){
273                        cxtexture.update_vec_texture(
274                            d3d11_cx,
275                        );
276                    }
277                    unsafe {
278                        if let Some(sr) = &cxtexture.os.shader_resource_view {
279                            d3d11_cx.context.PSSetShaderResources(i as u32, Some(&[Some(sr.clone())]));
280                            d3d11_cx.context.VSSetShaderResources(i as u32, Some(&[Some(sr.clone())]));
281                        }
282                        else {
283                            d3d11_cx.context.PSSetShaderResources(i as u32, None);
284                            d3d11_cx.context.VSSetShaderResources(i as u32, None);
285                        }
286                    }
287                }
288                //if self.passes[pass_id].debug{
289                // println!("DRAWING {} {}", geometry.indices.len(), instances);
290                //}
291                unsafe {
292                    d3d11_cx.context.DrawIndexedInstanced(
293                        geometry.indices.len() as u32,
294                        instances as u32,
295                        0,
296                        0,
297                        0
298                    )
299                };
300            }
301        }
302    }
303
304    pub fn get_shared_handle(&self, _texture: &Texture) -> HANDLE {
305        self.textures[_texture.texture_id()].os.shared_handle
306    }
307
308    pub fn setup_pass_render_targets(&mut self, pass_id: PassId, first_target: &Option<ID3D11RenderTargetView >, d3d11_cx: &D3d11Cx) {
309        
310        let dpi_factor = self.passes[pass_id].dpi_factor.unwrap();
311        
312        let pass_rect = self.get_pass_rect(pass_id, dpi_factor).unwrap();
313        self.passes[pass_id].set_ortho_matrix(pass_rect.pos, pass_rect.size);
314        self.passes[pass_id].paint_dirty = false;
315
316        self.passes[pass_id].set_dpi_factor(dpi_factor);
317        
318        let viewport = D3D11_VIEWPORT {
319            Width: (pass_rect.size.x * dpi_factor) as f32,
320            Height: (pass_rect.size.y * dpi_factor) as f32,
321            MinDepth: 0.,
322            MaxDepth: 1.,
323            TopLeftX: 0.0,
324            TopLeftY: 0.0
325        };
326        unsafe {
327            d3d11_cx.context.RSSetViewports(Some(&[viewport]));
328        }
329        if viewport.Width < 1.0 || viewport.Height < 1.0{
330            return
331        }
332        // set up the color texture array
333        let mut color_textures = Vec::<Option<ID3D11RenderTargetView>>::new();
334        
335        if let Some(render_target) = first_target {
336            color_textures.push(Some(render_target.clone()));
337            let color = self.passes[pass_id].clear_color;
338            let color = [color.x, color.y, color.z, color.w];
339            unsafe {d3d11_cx.context.ClearRenderTargetView(first_target.as_ref().unwrap(), &color)}
340        }
341        else {
342            for color_texture in self.passes[pass_id].color_textures.iter() {
343                let cxtexture = &mut self.textures[color_texture.texture.texture_id()];
344                let size = pass_rect.size * dpi_factor;
345                cxtexture.update_render_target(d3d11_cx, size.x as usize, size.y as usize);
346                let is_initial = cxtexture.take_initial();
347                let render_target = cxtexture.os.render_target_view.clone();
348                color_textures.push(Some(render_target.clone().unwrap()));
349                // possibly clear it
350                match color_texture.clear_color {
351                    PassClearColor::InitWith(color) => {
352                        if is_initial {
353                            let color = [color.x, color.y, color.z, color.w];
354                            unsafe {d3d11_cx.context.ClearRenderTargetView(render_target.as_ref().unwrap(), &color)}
355                        }
356                    },
357                    PassClearColor::ClearWith(color) => {
358                        let color = [color.x, color.y, color.z, color.w];
359                        unsafe {d3d11_cx.context.ClearRenderTargetView(render_target.as_ref().unwrap(), &color)}
360                    }
361                }
362            }
363        }
364        
365        // attach/clear depth buffers, if any
366        if let Some(depth_texture) = &self.passes[pass_id].depth_texture {
367            let cxtexture = &mut self.textures[depth_texture.texture_id()];
368            let size = pass_rect.size * dpi_factor;
369            cxtexture.update_depth_stencil(d3d11_cx, size.x as usize, size.y as usize);
370            let is_initial = cxtexture.take_initial();
371                        
372            match self.passes[pass_id].clear_depth {
373                PassClearDepth::InitWith(depth_clear) => {
374                    if is_initial {
375                        unsafe {d3d11_cx.context.ClearDepthStencilView(
376                            cxtexture.os.depth_stencil_view.as_ref().unwrap(),
377                            D3D11_CLEAR_DEPTH.0 as u32 | D3D11_CLEAR_STENCIL.0 as u32,
378                            depth_clear,
379                            0
380                        )}
381                    }
382                },
383                PassClearDepth::ClearWith(depth_clear) => {
384                    unsafe {d3d11_cx.context.ClearDepthStencilView(
385                        cxtexture.os.depth_stencil_view.as_ref().unwrap(),
386                        D3D11_CLEAR_DEPTH.0 as u32 | D3D11_CLEAR_STENCIL.0 as u32,
387                        depth_clear,
388                        0
389                    )}
390                }
391            }
392            unsafe {d3d11_cx.context.OMSetRenderTargets(
393                Some(&color_textures),
394                None, //cxtexture.os.depth_stencil_view.as_ref().unwrap()
395            )}
396        }
397        else {
398            unsafe {d3d11_cx.context.OMSetRenderTargets(
399                Some(&color_textures),
400                None
401            )}
402        }
403        
404        // create depth, blend and raster states
405        self.passes[pass_id].os.set_states(d3d11_cx);
406        
407        let cxpass = &mut self.passes[pass_id];
408        
409        cxpass.os.pass_uniforms.update_with_f32_constant_data(&d3d11_cx, cxpass.pass_uniforms.as_slice());
410    }
411    
412    pub fn draw_pass_to_window(&mut self, pass_id: PassId, vsync: bool, d3d11_window: &mut D3d11Window, d3d11_cx: &D3d11Cx) {
413        // let time1 = Cx::profile_time_ns();
414        let draw_list_id = self.passes[pass_id].main_draw_list_id.unwrap();
415        
416        self.setup_pass_render_targets(pass_id, &d3d11_window.render_target_view, d3d11_cx);
417        
418        let mut zbias = 0.0;
419        let zbias_step = self.passes[pass_id].zbias_step;
420        
421        self.render_view(
422            pass_id,
423            draw_list_id,
424            &mut zbias,
425            zbias_step,
426            d3d11_cx
427        );
428        d3d11_window.present(vsync);
429        if d3d11_window.first_draw {
430            d3d11_window.win32_window.show();
431            d3d11_window.first_draw = false;
432        }
433        //println!("{}", (Cx::profile_time_ns() - time1)as f64 / 1000.0);
434    }
435    
436    pub fn draw_pass_to_texture(&mut self, pass_id: PassId,  d3d11_cx: &D3d11Cx,texture_id: Option<TextureId>) {
437        // let time1 = Cx::profile_time_ns();
438        let draw_list_id = self.passes[pass_id].main_draw_list_id.unwrap();
439        
440        if let Some(texture_id) = texture_id{
441            let render_target_view = self.textures[texture_id].os.render_target_view.clone();
442            self.setup_pass_render_targets(pass_id, &render_target_view, d3d11_cx);
443        }
444        else{
445            self.setup_pass_render_targets(pass_id, &None, d3d11_cx);
446        }
447            
448        let mut zbias = 0.0;
449        let zbias_step = self.passes[pass_id].zbias_step;
450        self.render_view(
451            pass_id,
452            draw_list_id,
453            &mut zbias,
454            zbias_step,
455            &d3d11_cx,
456        );
457    }
458    
459    pub (crate) fn hlsl_compile_shaders(&mut self, d3d11_cx: &D3d11Cx) {
460        for draw_shader_ptr in &self.draw_shaders.compile_set {
461            if let Some(item) = self.draw_shaders.ptr_to_item.get(&draw_shader_ptr) {
462                let cx_shader = &mut self.draw_shaders.shaders[item.draw_shader_id];
463                let draw_shader_def = self.shader_registry.draw_shader_defs.get(&draw_shader_ptr);
464                let hlsl = generate_hlsl::generate_shader(
465                    draw_shader_def.as_ref().unwrap(),
466                    &cx_shader.mapping.const_table,
467                    &self.shader_registry
468                );
469                
470                if cx_shader.mapping.flags.debug {
471                    crate::log!("{}", hlsl);
472                }
473                // lets see if we have the shader already
474                for (index, ds) in self.draw_shaders.os_shaders.iter().enumerate() {
475                    if ds.hlsl == hlsl {
476                        cx_shader.os_shader_id = Some(index);
477                        break;
478                    }
479                }
480                if cx_shader.os_shader_id.is_none() {
481                    if let Some(shp) = CxOsDrawShader::new(d3d11_cx, hlsl, &cx_shader.mapping) {
482                        cx_shader.os_shader_id = Some(self.draw_shaders.os_shaders.len());
483                        self.draw_shaders.os_shaders.push(shp);
484                    }
485                }
486            }
487        }
488        self.draw_shaders.compile_set.clear();
489    }
490
491    pub fn share_texture_for_presentable_image(
492        &mut self,
493        texture: &Texture,
494    ) -> crate::cx_stdin::SharedPresentableImageOsHandle {
495        let cxtexture = &mut self.textures[texture.texture_id()];
496        cxtexture.update_shared_texture(self.os.d3d11_device.as_ref().unwrap());
497        cxtexture.os.shared_handle.0 as u64
498    }
499}
500
501fn texture_pixel_to_dx11_pixel(pix:&TexturePixel)->DXGI_FORMAT{
502    match pix{
503        TexturePixel::BGRAu8 => DXGI_FORMAT_B8G8R8A8_UNORM,
504        TexturePixel::RGBAf16 => DXGI_FORMAT_R16_FLOAT,
505        TexturePixel::RGBAf32 => DXGI_FORMAT_R32G32B32A32_FLOAT,
506        TexturePixel::Ru8  => DXGI_FORMAT_R8_UNORM,
507        TexturePixel::RGu8  => DXGI_FORMAT_R8G8_UNORM,
508        TexturePixel::Rf32  => DXGI_FORMAT_R32_FLOAT,
509        TexturePixel::D32 => DXGI_FORMAT_D32_FLOAT,
510    }   
511}
512
513pub struct D3d11Window {
514    pub window_id: WindowId,
515    pub is_in_resize: bool,
516    pub window_geom: WindowGeom,
517    pub win32_window: Box<Win32Window>,
518    pub render_target_view: Option<ID3D11RenderTargetView >,
519    pub swap_texture: Option<ID3D11Texture2D >,
520    pub alloc_size: DVec2,
521    pub first_draw: bool,
522    pub swap_chain: IDXGISwapChain1,
523}
524
525impl D3d11Window {
526    pub fn new(window_id: WindowId, d3d11_cx: &D3d11Cx, inner_size: DVec2, position: Option<DVec2>, title: &str) -> D3d11Window {
527
528        // create window, and then initialize it; this is needed because
529        // GWLP_USERDATA needs to reference a stable and existing window
530        let mut win32_window = Box::new(Win32Window::new(window_id, title, position));
531        win32_window.init(inner_size);
532        
533        let wg = win32_window.get_window_geom();
534        
535        let sc_desc = DXGI_SWAP_CHAIN_DESC1 {
536            AlphaMode: DXGI_ALPHA_MODE_IGNORE,
537            BufferCount: 2,
538            Width: (wg.inner_size.x * wg.dpi_factor) as u32,
539            Height: (wg.inner_size.y * wg.dpi_factor) as u32,
540            Format: DXGI_FORMAT_B8G8R8A8_UNORM,
541            Flags: 0,
542            BufferUsage: DXGI_USAGE_RENDER_TARGET_OUTPUT,
543            SampleDesc: DXGI_SAMPLE_DESC {Count: 1, Quality: 0,},
544            Scaling: DXGI_SCALING_NONE,
545            Stereo: FALSE,
546            SwapEffect: DXGI_SWAP_EFFECT_FLIP_DISCARD,
547        };
548        
549        unsafe {
550            let swap_chain = d3d11_cx.factory.CreateSwapChainForHwnd(
551                &d3d11_cx.device,
552                win32_window.hwnd,
553                &sc_desc,
554                None,
555                None,
556            ).unwrap();
557            
558            let swap_texture = swap_chain.GetBuffer(0).unwrap();
559            let mut render_target_view = None;
560            d3d11_cx.device.CreateRenderTargetView(&swap_texture, None, Some(&mut render_target_view)).unwrap();
561            swap_chain.SetBackgroundColor(&mut DXGI_RGBA {
562                r: 0.3,
563                g: 0.3,
564                b: 0.3,
565                a: 1.0
566            }).unwrap();
567            D3d11Window {
568                first_draw: true,
569                is_in_resize: false,
570                window_id: window_id,
571                alloc_size: wg.inner_size,
572                window_geom: wg,
573                win32_window: win32_window,
574                swap_texture: Some(swap_texture),
575                render_target_view: render_target_view,
576                swap_chain: swap_chain,
577            }
578        }
579    }
580    
581    pub fn start_resize(&mut self) {
582        self.is_in_resize = true;
583    }
584    
585    // switch back to swapchain
586    pub fn stop_resize(&mut self) {
587        self.is_in_resize = false;
588        self.alloc_size = DVec2::default();
589    }
590    
591    
592    pub fn resize_buffers(&mut self, d3d11_cx: &D3d11Cx) {
593        if self.alloc_size == self.window_geom.inner_size {
594            return
595        }
596        self.alloc_size = self.window_geom.inner_size;
597        self.swap_texture = None;
598        self.render_target_view = None;
599        
600        unsafe {
601            let wg = &self.window_geom;
602            self.swap_chain.ResizeBuffers(
603                2,
604                (wg.inner_size.x * wg.dpi_factor) as u32,
605                (wg.inner_size.y * wg.dpi_factor) as u32,
606                DXGI_FORMAT_B8G8R8A8_UNORM,
607                0
608            ).unwrap();
609            
610            let swap_texture = self.swap_chain.GetBuffer(0).unwrap();
611            let mut render_target_view = None;
612            d3d11_cx.device.CreateRenderTargetView(&swap_texture, None, Some(&mut render_target_view)).unwrap();
613            
614            self.swap_texture = Some(swap_texture);
615            self.render_target_view = render_target_view;
616        }
617    }
618    
619    pub fn present(&mut self, vsync: bool) {
620        unsafe {self.swap_chain.Present(if vsync {1}else {0}, 0).unwrap()};
621    }
622    
623}
624
625#[derive(Clone)]
626pub struct D3d11Cx {
627    pub device: ID3D11Device,
628    pub context: ID3D11DeviceContext,
629    pub query: ID3D11Query,
630    pub factory: IDXGIFactory2,
631}
632
633impl D3d11Cx {
634    
635    pub fn new() -> D3d11Cx {
636        unsafe {
637            let factory: IDXGIFactory2 = CreateDXGIFactory2(0).unwrap();
638            let adapter = factory.EnumAdapters(0).unwrap();
639            let mut device: Option<ID3D11Device> = None;
640            let mut context: Option<ID3D11DeviceContext> = None;
641            let mut query: Option<ID3D11Query> = None;
642            D3D11CreateDevice(
643                &adapter,
644                D3D_DRIVER_TYPE_UNKNOWN,
645                HINSTANCE(0),
646                D3D11_CREATE_DEVICE_FLAG(0),
647                Some(&[D3D_FEATURE_LEVEL_11_0]),
648                D3D11_SDK_VERSION,
649                Some(&mut device),
650                None,
651                Some(&mut context)
652            ).unwrap();
653
654            let device = device.unwrap();
655            let context = context.unwrap();
656
657            device.CreateQuery(&D3D11_QUERY_DESC {
658                Query: D3D11_QUERY_EVENT,
659                MiscFlags: 0,
660            },Some(&mut query)).unwrap();
661
662            let query = query.unwrap();
663
664            D3d11Cx {
665                device,
666                context,
667                factory,
668                query,
669            }
670        }
671    }
672
673    pub fn start_querying(&self) {
674
675        // QUERY_EVENT signals when rendering is complete
676        unsafe { self.context.End(&self.query) };
677    }
678
679    pub fn is_gpu_done(&self) -> bool {
680        let hresult = unsafe { (Interface::vtable(&self.context).GetData)(Interface::as_raw(&self.context),Interface::as_raw(&self.query),std::ptr::null_mut(),0,0) };
681        hresult != S_FALSE
682    }
683}
684
685#[derive(Clone, Default)]
686pub struct CxOsDrawList {
687    pub draw_list_uniforms: D3d11Buffer
688}
689
690#[derive(Default, Clone)]
691pub struct CxOsDrawCall {
692    pub draw_call_uniforms: D3d11Buffer,
693    pub user_uniforms: D3d11Buffer,
694    pub inst_vbuf: D3d11Buffer
695}
696
697#[derive(Default, Clone)]
698pub struct D3d11Buffer {
699    pub last_size: usize,
700    pub buffer: Option<ID3D11Buffer>
701}
702
703impl D3d11Buffer {
704    fn create_buffer_or_update(&mut self, d3d11_cx: &D3d11Cx, buffer_desc: &D3D11_BUFFER_DESC, sub_data: &D3D11_SUBRESOURCE_DATA, len_slots: usize, data: *const std::ffi::c_void) {
705        if self.last_size == len_slots {
706            let mut mapped = D3D11_MAPPED_SUBRESOURCE::default();
707            let p_mapped : *mut _ = &mut mapped;
708            unsafe {
709                d3d11_cx.context.Map(self.buffer.as_ref().unwrap(),
710                        0, D3D11_MAP_WRITE_DISCARD, 0, Some(p_mapped)).unwrap();
711
712                std::ptr::copy_nonoverlapping(data, mapped.pData, len_slots * 4);
713                d3d11_cx.context.Unmap(self.buffer.as_ref().unwrap(), 0);
714            }
715        } else {
716            self.last_size = len_slots;
717            unsafe { d3d11_cx.device.CreateBuffer(buffer_desc, Some(sub_data), Some(&mut self.buffer)).unwrap() }
718        }
719    }
720
721    pub fn update_with_data(&mut self, d3d11_cx: &D3d11Cx, bind_flags: D3D11_BIND_FLAG, len_slots: usize, data: *const std::ffi::c_void) {
722        let buffer_desc = D3D11_BUFFER_DESC {
723            Usage: D3D11_USAGE_DYNAMIC,
724            ByteWidth: (len_slots * 4) as u32,
725            BindFlags: bind_flags.0 as u32,
726            CPUAccessFlags: D3D11_CPU_ACCESS_WRITE.0 as u32,
727            MiscFlags: 0,
728            StructureByteStride: 0
729        };
730        
731        let sub_data = D3D11_SUBRESOURCE_DATA {
732            pSysMem: data,
733            SysMemPitch: 0,
734            SysMemSlicePitch: 0
735        };
736        self.create_buffer_or_update(d3d11_cx, &buffer_desc, &sub_data, len_slots, data);
737    }
738    
739    pub fn update_with_u32_index_data(&mut self, d3d11_cx: &D3d11Cx, data: &[u32]) {
740        self.update_with_data(d3d11_cx, D3D11_BIND_INDEX_BUFFER, data.len(), data.as_ptr() as *const _);
741    }
742    
743    pub fn update_with_f32_vertex_data(&mut self, d3d11_cx: &D3d11Cx, data: &[f32]) {
744        self.update_with_data(d3d11_cx, D3D11_BIND_VERTEX_BUFFER, data.len(), data.as_ptr() as *const _);
745    }
746    
747    pub fn update_with_f32_constant_data(&mut self, d3d11_cx: &D3d11Cx, data: &[f32]) {
748        if data.len() == 0 {
749            return
750        }
751        if (data.len() & 3) != 0 { // we have to align the data at the end
752            let mut new_data = data.to_vec();
753            let steps = 4 - (data.len() & 3);
754            for _ in 0..steps {
755                new_data.push(0.0);
756            };
757            return self.update_with_f32_constant_data(d3d11_cx, &new_data);
758        }
759        let sub_data = D3D11_SUBRESOURCE_DATA {
760            pSysMem: data.as_ptr() as *const _,
761            SysMemPitch: 0,
762            SysMemSlicePitch: 0
763        };
764        let len_slots = data.len();
765        
766        let buffer_desc = D3D11_BUFFER_DESC {
767            Usage: D3D11_USAGE_DYNAMIC,
768            ByteWidth: (len_slots * 4) as u32,
769            BindFlags: D3D11_BIND_CONSTANT_BUFFER.0 as u32,
770            CPUAccessFlags: D3D11_CPU_ACCESS_WRITE.0 as u32,
771            MiscFlags: 0,
772            StructureByteStride: 0
773        };
774        let data = unsafe { core::slice::from_raw_parts(data.as_ptr() as *const u8, std::mem::size_of::<f32>() * data.len()).as_ptr() as *const _ };
775        self.create_buffer_or_update(d3d11_cx, &buffer_desc, &sub_data, len_slots, data);
776    }
777}
778
779
780#[derive(Default)]
781pub struct CxOsTexture {
782    texture: Option<ID3D11Texture2D >,
783    pub shared_handle: HANDLE,
784    shader_resource_view: Option<ID3D11ShaderResourceView >,
785    render_target_view: Option<ID3D11RenderTargetView >,
786    depth_stencil_view: Option<ID3D11DepthStencilView >,
787}
788
789impl CxTexture {
790    
791    pub fn update_vec_texture(
792        &mut self,
793        d3d11_cx: &D3d11Cx,
794    ) {
795        // TODO maybe we can update the data instead of making a new texture?
796        if self.alloc_vec(){}
797        if !self.take_updated().is_empty() {
798            fn get_descs(format: DXGI_FORMAT, width: usize, height: usize, bpp: usize, data: *const std::ffi::c_void)->(D3D11_SUBRESOURCE_DATA,D3D11_TEXTURE2D_DESC) {
799                let sub_data = D3D11_SUBRESOURCE_DATA {
800                    pSysMem: data,
801                    SysMemPitch: (width * bpp) as u32,
802                    SysMemSlicePitch: 0
803                };
804                                            
805                let texture_desc = D3D11_TEXTURE2D_DESC {
806                    Width: width as u32,
807                    Height: height as u32,
808                    MipLevels: 1,
809                    ArraySize: 1,
810                    Format: format,
811                    SampleDesc: DXGI_SAMPLE_DESC {
812                        Count: 1,
813                        Quality: 0
814                    },
815                    Usage: D3D11_USAGE_DEFAULT,
816                    BindFlags: D3D11_BIND_SHADER_RESOURCE.0 as u32,
817                    CPUAccessFlags: 0,
818                    MiscFlags: 0,
819                };
820                (sub_data,texture_desc)
821            }
822            
823            let (sub_data, texture_desc) = match &self.format{
824                TextureFormat::VecBGRAu8_32{width, height, data, ..}=>{
825                    get_descs(DXGI_FORMAT_B8G8R8A8_UNORM, *width, *height, 4, data.as_ref().unwrap().as_ptr() as *const _)
826                }
827                TextureFormat::VecRGBAf32{width, height, data, ..}=>{
828                    get_descs(DXGI_FORMAT_R32G32B32A32_FLOAT, *width, *height, 16, data.as_ref().unwrap().as_ptr() as *const _)
829                }
830                TextureFormat::VecRu8{width, height, data, ..}=>{
831                    get_descs(DXGI_FORMAT_R8_UNORM, *width, *height, 1, data.as_ref().unwrap().as_ptr() as *const _)
832                }
833                TextureFormat::VecRGu8{width, height, data, ..}=>{
834                    get_descs(DXGI_FORMAT_R8G8_UNORM, *width, *height, 1, data.as_ref().unwrap().as_ptr() as *const _)
835                }
836                TextureFormat::VecRf32{width, height, data, ..}=>{
837                    get_descs(DXGI_FORMAT_R32_FLOAT, *width, *height, 4, data.as_ref().unwrap().as_ptr() as *const _)
838                }
839                _=>panic!()
840            };
841                                        
842            let mut texture = None;
843            unsafe {d3d11_cx.device.CreateTexture2D(&texture_desc, Some(&sub_data), Some(&mut texture)).unwrap()};
844            let resource: ID3D11Resource = texture.clone().unwrap().cast().unwrap();
845            let mut shader_resource_view = None;
846            unsafe {d3d11_cx.device.CreateShaderResourceView(&resource, None, Some(&mut shader_resource_view)).unwrap()};
847            self.os.texture = texture;
848            self.os.shader_resource_view = shader_resource_view;
849        }
850    }
851    
852    pub fn update_render_target(
853        &mut self,
854        d3d11_cx: &D3d11Cx,
855        width: usize,
856        height: usize
857    ) {
858        if self.alloc_render(width, height){
859            let alloc = self.alloc.as_ref().unwrap();
860            let misc_flags = D3D11_RESOURCE_MISC_FLAG(0);
861            let format = texture_pixel_to_dx11_pixel(&alloc.pixel);
862            
863            let texture_desc = D3D11_TEXTURE2D_DESC {
864                Width: width as u32,
865                Height: height as u32,
866                MipLevels: 1,
867                ArraySize: 1,
868                Format: format,
869                SampleDesc: DXGI_SAMPLE_DESC {Count: 1, Quality: 0},
870                Usage: D3D11_USAGE_DEFAULT,
871                BindFlags: (D3D11_BIND_RENDER_TARGET.0 | D3D11_BIND_SHADER_RESOURCE.0) as u32,
872                CPUAccessFlags: 0,
873                MiscFlags: misc_flags.0 as u32,
874            };
875            
876            let mut texture = None;
877            unsafe {d3d11_cx.device.CreateTexture2D(&texture_desc, None, Some(&mut texture)).unwrap()};
878            let resource: ID3D11Resource = texture.clone().unwrap().cast().unwrap();
879            let mut shader_resource_view = None;
880            unsafe {d3d11_cx.device.CreateShaderResourceView(&resource, None, Some(&mut shader_resource_view)).unwrap()};
881            let mut render_target_view = None;
882            unsafe {d3d11_cx.device.CreateRenderTargetView(&resource, None, Some(&mut render_target_view)).unwrap()};
883            
884            self.os.texture = texture;
885            self.os.shader_resource_view = shader_resource_view;
886            self.os.render_target_view = render_target_view;
887        }
888    }
889    
890    pub fn update_depth_stencil(
891        &mut self,
892        d3d11_cx: &D3d11Cx,
893        width: usize,
894        height: usize
895    ) {
896        if self.alloc_depth(width, height){
897            let alloc = self.alloc.as_ref().unwrap();
898            let format;
899            match alloc.pixel {
900                TexturePixel::D32 => {
901                    format = DXGI_FORMAT_D32_FLOAT;
902                }
903                _ => {
904                    panic!("Wrong format for update_depth_stencil");
905                }
906            }
907            let texture_desc = D3D11_TEXTURE2D_DESC {
908                Width: width as u32,
909                Height: height as u32,
910                MipLevels: 1,
911                ArraySize: 1,
912                Format: format,
913                SampleDesc: DXGI_SAMPLE_DESC {Count: 1, Quality: 0},
914                Usage: D3D11_USAGE_DEFAULT,
915                BindFlags: D3D11_BIND_DEPTH_STENCIL.0 as u32, // | D3D11_BIND_SHADER_RESOURCE,
916                CPUAccessFlags: 0,
917                MiscFlags: 0,
918            };
919            
920            let mut texture = None;
921            unsafe {d3d11_cx.device.CreateTexture2D(&texture_desc, None, Some(&mut texture)).unwrap()};
922            let resource: ID3D11Resource = texture.clone().unwrap().cast().unwrap();
923            //let shader_resource_view = unsafe {d3d11_cx.device.CreateShaderResourceView(&texture, None).unwrap()};
924            
925            let dsv_desc = D3D11_DEPTH_STENCIL_VIEW_DESC {
926                Format: DXGI_FORMAT_D32_FLOAT,
927                ViewDimension: D3D11_DSV_DIMENSION_TEXTURE2D,
928                Flags: 0,
929                ..Default::default()
930            };
931            
932            let mut depth_stencil_view = None;
933            unsafe {d3d11_cx.device.CreateDepthStencilView(&resource, Some(&dsv_desc), Some(&mut depth_stencil_view)).unwrap()};
934            
935            self.os.depth_stencil_view = depth_stencil_view;
936            self.os.texture = texture;
937            self.os.shader_resource_view = None; //Some(shader_resource_view);
938        }
939    }
940    
941    fn update_shared_texture(
942        &mut self,
943        d3d11_device: &ID3D11Device,
944    ) {
945        if self.alloc_shared(){
946            let alloc = self.alloc.as_ref().unwrap();
947
948            let texture_desc = D3D11_TEXTURE2D_DESC {
949                Width: alloc.width as u32,
950                Height: alloc.height as u32,
951                MipLevels: 1,
952                ArraySize: 1,
953                Format: DXGI_FORMAT_B8G8R8A8_UNORM,
954                SampleDesc: DXGI_SAMPLE_DESC {
955                    Count: 1,
956                    Quality: 0
957                },
958                Usage: D3D11_USAGE_DEFAULT,
959                BindFlags: (D3D11_BIND_RENDER_TARGET.0 | D3D11_BIND_SHADER_RESOURCE.0) as u32,
960                CPUAccessFlags: 0,
961                MiscFlags: 2,  // D3D11_RESOURCE_MISC_SHARED
962            };
963            
964            let mut texture = None;
965            unsafe {d3d11_device.CreateTexture2D(&texture_desc, None, Some(&mut texture)).unwrap()};
966            let resource: ID3D11Resource = texture.clone().unwrap().cast().unwrap();
967            let mut shader_resource_view = None;
968            unsafe {d3d11_device.CreateShaderResourceView(&resource, None, Some(&mut shader_resource_view)).unwrap()};
969
970            // get IDXGIResource interface on newly created texture object
971            let dxgi_resource: IDXGIResource = resource.cast().unwrap();
972            //let mut dxgi_resource_ptr = None;
973            //unsafe { resource.query(IDXGIResource::IID,Some(&mut dxgi_resource_ptr)).unwrap() };
974            //let dxgi_resource = dxgi_resource_ptr.as_ref().unwrap().into();
975
976            // get shared handle of this resource
977            let handle = unsafe { dxgi_resource.GetSharedHandle().unwrap() };
978            //log!("created new shared texture with handle {:?}",handle);
979
980            self.os.texture = texture;
981            self.os.shader_resource_view = shader_resource_view;
982            self.os.shared_handle = handle;
983        }
984    }
985
986    pub fn update_from_shared_handle(&mut self,
987        d3d11_cx: &D3d11Cx,
988        handle: HANDLE,
989    ) {
990        if self.alloc_shared(){
991            let mut texture: Option<ID3D11Texture2D> = None;
992            if let Ok(()) = unsafe { d3d11_cx.device.OpenSharedResource(handle,&mut texture) } {
993    
994                let resource: ID3D11Resource = texture.clone().unwrap().cast().unwrap();
995                let mut shader_resource_view = None;
996                unsafe {d3d11_cx.device.CreateShaderResourceView(&resource, None, Some(&mut shader_resource_view)).unwrap()};
997                let mut render_target_view = None;
998                unsafe {d3d11_cx.device.CreateRenderTargetView(&resource, None, Some(&mut render_target_view)).unwrap()};
999                self.os.texture = texture;
1000                self.os.render_target_view = render_target_view;
1001                self.os.shader_resource_view = shader_resource_view;
1002            }
1003        }
1004    }
1005}
1006
1007impl CxOsPass {
1008    pub fn set_states(&mut self, d3d11_cx: &D3d11Cx,) {
1009        
1010        if self.blend_state.is_none() {
1011            
1012            let mut blend_desc: D3D11_BLEND_DESC = Default::default();
1013            blend_desc.AlphaToCoverageEnable = FALSE;
1014            blend_desc.RenderTarget[0] = D3D11_RENDER_TARGET_BLEND_DESC {
1015                BlendEnable: TRUE,
1016                SrcBlend: D3D11_BLEND_ONE,
1017                SrcBlendAlpha: D3D11_BLEND_ONE,
1018                DestBlend: D3D11_BLEND_INV_SRC_ALPHA,
1019                DestBlendAlpha: D3D11_BLEND_INV_SRC_ALPHA,
1020                BlendOp: D3D11_BLEND_OP_ADD,
1021                BlendOpAlpha: D3D11_BLEND_OP_ADD,
1022                RenderTargetWriteMask: D3D11_COLOR_WRITE_ENABLE_ALL.0 as u8,
1023            };
1024            unsafe {d3d11_cx.device.CreateBlendState(&blend_desc, Some(&mut self.blend_state)).unwrap()}
1025        }
1026        
1027        if self.raster_state.is_none() {
1028            let raster_desc = D3D11_RASTERIZER_DESC {
1029                AntialiasedLineEnable: FALSE,
1030                CullMode: D3D11_CULL_NONE,
1031                DepthBias: 0,
1032                DepthBiasClamp: 0.0,
1033                DepthClipEnable: TRUE,
1034                FillMode: D3D11_FILL_SOLID,
1035                FrontCounterClockwise: FALSE,
1036                MultisampleEnable: FALSE,
1037                ScissorEnable: FALSE,
1038                SlopeScaledDepthBias: 0.0,
1039            };
1040            unsafe {d3d11_cx.device.CreateRasterizerState(&raster_desc, Some(&mut self.raster_state)).unwrap()}
1041        }
1042        
1043        if self.depth_stencil_state.is_none() {
1044            let ds_desc = D3D11_DEPTH_STENCIL_DESC {
1045                DepthEnable: TRUE,
1046                DepthWriteMask: D3D11_DEPTH_WRITE_MASK_ALL,
1047                DepthFunc: D3D11_COMPARISON_LESS_EQUAL,
1048                StencilEnable: FALSE,
1049                StencilReadMask: 0xff,
1050                StencilWriteMask: 0xff,
1051                FrontFace: D3D11_DEPTH_STENCILOP_DESC {
1052                    StencilFailOp: D3D11_STENCIL_OP_REPLACE,
1053                    StencilDepthFailOp: D3D11_STENCIL_OP_REPLACE,
1054                    StencilPassOp: D3D11_STENCIL_OP_REPLACE,
1055                    StencilFunc: D3D11_COMPARISON_ALWAYS,
1056                },
1057                BackFace: D3D11_DEPTH_STENCILOP_DESC {
1058                    StencilFailOp: D3D11_STENCIL_OP_REPLACE,
1059                    StencilDepthFailOp: D3D11_STENCIL_OP_REPLACE,
1060                    StencilPassOp: D3D11_STENCIL_OP_REPLACE,
1061                    StencilFunc: D3D11_COMPARISON_ALWAYS,
1062                },
1063            };
1064            unsafe {d3d11_cx.device.CreateDepthStencilState(&ds_desc, Some(&mut self.depth_stencil_state)).unwrap()}
1065        }
1066        
1067        unsafe {
1068            d3d11_cx.context.RSSetState(self.raster_state.as_ref().unwrap());
1069            let blend_factor = [0., 0., 0., 0.];
1070            d3d11_cx.context.OMSetBlendState(self.blend_state.as_ref().unwrap(), Some(&blend_factor), 0xffffffff);
1071            d3d11_cx.context.OMSetDepthStencilState(self.depth_stencil_state.as_ref().unwrap(), 0);
1072        }
1073    }
1074}
1075
1076#[derive(Default, Clone)]
1077pub struct CxOsPass {
1078    pass_uniforms: D3d11Buffer,
1079    blend_state: Option<ID3D11BlendState >,
1080    raster_state: Option<ID3D11RasterizerState >,
1081    depth_stencil_state: Option<ID3D11DepthStencilState >
1082}
1083
1084#[derive(Default, Clone)]
1085pub struct CxOsGeometry {
1086    pub geom_vbuf: D3d11Buffer,
1087    pub geom_ibuf: D3d11Buffer,
1088}
1089
1090#[derive(Clone)]
1091pub struct CxOsDrawShader {
1092    pub hlsl: String,
1093    pub const_table_uniforms: D3d11Buffer,
1094    pub live_uniforms: D3d11Buffer,
1095    pub pixel_shader: ID3D11PixelShader,
1096    pub vertex_shader: ID3D11VertexShader,
1097    pub pixel_shader_blob: ID3DBlob,
1098    pub vertex_shader_blob: ID3DBlob,
1099    pub input_layout: ID3D11InputLayout
1100}
1101
1102impl CxOsDrawShader {
1103    
1104    fn new(d3d11_cx: &D3d11Cx, hlsl: String, mapping: &CxDrawShaderMapping) -> Option<Self> {
1105        
1106        fn compile_shader(target: &str, entry: &str, shader: &str) -> Result<ID3DBlob, String> {
1107            unsafe {
1108                let shader_bytes = shader.as_bytes();
1109                let mut blob = None;
1110                let mut errors = None;
1111                if D3DCompile(
1112                    shader_bytes.as_ptr() as *const _,
1113                    shader_bytes.len(),
1114                    PCSTR("makepad_shader\0".as_ptr()), // sourcename
1115                    None, // defines
1116                    None, // include
1117                    PCSTR(entry.as_ptr()), // entry point
1118                    PCSTR(target.as_ptr()), // target
1119                    0, // flags1
1120                    0, // flags2
1121                    &mut blob,
1122                    Some(&mut errors)
1123                ).is_ok() {
1124                    return Ok(blob.unwrap());
1125                };
1126                let error = errors.unwrap();
1127                let pointer = error.GetBufferPointer();
1128                let size = error.GetBufferSize();
1129                let slice = std::slice::from_raw_parts(pointer as *const u8, size as usize);
1130                return Err(String::from_utf8_lossy(slice).into_owned());
1131            }
1132        }
1133        fn split_source(src: &str) -> String {
1134            let mut r = String::new();
1135            let split = src.split("\n");
1136            for (line, chunk) in split.enumerate() {
1137                r.push_str(&(line + 1).to_string());
1138                r.push_str(":");
1139                r.push_str(chunk);
1140                r.push_str("\n");
1141            }
1142            return r
1143        }
1144        
1145        fn slots_to_dxgi_format(slots: usize) -> DXGI_FORMAT {
1146            
1147            match slots {
1148                1 => DXGI_FORMAT_R32_FLOAT,
1149                2 => DXGI_FORMAT_R32G32_FLOAT,
1150                3 => DXGI_FORMAT_R32G32B32_FLOAT,
1151                4 => DXGI_FORMAT_R32G32B32A32_FLOAT,
1152                _ => panic!("slots_to_dxgi_format unsupported slotcount {}", slots)
1153            }
1154        }
1155        
1156        let vs_blob = match compile_shader("vs_5_0\0", "vertex_main\0", &hlsl) {
1157            Err(msg) => {
1158                println!("Cannot compile vertexshader\n{}\n{}", msg, split_source(&hlsl));
1159                return None
1160            },
1161            Ok(blob) => {
1162                blob
1163            }
1164        };
1165        
1166        let ps_blob = match compile_shader("ps_5_0\0", "pixel_main\0", &hlsl) {
1167            Err(msg) => {
1168                println!("Cannot compile pixelshader\n{}\n{}", msg, split_source(&hlsl));
1169                return None
1170            },
1171            Ok(blob) => {
1172                blob
1173            }
1174        };
1175        
1176        let mut vs = None;
1177        unsafe {d3d11_cx.device.CreateVertexShader(
1178            std::slice::from_raw_parts(vs_blob.GetBufferPointer() as *const u8, vs_blob.GetBufferSize() as usize),
1179            None,
1180            Some(&mut vs)
1181        ).unwrap()};
1182        
1183        let mut ps = None;
1184        unsafe {d3d11_cx.device.CreatePixelShader(
1185            std::slice::from_raw_parts(ps_blob.GetBufferPointer() as *const u8, ps_blob.GetBufferSize() as usize),
1186            None,
1187            Some(&mut ps)
1188        ).unwrap()};
1189        
1190        let mut layout_desc = Vec::new();
1191        let mut strings = Vec::new();
1192        
1193        for (index, geom) in mapping.geometries.inputs.iter().enumerate() {
1194            
1195            strings.push(format!("GEOM{}\0", generate_hlsl::index_to_char(index))); //std::char::from_u32(index as u32 + 65).unwrap())).unwrap());
1196            
1197            layout_desc.push(D3D11_INPUT_ELEMENT_DESC {
1198                SemanticName: PCSTR(strings.last().unwrap().as_ptr()),
1199                SemanticIndex: 0,
1200                Format: slots_to_dxgi_format(geom.slots),
1201                InputSlot: 0,
1202                AlignedByteOffset: (geom.offset * 4) as u32,
1203                InputSlotClass: D3D11_INPUT_PER_VERTEX_DATA,
1204                InstanceDataStepRate: 0
1205            })
1206        }
1207        
1208        let mut index = 0;
1209        for inst in &mapping.instances.inputs {
1210            if inst.slots == 16 {
1211                for i in 0..4 {
1212                    strings.push(format!("INST{}\0", generate_hlsl::index_to_char(index))); //std::char::from_u32(index as u32 + 65).unwrap())).unwrap());
1213                    layout_desc.push(D3D11_INPUT_ELEMENT_DESC {
1214                        SemanticName: PCSTR(strings.last().unwrap().as_ptr()),
1215                        SemanticIndex: 0,
1216                        Format: slots_to_dxgi_format(4),
1217                        InputSlot: 1,
1218                        AlignedByteOffset: (inst.offset * 4 + i * 16) as u32,
1219                        InputSlotClass: D3D11_INPUT_PER_INSTANCE_DATA,
1220                        InstanceDataStepRate: 1
1221                    });
1222                    index += 1;
1223                }
1224            }
1225            else if inst.slots == 9 {
1226                for i in 0..3 {
1227                    strings.push(format!("INST{}\0", generate_hlsl::index_to_char(index))); //std::char::from_u32(index as u32 + 65).unwrap())).unwrap());
1228                    layout_desc.push(D3D11_INPUT_ELEMENT_DESC {
1229                        SemanticName: PCSTR(strings.last().unwrap().as_ptr()),
1230                        SemanticIndex: 0,
1231                        Format: slots_to_dxgi_format(3),
1232                        InputSlot: 1,
1233                        AlignedByteOffset: (inst.offset * 4 + i * 9) as u32,
1234                        InputSlotClass: D3D11_INPUT_PER_INSTANCE_DATA,
1235                        InstanceDataStepRate: 1
1236                    });
1237                    index += 1;
1238                }
1239            }
1240            else {
1241                strings.push(format!("INST{}\0", generate_hlsl::index_to_char(index))); //std::char::from_u32(index as u32 + 65).unwrap())).unwrap());
1242                layout_desc.push(D3D11_INPUT_ELEMENT_DESC {
1243                    SemanticName: PCSTR(strings.last().unwrap().as_ptr()),
1244                    SemanticIndex: 0,
1245                    Format: slots_to_dxgi_format(inst.slots),
1246                    InputSlot: 1,
1247                    AlignedByteOffset: (inst.offset * 4) as u32,
1248                    InputSlotClass: D3D11_INPUT_PER_INSTANCE_DATA,
1249                    InstanceDataStepRate: 1
1250                });
1251                index += 1;
1252            }
1253        }
1254        
1255        let mut input_layout = None;
1256        unsafe {
1257            d3d11_cx.device.CreateInputLayout(
1258                &layout_desc,
1259                std::slice::from_raw_parts(vs_blob.GetBufferPointer() as *const u8, vs_blob.GetBufferSize() as usize),
1260                Some(&mut input_layout)
1261            ).unwrap()
1262        };
1263        
1264        let mut live_uniforms = D3d11Buffer::default();
1265        live_uniforms.update_with_f32_constant_data(d3d11_cx, mapping.live_uniforms_buf.as_ref());
1266        
1267        let mut const_table_uniforms = D3d11Buffer::default();
1268        const_table_uniforms.update_with_f32_constant_data(d3d11_cx, mapping.const_table.table.as_ref());
1269        
1270        Some(Self {
1271            hlsl,
1272            const_table_uniforms,
1273            live_uniforms,
1274            pixel_shader: ps.unwrap(),
1275            vertex_shader: vs.unwrap(),
1276            pixel_shader_blob: ps_blob,
1277            vertex_shader_blob: vs_blob,
1278            input_layout: input_layout.unwrap()
1279        })
1280    }
1281}