From 21be559a9f3e40e143458ff7e29e70e071057dd4 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Tue, 21 Jul 2020 13:52:44 -0400 Subject: [PATCH] Add depth clamping support --- wgpu-core/src/conv.rs | 2 +- wgpu-core/src/device/mod.rs | 18 ++++++++++++++---- wgpu-core/src/instance.rs | 4 ++++ wgpu-core/src/pipeline.rs | 1 + wgpu-core/src/swap_chain.rs | 13 +++++++------ wgpu-types/src/lib.rs | 16 ++++++++++++++++ 6 files changed, 43 insertions(+), 11 deletions(-) diff --git a/wgpu-core/src/conv.rs b/wgpu-core/src/conv.rs index 0b15c42823..0e88169e41 100644 --- a/wgpu-core/src/conv.rs +++ b/wgpu-core/src/conv.rs @@ -635,7 +635,7 @@ pub fn map_rasterization_state_descriptor( ) -> hal::pso::Rasterizer { use hal::pso; pso::Rasterizer { - depth_clamping: false, + depth_clamping: desc.clamp_depth, polygon_mode: pso::PolygonMode::Fill, cull_face: match desc.cull_mode { wgt::CullMode::None => pso::Face::empty(), diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index f2f9d2a92f..ca85acd980 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -2108,10 +2108,12 @@ impl Global { let color_states = &desc.color_states; let depth_stencil_state = desc.depth_stencil_state.as_ref(); - let rasterization_state = desc.rasterization_state.as_ref(); - let rasterizer = conv::map_rasterization_state_descriptor( - &rasterization_state.cloned().unwrap_or_default(), - ); + let rasterization_state = desc + .rasterization_state + .as_ref() + .cloned() + .unwrap_or_default(); + let rasterizer = conv::map_rasterization_state_descriptor(&rasterization_state); let mut interface = validation::StageInterface::default(); let mut validated_stages = wgt::ShaderStage::empty(); @@ -2199,6 +2201,14 @@ impl Global { let (device_guard, mut token) = hub.devices.read(&mut token); let device = &device_guard[device_id]; + if rasterization_state.clamp_depth + && !device.features.contains(wgt::Features::DEPTH_CLAMPING) + { + return Err(pipeline::RenderPipelineError::MissingFeature( + wgt::Features::DEPTH_CLAMPING, + )); + } + let (raw_pipeline, layout_ref_count) = { let (pipeline_layout_guard, mut token) = hub.pipeline_layouts.read(&mut token); let (bgl_guard, mut token) = hub.bind_group_layouts.read(&mut token); diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 836f46a103..3f840c2208 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -127,6 +127,10 @@ impl Adapter { let mut features = wgt::Features::default() | wgt::Features::MAPPABLE_PRIMARY_BUFFERS | wgt::Features::PUSH_CONSTANTS; + features.set( + wgt::Features::DEPTH_CLAMPING, + adapter_features.contains(hal::Features::DEPTH_CLAMP), + ); features.set( wgt::Features::SAMPLED_TEXTURE_BINDING_ARRAY, adapter_features.contains(hal::Features::TEXTURE_DESCRIPTOR_ARRAY), diff --git a/wgpu-core/src/pipeline.rs b/wgpu-core/src/pipeline.rs index 75113cbda6..4e93f45d2c 100644 --- a/wgpu-core/src/pipeline.rs +++ b/wgpu-core/src/pipeline.rs @@ -55,6 +55,7 @@ pub type RenderPipelineDescriptor<'a> = #[derive(Clone, Debug)] pub enum RenderPipelineError { + MissingFeature(wgt::Features), InvalidVertexAttributeOffset { location: wgt::ShaderLocation, offset: BufferAddress, diff --git a/wgpu-core/src/swap_chain.rs b/wgpu-core/src/swap_chain.rs index ffd8b78611..8b43ff7f73 100644 --- a/wgpu-core/src/swap_chain.rs +++ b/wgpu-core/src/swap_chain.rs @@ -41,10 +41,7 @@ use crate::{ resource, span, LifeGuard, PrivateFeatures, Stored, SubmissionIndex, }; -use hal::{ - self, device::Device as _, queue::CommandQueue as _, - window::PresentationSurface as _, -}; +use hal::{self, device::Device as _, queue::CommandQueue as _, window::PresentationSurface as _}; use thiserror::Error; use wgt::{SwapChainDescriptor, SwapChainStatus}; @@ -129,12 +126,16 @@ impl Global { Err(err) => ( None, match err { - hal::window::AcquireError::OutOfMemory(_) => return Err(SwapChainError::OutOfMemory), + hal::window::AcquireError::OutOfMemory(_) => { + return Err(SwapChainError::OutOfMemory) + } hal::window::AcquireError::NotReady => unreachable!(), // we always set a timeout hal::window::AcquireError::Timeout => SwapChainStatus::Timeout, hal::window::AcquireError::OutOfDate => SwapChainStatus::Outdated, hal::window::AcquireError::SurfaceLost(_) => SwapChainStatus::Lost, - hal::window::AcquireError::DeviceLost(_) => return Err(SwapChainError::DeviceLost), + hal::window::AcquireError::DeviceLost(_) => { + return Err(SwapChainError::DeviceLost) + } }, ), }; diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 72059b0b25..ea5824dce9 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -131,6 +131,18 @@ bitflags::bitflags! { #[cfg_attr(feature = "trace", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct Features: u64 { + /// By default, polygon depth is clipped to 0-1 range. Anything outside of that range + /// is rejected, and respective fragments are not touched. + /// + /// With this extension, we can force clamping of the polygon depth to 0-1. That allows + /// shadow map occluders to be rendered into a tighter depth range. + /// + /// Supported platforms: + /// - desktops + /// - some mobile chips + /// + /// This is a web and native feature. + const DEPTH_CLAMPING = 0x0000_0000_0000_0001; /// Webgpu only allows the MAP_READ and MAP_WRITE buffer usage to be matched with /// COPY_DST and COPY_SRC respectively. This removes this requirement. /// @@ -543,6 +555,10 @@ impl Default for CullMode { pub struct RasterizationStateDescriptor { pub front_face: FrontFace, pub cull_mode: CullMode, + /// If enabled polygon depth is clamped to 0-1 range instead of being clipped. + /// + /// Requires `Features::DEPTH_CLAMPING` enabled. + pub clamp_depth: bool, pub depth_bias: i32, pub depth_bias_slope_scale: f32, pub depth_bias_clamp: f32,