mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Add ability to generate named expressions
This commit is contained in:
committed by
Dzmitry Malyshau
parent
98769c642d
commit
90c2cf6aa6
@@ -194,9 +194,11 @@ struct FunctionCtx<'a> {
|
||||
info: &'a FunctionInfo,
|
||||
/// The expression arena of the current function being written
|
||||
expressions: &'a Arena<Expression>,
|
||||
/// Map of expressions that have associated variable names
|
||||
named_expressions: &'a crate::NamedExpressions,
|
||||
}
|
||||
|
||||
impl<'a> FunctionCtx<'a> {
|
||||
impl<'a> FunctionCtx<'_> {
|
||||
/// Helper method that generates a [`NameKey`](crate::proc::NameKey) for a local in the current function
|
||||
fn name_key(&self, local: Handle<LocalVariable>) -> NameKey {
|
||||
match self.func {
|
||||
@@ -295,9 +297,6 @@ pub enum Error {
|
||||
/// A scalar with an unsupported width was requested
|
||||
#[error("A scalar with an unsupported width was requested: {0:?} {1:?}")]
|
||||
UnsupportedScalar(ScalarKind, Bytes),
|
||||
/// [`Interpolation::Patch`](crate::Interpolation::Patch) isn't supported
|
||||
#[error("Patch interpolation isn't supported")]
|
||||
PatchInterpolationNotSupported,
|
||||
/// A image was used with multiple samplers, this isn't supported
|
||||
#[error("A image was used with multiple samplers")]
|
||||
ImageMultipleSamplers,
|
||||
@@ -320,6 +319,7 @@ pub struct Writer<'a, W> {
|
||||
// Internal State
|
||||
/// Features manager used to store all the needed features and write them
|
||||
features: FeaturesManager,
|
||||
namer: Namer,
|
||||
/// A map with all the names needed for writing the module
|
||||
/// (generated by a [`Namer`](crate::proc::Namer))
|
||||
names: FastHashMap<NameKey, String>,
|
||||
@@ -332,7 +332,7 @@ pub struct Writer<'a, W> {
|
||||
/// Used to generate a unique number for blocks
|
||||
block_id: IdGenerator,
|
||||
/// Set of expressions that have associated temporary variables
|
||||
cached_expressions: FastHashMap<Handle<Expression>, String>,
|
||||
named_expressions: crate::NamedExpressions,
|
||||
}
|
||||
|
||||
impl<'a, W: Write> Writer<'a, W> {
|
||||
@@ -363,7 +363,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
|
||||
// Generate a map with names required to write the module
|
||||
let mut names = FastHashMap::default();
|
||||
Namer::default().reset(module, keywords::RESERVED_KEYWORDS, &["gl_"], &mut names);
|
||||
let mut namer = Namer::default();
|
||||
namer.reset(module, keywords::RESERVED_KEYWORDS, &["gl_"], &mut names);
|
||||
|
||||
// Build the instance
|
||||
let mut this = Self {
|
||||
@@ -371,7 +372,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
info,
|
||||
out,
|
||||
options,
|
||||
|
||||
namer,
|
||||
features: FeaturesManager::new(),
|
||||
names,
|
||||
reflection_names: FastHashMap::default(),
|
||||
@@ -379,7 +380,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
entry_point_idx: ep_idx as u16,
|
||||
|
||||
block_id: IdGenerator::default(),
|
||||
cached_expressions: FastHashMap::default(),
|
||||
named_expressions: crate::NamedExpressions::default(),
|
||||
};
|
||||
|
||||
// Find all features required to print this module
|
||||
@@ -884,9 +885,10 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
func: ty,
|
||||
info,
|
||||
expressions: &func.expressions,
|
||||
named_expressions: &func.named_expressions,
|
||||
};
|
||||
|
||||
self.cached_expressions.clear();
|
||||
self.named_expressions.clear();
|
||||
|
||||
// Write the function header
|
||||
//
|
||||
@@ -1189,30 +1191,23 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
// This is where we can generate intermediate constants for some expression types.
|
||||
Statement::Emit(ref range) => {
|
||||
for handle in range.clone() {
|
||||
if let Some(name) = ctx.named_expressions.get(&handle) {
|
||||
write!(self.out, "{}", INDENT.repeat(indent))?;
|
||||
|
||||
// Front end provides names for all variables at the start of writing.
|
||||
// But we write them to step by step. We need to recache them inside `write_named_expr`
|
||||
// Otherwise, we could accidentally write variable name instead of full expression.
|
||||
// Also, we use sanitized names! It defense backend from generating variable with name from reserved keywords.
|
||||
let sanitized_name = self.namer.call_unique(name);
|
||||
self.write_named_expr(handle, sanitized_name, ctx)?;
|
||||
continue;
|
||||
}
|
||||
|
||||
let min_ref_count = ctx.expressions[handle].bake_ref_count();
|
||||
if min_ref_count <= ctx.info[handle].ref_count {
|
||||
write!(self.out, "{}", INDENT.repeat(indent))?;
|
||||
match ctx.info[handle].ty {
|
||||
TypeResolution::Handle(ty_handle) => {
|
||||
match self.module.types[ty_handle].inner {
|
||||
TypeInner::Struct { .. } => {
|
||||
let ty_name = &self.names[&NameKey::Type(ty_handle)];
|
||||
write!(self.out, "{}", ty_name)?;
|
||||
}
|
||||
_ => {
|
||||
self.write_type(ty_handle)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeResolution::Value(ref inner) => {
|
||||
self.write_value_type(inner)?;
|
||||
}
|
||||
}
|
||||
let name = format!("_expr{}", handle.index());
|
||||
write!(self.out, " {} = ", name)?;
|
||||
self.write_expr(handle, ctx)?;
|
||||
writeln!(self.out, ";")?;
|
||||
self.cached_expressions.insert(handle, name);
|
||||
self.write_named_expr(handle, name, ctx)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1491,7 +1486,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
let result = self.module.functions[function].result.as_ref().unwrap();
|
||||
self.write_type(result.ty)?;
|
||||
write!(self.out, " {} = ", name)?;
|
||||
self.cached_expressions.insert(expr, name);
|
||||
self.named_expressions.insert(expr, name);
|
||||
}
|
||||
write!(self.out, "{}(", &self.names[&NameKey::Function(function)])?;
|
||||
self.write_slice(arguments, |this, _, arg| this.write_expr(*arg, ctx))?;
|
||||
@@ -1507,10 +1502,11 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
/// # Notes
|
||||
/// Doesn't add any newlines or leading/trailing spaces
|
||||
fn write_expr(&mut self, expr: Handle<Expression>, ctx: &FunctionCtx<'_>) -> BackendResult {
|
||||
if let Some(name) = self.cached_expressions.get(&expr) {
|
||||
if let Some(name) = self.named_expressions.get(&expr) {
|
||||
write!(self.out, "{}", name)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
match ctx.expressions[expr] {
|
||||
// `Access` is applied to arrays, vectors and matrices and is written as indexing
|
||||
Expression::Access { base, index } => {
|
||||
@@ -2114,6 +2110,34 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_named_expr(
|
||||
&mut self,
|
||||
handle: Handle<Expression>,
|
||||
name: String,
|
||||
ctx: &FunctionCtx,
|
||||
) -> BackendResult {
|
||||
match ctx.info[handle].ty {
|
||||
TypeResolution::Handle(ty_handle) => match self.module.types[ty_handle].inner {
|
||||
TypeInner::Struct { .. } => {
|
||||
let ty_name = &self.names[&NameKey::Type(ty_handle)];
|
||||
write!(self.out, "{}", ty_name)?;
|
||||
}
|
||||
_ => {
|
||||
self.write_type(ty_handle)?;
|
||||
}
|
||||
},
|
||||
TypeResolution::Value(ref inner) => {
|
||||
self.write_value_type(inner)?;
|
||||
}
|
||||
}
|
||||
write!(self.out, " {} = ", name)?;
|
||||
self.write_expr(handle, ctx)?;
|
||||
writeln!(self.out, ";")?;
|
||||
self.named_expressions.insert(handle, name);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Helper method used to produce the reflection info that's returned to the user
|
||||
///
|
||||
/// It takes an iterator of [`Function`](crate::Function) references instead of
|
||||
|
||||
@@ -77,7 +77,7 @@ pub struct PerStageResources {
|
||||
|
||||
/// The slot of a buffer that contains an array of `u32`,
|
||||
/// one for the size of each bound buffer that contains a runtime array,
|
||||
/// in order of [`GlobalVariable`] declarations.
|
||||
/// in order of [`crate::GlobalVariable`] declarations.
|
||||
#[cfg_attr(feature = "deserialize", serde(default))]
|
||||
pub sizes_buffer: Option<Slot>,
|
||||
}
|
||||
|
||||
@@ -4,11 +4,10 @@ use crate::{
|
||||
proc::{EntryPointIndex, NameKey, Namer, TypeResolution},
|
||||
valid::{FunctionInfo, ModuleInfo},
|
||||
Arena, ArraySize, Binding, Constant, ConstantInner, Expression, FastHashMap, Function,
|
||||
GlobalVariable, Handle, ImageClass, ImageDimension, Interpolation, Module, SampleLevel,
|
||||
Sampling, ScalarKind, ScalarValue, ShaderStage, Statement, StorageClass, StorageFormat,
|
||||
StructMember, Type, TypeInner,
|
||||
GlobalVariable, Handle, ImageClass, ImageDimension, Interpolation, LocalVariable, Module,
|
||||
SampleLevel, Sampling, ScalarKind, ScalarValue, ShaderStage, Statement, StorageClass,
|
||||
StorageFormat, StructMember, Type, TypeInner,
|
||||
};
|
||||
use bit_set::BitSet;
|
||||
use std::fmt::Write;
|
||||
|
||||
const INDENT: &str = " ";
|
||||
@@ -53,13 +52,25 @@ struct FunctionCtx<'a> {
|
||||
info: &'a FunctionInfo,
|
||||
/// The expression arena of the current function being written
|
||||
expressions: &'a Arena<Expression>,
|
||||
/// Map of expressions that have associated variable names
|
||||
named_expressions: &'a crate::NamedExpressions,
|
||||
}
|
||||
|
||||
impl<'a> FunctionCtx<'_> {
|
||||
/// Helper method that generates a [`NameKey`](crate::proc::NameKey) for a local in the current function
|
||||
fn name_key(&self, local: Handle<LocalVariable>) -> NameKey {
|
||||
match self.ty {
|
||||
FunctionType::Function(handle) => NameKey::FunctionLocal(handle, local),
|
||||
FunctionType::EntryPoint(idx) => NameKey::EntryPointLocal(idx, local),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Writer<W> {
|
||||
out: W,
|
||||
names: FastHashMap<NameKey, String>,
|
||||
namer: Namer,
|
||||
named_expressions: BitSet,
|
||||
named_expressions: crate::NamedExpressions,
|
||||
ep_results: Vec<(ShaderStage, Handle<Type>)>,
|
||||
}
|
||||
|
||||
@@ -69,7 +80,7 @@ impl<W: Write> Writer<W> {
|
||||
out,
|
||||
names: FastHashMap::default(),
|
||||
namer: Namer::default(),
|
||||
named_expressions: BitSet::new(),
|
||||
named_expressions: crate::NamedExpressions::default(),
|
||||
ep_results: vec![],
|
||||
}
|
||||
}
|
||||
@@ -78,6 +89,7 @@ impl<W: Write> Writer<W> {
|
||||
self.names.clear();
|
||||
self.namer.reset(module, RESERVED, &[], &mut self.names);
|
||||
self.named_expressions.clear();
|
||||
self.ep_results.clear();
|
||||
}
|
||||
|
||||
pub fn write(&mut self, module: &Module, info: &ModuleInfo) -> BackendResult {
|
||||
@@ -128,6 +140,7 @@ impl<W: Write> Writer<W> {
|
||||
ty: FunctionType::Function(handle),
|
||||
info: fun_info,
|
||||
expressions: &function.expressions,
|
||||
named_expressions: &function.named_expressions,
|
||||
};
|
||||
|
||||
// Write the function
|
||||
@@ -154,6 +167,7 @@ impl<W: Write> Writer<W> {
|
||||
ty: FunctionType::EntryPoint(index as u16),
|
||||
info: &info.get_entry_point(index),
|
||||
expressions: &ep.function.expressions,
|
||||
named_expressions: &ep.function.named_expressions,
|
||||
};
|
||||
self.write_function(&module, &ep.function, &func_ctx)?;
|
||||
|
||||
@@ -271,11 +285,7 @@ impl<W: Write> Writer<W> {
|
||||
|
||||
// Write the local name
|
||||
// The leading space is important
|
||||
let name_key = match func_ctx.ty {
|
||||
FunctionType::Function(func_handle) => NameKey::FunctionLocal(func_handle, handle),
|
||||
FunctionType::EntryPoint(idx) => NameKey::EntryPointLocal(idx, handle),
|
||||
};
|
||||
write!(self.out, "var {}: ", self.names[&name_key])?;
|
||||
write!(self.out, "var {}: ", self.names[&func_ctx.name_key(handle)])?;
|
||||
|
||||
// Write the local type
|
||||
self.write_type(&module, local.ty)?;
|
||||
@@ -570,6 +580,21 @@ impl<W: Write> Writer<W> {
|
||||
match *stmt {
|
||||
Statement::Emit(ref range) => {
|
||||
for handle in range.clone() {
|
||||
if let Some(name) = func_ctx.named_expressions.get(&handle) {
|
||||
write!(self.out, "{}", INDENT.repeat(indent))?;
|
||||
let sanitized_name = self.namer.call_unique(name);
|
||||
self.start_named_expr(module, handle, &func_ctx, &sanitized_name)?;
|
||||
self.write_expr(module, handle, &func_ctx)?;
|
||||
writeln!(self.out, ";")?;
|
||||
|
||||
// Front end provides names for all variables at the start of writing.
|
||||
// But we write them to step by step. We need to recache them.
|
||||
// Otherwise, we could accidentally write variable name instead of full expression.
|
||||
// Also, we use sanitized names! It defense backend from generating variable with name from reserved keywords.
|
||||
self.named_expressions.insert(handle, sanitized_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
let expr = &func_ctx.expressions[handle];
|
||||
let min_ref_count = expr.bake_ref_count();
|
||||
// Forcefully creating baking expressions in some cases to help with readability
|
||||
@@ -581,10 +606,8 @@ impl<W: Write> Writer<W> {
|
||||
};
|
||||
if min_ref_count <= func_ctx.info[handle].ref_count || required_baking_expr {
|
||||
write!(self.out, "{}", INDENT.repeat(indent))?;
|
||||
self.start_baking_expr(module, handle, &func_ctx)?;
|
||||
self.write_expr(module, handle, &func_ctx)?;
|
||||
self.write_baking_expr(module, handle, &func_ctx)?;
|
||||
writeln!(self.out, ";")?;
|
||||
self.named_expressions.insert(handle.index());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -654,8 +677,7 @@ impl<W: Write> Writer<W> {
|
||||
} => {
|
||||
write!(self.out, "{}", INDENT.repeat(indent))?;
|
||||
if let Some(expr) = result {
|
||||
self.start_baking_expr(module, expr, &func_ctx)?;
|
||||
self.named_expressions.insert(expr.index());
|
||||
self.write_baking_expr(module, expr, &func_ctx)?;
|
||||
}
|
||||
let func_name = &self.names[&NameKey::Function(function)];
|
||||
write!(self.out, "{}(", func_name)?;
|
||||
@@ -793,33 +815,23 @@ impl<W: Write> Writer<W> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn start_baking_expr(
|
||||
fn start_named_expr(
|
||||
&mut self,
|
||||
module: &Module,
|
||||
handle: Handle<Expression>,
|
||||
context: &FunctionCtx,
|
||||
func_ctx: &FunctionCtx,
|
||||
name: &str,
|
||||
) -> BackendResult {
|
||||
// Write variable name
|
||||
write!(self.out, "let {}{}: ", BAKE_PREFIX, handle.index())?;
|
||||
let ty = &context.info[handle].ty;
|
||||
write!(self.out, "let {}: ", name)?;
|
||||
let ty = &func_ctx.info[handle].ty;
|
||||
// Write variable type
|
||||
match *ty {
|
||||
TypeResolution::Handle(ty_handle) => {
|
||||
self.write_type(module, ty_handle)?;
|
||||
TypeResolution::Handle(handle) => {
|
||||
self.write_type(module, handle)?;
|
||||
}
|
||||
TypeResolution::Value(crate::TypeInner::Scalar { kind, .. }) => {
|
||||
write!(self.out, "{}", scalar_kind_str(kind))?;
|
||||
}
|
||||
TypeResolution::Value(crate::TypeInner::Vector { size, kind, .. }) => {
|
||||
write!(
|
||||
self.out,
|
||||
"vec{}<{}>",
|
||||
vector_size_str(size),
|
||||
scalar_kind_str(kind),
|
||||
)?;
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Unimplemented(format!("start_baking_expr {:?}", ty)));
|
||||
TypeResolution::Value(ref inner) => {
|
||||
self.write_value_type(module, inner)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -827,6 +839,20 @@ impl<W: Write> Writer<W> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_baking_expr(
|
||||
&mut self,
|
||||
module: &Module,
|
||||
handle: Handle<Expression>,
|
||||
func_ctx: &FunctionCtx,
|
||||
) -> BackendResult {
|
||||
let name = format!("{}{}", BAKE_PREFIX, handle.index());
|
||||
self.start_named_expr(module, handle, func_ctx, &name)?;
|
||||
self.write_expr(module, handle, func_ctx)?;
|
||||
self.named_expressions.insert(handle, name);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Helper method to write expressions
|
||||
///
|
||||
/// # Notes
|
||||
@@ -837,13 +863,13 @@ impl<W: Write> Writer<W> {
|
||||
expr: Handle<Expression>,
|
||||
func_ctx: &FunctionCtx<'_>,
|
||||
) -> BackendResult {
|
||||
let expression = &func_ctx.expressions[expr];
|
||||
|
||||
if self.named_expressions.contains(expr.index()) {
|
||||
write!(self.out, "{}{}", BAKE_PREFIX, expr.index())?;
|
||||
if let Some(name) = self.named_expressions.get(&expr) {
|
||||
write!(self.out, "{}", name)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let expression = &func_ctx.expressions[expr];
|
||||
|
||||
match *expression {
|
||||
Expression::Constant(constant) => self.write_constant(module, constant)?,
|
||||
Expression::Compose { ty, ref components } => {
|
||||
@@ -1110,13 +1136,7 @@ impl<W: Write> Writer<W> {
|
||||
}
|
||||
Expression::Load { pointer } => self.write_expr(module, pointer, func_ctx)?,
|
||||
Expression::LocalVariable(handle) => {
|
||||
let name_key = match func_ctx.ty {
|
||||
FunctionType::Function(func_handle) => {
|
||||
NameKey::FunctionLocal(func_handle, handle)
|
||||
}
|
||||
FunctionType::EntryPoint(idx) => NameKey::EntryPointLocal(idx, handle),
|
||||
};
|
||||
write!(self.out, "{}", self.names[&name_key])?
|
||||
write!(self.out, "{}", self.names[&func_ctx.name_key(handle)])?
|
||||
}
|
||||
Expression::ArrayLength(expr) => {
|
||||
write!(self.out, "arrayLength(")?;
|
||||
@@ -1273,10 +1293,8 @@ impl<W: Write> Writer<W> {
|
||||
|
||||
write!(self.out, ")")?
|
||||
}
|
||||
Expression::Call(function) => {
|
||||
let func_name = &self.names[&NameKey::Function(function)];
|
||||
write!(self.out, "{}(", func_name)?
|
||||
}
|
||||
// Nothing to do here, since call expression already cached
|
||||
Expression::Call(_) => {}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -630,6 +630,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
|
||||
name: Some(name),
|
||||
result,
|
||||
expressions,
|
||||
named_expressions: crate::FastHashMap::default(),
|
||||
local_variables,
|
||||
arguments,
|
||||
body,
|
||||
|
||||
@@ -28,7 +28,7 @@ pub enum Terminator {
|
||||
///
|
||||
/// switch(SELECTOR) {
|
||||
/// case TARGET_LITERAL#: {
|
||||
/// TARGET_BLOCK#
|
||||
/// TARGET_BLOCK#
|
||||
/// }
|
||||
/// default: {
|
||||
/// DEFAULT
|
||||
@@ -90,6 +90,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
|
||||
},
|
||||
local_variables: Arena::new(),
|
||||
expressions: self.make_expression_storage(),
|
||||
named_expressions: crate::FastHashMap::default(),
|
||||
body: Vec::new(),
|
||||
}
|
||||
};
|
||||
@@ -194,6 +195,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
|
||||
result: None,
|
||||
local_variables: Arena::new(),
|
||||
expressions: Arena::new(),
|
||||
named_expressions: crate::FastHashMap::default(),
|
||||
body: Vec::new(),
|
||||
};
|
||||
|
||||
|
||||
@@ -589,6 +589,7 @@ struct StatementContext<'input, 'temp, 'out> {
|
||||
typifier: &'temp mut super::Typifier,
|
||||
variables: &'out mut Arena<crate::LocalVariable>,
|
||||
expressions: &'out mut Arena<crate::Expression>,
|
||||
named_expressions: &'out mut FastHashMap<Handle<crate::Expression>, String>,
|
||||
types: &'out mut Arena<crate::Type>,
|
||||
constants: &'out mut Arena<crate::Constant>,
|
||||
global_vars: &'out Arena<crate::GlobalVariable>,
|
||||
@@ -603,6 +604,7 @@ impl<'a, 'temp> StatementContext<'a, 'temp, '_> {
|
||||
typifier: self.typifier,
|
||||
variables: self.variables,
|
||||
expressions: self.expressions,
|
||||
named_expressions: self.named_expressions,
|
||||
types: self.types,
|
||||
constants: self.constants,
|
||||
global_vars: self.global_vars,
|
||||
@@ -2563,6 +2565,9 @@ impl Parser {
|
||||
}
|
||||
block.extend(emitter.finish(context.expressions));
|
||||
context.lookup_ident.insert(name, expr_id);
|
||||
context
|
||||
.named_expressions
|
||||
.insert(expr_id, String::from(name));
|
||||
}
|
||||
"var" => {
|
||||
enum Init {
|
||||
@@ -2985,11 +2990,13 @@ impl Parser {
|
||||
result,
|
||||
local_variables: Arena::new(),
|
||||
expressions,
|
||||
named_expressions: crate::NamedExpressions::default(),
|
||||
body: Vec::new(),
|
||||
};
|
||||
|
||||
// read body
|
||||
let mut typifier = super::Typifier::new();
|
||||
let mut named_expressions = crate::FastHashMap::default();
|
||||
fun.body = self.parse_block(
|
||||
lexer,
|
||||
StatementContext {
|
||||
@@ -2997,6 +3004,7 @@ impl Parser {
|
||||
typifier: &mut typifier,
|
||||
variables: &mut fun.local_variables,
|
||||
expressions: &mut fun.expressions,
|
||||
named_expressions: &mut named_expressions,
|
||||
types: &mut module.types,
|
||||
constants: &mut module.constants,
|
||||
global_vars: &module.global_variables,
|
||||
@@ -3010,6 +3018,9 @@ impl Parser {
|
||||
// done
|
||||
self.scopes.pop();
|
||||
|
||||
// Set named expressions after block parsing ends
|
||||
fun.named_expressions = named_expressions;
|
||||
|
||||
Ok((fun, fun_name))
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +151,9 @@ pub type FastHashMap<K, T> = HashMap<K, T, BuildHasherDefault<fxhash::FxHasher>>
|
||||
/// Hash set that is faster but not resilient to DoS attacks.
|
||||
pub type FastHashSet<K> = HashSet<K, BuildHasherDefault<fxhash::FxHasher>>;
|
||||
|
||||
/// Map of expressions that have associated variable names
|
||||
pub(crate) type NamedExpressions = FastHashMap<Handle<Expression>, String>;
|
||||
|
||||
/// Early fragment tests. In a standard situation if a driver determines that it is possible to
|
||||
/// switch on early depth test it will. Typical situations when early depth test is switched off:
|
||||
/// - Calling ```discard``` in a shader.
|
||||
@@ -1043,6 +1046,8 @@ pub struct Function {
|
||||
pub local_variables: Arena<LocalVariable>,
|
||||
/// Expressions used inside this function.
|
||||
pub expressions: Arena<Expression>,
|
||||
/// Map of expressions that have associated variable names
|
||||
pub named_expressions: NamedExpressions,
|
||||
/// Block of instructions comprising the body of the function.
|
||||
pub body: Block,
|
||||
}
|
||||
|
||||
@@ -48,6 +48,22 @@ impl Namer {
|
||||
base
|
||||
}
|
||||
|
||||
/// Helper function that return unique name without cache update.
|
||||
/// This function should be used **after** [`Namer`](crate::proc::Namer) initialization by [`reset`](Self::reset()) function.
|
||||
pub fn call_unique(&mut self, string: &str) -> String {
|
||||
let base = self.sanitize(string);
|
||||
match self.unique.entry(base) {
|
||||
Entry::Occupied(mut e) => {
|
||||
*e.get_mut() += 1;
|
||||
format!("{}{}", e.key(), e.get())
|
||||
}
|
||||
Entry::Vacant(e) => {
|
||||
let name = e.key().to_string();
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call(&mut self, label_raw: &str) -> String {
|
||||
let base = self.sanitize(label_raw);
|
||||
match self.unique.entry(base) {
|
||||
|
||||
@@ -9,5 +9,9 @@ var<storage> bar: [[access(read_write)]] Bar;
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn foo([[builtin(vertex_index)]] vi: u32) -> [[builtin(position)]] vec4<f32> {
|
||||
return vec4<f32>(vec4<i32>(array<i32,5>(bar.data[(arrayLength(&bar.data) - 1u)], i32(bar.matrix[3u].x), 3, 4, 5)[vi]));
|
||||
let b: f32 = bar.matrix[3u].x;
|
||||
let a: i32 = bar.data[(arrayLength(&bar.data) - 1u)];
|
||||
let array: array<i32,5> = array<i32,5>(a, i32(b), 3, 4, 5);
|
||||
let value: i32 = array[vi];
|
||||
return vec4<f32>(vec4<i32>(value));
|
||||
}
|
||||
|
||||
@@ -37,11 +37,12 @@ void main() {
|
||||
vec2 pos1;
|
||||
vec2 vel1;
|
||||
uint i = 0u;
|
||||
if((global_invocation_id.x >= 1500u)) {
|
||||
uint index = global_invocation_id.x;
|
||||
if((index >= 1500u)) {
|
||||
return;
|
||||
}
|
||||
vPos = _group_0_binding_1.particles[global_invocation_id.x].pos;
|
||||
vVel = _group_0_binding_1.particles[global_invocation_id.x].vel;
|
||||
vPos = _group_0_binding_1.particles[index].pos;
|
||||
vVel = _group_0_binding_1.particles[index].vel;
|
||||
cMass = vec2(0.0, 0.0);
|
||||
cVel = vec2(0.0, 0.0);
|
||||
colVel = vec2(0.0, 0.0);
|
||||
@@ -49,7 +50,7 @@ void main() {
|
||||
if((i >= 1500u)) {
|
||||
break;
|
||||
}
|
||||
if((i == global_invocation_id.x)) {
|
||||
if((i == index)) {
|
||||
continue;
|
||||
}
|
||||
pos1 = _group_0_binding_1.particles[i].pos;
|
||||
@@ -88,8 +89,8 @@ void main() {
|
||||
if((vPos.y > 1.0)) {
|
||||
vPos.y = -1.0;
|
||||
}
|
||||
_group_0_binding_2.particles[global_invocation_id.x].pos = vPos;
|
||||
_group_0_binding_2.particles[global_invocation_id.x].vel = vVel;
|
||||
_group_0_binding_2.particles[index].pos = vPos;
|
||||
_group_0_binding_2.particles[index].vel = vVel;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,11 +41,12 @@ fn main([[builtin(global_invocation_id)]] global_invocation_id: vec3<u32>) {
|
||||
var vel1: vec2<f32>;
|
||||
var i: u32 = 0u;
|
||||
|
||||
if ((global_invocation_id.x >= NUM_PARTICLES)) {
|
||||
let index: u32 = global_invocation_id.x;
|
||||
if ((index >= NUM_PARTICLES)) {
|
||||
return;
|
||||
}
|
||||
vPos = particlesSrc.particles[global_invocation_id.x].pos;
|
||||
vVel = particlesSrc.particles[global_invocation_id.x].vel;
|
||||
vPos = particlesSrc.particles[index].pos;
|
||||
vVel = particlesSrc.particles[index].vel;
|
||||
cMass = vec2<f32>(0.0, 0.0);
|
||||
cVel = vec2<f32>(0.0, 0.0);
|
||||
colVel = vec2<f32>(0.0, 0.0);
|
||||
@@ -53,7 +54,7 @@ fn main([[builtin(global_invocation_id)]] global_invocation_id: vec3<u32>) {
|
||||
if ((i >= NUM_PARTICLES)) {
|
||||
break;
|
||||
}
|
||||
if ((i == global_invocation_id.x)) {
|
||||
if ((i == index)) {
|
||||
continue;
|
||||
}
|
||||
pos1 = particlesSrc.particles[i].pos;
|
||||
@@ -94,7 +95,7 @@ fn main([[builtin(global_invocation_id)]] global_invocation_id: vec3<u32>) {
|
||||
if ((vPos.y > 1.0)) {
|
||||
vPos.y = -1.0;
|
||||
}
|
||||
particlesDst.particles[global_invocation_id.x].pos = vPos;
|
||||
particlesDst.particles[global_invocation_id.x].vel = vVel;
|
||||
particlesDst.particles[index].pos = vPos;
|
||||
particlesDst.particles[index].vel = vVel;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
pointer: 5,
|
||||
),
|
||||
],
|
||||
named_expressions: {},
|
||||
body: [
|
||||
Store(
|
||||
pointer: 3,
|
||||
@@ -320,6 +321,7 @@
|
||||
),
|
||||
Call(1),
|
||||
],
|
||||
named_expressions: {},
|
||||
body: [
|
||||
Emit((
|
||||
start: 2,
|
||||
|
||||
@@ -23,41 +23,42 @@ var image_2d_depth: texture_depth_2d;
|
||||
|
||||
[[stage(compute), workgroup_size(16, 1, 1)]]
|
||||
fn main([[builtin(local_invocation_id)]] local_id: vec3<u32>) {
|
||||
let _e3: vec2<i32> = textureDimensions(image_src);
|
||||
let _e10: vec2<i32> = ((_e3 * vec2<i32>(local_id.xy)) % vec2<i32>(10, 20));
|
||||
let _e11: vec4<u32> = textureLoad(image_src, _e10);
|
||||
textureStore(image_dst, _e10.x, _e11);
|
||||
let dim: vec2<i32> = textureDimensions(image_src);
|
||||
let itc: vec2<i32> = ((dim * vec2<i32>(local_id.xy)) % vec2<i32>(10, 20));
|
||||
let value: vec4<u32> = textureLoad(image_src, itc);
|
||||
textureStore(image_dst, itc.x, value);
|
||||
return;
|
||||
}
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn queries() -> [[builtin(position)]] vec4<f32> {
|
||||
let _e9: i32 = textureDimensions(image_1d);
|
||||
let _e10: vec2<i32> = textureDimensions(image_2d);
|
||||
let _e11: i32 = textureNumLevels(image_2d);
|
||||
let _e13: vec2<i32> = textureDimensions(image_2d, 1);
|
||||
let _e14: vec2<i32> = textureDimensions(image_2d_array);
|
||||
let _e15: i32 = textureNumLevels(image_2d_array);
|
||||
let _e17: vec2<i32> = textureDimensions(image_2d_array, 1);
|
||||
let _e18: i32 = textureNumLayers(image_2d_array);
|
||||
let _e19: vec3<i32> = textureDimensions(image_cube);
|
||||
let _e20: i32 = textureNumLevels(image_cube);
|
||||
let _e22: vec3<i32> = textureDimensions(image_cube, 1);
|
||||
let _e23: vec3<i32> = textureDimensions(image_cube_array);
|
||||
let _e24: i32 = textureNumLevels(image_cube_array);
|
||||
let _e26: vec3<i32> = textureDimensions(image_cube_array, 1);
|
||||
let _e27: i32 = textureNumLayers(image_cube_array);
|
||||
let _e28: vec3<i32> = textureDimensions(image_3d);
|
||||
let _e29: i32 = textureNumLevels(image_3d);
|
||||
let _e31: vec3<i32> = textureDimensions(image_3d, 1);
|
||||
let _e32: i32 = textureNumSamples(image_aa);
|
||||
return vec4<f32>(f32(((((((((((((((((((_e9 + _e10.y) + _e13.y) + _e14.y) + _e17.y) + _e18) + _e19.y) + _e22.y) + _e23.y) + _e26.y) + _e27) + _e28.z) + _e31.z) + _e32) + _e11) + _e15) + _e29) + _e20) + _e24)));
|
||||
let dim_1d: i32 = textureDimensions(image_1d);
|
||||
let dim_2d: vec2<i32> = textureDimensions(image_2d);
|
||||
let num_levels_2d: i32 = textureNumLevels(image_2d);
|
||||
let dim_2d_lod: vec2<i32> = textureDimensions(image_2d, 1);
|
||||
let dim_2d_array: vec2<i32> = textureDimensions(image_2d_array);
|
||||
let num_levels_2d_array: i32 = textureNumLevels(image_2d_array);
|
||||
let dim_2d_array_lod: vec2<i32> = textureDimensions(image_2d_array, 1);
|
||||
let num_layers_2d: i32 = textureNumLayers(image_2d_array);
|
||||
let dim_cube: vec3<i32> = textureDimensions(image_cube);
|
||||
let num_levels_cube: i32 = textureNumLevels(image_cube);
|
||||
let dim_cube_lod: vec3<i32> = textureDimensions(image_cube, 1);
|
||||
let dim_cube_array: vec3<i32> = textureDimensions(image_cube_array);
|
||||
let num_levels_cube_array: i32 = textureNumLevels(image_cube_array);
|
||||
let dim_cube_array_lod: vec3<i32> = textureDimensions(image_cube_array, 1);
|
||||
let num_layers_cube: i32 = textureNumLayers(image_cube_array);
|
||||
let dim_3d: vec3<i32> = textureDimensions(image_3d);
|
||||
let num_levels_3d: i32 = textureNumLevels(image_3d);
|
||||
let dim_3d_lod: vec3<i32> = textureDimensions(image_3d, 1);
|
||||
let num_samples_aa: i32 = textureNumSamples(image_aa);
|
||||
let sum: i32 = ((((((((((((((((((dim_1d + dim_2d.y) + dim_2d_lod.y) + dim_2d_array.y) + dim_2d_array_lod.y) + num_layers_2d) + dim_cube.y) + dim_cube_lod.y) + dim_cube_array.y) + dim_cube_array_lod.y) + num_layers_cube) + dim_3d.z) + dim_3d_lod.z) + num_samples_aa) + num_levels_2d) + num_levels_2d_array) + num_levels_3d) + num_levels_cube) + num_levels_cube_array);
|
||||
return vec4<f32>(f32(sum));
|
||||
}
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn sample_comparison() -> [[location(0)]] f32 {
|
||||
let _e12: vec2<f32> = vec2<f32>(0.5);
|
||||
let _e14: f32 = textureSampleCompare(image_2d_depth, sampler_cmp, _e12, 0.5);
|
||||
let _e15: f32 = textureSampleCompareLevel(image_2d_depth, sampler_cmp, _e12, 0.5);
|
||||
return (_e14 + _e15);
|
||||
let tc: vec2<f32> = vec2<f32>(0.5);
|
||||
let s2d_depth: f32 = textureSampleCompare(image_2d_depth, sampler_cmp, tc, 0.5);
|
||||
let s2d_depth_level: f32 = textureSampleCompareLevel(image_2d_depth, sampler_cmp, tc, 0.5);
|
||||
return (s2d_depth + s2d_depth_level);
|
||||
}
|
||||
|
||||
@@ -11,12 +11,15 @@ struct FragmentOutput {
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn vertex([[builtin(vertex_index)]] vertex_index: u32, [[builtin(instance_index)]] instance_index: u32, [[location(10)]] color1: u32) -> VertexOutput {
|
||||
return VertexOutput(vec4<f32>(1.0), f32(((vertex_index + instance_index) + color1)));
|
||||
let tmp: u32 = ((vertex_index + instance_index) + color1);
|
||||
return VertexOutput(vec4<f32>(1.0), f32(tmp));
|
||||
}
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn fragment(in: VertexOutput, [[builtin(front_facing)]] front_facing: bool, [[builtin(sample_index)]] sample_index: u32, [[builtin(sample_mask)]] sample_mask1: u32) -> FragmentOutput {
|
||||
return FragmentOutput(in.varying, (sample_mask1 & (1u << sample_index)), select(0.0, 1.0, front_facing));
|
||||
let mask: u32 = (sample_mask1 & (1u << sample_index));
|
||||
let color2: f32 = select(0.0, 1.0, front_facing);
|
||||
return FragmentOutput(in.varying, mask, color2);
|
||||
}
|
||||
|
||||
[[stage(compute), workgroup_size(1, 1, 1)]]
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
fn splat() -> vec4<f32> {
|
||||
return ((((vec2<f32>(1.0) + vec2<f32>(2.0)) - vec2<f32>(3.0)) / vec2<f32>(4.0)).xyxy + vec4<f32>((vec4<i32>(5) % vec4<i32>(2))));
|
||||
let a: vec2<f32> = (((vec2<f32>(1.0) + vec2<f32>(2.0)) - vec2<f32>(3.0)) / vec2<f32>(4.0));
|
||||
let b: vec4<i32> = (vec4<i32>(5) % vec4<i32>(2));
|
||||
return (a.xyxy + vec4<f32>(b));
|
||||
}
|
||||
|
||||
fn unary() -> i32 {
|
||||
|
||||
@@ -14,11 +14,12 @@ layout(location = 0) out vec4 _fs2p_location0;
|
||||
|
||||
void main() {
|
||||
vec2 uv2 = _vs2fs_location0;
|
||||
vec4 _expr4 = texture(_group_0_binding_0, vec2(uv2));
|
||||
if((_expr4.w == 0.0)) {
|
||||
vec4 color = texture(_group_0_binding_0, vec2(uv2));
|
||||
if((color.w == 0.0)) {
|
||||
discard;
|
||||
}
|
||||
_fs2p_location0 = (_expr4.w * _expr4);
|
||||
vec4 premultiplied = (color.w * color);
|
||||
_fs2p_location0 = premultiplied;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,10 @@ fn main([[location(0)]] pos: vec2<f32>, [[location(1)]] uv1: vec2<f32>) -> Verte
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn main1([[location(0), interpolate(perspective)]] uv2: vec2<f32>) -> [[location(0)]] vec4<f32> {
|
||||
let _e4: vec4<f32> = textureSample(u_texture, u_sampler, uv2);
|
||||
if ((_e4.w == 0.0)) {
|
||||
let color: vec4<f32> = textureSample(u_texture, u_sampler, uv2);
|
||||
if ((color.w == 0.0)) {
|
||||
discard;
|
||||
}
|
||||
return (_e4.w * _e4);
|
||||
let premultiplied: vec4<f32> = (color.w * color);
|
||||
return premultiplied;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,9 @@ float fetch_shadow(uint light_id, vec4 homogeneous_coords) {
|
||||
if((homogeneous_coords.w <= 0.0)) {
|
||||
return 1.0;
|
||||
}
|
||||
float _expr26 = textureGrad(_group_0_binding_2, vec4((((homogeneous_coords.xy * vec2(0.5, -0.5)) / vec2(homogeneous_coords.w)) + vec2(0.5, 0.5)), int(light_id), (homogeneous_coords.z / homogeneous_coords.w)), vec2(0, 0), vec2(0,0));
|
||||
vec2 flip_correction = vec2(0.5, -0.5);
|
||||
vec2 light_local = (((homogeneous_coords.xy * flip_correction) / vec2(homogeneous_coords.w)) + vec2(0.5, 0.5));
|
||||
float _expr26 = textureGrad(_group_0_binding_2, vec4(light_local, int(light_id), (homogeneous_coords.z / homogeneous_coords.w)), vec2(0, 0), vec2(0,0));
|
||||
return _expr26;
|
||||
}
|
||||
|
||||
@@ -33,13 +35,16 @@ void main() {
|
||||
vec4 position = _vs2fs_location1;
|
||||
vec3 color1 = vec3(0.05, 0.05, 0.05);
|
||||
uint i = 0u;
|
||||
vec3 normal = normalize(raw_normal);
|
||||
while(true) {
|
||||
if((i >= min(_group_0_binding_0.num_lights.x, 10u))) {
|
||||
break;
|
||||
}
|
||||
Light _expr21 = _group_0_binding_1.data[i];
|
||||
float _expr25 = fetch_shadow(i, (_expr21.proj * position));
|
||||
color1 = (color1 + ((_expr25 * max(0.0, dot(normalize(raw_normal), normalize((_expr21.pos.xyz - position.xyz))))) * _expr21.color.xyz));
|
||||
Light light = _group_0_binding_1.data[i];
|
||||
float _expr25 = fetch_shadow(i, (light.proj * position));
|
||||
vec3 light_dir = normalize((light.pos.xyz - position.xyz));
|
||||
float diffuse = max(0.0, dot(normal, light_dir));
|
||||
color1 = (color1 + ((_expr25 * diffuse) * light.color.xyz));
|
||||
i = (i + 1u);
|
||||
}
|
||||
_fs2p_location0 = vec4(color1, 1.0);
|
||||
|
||||
@@ -1054,6 +1054,7 @@
|
||||
depth_ref: Some(69),
|
||||
),
|
||||
],
|
||||
named_expressions: {},
|
||||
body: [
|
||||
Emit((
|
||||
start: 48,
|
||||
@@ -1443,6 +1444,7 @@
|
||||
],
|
||||
),
|
||||
],
|
||||
named_expressions: {},
|
||||
body: [
|
||||
Loop(
|
||||
body: [
|
||||
@@ -1550,6 +1552,7 @@
|
||||
pointer: 5,
|
||||
),
|
||||
],
|
||||
named_expressions: {},
|
||||
body: [
|
||||
Store(
|
||||
pointer: 2,
|
||||
|
||||
@@ -30,7 +30,9 @@ fn fetch_shadow(light_id: u32, homogeneous_coords: vec4<f32>) -> f32 {
|
||||
if ((homogeneous_coords.w <= 0.0)) {
|
||||
return 1.0;
|
||||
}
|
||||
let _e26: f32 = textureSampleCompareLevel(t_shadow, sampler_shadow, (((homogeneous_coords.xy * vec2<f32>(0.5, -0.5)) / vec2<f32>(homogeneous_coords.w)) + vec2<f32>(0.5, 0.5)), i32(light_id), (homogeneous_coords.z / homogeneous_coords.w));
|
||||
let flip_correction: vec2<f32> = vec2<f32>(0.5, -0.5);
|
||||
let light_local: vec2<f32> = (((homogeneous_coords.xy * flip_correction) / vec2<f32>(homogeneous_coords.w)) + vec2<f32>(0.5, 0.5));
|
||||
let _e26: f32 = textureSampleCompareLevel(t_shadow, sampler_shadow, light_local, i32(light_id), (homogeneous_coords.z / homogeneous_coords.w));
|
||||
return _e26;
|
||||
}
|
||||
|
||||
@@ -39,13 +41,16 @@ fn fs_main([[location(0), interpolate(perspective)]] raw_normal: vec3<f32>, [[lo
|
||||
var color1: vec3<f32> = vec3<f32>(0.05, 0.05, 0.05);
|
||||
var i: u32 = 0u;
|
||||
|
||||
let normal: vec3<f32> = normalize(raw_normal);
|
||||
loop {
|
||||
if ((i >= min(u_globals.num_lights.x, c_max_lights))) {
|
||||
break;
|
||||
}
|
||||
let _e21: Light = s_lights.data[i];
|
||||
let _e25: f32 = fetch_shadow(i, (_e21.proj * position));
|
||||
color1 = (color1 + ((_e25 * max(0.0, dot(normalize(raw_normal), normalize((_e21.pos.xyz - position.xyz))))) * _e21.color.xyz));
|
||||
let light: Light = s_lights.data[i];
|
||||
let _e25: f32 = fetch_shadow(i, (light.proj * position));
|
||||
let light_dir: vec3<f32> = normalize((light.pos.xyz - position.xyz));
|
||||
let diffuse: f32 = max(0.0, dot(normal, light_dir));
|
||||
color1 = (color1 + ((_e25 * diffuse) * light.color.xyz));
|
||||
continuing {
|
||||
i = (i + 1u);
|
||||
}
|
||||
|
||||
@@ -19,8 +19,10 @@ void main() {
|
||||
int tmp2_;
|
||||
tmp1_ = (int(vertex_index) / 2);
|
||||
tmp2_ = (int(vertex_index) & 1);
|
||||
vec4 _expr24 = vec4(((float(tmp1_) * 4.0) - 1.0), ((float(tmp2_) * 4.0) - 1.0), 0.0, 1.0);
|
||||
VertexOutput _tmp_return = VertexOutput(_expr24, (transpose(mat3x3(_group_0_binding_0.view[0].xyz, _group_0_binding_0.view[1].xyz, _group_0_binding_0.view[2].xyz)) * (_group_0_binding_0.proj_inv * _expr24).xyz));
|
||||
vec4 pos = vec4(((float(tmp1_) * 4.0) - 1.0), ((float(tmp2_) * 4.0) - 1.0), 0.0, 1.0);
|
||||
mat3x3 inv_model_view = transpose(mat3x3(_group_0_binding_0.view[0].xyz, _group_0_binding_0.view[1].xyz, _group_0_binding_0.view[2].xyz));
|
||||
vec4 unprojected = (_group_0_binding_0.proj_inv * pos);
|
||||
VertexOutput _tmp_return = VertexOutput(pos, (inv_model_view * unprojected.xyz));
|
||||
gl_Position = _tmp_return.position;
|
||||
_vs2fs_location0 = _tmp_return.uv;
|
||||
return;
|
||||
|
||||
@@ -23,8 +23,10 @@ fn vs_main([[builtin(vertex_index)]] vertex_index: u32) -> VertexOutput {
|
||||
|
||||
tmp1_ = (i32(vertex_index) / 2);
|
||||
tmp2_ = (i32(vertex_index) & 1);
|
||||
let _e24: vec4<f32> = vec4<f32>(((f32(tmp1_) * 4.0) - 1.0), ((f32(tmp2_) * 4.0) - 1.0), 0.0, 1.0);
|
||||
return VertexOutput(_e24, (transpose(mat3x3<f32>(r_data.view[0].xyz, r_data.view[1].xyz, r_data.view[2].xyz)) * (r_data.proj_inv * _e24).xyz));
|
||||
let pos: vec4<f32> = vec4<f32>(((f32(tmp1_) * 4.0) - 1.0), ((f32(tmp2_) * 4.0) - 1.0), 0.0, 1.0);
|
||||
let inv_model_view: mat3x3<f32> = transpose(mat3x3<f32>(r_data.view[0].xyz, r_data.view[1].xyz, r_data.view[2].xyz));
|
||||
let unprojected: vec4<f32> = (r_data.proj_inv * pos);
|
||||
return VertexOutput(pos, (inv_model_view * unprojected.xyz));
|
||||
}
|
||||
|
||||
[[stage(fragment)]]
|
||||
|
||||
@@ -6,10 +6,10 @@ layout(location = 0) out vec4 _fs2p_location0;
|
||||
|
||||
void main() {
|
||||
vec4 foo = gl_FragCoord;
|
||||
vec4 _expr1 = dFdx(foo);
|
||||
vec4 _expr2 = dFdy(foo);
|
||||
vec4 _expr3 = fwidth(foo);
|
||||
_fs2p_location0 = ((_expr1 + _expr2) * _expr3);
|
||||
vec4 x = dFdx(foo);
|
||||
vec4 y = dFdy(foo);
|
||||
vec4 z = fwidth(foo);
|
||||
_fs2p_location0 = ((x + y) * z);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[[stage(fragment)]]
|
||||
fn derivatives([[builtin(position)]] foo: vec4<f32>) -> [[location(0)]] vec4<f32> {
|
||||
let _e1: vec4<f32> = dpdx(foo);
|
||||
let _e2: vec4<f32> = dpdy(foo);
|
||||
let _e3: vec4<f32> = fwidth(foo);
|
||||
return ((_e1 + _e2) * _e3);
|
||||
let x: vec4<f32> = dpdx(foo);
|
||||
let y: vec4<f32> = dpdy(foo);
|
||||
let z: vec4<f32> = fwidth(foo);
|
||||
return ((x + y) * z);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user