diff --git a/src/glsl/builtin_functions.cpp b/src/glsl/builtin_functions.cpp index ee85b44bb8b..f14f1e09c80 100644 --- a/src/glsl/builtin_functions.cpp +++ b/src/glsl/builtin_functions.cpp @@ -539,8 +539,11 @@ class builtin_builder { B1(tan) B1(asin) B1(acos) + B1(acos_native) B1(atan2) B1(atan) + B1(atan2_native) + B1(atan_native) B1(sinh) B1(cosh) B1(tanh) @@ -743,7 +746,15 @@ builtin_builder::find(_mesa_glsl_parse_state *state, */ state->uses_builtin_functions = true; - ir_function *f = shader->symbols->get_function(name); + ir_function *f; + if (state->emit_native_acos && strcmp(name,"acos")==0) + f = shader->symbols->get_function("acos_native"); + else + if (state->emit_native_atan && strcmp(name,"atan")==0) + f = shader->symbols->get_function("atan_native"); + else + f = shader->symbols->get_function(name); + if (f == NULL) return NULL; @@ -944,6 +955,7 @@ builtin_builder::create_builtins() F(tan) F(asin) F(acos) + F(acos_native) add_function("atan", _atan(glsl_type::float_type), @@ -956,6 +968,17 @@ builtin_builder::create_builtins() _atan2(glsl_type::vec4_type), NULL); + add_function("atan_native", + _atan_native(glsl_type::float_type), + _atan_native(glsl_type::vec2_type), + _atan_native(glsl_type::vec3_type), + _atan_native(glsl_type::vec4_type), + _atan2_native(glsl_type::float_type), + _atan2_native(glsl_type::vec2_type), + _atan2_native(glsl_type::vec3_type), + _atan2_native(glsl_type::vec4_type), + NULL); + F(sinh) F(cosh) F(tanh) @@ -2711,12 +2734,31 @@ builtin_builder::_acos(const glsl_type *type) { ir_variable *x = in_var(type, "x"); MAKE_SIG(type, always_available, 1, x); - body.emit(ret(sub(imm(M_PI_2f), asin_expr(x)))); + return sig; +} +ir_function_signature * +builtin_builder::_acos_native(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(type, always_available, 1, x); + body.emit(ret(acos(x))); return sig; } + +ir_function_signature * +builtin_builder::_atan2_native(const glsl_type *type) +{ + ir_variable *vec_y = in_var(type, "vec_y"); + ir_variable *vec_x = in_var(type, "vec_x"); + MAKE_SIG(type, always_available, 2, vec_y, vec_x); + body.emit(ret(atan2(vec_y, vec_x))); + return sig; +} + + ir_function_signature * builtin_builder::_atan2(const glsl_type *type) { @@ -2825,6 +2867,17 @@ builtin_builder::_atan(const glsl_type *type) return sig; } +ir_function_signature * +builtin_builder::_atan_native(const glsl_type *type) +{ + ir_variable *y_over_x = in_var(type, "y_over_x"); + MAKE_SIG(type, always_available, 1, y_over_x); + + body.emit(ret(atan(y_over_x))); + + return sig; +} + ir_function_signature * builtin_builder::_sinh(const glsl_type *type) { diff --git a/src/glsl/glsl_optimizer.cpp b/src/glsl/glsl_optimizer.cpp index b90704abdb8..df3248ea466 100644 --- a/src/glsl/glsl_optimizer.cpp +++ b/src/glsl/glsl_optimizer.cpp @@ -632,6 +632,9 @@ glslopt_shader* glslopt_optimize (glslopt_ctx* ctx, glslopt_shader_type type, co state->metal_target = true; state->error = 0; + state->emit_native_acos = (options & kGlslOptionsEmitNativeAcos)!=0; + state->emit_native_atan = (options & kGlslOptionsEmitNativeAtan)!=0; + if (!(options & kGlslOptionSkipPreprocessor)) { state->error = !!glcpp_preprocess (state, &shaderSource, &state->info_log, state->extensions, &ctx->mesa_ctx); diff --git a/src/glsl/glsl_optimizer.h b/src/glsl/glsl_optimizer.h index d0bf9f7fa46..584cba15a9a 100644 --- a/src/glsl/glsl_optimizer.h +++ b/src/glsl/glsl_optimizer.h @@ -33,6 +33,8 @@ enum glslopt_shader_type { enum glslopt_options { kGlslOptionSkipPreprocessor = (1<<0), // Skip preprocessing shader source. Saves some time if you know you don't need it. kGlslOptionNotFullShader = (1<<1), // Passed shader is not the full shader source. This makes some optimizations weaker. + kGlslOptionsEmitNativeAcos = (1<<2), // don't emit approximation of acos but use acos function instead + kGlslOptionsEmitNativeAtan = (1<<3), // don't emit approximation of atan but use atan function instead }; // Optimizer target language diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index 51530d5368b..c8782029dad 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -222,6 +222,8 @@ struct _mesa_glsl_parse_state { unsigned language_version; bool had_version_string; bool had_float_precision; + bool emit_native_acos; + bool emit_native_atan; gl_shader_stage stage; /** diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 05fe79241f3..6a5668560a9 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -1317,6 +1317,8 @@ enum ir_expression_operation { ir_unop_cos, ir_unop_sin_reduced, /**< Reduced range sin. [-pi, pi] */ ir_unop_cos_reduced, /**< Reduced range cos. [-pi, pi] */ + ir_unop_acos, + ir_unop_atan, /*@}*/ /** @@ -1514,10 +1516,17 @@ enum ir_expression_operation { */ ir_binop_interpolate_at_sample, + /** + * \name Trigonometric operations. + */ + /*@{*/ + ir_binop_atan2, + /*@}*/ + /** * A sentinel marking the last of the binary operations. */ - ir_last_binop = ir_binop_interpolate_at_sample, + ir_last_binop = ir_binop_atan2, /** * \name Fused floating-point multiply-add, part of ARB_gpu_shader5. diff --git a/src/glsl/ir_builder.cpp b/src/glsl/ir_builder.cpp index b3b5cb06b42..d4954875bb6 100644 --- a/src/glsl/ir_builder.cpp +++ b/src/glsl/ir_builder.cpp @@ -298,6 +298,24 @@ cos(operand a) return expr(ir_unop_cos, a); } +ir_expression * +acos(operand a) +{ + return expr(ir_unop_acos, a); +} + +ir_expression * +atan(operand a) +{ + return expr(ir_unop_atan, a); +} + +ir_expression * +atan2(operand a, operand b) +{ + return expr(ir_binop_atan2, a, b); +} + ir_expression * exp(operand a) { diff --git a/src/glsl/ir_builder.h b/src/glsl/ir_builder.h index a39ce999765..4258c2d9b83 100644 --- a/src/glsl/ir_builder.h +++ b/src/glsl/ir_builder.h @@ -145,6 +145,9 @@ ir_expression *abs(operand a); ir_expression *neg(operand a); ir_expression *sin(operand a); ir_expression *cos(operand a); +ir_expression *acos(operand a); +ir_expression *atan(operand a); +ir_expression *atan2(operand a, operand b); ir_expression *exp(operand a); ir_expression *rsq(operand a); ir_expression *sqrt(operand a); diff --git a/src/glsl/ir_print_glsl_visitor.cpp b/src/glsl/ir_print_glsl_visitor.cpp index 061a51b8b67..d3d27f1e067 100644 --- a/src/glsl/ir_print_glsl_visitor.cpp +++ b/src/glsl/ir_print_glsl_visitor.cpp @@ -638,6 +638,8 @@ static const char *const operator_glsl_strs[] = { "cos", "sin", // reduced "cos", // reduced + "acos", // native + "atan", // native "dFdx", "dFdxCoarse", "dFdxFine", @@ -698,6 +700,7 @@ static const char *const operator_glsl_strs[] = { "vectorExtract_TODO", "interpolateAtOffset", "interpolateAtSample", + "atan", //atan2 native "fma", "clamp", "mix", @@ -724,6 +727,7 @@ static bool is_binop_func_like(ir_expression_operation op, const glsl_type* type if (op == ir_binop_equal || op == ir_binop_nequal || op == ir_binop_mod || + op == ir_binop_atan2 || (op >= ir_binop_dot && op <= ir_binop_pow)) return true; if (type->is_vector() && (op >= ir_binop_less && op <= ir_binop_nequal)) diff --git a/src/glsl/ir_print_metal_visitor.cpp b/src/glsl/ir_print_metal_visitor.cpp index c1e9cd706d8..cf0d85f5866 100644 --- a/src/glsl/ir_print_metal_visitor.cpp +++ b/src/glsl/ir_print_metal_visitor.cpp @@ -829,6 +829,8 @@ static const char *const operator_glsl_strs[] = { "cos", "fast::sin", // reduced "fast::cos", // reduced + "acos", // native + "atan", // native "dfdx", "dfdx", // coarse "dfdx", // fine @@ -889,6 +891,7 @@ static const char *const operator_glsl_strs[] = { "vectorExtract_TODO", "interpolateAtOffset_TODO", "interpolateAtSample_TODO", + "atan2TODO", //atan2 native "fma", "clamp", "mix",