From 1153bc698e36e13b8861f42cc418667e31ac5927 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 27 Sep 2021 16:29:11 -0400 Subject: [PATCH] [spv-out] option to clamp frag_depth --- src/back/spv/block.rs | 119 +++++++++++++++++------- src/back/spv/mod.rs | 6 +- tests/in/interface.param.ron | 1 + tests/out/spv/interface.fragment.spvasm | 13 ++- tests/snapshots.rs | 6 ++ 5 files changed, 105 insertions(+), 40 deletions(-) diff --git a/src/back/spv/block.rs b/src/back/spv/block.rs index e9970c23ca..c46a4d4ba9 100644 --- a/src/back/spv/block.rs +++ b/src/back/spv/block.rs @@ -20,6 +20,85 @@ fn get_dimension(type_inner: &crate::TypeInner) -> Dimension { } impl Writer { + // Flip Y coordinate to adjust for coordinate space difference + // between SPIR-V and our IR. + fn write_epilogue_position_y_flip( + &mut self, + position_id: Word, + body: &mut Vec, + ) -> Result<(), Error> { + let access_id = self.id_gen.next(); + let float_ptr_type_id = self.get_type_id(LookupType::Local(LocalType::Value { + vector_size: None, + kind: crate::ScalarKind::Float, + width: 4, + pointer_class: Some(spirv::StorageClass::Output), + })); + let index_y_id = self.get_index_constant(1); + body.push(Instruction::access_chain( + float_ptr_type_id, + access_id, + position_id, + &[index_y_id], + )); + + let load_id = self.id_gen.next(); + let float_type_id = self.get_type_id(LookupType::Local(LocalType::Value { + vector_size: None, + kind: crate::ScalarKind::Float, + width: 4, + pointer_class: None, + })); + body.push(Instruction::load(float_type_id, load_id, access_id, None)); + + let neg_id = self.id_gen.next(); + body.push(Instruction::unary( + spirv::Op::FNegate, + float_type_id, + neg_id, + load_id, + )); + + body.push(Instruction::store(access_id, neg_id, None)); + Ok(()) + } + + // Clamp fragment depth between 0 and 1. + fn write_epilogue_frag_depth_clamp( + &mut self, + frag_depth_id: Word, + body: &mut Vec, + ) -> Result<(), Error> { + let float_type_id = self.get_type_id(LookupType::Local(LocalType::Value { + vector_size: None, + kind: crate::ScalarKind::Float, + width: 4, + pointer_class: None, + })); + let value0_id = self.get_constant_scalar(crate::ScalarValue::Float(0.0), 4); + let value1_id = self.get_constant_scalar(crate::ScalarValue::Float(1.0), 4); + + let original_id = self.id_gen.next(); + body.push(Instruction::load( + float_type_id, + original_id, + frag_depth_id, + None, + )); + + let clamp_id = self.id_gen.next(); + body.push(Instruction::ext_inst( + self.gl450_ext_inst_id, + spirv::GLOp::FClamp, + float_type_id, + clamp_id, + &[original_id, value0_id, value1_id], + )); + + body.push(Instruction::store(frag_depth_id, clamp_id, None)); + Ok(()) + } + fn write_entry_point_return( &mut self, value_id: Word, @@ -44,43 +123,15 @@ impl Writer { body.push(Instruction::store(res_member.id, member_value_id, None)); - // Flip Y coordinate to adjust for coordinate space difference - // between SPIR-V and our IR. if self.flags.contains(WriterFlags::ADJUST_COORDINATE_SPACE) && res_member.built_in == Some(crate::BuiltIn::Position) { - let access_id = self.id_gen.next(); - let float_ptr_type_id = self.get_type_id(LookupType::Local(LocalType::Value { - vector_size: None, - kind: crate::ScalarKind::Float, - width: 4, - pointer_class: Some(spirv::StorageClass::Output), - })); - let index_y_id = self.get_index_constant(1); - body.push(Instruction::access_chain( - float_ptr_type_id, - access_id, - res_member.id, - &[index_y_id], - )); - - let load_id = self.id_gen.next(); - let float_type_id = self.get_type_id(LookupType::Local(LocalType::Value { - vector_size: None, - kind: crate::ScalarKind::Float, - width: 4, - pointer_class: None, - })); - body.push(Instruction::load(float_type_id, load_id, access_id, None)); - - let neg_id = self.id_gen.next(); - body.push(Instruction::unary( - spirv::Op::FNegate, - float_type_id, - neg_id, - load_id, - )); - body.push(Instruction::store(access_id, neg_id, None)); + self.write_epilogue_position_y_flip(res_member.id, body)?; + } + if self.flags.contains(WriterFlags::CLAMP_FRAG_DEPTH) + && res_member.built_in == Some(crate::BuiltIn::FragDepth) + { + self.write_epilogue_frag_depth_clamp(res_member.id, body)?; } } Ok(()) diff --git a/src/back/spv/mod.rs b/src/back/spv/mod.rs index 7acbd3b6d1..4eb75706b0 100644 --- a/src/back/spv/mod.rs +++ b/src/back/spv/mod.rs @@ -568,6 +568,8 @@ bitflags::bitflags! { /// Emit `PointSize` output builtin to vertex shaders, which is /// required for drawing with `PointList` topology. const FORCE_POINT_SIZE = 0x8; + /// Clamp `BuiltIn::FragDepth` output between 0 and 1. + const CLAMP_FRAG_DEPTH = 0x10; } } @@ -592,7 +594,9 @@ pub struct Options { impl Default for Options { fn default() -> Self { - let mut flags = WriterFlags::ADJUST_COORDINATE_SPACE | WriterFlags::LABEL_VARYINGS; + let mut flags = WriterFlags::ADJUST_COORDINATE_SPACE + | WriterFlags::LABEL_VARYINGS + | WriterFlags::CLAMP_FRAG_DEPTH; if cfg!(debug_assertions) { flags |= WriterFlags::DEBUG; } diff --git a/tests/in/interface.param.ron b/tests/in/interface.param.ron index fdca2996b4..4e32d785ca 100644 --- a/tests/in/interface.param.ron +++ b/tests/in/interface.param.ron @@ -4,6 +4,7 @@ capabilities: [ Shader, SampleRateShading ], adjust_coordinate_space: false, force_point_size: true, + clamp_frag_depth: true, separate_entry_points: true, ), hlsl_custom: true, diff --git a/tests/out/spv/interface.fragment.spvasm b/tests/out/spv/interface.fragment.spvasm index 4253449906..5e7b97af1f 100644 --- a/tests/out/spv/interface.fragment.spvasm +++ b/tests/out/spv/interface.fragment.spvasm @@ -1,7 +1,7 @@ ; SPIR-V ; Version: 1.0 ; Generator: rspirv -; Bound: 49 +; Bound: 51 OpCapability Shader OpCapability SampleRateShading %1 = OpExtInstImport "GLSL.std.450" @@ -70,9 +70,12 @@ OpBranch %40 %45 = OpCompositeConstruct %13 %44 %42 %43 %46 = OpCompositeExtract %4 %45 0 OpStore %33 %46 -%47 = OpCompositeExtract %6 %45 1 -OpStore %35 %47 -%48 = OpCompositeExtract %4 %45 2 -OpStore %37 %48 +%47 = OpLoad %4 %33 +%48 = OpExtInst %4 %1 FClamp %47 %7 %3 +OpStore %33 %48 +%49 = OpCompositeExtract %6 %45 1 +OpStore %35 %49 +%50 = OpCompositeExtract %4 %45 2 +OpStore %37 %50 OpReturn OpFunctionEnd \ No newline at end of file diff --git a/tests/snapshots.rs b/tests/snapshots.rs index b34aadf842..1ab06a2be9 100644 --- a/tests/snapshots.rs +++ b/tests/snapshots.rs @@ -62,6 +62,8 @@ struct SpirvOutParameters { #[serde(default)] force_point_size: bool, #[serde(default)] + clamp_frag_depth: bool, + #[serde(default)] separate_entry_points: bool, } @@ -201,6 +203,10 @@ fn write_output_spv( spv::WriterFlags::FORCE_POINT_SIZE, params.spv.force_point_size, ); + flags.set( + spv::WriterFlags::CLAMP_FRAG_DEPTH, + params.spv.clamp_frag_depth, + ); let options = spv::Options { lang_version: (params.spv.version.0, params.spv.version.1), flags,