mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
hal/dx12: attachment clears and resolvess
This commit is contained in:
@@ -46,7 +46,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
}
|
||||
self.list = Some(list);
|
||||
self.temp.clear();
|
||||
self.has_pass_label = false;
|
||||
self.pass.clear();
|
||||
Ok(())
|
||||
}
|
||||
unsafe fn discard_encoding(&mut self) {
|
||||
@@ -391,14 +391,14 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor<super::Api>) {
|
||||
if let Some(label) = desc.label {
|
||||
self.begin_debug_marker(label);
|
||||
self.has_pass_label = true;
|
||||
self.pass.has_label = true;
|
||||
}
|
||||
|
||||
self.temp.barriers.clear();
|
||||
|
||||
let mut color_views = [native::CpuDescriptor { ptr: 0 }; crate::MAX_COLOR_TARGETS];
|
||||
for (cv, cat) in color_views.iter_mut().zip(desc.color_attachments.iter()) {
|
||||
*cv = cat.target.view.handle_rtv.unwrap().raw;
|
||||
for (rtv, cat) in color_views.iter_mut().zip(desc.color_attachments.iter()) {
|
||||
*rtv = cat.target.view.handle_rtv.unwrap().raw;
|
||||
}
|
||||
let ds_view = match desc.depth_stencil_attachment {
|
||||
None => ptr::null(),
|
||||
@@ -411,18 +411,107 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
}
|
||||
};
|
||||
|
||||
self.list.unwrap().OMSetRenderTargets(
|
||||
let list = self.list.unwrap();
|
||||
list.OMSetRenderTargets(
|
||||
desc.color_attachments.len() as u32,
|
||||
color_views.as_ptr(),
|
||||
0,
|
||||
ds_view,
|
||||
);
|
||||
|
||||
self.pass.resolves.clear();
|
||||
for (rtv, cat) in color_views.iter().zip(desc.color_attachments.iter()) {
|
||||
if !cat.ops.contains(crate::AttachmentOps::LOAD) {
|
||||
let value = [
|
||||
cat.clear_value.r as f32,
|
||||
cat.clear_value.g as f32,
|
||||
cat.clear_value.b as f32,
|
||||
cat.clear_value.a as f32,
|
||||
];
|
||||
list.clear_render_target_view(*rtv, value, &[]);
|
||||
}
|
||||
if let Some(ref target) = cat.resolve_target {
|
||||
self.pass.resolves.push(super::PassResolve {
|
||||
src: cat.target.view.target_base,
|
||||
dst: target.view.target_base,
|
||||
format: target.view.raw_format,
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some(ref ds) = desc.depth_stencil_attachment {
|
||||
let mut flags = native::ClearFlags::empty();
|
||||
if !ds.depth_ops.contains(crate::AttachmentOps::LOAD) {
|
||||
flags |= native::ClearFlags::DEPTH;
|
||||
}
|
||||
if !ds.stencil_ops.contains(crate::AttachmentOps::LOAD) {
|
||||
flags |= native::ClearFlags::STENCIL;
|
||||
}
|
||||
|
||||
if !ds_view.is_null() {
|
||||
list.clear_depth_stencil_view(
|
||||
*ds_view,
|
||||
flags,
|
||||
ds.clear_value.0,
|
||||
ds.clear_value.1 as u8,
|
||||
&[],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe fn end_render_pass(&mut self) {
|
||||
if self.has_pass_label {
|
||||
self.end_debug_marker();
|
||||
self.has_pass_label = false;
|
||||
if !self.pass.resolves.is_empty() {
|
||||
let list = self.list.unwrap();
|
||||
self.temp.barriers.clear();
|
||||
|
||||
// All the targets are expected to be in `COLOR_TARGET` state,
|
||||
// but D3D12 has special source/destination states for the resolves.
|
||||
for resolve in self.pass.resolves.iter() {
|
||||
let mut barrier = d3d12::D3D12_RESOURCE_BARRIER {
|
||||
Type: d3d12::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
|
||||
Flags: d3d12::D3D12_RESOURCE_BARRIER_FLAG_NONE,
|
||||
u: mem::zeroed(),
|
||||
};
|
||||
//Note: this assumes `D3D12_RESOURCE_STATE_RENDER_TARGET`.
|
||||
// If it's not the case, we can include the `TextureUses` in `PassResove`.
|
||||
*barrier.u.Transition_mut() = d3d12::D3D12_RESOURCE_TRANSITION_BARRIER {
|
||||
pResource: resolve.src.0.as_mut_ptr(),
|
||||
Subresource: resolve.src.1,
|
||||
StateBefore: d3d12::D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
StateAfter: d3d12::D3D12_RESOURCE_STATE_RESOLVE_DEST,
|
||||
};
|
||||
self.temp.barriers.push(barrier);
|
||||
*barrier.u.Transition_mut() = d3d12::D3D12_RESOURCE_TRANSITION_BARRIER {
|
||||
pResource: resolve.dst.0.as_mut_ptr(),
|
||||
Subresource: resolve.dst.1,
|
||||
StateBefore: d3d12::D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
StateAfter: d3d12::D3D12_RESOURCE_STATE_RESOLVE_DEST,
|
||||
};
|
||||
self.temp.barriers.push(barrier);
|
||||
}
|
||||
list.ResourceBarrier(self.temp.barriers.len() as u32, self.temp.barriers.as_ptr());
|
||||
|
||||
for resolve in self.pass.resolves.iter() {
|
||||
list.ResolveSubresource(
|
||||
resolve.dst.0.as_mut_ptr(),
|
||||
resolve.dst.1,
|
||||
resolve.src.0.as_mut_ptr(),
|
||||
resolve.src.1,
|
||||
resolve.format,
|
||||
);
|
||||
}
|
||||
|
||||
// Flip all the barriers to reverse, back into `COLOR_TARGET`.
|
||||
for barrier in self.temp.barriers.iter_mut() {
|
||||
let transition = barrier.u.Transition_mut();
|
||||
mem::swap(&mut transition.StateBefore, &mut transition.StateAfter);
|
||||
}
|
||||
list.ResourceBarrier(self.temp.barriers.len() as u32, self.temp.barriers.as_ptr());
|
||||
}
|
||||
|
||||
if self.pass.has_label {
|
||||
self.end_debug_marker();
|
||||
}
|
||||
self.pass.clear();
|
||||
}
|
||||
|
||||
unsafe fn set_bind_group(
|
||||
@@ -596,14 +685,14 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) {
|
||||
if let Some(label) = desc.label {
|
||||
self.begin_debug_marker(label);
|
||||
self.has_pass_label = true;
|
||||
self.pass.has_label = true;
|
||||
}
|
||||
}
|
||||
unsafe fn end_compute_pass(&mut self) {
|
||||
if self.has_pass_label {
|
||||
if self.pass.has_label {
|
||||
self.end_debug_marker();
|
||||
self.has_pass_label = false;
|
||||
}
|
||||
self.pass.clear();
|
||||
}
|
||||
|
||||
unsafe fn set_compute_pipeline(&mut self, pipeline: &Resource) {}
|
||||
|
||||
@@ -670,6 +670,12 @@ impl crate::Device<super::Api> for super::Device {
|
||||
desc: &crate::TextureViewDescriptor,
|
||||
) -> Result<super::TextureView, crate::DeviceError> {
|
||||
Ok(super::TextureView {
|
||||
//Note: this mapping also happens in all of the `view_texture_as_*`
|
||||
raw_format: conv::map_texture_format(desc.format),
|
||||
target_base: (
|
||||
texture.resource,
|
||||
texture.calc_subresource(desc.range.base_mip_level, desc.range.base_array_layer, 0),
|
||||
),
|
||||
handle_srv: if desc
|
||||
.usage
|
||||
.intersects(crate::TextureUses::SAMPLED | crate::TextureUses::STORAGE_LOAD)
|
||||
@@ -783,7 +789,7 @@ impl crate::Device<super::Api> for super::Device {
|
||||
shared: Arc::clone(&self.shared),
|
||||
list: None,
|
||||
free_lists: Vec::new(),
|
||||
has_pass_label: false,
|
||||
pass: super::PassState::default(),
|
||||
temp: super::Temp::default(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -14,10 +14,11 @@ mod descriptor;
|
||||
mod device;
|
||||
mod instance;
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use parking_lot::Mutex;
|
||||
use std::{borrow::Cow, ptr, sync::Arc};
|
||||
use winapi::{
|
||||
shared::{dxgi, dxgi1_2, dxgi1_4, dxgitype, windef, winerror},
|
||||
shared::{dxgi, dxgi1_2, dxgi1_4, dxgiformat, dxgitype, windef, winerror},
|
||||
um::{d3d12, synchapi, winbase, winnt},
|
||||
Interface as _,
|
||||
};
|
||||
@@ -222,13 +223,32 @@ impl Temp {
|
||||
}
|
||||
}
|
||||
|
||||
struct PassResolve {
|
||||
src: (native::Resource, u32),
|
||||
dst: (native::Resource, u32),
|
||||
format: dxgiformat::DXGI_FORMAT,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct PassState {
|
||||
has_label: bool,
|
||||
resolves: ArrayVec<[PassResolve; crate::MAX_COLOR_TARGETS]>,
|
||||
}
|
||||
|
||||
impl PassState {
|
||||
fn clear(&mut self) {
|
||||
self.has_label = false;
|
||||
self.resolves.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CommandEncoder {
|
||||
allocator: native::CommandAllocator,
|
||||
device: native::Device,
|
||||
shared: Arc<DeviceShared>,
|
||||
list: Option<native::GraphicsCommandList>,
|
||||
free_lists: Vec<native::GraphicsCommandList>,
|
||||
has_pass_label: bool,
|
||||
pass: PassState,
|
||||
temp: Temp,
|
||||
}
|
||||
|
||||
@@ -284,6 +304,8 @@ impl Texture {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TextureView {
|
||||
raw_format: dxgiformat::DXGI_FORMAT,
|
||||
target_base: (native::Resource, u32),
|
||||
handle_srv: Option<descriptor::Handle>,
|
||||
handle_uav: Option<descriptor::Handle>,
|
||||
handle_rtv: Option<descriptor::Handle>,
|
||||
@@ -349,7 +371,7 @@ pub struct PipelineLayout {
|
||||
total_slots: u32,
|
||||
// Storing for each associated bind group, which tables we created
|
||||
// in the root signature. This is required for binding descriptor sets.
|
||||
elements: arrayvec::ArrayVec<RootElement, crate::MAX_BIND_GROUPS>,
|
||||
elements: ArrayVec<RootElement, crate::MAX_BIND_GROUPS>,
|
||||
}
|
||||
|
||||
unsafe impl Send for PipelineLayout {}
|
||||
|
||||
Reference in New Issue
Block a user