diff --git a/src/back/spv/helpers.rs b/src/back/spv/helpers.rs index 35b1389594..72be7f7b58 100644 --- a/src/back/spv/helpers.rs +++ b/src/back/spv/helpers.rs @@ -1,3 +1,4 @@ +use crate::{Arena, Handle}; use spirv::Word; pub(super) fn bytes_to_words(bytes: &[u8]) -> Vec { @@ -30,3 +31,20 @@ pub(super) fn map_storage_class(class: crate::StorageClass) -> spirv::StorageCla crate::StorageClass::PushConstant => spirv::StorageClass::PushConstant, } } + +pub(super) fn contains_builtin( + binding: Option<&crate::Binding>, + ty: Handle, + arena: &Arena, + built_in: crate::BuiltIn, +) -> bool { + if let Some(&crate::Binding::BuiltIn(bi)) = binding { + bi == built_in + } else if let crate::TypeInner::Struct { ref members, .. } = arena[ty].inner { + members + .iter() + .any(|member| contains_builtin(member.binding.as_ref(), member.ty, arena, built_in)) + } else { + false // unreachable + } +} diff --git a/src/back/spv/writer.rs b/src/back/spv/writer.rs index 775582c869..61a15260c8 100644 --- a/src/back/spv/writer.rs +++ b/src/back/spv/writer.rs @@ -1,5 +1,6 @@ use super::{ - helpers::map_storage_class, Instruction, LogicalLayout, Options, PhysicalLayout, WriterFlags, + helpers::{contains_builtin, map_storage_class}, + Instruction, LogicalLayout, Options, PhysicalLayout, WriterFlags, }; use crate::{ arena::{Arena, Handle}, @@ -652,6 +653,17 @@ impl Writer { Ok(function_id) } + fn write_execution_mode( + &mut self, + function_id: Word, + mode: spirv::ExecutionMode, + ) -> Result<(), Error> { + self.check(mode.required_capabilities())?; + Instruction::execution_mode(function_id, mode, &[]) + .to_words(&mut self.logical_layout.execution_modes); + Ok(()) + } + // TODO Move to instructions module fn write_entry_point( &mut self, @@ -670,10 +682,20 @@ impl Writer { let exec_model = match entry_point.stage { crate::ShaderStage::Vertex => spirv::ExecutionModel::Vertex, crate::ShaderStage::Fragment => { - let execution_mode = spirv::ExecutionMode::OriginUpperLeft; - self.check(execution_mode.required_capabilities())?; - Instruction::execution_mode(function_id, execution_mode, &[]) - .to_words(&mut self.logical_layout.execution_modes); + self.write_execution_mode(function_id, spirv::ExecutionMode::OriginUpperLeft)?; + if let Some(ref result) = entry_point.function.result { + if contains_builtin( + result.binding.as_ref(), + result.ty, + &ir_module.types, + crate::BuiltIn::FragDepth, + ) { + self.write_execution_mode( + function_id, + spirv::ExecutionMode::DepthReplacing, + )?; + } + } spirv::ExecutionModel::Fragment } crate::ShaderStage::Compute => {