mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-12-04 20:53:57 +00:00
glsl-in: inject samplerCubeArray builtins on use
Arrayed cube images require a special capabilities in some backends, so like how we already do with doubles, we now only inject them if a call uses one as an argument. This required some refractoring on the builtins handling of variations but now the interface is cleaner and adding new variations (if needed) should be easier.
This commit is contained in:
parent
07f9cf670c
commit
66d59eb7ac
@ -62,14 +62,26 @@ pub struct Overload {
|
||||
pub void: bool,
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
/// Tracks the variations of the builtin already generated, this is needed because some
|
||||
/// builtins overloads can't be generated unless explicitly used, since they might cause
|
||||
/// uneeded capabilities to be requested
|
||||
#[derive(Default)]
|
||||
pub struct BuiltinVariations: u32 {
|
||||
/// Request the standard overloads
|
||||
const STANDARD = 1 << 0;
|
||||
/// Request overloads that use the double type
|
||||
const DOUBLE = 1 << 1;
|
||||
/// Request overloads that use samplerCubeArray(Shadow)
|
||||
const CUBE_TEXTURES_ARRAY = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct FunctionDeclaration {
|
||||
pub overloads: Vec<Overload>,
|
||||
/// Whether or not this function has the name of a builtin.
|
||||
pub builtin: bool,
|
||||
/// If [`builtin`](Self::builtin) is true, this field indicates whether
|
||||
/// this function already has double overloads added or not. Otherwise, it is unused.
|
||||
pub double: bool,
|
||||
/// Tracks the builtin overload variations that were already generated
|
||||
pub variations: BuiltinVariations,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -1,11 +1,14 @@
|
||||
use super::{
|
||||
ast::{FunctionDeclaration, FunctionKind, Overload, ParameterInfo, ParameterQualifier},
|
||||
ast::{
|
||||
BuiltinVariations, FunctionDeclaration, FunctionKind, Overload, ParameterInfo,
|
||||
ParameterQualifier,
|
||||
},
|
||||
context::Context,
|
||||
Error, ErrorKind, Parser, Result,
|
||||
};
|
||||
use crate::{
|
||||
BinaryOperator, Block, Constant, DerivativeAxis, Expression, Handle, ImageClass,
|
||||
ImageDimension, ImageQuery, MathFunction, Module, RelationalFunction, SampleLevel,
|
||||
ImageDimension as Dim, ImageQuery, MathFunction, Module, RelationalFunction, SampleLevel,
|
||||
ScalarKind as Sk, Span, Type, TypeInner, VectorSize,
|
||||
};
|
||||
|
||||
@ -67,85 +70,30 @@ fn make_coords_arg(number_of_components: usize, kind: Sk) -> TypeInner {
|
||||
}
|
||||
}
|
||||
|
||||
/// Inject builtins into
|
||||
/// Inject builtins into the declaration
|
||||
///
|
||||
/// This is done to not add a large startup cost and not increase memory
|
||||
/// usage if it isn't needed.
|
||||
///
|
||||
/// This version does not add builtins with arguments using the double type
|
||||
/// [`inject_double_builtin`](inject_double_builtin) for builtins
|
||||
/// using the double type
|
||||
pub fn inject_builtin(declaration: &mut FunctionDeclaration, module: &mut Module, name: &str) {
|
||||
use crate::ImageDimension as Dim;
|
||||
pub fn inject_builtin(
|
||||
declaration: &mut FunctionDeclaration,
|
||||
module: &mut Module,
|
||||
name: &str,
|
||||
mut variations: BuiltinVariations,
|
||||
) {
|
||||
// Don't regeneate variations
|
||||
variations.remove(declaration.variations);
|
||||
declaration.variations |= variations;
|
||||
|
||||
if variations.contains(BuiltinVariations::STANDARD) {
|
||||
inject_standard_builtins(declaration, module, name)
|
||||
}
|
||||
|
||||
if variations.contains(BuiltinVariations::DOUBLE) {
|
||||
inject_double_builtin(declaration, module, name)
|
||||
}
|
||||
|
||||
declaration.builtin = true;
|
||||
let width = 4;
|
||||
match name {
|
||||
"sampler1D" | "sampler1DArray" | "sampler2D" | "sampler2DArray" | "sampler2DMS"
|
||||
| "sampler2DMSArray" | "sampler3D" | "samplerCube" | "samplerCubeArray" => {
|
||||
declaration.overloads.push(module.add_builtin(
|
||||
vec![
|
||||
TypeInner::Image {
|
||||
dim: match name {
|
||||
"sampler1D" | "sampler1DArray" => Dim::D1,
|
||||
"sampler2D" | "sampler2DArray" | "sampler2DMS" | "sampler2DMSArray" => {
|
||||
Dim::D2
|
||||
}
|
||||
"sampler3D" => Dim::D3,
|
||||
_ => Dim::Cube,
|
||||
},
|
||||
arrayed: matches!(
|
||||
name,
|
||||
"sampler1DArray"
|
||||
| "sampler2DArray"
|
||||
| "sampler2DMSArray"
|
||||
| "samplerCubeArray"
|
||||
),
|
||||
class: ImageClass::Sampled {
|
||||
kind: Sk::Float,
|
||||
multi: matches!(name, "sampler2DMS" | "sampler2DMSArray"),
|
||||
},
|
||||
},
|
||||
TypeInner::Sampler { comparison: false },
|
||||
],
|
||||
MacroCall::Sampler,
|
||||
))
|
||||
}
|
||||
"sampler1DShadow"
|
||||
| "sampler1DArrayShadow"
|
||||
| "sampler2DShadow"
|
||||
| "sampler2DArrayShadow"
|
||||
| "samplerCubeShadow"
|
||||
| "samplerCubeArrayShadow" => {
|
||||
let dim = match name {
|
||||
"sampler1DShadow" | "sampler1DArrayShadow" => Dim::D1,
|
||||
"sampler2DShadow" | "sampler2DArrayShadow" => Dim::D2,
|
||||
_ => Dim::Cube,
|
||||
};
|
||||
let arrayed = matches!(
|
||||
name,
|
||||
"sampler1DArrayShadow" | "sampler2DArrayShadow" | "samplerCubeArrayShadow"
|
||||
);
|
||||
|
||||
for i in 0..2 {
|
||||
let ty = TypeInner::Image {
|
||||
dim,
|
||||
arrayed,
|
||||
class: match i {
|
||||
0 => ImageClass::Sampled {
|
||||
kind: Sk::Float,
|
||||
multi: false,
|
||||
},
|
||||
_ => ImageClass::Depth { multi: false },
|
||||
},
|
||||
};
|
||||
|
||||
declaration.overloads.push(module.add_builtin(
|
||||
vec![ty, TypeInner::Sampler { comparison: true }],
|
||||
MacroCall::SamplerShadow,
|
||||
))
|
||||
}
|
||||
}
|
||||
"texture"
|
||||
| "textureGrad"
|
||||
| "textureGradOffset"
|
||||
@ -273,7 +221,7 @@ pub fn inject_builtin(declaration: &mut FunctionDeclaration, module: &mut Module
|
||||
if lod || grad || offset || proj || bias {
|
||||
continue;
|
||||
}
|
||||
debug_assert!(dim == ImageDimension::Cube && shadow && arrayed);
|
||||
debug_assert!(dim == Dim::Cube && shadow && arrayed);
|
||||
}
|
||||
debug_assert!(num_coords <= 5);
|
||||
|
||||
@ -318,7 +266,7 @@ pub fn inject_builtin(declaration: &mut FunctionDeclaration, module: &mut Module
|
||||
}
|
||||
};
|
||||
|
||||
texture_args_generator(TextureArgsOptions::SHADOW, f)
|
||||
texture_args_generator(TextureArgsOptions::SHADOW | variations.into(), f)
|
||||
}
|
||||
"textureSize" => {
|
||||
let f = |kind, dim, arrayed, multi, shadow| {
|
||||
@ -347,7 +295,10 @@ pub fn inject_builtin(declaration: &mut FunctionDeclaration, module: &mut Module
|
||||
.push(module.add_builtin(args, MacroCall::TextureSize { arrayed }))
|
||||
};
|
||||
|
||||
texture_args_generator(TextureArgsOptions::all(), f)
|
||||
texture_args_generator(
|
||||
TextureArgsOptions::SHADOW | TextureArgsOptions::MULTI | variations.into(),
|
||||
f,
|
||||
)
|
||||
}
|
||||
"texelFetch" => {
|
||||
let f = |kind, dim, arrayed, multi, _shadow| {
|
||||
@ -380,7 +331,7 @@ pub fn inject_builtin(declaration: &mut FunctionDeclaration, module: &mut Module
|
||||
};
|
||||
|
||||
// Don't generate shadow images since they aren't supported
|
||||
texture_args_generator(TextureArgsOptions::MULTI, f)
|
||||
texture_args_generator(TextureArgsOptions::MULTI | variations.into(), f)
|
||||
}
|
||||
"imageSize" => {
|
||||
let f = |kind: Sk, dim, arrayed, _, _| {
|
||||
@ -404,7 +355,7 @@ pub fn inject_builtin(declaration: &mut FunctionDeclaration, module: &mut Module
|
||||
.push(module.add_builtin(vec![image], MacroCall::TextureSize { arrayed }))
|
||||
};
|
||||
|
||||
texture_args_generator(TextureArgsOptions::empty(), f)
|
||||
texture_args_generator(variations.into(), f)
|
||||
}
|
||||
"imageLoad" => {
|
||||
let f = |kind: Sk, dim, arrayed, _, _| {
|
||||
@ -443,7 +394,7 @@ pub fn inject_builtin(declaration: &mut FunctionDeclaration, module: &mut Module
|
||||
};
|
||||
|
||||
// Don't generate shadow nor multisampled images since they aren't supported
|
||||
texture_args_generator(TextureArgsOptions::empty(), f)
|
||||
texture_args_generator(variations.into(), f)
|
||||
}
|
||||
"imageStore" => {
|
||||
let f = |kind: Sk, dim, arrayed, _, _| {
|
||||
@ -490,7 +441,84 @@ pub fn inject_builtin(declaration: &mut FunctionDeclaration, module: &mut Module
|
||||
};
|
||||
|
||||
// Don't generate shadow nor multisampled images since they aren't supported
|
||||
texture_args_generator(TextureArgsOptions::empty(), f)
|
||||
texture_args_generator(variations.into(), f)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Injects the builtins into declaration that don't need any special variations
|
||||
fn inject_standard_builtins(
|
||||
declaration: &mut FunctionDeclaration,
|
||||
module: &mut Module,
|
||||
name: &str,
|
||||
) {
|
||||
let width = 4;
|
||||
match name {
|
||||
"sampler1D" | "sampler1DArray" | "sampler2D" | "sampler2DArray" | "sampler2DMS"
|
||||
| "sampler2DMSArray" | "sampler3D" | "samplerCube" | "samplerCubeArray" => {
|
||||
declaration.overloads.push(module.add_builtin(
|
||||
vec![
|
||||
TypeInner::Image {
|
||||
dim: match name {
|
||||
"sampler1D" | "sampler1DArray" => Dim::D1,
|
||||
"sampler2D" | "sampler2DArray" | "sampler2DMS" | "sampler2DMSArray" => {
|
||||
Dim::D2
|
||||
}
|
||||
"sampler3D" => Dim::D3,
|
||||
_ => Dim::Cube,
|
||||
},
|
||||
arrayed: matches!(
|
||||
name,
|
||||
"sampler1DArray"
|
||||
| "sampler2DArray"
|
||||
| "sampler2DMSArray"
|
||||
| "samplerCubeArray"
|
||||
),
|
||||
class: ImageClass::Sampled {
|
||||
kind: Sk::Float,
|
||||
multi: matches!(name, "sampler2DMS" | "sampler2DMSArray"),
|
||||
},
|
||||
},
|
||||
TypeInner::Sampler { comparison: false },
|
||||
],
|
||||
MacroCall::Sampler,
|
||||
))
|
||||
}
|
||||
"sampler1DShadow"
|
||||
| "sampler1DArrayShadow"
|
||||
| "sampler2DShadow"
|
||||
| "sampler2DArrayShadow"
|
||||
| "samplerCubeShadow"
|
||||
| "samplerCubeArrayShadow" => {
|
||||
let dim = match name {
|
||||
"sampler1DShadow" | "sampler1DArrayShadow" => Dim::D1,
|
||||
"sampler2DShadow" | "sampler2DArrayShadow" => Dim::D2,
|
||||
_ => Dim::Cube,
|
||||
};
|
||||
let arrayed = matches!(
|
||||
name,
|
||||
"sampler1DArrayShadow" | "sampler2DArrayShadow" | "samplerCubeArrayShadow"
|
||||
);
|
||||
|
||||
for i in 0..2 {
|
||||
let ty = TypeInner::Image {
|
||||
dim,
|
||||
arrayed,
|
||||
class: match i {
|
||||
0 => ImageClass::Sampled {
|
||||
kind: Sk::Float,
|
||||
multi: false,
|
||||
},
|
||||
_ => ImageClass::Depth { multi: false },
|
||||
},
|
||||
};
|
||||
|
||||
declaration.overloads.push(module.add_builtin(
|
||||
vec![ty, TypeInner::Sampler { comparison: true }],
|
||||
MacroCall::SamplerShadow,
|
||||
))
|
||||
}
|
||||
}
|
||||
"sin" | "exp" | "exp2" | "sinh" | "cos" | "cosh" | "tan" | "tanh" | "acos" | "asin"
|
||||
| "log" | "log2" | "radians" | "degrees" | "asinh" | "acosh" | "atanh"
|
||||
@ -961,13 +989,8 @@ pub fn inject_builtin(declaration: &mut FunctionDeclaration, module: &mut Module
|
||||
}
|
||||
}
|
||||
|
||||
/// Double version of [`inject_builtin`](inject_builtin)
|
||||
pub fn inject_double_builtin(
|
||||
declaration: &mut FunctionDeclaration,
|
||||
module: &mut Module,
|
||||
name: &str,
|
||||
) {
|
||||
declaration.double = true;
|
||||
/// Injects the builtins into declaration that need doubles
|
||||
fn inject_double_builtin(declaration: &mut FunctionDeclaration, module: &mut Module, name: &str) {
|
||||
let width = 8;
|
||||
match name {
|
||||
"abs" | "sign" => {
|
||||
@ -1114,6 +1137,7 @@ pub fn inject_double_builtin(
|
||||
}
|
||||
}
|
||||
|
||||
/// Injects the builtins into declaration that can used either float or doubles
|
||||
fn inject_common_builtin(
|
||||
declaration: &mut FunctionDeclaration,
|
||||
module: &mut Module,
|
||||
@ -1512,7 +1536,7 @@ fn inject_common_builtin(
|
||||
}
|
||||
}
|
||||
// The function isn't a builtin or we don't yet support it
|
||||
_ => declaration.builtin = false,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2028,10 +2052,10 @@ impl Parser {
|
||||
} = *self.resolve_type(ctx, image, meta)?
|
||||
{
|
||||
let image_size = match dim {
|
||||
ImageDimension::D1 => None,
|
||||
ImageDimension::D2 => Some(VectorSize::Bi),
|
||||
ImageDimension::D3 => Some(VectorSize::Tri),
|
||||
ImageDimension::Cube => Some(VectorSize::Tri),
|
||||
Dim::D1 => None,
|
||||
Dim::D2 => Some(VectorSize::Bi),
|
||||
Dim::D3 => Some(VectorSize::Tri),
|
||||
Dim::Cube => Some(VectorSize::Tri),
|
||||
};
|
||||
let coord_size = match *self.resolve_type(ctx, coord, meta)? {
|
||||
TypeInner::Vector { size, .. } => Some(size),
|
||||
@ -2060,7 +2084,7 @@ impl Parser {
|
||||
|
||||
let mut coord_index = image_size.map_or(1, |s| s as u32);
|
||||
|
||||
let array_index = if arrayed && !(storage && dim == ImageDimension::Cube) {
|
||||
let array_index = if arrayed && !(storage && dim == Dim::Cube) {
|
||||
let index = coord_index;
|
||||
coord_index += 1;
|
||||
|
||||
@ -2174,6 +2198,23 @@ bitflags::bitflags! {
|
||||
const MULTI = 1 << 0;
|
||||
/// Generates shadow variants of images
|
||||
const SHADOW = 1 << 1;
|
||||
/// Generates standard images
|
||||
const STANDARD = 1 << 2;
|
||||
/// Generates cube arrayed images
|
||||
const CUBE_ARRAY = 1 << 3;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BuiltinVariations> for TextureArgsOptions {
|
||||
fn from(variations: BuiltinVariations) -> Self {
|
||||
let mut options = TextureArgsOptions::empty();
|
||||
if variations.contains(BuiltinVariations::STANDARD) {
|
||||
options |= TextureArgsOptions::STANDARD
|
||||
}
|
||||
if variations.contains(BuiltinVariations::CUBE_TEXTURES_ARRAY) {
|
||||
options |= TextureArgsOptions::CUBE_ARRAY
|
||||
}
|
||||
options
|
||||
}
|
||||
}
|
||||
|
||||
@ -2188,13 +2229,19 @@ bitflags::bitflags! {
|
||||
/// see the struct documentation
|
||||
fn texture_args_generator(
|
||||
options: TextureArgsOptions,
|
||||
mut f: impl FnMut(crate::ScalarKind, ImageDimension, bool, bool, bool),
|
||||
mut f: impl FnMut(crate::ScalarKind, Dim, bool, bool, bool),
|
||||
) {
|
||||
use crate::ImageDimension as Dim;
|
||||
|
||||
for kind in [Sk::Float, Sk::Uint, Sk::Sint].iter().copied() {
|
||||
for dim in [Dim::D1, Dim::D2, Dim::D3, Dim::Cube].iter().copied() {
|
||||
for arrayed in [false, true].iter().copied() {
|
||||
if dim == Dim::Cube && arrayed {
|
||||
if !options.contains(TextureArgsOptions::CUBE_ARRAY) {
|
||||
continue;
|
||||
}
|
||||
} else if !options.contains(TextureArgsOptions::STANDARD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
f(kind, dim, arrayed, false, false);
|
||||
|
||||
// 3D images can't be neither arrayed nor shadow
|
||||
@ -2220,10 +2267,10 @@ fn texture_args_generator(
|
||||
|
||||
/// Helper functions used to convert from a image dimension into a integer representing the
|
||||
/// number of components needed for the coordinates vector (1 means scalar instead of vector)
|
||||
fn image_dims_to_coords_size(dim: ImageDimension) -> usize {
|
||||
fn image_dims_to_coords_size(dim: Dim) -> usize {
|
||||
match dim {
|
||||
ImageDimension::D1 => 1,
|
||||
ImageDimension::D2 => 2,
|
||||
Dim::D1 => 1,
|
||||
Dim::D2 => 2,
|
||||
_ => 3,
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::{
|
||||
ast::*,
|
||||
builtins::{inject_builtin, inject_double_builtin, sampled_to_depth},
|
||||
builtins::{inject_builtin, sampled_to_depth},
|
||||
context::{Context, ExprPos, StmtContext},
|
||||
error::{Error, ErrorKind},
|
||||
types::scalar_components,
|
||||
@ -602,26 +602,26 @@ impl Parser {
|
||||
raw_args: &[Handle<HirExpr>],
|
||||
meta: Span,
|
||||
) -> Result<Option<Handle<Expression>>> {
|
||||
// If the name for the function hasn't yet been initialized check if any
|
||||
// builtin can be injected.
|
||||
if self.lookup_function.get(&name).is_none() {
|
||||
let declaration = self.lookup_function.entry(name.clone()).or_default();
|
||||
inject_builtin(declaration, &mut self.module, &name);
|
||||
// Grow the typifier to be able to index it later without needing
|
||||
// to hold the context mutably
|
||||
for &(expr, span) in args.iter() {
|
||||
self.typifier_grow(ctx, expr, span)?;
|
||||
}
|
||||
|
||||
// Check if any argument uses a double type
|
||||
let has_double = args
|
||||
.iter()
|
||||
.any(|&(expr, meta)| self.resolve_type(ctx, expr, meta).map_or(false, is_double));
|
||||
// Check if the passed arguments require any special variations
|
||||
let mut variations = builtin_required_variations(
|
||||
args.iter()
|
||||
.map(|&(expr, _)| ctx.typifier.get(expr, &self.module.types)),
|
||||
);
|
||||
|
||||
// At this point a declaration is guaranteed
|
||||
let declaration = self.lookup_function.get_mut(&name).unwrap();
|
||||
// Initiate the declaration if it wasn't previously initialized and inject builtins
|
||||
let declaration = self.lookup_function.entry(name.clone()).or_insert_with(|| {
|
||||
variations |= BuiltinVariations::STANDARD;
|
||||
Default::default()
|
||||
});
|
||||
inject_builtin(declaration, &mut self.module, &name, variations);
|
||||
|
||||
if declaration.builtin && !declaration.double && has_double {
|
||||
inject_double_builtin(declaration, &mut self.module, &name);
|
||||
}
|
||||
|
||||
// Borrow again but without mutability
|
||||
// Borrow again but without mutability, at this point a declaration is guaranteed
|
||||
let declaration = self.lookup_function.get(&name).unwrap();
|
||||
|
||||
// Possibly contains the overload to be used in the call
|
||||
@ -1026,11 +1026,6 @@ impl Parser {
|
||||
mut body: Block,
|
||||
meta: Span,
|
||||
) {
|
||||
if self.lookup_function.get(&name).is_none() {
|
||||
let declaration = self.lookup_function.entry(name.clone()).or_default();
|
||||
inject_builtin(declaration, &mut self.module, &name);
|
||||
}
|
||||
|
||||
ensure_block_returns(&mut body);
|
||||
|
||||
let void = result.is_none();
|
||||
@ -1041,7 +1036,16 @@ impl Parser {
|
||||
..
|
||||
} = self;
|
||||
|
||||
let declaration = lookup_function.entry(name.clone()).or_default();
|
||||
// Check if the passed arguments require any special variations
|
||||
let mut variations =
|
||||
builtin_required_variations(ctx.parameters.iter().map(|&arg| &module.types[arg].inner));
|
||||
|
||||
// Initiate the declaration if it wasn't previously initialized and inject builtins
|
||||
let declaration = lookup_function.entry(name.clone()).or_insert_with(|| {
|
||||
variations |= BuiltinVariations::STANDARD;
|
||||
Default::default()
|
||||
});
|
||||
inject_builtin(declaration, module, &name, variations);
|
||||
|
||||
let Context {
|
||||
expressions,
|
||||
@ -1052,15 +1056,6 @@ impl Parser {
|
||||
..
|
||||
} = ctx;
|
||||
|
||||
if declaration.builtin
|
||||
&& !declaration.double
|
||||
&& parameters
|
||||
.iter()
|
||||
.any(|ty| is_double(&module.types[*ty].inner))
|
||||
{
|
||||
inject_double_builtin(declaration, module, &name);
|
||||
}
|
||||
|
||||
let function = Function {
|
||||
name: Some(name),
|
||||
arguments,
|
||||
@ -1122,11 +1117,6 @@ impl Parser {
|
||||
result: Option<FunctionResult>,
|
||||
meta: Span,
|
||||
) {
|
||||
if self.lookup_function.get(&name).is_none() {
|
||||
let declaration = self.lookup_function.entry(name.clone()).or_default();
|
||||
inject_builtin(declaration, &mut self.module, &name);
|
||||
}
|
||||
|
||||
let void = result.is_none();
|
||||
|
||||
let &mut Parser {
|
||||
@ -1135,7 +1125,16 @@ impl Parser {
|
||||
..
|
||||
} = self;
|
||||
|
||||
let declaration = lookup_function.entry(name.clone()).or_default();
|
||||
// Check if the passed arguments require any special variations
|
||||
let mut variations =
|
||||
builtin_required_variations(ctx.parameters.iter().map(|&arg| &module.types[arg].inner));
|
||||
|
||||
// Initiate the declaration if it wasn't previously initialized and inject builtins
|
||||
let declaration = lookup_function.entry(name.clone()).or_insert_with(|| {
|
||||
variations |= BuiltinVariations::STANDARD;
|
||||
Default::default()
|
||||
});
|
||||
inject_builtin(declaration, module, &name, variations);
|
||||
|
||||
let Context {
|
||||
arguments,
|
||||
@ -1144,15 +1143,6 @@ impl Parser {
|
||||
..
|
||||
} = ctx;
|
||||
|
||||
if declaration.builtin
|
||||
&& !declaration.double
|
||||
&& parameters
|
||||
.iter()
|
||||
.any(|ty| is_double(&module.types[*ty].inner))
|
||||
{
|
||||
inject_double_builtin(declaration, module, &name);
|
||||
}
|
||||
|
||||
let function = Function {
|
||||
name: Some(name),
|
||||
arguments,
|
||||
@ -1404,16 +1394,6 @@ impl Parser {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_double(ty: &TypeInner) -> bool {
|
||||
match *ty {
|
||||
TypeInner::ValuePointer { kind, width, .. }
|
||||
| TypeInner::Scalar { kind, width }
|
||||
| TypeInner::Vector { kind, width, .. } => kind == ScalarKind::Float && width == 8,
|
||||
TypeInner::Matrix { width, .. } => width == 8,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper enum containing the type of conversion need for a call
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
enum Conversion {
|
||||
@ -1498,3 +1478,34 @@ fn conversion(target: &TypeInner, source: &TypeInner) -> Option<Conversion> {
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Helper method returning all the non standard builtin variations needed
|
||||
/// to process the function call with the passed arguments
|
||||
fn builtin_required_variations<'a>(args: impl Iterator<Item = &'a TypeInner>) -> BuiltinVariations {
|
||||
let mut variations = BuiltinVariations::empty();
|
||||
|
||||
for ty in args {
|
||||
match *ty {
|
||||
TypeInner::ValuePointer { kind, width, .. }
|
||||
| TypeInner::Scalar { kind, width }
|
||||
| TypeInner::Vector { kind, width, .. } => {
|
||||
if kind == ScalarKind::Float && width == 8 {
|
||||
variations |= BuiltinVariations::DOUBLE
|
||||
}
|
||||
}
|
||||
TypeInner::Matrix { width, .. } => {
|
||||
if width == 8 {
|
||||
variations |= BuiltinVariations::DOUBLE
|
||||
}
|
||||
}
|
||||
TypeInner::Image { dim, arrayed, .. } => {
|
||||
if dim == crate::ImageDimension::Cube && arrayed {
|
||||
variations |= BuiltinVariations::CUBE_TEXTURES_ARRAY
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
variations
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user