Skip to content

Commit 36237d9

Browse files
committed
Various tweaks to native launch
- Add flag to create device in debug mode (currently fails because i don't have sdk - add message when that occurs) - turn of present sync (for higher dps) and enable present by default (weird to draw without every presenting, don't want to screw up device though there are some modes where this is valid) - try to compile shader but it currently fails, need to get this working to prevent device from "hanging" and getting removed after first draw call
1 parent e06351c commit 36237d9

1 file changed

Lines changed: 94 additions & 28 deletions

File tree

Test.NativeLaunch/src/main.rs

Lines changed: 94 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -56,26 +56,42 @@ try to use it.
5656

5757
use 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

8096
use 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
232250
fn 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

Comments
 (0)