| # Copyright 2013 The Flutter Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import("//build/compiled_action.gni") |
| import("//flutter/impeller/tools/args.gni") |
| |
| # Dispatches to the build or prebuilt impellerc depending on the value of |
| # the `impeller_use_prebuilt_impellerc` argument. |
| # * When the `single_invocation` argument is false, all variables are |
| # forwarded to `compiled_action_foreach` or `action_foreach`, which will |
| # invoke `impellerc` separately for each source. |
| # * When the `single_invocation` argument is true, `impellerc` is only |
| # invoked once via `compiled_action` or `action`. |
| template("_impellerc") { |
| if (invoker.single_invocation) { |
| compiled_action(target_name) { |
| forward_variables_from(invoker, "*") |
| tool = "//flutter/impeller/compiler:impellerc" |
| } |
| } else { |
| compiled_action_foreach(target_name) { |
| forward_variables_from(invoker, "*") |
| tool = "//flutter/impeller/compiler:impellerc" |
| } |
| } |
| } |
| |
| # Required: shaders The list of shaders inputs to compile. |
| # Required: shader_target_flags The target flag(s) to append. Valid options: |
| # --sksl |
| # --metal-ios |
| # --metal-desktop |
| # --opengl-es |
| # --opengl-desktop |
| # --vulkan |
| # --runtime-stage-metal |
| # --runtime-stage-gles |
| # --runtime-stage-gles3 |
| # --runtime-stage-vulkan |
| # Not required for --shader_bundle mode. |
| # Required: sl_file_extension The file extension to use for output files. |
| # Not required for --shader_bundle mode. |
| # Optional: iplr Causes --sl output to be in iplr/runtime |
| # stage flatbuffer format. |
| # Optional: shader_bundle Specifies a Flutter GPU shader bundle |
| # configuration. |
| # Required: shader_bundle_output Specifies the output filename of the shader |
| # bundle. This is only required if |
| # shader_bundle is supplied. |
| # Optional: defines Specifies a list of valueless macro |
| # definitions. |
| # Optional: intermediates_subdir Specifies the subdirectory in which to put |
| # intermediates. |
| # Optional: json Causes output format to be JSON instead of |
| # flatbuffer. |
| template("impellerc") { |
| assert(defined(invoker.shaders), "Impeller shaders must be specified.") |
| assert(defined(invoker.shader_target_flags) || defined(invoker.shader_bundle), |
| "The flag to impellerc for target selection must be specified.") |
| assert(defined(invoker.sl_file_extension) || defined(invoker.shader_bundle), |
| "The extension of the SL file must be specified (metal, glsl, etc..).") |
| if (defined(invoker.shader_bundle)) { |
| assert( |
| defined(invoker.shader_bundle_output), |
| "When shader_bundle is specified, shader_bundle_output must also be specified.") |
| } |
| |
| if (defined(invoker.shader_target_flags)) { |
| shader_target_flags = invoker.shader_target_flags |
| } else { |
| shader_target_flags = [] |
| } |
| |
| sksl = false |
| foreach(shader_target_flag, shader_target_flags) { |
| sksl = shader_target_flag == "--sksl" |
| } |
| iplr = false |
| if (defined(invoker.iplr) && invoker.iplr) { |
| iplr = invoker.iplr |
| } |
| json = false |
| if (defined(invoker.json) && invoker.json) { |
| json = invoker.json |
| } |
| |
| # Not needed on every path. |
| not_needed([ |
| "iplr", |
| "sksl", |
| "shader_bundle", |
| "shader_bundle_output", |
| ]) |
| |
| _impellerc(target_name) { |
| pool = "//build/toolchain:toolchain_pool" |
| shader_bundle = defined(invoker.shader_bundle) |
| |
| # When single_invocation is true, impellerc will be invoked exactly once. When it's |
| # false, impellerc be invoked for each of the source file entries (invoker.shaders). |
| single_invocation = shader_bundle |
| |
| if (defined(invoker.intermediates_subdir)) { |
| subdir = invoker.intermediates_subdir |
| generated_dir = "$target_gen_dir/$subdir" |
| } else { |
| generated_dir = "$target_gen_dir" |
| } |
| |
| shader_lib_dir = rebase_path("//flutter/impeller/compiler/shader_lib") |
| args = [ "--include=$shader_lib_dir" ] + shader_target_flags |
| |
| # When we're in single invocation mode, we can't use source enumeration. |
| if (!single_invocation) { |
| depfile_path = "$generated_dir/{{source_file_part}}.d" |
| depfile_intermediate_path = rebase_path(depfile_path, root_build_dir) |
| depfile = depfile_path |
| args += [ |
| "--input={{source}}", |
| "--include={{source_dir}}", |
| "--depfile=$depfile_intermediate_path", |
| ] |
| |
| if (defined(invoker.shader_target_flag)) { |
| args += [ "${invoker.shader_target_flag}" ] |
| } |
| } |
| |
| if (defined(invoker.gles_language_version)) { |
| gles_language_version = invoker.gles_language_version |
| args += [ "--gles-language-version=$gles_language_version" ] |
| } |
| |
| if (defined(invoker.metal_version)) { |
| assert(is_mac || is_ios) |
| metal_version = invoker.metal_version |
| args += [ "--metal-version=$metal_version" ] |
| } |
| |
| if (defined(invoker.use_half_textures) && invoker.use_half_textures) { |
| args += [ "--use-half-textures" ] |
| } |
| if (defined(invoker.require_framebuffer_fetch) && |
| invoker.require_framebuffer_fetch) { |
| args += [ "--require-framebuffer-fetch" ] |
| } |
| |
| if (json) { |
| args += [ "--json" ] |
| } |
| |
| if (iplr) { |
| # When building in IPLR mode, the compiler may be executed twice |
| args += [ "--iplr" ] |
| } |
| |
| # The `sl_output` is the raw shader file output by the compiler. For --iplr |
| # and --shader-bundle, this is used as the filename for the flatbuffer to |
| # output. |
| |
| if (shader_bundle) { |
| # When a shader bundle is specified, don't bother supplying flags for |
| # the reflection state as these are ignored. In this mode, the compiler |
| # is invoked multiple times and the reflection state for each shader is |
| # written to the output flatbuffer. |
| sl_output = "$generated_dir/${invoker.shader_bundle_output}" |
| sl_output_path = rebase_path(sl_output, root_build_dir) |
| |
| args += [ |
| "--sl=$sl_output_path", |
| "--shader-bundle=${invoker.shader_bundle}", |
| ] |
| |
| outputs = [ sl_output ] |
| } else if (sksl) { |
| # When SkSL is selected as a `shader_target_flags`, don't generate |
| # C++ reflection state. Nothing needs to use it and it's likely invalid |
| # given the special cases when generating SkSL. |
| # Note that this configuration is orthogonal to the "--iplr" flag |
| sl_output = |
| "$generated_dir/{{source_file_part}}.${invoker.sl_file_extension}" |
| sl_output_path = rebase_path(sl_output, root_build_dir) |
| |
| spirv_intermediate = "$generated_dir/{{source_file_part}}.spirv" |
| spirv_intermediate_path = rebase_path(spirv_intermediate, root_build_dir) |
| args += [ |
| "--sl=$sl_output_path", |
| "--spirv=$spirv_intermediate_path", |
| ] |
| |
| outputs = [ sl_output ] |
| } else { |
| # The default branch. Here we just generate one shader along with all of |
| # its C++ reflection state. |
| |
| sl_output = |
| "$generated_dir/{{source_file_part}}.${invoker.sl_file_extension}" |
| sl_output_path = rebase_path(sl_output, root_build_dir) |
| |
| reflection_json_intermediate = "$generated_dir/{{source_file_part}}.json" |
| reflection_header_intermediate = "$generated_dir/{{source_file_part}}.h" |
| reflection_cc_intermediate = "$generated_dir/{{source_file_part}}.cc" |
| |
| spirv_intermediate = "$generated_dir/{{source_file_part}}.spirv" |
| spirv_intermediate_path = rebase_path(spirv_intermediate, root_build_dir) |
| reflection_json_path = |
| rebase_path(reflection_json_intermediate, root_build_dir) |
| reflection_header_path = |
| rebase_path(reflection_header_intermediate, root_build_dir) |
| reflection_cc_path = |
| rebase_path(reflection_cc_intermediate, root_build_dir) |
| |
| args += [ |
| "--sl=$sl_output_path", |
| "--spirv=$spirv_intermediate_path", |
| "--reflection-json=$reflection_json_path", |
| "--reflection-header=$reflection_header_path", |
| "--reflection-cc=$reflection_cc_path", |
| ] |
| |
| outputs = [ |
| sl_output, |
| reflection_header_intermediate, |
| reflection_cc_intermediate, |
| ] |
| } |
| |
| if (defined(invoker.defines)) { |
| foreach(def, invoker.defines) { |
| args += [ "--define=$def" ] |
| } |
| } |
| |
| if (single_invocation) { |
| inputs = invoker.shaders |
| } else { |
| sources = invoker.shaders |
| } |
| } |
| } |
| |
| template("impellerc_reflect") { |
| assert( |
| defined(invoker.impellerc_invocation), |
| "The target that specifies the ImpellerC invocation to reflect must be defined.") |
| |
| reflect_config = "reflect_$target_name" |
| config(reflect_config) { |
| include_dirs = [ get_path_info( |
| get_label_info("//flutter/impeller:impeller", "target_gen_dir"), |
| "dir") ] |
| } |
| |
| impellerc_invocation = invoker.impellerc_invocation |
| |
| source_set(target_name) { |
| public_configs = [ ":$reflect_config" ] |
| public = filter_include(get_target_outputs(impellerc_invocation), [ "*.h" ]) |
| sources = filter_include(get_target_outputs(impellerc_invocation), |
| [ |
| "*.h", |
| "*.cc", |
| "*.mm", |
| ]) |
| |
| deps = [ |
| "//flutter/impeller/core", |
| impellerc_invocation, |
| ] |
| } |
| } |