| # Copyright 2019 The Fuchsia 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_rules.gni") |
| |
| import("//build/compiled_action.gni") |
| |
| declare_args() { |
| # |
| # Set to true in your args.gn file to generate pre-processed and |
| # auto-formatted shaders under the "debug" sub-directory of HotSort |
| # and Spinel target generation output directories. |
| # |
| # These are never used, but can be reviewed manually to verify the |
| # impact of configuration parameters, or when modifying a compute |
| # shader. |
| # |
| # Example results: |
| # |
| # out/default/ |
| # gen/src/graphics/lib/compute/ |
| # hotsort/targets/hs_amd_gcn3_u64/ |
| # comp/ |
| # hs_transpose.comp -> unpreprocessed shader |
| # debug/ |
| # hs_transpose.glsl -> preprocessed shader |
| # |
| graphics_compute_generate_debug_shaders = true |
| |
| # |
| # At times we may want to compare the performance of unoptimized |
| # vs. optimized shaders. On desktop platforms, use of spirv-opt |
| # doesn't appear to provide major performance improvements but it |
| # significantly reduces the size of the SPIR-V modules. |
| # |
| # Disabling the spirv-opt pass may also be useful in identifying and |
| # attributing code generation bugs. |
| # |
| graphics_compute_skip_spirv_opt = false |
| |
| # |
| # If you're using GPU-assisted validation then it's useful to |
| # include debug info in combination with skipping the spirv-opt and |
| # spirv-reduce pass. |
| # |
| graphics_compute_generate_spirv_debug_info = false |
| } |
| |
| # |
| # Generate a human-readable version of a set of compute shaders. |
| # These are pre-processed and auto-formatted to make them easier to read |
| # and compare during development. |
| # |
| # Variables: |
| # sources : list of source .comp shader files. |
| # inputs : list of other input files (headers included by the main shaders). |
| # outputs : list of output file templates. |
| # include_dirs : list of additional include directories passed to the pre-processor. |
| # defines : list of defines. |
| # |
| # Additional variables whose defaults are determined by declare_args(): |
| # gen_debug_shaders : generate debug shaders |
| # skip_spirv_opt : skip the `spirv-opt` pass |
| # |
| template("graphics_compute_generate_debug_glsl_shader_foreach") { |
| _include_dirs = [] |
| if (defined(invoker.include_dirs)) { |
| _include_dirs += invoker.include_dirs |
| } |
| _defines = [] |
| if (defined(invoker.defines)) { |
| _defines += invoker.defines |
| } |
| |
| # |
| # Locate glslangValidator host executable. This is similar to what |
| # compiled_action() does. |
| # |
| _host_glslang_target = |
| "${graphics_compute_glslangValidator_tool_target}($host_toolchain)" |
| _host_glslang_name = get_label_info(_host_glslang_target, "name") |
| _host_glslang_out_dir = get_label_info(_host_glslang_target, "root_out_dir") |
| _host_glslang_executable = "${_host_glslang_out_dir}/${_host_glslang_name}" |
| |
| action_foreach(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "inputs", |
| "outputs", |
| "public_deps", |
| "sources", |
| "defines", |
| ]) |
| if (!defined(inputs)) { |
| inputs = [] |
| } |
| inputs += [ |
| graphics_compute_clang_format_host_tool, |
| _host_glslang_executable, |
| ] |
| script = |
| "${graphics_compute_dir}/scripts/preprocess_and_format_glsl_shader.py" |
| args = [ |
| "--clang-format-tool", |
| rebase_path(graphics_compute_clang_format_host_tool, root_build_dir), |
| "--glslangValidator-tool", |
| rebase_path(_host_glslang_executable, root_build_dir), |
| "-o", |
| rebase_path(outputs[0], root_build_dir), |
| "{{source}}", |
| ] |
| foreach(include_dir, _include_dirs) { |
| args += [ "-I" + rebase_path(include_dir, root_build_dir) ] |
| } |
| foreach(_define, _defines) { |
| args += [ "-D" + _define ] |
| } |
| if (is_fuchsia) { |
| args += [ "-D__Fuchsia__" ] |
| } |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += [ _host_glslang_target ] |
| } |
| } |
| |
| # |
| # Compile a set of glsl shaders, each into a SPIR-V module. |
| # |
| # NOTE: To get the list of generated files, use target_outputs(":<name>") |
| # after calling graphics_compute_compile_glsl_shader_foreach("<name>"). |
| # |
| # Variables: |
| # sources : list of source .comp shader files. |
| # inputs : list of other input files (headers included by the main shaders). |
| # output_dir : output directory. |
| # include_dirs : list of additional include directories passed to the pre-processor. |
| # defines : list of defines. |
| # |
| # Additional variables whose defaults are determined by declare_args(): |
| # gen_debug_shaders : generate debug shaders |
| # skip_spirv_opt : skip the `spirv-opt` pass |
| # |
| template("graphics_compute_compile_glsl_shader_foreach") { |
| _output_dir = invoker.output_dir |
| _gen_debug_shaders = graphics_compute_generate_debug_shaders |
| if (defined(invoker.gen_debug_shaders)) { |
| _gen_debug_shaders = invoker.gen_debug_shaders |
| } |
| if (_gen_debug_shaders) { |
| _gen_debug_target_name = "gen_debug_${target_name}" |
| graphics_compute_generate_debug_glsl_shader_foreach( |
| _gen_debug_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "include_dirs", |
| "inputs", |
| "public_deps", |
| "sources", |
| "defines", |
| ]) |
| outputs = [ "${_output_dir}/debug/{{source_name_part}}.glsl" ] |
| } |
| } else { |
| # Make GN quiet about this variable. |
| assert(defined(invoker.debug_outputs) || !defined(invoker.debug_outputs)) |
| } |
| |
| # |
| # Optimized or not? |
| # |
| _skip_spirv_opt = graphics_compute_skip_spirv_opt |
| |
| if (defined(invoker.skip_spirv_opt)) { |
| _skip_spirv_opt = invoker.skip_spirv_opt |
| } |
| |
| if (_skip_spirv_opt) { |
| _gen_spv_target_name = target_name |
| } else { |
| _gen_spv_target_name = "gen_spv_${target_name}" |
| } |
| |
| # |
| # Compile the glsl shaders |
| # |
| compiled_action_foreach(_gen_spv_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "inputs", |
| "public_deps", |
| "sources", |
| ]) |
| tool = graphics_compute_glslangValidator_tool_target |
| outputs = [ "${_output_dir}/spv/{{source_name_part}}.spv" ] |
| args = [ |
| "--quiet", |
| "-o", |
| rebase_path(outputs[0], root_build_dir), |
| "{{source}}", |
| ] |
| if (graphics_compute_generate_spirv_debug_info) { |
| args += [ "-g" ] |
| } |
| if (defined(invoker.include_dirs)) { |
| foreach(_include_dir, invoker.include_dirs) { |
| args += [ "-I" + rebase_path(_include_dir, root_build_dir) ] |
| } |
| } |
| if (defined(invoker.defines)) { |
| foreach(_define, invoker.defines) { |
| args += [ "-D" + _define ] |
| } |
| } |
| if (is_fuchsia) { |
| args += [ "-D__Fuchsia__" ] |
| } |
| if (defined(invoker.args)) { |
| args += invoker.args |
| } |
| if (_gen_debug_shaders) { |
| # Force debug shader generation. |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += [ ":${_gen_debug_target_name}" ] |
| } |
| } |
| |
| # |
| # Optimize and remap if (_skip_spirv_opt == false) |
| # |
| if (!_skip_spirv_opt) { |
| # |
| # Optimize the modules |
| # |
| _gen_opt_target_name = "gen_opt_${target_name}" |
| compiled_action_foreach(_gen_opt_target_name) { |
| tool = "//third_party/spirv-tools:spirv-opt" |
| sources = get_target_outputs(":${_gen_spv_target_name}") |
| outputs = [ "${_output_dir}/opt/{{source_name_part}}.spv" ] |
| args = [ |
| "-O", |
| "{{source}}", |
| "-o", |
| rebase_path(outputs[0], root_build_dir), |
| ] |
| public_deps = [ ":${_gen_spv_target_name}" ] |
| } |
| |
| # |
| # Remap the optimized modules |
| # |
| # NOTE: Callers of graphics_compute_compile_glsl_shader_foreach(<name>) will |
| # typically want to use target_outputs(":<name>") to get the list of |
| # generated file. This implies that the last action *must* use |
| # the invoker's target_name, or this won't work. |
| # |
| compiled_action_foreach(target_name) { |
| tool = "//third_party/glslang:spirv-remap" |
| sources = get_target_outputs(":${_gen_opt_target_name}") |
| public_deps = [ ":${_gen_opt_target_name}" ] |
| outputs = [ "${_output_dir}/remap/{{source_name_part}}.spv" ] |
| args = [ |
| "--do-everything", # See fxb:86545 for debugPrintfEXT() |
| "--input", |
| "{{source}}", |
| "--output", |
| rebase_path("${_output_dir}/remap", root_build_dir), |
| ] |
| } |
| } |
| } |