Skip to content

Commit

Permalink
Merge #1602
Browse files Browse the repository at this point in the history
1602: New DX12 backend (unfinished) r=kvark a=kvark

**Connections**
Continuation of #1471

**Description**
Mostly fresh implementation on DX12 backend for wgpu-hal
Core changes:
  - texture usage is filtered before passing to `create_texture_view`, so that wgpu-hal can assume every bit is important.
  - all the copies involving textures are limited to one array layer at a time
  - remove render pass boundary usages

**Testing**
Examples (not running yet)


Co-authored-by: Dzmitry Malyshau <dmalyshau@mozilla.com>
Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
  • Loading branch information
3 people committed Jul 13, 2021
2 parents 2e02eef + 0df804e commit 0f784bb
Show file tree
Hide file tree
Showing 40 changed files with 5,216 additions and 634 deletions.
22 changes: 21 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ If you are looking for the native implementation or bindings to the API in other
API | Windows 7/10 | Linux & Android | macOS & iOS |
----- | ------------------ | ------------------ | ------------------ |
DX11 | :construction: | | |
DX12 | :construction: | | |
DX12 | :ok: | | |
Vulkan | :white_check_mark: | :white_check_mark: | |
Metal | | | :white_check_mark: |
GLes3 | | :ok: | |
Expand Down
4 changes: 2 additions & 2 deletions wgpu-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ thiserror = "1"

[dependencies.naga]
git = "https://github.com/gfx-rs/naga"
rev = "0b9af95793e319817e74a30601cbcd4bad9bb3e6"
rev = "458db0b"
features = ["wgsl-in"]

[dependencies.wgt]
Expand All @@ -57,7 +57,7 @@ hal = { path = "../wgpu-hal", package = "wgpu-hal", features = ["metal"] }
hal = { path = "../wgpu-hal", package = "wgpu-hal", features = ["vulkan", "gles"] }

[target.'cfg(all(not(target_arch = "wasm32"), windows))'.dependencies]
hal = { path = "../wgpu-hal", package = "wgpu-hal", features = ["vulkan"] }
hal = { path = "../wgpu-hal", package = "wgpu-hal", features = ["vulkan", "dx12"] }

