From ea883d98e2b49a3bab843f29ee526f83bac93019 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 23 Aug 2021 01:37:05 -0400 Subject: [PATCH] [spv-in] track function parameter sampling flags across handle permutation --- src/front/spv/function.rs | 20 +++++--- src/front/spv/image.rs | 11 ++--- src/front/spv/mod.rs | 100 ++++++++++++++++++++++---------------- 3 files changed, 73 insertions(+), 58 deletions(-) diff --git a/src/front/spv/function.rs b/src/front/spv/function.rs index 81a4a5f885..74a00f9b1e 100644 --- a/src/front/spv/function.rs +++ b/src/front/spv/function.rs @@ -1,6 +1,6 @@ use crate::arena::{Arena, Handle}; -use super::{flow::*, Error, FunctionInfo, Instruction, LookupExpression, LookupHelper as _}; +use super::{flow::*, Error, Instruction, LookupExpression, LookupHelper as _}; use crate::front::Emitter; pub type BlockId = u32; @@ -142,10 +142,8 @@ impl> super::Parser { // Read body self.function_call_graph.add_node(fun_id); let mut flow_graph = FlowGraph::new(); - - let mut function_info = FunctionInfo { - parameters_sampling: vec![super::image::SamplingFlags::empty(); fun.arguments.len()], - }; + let mut parameters_sampling = + vec![super::image::SamplingFlags::empty(); fun.arguments.len()]; // Scan the blocks and add them as nodes loop { @@ -166,7 +164,7 @@ impl> super::Parser { &module.types, &module.global_variables, &fun.arguments, - &mut function_info, + &mut parameters_sampling, )?; flow_graph.add_node(node); @@ -200,8 +198,14 @@ impl> super::Parser { // done let fun_handle = module.functions.append(fun, self.span_from_with_op(start)); - self.lookup_function.insert(fun_id, fun_handle); - self.function_info.push(function_info); + self.lookup_function.insert( + fun_id, + super::LookupFunction { + handle: fun_handle, + parameters_sampling, + }, + ); + 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 7426242789..6651a52a81 100644 --- a/src/front/spv/image.rs +++ b/src/front/spv/image.rs @@ -3,7 +3,7 @@ use crate::{ FunctionArgument, }; -use super::{Error, FunctionInfo, LookupExpression, LookupHelper as _}; +use super::{Error, LookupExpression, LookupHelper as _}; #[derive(Clone, Debug)] pub(super) struct LookupSampledImage { @@ -415,7 +415,7 @@ impl> super::Parser { global_arena: &Arena, arguments: &[FunctionArgument], expressions: &mut Arena, - function_info: &mut FunctionInfo, + parameters_sampling: &mut [SamplingFlags], ) -> Result<(), Error> { let start = self.data_offset; let result_type_id = self.next()?; @@ -513,9 +513,7 @@ impl> super::Parser { global_arena[handle].ty } crate::Expression::FunctionArgument(i) => { - let flags = &mut function_info.parameters_sampling[i as usize]; - *flags |= sampling_bit; - + parameters_sampling[i as usize] |= sampling_bit; arguments[i as usize].ty } ref other => return Err(Error::InvalidGlobalVar(other.clone())), @@ -525,8 +523,7 @@ impl> super::Parser { *self.handle_sampling.get_mut(&handle).unwrap() |= sampling_bit } crate::Expression::FunctionArgument(i) => { - let flags = &mut function_info.parameters_sampling[i as usize]; - *flags |= sampling_bit; + parameters_sampling[i as usize] |= sampling_bit; } ref other => return Err(Error::InvalidGlobalVar(other.clone())), } diff --git a/src/front/spv/mod.rs b/src/front/spv/mod.rs index d608ef6049..35646e059b 100644 --- a/src/front/spv/mod.rs +++ b/src/front/spv/mod.rs @@ -296,6 +296,11 @@ struct LookupFunctionType { return_type_id: spirv::Word, } +struct LookupFunction { + handle: Handle, + parameters_sampling: Vec, +} + #[derive(Debug)] struct EntryPoint { stage: crate::ShaderStage, @@ -387,10 +392,6 @@ impl Default for Options { } } -struct FunctionInfo { - parameters_sampling: Vec, -} - pub struct Parser { data: I, data_offset: usize, @@ -413,7 +414,7 @@ pub struct Parser { lookup_load_override: FastHashMap, lookup_sampled_image: FastHashMap, lookup_function_type: FastHashMap, - lookup_function: FastHashMap>, + lookup_function: FastHashMap, lookup_entry_point: FastHashMap, //Note: each `OpFunctionCall` gets a single entry here, indexed by the // dummy `Handle` of the call site. @@ -426,7 +427,6 @@ pub struct Parser { options: Options, index_constants: Vec>, index_constant_expressions: Vec>, - function_info: Vec, } impl> Parser { @@ -459,7 +459,6 @@ impl> Parser { options: options.clone(), index_constants: Vec::new(), index_constant_expressions: Vec::new(), - function_info: Vec::new(), } } @@ -852,7 +851,7 @@ impl> Parser { type_arena: &Arena, global_arena: &Arena, arguments: &[crate::FunctionArgument], - function_info: &mut FunctionInfo, + parmeter_sampling: &mut [image::SamplingFlags], ) -> Result { let mut block = crate::Block::new(); let mut phis = Vec::new(); @@ -1645,7 +1644,7 @@ impl> Parser { global_arena, arguments, expressions, - function_info, + parmeter_sampling, )?; } Op::ImageSampleProjImplicitLod | Op::ImageSampleProjExplicitLod => { @@ -1661,7 +1660,7 @@ impl> Parser { global_arena, arguments, expressions, - function_info, + parmeter_sampling, )?; } Op::ImageSampleDrefImplicitLod | Op::ImageSampleDrefExplicitLod => { @@ -1677,7 +1676,7 @@ impl> Parser { global_arena, arguments, expressions, - function_info, + parmeter_sampling, )?; } Op::ImageSampleProjDrefImplicitLod | Op::ImageSampleProjDrefExplicitLod => { @@ -1693,7 +1692,7 @@ impl> Parser { global_arena, arguments, expressions, - function_info, + parmeter_sampling, )?; } Op::ImageQuerySize => { @@ -2415,7 +2414,7 @@ impl> Parser { &mut self, statements: &mut crate::Block, expressions: &mut Arena, - function: Option>, + fun_parameter_sampling: &mut [image::SamplingFlags], ) -> Result<(), Error> { use crate::Statement as S; let mut i = 0usize; @@ -2423,7 +2422,7 @@ impl> Parser { match statements[i] { S::Emit(_) => {} S::Block(ref mut block) => { - self.patch_statements(block, expressions, function)?; + self.patch_statements(block, expressions, fun_parameter_sampling)?; } S::If { condition: _, @@ -2435,8 +2434,8 @@ impl> Parser { let extracted = mem::take(accept); statements.splice(i + 1..i + 1, extracted); } else { - self.patch_statements(reject, expressions, function)?; - self.patch_statements(accept, expressions, function)?; + self.patch_statements(reject, expressions, fun_parameter_sampling)?; + self.patch_statements(accept, expressions, fun_parameter_sampling)?; } } S::Switch { @@ -2450,17 +2449,21 @@ impl> Parser { statements.splice(i + 1..i + 1, extracted); } else { for case in cases.iter_mut() { - self.patch_statements(&mut case.body, expressions, function)?; + self.patch_statements( + &mut case.body, + expressions, + fun_parameter_sampling, + )?; } - self.patch_statements(default, expressions, function)?; + self.patch_statements(default, expressions, fun_parameter_sampling)?; } } S::Loop { ref mut body, ref mut continuing, } => { - self.patch_statements(body, expressions, function)?; - self.patch_statements(continuing, expressions, function)?; + self.patch_statements(body, expressions, fun_parameter_sampling)?; + self.patch_statements(continuing, expressions, fun_parameter_sampling)?; } S::Break | S::Continue @@ -2476,21 +2479,16 @@ impl> Parser { .. } => { let fun_id = self.deferred_function_calls[callee.index()]; - let handle = *self.lookup_function.lookup(fun_id)?; + let fun_lookup = self.lookup_function.lookup(fun_id)?; + *callee = fun_lookup.handle; // Patch sampling flags - for (i, arg) in arguments.iter().enumerate() { - let callee_info = &self.function_info[handle.index()]; - - let flags = match callee_info.parameters_sampling.get(i) { - Some(&flags) => flags, + for (arg_index, arg) in arguments.iter().enumerate() { + let flags = match fun_lookup.parameters_sampling.get(arg_index) { + Some(&flags) if !flags.is_empty() => flags, _ => continue, }; - if flags.is_empty() { - continue; - } - match expressions[*arg] { crate::Expression::GlobalVariable(handle) => { if let Some(sampling) = self.handle_sampling.get_mut(&handle) { @@ -2498,17 +2496,11 @@ impl> Parser { } } crate::Expression::FunctionArgument(i) => { - if let Some(handle) = function { - let function_info = - self.function_info.get_mut(handle.index()).unwrap(); - function_info.parameters_sampling[i as usize] |= flags; - } + fun_parameter_sampling[i as usize] |= flags; } ref other => return Err(Error::InvalidGlobalVar(other.clone())), } } - - *callee = handle; } } i += 1; @@ -2521,13 +2513,35 @@ impl> Parser { handle: Option>, fun: &mut crate::Function, ) -> Result<(), Error> { + // Note: this search is a bit unfortunate + let (fun_id, mut parameters_sampling) = match handle { + Some(h) => { + let (&fun_id, lookup) = self + .lookup_function + .iter_mut() + .find(|&(_, ref lookup)| lookup.handle == h) + .unwrap(); + (fun_id, mem::take(&mut lookup.parameters_sampling)) + } + None => (0, Vec::new()), + }; + for (_, expr) in fun.expressions.iter_mut() { if let crate::Expression::CallResult(ref mut function) = *expr { let fun_id = self.deferred_function_calls[function.index()]; - *function = *self.lookup_function.lookup(fun_id)?; + *function = self.lookup_function.lookup(fun_id)?.handle; } } - self.patch_statements(&mut fun.body, &mut fun.expressions, handle)?; + + self.patch_statements( + &mut fun.body, + &mut fun.expressions, + &mut parameters_sampling, + )?; + + if let Some(lookup) = self.lookup_function.get_mut(&fun_id) { + lookup.parameters_sampling = parameters_sampling; + } Ok(()) } @@ -2633,13 +2647,13 @@ impl> Parser { // skip all the fake IDs registered for the entry points continue; } - let handle = self.lookup_function.get_mut(&fun_id).unwrap(); + let lookup = self.lookup_function.get_mut(&fun_id).unwrap(); // take out the function from the old array - let fun = mem::take(&mut functions[*handle]); + let fun = mem::take(&mut functions[lookup.handle]); // add it to the newly formed arena, and adjust the lookup - *handle = module + lookup.handle = module .functions - .append(fun, functions.get_span(*handle).clone()); + .append(fun, functions.get_span(lookup.handle).clone()); } } // patch all the functions