makepad_platform/os/windows/
d3d11.rs

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