[spv-in] track function parameter sampling flags across handle permutation

This commit is contained in:
Dzmitry Malyshau
2021-08-23 01:37:05 -04:00
committed by Dzmitry Malyshau
parent 901e2c0694
commit ea883d98e2
3 changed files with 73 additions and 58 deletions

View File

@@ -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<I: Iterator<Item = u32>> super::Parser<I> {
// 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<I: Iterator<Item = u32>> super::Parser<I> {
&module.types,
&module.global_variables,
&fun.arguments,
&mut function_info,
&mut parameters_sampling,
)?;
flow_graph.add_node(node);
@@ -200,8 +198,14 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
// 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 {

View File

@@ -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<I: Iterator<Item = u32>> super::Parser<I> {
global_arena: &Arena<crate::GlobalVariable>,
arguments: &[FunctionArgument],
expressions: &mut Arena<crate::Expression>,
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<I: Iterator<Item = u32>> super::Parser<I> {
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<I: Iterator<Item = u32>> super::Parser<I> {
*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())),
}

View File

@@ -296,6 +296,11 @@ struct LookupFunctionType {
return_type_id: spirv::Word,
}
struct LookupFunction {
handle: Handle<crate::Function>,
parameters_sampling: Vec<image::SamplingFlags>,
}
#[derive(Debug)]
struct EntryPoint {
stage: crate::ShaderStage,
@@ -387,10 +392,6 @@ impl Default for Options {
}
}
struct FunctionInfo {
parameters_sampling: Vec<image::SamplingFlags>,
}
pub struct Parser<I> {
data: I,
data_offset: usize,
@@ -413,7 +414,7 @@ pub struct Parser<I> {
lookup_load_override: FastHashMap<spirv::Word, LookupLoadOverride>,
lookup_sampled_image: FastHashMap<spirv::Word, image::LookupSampledImage>,
lookup_function_type: FastHashMap<spirv::Word, LookupFunctionType>,
lookup_function: FastHashMap<spirv::Word, Handle<crate::Function>>,
lookup_function: FastHashMap<spirv::Word, LookupFunction>,
lookup_entry_point: FastHashMap<spirv::Word, EntryPoint>,
//Note: each `OpFunctionCall` gets a single entry here, indexed by the
// dummy `Handle<crate::Function>` of the call site.
@@ -426,7 +427,6 @@ pub struct Parser<I> {
options: Options,
index_constants: Vec<Handle<crate::Constant>>,
index_constant_expressions: Vec<Handle<crate::Expression>>,
function_info: Vec<FunctionInfo>,
}
impl<I: Iterator<Item = u32>> Parser<I> {
@@ -459,7 +459,6 @@ impl<I: Iterator<Item = u32>> Parser<I> {
options: options.clone(),
index_constants: Vec::new(),
index_constant_expressions: Vec::new(),
function_info: Vec::new(),
}
}
@@ -852,7 +851,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
type_arena: &Arena<crate::Type>,
global_arena: &Arena<crate::GlobalVariable>,
arguments: &[crate::FunctionArgument],
function_info: &mut FunctionInfo,
parmeter_sampling: &mut [image::SamplingFlags],
) -> Result<ControlFlowNode, Error> {
let mut block = crate::Block::new();
let mut phis = Vec::new();
@@ -1645,7 +1644,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
global_arena,
arguments,
expressions,
function_info,
parmeter_sampling,
)?;
}
Op::ImageSampleProjImplicitLod | Op::ImageSampleProjExplicitLod => {
@@ -1661,7 +1660,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
global_arena,
arguments,
expressions,
function_info,
parmeter_sampling,
)?;
}
Op::ImageSampleDrefImplicitLod | Op::ImageSampleDrefExplicitLod => {
@@ -1677,7 +1676,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
global_arena,
arguments,
expressions,
function_info,
parmeter_sampling,
)?;
}
Op::ImageSampleProjDrefImplicitLod | Op::ImageSampleProjDrefExplicitLod => {
@@ -1693,7 +1692,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
global_arena,
arguments,
expressions,
function_info,
parmeter_sampling,
)?;
}
Op::ImageQuerySize => {
@@ -2415,7 +2414,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
&mut self,
statements: &mut crate::Block,
expressions: &mut Arena<crate::Expression>,
function: Option<Handle<crate::Function>>,
fun_parameter_sampling: &mut [image::SamplingFlags],
) -> Result<(), Error> {
use crate::Statement as S;
let mut i = 0usize;
@@ -2423,7 +2422,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
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<I: Iterator<Item = u32>> Parser<I> {
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<I: Iterator<Item = u32>> Parser<I> {
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<I: Iterator<Item = u32>> Parser<I> {
..
} => {
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<I: Iterator<Item = u32>> Parser<I> {
}
}
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<I: Iterator<Item = u32>> Parser<I> {
handle: Option<Handle<crate::Function>>,
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<I: Iterator<Item = u32>> Parser<I> {
// 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