blob: 5e50375f1a57f1c8625b408c2fbc5f863e72fb53 [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 = 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),
]
}
}
}