@@ -56,26 +56,42 @@ try to use it.
5656
5757use std:: { path:: PathBuf , time:: SystemTime } ;
5858
59- use winapi:: { um:: { winuser:: { CreateWindowExW , WS_OVERLAPPEDWINDOW , CW_USEDEFAULT , ShowWindow ,
60- WM_QUIT , TranslateMessage , DispatchMessageW ,
61- PeekMessageW , PM_REMOVE , WNDCLASSEXW , CS_VREDRAW , CS_HREDRAW ,
62- PostQuitMessage , DefWindowProcW , COLOR_WINDOWFRAME , RegisterClassExW , SW_SHOWDEFAULT , WM_CLOSE , WM_DESTROY } ,
63- libloaderapi:: { GetModuleHandleA , LoadLibraryA , GetProcAddress } ,
64- d3d11:: { ID3D11Device , ID3D11DeviceContext , D3D11_SDK_VERSION ,
65- D3D11_INPUT_ELEMENT_DESC , D3D11_INPUT_PER_VERTEX_DATA , ID3D11InputLayout ,
66- ID3D11Buffer , D3D11_BUFFER_DESC , D3D11_USAGE_DEFAULT , D3D11_BIND_VERTEX_BUFFER ,
67- D3D11_SUBRESOURCE_DATA , D3D11_BIND_INDEX_BUFFER } ,
68- d3dcommon:: { D3D_DRIVER_TYPE_HARDWARE , D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST } } ,
69- shared:: { windef:: { HWND , HMENU , HICON , HCURSOR , HBRUSH } ,
70- minwindef:: { LPVOID , UINT , WPARAM , LPARAM , LRESULT , HMODULE } ,
71- ntdef:: { LPCSTR , LPCWSTR , HRESULT } ,
72- dxgi:: { IDXGIAdapter , DXGI_SWAP_CHAIN_DESC , DXGI_SWAP_EFFECT_DISCARD ,
73- IDXGISwapChain , DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH } ,
74- dxgitype:: { DXGI_MODE_DESC , DXGI_RATIONAL , DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED ,
75- DXGI_MODE_SCALING_UNSPECIFIED , DXGI_SAMPLE_DESC , DXGI_USAGE_RENDER_TARGET_OUTPUT } ,
76- dxgiformat:: { DXGI_FORMAT_R8G8B8A8_UNORM , DXGI_FORMAT_R32G32B32_FLOAT ,
77- DXGI_FORMAT_R32G32_FLOAT , DXGI_FORMAT_R8G8B8A8_UINT ,
78- DXGI_FORMAT_R16_UINT } } , ctypes:: c_void} ;
59+ // If these imports get too ugly or rust analyzer sticks them all on one line, use LLM to reorg them.
60+ use winapi:: ctypes:: c_void;
61+ use winapi:: shared:: {
62+ dxgi:: {
63+ IDXGIAdapter , IDXGISwapChain , DXGI_SWAP_CHAIN_DESC , DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH ,
64+ DXGI_SWAP_EFFECT_DISCARD ,
65+ } ,
66+ dxgiformat:: {
67+ DXGI_FORMAT_R16_UINT , DXGI_FORMAT_R32G32B32_FLOAT , DXGI_FORMAT_R32G32_FLOAT ,
68+ DXGI_FORMAT_R8G8B8A8_UINT , DXGI_FORMAT_R8G8B8A8_UNORM ,
69+ } ,
70+ dxgitype:: {
71+ DXGI_MODE_DESC , DXGI_MODE_SCALING_UNSPECIFIED , DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED ,
72+ DXGI_RATIONAL , DXGI_SAMPLE_DESC , DXGI_USAGE_RENDER_TARGET_OUTPUT ,
73+ } ,
74+ minwindef:: { HMODULE , LPARAM , LPVOID , LRESULT , UINT , WPARAM } ,
75+ ntdef:: { HRESULT , LPCSTR , LPCWSTR } ,
76+ windef:: { HBRUSH , HCURSOR , HICON , HMENU , HWND } ,
77+ winerror:: DXGI_ERROR_SDK_COMPONENT_MISSING ,
78+ } ;
79+ use winapi:: um:: {
80+ d3d11:: {
81+ ID3D11Buffer , ID3D11Device , ID3D11DeviceContext , ID3D11InputLayout , ID3D11VertexShader ,
82+ D3D11_BIND_INDEX_BUFFER , D3D11_BIND_VERTEX_BUFFER , D3D11_BUFFER_DESC ,
83+ D3D11_CREATE_DEVICE_BGRA_SUPPORT , D3D11_CREATE_DEVICE_DEBUG , D3D11_INPUT_ELEMENT_DESC ,
84+ D3D11_INPUT_PER_VERTEX_DATA , D3D11_SDK_VERSION , D3D11_SUBRESOURCE_DATA , D3D11_USAGE_DEFAULT ,
85+ } ,
86+ d3dcommon:: { D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST , D3D_DRIVER_TYPE_HARDWARE , D3D_FEATURE_LEVEL_11_0 } ,
87+ libloaderapi:: { GetModuleHandleA , GetProcAddress , LoadLibraryA } ,
88+ winuser:: {
89+ CreateWindowExW , DefWindowProcW , DispatchMessageW , PeekMessageW , PostQuitMessage ,
90+ RegisterClassExW , ShowWindow , TranslateMessage , COLOR_WINDOWFRAME , CS_HREDRAW , CS_VREDRAW ,
91+ CW_USEDEFAULT , PM_REMOVE , SW_SHOWDEFAULT , WM_CLOSE , WM_DESTROY , WM_QUIT , WNDCLASSEXW ,
92+ WS_OVERLAPPEDWINDOW ,
93+ } ,
94+ } ;
7995
8096use winapi:: um:: d3dcommon:: { D3D_DRIVER_TYPE , D3D_FEATURE_LEVEL } ;
8197
@@ -228,14 +244,18 @@ unsafe fn load_d3d11() -> Option<D3D11CreateDeviceAndSwapChainFN> {
228244 Some ( std:: mem:: transmute ( d3d11_create_device) )
229245}
230246
247+ const USE_DEBUG_DEVICE : bool = false ;
248+
231249// Use the specified create device function to create a d3d11 device
232250fn create_d3d11_device ( window : HWND , create_dev_fn : D3D11CreateDeviceAndSwapChainFN )
233251 -> anyhow:: Result < ( * mut ID3D11Device , * mut ID3D11DeviceContext , * mut IDXGISwapChain ) > {
234252 let mut device = std:: ptr:: null_mut ( ) ;
235253 let mut context = std:: ptr:: null_mut ( ) ;
236254 let mut swapchain: * mut IDXGISwapChain = std:: ptr:: null_mut ( ) ;
237- let mut feature_level = 0 ;
255+ let mut feature_level = D3D_FEATURE_LEVEL_11_0 ;
238256 let dtype = D3D_DRIVER_TYPE_HARDWARE ;
257+ let flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT
258+ | if USE_DEBUG_DEVICE { D3D11_CREATE_DEVICE_DEBUG } else { 0 } ;
239259
240260 // init the swap chain DXGI_SWAP_CHAIN_DESC description
241261 let desc: DXGI_SWAP_CHAIN_DESC = DXGI_SWAP_CHAIN_DESC {
@@ -269,7 +289,7 @@ fn create_d3d11_device(window:HWND, create_dev_fn: D3D11CreateDeviceAndSwapChain
269289 std:: ptr:: null_mut ( ) ,
270290 dtype,
271291 std:: ptr:: null_mut ( ) ,
272- 0 ,
292+ flags ,
273293 std:: ptr:: null_mut ( ) ,
274294 0 ,
275295 D3D11_SDK_VERSION ,
@@ -281,7 +301,11 @@ fn create_d3d11_device(window:HWND, create_dev_fn: D3D11CreateDeviceAndSwapChain
281301 )
282302 } ;
283303 if hr != 0 {
304+ if hr == DXGI_ERROR_SDK_COMPONENT_MISSING {
305+ eprintln ! ( "device creation failed due to missing sdk component (DXGI_ERROR_SDK_COMPONENT_MISSING)" ) ;
306+ }
284307 return Err ( anyhow ! ( "failed to create d3d11 device: {:X}" , hr) )
308+
285309 }
286310 println ! ( "created d3d11 device: feature level: {:X}" , feature_level) ;
287311 Ok ( ( device, context, swapchain) )
@@ -650,17 +674,58 @@ unsafe fn runapp() -> anyhow::Result<()> {
650674 let index_buffer = create_index_buffer (
651675 device, ( prim_count * 3 ) . try_into ( ) . expect ( "can't conert to u32?" ) ) ?;
652676
677+ use std:: ptr:: null_mut;
678+
679+ // This doesn't work at the moment (some kind of problem with my shader) but its illegal
680+ // to draw in d3d11 without one, which is one reason why the device hangs after 1 draw call below.
681+ // however we can still call DIP as much as we want which is enough to test the MM load.
682+ let vshader = if let Some ( ref sfile) = opts. shader_out_file {
683+ let vshader = std:: fs:: read ( sfile) ?;
684+ let pVShaderBytecode = vshader. as_ptr ( ) as * const c_void ;
685+ let BytecodeLength = vshader. len ( ) ;
686+ let pVShader: * mut * mut ID3D11VertexShader = std:: ptr:: null_mut ( ) ;
687+ let hr = ( * device) . CreateVertexShader ( pVShaderBytecode, BytecodeLength , null_mut ( ) , pVShader) ;
688+ if hr == 0 && pVShader != null_mut ( ) {
689+ Some ( pVShader)
690+ } else {
691+ eprintln ! ( "error: failed to create vertex shader: {:X}" , hr) ;
692+ None
693+ }
694+ } else {
695+ None
696+ } ;
697+
653698 let mut msg;
654699 let mut start = SystemTime :: now ( ) ;
655700 let mut done = false ;
656- let mut dip_calls = 0 ;
701+ let mut dip_calls: i32 = 0 ;
702+ let mut total_dip_calls = 0 ;
657703 let mut info_start = SystemTime :: now ( ) ;
704+ let mut removed_once = false ;
658705 while !done {
659706 if SystemTime :: now ( ) . duration_since ( info_start) . expect ( "whatever" ) . as_secs ( ) >= 1 {
660707 println ! ( "dip calls: {}, prim/vert count: {:?}" , dip_calls, ( prim_count, vert_count) ) ;
708+ total_dip_calls += dip_calls;
661709 dip_calls = 0 ;
662710 info_start = SystemTime :: now ( ) ;
663711 }
712+ let dev_removed_reason = ( * device) . GetDeviceRemovedReason ( ) ;
713+ if !removed_once && dev_removed_reason != 0 {
714+ total_dip_calls += dip_calls;
715+
716+ removed_once = true ;
717+ use winapi:: shared:: winerror:: * ;
718+
719+ print ! ( "warning: device removed after {} draw calls, reason: " , total_dip_calls) ;
720+ match dev_removed_reason {
721+ DXGI_ERROR_DEVICE_HUNG => println ! ( "{}" , & format!( "device hung" ) ) ,
722+ DXGI_ERROR_DEVICE_REMOVED => println ! ( "{}" , & format!( "device removed" ) ) ,
723+ DXGI_ERROR_DEVICE_RESET => println ! ( "{}" , & format!( "device reset" ) ) ,
724+ DXGI_ERROR_DRIVER_INTERNAL_ERROR => println ! ( "{}" , & format!( "driver internal error" ) ) ,
725+ DXGI_ERROR_INVALID_CALL => println ! ( "{}" , & format!( "invalid call" ) ) ,
726+ _ => println ! ( "{}" , & format!( "unknown device removed reason" ) ) ,
727+ }
728+ }
664729
665730 msg = std:: mem:: zeroed ( ) ;
666731 while PeekMessageW ( & mut msg, 0 as HWND , 0 , 0 , PM_REMOVE ) != 0 {
@@ -679,17 +744,18 @@ unsafe fn runapp() -> anyhow::Result<()> {
679744 let now = SystemTime :: now ( ) ;
680745 let _elapsed = now. duration_since ( start) . expect ( "whatever" ) . as_millis ( ) ;
681746
682- // setting this to true typically slows down the DIP rate so much (like 30/sec) that MM doesn't even
683- // try to initialize - so its kinda useless. should probably figure that out as constantly drawing
684- // without present possibly makes the device unhappy
685- let mut do_present = false ;
747+ // if the sync interval in present below is > than zero this will slow down the dip rate to
748+ // the something like the refresh rate of display or some safe value like 30/sec
749+ let mut do_present = true ;
686750 // "render" some stuff
687751 {
688752 // call VSSetConstantBuffers to set the constant buffer on the context, this will
689753 // trigger some MM rehook code
690754 let buffer = std:: ptr:: null_mut ( ) ;
691755 ( * context) . VSSetConstantBuffers ( 0 , 1 , & buffer) ;
692756
757+ //(*context).VSSetShader()
758+
693759 //println!("setting index buffer");
694760 ( * context) . IASetIndexBuffer ( index_buffer, DXGI_FORMAT_R16_UINT , 0 ) ;
695761
@@ -739,7 +805,7 @@ unsafe fn runapp() -> anyhow::Result<()> {
739805 // swap the buffers. we don't care about this since we don't render anything
740806 // but the device probably works more realisticaly if there is a present after X
741807 // amount of drawing.
742- ( * swapchain) . Present ( 1 , 0 ) ;
808+ ( * swapchain) . Present ( 0 , 0 ) ;
743809 }
744810 }
745811 } ;
0 commit comments