blob: 4113f79e2ba69490cc504e4a0e623b76af5ab21a [file] [log] [blame]
# 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 = true
# The glslangValidator compiler is noisy by default. A cleanly
# compiling shader still prints out its filename.
#
# This negatively impacts the GN build.
#
# For this reason, we silence the compiler with the "-s" option but
# unfortunately this also disables all error reporting.
#
# Set to true to see detailed error reporting.
#
graphics_compute_verbose_compile = 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.
#
template("graphics_compute_generate_debug_glsl_shader_foreach") {
_include_dirs = []
if (defined(invoker.include_dirs)) {
_include_dirs += invoker.include_dirs
}
# 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",
])
script =
"${graphics_compute_dir}/scripts/preprocess_and_format_glsl_shader.py"
args = [
"--clang-format-tool",
graphics_compute_clang_format_host_tool,
"--glslangValidator-tool",
rebase_path(_host_glslang_executable),
"-o",
rebase_path(outputs[0], root_build_dir),
"{{source}}",
]
foreach(include_dir, _include_dirs) {
args += [ "-I" + rebase_path(include_dir, root_build_dir) ]
}
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.
#
template("graphics_compute_compile_glsl_shader_foreach") {
_output_dir = invoker.output_dir
if (graphics_compute_generate_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",
])
outputs = [ "${_output_dir}/debug/{{source_name_part}}.glsl" ]
}
} else {
# Make GN quiet about this variable.
assert(defined(invoker.debug_outputs) || !defined(invoker.debug_outputs))
}
_gen_spv_target_name = "gen_spv_${target_name}"
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" ]
if (graphics_compute_verbose_compile) {
args = []
} else {
args = [ "-s" ]
}
args += [
"-o",
rebase_path(outputs[0], root_build_dir),
"{{source}}",
]
if (defined(invoker.include_dirs)) {
foreach(include_dir, invoker.include_dirs) {
args += [ "-I" + rebase_path(include_dir, root_build_dir) ]
}
}
if (defined(invoker.args)) {
args += invoker.args
}
if (graphics_compute_generate_debug_shaders) {
# Force debug shader generation.
if (!defined(deps)) {
deps = []
}
deps += [ ":${_gen_debug_target_name}" ]
}
}
#
# 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),
]
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"
if (graphics_compute_skip_spirv_opt) {
sources = get_target_outputs(":${_gen_spv_target_name}")
deps = [ ":${_gen_spv_target_name}" ]
} else {
sources = get_target_outputs(":${_gen_opt_target_name}")
deps = [ ":${_gen_opt_target_name}" ]
}
outputs = [ "${_output_dir}/remap/{{source_name_part}}.spv" ]
args = [
"--do-everything",
"--input",
"{{source}}",
"--output",
rebase_path("${_output_dir}/remap", root_build_dir),
]
}
}