This commit is contained in:
Junkui Zhang 2025-07-22 20:51:24 +08:00
parent fcb77979f3
commit be7d56e11b
3 changed files with 40 additions and 40 deletions

View file

@ -27,8 +27,8 @@ const MULTISAMPLE_COUNT: u32 = 4;
pub(crate) struct DirectXRenderer { pub(crate) struct DirectXRenderer {
hwnd: HWND, hwnd: HWND,
atlas: Arc<DirectXAtlas>, atlas: Arc<DirectXAtlas>,
devices: DirectXDevices, devices: ManuallyDrop<DirectXDevices>,
resources: DirectXResources, resources: ManuallyDrop<DirectXResources>,
globals: DirectXGlobalElements, globals: DirectXGlobalElements,
pipelines: DirectXRenderPipelines, pipelines: DirectXRenderPipelines,
#[cfg(not(feature = "enable-renderdoc"))] #[cfg(not(feature = "enable-renderdoc"))]
@ -115,16 +115,14 @@ impl DirectXDevices {
} }
impl DirectXRenderer { impl DirectXRenderer {
pub(crate) fn new(devices: &DirectXDevices, hwnd: HWND) -> Result<Self> { pub(crate) fn new(hwnd: HWND) -> Result<Self> {
let atlas = Arc::new(DirectXAtlas::new( let devices = ManuallyDrop::new(DirectXDevices::new().context("Creating DirectX devices")?);
devices.device.clone(), let atlas = Arc::new(DirectXAtlas::new(&devices.device, &devices.device_context));
devices.device_context.clone(),
));
#[cfg(not(feature = "enable-renderdoc"))] #[cfg(not(feature = "enable-renderdoc"))]
let resources = DirectXResources::new(devices).unwrap(); let resources = DirectXResources::new(&devices, 1, 1).unwrap();
#[cfg(feature = "enable-renderdoc")] #[cfg(feature = "enable-renderdoc")]
let resources = DirectXResources::new(devices, hwnd)?; let resources = DirectXResources::new(&devices, hwnd)?;
let globals = DirectXGlobalElements::new(&devices.device).unwrap(); let globals = DirectXGlobalElements::new(&devices.device).unwrap();
let pipelines = DirectXRenderPipelines::new(&devices.device).unwrap(); let pipelines = DirectXRenderPipelines::new(&devices.device).unwrap();
@ -139,7 +137,7 @@ impl DirectXRenderer {
Ok(DirectXRenderer { Ok(DirectXRenderer {
hwnd, hwnd,
atlas, atlas,
devices: devices.clone(), devices,
resources, resources,
globals, globals,
pipelines, pipelines,
@ -212,17 +210,29 @@ impl DirectXRenderer {
} }
fn handle_device_lost(&mut self) -> Result<()> { fn handle_device_lost(&mut self) -> Result<()> {
let devices = DirectXDevices::new().context("Recreating DirectX devices")?;
#[cfg(not(feature = "enable-renderdoc"))]
unsafe { unsafe {
ManuallyDrop::drop(&mut self.devices);
ManuallyDrop::drop(&mut self.resources);
#[cfg(not(feature = "enable-renderdoc"))]
ManuallyDrop::drop(&mut self._direct_composition); ManuallyDrop::drop(&mut self._direct_composition);
} }
self.atlas let devices =
.handle_device_lost(devices.device.clone(), devices.device_context.clone()); ManuallyDrop::new(DirectXDevices::new().context("Recreating DirectX devices")?);
unsafe {
devices.device_context.OMSetRenderTargets(None, None);
devices.device_context.ClearState();
devices.device_context.Flush();
}
#[cfg(not(feature = "enable-renderdoc"))] #[cfg(not(feature = "enable-renderdoc"))]
let resources = DirectXResources::new(&devices).unwrap(); let resources =
DirectXResources::new(&devices, self.resources.width, self.resources.height).unwrap();
#[cfg(feature = "enable-renderdoc")] #[cfg(feature = "enable-renderdoc")]
let resources = DirectXResources::new(&devices, self.hwnd)?; let resources = DirectXResources::new(
&devices,
self.resources.width,
self.resources.height,
self.hwnd,
)?;
let globals = DirectXGlobalElements::new(&devices.device).unwrap(); let globals = DirectXGlobalElements::new(&devices.device).unwrap();
let pipelines = DirectXRenderPipelines::new(&devices.device).unwrap(); let pipelines = DirectXRenderPipelines::new(&devices.device).unwrap();
@ -233,6 +243,8 @@ impl DirectXRenderer {
.set_swap_chain(&resources.swap_chain) .set_swap_chain(&resources.swap_chain)
.unwrap(); .unwrap();
self.atlas
.handle_device_lost(&devices.device, &devices.device_context);
self.devices = devices; self.devices = devices;
self.resources = resources; self.resources = resources;
self.globals = globals; self.globals = globals;
@ -505,11 +517,10 @@ impl DirectXRenderer {
impl DirectXResources { impl DirectXResources {
pub fn new( pub fn new(
devices: &DirectXDevices, devices: &DirectXDevices,
width: u32,
height: u32,
#[cfg(feature = "enable-renderdoc")] hwnd: HWND, #[cfg(feature = "enable-renderdoc")] hwnd: HWND,
) -> Result<Self> { ) -> Result<ManuallyDrop<Self>> {
let width = 1;
let height = 1;
#[cfg(not(feature = "enable-renderdoc"))] #[cfg(not(feature = "enable-renderdoc"))]
let swap_chain = create_swap_chain(&devices.dxgi_factory, &devices.device, width, height)?; let swap_chain = create_swap_chain(&devices.dxgi_factory, &devices.device, width, height)?;
#[cfg(feature = "enable-renderdoc")] #[cfg(feature = "enable-renderdoc")]
@ -520,7 +531,7 @@ impl DirectXResources {
create_resources(devices, &swap_chain, width, height)?; create_resources(devices, &swap_chain, width, height)?;
set_rasterizer_state(&devices.device, &devices.device_context)?; set_rasterizer_state(&devices.device, &devices.device_context)?;
Ok(Self { Ok(ManuallyDrop::new(Self {
swap_chain, swap_chain,
render_target, render_target,
render_target_view, render_target_view,
@ -529,7 +540,7 @@ impl DirectXResources {
width, width,
height, height,
viewport, viewport,
}) }))
} }
#[inline] #[inline]
@ -978,10 +989,12 @@ struct PathSprite {
color: Background, color: Background,
} }
#[cfg(not(feature = "enable-renderdoc"))]
impl Drop for DirectXRenderer { impl Drop for DirectXRenderer {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
ManuallyDrop::drop(&mut self.devices);
ManuallyDrop::drop(&mut self.resources);
#[cfg(not(feature = "enable-renderdoc"))]
ManuallyDrop::drop(&mut self._direct_composition); ManuallyDrop::drop(&mut self._direct_composition);
} }
} }

View file

@ -34,7 +34,6 @@ pub(crate) struct WindowsPlatform {
state: RefCell<WindowsPlatformState>, state: RefCell<WindowsPlatformState>,
raw_window_handles: RwLock<SmallVec<[HWND; 4]>>, raw_window_handles: RwLock<SmallVec<[HWND; 4]>>,
// The below members will never change throughout the entire lifecycle of the app. // The below members will never change throughout the entire lifecycle of the app.
directx_devices: DirectXDevices,
icon: HICON, icon: HICON,
main_receiver: flume::Receiver<Runnable>, main_receiver: flume::Receiver<Runnable>,
background_executor: BackgroundExecutor, background_executor: BackgroundExecutor,
@ -111,13 +110,11 @@ impl WindowsPlatform {
let icon = load_icon().unwrap_or_default(); let icon = load_icon().unwrap_or_default();
let state = RefCell::new(WindowsPlatformState::new()); let state = RefCell::new(WindowsPlatformState::new());
let raw_window_handles = RwLock::new(SmallVec::new()); let raw_window_handles = RwLock::new(SmallVec::new());
let directx_devices = DirectXDevices::new().context("Unable to init directx devices.")?;
let windows_version = WindowsVersion::new().context("Error retrieve windows version")?; let windows_version = WindowsVersion::new().context("Error retrieve windows version")?;
Ok(Self { Ok(Self {
state, state,
raw_window_handles, raw_window_handles,
directx_devices,
icon, icon,
main_receiver, main_receiver,
background_executor, background_executor,
@ -455,13 +452,8 @@ impl Platform for WindowsPlatform {
handle: AnyWindowHandle, handle: AnyWindowHandle,
options: WindowParams, options: WindowParams,
) -> Result<Box<dyn PlatformWindow>> { ) -> Result<Box<dyn PlatformWindow>> {
let window = WindowsWindow::new( let window = WindowsWindow::new(handle, options, self.generate_creation_info())
handle, .inspect_err(|err| show_error("Failed to open new window", err.to_string()))?;
options,
self.generate_creation_info(),
&self.directx_devices,
)
.inspect_err(|err| show_error("Failed to open new window", err.to_string()))?;
let handle = window.get_raw_handle(); let handle = window.get_raw_handle();
self.raw_window_handles.write().push(handle); self.raw_window_handles.write().push(handle);

View file

@ -82,7 +82,6 @@ impl WindowsWindowState {
cs: &CREATESTRUCTW, cs: &CREATESTRUCTW,
current_cursor: Option<HCURSOR>, current_cursor: Option<HCURSOR>,
display: WindowsDisplay, display: WindowsDisplay,
gpu_context: &DirectXDevices,
min_size: Option<Size<Pixels>>, min_size: Option<Size<Pixels>>,
appearance: WindowAppearance, appearance: WindowAppearance,
) -> Result<Self> { ) -> Result<Self> {
@ -101,7 +100,7 @@ impl WindowsWindowState {
}; };
let border_offset = WindowBorderOffset::default(); let border_offset = WindowBorderOffset::default();
let restore_from_minimized = None; let restore_from_minimized = None;
let renderer = DirectXRenderer::new(gpu_context, hwnd)?; let renderer = DirectXRenderer::new(hwnd)?;
let callbacks = Callbacks::default(); let callbacks = Callbacks::default();
let input_handler = None; let input_handler = None;
let pending_surrogate = None; let pending_surrogate = None;
@ -207,7 +206,6 @@ impl WindowsWindowStatePtr {
cs, cs,
context.current_cursor, context.current_cursor,
context.display, context.display,
context.gpu_context,
context.min_size, context.min_size,
context.appearance, context.appearance,
)?); )?);
@ -326,7 +324,7 @@ pub(crate) struct Callbacks {
pub(crate) appearance_changed: Option<Box<dyn FnMut()>>, pub(crate) appearance_changed: Option<Box<dyn FnMut()>>,
} }
struct WindowCreateContext<'a> { struct WindowCreateContext {
inner: Option<Result<Rc<WindowsWindowStatePtr>>>, inner: Option<Result<Rc<WindowsWindowStatePtr>>>,
handle: AnyWindowHandle, handle: AnyWindowHandle,
hide_title_bar: bool, hide_title_bar: bool,
@ -339,7 +337,6 @@ struct WindowCreateContext<'a> {
drop_target_helper: IDropTargetHelper, drop_target_helper: IDropTargetHelper,
validation_number: usize, validation_number: usize,
main_receiver: flume::Receiver<Runnable>, main_receiver: flume::Receiver<Runnable>,
gpu_context: &'a DirectXDevices,
main_thread_id_win32: u32, main_thread_id_win32: u32,
appearance: WindowAppearance, appearance: WindowAppearance,
} }
@ -349,7 +346,6 @@ impl WindowsWindow {
handle: AnyWindowHandle, handle: AnyWindowHandle,
params: WindowParams, params: WindowParams,
creation_info: WindowCreationInfo, creation_info: WindowCreationInfo,
gpu_context: &DirectXDevices,
) -> Result<Self> { ) -> Result<Self> {
let WindowCreationInfo { let WindowCreationInfo {
icon, icon,
@ -408,7 +404,6 @@ impl WindowsWindow {
drop_target_helper, drop_target_helper,
validation_number, validation_number,
main_receiver, main_receiver,
gpu_context,
main_thread_id_win32, main_thread_id_win32,
appearance, appearance,
}; };