Skip to content

Commit

Permalink
[dx12] Add support for PresentMode::IMMEDIATE
Browse files Browse the repository at this point in the history
  • Loading branch information
yzsolt committed Nov 28, 2020
1 parent b3fc284 commit c57c938
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/backend/dx12/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ log = "0.4"
parking_lot = "0.11"
smallvec = "1"
spirv_cross = { version = "0.22", features = ["hlsl"] }
winapi = { version = "0.3", features = ["basetsd","d3d12","d3d12sdklayers","d3d12shader","d3dcommon","d3dcompiler","dxgi1_2","dxgi1_3","dxgi1_4","dxgi1_6","dxgidebug","dxgiformat","dxgitype","handleapi","minwindef","synchapi","unknwnbase","winbase","windef","winerror","winnt","winuser"] }
winapi = { version = "0.3", features = ["basetsd","d3d12","d3d12sdklayers","d3d12shader","d3dcommon","d3dcompiler","dxgi1_2","dxgi1_3","dxgi1_4","dxgi1_5","dxgi1_6","dxgidebug","dxgiformat","dxgitype","handleapi","minwindef","synchapi","unknwnbase","winbase","windef","winerror","winnt","winuser"] }
raw-window-handle = "0.3"

# This forces docs.rs to build the crate on windows, otherwise the build fails
Expand Down
7 changes: 6 additions & 1 deletion src/backend/dx12/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1085,14 +1085,19 @@ impl Device {
//TODO: proper error type?
let non_srgb_format = conv::map_format_nosrgb(config.format).unwrap();

let mut flags = dxgi::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
if config.present_mode.contains(w::PresentMode::IMMEDIATE) {
flags |= dxgi::DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
}

// TODO: double-check values
let desc = dxgi1_2::DXGI_SWAP_CHAIN_DESC1 {
AlphaMode: dxgi1_2::DXGI_ALPHA_MODE_IGNORE,
BufferCount: config.image_count,
Width: config.extent.width,
Height: config.extent.height,
Format: non_srgb_format,
Flags: dxgi::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT,
Flags: flags,
BufferUsage: dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT,
SampleDesc: dxgitype::DXGI_SAMPLE_DESC {
Count: 1,
Expand Down
45 changes: 41 additions & 4 deletions src/backend/dx12/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use std::{borrow::Borrow, fmt, mem, os::raw::c_void};

use winapi::{
shared::{
dxgi, dxgi1_4, dxgitype,
dxgi, dxgi1_4, dxgi1_5, dxgitype,
minwindef::{BOOL, FALSE, TRUE},
windef::{HWND, RECT},
winerror,
},
Expand All @@ -27,6 +28,7 @@ struct Presentation {
swapchain: Swapchain,
format: f::Format,
size: w::Extent2D,
mode: w::PresentMode,
}

pub struct Surface {
Expand Down Expand Up @@ -60,7 +62,13 @@ impl Surface {
return Err(w::PresentError::OutOfDate);
}

sc.inner.Present(1, 0);
let (interval, flags) = match present.mode {
w::PresentMode::IMMEDIATE => (0, dxgi::DXGI_PRESENT_ALLOW_TEARING),
w::PresentMode::FIFO => (1, 0),
_ => (1, 0), // Surface was created with an unsupported present mode, fall back to FIFO
};

sc.inner.Present(interval, flags);
Ok(())
}
}
Expand All @@ -85,8 +93,31 @@ impl w::Surface<Backend> for Surface {
})
};

let allow_tearing = unsafe {
let (f5, hr) = self.factory.cast::<dxgi1_5::IDXGIFactory5>();
if winerror::SUCCEEDED(hr) {
let mut allow_tearing: BOOL = FALSE;
let hr = f5.CheckFeatureSupport(
dxgi1_5::DXGI_FEATURE_PRESENT_ALLOW_TEARING,
&mut allow_tearing as *mut _ as *mut _,
mem::size_of::<BOOL>() as _,
);

f5.destroy();

winerror::SUCCEEDED(hr) && allow_tearing == TRUE
} else {
false
}
};

let mut present_modes = w::PresentMode::FIFO;
if allow_tearing {
present_modes |= w::PresentMode::IMMEDIATE;
}

w::SurfaceCapabilities {
present_modes: w::PresentMode::FIFO, //TODO
present_modes,
composite_alpha_modes: w::CompositeAlphaMode::OPAQUE, //TODO
image_count: 2..=16, // we currently use a flip effect which supports 2..=16 buffers
current_extent,
Expand Down Expand Up @@ -152,13 +183,18 @@ impl w::PresentationSurface<Backend> for Surface {
// can't have image resources in flight used by GPU
device.wait_idle().unwrap();

let mut flags = dxgi::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
if config.present_mode.contains(w::PresentMode::IMMEDIATE) {
flags |= dxgi::DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
}

let inner = present.swapchain.release_resources();
let result = inner.ResizeBuffers(
config.image_count,
config.extent.width,
config.extent.height,
conv::map_format_nosrgb(config.format).unwrap(),
dxgi::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT,
flags,
);
if result != winerror::S_OK {
error!("ResizeBuffers failed with 0x{:x}", result as u32);
Expand All @@ -185,6 +221,7 @@ impl w::PresentationSurface<Backend> for Surface {
swapchain: device.wrap_swapchain(swapchain, &config),
format: config.format,
size: config.extent,
mode: config.present_mode,
});
Ok(())
}
Expand Down

0 comments on commit c57c938

Please sign in to comment.