diff options
Diffstat (limited to 'third_party/webrender/glsl-to-cxx/src')
-rw-r--r-- | third_party/webrender/glsl-to-cxx/src/hir.rs | 999 | ||||
-rw-r--r-- | third_party/webrender/glsl-to-cxx/src/lib.rs | 354 |
2 files changed, 371 insertions, 982 deletions
diff --git a/third_party/webrender/glsl-to-cxx/src/hir.rs b/third_party/webrender/glsl-to-cxx/src/hir.rs index 287ae8d035b..710b50b7af2 100644 --- a/third_party/webrender/glsl-to-cxx/src/hir.rs +++ b/third_party/webrender/glsl-to-cxx/src/hir.rs @@ -1,38 +1,6 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Large chunks of this file are derived from the glsl crate which is: - * Copyright (c) 2018, Dimitri Sabadie <dimitri.sabadie@gmail.com> - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * * Neither the name of Dimitri Sabadie <dimitri.sabadie@gmail.com> nor the names of other - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use glsl::syntax; use glsl::syntax::{ArrayedIdentifier, ArraySpecifier, AssignmentOp, BinaryOp, Identifier}; @@ -77,7 +45,6 @@ pub enum SamplerFormat { RGBA32F, RGBA32I, R8, - RG8, } impl SamplerFormat { @@ -88,7 +55,6 @@ impl SamplerFormat { SamplerFormat::RGBA32F => Some("RGBA32F"), SamplerFormat::RGBA32I => Some("RGBA32I"), SamplerFormat::R8 => Some("R8"), - SamplerFormat::RG8 => Some("RG8"), } } } @@ -788,14 +754,6 @@ impl Type { array_sizes: None, } } - - pub fn new_array(kind: TypeKind, size: i32) -> Self { - Type { - kind, - precision: None, - array_sizes: Some(Box::new(ArraySizes { sizes: vec![make_const(TypeKind::Int, size)] })), - } - } } impl LiftFrom<&syntax::FullySpecifiedType> for Type { @@ -902,7 +860,7 @@ impl RunClass { #[derive(Debug, Clone, PartialEq)] pub enum SymDecl { - NativeFunction(FunctionType, Option<&'static str>, RunClass), + NativeFunction(FunctionType, Option<&'static str>), UserFunction(Rc<FunctionDefinition>, RunClass), Local(StorageClass, Type, RunClass), Global( @@ -969,8 +927,6 @@ pub struct State { modified_globals: RefCell<Vec<SymRef>>, pub used_globals: RefCell<Vec<SymRef>>, pub texel_fetches: HashMap<(SymRef, SymRef), TexelFetchOffsets>, - clip_dist_sym: SymRef, - pub used_clip_dist: u32, } impl State { @@ -986,8 +942,6 @@ impl State { modified_globals: RefCell::new(Vec::new()), used_globals: RefCell::new(Vec::new()), texel_fetches: HashMap::new(), - clip_dist_sym: SymRef(0), - used_clip_dist: 0, } } @@ -1795,9 +1749,6 @@ fn translate_variable_declaration( "r8" => { storage = StorageClass::Sampler(SamplerFormat::R8); } - "rg8" => { - storage = StorageClass::Sampler(SamplerFormat::RG8); - } _ => {} } } @@ -1904,33 +1855,11 @@ fn translate_declaration( syntax::Declaration::FunctionPrototype(p) => { Declaration::FunctionPrototype(translate_function_prototype(state, p)) } - syntax::Declaration::Global(ty, ids) => { - // glsl non-es supports requalifying variables, but we don't yet. - // However, we still want to allow global layout qualifiers for - // KHR_advanced_blend_equation. - if !ids.is_empty() { - panic!(); - } - let _ = for qual in &ty.qualifiers { - match qual { - syntax::TypeQualifierSpec::Layout(l) => { - for id in &l.ids { - match id { - syntax::LayoutQualifierSpec::Identifier(key, _) => { - match key.as_str() { - "blend_support_all_equations" => (), - _ => panic!(), - } - } - _ => panic!(), - } - } - } - syntax::TypeQualifierSpec::Storage(syntax::StorageQualifier::Out) => (), - _ => panic!(), - } - }; - Declaration::Global(lift_type_qualifier_for_declaration(state, &Some(ty.clone())).unwrap(), ids.clone()) + syntax::Declaration::Global(_ty, _ids) => { + panic!(); + // glsl non-es supports requalifying variables + // we don't right now + //Declaration::Global(..) } syntax::Declaration::InitDeclaratorList(dl) => { translate_init_declarator_list(state, dl, default_run_class) @@ -1944,9 +1873,6 @@ fn is_vector(ty: &Type) -> bool { TypeKind::Vec2 | TypeKind::Vec3 | TypeKind::Vec4 - | TypeKind::BVec2 - | TypeKind::BVec3 - | TypeKind::BVec4 | TypeKind::IVec2 | TypeKind::IVec3 | TypeKind::IVec4 => ty.array_sizes == None, @@ -1954,32 +1880,6 @@ fn is_vector(ty: &Type) -> bool { } } -fn index_vector(ty: &Type) -> Option<TypeKind> { - use TypeKind::*; - if ty.array_sizes != None { - return None; - } - Some(match ty.kind { - Vec2 => Float, - Vec3 => Float, - Vec4 => Float, - DVec2 => Double, - DVec3 => Double, - DVec4 => Double, - BVec2 => Bool, - BVec3 => Bool, - BVec4 => Bool, - IVec2 => Int, - IVec3 => Int, - IVec4 => Int, - UVec2 => UInt, - UVec3 => UInt, - UVec4 => UInt, - _ => return None, - }) - -} - fn index_matrix(ty: &Type) -> Option<TypeKind> { use TypeKind::*; if ty.array_sizes != None { @@ -2015,28 +1915,30 @@ fn is_ivec(ty: &Type) -> bool { } } -fn can_implicitly_convert_to(src: &Type, dst: &Type) -> bool { +fn compatible_type(lhs: &Type, rhs: &Type) -> bool { // XXX: use an underlying type helper - if src == &Type::new(TypeKind::Double) && dst == &Type::new(TypeKind::Float) { - // We're not supposed to implicitly convert from double to float but glsl 4 has a bug - // where it parses unannotated float constants as double. + if lhs == &Type::new(TypeKind::Double) && rhs == &Type::new(TypeKind::Float) { + true + } else if rhs == &Type::new(TypeKind::Double) && lhs == &Type::new(TypeKind::Float) { true - } else if dst == &Type::new(TypeKind::Double) && src == &Type::new(TypeKind::Float) { + } else if rhs == &Type::new(TypeKind::Int) && + (lhs == &Type::new(TypeKind::Float) || lhs == &Type::new(TypeKind::Double)) + { true - } else if (dst == &Type::new(TypeKind::Float) || dst == &Type::new(TypeKind::Double)) && - src == &Type::new(TypeKind::Int) + } else if (rhs == &Type::new(TypeKind::Float) || rhs == &Type::new(TypeKind::Double)) && + lhs == &Type::new(TypeKind::Int) { true - } else if (dst == &Type::new(TypeKind::Vec2) || dst == &Type::new(TypeKind::DVec2)) && - src == &Type::new(TypeKind::IVec2) + } else if (rhs == &Type::new(TypeKind::Vec2) || rhs == &Type::new(TypeKind::DVec2)) && + lhs == &Type::new(TypeKind::IVec2) { true - } else if dst == &Type::new(TypeKind::IVec2) && - (src == &Type::new(TypeKind::Vec2) || src == &Type::new(TypeKind::DVec2)) + } else if rhs == &Type::new(TypeKind::IVec2) && + (lhs == &Type::new(TypeKind::Vec2) || lhs == &Type::new(TypeKind::DVec2)) { true } else { - src.kind == dst.kind && src.array_sizes == dst.array_sizes + lhs.kind == rhs.kind && lhs.array_sizes == rhs.array_sizes } } @@ -2086,7 +1988,7 @@ pub fn is_output(expr: &Expr, state: &State) -> Option<SymRef> { match &expr.kind { ExprKind::Variable(i) => match state.sym(*i).decl { SymDecl::Global(storage, ..) => match storage { - StorageClass::In | StorageClass::Out => return Some(*i), + StorageClass::Out => return Some(*i), _ => {} }, SymDecl::Local(..) => {} @@ -2230,18 +2132,6 @@ fn translate_expression(state: &mut State, e: &syntax::Expr) -> Expr { if !globals.contains(&global) { globals.push(global); } - if global == state.clip_dist_sym { - if let ExprKind::Bracket(_, idx) = &lhs.kind { - // Get the constant array index used for gl_ClipDistance and add it to the used mask. - let idx = match idx.kind { - ExprKind::IntConst(idx) => idx, - ExprKind::UIntConst(idx) => idx as i32, - _ => panic!("bad index for gl_ClipDistance"), - }; - assert!(idx >= 0 && idx < 4); - state.used_clip_dist |= 1 << idx; - } - } } Expr { kind: ExprKind::Assignment(lhs, op.clone(), rhs), @@ -2251,23 +2141,28 @@ fn translate_expression(state: &mut State, e: &syntax::Expr) -> Expr { syntax::Expr::Binary(op, lhs, rhs) => { let lhs = Box::new(translate_expression(state, lhs)); let rhs = Box::new(translate_expression(state, rhs)); + let ty = if op == &BinaryOp::Mult { + if lhs.ty.kind == TypeKind::Mat3 && rhs.ty.kind == TypeKind::Vec3 { + rhs.ty.clone() + } else if lhs.ty.kind == TypeKind::Mat4 && rhs.ty.kind == TypeKind::Vec4 { + rhs.ty.clone() + } else if lhs.ty.kind == TypeKind::Mat2 && rhs.ty.kind == TypeKind::Vec2 { + rhs.ty.clone() + } else if lhs.ty.kind == TypeKind::Mat2 && rhs.ty.kind == TypeKind::Float { + lhs.ty.clone() + } else { + promoted_type(&lhs.ty, &rhs.ty) + } + } else { + promoted_type(&lhs.ty, &rhs.ty) + }; + + // comparison operators have a bool result let ty = match op { - BinaryOp::Equal | BinaryOp::NonEqual | BinaryOp::GT | BinaryOp::GTE | BinaryOp::LT | BinaryOp::LTE => { - // comparison operators have a bool result + BinaryOp::Equal | BinaryOp::GT | BinaryOp::GTE | BinaryOp::LT | BinaryOp::LTE => { Type::new(TypeKind::Bool) } - BinaryOp::Mult => { - match (lhs.ty.kind, rhs.ty.kind) { - (TypeKind::Mat2, TypeKind::Vec2) | - (TypeKind::Mat3, TypeKind::Vec3) | - (TypeKind::Mat4, TypeKind::Vec4) => rhs.ty.clone(), - (TypeKind::Mat2, TypeKind::Float) | - (TypeKind::Mat3, TypeKind::Float) | - (TypeKind::Mat4, TypeKind::Float) => lhs.ty.clone(), - _ => promoted_type(&lhs.ty, &rhs.ty), - } - } - _ => promoted_type(&lhs.ty, &rhs.ty), + _ => ty, }; Expr { @@ -2330,19 +2225,6 @@ fn translate_expression(state: &mut State, e: &syntax::Expr) -> Expr { .insert((sampler, base), TexelFetchOffsets::new(x, y)); } } - } else if name == "swgl_stepInterp" { - let mut globals = state.modified_globals.borrow_mut(); - for (i, sym) in state.syms.iter().enumerate() { - match &sym.borrow().decl { - SymDecl::Global(StorageClass::In, _, _, RunClass::Vector) => { - let symref = SymRef(i as u32); - if !globals.contains(&symref) { - globals.push(symref); - } - } - _ => {} - } - } } let sym = match state.lookup(name) { Some(s) => s, @@ -2358,31 +2240,19 @@ fn translate_expression(state: &mut State, e: &syntax::Expr) -> Expr { } } match &state.sym(sym).decl { - SymDecl::NativeFunction(fn_ty, _, _) => { - // Search for a signature where all parameter types are - // compatible. If there are many compatible signatures, - // then choose the one with the most exact matches. - // This is an approximation of the algorith described in - // the "Function Definitions" section of the spec. + SymDecl::NativeFunction(fn_ty, _) => { let mut ret = None; - let mut best_score = 0; - 'next_sig: for sig in &fn_ty.signatures { - let mut score = 0; + for sig in &fn_ty.signatures { + let mut matching = true; for (e, p) in params.iter().zip(sig.params.iter()) { - if e.ty == *p { - score += 1; - } else if !can_implicitly_convert_to(&e.ty, p) { - continue 'next_sig; + if !compatible_type(&e.ty, p) { + matching = false; + break; } } - if score >= best_score { + if matching { ret = Some(sig.ret.clone()); - best_score = score; - // If all parameters match exactly, then there - // is no need to search for other matches. - if best_score >= params.len() { - break; - } + break; } } ret_ty = match ret { @@ -2417,7 +2287,7 @@ fn translate_expression(state: &mut State, e: &syntax::Expr) -> Expr { } _ => {} } - can_implicitly_convert_to(&e.ty, &d.ty) + compatible_type(&e.ty, &d.ty) } FunctionParameterDeclaration::Unnamed(..) => panic!(), }; @@ -2438,7 +2308,6 @@ fn translate_expression(state: &mut State, e: &syntax::Expr) -> Expr { syntax::Expr::Variable(i) => match i.as_str() { "vec4" => TypeKind::Vec4, "vec2" => TypeKind::Vec2, - "int" => TypeKind::Int, _ => panic!("unexpected type constructor {:?}", i), }, _ => panic!(), @@ -2563,8 +2432,8 @@ fn translate_expression(state: &mut State, e: &syntax::Expr) -> Expr { } syntax::Expr::Bracket(e, specifier) => { let e = Box::new(translate_expression(state, e)); - let ty = if let Some(ty) = index_vector(&e.ty) { - Type::new(ty) + let ty = if is_vector(&e.ty) { + Type::new(TypeKind::Float) } else if let Some(ty) = index_matrix(&e.ty) { Type::new(ty) } else { @@ -2895,13 +2764,12 @@ fn translate_external_declaration( } } -fn declare_function_ext( +fn declare_function( state: &mut State, name: &str, cxx_name: Option<&'static str>, ret: Type, params: Vec<Type>, - run_class: RunClass, ) { let sig = FunctionSignature { ret, params }; match state.lookup_sym_mut(name) { @@ -2917,7 +2785,6 @@ fn declare_function_ext( signatures: NonEmpty::new(sig), }, cxx_name, - run_class, ), ); } @@ -2926,16 +2793,6 @@ fn declare_function_ext( //state.declare(name, Type::Function(FunctionType{ v})) } -fn declare_function( - state: &mut State, - name: &str, - cxx_name: Option<&'static str>, - ret: Type, - params: Vec<Type>, -) { - declare_function_ext(state, name, cxx_name, ret, params, RunClass::Unknown) -} - pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> TranslationUnit { // global scope state.push_scope("global".into()); @@ -2952,13 +2809,6 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio "vec2", Some("make_vec2"), Type::new(Vec2), - vec![Type::new(Float), Type::new(Float)], - ); - declare_function( - state, - "vec2", - Some("make_vec2"), - Type::new(Vec2), vec![Type::new(IVec2)], ); declare_function( @@ -2994,13 +2844,6 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio "vec4", Some("make_vec4"), Type::new(Vec4), - vec![Type::new(Float)], - ); - declare_function( - state, - "vec4", - Some("make_vec4"), - Type::new(Vec4), vec![Type::new(Vec3), Type::new(Float)], ); declare_function( @@ -3053,32 +2896,12 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio ); declare_function( state, - "bvec3", - Some("make_bvec3"), - Type::new(BVec3), - vec![Type::new(Bool)], - ); - declare_function( - state, - "bvec4", - Some("make_bvec4"), - Type::new(BVec4), - vec![Type::new(Bool)], - ); - declare_function( - state, "bvec4", Some("make_bvec4"), Type::new(BVec4), vec![Type::new(BVec2), Type::new(BVec2)], ); - declare_function( - state, - "bvec4", - Some("make_bvec4"), - Type::new(BVec4), - vec![Type::new(Bool), Type::new(Bool), Type::new(Bool), Type::new(Bool)], - ); + declare_function( state, "int", @@ -3166,13 +2989,6 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio "ivec4", Some("make_ivec4"), Type::new(IVec4), - vec![Type::new(Vec4)], - ); - declare_function( - state, - "ivec4", - Some("make_ivec4"), - Type::new(IVec4), vec![Type::new(IVec2), Type::new(Int), Type::new(Int)], ); @@ -3267,9 +3083,6 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio declare_function(state, "abs", None, Type::new(Vec2), vec![Type::new(Vec2)]); declare_function(state, "abs", None, Type::new(Vec3), vec![Type::new(Vec3)]); declare_function(state, "abs", None, Type::new(Float), vec![Type::new(Float)]); - declare_function(state, "sign", None, Type::new(Vec2), vec![Type::new(Vec2)]); - declare_function(state, "sign", None, Type::new(Vec3), vec![Type::new(Vec3)]); - declare_function(state, "sign", None, Type::new(Float), vec![Type::new(Float)]); declare_function( state, "dot", @@ -3284,38 +3097,56 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio Type::new(Float), vec![Type::new(Vec2), Type::new(Vec2)], ); - for t in &[Vec2, Vec3, Vec4] { - declare_function( - state, - "min", - None, - Type::new(*t), - vec![Type::new(*t), Type::new(Float)], - ); - declare_function( - state, - "max", - None, - Type::new(*t), - vec![Type::new(*t), Type::new(Float)], - ); - } - for t in &[Int, Float, Vec2, Vec3, Vec4] { - declare_function( - state, - "min", - None, - Type::new(*t), - vec![Type::new(*t), Type::new(*t)], - ); - declare_function( - state, - "max", - None, - Type::new(*t), - vec![Type::new(*t), Type::new(*t)], - ); - } + declare_function( + state, + "min", + None, + Type::new(Float), + vec![Type::new(Float), Type::new(Float)], + ); + declare_function( + state, + "min", + None, + Type::new(Vec2), + vec![Type::new(Vec2), Type::new(Vec2)], + ); + declare_function( + state, + "min", + None, + Type::new(Vec3), + vec![Type::new(Vec3), Type::new(Vec3)], + ); + + declare_function( + state, + "max", + None, + Type::new(Float), + vec![Type::new(Float), Type::new(Float)], + ); + declare_function( + state, + "max", + None, + Type::new(Vec2), + vec![Type::new(Vec2), Type::new(Vec2)], + ); + declare_function( + state, + "max", + None, + Type::new(Vec2), + vec![Type::new(Vec2), Type::new(Float)], + ); + declare_function( + state, + "max", + None, + Type::new(Vec3), + vec![Type::new(Vec3), Type::new(Vec3)], + ); declare_function( state, @@ -3405,152 +3236,96 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio state, "step", None, - Type::new(Vec2), - vec![Type::new(Float), Type::new(Vec2)], - ); - declare_function( - state, - "step", - None, Type::new(Vec3), vec![Type::new(Vec3), Type::new(Vec3)], ); declare_function( state, - "step", - None, - Type::new(Vec4), - vec![Type::new(Float), Type::new(Vec4)], - ); - declare_function( - state, "notEqual", None, Type::new(BVec4), vec![Type::new(IVec4), Type::new(IVec4)], ); - declare_function_ext( + declare_function( state, "fwidth", None, Type::new(Vec2), vec![Type::new(Vec2)], - RunClass::Scalar, ); - declare_function_ext( + declare_function(state, "cos", None, Type::new(Float), vec![Type::new(Float)]); + declare_function(state, "sin", None, Type::new(Float), vec![Type::new(Float)]); + declare_function(state, "tan", None, Type::new(Float), vec![Type::new(Float)]); + declare_function(state, "atan", None, Type::new(Float), vec![Type::new(Float)]); + declare_function(state, "atan", None, Type::new(Float), vec![Type::new(Float), Type::new(Float)]); + declare_function( state, - "dFdx", + "clamp", None, - Type::new(Float), - vec![Type::new(Float)], - RunClass::Scalar, + Type::new(Vec3), + vec![Type::new(Vec3), Type::new(Float), Type::new(Float)], ); - declare_function_ext( + declare_function( state, - "dFdx", + "clamp", + None, + Type::new(Double), + vec![Type::new(Double), Type::new(Double), Type::new(Double)], + ); + declare_function( + state, + "clamp", None, Type::new(Vec2), - vec![Type::new(Vec2)], - RunClass::Scalar, + vec![Type::new(Vec2), Type::new(Vec2), Type::new(Vec2)], ); - - declare_function(state, "cos", None, Type::new(Float), vec![Type::new(Float)]); - declare_function(state, "sin", None, Type::new(Float), vec![Type::new(Float)]); - declare_function(state, "tan", None, Type::new(Float), vec![Type::new(Float)]); - declare_function(state, "atan", None, Type::new(Float), vec![Type::new(Float)]); - declare_function(state, "atan", None, Type::new(Float), vec![Type::new(Float), Type::new(Float)]); - for t in &[Vec2, Vec3, Vec4] { - declare_function( - state, - "clamp", - None, - Type::new(*t), - vec![Type::new(*t), Type::new(Float), Type::new(Float)], - ); - } - for t in &[Float, Vec2, Vec3, Vec4] { - declare_function( - state, - "clamp", - None, - Type::new(*t), - vec![Type::new(*t), Type::new(*t), Type::new(*t)], - ); - } declare_function( state, - "length", + "clamp", None, - Type::new(Float), - vec![Type::new(Vec2)], + Type::new(Vec3), + vec![Type::new(Vec3), Type::new(Vec3), Type::new(Vec3)], ); - declare_function(state, "pow", None, Type::new(Vec3), vec![Type::new(Vec3)]); - declare_function(state, "pow", None, Type::new(Float), vec![Type::new(Float)]); - declare_function(state, "exp", None, Type::new(Float), vec![Type::new(Float)]); - declare_function(state, "exp2", None, Type::new(Float), vec![Type::new(Float)]); - declare_function(state, "log", None, Type::new(Float), vec![Type::new(Float)]); - declare_function(state, "log2", None, Type::new(Float), vec![Type::new(Float)]); - for t in &[Float, Vec2] { - // recip is non-standard - declare_function( - state, - "recip", - None, - Type::new(*t), - vec![Type::new(*t)], - ); - declare_function( - state, - "inversesqrt", - None, - Type::new(*t), - vec![Type::new(*t)], - ); - declare_function( - state, - "sqrt", - None, - Type::new(*t), - vec![Type::new(*t)], - ); - } declare_function( state, - "distance", + "clamp", None, - Type::new(Float), - vec![Type::new(Vec2), Type::new(Vec2)], + Type::new(Vec4), + vec![Type::new(Vec4), Type::new(Vec4), Type::new(Vec4)], ); - declare_function( state, - "equal", + "length", None, - Type::new(BVec2), - vec![Type::new(Vec2), Type::new(Vec2)], + Type::new(Float), + vec![Type::new(Vec2)], ); + declare_function(state, "pow", None, Type::new(Vec3), vec![Type::new(Vec3)]); + declare_function(state, "pow", None, Type::new(Float), vec![Type::new(Float)]); + declare_function(state, "exp", None, Type::new(Float), vec![Type::new(Float)]); declare_function( state, - "equal", + "inversesqrt", None, - Type::new(BVec4), - vec![Type::new(Vec4), Type::new(Vec4)], + Type::new(Float), + vec![Type::new(Float)], ); declare_function( state, - "notEqual", + "sqrt", None, - Type::new(BVec2), - vec![Type::new(Vec2), Type::new(Vec2)], + Type::new(Float), + vec![Type::new(Float)], ); declare_function( state, - "notEqual", + "distance", None, - Type::new(BVec4), - vec![Type::new(Vec4), Type::new(Vec4)], + Type::new(Float), + vec![Type::new(Vec2), Type::new(Vec2)], ); + declare_function( state, "lessThanEqual", @@ -3581,13 +3356,6 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio ); declare_function( state, - "lessThan", - None, - Type::new(BVec4), - vec![Type::new(Vec4), Type::new(Vec4)], - ); - declare_function( - state, "greaterThan", None, Type::new(BVec2), @@ -3595,13 +3363,6 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio ); declare_function( state, - "greaterThan", - None, - Type::new(BVec4), - vec![Type::new(Vec4), Type::new(Vec4)], - ); - declare_function( - state, "greaterThanEqual", None, Type::new(BVec2), @@ -3611,7 +3372,7 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio state, "greaterThanEqual", None, - Type::new(BVec4), + Type::new(BVec2), vec![Type::new(Vec4), Type::new(Vec4)], ); declare_function(state, "any", None, Type::new(Bool), vec![Type::new(BVec2)]); @@ -3631,22 +3392,22 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio state, "floor", None, - Type::new(Float), - vec![Type::new(Float)], + Type::new(Double), + vec![Type::new(Double)], ); declare_function( state, "ceil", None, - Type::new(Float), - vec![Type::new(Float)], + Type::new(Double), + vec![Type::new(Double)], ); declare_function( state, "round", None, - Type::new(Float), - vec![Type::new(Float)], + Type::new(Double), + vec![Type::new(Double)], ); declare_function( state, @@ -3655,13 +3416,6 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio Type::new(Float), vec![Type::new(Float)], ); - declare_function( - state, - "fract", - None, - Type::new(Vec2), - vec![Type::new(Vec2)], - ); declare_function(state, "mod", None, Type::new(Vec2), vec![Type::new(Vec2)]); declare_function(state, "mod", None, Type::new(Float), vec![Type::new(Float)]); @@ -3676,6 +3430,13 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio state, "texelFetch", None, + Type::new(Vec4), + vec![Type::new(Sampler2DArray), Type::new(IVec3), Type::new(Int)], + ); + declare_function( + state, + "texelFetch", + None, Type::new(IVec4), vec![Type::new(ISampler2D), Type::new(IVec2), Type::new(Int)], ); @@ -3719,6 +3480,27 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio ); declare_function( state, + "texture", + None, + Type::new(Vec4), + vec![Type::new(Sampler2DArray), Type::new(Vec3)], + ); + declare_function( + state, + "textureLod", + None, + Type::new(Vec4), + vec![Type::new(Sampler2DArray), Type::new(Vec3), Type::new(Float)], + ); + declare_function( + state, + "textureSize", + None, + Type::new(IVec3), + vec![Type::new(Sampler2DArray), Type::new(Int)], + ); + declare_function( + state, "textureSize", None, Type::new(IVec2), @@ -3765,417 +3547,6 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio "gl_Position", SymDecl::Global(StorageClass::Out, None, Type::new(Vec4), RunClass::Vector), ); - state.clip_dist_sym = state.declare( - "gl_ClipDistance", - SymDecl::Global(StorageClass::Out, None, Type::new_array(Float, 4), RunClass::Vector), - ); - - state.declare( - "swgl_SpanLength", - SymDecl::Global(StorageClass::In, None, Type::new(Int), RunClass::Scalar), - ); - state.declare( - "swgl_StepSize", - SymDecl::Global(StorageClass::Const, None, Type::new(Int), RunClass::Scalar), - ); - - for t in &[Float, Vec2, Vec3, Vec4, Int, IVec2, IVec3, IVec4, Mat3, Mat4] { - declare_function_ext( - state, - "swgl_forceScalar", - None, - Type::new(*t), - vec![Type::new(*t)], - RunClass::Scalar, - ); - } - - // GL_ARB_shader_group_vote - for (name, cxx_name) in &[("anyInvocations", "test_any"), - ("allInvocations", "test_all"), - ("allInvocationsEqual", "test_equal")] { - declare_function_ext( - state, - name, - Some(cxx_name), - Type::new(Bool), - vec![Type::new(Bool)], - RunClass::Scalar, - ); - } - - declare_function( - state, - "swgl_stepInterp", - None, - Type::new(Void), - vec![], - ); - - for t in &[Float, Vec2, Vec3, Vec4] { - declare_function_ext( - state, - "swgl_interpStep", - None, - Type::new(*t), - vec![Type::new(*t)], - RunClass::Scalar, - ); - } - - declare_function( - state, - "swgl_commitPartialSolidRGBA8", - None, - Type::new(Void), - vec![Type::new(Int), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitPartialSolidR8", - None, - Type::new(Void), - vec![Type::new(Int), Type::new(Float)], - ); - declare_function( - state, - "swgl_commitSolidRGBA8", - None, - Type::new(Void), - vec![Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitSolidR8", - None, - Type::new(Void), - vec![Type::new(Float)], - ); - declare_function( - state, - "swgl_commitColorRGBA8", - None, - Type::new(Void), - vec![Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitColorR8", - None, - Type::new(Void), - vec![Type::new(Float)], - ); - declare_function( - state, - "swgl_blendDropShadow", - None, - Type::new(Void), - vec![Type::new(Vec4)], - ); - declare_function( - state, - "swgl_blendSubpixelText", - None, - Type::new(Void), - vec![Type::new(Vec4)], - ); - declare_function( - state, - "swgl_clipMask", - None, - Type::new(Void), - vec![Type::new(Sampler2D), Type::new(Vec2), Type::new(Vec2), Type::new(Vec2)], - ); - declare_function( - state, - "swgl_antiAlias", - None, - Type::new(Void), - vec![Type::new(Int)], - ); - declare_function( - state, - "swgl_antiAlias", - None, - Type::new(Void), - vec![Type::new(BVec4)], - ); - declare_function_ext( - state, - "swgl_validateGradient", - None, - Type::new(Int), - vec![Type::new(Sampler2D), Type::new(IVec2), Type::new(Int)], - RunClass::Scalar, - ); - declare_function( - state, - "swgl_commitLinearGradientRGBA8", - None, - Type::new(Void), - vec![Type::new(Sampler2D), Type::new(Int), Type::new(Float), Type::new(Bool), Type::new(Float)], - ); - declare_function( - state, - "swgl_commitRadialGradientRGBA8", - None, - Type::new(Void), - vec![Type::new(Sampler2D), Type::new(Int), Type::new(Float), Type::new(Bool), Type::new(Vec2), - Type::new(Float)], - ); - declare_function( - state, - "swgl_commitGradientRGBA8", - None, - Type::new(Void), - vec![Type::new(Sampler2D), Type::new(Int), Type::new(Float)], - ); - declare_function( - state, - "swgl_commitGradientColorRGBA8", - None, - Type::new(Void), - vec![Type::new(Sampler2D), Type::new(Int), Type::new(Float), Type::new(Float)], - ); - for s in &[Sampler2D, Sampler2DRect] { - declare_function_ext( - state, - "swgl_isTextureLinear", - None, - Type::new(Bool), - vec![Type::new(*s)], - RunClass::Scalar, - ); - declare_function_ext( - state, - "swgl_isTextureRGBA8", - None, - Type::new(Bool), - vec![Type::new(*s)], - RunClass::Scalar, - ); - declare_function_ext( - state, - "swgl_isTextureR8", - None, - Type::new(Bool), - vec![Type::new(*s)], - RunClass::Scalar, - ); - declare_function( - state, - "swgl_commitTextureLinearRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitTextureLinearR8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitTextureLinearR8ToRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitPartialTextureLinearR8", - None, - Type::new(Void), - vec![Type::new(Int), Type::new(*s), Type::new(Vec2), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitPartialTextureLinearInvertR8", - None, - Type::new(Void), - vec![Type::new(Int), Type::new(*s), Type::new(Vec2), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitTextureLinearColorRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitTextureLinearColorRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Float)], - ); - declare_function( - state, - "swgl_commitTextureLinearColorR8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Float)], - ); - declare_function( - state, - "swgl_commitTextureLinearColorR8ToRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Vec4)], - ); - - declare_function( - state, - "swgl_commitTextureLinearRepeatRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec2), - Type::new(Vec4), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitTextureLinearRepeatColorRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec2), - Type::new(Vec4), Type::new(Vec4), Type::new(Vec4)], - ); - - declare_function( - state, - "swgl_commitTextureNearestRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitTextureNearestColorRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitTextureNearestRepeatRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec2), - Type::new(Vec4), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitTextureNearestRepeatColorRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec2), - Type::new(Vec4), Type::new(Vec4), Type::new(Vec4)], - ); - - declare_function( - state, - "swgl_commitTextureRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitTextureColorRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitTextureRepeatRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec2), - Type::new(Vec4), Type::new(Vec4)], - ); - declare_function( - state, - "swgl_commitTextureRepeatColorRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec2), - Type::new(Vec4), Type::new(Vec4), Type::new(Vec4)], - ); - - declare_function( - state, - "swgl_commitGaussianBlurRGBA8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Bool), - Type::new(Int), Type::new(Vec2)], - ); - declare_function( - state, - "swgl_commitGaussianBlurR8", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Bool), - Type::new(Int), Type::new(Vec2)], - ); - declare_function( - state, - "swgl_commitTextureLinearYUV", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), - Type::new(Int), Type::new(Int)], - ); - declare_function( - state, - "swgl_commitTextureLinearYUV", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), - Type::new(*s), Type::new(Vec2), Type::new(Vec4), - Type::new(Int), Type::new(Int)], - ); - declare_function( - state, - "swgl_commitTextureLinearYUV", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), - Type::new(*s), Type::new(Vec2), Type::new(Vec4), - Type::new(*s), Type::new(Vec2), Type::new(Vec4), - Type::new(Int), Type::new(Int)], - ); - declare_function( - state, - "swgl_commitTextureLinearColorYUV", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), - Type::new(Int), Type::new(Int), Type::new(Float)], - ); - declare_function( - state, - "swgl_commitTextureLinearColorYUV", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), - Type::new(*s), Type::new(Vec2), Type::new(Vec4), - Type::new(Int), Type::new(Int), Type::new(Float)], - ); - declare_function( - state, - "swgl_commitTextureLinearColorYUV", - None, - Type::new(Void), - vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), - Type::new(*s), Type::new(Vec2), Type::new(Vec4), - Type::new(*s), Type::new(Vec2), Type::new(Vec4), - Type::new(Int), Type::new(Int), Type::new(Float)], - ); - } TranslationUnit(tu.0.map(state, translate_external_declaration)) } @@ -4227,13 +3598,7 @@ fn infer_expr_inner(state: &mut State, expr: &Expr, assign: &mut SymRef) -> RunC }; match fun { FunIdentifier::Identifier(ref sym) => match &state.sym(*sym).decl { - SymDecl::NativeFunction(_, _, ref ret_class) => { - if *ret_class != RunClass::Unknown { - *ret_class - } else { - run_class - } - } + SymDecl::NativeFunction(..) => run_class, SymDecl::UserFunction(ref fd, ref run_class) => { for (&(mut arg_class, assign), param) in arg_classes.iter().zip(fd.prototype.parameters.iter()) diff --git a/third_party/webrender/glsl-to-cxx/src/lib.rs b/third_party/webrender/glsl-to-cxx/src/lib.rs index a42f14a23b6..409af02d586 100644 --- a/third_party/webrender/glsl-to-cxx/src/lib.rs +++ b/third_party/webrender/glsl-to-cxx/src/lib.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -extern crate glsl; +use glsl; mod hir; @@ -61,6 +61,8 @@ pub fn translate(args: &mut dyn Iterator<Item = String>) -> String { .to_string_lossy() .to_string(); + let frag_include = args.next(); + let (vs_state, vs_hir, vs_is_frag) = parse_shader(vertex_file); let (fs_state, fs_hir, fs_is_frag) = parse_shader(frag_file); @@ -77,6 +79,7 @@ pub fn translate(args: &mut dyn Iterator<Item = String>) -> String { vs_hir, vs_is_frag, &uniform_indices, + None, ); result += "\n"; result += &translate_shader( @@ -85,6 +88,7 @@ pub fn translate(args: &mut dyn Iterator<Item = String>) -> String { fs_hir, fs_is_frag, &uniform_indices, + frag_include, ); result } @@ -116,6 +120,7 @@ fn translate_shader( hir: hir::TranslationUnit, is_frag: bool, uniform_indices: &UniformIndices, + include_file: Option<String>, ) -> String { //println!("{:#?}", state); @@ -180,6 +185,8 @@ fn translate_shader( uses_discard: false, used_fragcoord: Cell::new(0), use_perspective: false, + has_draw_span_rgba8: false, + has_draw_span_r8: false, used_globals: RefCell::new(Vec::new()), texel_fetches: RefCell::new(Vec::new()), }; @@ -208,6 +215,10 @@ fn translate_shader( show_translation_unit(&mut state, &hir); + if let Some(include_file) = include_file { + write_include_file(&mut state, include_file); + } + let pruned_inputs: Vec<_> = inputs .iter() .filter(|i| state.used_globals.borrow().contains(i)) @@ -239,7 +250,6 @@ fn translate_shader( write!(state, " return this;\n}}\n"); write!(state, "FragmentShaderImpl* get_fragment_shader() override {{\n"); write!(state, " return this;\n}}\n"); - write!(state, "const char* get_name() const override {{ return \"{}\"; }}\n", name); write!(state, "static ProgramImpl* loader() {{ return new {}_program; }}\n", name); write!(state, "}};\n\n"); } @@ -292,7 +302,8 @@ fn write_program_samplers(state: &mut OutputState, uniform_indices: &UniformIndi match tk { hir::TypeKind::Sampler2D | hir::TypeKind::Sampler2DRect - | hir::TypeKind::ISampler2D => { + | hir::TypeKind::ISampler2D + | hir::TypeKind::Sampler2DArray => { write!(state, " "); show_type_kind(state, &tk); let suffix = if let hir::StorageClass::Sampler(format) = storage { @@ -315,7 +326,8 @@ fn write_program_samplers(state: &mut OutputState, uniform_indices: &UniformIndi match tk { hir::TypeKind::Sampler2D | hir::TypeKind::Sampler2DRect - | hir::TypeKind::ISampler2D => { + | hir::TypeKind::ISampler2D + | hir::TypeKind::Sampler2DArray => { write!(state, " case {}:\n", index); write!(state, " {}_slot = value;\n", name); write!(state, " return true;\n"); @@ -343,6 +355,9 @@ fn write_bind_textures(state: &mut OutputState, uniforms: &UniformIndices) { hir::TypeKind::ISampler2D => write!(state, " {0} = lookup_isampler(&samplers.{0}_impl, samplers.{0}_slot);\n", name), + hir::TypeKind::Sampler2DArray => write!(state, + " {0} = lookup_sampler_array(&samplers.{0}_impl, samplers.{0}_slot);\n", + name), _ => {} }; } @@ -393,8 +408,9 @@ fn write_set_uniform_4fv( if float4_compatible(tk.clone()) { write!( state, - " self->{} = vec4_scalar::load_from_ptr(value);\n", - name + " self->{} = {}_scalar(value);\n", + name, + tk.glsl_primitive_type_name().unwrap(), ); } else { write!(state, " assert(0); // {}\n", name); @@ -535,9 +551,6 @@ fn write_load_attribs(state: &mut OutputState, attribs: &[hir::SymRef]) { fn write_store_outputs(state: &mut OutputState, outputs: &[hir::SymRef]) { let is_scalar = state.is_scalar.replace(true); write!(state, "public:\nstruct InterpOutputs {{\n"); - if state.hir.used_clip_dist != 0 { - state.write(" Float swgl_ClipDistance;\n"); - } for i in outputs { let sym = state.hir.sym(*i); match &sym.decl { @@ -563,15 +576,6 @@ fn write_store_outputs(state: &mut OutputState, outputs: &[hir::SymRef]) { state, " auto* dest = reinterpret_cast<InterpOutputs*>(dest_ptr);\n" ); - if state.hir.used_clip_dist != 0 { - for (i, comp) in "xyzw".chars().enumerate() { - if (state.hir.used_clip_dist & (1 << i)) != 0 { - write!(state, " dest->swgl_ClipDistance.{} = get_nth(gl_ClipDistance[{}], n);\n", comp, i); - } else { - write!(state, " dest->swgl_ClipDistance.{} = 0.0f;\n", comp); - } - } - } for i in outputs { let sym = state.hir.sym(*i); match &sym.decl { @@ -622,7 +626,7 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) { write!(state, "static void read_interp_inputs(\ - Self *self, const InterpInputs *init, const InterpInputs *step) {{\n"); + Self *self, const InterpInputs *init, const InterpInputs *step, float step_width) {{\n"); for i in inputs { let sym = state.hir.sym(*i); match &sym.decl { @@ -636,7 +640,7 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) { ); write!( state, - " self->interp_step.{0} = step->{0} * 4.0f;\n", + " self->interp_step.{0} = step->{0} * step_width;\n", name ); } @@ -653,7 +657,7 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) { if state.use_perspective { write!(state, "static void read_perspective_inputs(\ - Self *self, const InterpInputs *init, const InterpInputs *step) {{\n"); + Self *self, const InterpInputs *init, const InterpInputs *step, float step_width) {{\n"); if has_varying { write!(state, " Float w = 1.0f / self->gl_FragCoord.w;\n"); } @@ -671,7 +675,7 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) { write!(state, " self->{0} = self->interp_perspective.{0} * w;\n", name); write!( state, - " self->interp_step.{0} = step->{0} * 4.0f;\n", + " self->interp_step.{0} = step->{0} * step_width;\n", name ); } @@ -682,12 +686,9 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) { write!(state, "}}\n"); } - write!(state, "ALWAYS_INLINE void step_interp_inputs(int steps = 4) {{\n"); + write!(state, "ALWAYS_INLINE void step_interp_inputs() {{\n"); if (used_fragcoord & 1) != 0 { - write!(state, " step_fragcoord(steps);\n"); - } - if !inputs.is_empty() { - write!(state, " float chunks = steps * 0.25f;\n"); + write!(state, " step_fragcoord();\n"); } for i in inputs { let sym = state.hir.sym(*i); @@ -695,7 +696,7 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) { hir::SymDecl::Global(_, _, _, run_class) => { if *run_class != hir::RunClass::Scalar { let name = sym.name.as_str(); - write!(state, " {0} += interp_step.{0} * chunks;\n", name); + write!(state, " {0} += interp_step.{0};\n", name); } } _ => panic!(), @@ -704,14 +705,11 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) { write!(state, "}}\n"); if state.use_perspective { - write!(state, "ALWAYS_INLINE void step_perspective_inputs(int steps = 4) {{\n"); + write!(state, "ALWAYS_INLINE void step_perspective_inputs() {{\n"); if (used_fragcoord & 1) != 0 { - write!(state, " step_fragcoord(steps);\n"); - } - write!(state, " step_perspective(steps);\n"); - if !inputs.is_empty() { - write!(state, " float chunks = steps * 0.25f;\n"); + write!(state, " step_fragcoord();\n"); } + write!(state, " step_perspective();\n"); if has_varying { write!(state, " Float w = 1.0f / gl_FragCoord.w;\n"); } @@ -721,7 +719,7 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) { hir::SymDecl::Global(_, _, _, run_class) => { if *run_class != hir::RunClass::Scalar { let name = sym.name.as_str(); - write!(state, " interp_perspective.{0} += interp_step.{0} * chunks;\n", name); + write!(state, " interp_perspective.{0} += interp_step.{0};\n", name); write!(state, " {0} = w * interp_perspective.{0};\n", name); } } @@ -730,6 +728,58 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) { } write!(state, "}}\n"); } + + if state.has_draw_span_rgba8 || state.has_draw_span_r8 { + write!( + state, + "ALWAYS_INLINE void step_interp_inputs(int chunks) {{\n" + ); + if (used_fragcoord & 1) != 0 { + write!(state, " step_fragcoord(chunks);\n"); + } + for i in inputs { + let sym = state.hir.sym(*i); + match &sym.decl { + hir::SymDecl::Global(_, _, _, run_class) => { + if *run_class != hir::RunClass::Scalar { + let name = sym.name.as_str(); + write!(state, " {0} += interp_step.{0} * chunks;\n", name); + } + } + _ => panic!(), + } + } + write!(state, "}}\n"); + } +} + +fn write_include_file(state: &mut OutputState, include_file: String) { + let include_contents = std::fs::read_to_string(&include_file).unwrap(); + + let mut offset = 0; + while offset < include_contents.len() { + let s = &include_contents[offset ..]; + if let Some(start_proto) = s.find("draw_span") { + let s = &s[start_proto ..]; + if let Some(end_proto) = s.find(')') { + let proto = &s[.. end_proto]; + if proto.contains("uint32_t") { + state.has_draw_span_rgba8 = true; + } else if proto.contains("uint8_t") { + state.has_draw_span_r8 = true; + } + offset += start_proto + end_proto; + continue; + } + } + break; + } + + let include_name = std::path::Path::new(&include_file) + .file_name() + .unwrap() + .to_string_lossy(); + write!(state, "\n#include \"{}\"\n\n", include_name); } pub struct OutputState { @@ -754,6 +804,8 @@ pub struct OutputState { uses_discard: bool, used_fragcoord: Cell<i32>, use_perspective: bool, + has_draw_span_rgba8: bool, + has_draw_span_r8: bool, used_globals: RefCell<Vec<hir::SymRef>>, texel_fetches: RefCell<Vec<(hir::SymRef, hir::SymRef, hir::TexelFetchOffsets)>>, } @@ -822,7 +874,7 @@ fn add_used_global(state: &OutputState, i: &hir::SymRef) { pub fn show_sym(state: &OutputState, i: &hir::SymRef) { let sym = state.hir.sym(*i); match &sym.decl { - hir::SymDecl::NativeFunction(_, ref cxx_name, _) => { + hir::SymDecl::NativeFunction(_, ref cxx_name) => { let mut name = sym.name.as_str(); if state.output_cxx { name = cxx_name.unwrap_or(name); @@ -1515,10 +1567,8 @@ fn expr_run_class(state: &OutputState, expr: &hir::Expr) -> hir::RunClass { }); match fun { hir::FunIdentifier::Identifier(ref sym) => match &state.hir.sym(*sym).decl { - hir::SymDecl::NativeFunction(_, _, ref ret_class) => { - if *ret_class != hir::RunClass::Unknown { - *ret_class - } else if arg_mask != 0 { + hir::SymDecl::NativeFunction(..) => { + if arg_mask != 0 { hir::RunClass::Vector } else { hir::RunClass::Scalar @@ -1846,21 +1896,33 @@ pub fn show_hir_expr_inner(state: &OutputState, expr: &hir::Expr, top_level: boo &state.hir, &args[0], &args[1], &args[3], ) { let base_sym = state.hir.sym(base); - let sampler_sym = state.hir.sym(sampler); - add_used_global(state, &sampler); - if let hir::SymDecl::Global(..) = &base_sym.decl { - add_used_global(state, &base); + if symbol_run_class(&base_sym.decl, state.vector_mask) + == hir::RunClass::Scalar + { + let sampler_sym = state.hir.sym(sampler); + add_used_global(state, &sampler); + if let hir::SymDecl::Global(..) = &base_sym.decl { + add_used_global(state, &base); + } + if y != 0 { + write!( + state, + "{}_{}_fetch[{}+{}*{}->stride]", + sampler_sym.name, + base_sym.name, + x, + y, + sampler_sym.name + ); + } else { + write!( + state, + "{}_{}_fetch[{}]", + sampler_sym.name, base_sym.name, x + ); + } + return; } - write!( - state, - "texelFetchUnchecked({}, {}_{}_fetch, {}, {})", - sampler_sym.name, - sampler_sym.name, - base_sym.name, - x, - y, - ); - return; } } show_sym(state, name) @@ -2296,12 +2358,15 @@ pub fn show_declaration(state: &mut OutputState, d: &hir::Declaration) { let base = list.head.name; let base_sym = state.hir.sym(base); if let hir::SymDecl::Local(..) = &base_sym.decl { - let mut texel_fetches = state.texel_fetches.borrow_mut(); - while let Some(idx) = texel_fetches.iter().position(|&(_, b, _)| b == base) + if symbol_run_class(&base_sym.decl, state.vector_mask) == hir::RunClass::Scalar { - let (sampler, _, offsets) = texel_fetches.remove(idx); - let sampler_sym = state.hir.sym(sampler); - define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets); + let mut texel_fetches = state.texel_fetches.borrow_mut(); + while let Some(idx) = texel_fetches.iter().position(|&(_, b, _)| b == base) + { + let (sampler, _, offsets) = texel_fetches.remove(idx); + let sampler_sym = state.hir.sym(sampler); + define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets); + } } } } @@ -2319,22 +2384,19 @@ pub fn show_declaration(state: &mut OutputState, d: &hir::Declaration) { //state.write(";\n"); } hir::Declaration::Global(ref qual, ref identifiers) => { - // We only want to output GLSL layout qualifiers if not C++ - if !state.output_cxx { - show_type_qualifier(state, &qual); + show_type_qualifier(state, &qual); - if !identifiers.is_empty() { - let mut iter = identifiers.iter(); - let first = iter.next().unwrap(); - show_identifier(state, first); + if !identifiers.is_empty() { + let mut iter = identifiers.iter(); + let first = iter.next().unwrap(); + show_identifier(state, first); - for identifier in iter { - let _ = write!(state, ", {}", identifier); - } + for identifier in iter { + let _ = write!(state, ", {}", identifier); } - - state.write(";\n"); } + + state.write(";\n"); } hir::Declaration::StructDefinition(ref sym) => { show_sym_decl(state, sym); @@ -2610,32 +2672,32 @@ fn define_texel_fetch_ptr( offsets: &hir::TexelFetchOffsets, ) { show_indent(state); - let ptr_type = if let hir::SymDecl::Global(_, _, ty, _) = &sampler_sym.decl { - if symbol_run_class(&base_sym.decl, state.vector_mask) == hir::RunClass::Scalar { - match ty.kind { - hir::TypeKind::Sampler2D - | hir::TypeKind::Sampler2DRect => "vec4_scalar*", - hir::TypeKind::ISampler2D => "ivec4_scalar*", - _ => panic!(), + if let hir::SymDecl::Global(_, _, ty, _) = &sampler_sym.decl { + match ty.kind { + hir::TypeKind::Sampler2D + | hir::TypeKind::Sampler2DRect => { + write!( + state, + "vec4_scalar* {}_{}_fetch = ", + sampler_sym.name, base_sym.name + ); } - } else { - "I32" + hir::TypeKind::ISampler2D => { + write!( + state, + "ivec4_scalar* {}_{}_fetch = ", + sampler_sym.name, base_sym.name + ); + } + _ => panic!(), } } else { panic!(); - }; + } write!( state, - "{} {}_{}_fetch = texelFetchPtr({}, {}, {}, {}, {}, {});\n", - ptr_type, - sampler_sym.name, - base_sym.name, - sampler_sym.name, - base_sym.name, - offsets.min_x, - offsets.max_x, - offsets.min_y, - offsets.max_y, + "texelFetchPtr({}, {}, {}, {}, {}, {});\n", + sampler_sym.name, base_sym.name, offsets.min_x, offsets.max_x, offsets.min_y, offsets.max_y ); } @@ -2688,64 +2750,27 @@ pub fn show_function_definition( } if state.output_cxx { - match fd.prototype.name.as_str() { - "swgl_drawSpanRGBA8" | - "swgl_drawSpanR8" => { - // Partial spans are not drawn using span shaders, but rather drawn with a fragment shader - // where the span shader left off. We need to undo any changes to the interpolants made by - // the span shaders so that we can reset the interpolants to where the fragment shader - // expects them. We do this by saving them in an _Undo_ struct on entry to the span shader, - // and then restore them in the _Undo_ struct destructor. - let mut needs_undo = vec![]; - for global in &fd.globals { - let sym = state.hir.sym(*global); - match &sym.decl { - hir::SymDecl::Global(hir::StorageClass::In, _, ty, hir::RunClass::Vector) => { - if needs_undo.is_empty() { - state.write("struct _Undo_ {\nSelf* self;\n"); - } - show_type(state, ty); - write!(state, " {};\n", sym.name); - needs_undo.push(sym.name.clone()); - } - _ => {} - } - } - if !needs_undo.is_empty() { - state.write("explicit _Undo_(Self* self) : self(self)"); - for name in &needs_undo { - write!(state, ", {0}(self->{0})", name); - } - state.write(" {}\n"); - state.write("~_Undo_() {\n"); - for name in &needs_undo { - write!(state, "self->{0} = {0};\n", name); - } - state.write("}} _undo_(this);\n"); - } - } - _ => {} - } - let mut texel_fetches = state.texel_fetches.borrow_mut(); texel_fetches.clear(); for ((sampler, base), offsets) in fd.texel_fetches.iter() { - add_used_global(state, sampler); - let sampler_sym = state.hir.sym(*sampler); let base_sym = state.hir.sym(*base); - match &base_sym.decl { - hir::SymDecl::Global(..) => { - add_used_global(state, base); - define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets); - } - hir::SymDecl::Local(..) => { - if fd.prototype.has_parameter(*base) { + if symbol_run_class(&base_sym.decl, vector_mask) == hir::RunClass::Scalar { + add_used_global(state, sampler); + let sampler_sym = state.hir.sym(*sampler); + match &base_sym.decl { + hir::SymDecl::Global(..) => { + add_used_global(state, base); define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets); - } else { - texel_fetches.push((*sampler, *base, offsets.clone())); } + hir::SymDecl::Local(..) => { + if fd.prototype.has_parameter(*base) { + define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets); + } else { + texel_fetches.push((*sampler, *base, offsets.clone())); + } + } + _ => panic!(), } - _ => panic!(), } } } @@ -3170,7 +3195,7 @@ pub fn show_iteration_statement(state: &mut OutputState, ist: &hir::IterationSta show_statement(state, body); state.write(" while ("); show_hir_expr(state, cond); - state.write(");\n"); + state.write(")\n"); } hir::IterationStatement::For(ref init, ref rest, ref body) => { state.write("for ("); @@ -3241,7 +3266,7 @@ pub fn show_jump_statement(state: &mut OutputState, j: &hir::JumpStatement) { if state.output_cxx { state.uses_discard = true; if let Some(mask) = &state.mask { - state.write("swgl_IsPixelDiscarded |= ("); + state.write("isPixelDiscarded |= ("); show_hir_expr(state, mask); state.write(")"); if state.return_declared { @@ -3249,7 +3274,7 @@ pub fn show_jump_statement(state: &mut OutputState, j: &hir::JumpStatement) { } state.write(";\n"); } else { - state.write("swgl_IsPixelDiscarded = true;\n"); + state.write("isPixelDiscarded = true;\n"); } } else { state.write("discard;\n"); @@ -3554,11 +3579,9 @@ pub fn show_translation_unit(state: &mut OutputState, tu: &hir::TranslationUnit) state.flush_buffer(); } if state.output_cxx { - for name in &["main", "swgl_drawSpanRGBA8", "swgl_drawSpanR8"] { - if let Some(sym) = state.hir.lookup(name) { - show_cxx_function_definition(state, sym, 0); - state.flush_buffer(); - } + if let Some(name) = state.hir.lookup("main") { + show_cxx_function_definition(state, name, 0); + state.flush_buffer(); } } } @@ -3568,33 +3591,37 @@ fn write_abi(state: &mut OutputState) { ShaderKind::Fragment => { state.write("static void run(Self *self) {\n"); if state.uses_discard { - state.write(" self->swgl_IsPixelDiscarded = false;\n"); + state.write(" self->isPixelDiscarded = false;\n"); } state.write(" self->main();\n"); state.write(" self->step_interp_inputs();\n"); state.write("}\n"); - state.write("static void skip(Self* self, int steps) {\n"); - state.write(" self->step_interp_inputs(steps);\n"); + state.write("static void skip(Self* self, int chunks) {\n"); + state.write(" self->step_interp_inputs();\n"); + state.write(" while (--chunks > 0) self->step_interp_inputs();\n"); state.write("}\n"); if state.use_perspective { state.write("static void run_perspective(Self *self) {\n"); if state.uses_discard { - state.write(" self->swgl_IsPixelDiscarded = false;\n"); + state.write(" self->isPixelDiscarded = false;\n"); } state.write(" self->main();\n"); state.write(" self->step_perspective_inputs();\n"); state.write("}\n"); - state.write("static void skip_perspective(Self* self, int steps) {\n"); - state.write(" self->step_perspective_inputs(steps);\n"); + state.write("static void skip_perspective(Self* self, int chunks) {\n"); + state.write(" self->step_perspective_inputs();\n"); + state.write(" while (--chunks > 0) self->step_perspective_inputs();\n"); state.write("}\n"); } - if state.hir.lookup("swgl_drawSpanRGBA8").is_some() { + if state.has_draw_span_rgba8 { state.write( - "static int draw_span_RGBA8(Self* self) { DISPATCH_DRAW_SPAN(self, RGBA8); }\n"); + "static void draw_span_RGBA8(Self* self, uint32_t* buf, int len) { \ + DISPATCH_DRAW_SPAN(self, buf, len); }\n"); } - if state.hir.lookup("swgl_drawSpanR8").is_some() { + if state.has_draw_span_r8 { state.write( - "static int draw_span_R8(Self* self) { DISPATCH_DRAW_SPAN(self, R8); }\n"); + "static void draw_span_R8(Self* self, uint8_t* buf, int len) { \ + DISPATCH_DRAW_SPAN(self, buf, len); }\n"); } write!(state, "public:\n{}_frag() {{\n", state.name); @@ -3616,10 +3643,10 @@ fn write_abi(state: &mut OutputState) { state.write(" init_span_func = (InitSpanFunc)&read_interp_inputs;\n"); state.write(" run_func = (RunFunc)&run;\n"); state.write(" skip_func = (SkipFunc)&skip;\n"); - if state.hir.lookup("swgl_drawSpanRGBA8").is_some() { + if state.has_draw_span_rgba8 { state.write(" draw_span_RGBA8_func = (DrawSpanRGBA8Func)&draw_span_RGBA8;\n"); } - if state.hir.lookup("swgl_drawSpanR8").is_some() { + if state.has_draw_span_r8 { state.write(" draw_span_R8_func = (DrawSpanR8Func)&draw_span_R8;\n"); } if state.uses_discard { @@ -3643,9 +3670,6 @@ fn write_abi(state: &mut OutputState) { state.write(" init_batch_func = (InitBatchFunc)&init_batch;\n"); state.write(" load_attribs_func = (LoadAttribsFunc)&load_attribs;\n"); state.write(" run_primitive_func = (RunPrimitiveFunc)&run;\n"); - if state.hir.used_clip_dist != 0 { - state.write(" enable_clip_distance();\n"); - } } } state.write("}\n"); |