diff --git a/src/back/glsl/mod.rs b/src/back/glsl/mod.rs index 4a68df9b0a..ac087e0e60 100644 --- a/src/back/glsl/mod.rs +++ b/src/back/glsl/mod.rs @@ -1983,8 +1983,6 @@ impl<'a, W: Write> Writer<'a, W> { write!(self.out, ")",)?; } } - // TODO: Why is this not implemented ??? - // return Err(Error::Custom("ImageQuery not implemented".to_string())); } // `Unary` is pretty straightforward // "-" - for `Negate` diff --git a/src/front/spv/error.rs b/src/front/spv/error.rs index 688127a271..6817106906 100644 --- a/src/front/spv/error.rs +++ b/src/front/spv/error.rs @@ -73,6 +73,8 @@ pub enum Error { InvalidBinding(spirv::Word), #[error("invalid global var {0:?}")] InvalidGlobalVar(crate::Expression), + #[error("invalid image/sampler expression {0:?}")] + InvalidImageExpression(crate::Expression), #[error("invalid image base type {0:?}")] InvalidImageBaseType(Handle), #[error("invalid image {0:?}")] diff --git a/src/front/spv/function.rs b/src/front/spv/function.rs index f124bd1f78..387b472909 100644 --- a/src/front/spv/function.rs +++ b/src/front/spv/function.rs @@ -193,7 +193,7 @@ impl> super::Parser { // done let fun_handle = module.functions.append(fun); self.lookup_function.insert(fun_id, fun_handle); - self.function_info.insert(fun_handle, function_info); + self.function_info.push(function_info); if let Some(ep) = self.lookup_entry_point.remove(&fun_id) { // create a wrapping function let mut function = crate::Function { diff --git a/src/front/spv/image.rs b/src/front/spv/image.rs index 75736771a1..bd952edaf4 100644 --- a/src/front/spv/image.rs +++ b/src/front/spv/image.rs @@ -31,7 +31,7 @@ impl Arena { match self[handle] { crate::Expression::GlobalVariable(handle) => Ok(global_vars[handle].ty), crate::Expression::FunctionArgument(i) => Ok(arguments[i as usize].ty), - ref other => Err(Error::InvalidGlobalVar(other.clone())), + ref other => Err(Error::InvalidImageExpression(other.clone())), } } } diff --git a/src/front/spv/mod.rs b/src/front/spv/mod.rs index 361be0aa4c..9dad738ad2 100644 --- a/src/front/spv/mod.rs +++ b/src/front/spv/mod.rs @@ -409,7 +409,7 @@ pub struct Parser { options: Options, index_constants: Vec>, index_constant_expressions: Vec>, - function_info: FastHashMap, FunctionInfo>, + function_info: Vec, } impl> Parser { @@ -441,7 +441,7 @@ impl> Parser { options: options.clone(), index_constants: Vec::new(), index_constant_expressions: Vec::new(), - function_info: FastHashMap::default(), + function_info: Vec::new(), } } @@ -2312,7 +2312,7 @@ impl> Parser { // Patch sampling flags for (i, arg) in arguments.iter().enumerate() { - let callee_info = &self.function_info[&handle]; + let callee_info = &self.function_info[handle.index()]; if let Some(flags) = callee_info.parameters_sampling.get(i).and_then(|e| *e) { @@ -2323,7 +2323,7 @@ impl> Parser { crate::Expression::FunctionArgument(i) => { if let Some(handle) = function { let function_info = - self.function_info.get_mut(&handle).unwrap(); + self.function_info.get_mut(handle.index()).unwrap(); let caller_flags = function_info.parameters_sampling [i as usize] .get_or_insert(image::SamplingFlags::empty()); diff --git a/src/valid/analyzer.rs b/src/valid/analyzer.rs index 032c4f37f2..2d68d322f3 100644 --- a/src/valid/analyzer.rs +++ b/src/valid/analyzer.rs @@ -159,7 +159,7 @@ impl ExpressionInfo { } } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] enum GlobalOrArgument { @@ -167,14 +167,22 @@ enum GlobalOrArgument { Argument(u32), } -#[derive(Debug, Clone)] +impl crate::Expression { + fn to_global_or_argument(&self) -> Option { + Some(match *self { + crate::Expression::GlobalVariable(var) => GlobalOrArgument::Global(var), + crate::Expression::FunctionArgument(i) => GlobalOrArgument::Argument(i), + _ => return None, + }) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] -struct ArgumentSampling { - /// Whether this argument is used as an image or a sampler - image: bool, - /// The other global or argument used in the sampling - uses: Vec, +struct Sampling { + image: GlobalOrArgument, + sampler: GlobalOrArgument, } #[derive(Debug)] @@ -199,10 +207,8 @@ pub struct FunctionInfo { /// /// Each item corresponds to an expression in the function. expressions: Box<[ExpressionInfo]>, - /// Vector with information of wether or not a functin argument is used for sampling - /// - /// Each item corresponds to a function argument - argument_sampling: Box<[Option]>, + /// HashSet with information about sampling realized by the function + sampling: crate::FastHashSet, } impl FunctionInfo { @@ -304,78 +310,39 @@ impl FunctionInfo { for key in info.sampling_set.iter() { self.sampling_set.insert(key.clone()); } - for (i, arg_sampling) in info - .argument_sampling - .iter() - .enumerate() - .filter_map(|(i, s)| Some((i, s.as_ref()?))) - { - let handle = arguments[i]; - let arg_storage = match expression_arena[handle] { - crate::Expression::GlobalVariable(var) => GlobalOrArgument::Global(var), - crate::Expression::FunctionArgument(i) => GlobalOrArgument::Argument(i), - _ => { - return Err(FunctionError::Expression { - handle, - error: ExpressionError::ExpectedGlobalVariable, - }) + for sampling in info.sampling.iter() { + let image_storage = match sampling.image { + GlobalOrArgument::Global(var) => GlobalOrArgument::Global(var), + GlobalOrArgument::Argument(i) => { + let handle = arguments[i as usize]; + expression_arena[handle].to_global_or_argument().ok_or( + FunctionError::Expression { + handle, + error: ExpressionError::ExpectedGlobalOrArgument, + }, + )? } }; - for other in arg_sampling.uses.iter() { - let other_storage = match *other { - GlobalOrArgument::Global(var) => GlobalOrArgument::Global(var), - GlobalOrArgument::Argument(i) => { - let other_handle = arguments[i as usize]; - match expression_arena[other_handle] { - crate::Expression::GlobalVariable(var) => GlobalOrArgument::Global(var), - crate::Expression::FunctionArgument(i) => GlobalOrArgument::Argument(i), - _ => { - return Err(FunctionError::Expression { - handle, - error: ExpressionError::ExpectedGlobalVariable, - }) - } - } - } - }; + let sampler_storage = match sampling.sampler { + GlobalOrArgument::Global(var) => GlobalOrArgument::Global(var), + GlobalOrArgument::Argument(i) => { + let handle = arguments[i as usize]; + expression_arena[handle].to_global_or_argument().ok_or( + FunctionError::Expression { + handle, + error: ExpressionError::ExpectedGlobalOrArgument, + }, + )? + } + }; - match (arg_storage, other_storage) { - (GlobalOrArgument::Global(arg), GlobalOrArgument::Global(other)) => { - if arg_sampling.image { - self.sampling_set.insert(SamplingKey { - image: arg, - sampler: other, - }); - } else { - self.sampling_set.insert(SamplingKey { - image: other, - sampler: arg, - }); - } - } - (GlobalOrArgument::Argument(i), _) => { - let sampling = - self.argument_sampling[i as usize].get_or_insert_with(|| { - ArgumentSampling { - image: arg_sampling.image, - uses: Vec::with_capacity(1), - } - }); - - sampling.uses.push(other_storage) - } - (_, GlobalOrArgument::Argument(i)) => { - let sampling = - self.argument_sampling[i as usize].get_or_insert_with(|| { - ArgumentSampling { - image: !arg_sampling.image, - uses: Vec::with_capacity(1), - } - }); - - sampling.uses.push(arg_storage) - } + match (image_storage, sampler_storage) { + (GlobalOrArgument::Global(image), GlobalOrArgument::Global(sampler)) => { + self.sampling_set.insert(SamplingKey { image, sampler }); + } + (image, sampler) => { + self.sampling.insert(Sampling { image, sampler }); } } } @@ -499,42 +466,28 @@ impl FunctionInfo { level, depth_ref, } => { - let image_storage = match expression_arena[image] { - crate::Expression::GlobalVariable(var) => GlobalOrArgument::Global(var), - crate::Expression::FunctionArgument(i) => GlobalOrArgument::Argument(i), - _ => return Err(ExpressionError::ExpectedGlobalVariable), - }; - let sampler_storage = match expression_arena[sampler] { - crate::Expression::GlobalVariable(var) => GlobalOrArgument::Global(var), - crate::Expression::FunctionArgument(i) => GlobalOrArgument::Argument(i), - _ => return Err(ExpressionError::ExpectedGlobalVariable), - }; + let image_storage = expression_arena[image] + .to_global_or_argument() + .ok_or(ExpressionError::ExpectedGlobalOrArgument)?; + let sampler_storage = expression_arena[sampler] + .to_global_or_argument() + .ok_or(ExpressionError::ExpectedGlobalOrArgument)?; match (image_storage, sampler_storage) { (GlobalOrArgument::Global(image), GlobalOrArgument::Global(sampler)) => { self.sampling_set.insert(SamplingKey { image, sampler }); } - (GlobalOrArgument::Argument(i), _) => { - let sampling = - self.argument_sampling[i as usize].get_or_insert_with(|| { - ArgumentSampling { - image: true, - uses: Vec::with_capacity(1), - } - }); - - sampling.uses.push(sampler_storage) + (GlobalOrArgument::Argument(_), _) => { + self.sampling.insert(Sampling { + image: image_storage, + sampler: sampler_storage, + }); } - (_, GlobalOrArgument::Argument(i)) => { - let sampling = - self.argument_sampling[i as usize].get_or_insert_with(|| { - ArgumentSampling { - image: false, - uses: Vec::with_capacity(1), - } - }); - - sampling.uses.push(image_storage) + (_, GlobalOrArgument::Argument(_)) => { + self.sampling.insert(Sampling { + image: image_storage, + sampler: sampler_storage, + }); } } @@ -864,7 +817,7 @@ impl ModuleInfo { sampling_set: crate::FastHashSet::default(), global_uses: vec![GlobalUse::empty(); module.global_variables.len()].into_boxed_slice(), expressions: vec![ExpressionInfo::new(); fun.expressions.len()].into_boxed_slice(), - argument_sampling: vec![None; fun.arguments.len()].into_boxed_slice(), + sampling: crate::FastHashSet::default(), }; let resolve_context = ResolveContext { constants: &module.constants, @@ -969,7 +922,7 @@ fn uniform_control_flow() { sampling_set: crate::FastHashSet::default(), global_uses: vec![GlobalUse::empty(); global_var_arena.len()].into_boxed_slice(), expressions: vec![ExpressionInfo::new(); expressions.len()].into_boxed_slice(), - argument_sampling: vec![None; 0].into_boxed_slice(), + sampling: crate::FastHashSet::default(), }; let resolve_context = ResolveContext { constants: &constant_arena, diff --git a/src/valid/expression.rs b/src/valid/expression.rs index 409ca82eb0..d1bb45f7bf 100644 --- a/src/valid/expression.rs +++ b/src/valid/expression.rs @@ -61,6 +61,8 @@ pub enum ExpressionError { Type(#[from] ResolveError), #[error("Not a global variable")] ExpectedGlobalVariable, + #[error("Not a global variable or a function argument")] + ExpectedGlobalOrArgument, #[error("Calling an undeclared function {0:?}")] CallToUndeclaredFunction(Handle), #[error("Needs to be an image instead of {0:?}")] diff --git a/tests/out/analysis/collatz.info.ron b/tests/out/analysis/collatz.info.ron index e46776e9de..f3b229d32c 100644 --- a/tests/out/analysis/collatz.info.ron +++ b/tests/out/analysis/collatz.info.ron @@ -336,9 +336,7 @@ ty: Handle(1), ), ], - argument_sampling: [ - None, - ], + sampling: [], ), ], entry_points: [ @@ -495,9 +493,7 @@ ty: Handle(1), ), ], - argument_sampling: [ - None, - ], + sampling: [], ), ], ) \ No newline at end of file diff --git a/tests/out/analysis/shadow.info.ron b/tests/out/analysis/shadow.info.ron index abaef43360..c084ca0574 100644 --- a/tests/out/analysis/shadow.info.ron +++ b/tests/out/analysis/shadow.info.ron @@ -1060,10 +1060,7 @@ )), ), ], - argument_sampling: [ - None, - None, - ], + sampling: [], ), ( flags: ( @@ -2752,7 +2749,7 @@ ty: Handle(4), ), ], - argument_sampling: [], + sampling: [], ), ], entry_points: [ @@ -2876,10 +2873,7 @@ ty: Handle(4), ), ], - argument_sampling: [ - None, - None, - ], + sampling: [], ), ], ) \ No newline at end of file