This commit is contained in:
Junkui Zhang 2025-07-17 15:52:51 +08:00
parent 63727f99da
commit 1888f21a14

View file

@ -29,6 +29,8 @@ pub(crate) struct DirectXRenderer {
resources: DirectXResources, resources: DirectXResources,
globals: DirectXGlobalElements, globals: DirectXGlobalElements,
pipelines: DirectXRenderPipelines, pipelines: DirectXRenderPipelines,
// #[cfg(not(feature = "enable-renderdoc"))]
_direct_composition: DirectComposition,
} }
/// Direct3D objects /// Direct3D objects
@ -42,17 +44,14 @@ pub(crate) struct DirectXDevices {
struct DirectXResources { struct DirectXResources {
// Direct3D rendering objects // Direct3D rendering objects
swap_chain: ManuallyDrop<IDXGISwapChain1>, swap_chain: IDXGISwapChain1,
render_target: ManuallyDrop<ID3D11Texture2D>, render_target: ManuallyDrop<ID3D11Texture2D>,
render_target_view: [Option<ID3D11RenderTargetView>; 1], render_target_view: [Option<ID3D11RenderTargetView>; 1],
msaa_target: ID3D11Texture2D, msaa_target: ID3D11Texture2D,
msaa_view: ID3D11RenderTargetView, msaa_view: [Option<ID3D11RenderTargetView>; 1],
// Cached viewport // Cached viewport
viewport: [D3D11_VIEWPORT; 1], viewport: [D3D11_VIEWPORT; 1],
// #[cfg(not(feature = "enable-renderdoc"))]
_direct_composition: DirectComposition,
} }
struct DirectXRenderPipelines { struct DirectXRenderPipelines {
@ -115,12 +114,18 @@ impl DirectXRenderer {
let resources = DirectXResources::new(devices, hwnd)?; let resources = DirectXResources::new(devices, hwnd)?;
let globals = DirectXGlobalElements::new(&devices.device)?; let globals = DirectXGlobalElements::new(&devices.device)?;
let pipelines = DirectXRenderPipelines::new(&devices.device)?; let pipelines = DirectXRenderPipelines::new(&devices.device)?;
// #[cfg(not(feature = "enable-renderdoc"))]
let direct_composition = DirectComposition::new(&devices.dxgi_device, hwnd)?;
// #[cfg(not(feature = "enable-renderdoc"))]
direct_composition.set_swap_chain(&resources.swap_chain)?;
Ok(DirectXRenderer { Ok(DirectXRenderer {
atlas, atlas,
devices: devices.clone(), devices: devices.clone(),
resources, resources,
globals, globals,
pipelines, pipelines,
// #[cfg(not(feature = "enable-renderdoc"))]
_direct_composition: direct_composition,
}) })
} }
@ -143,10 +148,10 @@ impl DirectXRenderer {
unsafe { unsafe {
self.devices self.devices
.device_context .device_context
.ClearRenderTargetView(&self.resources.msaa_view, &[0.0; 4]); .ClearRenderTargetView(self.resources.msaa_view[0].as_ref().unwrap(), &[0.0; 4]);
self.devices self.devices
.device_context .device_context
.OMSetRenderTargets(Some(&[Some(self.resources.msaa_view.clone())]), None); .OMSetRenderTargets(Some(&self.resources.msaa_view), None);
self.devices self.devices
.device_context .device_context
.RSSetViewports(Some(&self.resources.viewport)); .RSSetViewports(Some(&self.resources.viewport));
@ -159,6 +164,23 @@ impl DirectXRenderer {
Ok(()) Ok(())
} }
fn present(&self) -> Result<()> {
unsafe {
self.devices.device_context.ResolveSubresource(
&*self.resources.render_target,
0,
&self.resources.msaa_target,
0,
RENDER_TARGET_FORMAT,
);
self.devices
.device_context
.OMSetRenderTargets(Some(&self.resources.render_target_view), None);
self.resources.swap_chain.Present(0, DXGI_PRESENT(0)).ok()?;
}
Ok(())
}
pub(crate) fn draw(&mut self, scene: &Scene) -> Result<()> { pub(crate) fn draw(&mut self, scene: &Scene) -> Result<()> {
self.pre_draw()?; self.pre_draw()?;
for batch in scene.batches() { for batch in scene.batches() {
@ -185,64 +207,29 @@ impl DirectXRenderer {
scene.polychrome_sprites.len(), scene.polychrome_sprites.len(),
scene.surfaces.len(),))?; scene.surfaces.len(),))?;
} }
unsafe { self.present()
self.devices.device_context.ResolveSubresource(
&*self.resources.render_target,
0,
&self.resources.msaa_target,
0,
RENDER_TARGET_FORMAT,
);
self.devices
.device_context
.OMSetRenderTargets(Some(&self.resources.render_target_view), None);
self.resources.swap_chain.Present(0, DXGI_PRESENT(0)).ok()?;
}
Ok(())
} }
pub(crate) fn resize(&mut self, new_size: Size<DevicePixels>) -> Result<()> { pub(crate) fn resize(&mut self, new_size: Size<DevicePixels>) -> Result<()> {
unsafe { unsafe {
let width = new_size.width.0 as u32;
let height = new_size.height.0 as u32;
self.devices.device_context.OMSetRenderTargets(None, None); self.devices.device_context.OMSetRenderTargets(None, None);
ManuallyDrop::drop(&mut self.resources.render_target); ManuallyDrop::drop(&mut self.resources.render_target);
} drop(self.resources.render_target_view[0].take().unwrap());
drop(self.resources.render_target_view[0].take().unwrap()); self.resources.swap_chain.ResizeBuffers(
unsafe { BUFFER_COUNT as u32,
width,
height,
RENDER_TARGET_FORMAT,
DXGI_SWAP_CHAIN_FLAG(0),
)?;
self.resources self.resources
.swap_chain .recreate_resources(&self.devices, width, height)?;
.ResizeBuffers(
BUFFER_COUNT as u32,
new_size.width.0 as u32,
new_size.height.0 as u32,
RENDER_TARGET_FORMAT,
DXGI_SWAP_CHAIN_FLAG(0),
)
.unwrap();
}
let (render_target, render_target_view) =
create_render_target_and_its_view(&self.resources.swap_chain, &self.devices.device)
.unwrap();
self.resources.render_target = render_target;
self.resources.render_target_view = render_target_view;
unsafe {
self.devices self.devices
.device_context .device_context
.OMSetRenderTargets(Some(&self.resources.render_target_view), None); .OMSetRenderTargets(Some(&self.resources.render_target_view), None);
} }
let (msaa_target, msaa_view) = create_msaa_target_and_its_view(
&self.devices.device,
new_size.width.0 as u32,
new_size.height.0 as u32,
)?;
self.resources.msaa_target = msaa_target;
self.resources.msaa_view = msaa_view;
self.resources.viewport = set_viewport(
&self.devices.device_context,
new_size.width.0 as f32,
new_size.height.0 as f32,
);
Ok(()) Ok(())
} }
@ -411,20 +398,13 @@ impl DirectXResources {
// #[cfg(feature = "enable-renderdoc")] // #[cfg(feature = "enable-renderdoc")]
// let swap_chain = // let swap_chain =
// create_swap_chain_default(&devices.dxgi_factory, &devices.device, hwnd, transparent)?; // create_swap_chain_default(&devices.dxgi_factory, &devices.device, hwnd, transparent)?;
// #[cfg(not(feature = "enable-renderdoc"))] let (render_target, render_target_view, msaa_target, msaa_view, viewport) =
let direct_composition = DirectComposition::new(&devices.dxgi_device, hwnd)?; create_resources(devices, &swap_chain, width, height)?;
// #[cfg(not(feature = "enable-renderdoc"))] // unsafe {
direct_composition.set_swap_chain(&swap_chain)?; // devices
let (render_target, render_target_view) = // .device_context
create_render_target_and_its_view(&swap_chain, &devices.device)?; // .OMSetRenderTargets(Some(&render_target_view), None);
let (msaa_target, msaa_view) = // }
create_msaa_target_and_its_view(&devices.device, width, height)?;
let viewport = set_viewport(&devices.device_context, width as f32, height as f32);
unsafe {
devices
.device_context
.OMSetRenderTargets(Some(&render_target_view), None);
}
set_rasterizer_state(&devices.device, &devices.device_context)?; set_rasterizer_state(&devices.device, &devices.device_context)?;
Ok(Self { Ok(Self {
@ -434,10 +414,25 @@ impl DirectXResources {
msaa_target, msaa_target,
msaa_view, msaa_view,
viewport, viewport,
// #[cfg(not(feature = "enable-renderdoc"))]
_direct_composition: direct_composition,
}) })
} }
#[inline]
fn recreate_resources(
&mut self,
devices: &DirectXDevices,
width: u32,
height: u32,
) -> Result<()> {
let (render_target, render_target_view, msaa_target, msaa_view, viewport) =
create_resources(devices, &self.swap_chain, width, height)?;
self.render_target = render_target;
self.render_target_view = render_target_view;
self.msaa_target = msaa_target;
self.msaa_view = msaa_view;
self.viewport = viewport;
Ok(())
}
} }
impl DirectXRenderPipelines { impl DirectXRenderPipelines {
@ -909,7 +904,6 @@ impl Drop for DirectXResources {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
ManuallyDrop::drop(&mut self.render_target); ManuallyDrop::drop(&mut self.render_target);
ManuallyDrop::drop(&mut self.swap_chain);
} }
} }
} }
@ -961,6 +955,8 @@ fn get_device(
D3D_DRIVER_TYPE_UNKNOWN, D3D_DRIVER_TYPE_UNKNOWN,
HMODULE::default(), HMODULE::default(),
device_flags, device_flags,
// 4x MSAA is required for Direct3D Feature Level 10.1 or better
// 8x MSAA is required for Direct3D Feature Level 11.0 or better
Some(&[D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1]), Some(&[D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1]),
D3D11_SDK_VERSION, D3D11_SDK_VERSION,
device, device,
@ -980,7 +976,7 @@ fn create_swap_chain(
device: &ID3D11Device, device: &ID3D11Device,
width: u32, width: u32,
height: u32, height: u32,
) -> Result<ManuallyDrop<IDXGISwapChain1>> { ) -> Result<IDXGISwapChain1> {
let desc = DXGI_SWAP_CHAIN_DESC1 { let desc = DXGI_SWAP_CHAIN_DESC1 {
Width: width, Width: width,
Height: height, Height: height,
@ -998,9 +994,7 @@ fn create_swap_chain(
AlphaMode: DXGI_ALPHA_MODE_PREMULTIPLIED, AlphaMode: DXGI_ALPHA_MODE_PREMULTIPLIED,
Flags: 0, Flags: 0,
}; };
Ok(ManuallyDrop::new(unsafe { Ok(unsafe { dxgi_factory.CreateSwapChainForComposition(device, &desc, None)? })
dxgi_factory.CreateSwapChainForComposition(device, &desc, None)?
}))
} }
// #[cfg(feature = "enable-renderdoc")] // #[cfg(feature = "enable-renderdoc")]
@ -1010,7 +1004,7 @@ fn create_swap_chain_default(
hwnd: HWND, hwnd: HWND,
width: u32, width: u32,
height: u32, height: u32,
) -> Result<ManuallyDrop<IDXGISwapChain1>> { ) -> Result<IDXGISwapChain1> {
use windows::Win32::Graphics::Dxgi::DXGI_MWA_NO_ALT_ENTER; use windows::Win32::Graphics::Dxgi::DXGI_MWA_NO_ALT_ENTER;
let desc = DXGI_SWAP_CHAIN_DESC1 { let desc = DXGI_SWAP_CHAIN_DESC1 {
@ -1032,7 +1026,33 @@ fn create_swap_chain_default(
let swap_chain = let swap_chain =
unsafe { dxgi_factory.CreateSwapChainForHwnd(device, hwnd, &desc, None, None) }?; unsafe { dxgi_factory.CreateSwapChainForHwnd(device, hwnd, &desc, None, None) }?;
unsafe { dxgi_factory.MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER) }?; unsafe { dxgi_factory.MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER) }?;
Ok(ManuallyDrop::new(swap_chain)) Ok(swap_chain)
}
#[inline]
fn create_resources(
devices: &DirectXDevices,
swap_chain: &IDXGISwapChain1,
width: u32,
height: u32,
) -> Result<(
ManuallyDrop<ID3D11Texture2D>,
[Option<ID3D11RenderTargetView>; 1],
ID3D11Texture2D,
[Option<ID3D11RenderTargetView>; 1],
[D3D11_VIEWPORT; 1],
)> {
let (render_target, render_target_view) =
create_render_target_and_its_view(&swap_chain, &devices.device)?;
let (msaa_target, msaa_view) = create_msaa_target_and_its_view(&devices.device, width, height)?;
let viewport = set_viewport(&devices.device_context, width as f32, height as f32);
Ok((
render_target,
render_target_view,
msaa_target,
msaa_view,
viewport,
))
} }
#[inline] #[inline]
@ -1057,7 +1077,7 @@ fn create_msaa_target_and_its_view(
device: &ID3D11Device, device: &ID3D11Device,
width: u32, width: u32,
height: u32, height: u32,
) -> Result<(ID3D11Texture2D, ID3D11RenderTargetView)> { ) -> Result<(ID3D11Texture2D, [Option<ID3D11RenderTargetView>; 1])> {
let msaa_target = unsafe { let msaa_target = unsafe {
let mut output = None; let mut output = None;
let desc = D3D11_TEXTURE2D_DESC { let desc = D3D11_TEXTURE2D_DESC {
@ -1083,7 +1103,7 @@ fn create_msaa_target_and_its_view(
device.CreateRenderTargetView(&msaa_target, None, Some(&mut output))?; device.CreateRenderTargetView(&msaa_target, None, Some(&mut output))?;
output.unwrap() output.unwrap()
}; };
Ok((msaa_target, msaa_view)) Ok((msaa_target, [Some(msaa_view)]))
} }
#[inline] #[inline]