Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Use composition to fix window transparency when using D3D #2529

Merged
merged 2 commits into from
May 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ tracy-context-switch-tracing = ["tracy-client-sys?/context-switch-tracing"]
tracy-sampling = ["tracy-client-sys?/sampling"]
tracy-code-transfer = ["tracy-client-sys?/code-transfer"]
tracy-callstack-inlines = ["tracy-client-sys?/callstack-inlines"]
d3d_debug = [] # Enable the D3D debug layer

[dependencies]
anyhow = { version = "1.0.75", features = ["backtrace"] }
Expand Down Expand Up @@ -89,6 +90,7 @@ skia-safe = { version = "0.73.0", features = ["gl", "d3d", "textlayout"] }
windows = { version = "0.56.0", features = [
"Win32_Graphics_Direct3D",
"Win32_Graphics_Direct3D12",
"Win32_Graphics_DirectComposition",
"Win32_Graphics_Dwm",
"Win32_Graphics_Dxgi",
"Win32_Graphics_Dxgi_Common",
Expand Down
80 changes: 57 additions & 23 deletions src/renderer/d3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,24 @@ use windows::core::{Interface, Result, PCWSTR};
use windows::Win32::Foundation::{CloseHandle, HANDLE, HWND};
use windows::Win32::Graphics::Direct3D::D3D_FEATURE_LEVEL_11_0;
use windows::Win32::Graphics::Direct3D12::{
D3D12CreateDevice, D3D12GetDebugInterface, ID3D12CommandQueue, ID3D12Debug, ID3D12Device,
ID3D12Fence, ID3D12Resource, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_DESC,
D3D12_COMMAND_QUEUE_FLAG_NONE, D3D12_FENCE_FLAG_NONE, D3D12_RESOURCE_STATE_PRESENT,
D3D12CreateDevice, ID3D12CommandQueue, ID3D12Device, ID3D12Fence, ID3D12Resource,
D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_DESC, D3D12_COMMAND_QUEUE_FLAG_NONE,
D3D12_FENCE_FLAG_NONE, D3D12_RESOURCE_STATE_PRESENT,
};
#[cfg(feature = "d3d_debug")]
use windows::Win32::Graphics::Direct3D12::{D3D12GetDebugInterface, ID3D12Debug};
use windows::Win32::Graphics::DirectComposition::{
DCompositionCreateDevice2, IDCompositionDevice, IDCompositionTarget, IDCompositionVisual,
};
use windows::Win32::Graphics::Dxgi::Common::{
DXGI_ALPHA_MODE_UNSPECIFIED, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SAMPLE_DESC,
DXGI_ALPHA_MODE_PREMULTIPLIED, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN,
DXGI_SAMPLE_DESC,
};
use windows::Win32::Graphics::Dxgi::{
CreateDXGIFactory2, IDXGIAdapter1, IDXGIFactory4, IDXGISwapChain1, IDXGISwapChain3,
DXGI_ADAPTER_FLAG, DXGI_ADAPTER_FLAG_SOFTWARE, DXGI_CREATE_FACTORY_DEBUG, DXGI_SCALING_NONE,
DXGI_ADAPTER_FLAG, DXGI_ADAPTER_FLAG_SOFTWARE, DXGI_CREATE_FACTORY_DEBUG, DXGI_SCALING_STRETCH,
DXGI_SWAP_CHAIN_DESC1, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT,
DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_USAGE_RENDER_TARGET_OUTPUT,
DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_USAGE_RENDER_TARGET_OUTPUT,
};
use windows::Win32::System::Threading::{CreateEventW, WaitForSingleObjectEx, INFINITE};
use winit::{
Expand Down Expand Up @@ -83,17 +89,20 @@ pub struct D3DSkiaRenderer {
#[cfg(feature = "gpu_profiling")]
pub device: ID3D12Device,
_adapter: IDXGIAdapter1,
_composition_device: IDCompositionDevice,
_target: IDCompositionTarget,
_visual: IDCompositionVisual,
window: Window,
}

impl D3DSkiaRenderer {
pub fn new(window: Window) -> Self {
let mut debug_controller: Option<ID3D12Debug> = None;
#[cfg(feature = "d3d_debug")]
unsafe {
let mut debug_controller: Option<ID3D12Debug> = None;
D3D12GetDebugInterface(&mut debug_controller)
.expect("Failed to create Direct3D debug controller");
}
unsafe {

debug_controller
.expect("Failed to enable debug layer")
.EnableDebugLayer();
Expand All @@ -102,6 +111,7 @@ impl D3DSkiaRenderer {
let dxgi_factory: IDXGIFactory4 = unsafe {
CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG).expect("Failed to create DXGI factory")
};

let adapter = get_hardware_adapter(&dxgi_factory)
.expect("Failed to find any suitable Direct3D 12 adapters");

Expand All @@ -124,10 +134,12 @@ impl D3DSkiaRenderer {
.expect("Failed to create the Direct3D command queue")
};

let size = window.inner_size();

// Describe and create the swap chain.
let swap_chain_desc = DXGI_SWAP_CHAIN_DESC1 {
Width: 0,
Height: 0,
Width: size.width,
Height: size.height,
Format: DXGI_FORMAT_R8G8B8A8_UNORM,
Stereo: false.into(),
SampleDesc: DXGI_SAMPLE_DESC {
Expand All @@ -136,9 +148,9 @@ impl D3DSkiaRenderer {
},
BufferUsage: DXGI_USAGE_RENDER_TARGET_OUTPUT,
BufferCount: 2,
Scaling: DXGI_SCALING_NONE,
SwapEffect: DXGI_SWAP_EFFECT_FLIP_DISCARD,
AlphaMode: DXGI_ALPHA_MODE_UNSPECIFIED,
Scaling: DXGI_SCALING_STRETCH,
SwapEffect: DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
AlphaMode: DXGI_ALPHA_MODE_PREMULTIPLIED,
Flags: DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT.0 as u32,
};

Expand All @@ -147,20 +159,14 @@ impl D3DSkiaRenderer {
.expect("Failed to fetch window handle")
.as_raw()
{
handle.hwnd
HWND(handle.hwnd.get())
} else {
panic!("Not a Win32 window");
};

let swap_chain = unsafe {
dxgi_factory
.CreateSwapChainForHwnd(
&command_queue,
HWND(hwnd.get()),
&swap_chain_desc,
None,
None,
)
.CreateSwapChainForComposition(&command_queue, &swap_chain_desc, None)
.expect("Failed to create the Direct3D swap chain")
};

Expand All @@ -172,6 +178,31 @@ impl D3DSkiaRenderer {
.SetMaximumFrameLatency(1)
.expect("Failed to set maximum frame latency");
}
let composition_device: IDCompositionDevice = unsafe {
DCompositionCreateDevice2(None).expect("Could not create composition device")
};
let target = unsafe {
composition_device
.CreateTargetForHwnd(hwnd, true)
.expect("Could not create composition target")
};
let visual = unsafe {
composition_device
.CreateVisual()
.expect("Could not create composition visual")
};

unsafe {
visual
.SetContent(&swap_chain)
.expect("Failed to set composition content");
target
.SetRoot(&visual)
.expect("Failed to set composition root");
composition_device
.Commit()
.expect("Failed to commit composition");
}

let swap_chain_waitable = unsafe { swap_chain.GetFrameLatencyWaitableObject() };
if swap_chain_waitable.is_invalid() {
Expand Down Expand Up @@ -219,6 +250,9 @@ impl D3DSkiaRenderer {
fence_event,
frame_swapped: true,
frame_index,
_composition_device: composition_device,
_target: target,
_visual: visual,
window,
};
ret.setup_surfaces();
Expand Down Expand Up @@ -372,7 +406,7 @@ impl SkiaRenderer for D3DSkiaRenderer {
0,
size.width,
size.height,
self.swap_chain_desc.Format,
DXGI_FORMAT_UNKNOWN,
self.swap_chain_desc.Flags,
)
.expect("Failed to resize buffers");
Expand Down
10 changes: 10 additions & 0 deletions src/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ use winit::platform::macos::WindowBuilderExtMacOS;
#[cfg(target_os = "linux")]
use winit::platform::{wayland::WindowBuilderExtWayland, x11::WindowBuilderExtX11};

#[cfg(target_os = "windows")]
use winit::platform::windows::WindowBuilderExtWindows;

#[cfg(target_os = "macos")]
use winit::platform::macos::EventLoopBuilderExtMacOS;

Expand Down Expand Up @@ -161,6 +164,13 @@ pub fn create_window(
.with_transparent(true)
.with_visible(false);

#[cfg(target_os = "windows")]
let winit_window_builder = if !cmd_line_settings.opengl {
WindowBuilderExtWindows::with_no_redirection_bitmap(winit_window_builder, true)
} else {
winit_window_builder
};

let frame_decoration = cmd_line_settings.frame;

#[cfg(target_os = "macos")]
Expand Down
Loading