[build-dependencies]
cfg_aliases = "0.1"
2 changes: 1 addition & 1 deletion wgpu-core/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fn main() {
// Backends
vulkan: { all(not(wasm), any(windows, unix_wo_apple)) },
metal: { all(not(wasm), apple) },
dx12: { all(false, not(wasm), windows) },
dx12: { all(not(wasm), windows) },
dx11: { all(false, not(wasm), windows) },
gl: { all(not(wasm), unix_wo_apple) },
}
Expand Down
142 changes: 70 additions & 72 deletions wgpu-core/src/command/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::{
memory_init_tracker::{MemoryInitKind, MemoryInitTrackerAction},
pipeline::PipelineFlags,
resource::{Texture, TextureView, TextureViewSource},
swap_chain::SwapChain,
track::{StatefulTrackerSubset, TextureSelector, UsageConflict},
validation::{
check_buffer_usage, check_texture_usage, MissingBufferUsageError, MissingTextureUsageError,
Expand Down Expand Up @@ -491,11 +492,11 @@ where
struct RenderAttachment<'a> {
texture_id: &'a Stored<id::TextureId>,
selector: &'a TextureSelector,
previous_use: Option<hal::TextureUses>,
new_use: hal::TextureUses,
usage: hal::TextureUses,
}

type AttachmentDataVec<T> = ArrayVec<T, { hal::MAX_COLOR_TARGETS + hal::MAX_COLOR_TARGETS + 1 }>;
const MAX_TOTAL_ATTACHMENTS: usize = hal::MAX_COLOR_TARGETS + hal::MAX_COLOR_TARGETS + 1;
type AttachmentDataVec<T> = ArrayVec<T, MAX_TOTAL_ATTACHMENTS>;

struct RenderPassInfo<'a, A: hal::Api> {
context: RenderPassContext,
Expand All @@ -514,6 +515,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
depth_stencil_attachment: Option<&RenderPassDepthStencilAttachment>,
cmd_buf: &mut CommandBuffer<A>,
view_guard: &'a Storage<TextureView<A>, id::TextureViewId>,
swap_chain_guard: &'a Storage<SwapChain<A>, id::SwapChainId>,
) -> Result<Self, RenderPassErrorInner> {
profiling::scope!("start", "RenderPassInfo");

Expand All @@ -527,7 +529,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
let mut attachment_type_name = "";
let mut extent = None;
let mut sample_count = 0;
let mut used_swap_chain = None::<Stored<id::SwapChainId>>;
let mut used_swap_chain = None::<(Stored<id::SwapChainId>, hal::TextureUses)>;

let mut add_view = |view: &TextureView<A>, type_name| {
if let Some(ex) = extent {
Expand Down Expand Up @@ -577,12 +579,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
}
};

// Using render pass for transition.
let previous_use = cmd_buf
.trackers
.textures
.query(source_id.value, view.selector.clone());
let new_use = if at.is_read_only(ds_aspects)? {
let usage = if at.is_read_only(ds_aspects)? {
is_ds_read_only = true;
hal::TextureUses::DEPTH_STENCIL_READ | hal::TextureUses::SAMPLED
} else {
Expand All @@ -591,16 +588,13 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
render_attachments.push(RenderAttachment {
texture_id: source_id,
selector: &view.selector,
previous_use,
new_use,
usage,
});

let old_use = previous_use.unwrap_or(new_use);
depth_stencil = Some(hal::DepthStencilAttachment {
target: hal::Attachment {
view: &view.raw,
usage: new_use,
boundary_usage: old_use..new_use,
usage,
},
depth_ops: at.depth.hal_ops(),
stencil_ops: at.stencil.hal_ops(),
Expand All @@ -626,33 +620,22 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
));
}

let boundary_usage = match color_view.source {
match color_view.source {
TextureViewSource::Native(ref source_id) => {
let previous_use = cmd_buf
.trackers
.textures
.query(source_id.value, color_view.selector.clone());
let new_use = hal::TextureUses::COLOR_TARGET;
render_attachments.push(RenderAttachment {
texture_id: source_id,
selector: &color_view.selector,
previous_use,
new_use,
usage: hal::TextureUses::COLOR_TARGET,
});

let old_use = previous_use.unwrap_or(new_use);
old_use..new_use
}
TextureViewSource::SwapChain(ref source_id) => {
assert!(used_swap_chain.is_none());
used_swap_chain = Some(source_id.clone());

let end = hal::TextureUses::empty();
let start = match at.channel.load_op {
//HACK: guess the start usage based on the load op
let start_usage = match at.channel.load_op {
LoadOp::Load => hal::TextureUses::empty(),
LoadOp::Clear => hal::TextureUses::UNINITIALIZED,
LoadOp::Load => end,
};
start..end
assert!(used_swap_chain.is_none());
used_swap_chain = Some((source_id.clone(), start_usage));
}
};

Expand All @@ -676,42 +659,32 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
return Err(RenderPassErrorInner::InvalidResolveTargetSampleCount);
}

let boundary_usage = match resolve_view.source {
match resolve_view.source {
TextureViewSource::Native(ref source_id) => {
let previous_use = cmd_buf
.trackers
.textures
.query(source_id.value, resolve_view.selector.clone());
let new_use = hal::TextureUses::COLOR_TARGET;
render_attachments.push(RenderAttachment {
texture_id: source_id,
selector: &resolve_view.selector,
previous_use,
new_use,
usage: hal::TextureUses::COLOR_TARGET,
});

let old_use = previous_use.unwrap_or(new_use);
old_use..new_use
}
TextureViewSource::SwapChain(ref source_id) => {
//HACK: guess the start usage
let start_usage = hal::TextureUses::UNINITIALIZED;
assert!(used_swap_chain.is_none());
used_swap_chain = Some(source_id.clone());
hal::TextureUses::UNINITIALIZED..hal::TextureUses::empty()
used_swap_chain = Some((source_id.clone(), start_usage));
}
};

hal_resolve_target = Some(hal::Attachment {
view: &resolve_view.raw,
usage: hal::TextureUses::COLOR_TARGET,
boundary_usage,
});
}

colors.push(hal::ColorAttachment {
target: hal::Attachment {
view: &color_view.raw,
usage: hal::TextureUses::COLOR_TARGET,
boundary_usage,
},
resolve_target: hal_resolve_target,
ops: at.channel.hal_ops(),
Expand All @@ -723,6 +696,21 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
return Err(RenderPassErrorInner::InvalidSampleCount(sample_count));
}

if let Some((ref sc_id, start_usage)) = used_swap_chain {
let &(_, ref suf_texture) = swap_chain_guard[sc_id.value]
.acquired_texture
.as_ref()
.unwrap();
let barrier = hal::TextureBarrier {
texture: std::borrow::Borrow::borrow(suf_texture),
usage: start_usage..hal::TextureUses::COLOR_TARGET,
range: wgt::ImageSubresourceRange::default(),
};
unsafe {
cmd_buf.encoder.raw.transition_textures(iter::once(barrier));
}
}

let view_data = AttachmentData {
colors: color_attachments
.iter()
Expand Down Expand Up @@ -756,7 +744,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
context,
trackers: StatefulTrackerSubset::new(A::VARIANT),
render_attachments,
used_swap_chain,
used_swap_chain: used_swap_chain.map(|(sc_id, _)| sc_id),
is_ds_read_only,
extent,
_phantom: PhantomData,
Expand All @@ -767,9 +755,28 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
mut self,
raw: &mut A::CommandEncoder,
texture_guard: &Storage<Texture<A>, id::TextureId>,
swap_chain_guard: &Storage<SwapChain<A>, id::SwapChainId>,
) -> Result<(StatefulTrackerSubset, Option<Stored<id::SwapChainId>>), RenderPassErrorInner>
{
profiling::scope!("finish", "RenderPassInfo");
unsafe {
raw.end_render_pass();
}

if let Some(ref sc_id) = self.used_swap_chain {
let &(_, ref suf_texture) = swap_chain_guard[sc_id.value]
.acquired_texture
.as_ref()
.unwrap();
let barrier = hal::TextureBarrier {
texture: std::borrow::Borrow::borrow(suf_texture),
usage: hal::TextureUses::COLOR_TARGET..hal::TextureUses::empty(),
range: wgt::ImageSubresourceRange::default(),
};
unsafe {
raw.transition_textures(iter::once(barrier));
}
}

for ra in self.render_attachments {
let texture = &texture_guard[ra.texture_id.value];
Expand All @@ -782,29 +789,11 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
ra.texture_id.value,
&ra.texture_id.ref_count,
ra.selector.clone(),
ra.new_use,
ra.usage,
)
.map_err(UsageConflict::from)?;

if let Some(usage) = ra.previous_use {
// Make the attachment tracks to be aware of the internal
// transition done by the render pass, by registering the
// previous usage as the initial state.
self.trackers
.textures
.prepend(
ra.texture_id.value,
&ra.texture_id.ref_count,
ra.selector.clone(),
usage,
)
.unwrap();
}
}

unsafe {
raw.end_render_pass();
}
Ok((self.trackers, self.used_swap_chain))
}
}
Expand Down Expand Up @@ -842,7 +831,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let (device_guard, mut token) = hub.devices.read(&mut token);

let (pass_raw, trackers, query_reset_state) = {
// read-only lock guard
let (swap_chain_guard, mut token) = hub.swap_chains.read(&mut token);
let (mut cmb_guard, mut token) = hub.command_buffers.write(&mut token);

let cmd_buf =
Expand Down Expand Up @@ -886,6 +875,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
depth_stencil_attachment,
cmd_buf,
&*view_guard,
&*swap_chain_guard,
)
.map_pass_err(scope)?;

Expand Down Expand Up @@ -1206,8 +1196,14 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}
RenderCommand::SetBlendConstant(ref color) => {
state.blend_constant = OptionalState::Set;
let array = [
color.r as f32,
color.g as f32,
color.b as f32,
color.a as f32,
];
unsafe {
raw.set_blend_constants(color);
raw.set_blend_constants(&array);
}
}
RenderCommand::SetStencilReference(value) => {
Expand Down Expand Up @@ -1738,8 +1734,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}

log::trace!("Merging {:?} with the render pass", encoder_id);
let (trackers, used_swapchain) =
info.finish(raw, &*texture_guard).map_pass_err(scope)?;
let (trackers, used_swapchain) = info
.finish(raw, &*texture_guard, &*swap_chain_guard)
.map_pass_err(scope)?;

let raw_cmd_buf = unsafe {
raw.end_encoding()
.map_err(|_| RenderPassErrorInner::OutOfMemory)
Expand Down
Loading

0 comments on commit 0f784bb

Please sign in to comment.