mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-27 01:03:41 +00:00
Remove the call graph processor
Uses the GlobalUse in glsl-out to check for function availability
This commit is contained in:
parent
9f113bdd95
commit
19e7f456c4
@ -249,15 +249,13 @@ fn main() {
|
||||
let name = args.get(4).map_or("main", |p| p.as_str()).to_string();
|
||||
let options = glsl::Options {
|
||||
version,
|
||||
entry_point: (
|
||||
match stage {
|
||||
"vert" => naga::ShaderStage::Vertex,
|
||||
"frag" => naga::ShaderStage::Fragment,
|
||||
"comp" => naga::ShaderStage::Compute,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
name,
|
||||
),
|
||||
shader_stage: match stage {
|
||||
"vert" => naga::ShaderStage::Vertex,
|
||||
"frag" => naga::ShaderStage::Fragment,
|
||||
"comp" => naga::ShaderStage::Compute,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
entry_point: name,
|
||||
};
|
||||
|
||||
let file = fs::OpenOptions::new()
|
||||
|
@ -175,8 +175,6 @@ impl<'a, W> Writer<'a, W> {
|
||||
/// If the version doesn't support any of the needed [`Features`](Features) a
|
||||
/// [`Error::MissingFeatures`](super::Error::MissingFeatures) will be returned
|
||||
pub(super) fn collect_required_features(&mut self) -> BackendResult {
|
||||
let stage = self.options.entry_point.0;
|
||||
|
||||
if let Some(depth_test) = self.entry_point.early_depth_test {
|
||||
self.features.request(Features::IMAGE_LOAD_STORE);
|
||||
|
||||
@ -185,7 +183,7 @@ impl<'a, W> Writer<'a, W> {
|
||||
}
|
||||
}
|
||||
|
||||
if let ShaderStage::Compute = stage {
|
||||
if let ShaderStage::Compute = self.options.shader_stage {
|
||||
self.features.request(Features::COMPUTE_SHADER)
|
||||
}
|
||||
|
||||
|
@ -44,10 +44,7 @@
|
||||
pub use features::Features;
|
||||
|
||||
use crate::{
|
||||
proc::{
|
||||
analyzer::Analysis, CallGraph, CallGraphBuilder, NameKey, Namer, ResolveContext,
|
||||
ResolveError, Typifier,
|
||||
},
|
||||
proc::{analyzer::Analysis, NameKey, Namer, ResolveContext, ResolveError, Typifier},
|
||||
Arena, ArraySize, BinaryOperator, Binding, BuiltIn, Bytes, ConservativeDepth, Constant,
|
||||
ConstantInner, DerivativeAxis, Expression, FastHashMap, Function, GlobalVariable, Handle,
|
||||
ImageClass, Interpolation, LocalVariable, Module, RelationalFunction, ScalarKind, ScalarValue,
|
||||
@ -129,11 +126,13 @@ impl fmt::Display for Version {
|
||||
pub struct Options {
|
||||
/// The glsl version to be used
|
||||
pub version: Version,
|
||||
/// The name and stage of the entry point
|
||||
/// The stage of the entry point
|
||||
pub shader_stage: ShaderStage,
|
||||
/// The name of the entry point
|
||||
///
|
||||
/// If no entry point that matches is found a error will be thrown while creating a new instance
|
||||
/// of [`Writer`](struct.Writer.html)
|
||||
pub entry_point: (ShaderStage, String),
|
||||
pub entry_point: String,
|
||||
}
|
||||
|
||||
/// Structure that connects a texture to a sampler or not
|
||||
@ -275,8 +274,6 @@ pub struct Writer<'a, W> {
|
||||
entry_point: &'a crate::EntryPoint,
|
||||
/// The index of the selected entry point
|
||||
entry_point_idx: crate::proc::EntryPointIndex,
|
||||
/// The current entry point call_graph (doesn't contain the entry point)
|
||||
call_graph: CallGraph,
|
||||
/// Used to generate a unique number for blocks
|
||||
block_id: IdGenerator,
|
||||
}
|
||||
@ -301,12 +298,12 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
}
|
||||
|
||||
// Try to find the entry point and corresponding index
|
||||
let (ep_idx, ep) = module
|
||||
let (ep_idx, (_, ep)) = module
|
||||
.entry_points
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find_map(|(i, (key, entry_point))| {
|
||||
Some((i as u16, entry_point)).filter(|_| &options.entry_point == key)
|
||||
.find(|(_, ((stage, name), _))| {
|
||||
options.shader_stage == *stage && &options.entry_point == name
|
||||
})
|
||||
.ok_or(Error::EntryPointNotFound)?;
|
||||
|
||||
@ -314,12 +311,6 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
let mut names = FastHashMap::default();
|
||||
Namer::default().reset(module, keywords::RESERVED_KEYWORDS, &mut names);
|
||||
|
||||
// Generate a call graph for the entry point
|
||||
let call_graph = CallGraphBuilder {
|
||||
functions: &module.functions,
|
||||
}
|
||||
.process(&ep.function);
|
||||
|
||||
// Build the instance
|
||||
let mut this = Self {
|
||||
module,
|
||||
@ -330,8 +321,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
features: FeaturesManager::new(),
|
||||
names,
|
||||
entry_point: ep,
|
||||
entry_point_idx: ep_idx,
|
||||
call_graph,
|
||||
entry_point_idx: ep_idx as u16,
|
||||
|
||||
block_id: IdGenerator::default(),
|
||||
};
|
||||
@ -407,7 +397,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
|
||||
let ep_info = self
|
||||
.analysis
|
||||
.get_entry_point(self.options.entry_point.0, &self.options.entry_point.1);
|
||||
.get_entry_point(self.options.shader_stage, &self.options.entry_point);
|
||||
|
||||
// Write the globals
|
||||
//
|
||||
@ -475,25 +465,19 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
_ => self.write_global(handle, global)?,
|
||||
}
|
||||
}
|
||||
// Write all regular functions
|
||||
for (handle, function) in self.module.functions.iter() {
|
||||
// Check that the function doesn't use globals that aren't supported
|
||||
// by the current entry point
|
||||
if !ep_info.dominates_global_use(&self.analysis[handle]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sort the graph topologically so that functions calls are valid
|
||||
// It's impossible for this to panic because the IR forbids cycles
|
||||
let functions = petgraph::algo::toposort(&self.call_graph, None).unwrap();
|
||||
|
||||
// Write all regular functions that are in the call graph this is important
|
||||
// because other functions might require for example globals that weren't written
|
||||
for node in functions {
|
||||
// We do this inside the loop instead of using `map` to satisfy the borrow checker
|
||||
let handle = self.call_graph[node];
|
||||
// We also `clone` to satisfy the borrow checker
|
||||
let name = self.names[&NameKey::Function(handle)].clone();
|
||||
|
||||
// Write the function
|
||||
self.write_function(
|
||||
FunctionType::Function(handle),
|
||||
&self.module.functions[handle],
|
||||
name,
|
||||
)?;
|
||||
self.write_function(FunctionType::Function(handle), function, name)?;
|
||||
|
||||
writeln!(self.out)?;
|
||||
}
|
||||
@ -692,7 +676,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
//
|
||||
// TODO: Should this throw an error?
|
||||
if let Some(interpolation) = global.interpolation {
|
||||
match (self.options.entry_point.0, global.class) {
|
||||
match (self.options.shader_stage, global.class) {
|
||||
(ShaderStage::Fragment, StorageClass::Input)
|
||||
| (ShaderStage::Vertex, StorageClass::Output) => {
|
||||
write!(self.out, "{} ", glsl_interpolation(interpolation)?)?;
|
||||
@ -731,7 +715,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
format!(
|
||||
"_location_{}{}",
|
||||
location,
|
||||
match (self.options.entry_point.0, global.class) {
|
||||
match (self.options.shader_stage, global.class) {
|
||||
(ShaderStage::Fragment, StorageClass::Input) => "_vs",
|
||||
(ShaderStage::Vertex, StorageClass::Output) => "_vs",
|
||||
_ => "",
|
||||
@ -1755,7 +1739,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
use std::collections::hash_map::Entry;
|
||||
let info = self
|
||||
.analysis
|
||||
.get_entry_point(self.options.entry_point.0, &self.options.entry_point.1);
|
||||
.get_entry_point(self.options.shader_stage, &self.options.entry_point);
|
||||
let mut mappings = FastHashMap::default();
|
||||
|
||||
for sampling in info.sampling_set.iter() {
|
||||
|
@ -99,6 +99,16 @@ impl FunctionInfo {
|
||||
pub fn expression_count(&self) -> usize {
|
||||
self.expressions.len()
|
||||
}
|
||||
pub fn dominates_global_use(&self, other: &Self) -> bool {
|
||||
for (self_global_uses, other_global_uses) in
|
||||
self.global_uses.iter().zip(other.global_uses.iter())
|
||||
{
|
||||
if !self_global_uses.contains(*other_global_uses) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<Handle<crate::GlobalVariable>> for FunctionInfo {
|
||||
|
@ -1,85 +0,0 @@
|
||||
use crate::{
|
||||
arena::{Arena, Handle},
|
||||
proc::{Interface, Visitor},
|
||||
Function,
|
||||
};
|
||||
use bit_set::BitSet;
|
||||
use petgraph::{
|
||||
graph::{DefaultIx, NodeIndex},
|
||||
Graph,
|
||||
};
|
||||
|
||||
pub type CallGraph = Graph<Handle<Function>, ()>;
|
||||
|
||||
pub struct CallGraphBuilder<'a> {
|
||||
pub functions: &'a Arena<Function>,
|
||||
}
|
||||
|
||||
impl<'a> CallGraphBuilder<'a> {
|
||||
pub fn process(&self, func: &Function) -> CallGraph {
|
||||
let mut graph = Graph::new();
|
||||
let mut children = Vec::new();
|
||||
let mut mask = BitSet::with_capacity(func.expressions.len());
|
||||
|
||||
let visitor = CallGraphVisitor {
|
||||
children: &mut children,
|
||||
};
|
||||
|
||||
let mut interface = Interface {
|
||||
expressions: &func.expressions,
|
||||
local_variables: &func.local_variables,
|
||||
visitor,
|
||||
mask: &mut mask,
|
||||
};
|
||||
|
||||
interface.traverse(&func.body);
|
||||
|
||||
for handle in children {
|
||||
let id = graph.add_node(handle);
|
||||
self.collect(handle, id, &mut graph, &mut mask);
|
||||
}
|
||||
|
||||
graph
|
||||
}
|
||||
|
||||
fn collect(
|
||||
&self,
|
||||
handle: Handle<Function>,
|
||||
id: NodeIndex<DefaultIx>,
|
||||
graph: &mut CallGraph,
|
||||
mask: &mut BitSet,
|
||||
) {
|
||||
let mut children = Vec::new();
|
||||
let visitor = CallGraphVisitor {
|
||||
children: &mut children,
|
||||
};
|
||||
let func = &self.functions[handle];
|
||||
mask.clear();
|
||||
|
||||
let mut interface = Interface {
|
||||
expressions: &func.expressions,
|
||||
local_variables: &func.local_variables,
|
||||
visitor,
|
||||
mask,
|
||||
};
|
||||
|
||||
interface.traverse(&func.body);
|
||||
|
||||
for handle in children {
|
||||
let child_id = graph.add_node(handle);
|
||||
graph.add_edge(id, child_id, ());
|
||||
|
||||
self.collect(handle, child_id, graph, mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CallGraphVisitor<'a> {
|
||||
children: &'a mut Vec<Handle<Function>>,
|
||||
}
|
||||
|
||||
impl<'a> Visitor for CallGraphVisitor<'a> {
|
||||
fn visit_fun(&mut self, func: Handle<Function>) {
|
||||
self.children.push(func)
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
//! Module processing functionality.
|
||||
|
||||
pub mod analyzer;
|
||||
#[cfg(feature = "petgraph")]
|
||||
mod call_graph;
|
||||
mod interface;
|
||||
mod layouter;
|
||||
mod namer;
|
||||
@ -10,8 +8,6 @@ mod terminator;
|
||||
mod typifier;
|
||||
mod validator;
|
||||
|
||||
#[cfg(feature = "petgraph")]
|
||||
pub use call_graph::{CallGraph, CallGraphBuilder};
|
||||
pub use interface::{Interface, Visitor};
|
||||
pub use layouter::{Alignment, Layouter};
|
||||
pub use namer::{EntryPointIndex, NameKey, Namer};
|
||||
|
@ -187,7 +187,8 @@ fn check_output_glsl(
|
||||
|
||||
let options = glsl::Options {
|
||||
version: glsl::Version::Embedded(310),
|
||||
entry_point: (stage, ep_name.to_string()),
|
||||
shader_stage: stage,
|
||||
entry_point: ep_name.to_string(),
|
||||
};
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
|
Loading…
Reference in New Issue
Block a user