mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +00:00
[naga wgsl] Implement local const
declarations (#6156)
This commit is contained in:
parent
4454cbfaab
commit
34bb9e4ceb
@ -47,7 +47,7 @@ pub use features::Features;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
back::{self, Baked},
|
back::{self, Baked},
|
||||||
proc::{self, NameKey},
|
proc::{self, ExpressionKindTracker, NameKey},
|
||||||
valid, Handle, ShaderStage, TypeInner,
|
valid, Handle, ShaderStage, TypeInner,
|
||||||
};
|
};
|
||||||
use features::FeaturesManager;
|
use features::FeaturesManager;
|
||||||
@ -1584,6 +1584,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||||||
info,
|
info,
|
||||||
expressions: &func.expressions,
|
expressions: &func.expressions,
|
||||||
named_expressions: &func.named_expressions,
|
named_expressions: &func.named_expressions,
|
||||||
|
expr_kind_tracker: ExpressionKindTracker::from_arena(&func.expressions),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.named_expressions.clear();
|
self.named_expressions.clear();
|
||||||
|
@ -8,7 +8,7 @@ use super::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
back::{self, Baked},
|
back::{self, Baked},
|
||||||
proc::{self, NameKey},
|
proc::{self, ExpressionKindTracker, NameKey},
|
||||||
valid, Handle, Module, Scalar, ScalarKind, ShaderStage, TypeInner,
|
valid, Handle, Module, Scalar, ScalarKind, ShaderStage, TypeInner,
|
||||||
};
|
};
|
||||||
use std::{fmt, mem};
|
use std::{fmt, mem};
|
||||||
@ -346,6 +346,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||||||
info,
|
info,
|
||||||
expressions: &function.expressions,
|
expressions: &function.expressions,
|
||||||
named_expressions: &function.named_expressions,
|
named_expressions: &function.named_expressions,
|
||||||
|
expr_kind_tracker: ExpressionKindTracker::from_arena(&function.expressions),
|
||||||
};
|
};
|
||||||
let name = self.names[&NameKey::Function(handle)].clone();
|
let name = self.names[&NameKey::Function(handle)].clone();
|
||||||
|
|
||||||
@ -386,6 +387,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||||||
info,
|
info,
|
||||||
expressions: &ep.function.expressions,
|
expressions: &ep.function.expressions,
|
||||||
named_expressions: &ep.function.named_expressions,
|
named_expressions: &ep.function.named_expressions,
|
||||||
|
expr_kind_tracker: ExpressionKindTracker::from_arena(&ep.function.expressions),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.write_wrapped_functions(module, &ctx)?;
|
self.write_wrapped_functions(module, &ctx)?;
|
||||||
|
@ -3,6 +3,8 @@ Backend functions that export shader [`Module`](super::Module)s into binary and
|
|||||||
*/
|
*/
|
||||||
#![allow(dead_code)] // can be dead if none of the enabled backends need it
|
#![allow(dead_code)] // can be dead if none of the enabled backends need it
|
||||||
|
|
||||||
|
use crate::proc::ExpressionKindTracker;
|
||||||
|
|
||||||
#[cfg(dot_out)]
|
#[cfg(dot_out)]
|
||||||
pub mod dot;
|
pub mod dot;
|
||||||
#[cfg(glsl_out)]
|
#[cfg(glsl_out)]
|
||||||
@ -118,6 +120,8 @@ pub struct FunctionCtx<'a> {
|
|||||||
pub expressions: &'a crate::Arena<crate::Expression>,
|
pub expressions: &'a crate::Arena<crate::Expression>,
|
||||||
/// Map of expressions that have associated variable names
|
/// Map of expressions that have associated variable names
|
||||||
pub named_expressions: &'a crate::NamedExpressions,
|
pub named_expressions: &'a crate::NamedExpressions,
|
||||||
|
/// For constness checks
|
||||||
|
pub expr_kind_tracker: ExpressionKindTracker,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionCtx<'_> {
|
impl FunctionCtx<'_> {
|
||||||
|
@ -289,6 +289,7 @@ fn process_function(
|
|||||||
&mut local_expression_kind_tracker,
|
&mut local_expression_kind_tracker,
|
||||||
&mut emitter,
|
&mut emitter,
|
||||||
&mut block,
|
&mut block,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
for (old_h, mut expr, span) in expressions.drain() {
|
for (old_h, mut expr, span) in expressions.drain() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::Error;
|
use super::Error;
|
||||||
use crate::{
|
use crate::{
|
||||||
back::{self, Baked},
|
back::{self, Baked},
|
||||||
proc::{self, NameKey},
|
proc::{self, ExpressionKindTracker, NameKey},
|
||||||
valid, Handle, Module, ShaderStage, TypeInner,
|
valid, Handle, Module, ShaderStage, TypeInner,
|
||||||
};
|
};
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
@ -166,6 +166,7 @@ impl<W: Write> Writer<W> {
|
|||||||
info: fun_info,
|
info: fun_info,
|
||||||
expressions: &function.expressions,
|
expressions: &function.expressions,
|
||||||
named_expressions: &function.named_expressions,
|
named_expressions: &function.named_expressions,
|
||||||
|
expr_kind_tracker: ExpressionKindTracker::from_arena(&function.expressions),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Write the function
|
// Write the function
|
||||||
@ -193,6 +194,7 @@ impl<W: Write> Writer<W> {
|
|||||||
info: info.get_entry_point(index),
|
info: info.get_entry_point(index),
|
||||||
expressions: &ep.function.expressions,
|
expressions: &ep.function.expressions,
|
||||||
named_expressions: &ep.function.named_expressions,
|
named_expressions: &ep.function.named_expressions,
|
||||||
|
expr_kind_tracker: ExpressionKindTracker::from_arena(&ep.function.expressions),
|
||||||
};
|
};
|
||||||
self.write_function(module, &ep.function, &func_ctx)?;
|
self.write_function(module, &ep.function, &func_ctx)?;
|
||||||
|
|
||||||
@ -1115,8 +1117,14 @@ impl<W: Write> Writer<W> {
|
|||||||
func_ctx: &back::FunctionCtx,
|
func_ctx: &back::FunctionCtx,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> BackendResult {
|
) -> BackendResult {
|
||||||
|
// Some functions are marked as const, but are not yet implemented as constant expression
|
||||||
|
let quantifier = if func_ctx.expr_kind_tracker.is_impl_const(handle) {
|
||||||
|
"const"
|
||||||
|
} else {
|
||||||
|
"let"
|
||||||
|
};
|
||||||
// Write variable name
|
// Write variable name
|
||||||
write!(self.out, "let {name}")?;
|
write!(self.out, "{quantifier} {name}")?;
|
||||||
if self.flags.contains(WriterFlags::EXPLICIT_TYPES) {
|
if self.flags.contains(WriterFlags::EXPLICIT_TYPES) {
|
||||||
write!(self.out, ": ")?;
|
write!(self.out, ": ")?;
|
||||||
let ty = &func_ctx.info[handle].ty;
|
let ty = &func_ctx.info[handle].ty;
|
||||||
|
@ -98,7 +98,7 @@ impl<'source> GlobalContext<'source, '_, '_> {
|
|||||||
types: self.types,
|
types: self.types,
|
||||||
module: self.module,
|
module: self.module,
|
||||||
const_typifier: self.const_typifier,
|
const_typifier: self.const_typifier,
|
||||||
expr_type: ExpressionContextType::Constant,
|
expr_type: ExpressionContextType::Constant(None),
|
||||||
global_expression_kind_tracker: self.global_expression_kind_tracker,
|
global_expression_kind_tracker: self.global_expression_kind_tracker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,7 +160,8 @@ pub struct StatementContext<'source, 'temp, 'out> {
|
|||||||
///
|
///
|
||||||
/// [`LocalVariable`]: crate::Expression::LocalVariable
|
/// [`LocalVariable`]: crate::Expression::LocalVariable
|
||||||
/// [`FunctionArgument`]: crate::Expression::FunctionArgument
|
/// [`FunctionArgument`]: crate::Expression::FunctionArgument
|
||||||
local_table: &'temp mut FastHashMap<Handle<ast::Local>, Typed<Handle<crate::Expression>>>,
|
local_table:
|
||||||
|
&'temp mut FastHashMap<Handle<ast::Local>, Declared<Typed<Handle<crate::Expression>>>>,
|
||||||
|
|
||||||
const_typifier: &'temp mut Typifier,
|
const_typifier: &'temp mut Typifier,
|
||||||
typifier: &'temp mut Typifier,
|
typifier: &'temp mut Typifier,
|
||||||
@ -184,6 +185,32 @@ pub struct StatementContext<'source, 'temp, 'out> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'temp> StatementContext<'a, 'temp, '_> {
|
impl<'a, 'temp> StatementContext<'a, 'temp, '_> {
|
||||||
|
fn as_const<'t>(
|
||||||
|
&'t mut self,
|
||||||
|
block: &'t mut crate::Block,
|
||||||
|
emitter: &'t mut Emitter,
|
||||||
|
) -> ExpressionContext<'a, 't, '_>
|
||||||
|
where
|
||||||
|
'temp: 't,
|
||||||
|
{
|
||||||
|
ExpressionContext {
|
||||||
|
globals: self.globals,
|
||||||
|
types: self.types,
|
||||||
|
ast_expressions: self.ast_expressions,
|
||||||
|
const_typifier: self.const_typifier,
|
||||||
|
global_expression_kind_tracker: self.global_expression_kind_tracker,
|
||||||
|
module: self.module,
|
||||||
|
expr_type: ExpressionContextType::Constant(Some(LocalExpressionContext {
|
||||||
|
local_table: self.local_table,
|
||||||
|
function: self.function,
|
||||||
|
block,
|
||||||
|
emitter,
|
||||||
|
typifier: self.typifier,
|
||||||
|
local_expression_kind_tracker: self.local_expression_kind_tracker,
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn as_expression<'t>(
|
fn as_expression<'t>(
|
||||||
&'t mut self,
|
&'t mut self,
|
||||||
block: &'t mut crate::Block,
|
block: &'t mut crate::Block,
|
||||||
@ -199,7 +226,7 @@ impl<'a, 'temp> StatementContext<'a, 'temp, '_> {
|
|||||||
const_typifier: self.const_typifier,
|
const_typifier: self.const_typifier,
|
||||||
global_expression_kind_tracker: self.global_expression_kind_tracker,
|
global_expression_kind_tracker: self.global_expression_kind_tracker,
|
||||||
module: self.module,
|
module: self.module,
|
||||||
expr_type: ExpressionContextType::Runtime(RuntimeExpressionContext {
|
expr_type: ExpressionContextType::Runtime(LocalExpressionContext {
|
||||||
local_table: self.local_table,
|
local_table: self.local_table,
|
||||||
function: self.function,
|
function: self.function,
|
||||||
block,
|
block,
|
||||||
@ -235,12 +262,12 @@ impl<'a, 'temp> StatementContext<'a, 'temp, '_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RuntimeExpressionContext<'temp, 'out> {
|
pub struct LocalExpressionContext<'temp, 'out> {
|
||||||
/// A map from [`ast::Local`] handles to the Naga expressions we've built for them.
|
/// A map from [`ast::Local`] handles to the Naga expressions we've built for them.
|
||||||
///
|
///
|
||||||
/// This is always [`StatementContext::local_table`] for the
|
/// This is always [`StatementContext::local_table`] for the
|
||||||
/// enclosing statement; see that documentation for details.
|
/// enclosing statement; see that documentation for details.
|
||||||
local_table: &'temp FastHashMap<Handle<ast::Local>, Typed<Handle<crate::Expression>>>,
|
local_table: &'temp FastHashMap<Handle<ast::Local>, Declared<Typed<Handle<crate::Expression>>>>,
|
||||||
|
|
||||||
function: &'out mut crate::Function,
|
function: &'out mut crate::Function,
|
||||||
block: &'temp mut crate::Block,
|
block: &'temp mut crate::Block,
|
||||||
@ -262,15 +289,15 @@ pub enum ExpressionContextType<'temp, 'out> {
|
|||||||
/// The given [`RuntimeExpressionContext`] holds information about local
|
/// The given [`RuntimeExpressionContext`] holds information about local
|
||||||
/// variables, arguments, and other definitions available only to runtime
|
/// variables, arguments, and other definitions available only to runtime
|
||||||
/// expressions, not constant or override expressions.
|
/// expressions, not constant or override expressions.
|
||||||
Runtime(RuntimeExpressionContext<'temp, 'out>),
|
Runtime(LocalExpressionContext<'temp, 'out>),
|
||||||
|
|
||||||
/// We are lowering to a constant expression, to be included in the module's
|
/// We are lowering to a constant expression, to be included in the module's
|
||||||
/// constant expression arena.
|
/// constant expression arena.
|
||||||
///
|
///
|
||||||
/// Everything constant expressions are allowed to refer to is
|
/// Everything global constant expressions are allowed to refer to is
|
||||||
/// available in the [`ExpressionContext`], so this variant
|
/// available in the [`ExpressionContext`], but local constant expressions can
|
||||||
/// carries no further information.
|
/// also refer to other
|
||||||
Constant,
|
Constant(Option<LocalExpressionContext<'temp, 'out>>),
|
||||||
|
|
||||||
/// We are lowering to an override expression, to be included in the module's
|
/// We are lowering to an override expression, to be included in the module's
|
||||||
/// constant expression arena.
|
/// constant expression arena.
|
||||||
@ -352,7 +379,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
|
|||||||
ast_expressions: self.ast_expressions,
|
ast_expressions: self.ast_expressions,
|
||||||
const_typifier: self.const_typifier,
|
const_typifier: self.const_typifier,
|
||||||
module: self.module,
|
module: self.module,
|
||||||
expr_type: ExpressionContextType::Constant,
|
expr_type: ExpressionContextType::Constant(None),
|
||||||
global_expression_kind_tracker: self.global_expression_kind_tracker,
|
global_expression_kind_tracker: self.global_expression_kind_tracker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -376,8 +403,19 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
|
|||||||
rctx.local_expression_kind_tracker,
|
rctx.local_expression_kind_tracker,
|
||||||
rctx.emitter,
|
rctx.emitter,
|
||||||
rctx.block,
|
rctx.block,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
ExpressionContextType::Constant => ConstantEvaluator::for_wgsl_module(
|
ExpressionContextType::Constant(Some(ref mut rctx)) => {
|
||||||
|
ConstantEvaluator::for_wgsl_function(
|
||||||
|
self.module,
|
||||||
|
&mut rctx.function.expressions,
|
||||||
|
rctx.local_expression_kind_tracker,
|
||||||
|
rctx.emitter,
|
||||||
|
rctx.block,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ExpressionContextType::Constant(None) => ConstantEvaluator::for_wgsl_module(
|
||||||
self.module,
|
self.module,
|
||||||
self.global_expression_kind_tracker,
|
self.global_expression_kind_tracker,
|
||||||
false,
|
false,
|
||||||
@ -412,15 +450,27 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
|
|||||||
.eval_expr_to_u32_from(handle, &ctx.function.expressions)
|
.eval_expr_to_u32_from(handle, &ctx.function.expressions)
|
||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
ExpressionContextType::Constant => self.module.to_ctx().eval_expr_to_u32(handle).ok(),
|
ExpressionContextType::Constant(Some(ref ctx)) => {
|
||||||
|
assert!(ctx.local_expression_kind_tracker.is_const(handle));
|
||||||
|
self.module
|
||||||
|
.to_ctx()
|
||||||
|
.eval_expr_to_u32_from(handle, &ctx.function.expressions)
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
ExpressionContextType::Constant(None) => {
|
||||||
|
self.module.to_ctx().eval_expr_to_u32(handle).ok()
|
||||||
|
}
|
||||||
ExpressionContextType::Override => None,
|
ExpressionContextType::Override => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_expression_span(&self, handle: Handle<crate::Expression>) -> Span {
|
fn get_expression_span(&self, handle: Handle<crate::Expression>) -> Span {
|
||||||
match self.expr_type {
|
match self.expr_type {
|
||||||
ExpressionContextType::Runtime(ref ctx) => ctx.function.expressions.get_span(handle),
|
ExpressionContextType::Runtime(ref ctx)
|
||||||
ExpressionContextType::Constant | ExpressionContextType::Override => {
|
| ExpressionContextType::Constant(Some(ref ctx)) => {
|
||||||
|
ctx.function.expressions.get_span(handle)
|
||||||
|
}
|
||||||
|
ExpressionContextType::Constant(None) | ExpressionContextType::Override => {
|
||||||
self.module.global_expressions.get_span(handle)
|
self.module.global_expressions.get_span(handle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -428,20 +478,35 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
|
|||||||
|
|
||||||
fn typifier(&self) -> &Typifier {
|
fn typifier(&self) -> &Typifier {
|
||||||
match self.expr_type {
|
match self.expr_type {
|
||||||
ExpressionContextType::Runtime(ref ctx) => ctx.typifier,
|
ExpressionContextType::Runtime(ref ctx)
|
||||||
ExpressionContextType::Constant | ExpressionContextType::Override => {
|
| ExpressionContextType::Constant(Some(ref ctx)) => ctx.typifier,
|
||||||
|
ExpressionContextType::Constant(None) | ExpressionContextType::Override => {
|
||||||
self.const_typifier
|
self.const_typifier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn local(
|
||||||
|
&mut self,
|
||||||
|
local: &Handle<ast::Local>,
|
||||||
|
span: Span,
|
||||||
|
) -> Result<Typed<Handle<crate::Expression>>, Error<'source>> {
|
||||||
|
match self.expr_type {
|
||||||
|
ExpressionContextType::Runtime(ref ctx) => Ok(ctx.local_table[local].runtime()),
|
||||||
|
ExpressionContextType::Constant(Some(ref ctx)) => ctx.local_table[local]
|
||||||
|
.const_time()
|
||||||
|
.ok_or(Error::UnexpectedOperationInConstContext(span)),
|
||||||
|
_ => Err(Error::UnexpectedOperationInConstContext(span)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn runtime_expression_ctx(
|
fn runtime_expression_ctx(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<&mut RuntimeExpressionContext<'temp, 'out>, Error<'source>> {
|
) -> Result<&mut LocalExpressionContext<'temp, 'out>, Error<'source>> {
|
||||||
match self.expr_type {
|
match self.expr_type {
|
||||||
ExpressionContextType::Runtime(ref mut ctx) => Ok(ctx),
|
ExpressionContextType::Runtime(ref mut ctx) => Ok(ctx),
|
||||||
ExpressionContextType::Constant | ExpressionContextType::Override => {
|
ExpressionContextType::Constant(_) | ExpressionContextType::Override => {
|
||||||
Err(Error::UnexpectedOperationInConstContext(span))
|
Err(Error::UnexpectedOperationInConstContext(span))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -480,7 +545,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
|
|||||||
}
|
}
|
||||||
// This means a `gather` operation appeared in a constant expression.
|
// This means a `gather` operation appeared in a constant expression.
|
||||||
// This error refers to the `gather` itself, not its "component" argument.
|
// This error refers to the `gather` itself, not its "component" argument.
|
||||||
ExpressionContextType::Constant | ExpressionContextType::Override => {
|
ExpressionContextType::Constant(_) | ExpressionContextType::Override => {
|
||||||
Err(Error::UnexpectedOperationInConstContext(gather_span))
|
Err(Error::UnexpectedOperationInConstContext(gather_span))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -505,8 +570,9 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
|
|||||||
// except that this lets the borrow checker see that it's okay
|
// except that this lets the borrow checker see that it's okay
|
||||||
// to also borrow self.module.types mutably below.
|
// to also borrow self.module.types mutably below.
|
||||||
let typifier = match self.expr_type {
|
let typifier = match self.expr_type {
|
||||||
ExpressionContextType::Runtime(ref ctx) => ctx.typifier,
|
ExpressionContextType::Runtime(ref ctx)
|
||||||
ExpressionContextType::Constant | ExpressionContextType::Override => {
|
| ExpressionContextType::Constant(Some(ref ctx)) => ctx.typifier,
|
||||||
|
ExpressionContextType::Constant(None) | ExpressionContextType::Override => {
|
||||||
&*self.const_typifier
|
&*self.const_typifier
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -542,7 +608,8 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
|
|||||||
let typifier;
|
let typifier;
|
||||||
let expressions;
|
let expressions;
|
||||||
match self.expr_type {
|
match self.expr_type {
|
||||||
ExpressionContextType::Runtime(ref mut ctx) => {
|
ExpressionContextType::Runtime(ref mut ctx)
|
||||||
|
| ExpressionContextType::Constant(Some(ref mut ctx)) => {
|
||||||
resolve_ctx = ResolveContext::with_locals(
|
resolve_ctx = ResolveContext::with_locals(
|
||||||
self.module,
|
self.module,
|
||||||
&ctx.function.local_variables,
|
&ctx.function.local_variables,
|
||||||
@ -551,7 +618,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
|
|||||||
typifier = &mut *ctx.typifier;
|
typifier = &mut *ctx.typifier;
|
||||||
expressions = &ctx.function.expressions;
|
expressions = &ctx.function.expressions;
|
||||||
}
|
}
|
||||||
ExpressionContextType::Constant | ExpressionContextType::Override => {
|
ExpressionContextType::Constant(None) | ExpressionContextType::Override => {
|
||||||
resolve_ctx = ResolveContext::with_locals(self.module, &empty_arena, &[]);
|
resolve_ctx = ResolveContext::with_locals(self.module, &empty_arena, &[]);
|
||||||
typifier = self.const_typifier;
|
typifier = self.const_typifier;
|
||||||
expressions = &self.module.global_expressions;
|
expressions = &self.module.global_expressions;
|
||||||
@ -643,18 +710,20 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<Handle<crate::Expression>, Error<'source>> {
|
) -> Result<Handle<crate::Expression>, Error<'source>> {
|
||||||
match self.expr_type {
|
match self.expr_type {
|
||||||
ExpressionContextType::Runtime(ref mut rctx) => {
|
ExpressionContextType::Runtime(ref mut rctx)
|
||||||
|
| ExpressionContextType::Constant(Some(ref mut rctx)) => {
|
||||||
rctx.block
|
rctx.block
|
||||||
.extend(rctx.emitter.finish(&rctx.function.expressions));
|
.extend(rctx.emitter.finish(&rctx.function.expressions));
|
||||||
}
|
}
|
||||||
ExpressionContextType::Constant | ExpressionContextType::Override => {}
|
ExpressionContextType::Constant(None) | ExpressionContextType::Override => {}
|
||||||
}
|
}
|
||||||
let result = self.append_expression(expression, span);
|
let result = self.append_expression(expression, span);
|
||||||
match self.expr_type {
|
match self.expr_type {
|
||||||
ExpressionContextType::Runtime(ref mut rctx) => {
|
ExpressionContextType::Runtime(ref mut rctx)
|
||||||
|
| ExpressionContextType::Constant(Some(ref mut rctx)) => {
|
||||||
rctx.emitter.start(&rctx.function.expressions);
|
rctx.emitter.start(&rctx.function.expressions);
|
||||||
}
|
}
|
||||||
ExpressionContextType::Constant | ExpressionContextType::Override => {}
|
ExpressionContextType::Constant(None) | ExpressionContextType::Override => {}
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
@ -718,6 +787,30 @@ impl<'source> ArgumentContext<'_, 'source> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
enum Declared<T> {
|
||||||
|
/// Value declared as const
|
||||||
|
Const(T),
|
||||||
|
|
||||||
|
/// Value declared as non-const
|
||||||
|
Runtime(T),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Declared<T> {
|
||||||
|
fn runtime(self) -> T {
|
||||||
|
match self {
|
||||||
|
Declared::Const(t) | Declared::Runtime(t) => t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn const_time(self) -> Option<T> {
|
||||||
|
match self {
|
||||||
|
Declared::Const(t) => Some(t),
|
||||||
|
Declared::Runtime(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// WGSL type annotations on expressions, types, values, etc.
|
/// WGSL type annotations on expressions, types, values, etc.
|
||||||
///
|
///
|
||||||
/// Naga and WGSL types are very close, but Naga lacks WGSL's `ref` types, which
|
/// Naga and WGSL types are very close, but Naga lacks WGSL's `ref` types, which
|
||||||
@ -1120,7 +1213,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||||||
let ty = self.resolve_ast_type(arg.ty, ctx)?;
|
let ty = self.resolve_ast_type(arg.ty, ctx)?;
|
||||||
let expr = expressions
|
let expr = expressions
|
||||||
.append(crate::Expression::FunctionArgument(i as u32), arg.name.span);
|
.append(crate::Expression::FunctionArgument(i as u32), arg.name.span);
|
||||||
local_table.insert(arg.handle, Typed::Plain(expr));
|
local_table.insert(arg.handle, Declared::Runtime(Typed::Plain(expr)));
|
||||||
named_expressions.insert(expr, (arg.name.name.to_string(), arg.name.span));
|
named_expressions.insert(expr, (arg.name.name.to_string(), arg.name.span));
|
||||||
local_expression_kind_tracker.insert(expr, crate::proc::ExpressionKind::Runtime);
|
local_expression_kind_tracker.insert(expr, crate::proc::ExpressionKind::Runtime);
|
||||||
|
|
||||||
@ -1268,7 +1361,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
block.extend(emitter.finish(&ctx.function.expressions));
|
block.extend(emitter.finish(&ctx.function.expressions));
|
||||||
ctx.local_table.insert(l.handle, Typed::Plain(value));
|
ctx.local_table
|
||||||
|
.insert(l.handle, Declared::Runtime(Typed::Plain(value)));
|
||||||
ctx.named_expressions
|
ctx.named_expressions
|
||||||
.insert(value, (l.name.name.to_string(), l.name.span));
|
.insert(value, (l.name.name.to_string(), l.name.span));
|
||||||
|
|
||||||
@ -1350,7 +1444,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||||||
Span::UNDEFINED,
|
Span::UNDEFINED,
|
||||||
)?;
|
)?;
|
||||||
block.extend(emitter.finish(&ctx.function.expressions));
|
block.extend(emitter.finish(&ctx.function.expressions));
|
||||||
ctx.local_table.insert(v.handle, Typed::Reference(handle));
|
ctx.local_table
|
||||||
|
.insert(v.handle, Declared::Runtime(Typed::Reference(handle)));
|
||||||
|
|
||||||
match initializer {
|
match initializer {
|
||||||
Some(initializer) => crate::Statement::Store {
|
Some(initializer) => crate::Statement::Store {
|
||||||
@ -1360,6 +1455,41 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast::LocalDecl::Const(ref c) => {
|
||||||
|
let mut emitter = Emitter::default();
|
||||||
|
emitter.start(&ctx.function.expressions);
|
||||||
|
|
||||||
|
let ectx = &mut ctx.as_const(block, &mut emitter);
|
||||||
|
|
||||||
|
let mut init = self.expression_for_abstract(c.init, ectx)?;
|
||||||
|
|
||||||
|
if let Some(explicit_ty) = c.ty {
|
||||||
|
let explicit_ty =
|
||||||
|
self.resolve_ast_type(explicit_ty, &mut ectx.as_global())?;
|
||||||
|
let explicit_ty_res = crate::proc::TypeResolution::Handle(explicit_ty);
|
||||||
|
init = ectx
|
||||||
|
.try_automatic_conversions(init, &explicit_ty_res, c.name.span)
|
||||||
|
.map_err(|error| match error {
|
||||||
|
Error::AutoConversion(error) => Error::InitializationTypeMismatch {
|
||||||
|
name: c.name.span,
|
||||||
|
expected: error.dest_type,
|
||||||
|
got: error.source_type,
|
||||||
|
},
|
||||||
|
other => other,
|
||||||
|
})?;
|
||||||
|
} else {
|
||||||
|
init = ectx.concretize(init)?;
|
||||||
|
ectx.register_type(init)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
block.extend(emitter.finish(&ctx.function.expressions));
|
||||||
|
ctx.local_table
|
||||||
|
.insert(c.handle, Declared::Const(Typed::Plain(init)));
|
||||||
|
ctx.named_expressions
|
||||||
|
.insert(init, (c.name.name.to_string(), c.name.span));
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ast::StatementKind::If {
|
ast::StatementKind::If {
|
||||||
condition,
|
condition,
|
||||||
@ -1658,8 +1788,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||||||
return Ok(Typed::Plain(handle));
|
return Ok(Typed::Plain(handle));
|
||||||
}
|
}
|
||||||
ast::Expression::Ident(ast::IdentExpr::Local(local)) => {
|
ast::Expression::Ident(ast::IdentExpr::Local(local)) => {
|
||||||
let rctx = ctx.runtime_expression_ctx(span)?;
|
return ctx.local(&local, span);
|
||||||
return Ok(rctx.local_table[&local]);
|
|
||||||
}
|
}
|
||||||
ast::Expression::Ident(ast::IdentExpr::Unresolved(name)) => {
|
ast::Expression::Ident(ast::IdentExpr::Unresolved(name)) => {
|
||||||
let global = ctx
|
let global = ctx
|
||||||
|
@ -109,7 +109,7 @@ pub struct EntryPoint<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(doc)]
|
#[cfg(doc)]
|
||||||
use crate::front::wgsl::lower::{RuntimeExpressionContext, StatementContext};
|
use crate::front::wgsl::lower::{LocalExpressionContext, StatementContext};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Function<'a> {
|
pub struct Function<'a> {
|
||||||
@ -460,10 +460,19 @@ pub struct Let<'a> {
|
|||||||
pub handle: Handle<Local>,
|
pub handle: Handle<Local>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LocalConst<'a> {
|
||||||
|
pub name: Ident<'a>,
|
||||||
|
pub ty: Option<Handle<Type<'a>>>,
|
||||||
|
pub init: Handle<Expression<'a>>,
|
||||||
|
pub handle: Handle<Local>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum LocalDecl<'a> {
|
pub enum LocalDecl<'a> {
|
||||||
Var(LocalVariable<'a>),
|
Var(LocalVariable<'a>),
|
||||||
Let(Let<'a>),
|
Let(Let<'a>),
|
||||||
|
Const(LocalConst<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -1688,6 +1688,28 @@ impl Parser {
|
|||||||
handle,
|
handle,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
"const" => {
|
||||||
|
let _ = lexer.next();
|
||||||
|
let name = lexer.next_ident()?;
|
||||||
|
|
||||||
|
let given_ty = if lexer.skip(Token::Separator(':')) {
|
||||||
|
let ty = self.type_decl(lexer, ctx)?;
|
||||||
|
Some(ty)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
lexer.expect(Token::Operation('='))?;
|
||||||
|
let expr_id = self.general_expression(lexer, ctx)?;
|
||||||
|
lexer.expect(Token::Separator(';'))?;
|
||||||
|
|
||||||
|
let handle = ctx.declare_local(name)?;
|
||||||
|
ast::StatementKind::LocalDecl(ast::LocalDecl::Const(ast::LocalConst {
|
||||||
|
name,
|
||||||
|
ty: given_ty,
|
||||||
|
init: expr_id,
|
||||||
|
handle,
|
||||||
|
}))
|
||||||
|
}
|
||||||
"var" => {
|
"var" => {
|
||||||
let _ = lexer.next();
|
let _ = lexer.next();
|
||||||
|
|
||||||
|
@ -317,7 +317,7 @@ pub struct ConstantEvaluator<'a> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum WgslRestrictions<'a> {
|
enum WgslRestrictions<'a> {
|
||||||
/// - const-expressions will be evaluated and inserted in the arena
|
/// - const-expressions will be evaluated and inserted in the arena
|
||||||
Const,
|
Const(Option<FunctionLocalData<'a>>),
|
||||||
/// - const-expressions will be evaluated and inserted in the arena
|
/// - const-expressions will be evaluated and inserted in the arena
|
||||||
/// - override-expressions will be inserted in the arena
|
/// - override-expressions will be inserted in the arena
|
||||||
Override,
|
Override,
|
||||||
@ -347,6 +347,8 @@ struct FunctionLocalData<'a> {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||||
pub enum ExpressionKind {
|
pub enum ExpressionKind {
|
||||||
|
/// If const is also implemented as const
|
||||||
|
ImplConst,
|
||||||
Const,
|
Const,
|
||||||
Override,
|
Override,
|
||||||
Runtime,
|
Runtime,
|
||||||
@ -372,14 +374,23 @@ impl ExpressionKindTracker {
|
|||||||
pub fn insert(&mut self, value: Handle<Expression>, expr_type: ExpressionKind) {
|
pub fn insert(&mut self, value: Handle<Expression>, expr_type: ExpressionKind) {
|
||||||
self.inner.insert(value, expr_type);
|
self.inner.insert(value, expr_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_const(&self, h: Handle<Expression>) -> bool {
|
pub fn is_const(&self, h: Handle<Expression>) -> bool {
|
||||||
matches!(self.type_of(h), ExpressionKind::Const)
|
matches!(
|
||||||
|
self.type_of(h),
|
||||||
|
ExpressionKind::Const | ExpressionKind::ImplConst
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if naga can also evaluate expression as const
|
||||||
|
pub fn is_impl_const(&self, h: Handle<Expression>) -> bool {
|
||||||
|
matches!(self.type_of(h), ExpressionKind::ImplConst)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_const_or_override(&self, h: Handle<Expression>) -> bool {
|
pub fn is_const_or_override(&self, h: Handle<Expression>) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
self.type_of(h),
|
self.type_of(h),
|
||||||
ExpressionKind::Const | ExpressionKind::Override
|
ExpressionKind::Const | ExpressionKind::Override | ExpressionKind::ImplConst
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,13 +411,14 @@ impl ExpressionKindTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn type_of_with_expr(&self, expr: &Expression) -> ExpressionKind {
|
fn type_of_with_expr(&self, expr: &Expression) -> ExpressionKind {
|
||||||
|
use crate::MathFunction as Mf;
|
||||||
match *expr {
|
match *expr {
|
||||||
Expression::Literal(_) | Expression::ZeroValue(_) | Expression::Constant(_) => {
|
Expression::Literal(_) | Expression::ZeroValue(_) | Expression::Constant(_) => {
|
||||||
ExpressionKind::Const
|
ExpressionKind::ImplConst
|
||||||
}
|
}
|
||||||
Expression::Override(_) => ExpressionKind::Override,
|
Expression::Override(_) => ExpressionKind::Override,
|
||||||
Expression::Compose { ref components, .. } => {
|
Expression::Compose { ref components, .. } => {
|
||||||
let mut expr_type = ExpressionKind::Const;
|
let mut expr_type = ExpressionKind::ImplConst;
|
||||||
for component in components {
|
for component in components {
|
||||||
expr_type = expr_type.max(self.type_of(*component))
|
expr_type = expr_type.max(self.type_of(*component))
|
||||||
}
|
}
|
||||||
@ -417,13 +429,16 @@ impl ExpressionKindTracker {
|
|||||||
Expression::Access { base, index } => self.type_of(base).max(self.type_of(index)),
|
Expression::Access { base, index } => self.type_of(base).max(self.type_of(index)),
|
||||||
Expression::Swizzle { vector, .. } => self.type_of(vector),
|
Expression::Swizzle { vector, .. } => self.type_of(vector),
|
||||||
Expression::Unary { expr, .. } => self.type_of(expr),
|
Expression::Unary { expr, .. } => self.type_of(expr),
|
||||||
Expression::Binary { left, right, .. } => self.type_of(left).max(self.type_of(right)),
|
Expression::Binary { left, right, .. } => self
|
||||||
|
.type_of(left)
|
||||||
|
.max(self.type_of(right))
|
||||||
|
.max(ExpressionKind::Const),
|
||||||
Expression::Math {
|
Expression::Math {
|
||||||
|
fun,
|
||||||
arg,
|
arg,
|
||||||
arg1,
|
arg1,
|
||||||
arg2,
|
arg2,
|
||||||
arg3,
|
arg3,
|
||||||
..
|
|
||||||
} => self
|
} => self
|
||||||
.type_of(arg)
|
.type_of(arg)
|
||||||
.max(
|
.max(
|
||||||
@ -437,8 +452,34 @@ impl ExpressionKindTracker {
|
|||||||
.max(
|
.max(
|
||||||
arg3.map(|arg| self.type_of(arg))
|
arg3.map(|arg| self.type_of(arg))
|
||||||
.unwrap_or(ExpressionKind::Const),
|
.unwrap_or(ExpressionKind::Const),
|
||||||
|
)
|
||||||
|
.max(
|
||||||
|
if matches!(
|
||||||
|
fun,
|
||||||
|
Mf::Dot
|
||||||
|
| Mf::Outer
|
||||||
|
| Mf::Cross
|
||||||
|
| Mf::Distance
|
||||||
|
| Mf::Length
|
||||||
|
| Mf::Normalize
|
||||||
|
| Mf::FaceForward
|
||||||
|
| Mf::Reflect
|
||||||
|
| Mf::Refract
|
||||||
|
| Mf::Ldexp
|
||||||
|
| Mf::Modf
|
||||||
|
| Mf::Mix
|
||||||
|
| Mf::Frexp
|
||||||
|
) {
|
||||||
|
ExpressionKind::Const
|
||||||
|
} else {
|
||||||
|
ExpressionKind::ImplConst
|
||||||
|
},
|
||||||
),
|
),
|
||||||
Expression::As { expr, .. } => self.type_of(expr),
|
Expression::As { convert, expr, .. } => self.type_of(expr).max(if convert.is_some() {
|
||||||
|
ExpressionKind::ImplConst
|
||||||
|
} else {
|
||||||
|
ExpressionKind::Const
|
||||||
|
}),
|
||||||
Expression::Select {
|
Expression::Select {
|
||||||
condition,
|
condition,
|
||||||
accept,
|
accept,
|
||||||
@ -446,7 +487,8 @@ impl ExpressionKindTracker {
|
|||||||
} => self
|
} => self
|
||||||
.type_of(condition)
|
.type_of(condition)
|
||||||
.max(self.type_of(accept))
|
.max(self.type_of(accept))
|
||||||
.max(self.type_of(reject)),
|
.max(self.type_of(reject))
|
||||||
|
.max(ExpressionKind::Const),
|
||||||
Expression::Relational { argument, .. } => self.type_of(argument),
|
Expression::Relational { argument, .. } => self.type_of(argument),
|
||||||
Expression::ArrayLength(expr) => self.type_of(expr),
|
Expression::ArrayLength(expr) => self.type_of(expr),
|
||||||
_ => ExpressionKind::Runtime,
|
_ => ExpressionKind::Runtime,
|
||||||
@ -556,7 +598,7 @@ impl<'a> ConstantEvaluator<'a> {
|
|||||||
Behavior::Wgsl(if in_override_ctx {
|
Behavior::Wgsl(if in_override_ctx {
|
||||||
WgslRestrictions::Override
|
WgslRestrictions::Override
|
||||||
} else {
|
} else {
|
||||||
WgslRestrictions::Const
|
WgslRestrictions::Const(None)
|
||||||
}),
|
}),
|
||||||
module,
|
module,
|
||||||
global_expression_kind_tracker,
|
global_expression_kind_tracker,
|
||||||
@ -603,13 +645,19 @@ impl<'a> ConstantEvaluator<'a> {
|
|||||||
local_expression_kind_tracker: &'a mut ExpressionKindTracker,
|
local_expression_kind_tracker: &'a mut ExpressionKindTracker,
|
||||||
emitter: &'a mut super::Emitter,
|
emitter: &'a mut super::Emitter,
|
||||||
block: &'a mut crate::Block,
|
block: &'a mut crate::Block,
|
||||||
|
is_const: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let local_data = FunctionLocalData {
|
||||||
|
global_expressions: &module.global_expressions,
|
||||||
|
emitter,
|
||||||
|
block,
|
||||||
|
};
|
||||||
Self {
|
Self {
|
||||||
behavior: Behavior::Wgsl(WgslRestrictions::Runtime(FunctionLocalData {
|
behavior: Behavior::Wgsl(if is_const {
|
||||||
global_expressions: &module.global_expressions,
|
WgslRestrictions::Const(Some(local_data))
|
||||||
emitter,
|
} else {
|
||||||
block,
|
WgslRestrictions::Runtime(local_data)
|
||||||
})),
|
}),
|
||||||
types: &mut module.types,
|
types: &mut module.types,
|
||||||
constants: &module.constants,
|
constants: &module.constants,
|
||||||
overrides: &module.overrides,
|
overrides: &module.overrides,
|
||||||
@ -718,6 +766,7 @@ impl<'a> ConstantEvaluator<'a> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<Handle<Expression>, ConstantEvaluatorError> {
|
) -> Result<Handle<Expression>, ConstantEvaluatorError> {
|
||||||
match self.expression_kind_tracker.type_of_with_expr(&expr) {
|
match self.expression_kind_tracker.type_of_with_expr(&expr) {
|
||||||
|
ExpressionKind::ImplConst => self.try_eval_and_append_impl(&expr, span),
|
||||||
ExpressionKind::Const => {
|
ExpressionKind::Const => {
|
||||||
let eval_result = self.try_eval_and_append_impl(&expr, span);
|
let eval_result = self.try_eval_and_append_impl(&expr, span);
|
||||||
// We should be able to evaluate `Const` expressions at this
|
// We should be able to evaluate `Const` expressions at this
|
||||||
@ -740,7 +789,7 @@ impl<'a> ConstantEvaluator<'a> {
|
|||||||
Behavior::Wgsl(WgslRestrictions::Override | WgslRestrictions::Runtime(_)) => {
|
Behavior::Wgsl(WgslRestrictions::Override | WgslRestrictions::Runtime(_)) => {
|
||||||
Ok(self.append_expr(expr, span, ExpressionKind::Override))
|
Ok(self.append_expr(expr, span, ExpressionKind::Override))
|
||||||
}
|
}
|
||||||
Behavior::Wgsl(WgslRestrictions::Const) => {
|
Behavior::Wgsl(WgslRestrictions::Const(_)) => {
|
||||||
Err(ConstantEvaluatorError::OverrideExpr)
|
Err(ConstantEvaluatorError::OverrideExpr)
|
||||||
}
|
}
|
||||||
Behavior::Glsl(_) => {
|
Behavior::Glsl(_) => {
|
||||||
@ -761,14 +810,17 @@ impl<'a> ConstantEvaluator<'a> {
|
|||||||
const fn is_global_arena(&self) -> bool {
|
const fn is_global_arena(&self) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
self.behavior,
|
self.behavior,
|
||||||
Behavior::Wgsl(WgslRestrictions::Const | WgslRestrictions::Override)
|
Behavior::Wgsl(WgslRestrictions::Const(None) | WgslRestrictions::Override)
|
||||||
| Behavior::Glsl(GlslRestrictions::Const)
|
| Behavior::Glsl(GlslRestrictions::Const)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn function_local_data(&self) -> Option<&FunctionLocalData<'a>> {
|
const fn function_local_data(&self) -> Option<&FunctionLocalData<'a>> {
|
||||||
match self.behavior {
|
match self.behavior {
|
||||||
Behavior::Wgsl(WgslRestrictions::Runtime(ref function_local_data))
|
Behavior::Wgsl(
|
||||||
|
WgslRestrictions::Runtime(ref function_local_data)
|
||||||
|
| WgslRestrictions::Const(Some(ref function_local_data)),
|
||||||
|
)
|
||||||
| Behavior::Glsl(GlslRestrictions::Runtime(ref function_local_data)) => {
|
| Behavior::Glsl(GlslRestrictions::Runtime(ref function_local_data)) => {
|
||||||
Some(function_local_data)
|
Some(function_local_data)
|
||||||
}
|
}
|
||||||
@ -2057,7 +2109,10 @@ impl<'a> ConstantEvaluator<'a> {
|
|||||||
expr_type: ExpressionKind,
|
expr_type: ExpressionKind,
|
||||||
) -> Handle<Expression> {
|
) -> Handle<Expression> {
|
||||||
let h = match self.behavior {
|
let h = match self.behavior {
|
||||||
Behavior::Wgsl(WgslRestrictions::Runtime(ref mut function_local_data))
|
Behavior::Wgsl(
|
||||||
|
WgslRestrictions::Runtime(ref mut function_local_data)
|
||||||
|
| WgslRestrictions::Const(Some(ref mut function_local_data)),
|
||||||
|
)
|
||||||
| Behavior::Glsl(GlslRestrictions::Runtime(ref mut function_local_data)) => {
|
| Behavior::Glsl(GlslRestrictions::Runtime(ref mut function_local_data)) => {
|
||||||
let is_running = function_local_data.emitter.is_running();
|
let is_running = function_local_data.emitter.is_running();
|
||||||
let needs_pre_emit = expr.needs_pre_emit();
|
let needs_pre_emit = expr.needs_pre_emit();
|
||||||
@ -2480,7 +2535,7 @@ mod tests {
|
|||||||
|
|
||||||
let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
|
let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
|
||||||
let mut solver = ConstantEvaluator {
|
let mut solver = ConstantEvaluator {
|
||||||
behavior: Behavior::Wgsl(WgslRestrictions::Const),
|
behavior: Behavior::Wgsl(WgslRestrictions::Const(None)),
|
||||||
types: &mut types,
|
types: &mut types,
|
||||||
constants: &constants,
|
constants: &constants,
|
||||||
overrides: &overrides,
|
overrides: &overrides,
|
||||||
@ -2566,7 +2621,7 @@ mod tests {
|
|||||||
|
|
||||||
let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
|
let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
|
||||||
let mut solver = ConstantEvaluator {
|
let mut solver = ConstantEvaluator {
|
||||||
behavior: Behavior::Wgsl(WgslRestrictions::Const),
|
behavior: Behavior::Wgsl(WgslRestrictions::Const(None)),
|
||||||
types: &mut types,
|
types: &mut types,
|
||||||
constants: &constants,
|
constants: &constants,
|
||||||
overrides: &overrides,
|
overrides: &overrides,
|
||||||
@ -2684,7 +2739,7 @@ mod tests {
|
|||||||
|
|
||||||
let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
|
let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
|
||||||
let mut solver = ConstantEvaluator {
|
let mut solver = ConstantEvaluator {
|
||||||
behavior: Behavior::Wgsl(WgslRestrictions::Const),
|
behavior: Behavior::Wgsl(WgslRestrictions::Const(None)),
|
||||||
types: &mut types,
|
types: &mut types,
|
||||||
constants: &constants,
|
constants: &constants,
|
||||||
overrides: &overrides,
|
overrides: &overrides,
|
||||||
@ -2777,7 +2832,7 @@ mod tests {
|
|||||||
|
|
||||||
let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
|
let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
|
||||||
let mut solver = ConstantEvaluator {
|
let mut solver = ConstantEvaluator {
|
||||||
behavior: Behavior::Wgsl(WgslRestrictions::Const),
|
behavior: Behavior::Wgsl(WgslRestrictions::Const(None)),
|
||||||
types: &mut types,
|
types: &mut types,
|
||||||
constants: &constants,
|
constants: &constants,
|
||||||
overrides: &overrides,
|
overrides: &overrides,
|
||||||
@ -2859,7 +2914,7 @@ mod tests {
|
|||||||
|
|
||||||
let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
|
let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
|
||||||
let mut solver = ConstantEvaluator {
|
let mut solver = ConstantEvaluator {
|
||||||
behavior: Behavior::Wgsl(WgslRestrictions::Const),
|
behavior: Behavior::Wgsl(WgslRestrictions::Const(None)),
|
||||||
types: &mut types,
|
types: &mut types,
|
||||||
constants: &constants,
|
constants: &constants,
|
||||||
overrides: &overrides,
|
overrides: &overrides,
|
||||||
|
1
naga/tests/in/local-const.param.ron
Normal file
1
naga/tests/in/local-const.param.ron
Normal file
@ -0,0 +1 @@
|
|||||||
|
()
|
26
naga/tests/in/local-const.wgsl
Normal file
26
naga/tests/in/local-const.wgsl
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const ga = 4; // AbstractInt with a value of 4.
|
||||||
|
const gb : i32 = 4; // i32 with a value of 4.
|
||||||
|
const gc : u32 = 4; // u32 with a value of 4.
|
||||||
|
const gd : f32 = 4; // f32 with a value of 4.
|
||||||
|
const ge = vec3(ga, ga, ga); // vec3 of AbstractInt with a value of (4, 4, 4).
|
||||||
|
const gf = 2.0; // AbstractFloat with a value of 2.
|
||||||
|
|
||||||
|
fn const_in_fn() {
|
||||||
|
const a = 4; // AbstractInt with a value of 4.
|
||||||
|
const b: i32 = 4; // i32 with a value of 4.
|
||||||
|
const c: u32 = 4; // u32 with a value of 4.
|
||||||
|
const d: f32 = 4; // f32 with a value of 4.
|
||||||
|
const e = vec3(a, a, a); // vec3 of AbstractInt with a value of (4, 4, 4).
|
||||||
|
const f = 2.0; // AbstractFloat with a value of 2.
|
||||||
|
// TODO: Make it per spec, currently not possible
|
||||||
|
// because naga does not support automatic conversions
|
||||||
|
// of Abstract types
|
||||||
|
|
||||||
|
// Check that we can access global constants
|
||||||
|
const ag = ga;
|
||||||
|
const bg = gb;
|
||||||
|
const cg = gc;
|
||||||
|
const dg = gd;
|
||||||
|
const eg = ge;
|
||||||
|
const fg = gf;
|
||||||
|
}
|
139
naga/tests/out/ir/local-const.compact.ron
Normal file
139
naga/tests/out/ir/local-const.compact.ron
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
(
|
||||||
|
types: [
|
||||||
|
(
|
||||||
|
name: None,
|
||||||
|
inner: Scalar((
|
||||||
|
kind: Sint,
|
||||||
|
width: 4,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: None,
|
||||||
|
inner: Scalar((
|
||||||
|
kind: Uint,
|
||||||
|
width: 4,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: None,
|
||||||
|
inner: Scalar((
|
||||||
|
kind: Float,
|
||||||
|
width: 4,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: None,
|
||||||
|
inner: Vector(
|
||||||
|
size: Tri,
|
||||||
|
scalar: (
|
||||||
|
kind: Sint,
|
||||||
|
width: 4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
special_types: (
|
||||||
|
ray_desc: None,
|
||||||
|
ray_intersection: None,
|
||||||
|
predeclared_types: {},
|
||||||
|
),
|
||||||
|
constants: [
|
||||||
|
(
|
||||||
|
name: Some("ga"),
|
||||||
|
ty: 0,
|
||||||
|
init: 0,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: Some("gb"),
|
||||||
|
ty: 0,
|
||||||
|
init: 1,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: Some("gc"),
|
||||||
|
ty: 1,
|
||||||
|
init: 2,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: Some("gd"),
|
||||||
|
ty: 2,
|
||||||
|
init: 3,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: Some("ge"),
|
||||||
|
ty: 3,
|
||||||
|
init: 4,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: Some("gf"),
|
||||||
|
ty: 2,
|
||||||
|
init: 5,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
overrides: [],
|
||||||
|
global_variables: [],
|
||||||
|
global_expressions: [
|
||||||
|
Literal(I32(4)),
|
||||||
|
Literal(I32(4)),
|
||||||
|
Literal(U32(4)),
|
||||||
|
Literal(F32(4.0)),
|
||||||
|
Compose(
|
||||||
|
ty: 3,
|
||||||
|
components: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Literal(F32(2.0)),
|
||||||
|
],
|
||||||
|
functions: [
|
||||||
|
(
|
||||||
|
name: Some("const_in_fn"),
|
||||||
|
arguments: [],
|
||||||
|
result: None,
|
||||||
|
local_variables: [],
|
||||||
|
expressions: [
|
||||||
|
Literal(I32(4)),
|
||||||
|
Literal(I32(4)),
|
||||||
|
Literal(U32(4)),
|
||||||
|
Literal(F32(4.0)),
|
||||||
|
Compose(
|
||||||
|
ty: 3,
|
||||||
|
components: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Literal(F32(2.0)),
|
||||||
|
Constant(0),
|
||||||
|
Constant(1),
|
||||||
|
Constant(2),
|
||||||
|
Constant(3),
|
||||||
|
Constant(4),
|
||||||
|
Constant(5),
|
||||||
|
],
|
||||||
|
named_expressions: {
|
||||||
|
0: "a",
|
||||||
|
1: "b",
|
||||||
|
2: "c",
|
||||||
|
3: "d",
|
||||||
|
4: "e",
|
||||||
|
5: "f",
|
||||||
|
6: "ag",
|
||||||
|
7: "bg",
|
||||||
|
8: "cg",
|
||||||
|
9: "dg",
|
||||||
|
10: "eg",
|
||||||
|
11: "fg",
|
||||||
|
},
|
||||||
|
body: [
|
||||||
|
Emit((
|
||||||
|
start: 4,
|
||||||
|
end: 5,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
entry_points: [],
|
||||||
|
)
|
139
naga/tests/out/ir/local-const.ron
Normal file
139
naga/tests/out/ir/local-const.ron
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
(
|
||||||
|
types: [
|
||||||
|
(
|
||||||
|
name: None,
|
||||||
|
inner: Scalar((
|
||||||
|
kind: Sint,
|
||||||
|
width: 4,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: None,
|
||||||
|
inner: Scalar((
|
||||||
|
kind: Uint,
|
||||||
|
width: 4,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: None,
|
||||||
|
inner: Scalar((
|
||||||
|
kind: Float,
|
||||||
|
width: 4,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: None,
|
||||||
|
inner: Vector(
|
||||||
|
size: Tri,
|
||||||
|
scalar: (
|
||||||
|
kind: Sint,
|
||||||
|
width: 4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
special_types: (
|
||||||
|
ray_desc: None,
|
||||||
|
ray_intersection: None,
|
||||||
|
predeclared_types: {},
|
||||||
|
),
|
||||||
|
constants: [
|
||||||
|
(
|
||||||
|
name: Some("ga"),
|
||||||
|
ty: 0,
|
||||||
|
init: 0,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: Some("gb"),
|
||||||
|
ty: 0,
|
||||||
|
init: 1,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: Some("gc"),
|
||||||
|
ty: 1,
|
||||||
|
init: 2,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: Some("gd"),
|
||||||
|
ty: 2,
|
||||||
|
init: 3,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: Some("ge"),
|
||||||
|
ty: 3,
|
||||||
|
init: 4,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
name: Some("gf"),
|
||||||
|
ty: 2,
|
||||||
|
init: 5,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
overrides: [],
|
||||||
|
global_variables: [],
|
||||||
|
global_expressions: [
|
||||||
|
Literal(I32(4)),
|
||||||
|
Literal(I32(4)),
|
||||||
|
Literal(U32(4)),
|
||||||
|
Literal(F32(4.0)),
|
||||||
|
Compose(
|
||||||
|
ty: 3,
|
||||||
|
components: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Literal(F32(2.0)),
|
||||||
|
],
|
||||||
|
functions: [
|
||||||
|
(
|
||||||
|
name: Some("const_in_fn"),
|
||||||
|
arguments: [],
|
||||||
|
result: None,
|
||||||
|
local_variables: [],
|
||||||
|
expressions: [
|
||||||
|
Literal(I32(4)),
|
||||||
|
Literal(I32(4)),
|
||||||
|
Literal(U32(4)),
|
||||||
|
Literal(F32(4.0)),
|
||||||
|
Compose(
|
||||||
|
ty: 3,
|
||||||
|
components: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Literal(F32(2.0)),
|
||||||
|
Constant(0),
|
||||||
|
Constant(1),
|
||||||
|
Constant(2),
|
||||||
|
Constant(3),
|
||||||
|
Constant(4),
|
||||||
|
Constant(5),
|
||||||
|
],
|
||||||
|
named_expressions: {
|
||||||
|
0: "a",
|
||||||
|
1: "b",
|
||||||
|
2: "c",
|
||||||
|
3: "d",
|
||||||
|
4: "e",
|
||||||
|
5: "f",
|
||||||
|
6: "ag",
|
||||||
|
7: "bg",
|
||||||
|
8: "cg",
|
||||||
|
9: "dg",
|
||||||
|
10: "eg",
|
||||||
|
11: "fg",
|
||||||
|
},
|
||||||
|
body: [
|
||||||
|
Emit((
|
||||||
|
start: 4,
|
||||||
|
end: 5,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
entry_points: [],
|
||||||
|
)
|
@ -34,8 +34,8 @@ fn main(fragment_in: FragmentIn) -> @location(0) vec4<f32> {
|
|||||||
|
|
||||||
let uniform_index = uni.index;
|
let uniform_index = uni.index;
|
||||||
let non_uniform_index = fragment_in.index;
|
let non_uniform_index = fragment_in.index;
|
||||||
let uv = vec2(0f);
|
const uv = vec2(0f);
|
||||||
let pix = vec2(0i);
|
const pix = vec2(0i);
|
||||||
let _e21 = textureDimensions(texture_array_unbounded[0]);
|
let _e21 = textureDimensions(texture_array_unbounded[0]);
|
||||||
let _e22 = u2_;
|
let _e22 = u2_;
|
||||||
u2_ = (_e22 + _e21);
|
u2_ = (_e22 + _e21);
|
||||||
|
@ -21,11 +21,11 @@ fn main() {
|
|||||||
var foo: Foo;
|
var foo: Foo;
|
||||||
|
|
||||||
foo = Foo(vec4(1f), 1i);
|
foo = Foo(vec4(1f), 1i);
|
||||||
let m0_ = mat2x2<f32>(vec2<f32>(1f, 0f), vec2<f32>(0f, 1f));
|
const m0_ = mat2x2<f32>(vec2<f32>(1f, 0f), vec2<f32>(0f, 1f));
|
||||||
let m1_ = mat4x4<f32>(vec4<f32>(1f, 0f, 0f, 0f), vec4<f32>(0f, 1f, 0f, 0f), vec4<f32>(0f, 0f, 1f, 0f), vec4<f32>(0f, 0f, 0f, 1f));
|
const m1_ = mat4x4<f32>(vec4<f32>(1f, 0f, 0f, 0f), vec4<f32>(0f, 1f, 0f, 0f), vec4<f32>(0f, 0f, 1f, 0f), vec4<f32>(0f, 0f, 0f, 1f));
|
||||||
let cit0_ = vec2(0u);
|
const cit0_ = vec2(0u);
|
||||||
let cit1_ = mat2x2<f32>(vec2(0f), vec2(0f));
|
const cit1_ = mat2x2<f32>(vec2(0f), vec2(0f));
|
||||||
let cit2_ = array<i32, 4>(0i, 1i, 2i, 3i);
|
const cit2_ = array<i32, 4>(0i, 1i, 2i, 3i);
|
||||||
let ic4_ = vec2<u32>(0u, 0u);
|
const ic4_ = vec2<u32>(0u, 0u);
|
||||||
let ic5_ = mat2x3<f32>(vec3<f32>(0f, 0f, 0f), vec3<f32>(0f, 0f, 0f));
|
const ic5_ = mat2x3<f32>(vec3<f32>(0f, 0f, 0f), vec3<f32>(0f, 0f, 0f));
|
||||||
}
|
}
|
||||||
|
@ -268,12 +268,12 @@ fn testUnaryOpMat(a_16: mat3x3<f32>) {
|
|||||||
let _e3 = a_17;
|
let _e3 = a_17;
|
||||||
v_8 = -(_e3);
|
v_8 = -(_e3);
|
||||||
let _e5 = a_17;
|
let _e5 = a_17;
|
||||||
let _e7 = vec3(1f);
|
const _e7 = vec3(1f);
|
||||||
let _e9 = (_e5 - mat3x3<f32>(_e7, _e7, _e7));
|
let _e9 = (_e5 - mat3x3<f32>(_e7, _e7, _e7));
|
||||||
a_17 = _e9;
|
a_17 = _e9;
|
||||||
v_8 = _e9;
|
v_8 = _e9;
|
||||||
let _e10 = a_17;
|
let _e10 = a_17;
|
||||||
let _e12 = vec3(1f);
|
const _e12 = vec3(1f);
|
||||||
a_17 = (_e10 - mat3x3<f32>(_e12, _e12, _e12));
|
a_17 = (_e10 - mat3x3<f32>(_e12, _e12, _e12));
|
||||||
v_8 = _e10;
|
v_8 = _e10;
|
||||||
return;
|
return;
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
fn test_fma() -> vec2<f32> {
|
fn test_fma() -> vec2<f32> {
|
||||||
let a = vec2<f32>(2f, 2f);
|
const a = vec2<f32>(2f, 2f);
|
||||||
let b = vec2<f32>(0.5f, 0.5f);
|
const b = vec2<f32>(0.5f, 0.5f);
|
||||||
let c = vec2<f32>(0.5f, 0.5f);
|
const c = vec2<f32>(0.5f, 0.5f);
|
||||||
return fma(a, b, c);
|
return fma(a, b, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_integer_dot_product() -> i32 {
|
fn test_integer_dot_product() -> i32 {
|
||||||
let a_2_ = vec2(1i);
|
const a_2_ = vec2(1i);
|
||||||
let b_2_ = vec2(1i);
|
const b_2_ = vec2(1i);
|
||||||
let c_2_ = dot(a_2_, b_2_);
|
let c_2_ = dot(a_2_, b_2_);
|
||||||
let a_3_ = vec3(1u);
|
const a_3_ = vec3(1u);
|
||||||
let b_3_ = vec3(1u);
|
const b_3_ = vec3(1u);
|
||||||
let c_3_ = dot(a_3_, b_3_);
|
let c_3_ = dot(a_3_, b_3_);
|
||||||
let c_4_ = dot(vec4(4i), vec4(2i));
|
let c_4_ = dot(vec4(4i), vec4(2i));
|
||||||
return c_4_;
|
return c_4_;
|
||||||
|
@ -110,8 +110,8 @@ fn levels_queries() -> @builtin(position) vec4<f32> {
|
|||||||
fn texture_sample() -> @location(0) vec4<f32> {
|
fn texture_sample() -> @location(0) vec4<f32> {
|
||||||
var a: vec4<f32>;
|
var a: vec4<f32>;
|
||||||
|
|
||||||
let tc = vec2(0.5f);
|
const tc = vec2(0.5f);
|
||||||
let tc3_ = vec3(0.5f);
|
const tc3_ = vec3(0.5f);
|
||||||
let _e9 = textureSample(image_1d, sampler_reg, tc.x);
|
let _e9 = textureSample(image_1d, sampler_reg, tc.x);
|
||||||
let _e10 = a;
|
let _e10 = a;
|
||||||
a = (_e10 + _e9);
|
a = (_e10 + _e9);
|
||||||
@ -186,8 +186,8 @@ fn texture_sample() -> @location(0) vec4<f32> {
|
|||||||
fn texture_sample_comparison() -> @location(0) f32 {
|
fn texture_sample_comparison() -> @location(0) f32 {
|
||||||
var a_1: f32;
|
var a_1: f32;
|
||||||
|
|
||||||
let tc_1 = vec2(0.5f);
|
const tc_1 = vec2(0.5f);
|
||||||
let tc3_1 = vec3(0.5f);
|
const tc3_1 = vec3(0.5f);
|
||||||
let _e8 = textureSampleCompare(image_2d_depth, sampler_cmp, tc_1, 0.5f);
|
let _e8 = textureSampleCompare(image_2d_depth, sampler_cmp, tc_1, 0.5f);
|
||||||
let _e9 = a_1;
|
let _e9 = a_1;
|
||||||
a_1 = (_e9 + _e8);
|
a_1 = (_e9 + _e8);
|
||||||
@ -218,7 +218,7 @@ fn texture_sample_comparison() -> @location(0) f32 {
|
|||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn gather() -> @location(0) vec4<f32> {
|
fn gather() -> @location(0) vec4<f32> {
|
||||||
let tc_2 = vec2(0.5f);
|
const tc_2 = vec2(0.5f);
|
||||||
let s2d = textureGather(1, image_2d, sampler_reg, tc_2);
|
let s2d = textureGather(1, image_2d, sampler_reg, tc_2);
|
||||||
let s2d_offset = textureGather(3, image_2d, sampler_reg, tc_2, vec2<i32>(3i, 1i));
|
let s2d_offset = textureGather(3, image_2d, sampler_reg, tc_2, vec2<i32>(3i, 1i));
|
||||||
let s2d_depth = textureGatherCompare(image_2d_depth, sampler_cmp, tc_2, 0.5f);
|
let s2d_depth = textureGatherCompare(image_2d_depth, sampler_cmp, tc_2, 0.5f);
|
||||||
@ -231,7 +231,7 @@ fn gather() -> @location(0) vec4<f32> {
|
|||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn depth_no_comparison() -> @location(0) vec4<f32> {
|
fn depth_no_comparison() -> @location(0) vec4<f32> {
|
||||||
let tc_3 = vec2(0.5f);
|
const tc_3 = vec2(0.5f);
|
||||||
let s2d_1 = textureSample(image_2d_depth, sampler_reg, tc_3);
|
let s2d_1 = textureSample(image_2d_depth, sampler_reg, tc_3);
|
||||||
let s2d_gather = textureGather(image_2d_depth, sampler_reg, tc_3);
|
let s2d_gather = textureGather(image_2d_depth, sampler_reg, tc_3);
|
||||||
return (vec4(s2d_1) + s2d_gather);
|
return (vec4(s2d_1) + s2d_gather);
|
||||||
|
11
naga/tests/out/wgsl/local-const.wgsl
Normal file
11
naga/tests/out/wgsl/local-const.wgsl
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
const ga: i32 = 4i;
|
||||||
|
const gb: i32 = 4i;
|
||||||
|
const gc: u32 = 4u;
|
||||||
|
const gd: f32 = 4f;
|
||||||
|
const ge: vec3<i32> = vec3<i32>(4i, 4i, 4i);
|
||||||
|
const gf: f32 = 2f;
|
||||||
|
|
||||||
|
fn const_in_fn() {
|
||||||
|
const e = vec3<i32>(4i, 4i, 4i);
|
||||||
|
}
|
||||||
|
|
@ -1,25 +1,25 @@
|
|||||||
@fragment
|
@fragment
|
||||||
fn main() {
|
fn main() {
|
||||||
let v = vec4(0f);
|
const v = vec4(0f);
|
||||||
let a = degrees(1f);
|
let a = degrees(1f);
|
||||||
let b = radians(1f);
|
let b = radians(1f);
|
||||||
let c = degrees(v);
|
let c = degrees(v);
|
||||||
let d = radians(v);
|
let d = radians(v);
|
||||||
let e = saturate(v);
|
let e = saturate(v);
|
||||||
let g = refract(v, v, 1f);
|
let g = refract(v, v, 1f);
|
||||||
let sign_b = vec4<i32>(-1i, -1i, -1i, -1i);
|
const sign_b = vec4<i32>(-1i, -1i, -1i, -1i);
|
||||||
let sign_d = vec4<f32>(-1f, -1f, -1f, -1f);
|
const sign_d = vec4<f32>(-1f, -1f, -1f, -1f);
|
||||||
let const_dot = dot(vec2<i32>(), vec2<i32>());
|
let const_dot = dot(vec2<i32>(), vec2<i32>());
|
||||||
let flb_b = vec2<i32>(-1i, -1i);
|
const flb_b = vec2<i32>(-1i, -1i);
|
||||||
let flb_c = vec2<u32>(0u, 0u);
|
const flb_c = vec2<u32>(0u, 0u);
|
||||||
let ftb_c = vec2<i32>(0i, 0i);
|
const ftb_c = vec2<i32>(0i, 0i);
|
||||||
let ftb_d = vec2<u32>(0u, 0u);
|
const ftb_d = vec2<u32>(0u, 0u);
|
||||||
let ctz_e = vec2<u32>(32u, 32u);
|
const ctz_e = vec2<u32>(32u, 32u);
|
||||||
let ctz_f = vec2<i32>(32i, 32i);
|
const ctz_f = vec2<i32>(32i, 32i);
|
||||||
let ctz_g = vec2<u32>(0u, 0u);
|
const ctz_g = vec2<u32>(0u, 0u);
|
||||||
let ctz_h = vec2<i32>(0i, 0i);
|
const ctz_h = vec2<i32>(0i, 0i);
|
||||||
let clz_c = vec2<i32>(0i, 0i);
|
const clz_c = vec2<i32>(0i, 0i);
|
||||||
let clz_d = vec2<u32>(31u, 31u);
|
const clz_d = vec2<u32>(31u, 31u);
|
||||||
let lde_a = ldexp(1f, 2i);
|
let lde_a = ldexp(1f, 2i);
|
||||||
let lde_b = ldexp(vec2<f32>(1f, 2f), vec2<i32>(3i, 4i));
|
let lde_b = ldexp(vec2<f32>(1f, 2f), vec2<i32>(3i, 4i));
|
||||||
let modf_a = modf(1.5f);
|
let modf_a = modf(1.5f);
|
||||||
|
@ -11,7 +11,7 @@ fn builtins() -> vec4<f32> {
|
|||||||
let m2_ = mix(v_f32_zero, v_f32_one, 0.1f);
|
let m2_ = mix(v_f32_zero, v_f32_one, 0.1f);
|
||||||
let b1_ = bitcast<f32>(1i);
|
let b1_ = bitcast<f32>(1i);
|
||||||
let b2_ = bitcast<vec4<f32>>(v_i32_one);
|
let b2_ = bitcast<vec4<f32>>(v_i32_one);
|
||||||
let v_i32_zero = vec4<i32>(0i, 0i, 0i, 0i);
|
const v_i32_zero = vec4<i32>(0i, 0i, 0i, 0i);
|
||||||
return (((((vec4<f32>((vec4(s1_) + v_i32_zero)) + s2_) + m1_) + m2_) + vec4(b1_)) + b2_);
|
return (((((vec4<f32>((vec4(s1_) + v_i32_zero)) + s2_) + m1_) + m2_) + vec4(b1_)) + b2_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,8 +40,8 @@ fn bool_cast(x: vec3<f32>) -> vec3<f32> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn logical() {
|
fn logical() {
|
||||||
let neg0_ = !(true);
|
const neg0_ = !(true);
|
||||||
let neg1_ = !(vec2(true));
|
const neg1_ = !(vec2(true));
|
||||||
let or = (true || false);
|
let or = (true || false);
|
||||||
let and = (true && false);
|
let and = (true && false);
|
||||||
let bitwise_or0_ = (true | false);
|
let bitwise_or0_ = (true | false);
|
||||||
@ -51,9 +51,9 @@ fn logical() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn arithmetic() {
|
fn arithmetic() {
|
||||||
let neg0_1 = -(1f);
|
const neg0_1 = -(1f);
|
||||||
let neg1_1 = -(vec2(1i));
|
const neg1_1 = -(vec2(1i));
|
||||||
let neg2_ = -(vec2(1f));
|
const neg2_ = -(vec2(1f));
|
||||||
let add0_ = (2i + 1i);
|
let add0_ = (2i + 1i);
|
||||||
let add1_ = (2u + 1u);
|
let add1_ = (2u + 1u);
|
||||||
let add2_ = (2f + 1f);
|
let add2_ = (2f + 1f);
|
||||||
@ -126,10 +126,10 @@ fn arithmetic() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn bit() {
|
fn bit() {
|
||||||
let flip0_ = ~(1i);
|
const flip0_ = ~(1i);
|
||||||
let flip1_ = ~(1u);
|
const flip1_ = ~(1u);
|
||||||
let flip2_ = ~(vec2(1i));
|
const flip2_ = ~(vec2(1i));
|
||||||
let flip3_ = ~(vec3(1u));
|
const flip3_ = ~(vec3(1u));
|
||||||
let or0_ = (2i | 1i);
|
let or0_ = (2i | 1i);
|
||||||
let or1_ = (2u | 1u);
|
let or1_ = (2u | 1u);
|
||||||
let or2_ = (vec2(2i) | vec2(1i));
|
let or2_ = (vec2(2i) | vec2(1i));
|
||||||
@ -230,14 +230,14 @@ fn assignment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn negation_avoids_prefix_decrement() {
|
fn negation_avoids_prefix_decrement() {
|
||||||
let p0_ = -(1i);
|
const p0_ = -(1i);
|
||||||
let p1_ = -(-(1i));
|
const p1_ = -(-(1i));
|
||||||
let p2_ = -(-(1i));
|
const p2_ = -(-(1i));
|
||||||
let p3_ = -(-(1i));
|
const p3_ = -(-(1i));
|
||||||
let p4_ = -(-(-(1i)));
|
const p4_ = -(-(-(1i)));
|
||||||
let p5_ = -(-(-(-(1i))));
|
const p5_ = -(-(-(-(1i))));
|
||||||
let p6_ = -(-(-(-(-(1i)))));
|
const p6_ = -(-(-(-(-(1i)))));
|
||||||
let p7_ = -(-(-(-(-(1i)))));
|
const p7_ = -(-(-(-(-(1i)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@compute @workgroup_size(1, 1, 1)
|
@compute @workgroup_size(1, 1, 1)
|
||||||
|
@ -21,11 +21,11 @@ fn main_1() {
|
|||||||
vec = _e21;
|
vec = _e21;
|
||||||
vec_target = _e21;
|
vec_target = _e21;
|
||||||
let _e32 = mat;
|
let _e32 = mat;
|
||||||
let _e34 = vec3(1f);
|
const _e34 = vec3(1f);
|
||||||
mat = (_e32 + mat4x3<f32>(_e34, _e34, _e34, _e34));
|
mat = (_e32 + mat4x3<f32>(_e34, _e34, _e34, _e34));
|
||||||
mat_target = _e32;
|
mat_target = _e32;
|
||||||
let _e37 = mat;
|
let _e37 = mat;
|
||||||
let _e39 = vec3(1f);
|
const _e39 = vec3(1f);
|
||||||
let _e41 = (_e37 - mat4x3<f32>(_e39, _e39, _e39, _e39));
|
let _e41 = (_e37 - mat4x3<f32>(_e39, _e39, _e39, _e39));
|
||||||
mat = _e41;
|
mat = _e41;
|
||||||
mat_target = _e41;
|
mat_target = _e41;
|
||||||
|
@ -40,7 +40,7 @@ fn fetch_shadow(light_id: u32, homogeneous_coords: vec4<f32>) -> f32 {
|
|||||||
if (homogeneous_coords.w <= 0f) {
|
if (homogeneous_coords.w <= 0f) {
|
||||||
return 1f;
|
return 1f;
|
||||||
}
|
}
|
||||||
let flip_correction = vec2<f32>(0.5f, -0.5f);
|
const flip_correction = vec2<f32>(0.5f, -0.5f);
|
||||||
let proj_correction = (1f / homogeneous_coords.w);
|
let proj_correction = (1f / homogeneous_coords.w);
|
||||||
let light_local = (((homogeneous_coords.xy * flip_correction) * proj_correction) + vec2<f32>(0.5f, 0.5f));
|
let light_local = (((homogeneous_coords.xy * flip_correction) * proj_correction) + vec2<f32>(0.5f, 0.5f));
|
||||||
let _e24 = textureSampleCompareLevel(t_shadow, sampler_shadow, light_local, i32(light_id), (homogeneous_coords.z * proj_correction));
|
let _e24 = textureSampleCompareLevel(t_shadow, sampler_shadow, light_local, i32(light_id), (homogeneous_coords.z * proj_correction));
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
let a = vec3<f32>(0f, 0f, 0f);
|
const a = vec3<f32>(0f, 0f, 0f);
|
||||||
let c = vec3(0f);
|
const c = vec3(0f);
|
||||||
let b = vec3<f32>(vec2(0f), 0f);
|
const b = vec3<f32>(vec2(0f), 0f);
|
||||||
let d = vec3<f32>(vec2(0f), 0f);
|
const d = vec3<f32>(vec2(0f), 0f);
|
||||||
let e = vec3<i32>(d);
|
const e = vec3<i32>(d);
|
||||||
let f = mat2x2<f32>(vec2<f32>(1f, 2f), vec2<f32>(3f, 4f));
|
const f = mat2x2<f32>(vec2<f32>(1f, 2f), vec2<f32>(3f, 4f));
|
||||||
let g = mat3x3<f32>(a, a, a);
|
const g = mat3x3<f32>(a, a, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,6 +818,7 @@ fn convert_wgsl() {
|
|||||||
"use-gl-ext-over-grad-workaround-if-instructed",
|
"use-gl-ext-over-grad-workaround-if-instructed",
|
||||||
Targets::GLSL,
|
Targets::GLSL,
|
||||||
),
|
),
|
||||||
|
("local-const", Targets::IR | Targets::WGSL),
|
||||||
(
|
(
|
||||||
"math-functions",
|
"math-functions",
|
||||||
Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::HLSL | Targets::WGSL,
|
Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::HLSL | Targets::WGSL,
|
||||||
|
@ -2277,3 +2277,97 @@ fn too_many_unclosed_loops() {
|
|||||||
.join()
|
.join()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn local_const_wrong_type() {
|
||||||
|
check(
|
||||||
|
"
|
||||||
|
fn f() {
|
||||||
|
const c: i32 = 5u;
|
||||||
|
}
|
||||||
|
",
|
||||||
|
r###"error: the type of `c` is expected to be `i32`, but got `u32`
|
||||||
|
┌─ wgsl:3:19
|
||||||
|
│
|
||||||
|
3 │ const c: i32 = 5u;
|
||||||
|
│ ^ definition of `c`
|
||||||
|
|
||||||
|
"###,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn local_const_from_let() {
|
||||||
|
check(
|
||||||
|
"
|
||||||
|
fn f() {
|
||||||
|
let a = 5;
|
||||||
|
const c = a;
|
||||||
|
}
|
||||||
|
",
|
||||||
|
r###"error: this operation is not supported in a const context
|
||||||
|
┌─ wgsl:4:23
|
||||||
|
│
|
||||||
|
4 │ const c = a;
|
||||||
|
│ ^ operation not supported here
|
||||||
|
|
||||||
|
"###,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn local_const_from_var() {
|
||||||
|
check(
|
||||||
|
"
|
||||||
|
fn f() {
|
||||||
|
var a = 5;
|
||||||
|
const c = a;
|
||||||
|
}
|
||||||
|
",
|
||||||
|
r###"error: this operation is not supported in a const context
|
||||||
|
┌─ wgsl:4:23
|
||||||
|
│
|
||||||
|
4 │ const c = a;
|
||||||
|
│ ^ operation not supported here
|
||||||
|
|
||||||
|
"###,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn local_const_from_override() {
|
||||||
|
check(
|
||||||
|
"
|
||||||
|
override o: i32;
|
||||||
|
fn f() {
|
||||||
|
const c = o;
|
||||||
|
}
|
||||||
|
",
|
||||||
|
r###"error: Unexpected override-expression
|
||||||
|
┌─ wgsl:4:23
|
||||||
|
│
|
||||||
|
4 │ const c = o;
|
||||||
|
│ ^ see msg
|
||||||
|
|
||||||
|
"###,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn local_const_from_global_var() {
|
||||||
|
check(
|
||||||
|
"
|
||||||
|
var v: i32;
|
||||||
|
fn f() {
|
||||||
|
const c = v;
|
||||||
|
}
|
||||||
|
",
|
||||||
|
r###"error: Unexpected runtime-expression
|
||||||
|
┌─ wgsl:4:23
|
||||||
|
│
|
||||||
|
4 │ const c = v;
|
||||||
|
│ ^ see msg
|
||||||
|
|
||||||
|
"###,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user