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

Use direct composition for d3d12 backend #99387

Merged
merged 1 commit into from
Nov 26, 2024
Merged
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
6 changes: 6 additions & 0 deletions drivers/d3d12/rendering_context_driver_d3d12.cpp
Original file line number Diff line number Diff line change
@@ -96,6 +96,9 @@ RenderingContextDriverD3D12::~RenderingContextDriverD3D12() {
if (lib_dxgi) {
FreeLibrary(lib_dxgi);
}
if (lib_dcomp) {
FreeLibrary(lib_dcomp);
}
}

Error RenderingContextDriverD3D12::_init_device_factory() {
@@ -108,6 +111,9 @@ Error RenderingContextDriverD3D12::_init_device_factory() {
lib_dxgi = LoadLibraryW(L"DXGI.dll");
ERR_FAIL_NULL_V(lib_dxgi, ERR_CANT_CREATE);

lib_dcomp = LoadLibraryW(L"Dcomp.dll");
ERR_FAIL_NULL_V(lib_dcomp, ERR_CANT_CREATE);

// Note: symbol is not available in MinGW import library.
PFN_D3D12_GET_INTERFACE d3d_D3D12GetInterface = (PFN_D3D12_GET_INTERFACE)(void *)GetProcAddress(lib_d3d12, "D3D12GetInterface");
if (!d3d_D3D12GetInterface) {
18 changes: 18 additions & 0 deletions drivers/d3d12/rendering_context_driver_d3d12.h
Original file line number Diff line number Diff line change
@@ -59,6 +59,20 @@
#undef AS
#endif

#if (WINVER < _WIN32_WINNT_WIN8) && defined(_MSC_VER)
#pragma push_macro("NTDDI_VERSION")
#pragma push_macro("WINVER")
#undef NTDDI_VERSION
#undef WINVER
#define NTDDI_VERSION NTDDI_WIN8
#define WINVER _WIN32_WINNT_WIN8
#include <dcomp.h>
#pragma pop_macro("WINVER")
#pragma pop_macro("NTDDI_VERSION")
#else
#include <dcomp.h>
#endif

#include "d3dx12.h"
#include <dxgi1_6.h>

@@ -114,10 +128,14 @@ class RenderingContextDriverD3D12 : public RenderingContextDriver {
uint32_t height = 0;
DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED;
bool needs_resize = false;
ComPtr<IDCompositionDevice> composition_device;
ComPtr<IDCompositionTarget> composition_target;
ComPtr<IDCompositionVisual> composition_visual;
};

HMODULE lib_d3d12 = nullptr;
HMODULE lib_dxgi = nullptr;
HMODULE lib_dcomp = nullptr;

IDXGIAdapter1 *create_adapter(uint32_t p_adapter_index) const;
ID3D12DeviceFactory *device_factory_get() const;
43 changes: 35 additions & 8 deletions drivers/d3d12/rendering_device_driver_d3d12.cpp
Original file line number Diff line number Diff line change
@@ -2469,7 +2469,7 @@ Error RenderingDeviceDriverD3D12::swap_chain_resize(CommandQueueID p_cmd_queue,
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
if (swap_chain->d3d_swap_chain != nullptr) {
_swap_chain_release_buffers(swap_chain);
res = swap_chain->d3d_swap_chain->ResizeBuffers(p_desired_framebuffer_count, 0, 0, DXGI_FORMAT_UNKNOWN, creation_flags);
res = swap_chain->d3d_swap_chain->ResizeBuffers(p_desired_framebuffer_count, surface->width, surface->height, DXGI_FORMAT_UNKNOWN, creation_flags);
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_UNAVAILABLE);
} else {
swap_chain_desc.BufferCount = p_desired_framebuffer_count;
@@ -2478,22 +2478,19 @@ Error RenderingDeviceDriverD3D12::swap_chain_resize(CommandQueueID p_cmd_queue,
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.Flags = creation_flags;
swap_chain_desc.Scaling = DXGI_SCALING_NONE;
swap_chain_desc.Scaling = DXGI_SCALING_STRETCH;
if (OS::get_singleton()->is_layered_allowed()) {
swap_chain_desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
has_comp_alpha[(uint64_t)p_cmd_queue.id] = true;
} else {
swap_chain_desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
has_comp_alpha[(uint64_t)p_cmd_queue.id] = false;
}
swap_chain_desc.Width = surface->width;
swap_chain_desc.Height = surface->height;

ComPtr<IDXGISwapChain1> swap_chain_1;
res = context_driver->dxgi_factory_get()->CreateSwapChainForHwnd(command_queue->d3d_queue.Get(), surface->hwnd, &swap_chain_desc, nullptr, nullptr, swap_chain_1.GetAddressOf());
if (!SUCCEEDED(res) && swap_chain_desc.AlphaMode != DXGI_ALPHA_MODE_IGNORE) {
swap_chain_desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
has_comp_alpha[(uint64_t)p_cmd_queue.id] = false;
res = context_driver->dxgi_factory_get()->CreateSwapChainForHwnd(command_queue->d3d_queue.Get(), surface->hwnd, &swap_chain_desc, nullptr, nullptr, swap_chain_1.GetAddressOf());
}
res = context_driver->dxgi_factory_get()->CreateSwapChainForComposition(command_queue->d3d_queue.Get(), &swap_chain_desc, nullptr, swap_chain_1.GetAddressOf());
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);

swap_chain_1.As(&swap_chain->d3d_swap_chain);
@@ -2503,6 +2500,36 @@ Error RenderingDeviceDriverD3D12::swap_chain_resize(CommandQueueID p_cmd_queue,
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);
}

if (surface->composition_device.Get() == nullptr) {
using PFN_DCompositionCreateDevice = HRESULT(WINAPI *)(IDXGIDevice *, REFIID, void **);
PFN_DCompositionCreateDevice pfn_DCompositionCreateDevice = (PFN_DCompositionCreateDevice)(void *)GetProcAddress(context_driver->lib_dcomp, "DCompositionCreateDevice");
ERR_FAIL_NULL_V(pfn_DCompositionCreateDevice, ERR_CANT_CREATE);

res = pfn_DCompositionCreateDevice(nullptr, IID_PPV_ARGS(surface->composition_device.GetAddressOf()));
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);

res = surface->composition_device->CreateTargetForHwnd(surface->hwnd, TRUE, surface->composition_target.GetAddressOf());
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);

res = surface->composition_device->CreateVisual(surface->composition_visual.GetAddressOf());
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);

res = surface->composition_visual->SetContent(swap_chain->d3d_swap_chain.Get());
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);

res = surface->composition_target->SetRoot(surface->composition_visual.Get());
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);

res = surface->composition_device->Commit();
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);
} else {
res = surface->composition_visual->SetContent(swap_chain->d3d_swap_chain.Get());
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);

res = surface->composition_device->Commit();
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);
}

res = swap_chain->d3d_swap_chain->GetDesc1(&swap_chain_desc);
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);
ERR_FAIL_COND_V(swap_chain_desc.BufferCount == 0, ERR_CANT_CREATE);
4 changes: 4 additions & 0 deletions platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
@@ -2167,6 +2167,10 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_initiali

r_style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
r_style_ex |= WS_EX_ACCEPTFILES;

if (OS::get_singleton()->get_current_rendering_driver_name() == "d3d12") {
r_style_ex |= WS_EX_NOREDIRECTIONBITMAP;
}
}

void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repaint) {
4 changes: 4 additions & 0 deletions platform/windows/display_server_windows.h
Original file line number Diff line number Diff line change
@@ -357,6 +357,10 @@ typedef enum _SHC_PROCESS_DPI_AWARENESS {
SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2,
} SHC_PROCESS_DPI_AWARENESS;

#ifndef WS_EX_NOREDIRECTIONBITMAP
#define WS_EX_NOREDIRECTIONBITMAP 0x00200000L
#endif

class DropTargetWindows;

class DisplayServerWindows : public DisplayServer {