Skip to content

Commit

Permalink
Use direct composition for d3d12 backend
Browse files Browse the repository at this point in the history
  • Loading branch information
0x0ACB committed Nov 18, 2024
1 parent 5efd124 commit c9cf855
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 13 deletions.
4 changes: 4 additions & 0 deletions drivers/d3d12/rendering_context_driver_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#endif

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

#include <wrl/client.h>
Expand Down Expand Up @@ -114,6 +115,9 @@ 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;
Expand Down
39 changes: 31 additions & 8 deletions drivers/d3d12/rendering_device_driver_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -2503,6 +2500,32 @@ Error RenderingDeviceDriverD3D12::swap_chain_resize(CommandQueueID p_cmd_queue,
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);
}

if (surface->composition_device.Get() == nullptr) {
res = 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);
Expand Down
11 changes: 6 additions & 5 deletions platform/windows/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,14 @@ def get_opts():

return [
("mingw_prefix", "MinGW prefix", mingw),
# Targeted Windows version: 7 (and later), minimum supported version
# Targeted Windows version: 8 (and later), minimum supported version
# XP support dropped after EOL due to missing API for IPv6 and other issues
# Vista support dropped after EOL due to GH-10243
# Windows 7 support dropped after EOL due to GH-95630
(
"target_win_version",
"Targeted Windows version, >= 0x0601 (Windows 7)",
"0x0601",
"Targeted Windows version, >= 0x0602 (Windows 8)",
"0x0602",
),
EnumVariable("windows_subsystem", "Windows subsystem", "gui", ("gui", "console")),
(
Expand Down Expand Up @@ -945,6 +946,6 @@ def check_d3d12_installed(env):


def validate_win_version(env):
if int(env["target_win_version"], 16) < 0x0601:
print_error("`target_win_version` should be 0x0601 or higher (Windows 7).")
if int(env["target_win_version"], 16) < 0x0602:
print_error("`target_win_version` should be 0x0602 or higher (Windows 8).")
sys.exit(255)
4 changes: 4 additions & 0 deletions platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit c9cf855

Please sign in to comment.