diff --git a/src/back/mod.rs b/src/back/mod.rs index 09a18303fa..51243a4045 100644 --- a/src/back/mod.rs +++ b/src/back/mod.rs @@ -175,3 +175,13 @@ fn vector_size_str(size: crate::VectorSize) -> &'static str { crate::VectorSize::Quad => "4", } } + +impl crate::TypeInner { + #[allow(unused)] + fn is_handle(&self) -> bool { + match *self { + crate::TypeInner::Image { .. } | crate::TypeInner::Sampler { .. } => true, + _ => false, + } + } +} diff --git a/src/back/spv/block.rs b/src/back/spv/block.rs index 90b8c7abe8..7de2359360 100644 --- a/src/back/spv/block.rs +++ b/src/back/spv/block.rs @@ -703,7 +703,7 @@ impl<'w> BlockContext<'w> { array_index, index, } => { - let image_id = self.get_image_id(block, image)?; + let image_id = self.get_image_id(image); let coordinate_id = self.write_texture_coordinates(coordinate, array_index, block)?; @@ -773,7 +773,7 @@ impl<'w> BlockContext<'w> { } => { use super::instructions::SampleLod; // image - let image_id = self.get_image_id(block, image)?; + let image_id = self.get_image_id(image); let image_type = self.fun_info[image].ty.handle().unwrap(); // Vulkan doesn't know about our `Depth` class, and it returns `vec4`, // so we need to grab the first component out of it. @@ -800,7 +800,7 @@ impl<'w> BlockContext<'w> { let sampled_image_type_id = self.get_type_id(LookupType::Local(LocalType::SampledImage { image_type_id }))?; - let sampler_id = self.get_image_id(block, sampler)?; + let sampler_id = self.get_image_id(sampler); let coordinate_id = self.write_texture_coordinates(coordinate, array_index, block)?; @@ -960,7 +960,7 @@ impl<'w> BlockContext<'w> { crate::Expression::ImageQuery { image, query } => { use crate::{ImageClass as Ic, ImageDimension as Id, ImageQuery as Iq}; - let image_id = self.get_image_id(block, image)?; + let image_id = self.get_image_id(image); let image_type = self.fun_info[image].ty.handle().unwrap(); let (dim, arrayed, class) = match self.ir_module.types[image_type].inner { crate::TypeInner::Image { @@ -1200,8 +1200,7 @@ impl<'w> BlockContext<'w> { break local_var.id; } crate::Expression::FunctionArgument(index) => { - let id = self.function.parameters[index as usize].result_id.unwrap(); - break id; + break self.function.parameter_id(index); } ref other => unimplemented!("Unexpected pointer expression {:?}", other), } @@ -1233,32 +1232,25 @@ impl<'w> BlockContext<'w> { Ok(pointer) } - fn get_image_id( - &mut self, - block: &mut Block, - expr_handle: Handle, - ) -> Result { - Ok(match self.ir_function.expressions[expr_handle] { + fn get_image_id(&mut self, expr_handle: Handle) -> Word { + let id = match self.ir_function.expressions[expr_handle] { crate::Expression::GlobalVariable(handle) => { - let id = self.writer.global_variables[handle.index()].handle_id; - if id == 0 { - unreachable!("Global variable {:?} doesn't have a handle ID", handle); - } - id + self.writer.global_variables[handle.index()].handle_id } crate::Expression::FunctionArgument(i) => { - let result_type_id = self.get_type_id(LookupType::Handle( - self.ir_function.arguments[i as usize].ty, - ))?; - let pointer_id = self.function.parameter_id(i); - let id = self.gen_id(); - block - .body - .push(Instruction::load(result_type_id, id, pointer_id, None)); - id + self.function.parameters[i as usize].handle_id } - ref other => unreachable!("Unexpected global expression {:?}", other), - }) + ref other => unreachable!("Unexpected image expression {:?}", other), + }; + + if id == 0 { + unreachable!( + "Image expression {:?} doesn't have a handle ID", + expr_handle + ); + } + + id } pub(super) fn write_block( @@ -1531,7 +1523,7 @@ impl<'w> BlockContext<'w> { array_index, value, } => { - let image_id = self.get_image_id(&mut block, image)?; + let image_id = self.get_image_id(image); let coordinate_id = self.write_texture_coordinates(coordinate, array_index, &mut block)?; let value_id = self.cached(value); diff --git a/src/back/spv/mod.rs b/src/back/spv/mod.rs index 98cdbcf0c7..952fb72041 100644 --- a/src/back/spv/mod.rs +++ b/src/back/spv/mod.rs @@ -125,7 +125,7 @@ struct EntryPointContext { #[derive(Default)] struct Function { signature: Option, - parameters: Vec, + parameters: Vec, variables: crate::FastHashMap, LocalVariable>, blocks: Vec, entry_point_context: Option, @@ -143,7 +143,10 @@ impl Function { fn parameter_id(&self, index: u32) -> Word { match self.entry_point_context { Some(ref context) => context.argument_ids[index as usize], - None => self.parameters[index as usize].result_id.unwrap(), + None => self.parameters[index as usize] + .instruction + .result_id + .unwrap(), } } } @@ -311,6 +314,12 @@ struct GlobalVariable { handle_id: Word, } +struct FunctionArgument { + /// Actual instruction of the argument. + instruction: Instruction, + handle_id: Word, +} + /// General information needed to emit SPIR-V for Naga statements. struct BlockContext<'w> { /// The writer handling the module to which this code belongs. diff --git a/src/back/spv/writer.rs b/src/back/spv/writer.rs index e53ec61647..89e7146590 100644 --- a/src/back/spv/writer.rs +++ b/src/back/spv/writer.rs @@ -1,9 +1,9 @@ use super::{ helpers::{contains_builtin, map_storage_class}, make_local, Block, BlockContext, CachedExpressions, EntryPointContext, Error, Function, - GlobalVariable, IdGenerator, Instruction, LocalType, LocalVariable, LogicalLayout, - LookupFunctionType, LookupType, LoopContext, Options, PhysicalLayout, ResultMember, Writer, - WriterFlags, BITS_PER_BYTE, + FunctionArgument, GlobalVariable, IdGenerator, Instruction, LocalType, LocalVariable, + LogicalLayout, LookupFunctionType, LookupType, LoopContext, Options, PhysicalLayout, + ResultMember, Writer, WriterFlags, BITS_PER_BYTE, }; use crate::{ arena::{Arena, Handle}, @@ -25,8 +25,8 @@ fn map_dim(dim: crate::ImageDimension) -> spirv::Dim { impl Function { fn to_words(&self, sink: &mut impl Extend) { self.signature.as_ref().unwrap().to_words(sink); - for instruction in self.parameters.iter() { - instruction.to_words(sink); + for argument in self.parameters.iter() { + argument.instruction.to_words(sink); } for (index, block) in self.blocks.iter().enumerate() { Instruction::label(block.label_id).to_words(sink); @@ -269,10 +269,7 @@ impl Writer { let mut parameter_type_ids = Vec::with_capacity(ir_function.arguments.len()); for argument in ir_function.arguments.iter() { let class = spirv::StorageClass::Input; - let handle_ty = match ir_module.types[argument.ty].inner { - crate::TypeInner::Image { .. } | crate::TypeInner::Sampler { .. } => true, - _ => false, - }; + let handle_ty = ir_module.types[argument.ty].inner.is_handle(); let argument_type_id = match handle_ty { true => self.get_pointer_id( &ir_module.types, @@ -321,9 +318,23 @@ impl Writer { }; ep_context.argument_ids.push(id); } else { - let id = self.id_gen.next(); - let instruction = Instruction::function_parameter(argument_type_id, id); - function.parameters.push(instruction); + let argument_id = self.id_gen.next(); + let instruction = Instruction::function_parameter(argument_type_id, argument_id); + function.parameters.push(FunctionArgument { + instruction, + handle_id: if handle_ty { + let id = self.id_gen.next(); + prelude.body.push(Instruction::load( + self.get_type_id(LookupType::Handle(argument.ty))?, + id, + argument_id, + None, + )); + id + } else { + 0 + }, + }); parameter_type_ids.push(argument_type_id); }; } diff --git a/tests/out/spv/texture-arg.spvasm b/tests/out/spv/texture-arg.spvasm index 80a87f76f1..12fd6965c3 100644 --- a/tests/out/spv/texture-arg.spvasm +++ b/tests/out/spv/texture-arg.spvasm @@ -10,7 +10,7 @@ OpExecutionMode %28 OriginUpperLeft OpSource GLSL 450 OpName %9 "Texture" OpName %11 "Sampler" -OpName %16 "test" +OpName %18 "test" OpName %28 "main" OpDecorate %9 DescriptorSet 0 OpDecorate %9 Binding 0 @@ -28,22 +28,22 @@ OpDecorate %26 Location 0 %9 = OpVariable %10 UniformConstant %12 = OpTypePointer UniformConstant %6 %11 = OpVariable %12 UniformConstant -%17 = OpTypeFunction %7 %10 %12 -%21 = OpTypeSampledImage %5 +%19 = OpTypeFunction %7 %10 %12 +%22 = OpTypeSampledImage %5 %27 = OpTypePointer Output %7 %26 = OpVariable %27 Output %29 = OpTypeFunction %2 -%16 = OpFunction %7 None %17 +%18 = OpFunction %7 None %19 %14 = OpFunctionParameter %10 -%15 = OpFunctionParameter %12 +%16 = OpFunctionParameter %12 %13 = OpLabel -OpBranch %18 -%18 = OpLabel -%19 = OpCompositeConstruct %8 %3 %3 -%20 = OpLoad %5 %14 -%22 = OpLoad %6 %15 -%23 = OpSampledImage %21 %20 %22 -%24 = OpImageSampleImplicitLod %7 %23 %19 +%15 = OpLoad %5 %14 +%17 = OpLoad %6 %16 +OpBranch %20 +%20 = OpLabel +%21 = OpCompositeConstruct %8 %3 %3 +%23 = OpSampledImage %22 %15 %17 +%24 = OpImageSampleImplicitLod %7 %23 %21 OpReturnValue %24 OpFunctionEnd %28 = OpFunction %2 None %29 @@ -52,7 +52,7 @@ OpFunctionEnd %31 = OpLoad %6 %11 OpBranch %32 %32 = OpLabel -%33 = OpFunctionCall %7 %16 %9 %11 +%33 = OpFunctionCall %7 %18 %9 %11 OpStore %26 %33 OpReturn OpFunctionEnd \ No newline at end of file