windows: Port to DirectX 11 (#34374)
Closes #16713 Closes #19739 Closes #33191 Closes #26692 Closes #17374 Closes #35077 Closes https://github.com/zed-industries/zed/issues/35205 Closes https://github.com/zed-industries/zed/issues/35262 Compared to the current Vulkan implementation, this PR brings several improvements: - Fewer weird bugs - Better hardware compatibility - VSync support - More accurate colors - Lower memory usage - Graceful handling of device loss --- **TODO:** - [x] Don’t use AGS binaries directly - [ ] The message loop is using too much CPU when ths app is idle - [x] There’s a [bug](https://github.com/zed-industries/zed/issues/33191#issuecomment-3109306630) in how `Path` is being rendered. --- Release Notes: - N/A --------- Co-authored-by: Kate <kate@zed.dev> Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
parent
0d9715325c
commit
15ad986329
17 changed files with 3577 additions and 180 deletions
|
@ -28,13 +28,12 @@ use windows::{
|
|||
core::*,
|
||||
};
|
||||
|
||||
use crate::{platform::blade::BladeContext, *};
|
||||
use crate::*;
|
||||
|
||||
pub(crate) struct WindowsPlatform {
|
||||
state: RefCell<WindowsPlatformState>,
|
||||
raw_window_handles: RwLock<SmallVec<[HWND; 4]>>,
|
||||
// The below members will never change throughout the entire lifecycle of the app.
|
||||
gpu_context: BladeContext,
|
||||
icon: HICON,
|
||||
main_receiver: flume::Receiver<Runnable>,
|
||||
background_executor: BackgroundExecutor,
|
||||
|
@ -111,13 +110,11 @@ impl WindowsPlatform {
|
|||
let icon = load_icon().unwrap_or_default();
|
||||
let state = RefCell::new(WindowsPlatformState::new());
|
||||
let raw_window_handles = RwLock::new(SmallVec::new());
|
||||
let gpu_context = BladeContext::new().context("Unable to init GPU context")?;
|
||||
let windows_version = WindowsVersion::new().context("Error retrieve windows version")?;
|
||||
|
||||
Ok(Self {
|
||||
state,
|
||||
raw_window_handles,
|
||||
gpu_context,
|
||||
icon,
|
||||
main_receiver,
|
||||
background_executor,
|
||||
|
@ -343,27 +340,11 @@ impl Platform for WindowsPlatform {
|
|||
|
||||
fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>) {
|
||||
on_finish_launching();
|
||||
let vsync_event = unsafe { Owned::new(CreateEventW(None, false, false, None).unwrap()) };
|
||||
begin_vsync(*vsync_event);
|
||||
'a: loop {
|
||||
let wait_result = unsafe {
|
||||
MsgWaitForMultipleObjects(Some(&[*vsync_event]), false, INFINITE, QS_ALLINPUT)
|
||||
};
|
||||
|
||||
match wait_result {
|
||||
// compositor clock ticked so we should draw a frame
|
||||
WAIT_EVENT(0) => self.redraw_all(),
|
||||
// Windows thread messages are posted
|
||||
WAIT_EVENT(1) => {
|
||||
if self.handle_events() {
|
||||
break 'a;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
log::error!("Something went wrong while waiting {:?}", wait_result);
|
||||
break;
|
||||
}
|
||||
loop {
|
||||
if self.handle_events() {
|
||||
break;
|
||||
}
|
||||
self.redraw_all();
|
||||
}
|
||||
|
||||
if let Some(ref mut callback) = self.state.borrow_mut().callbacks.quit {
|
||||
|
@ -455,12 +436,7 @@ impl Platform for WindowsPlatform {
|
|||
handle: AnyWindowHandle,
|
||||
options: WindowParams,
|
||||
) -> Result<Box<dyn PlatformWindow>> {
|
||||
let window = WindowsWindow::new(
|
||||
handle,
|
||||
options,
|
||||
self.generate_creation_info(),
|
||||
&self.gpu_context,
|
||||
)?;
|
||||
let window = WindowsWindow::new(handle, options, self.generate_creation_info())?;
|
||||
let handle = window.get_raw_handle();
|
||||
self.raw_window_handles.write().push(handle);
|
||||
|
||||
|
@ -846,16 +822,6 @@ fn file_save_dialog(directory: PathBuf, window: Option<HWND>) -> Result<Option<P
|
|||
Ok(Some(PathBuf::from(file_path_string)))
|
||||
}
|
||||
|
||||
fn begin_vsync(vsync_event: HANDLE) {
|
||||
let event: SafeHandle = vsync_event.into();
|
||||
std::thread::spawn(move || unsafe {
|
||||
loop {
|
||||
windows::Win32::Graphics::Dwm::DwmFlush().log_err();
|
||||
SetEvent(*event).log_err();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn load_icon() -> Result<HICON> {
|
||||
let module = unsafe { GetModuleHandleW(None).context("unable to get module handle")? };
|
||||
let handle = unsafe {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue