From cdc53fa81cbeb80373eac33ef7695d9025caf14b Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Mon, 29 Oct 2018 22:30:06 -0700 Subject: [PATCH] st/nir: Make new helpers for constructing built-in NIR shaders. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The state tracker generates several built-in shaders in order to perform scissored clears, upload/download PBOs, and so on. These are currently constructed using TGSI, using ureg and u_simple_shader. I want to have NIR versions of these shaders, for my Gallium driver that has a NIR backend but no TGSI support. To that end, we'll want a few helpers to help construct simple shaders. This patch adds two new helpers: - st_nir_finish_builtin_shader() takes a manually constructed NIR shader, applies lowering passes (like st_link_nir would do for GLSL), and constructs the pipe_shader_state. - st_nir_make_passthrough_shader() makes a simple passthrough shader, which copies inputs to outputs. This is similar to u_simple_shaders. v2: Set info->fs.untyped_color_outputs for vc4/v3d (thanks Eric!). Reviewed-by: Marek Olšák Tested-by: Rob Clark Tested-by: Eric Anholt --- src/mesa/Makefile.sources | 1 + src/mesa/meson.build | 1 + src/mesa/state_tracker/st_nir.h | 15 +++ src/mesa/state_tracker/st_nir_builtins.c | 138 +++++++++++++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 src/mesa/state_tracker/st_nir_builtins.c diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources index 6ff7ee2e3b6..05d2f8a08ee 100644 --- a/src/mesa/Makefile.sources +++ b/src/mesa/Makefile.sources @@ -538,6 +538,7 @@ STATETRACKER_FILES = \ state_tracker/st_mesa_to_tgsi.c \ state_tracker/st_mesa_to_tgsi.h \ state_tracker/st_nir.h \ + state_tracker/st_nir_builtins.c \ state_tracker/st_nir_lower_builtin.c \ state_tracker/st_nir_lower_tex_src_plane.c \ state_tracker/st_nir_lower_uniforms_to_ubo.c \ diff --git a/src/mesa/meson.build b/src/mesa/meson.build index 27c8c401c4d..6d4a382e268 100644 --- a/src/mesa/meson.build +++ b/src/mesa/meson.build @@ -582,6 +582,7 @@ files_libmesa_gallium = files( 'state_tracker/st_mesa_to_tgsi.c', 'state_tracker/st_mesa_to_tgsi.h', 'state_tracker/st_nir.h', + 'state_tracker/st_nir_builtins.c', 'state_tracker/st_nir_lower_builtin.c', 'state_tracker/st_nir_lower_tex_src_plane.c', 'state_tracker/st_nir_lower_uniforms_to_ubo.c', diff --git a/src/mesa/state_tracker/st_nir.h b/src/mesa/state_tracker/st_nir.h index 1bb65c9d3f1..fcd67e32d44 100644 --- a/src/mesa/state_tracker/st_nir.h +++ b/src/mesa/state_tracker/st_nir.h @@ -55,6 +55,21 @@ st_link_nir(struct gl_context *ctx, void st_nir_assign_varying_locations(struct st_context *st, struct nir_shader *nir); +struct pipe_shader_state * +st_nir_finish_builtin_shader(struct st_context *st, + struct nir_shader *nir, + const char *name); + +struct pipe_shader_state * +st_nir_make_passthrough_shader(struct st_context *st, + const char *shader_name, + gl_shader_stage stage, + unsigned num_vars, + unsigned *input_locations, + unsigned *output_locations, + unsigned *interpolation_modes, + unsigned sysval_mask); + #ifdef __cplusplus } #endif diff --git a/src/mesa/state_tracker/st_nir_builtins.c b/src/mesa/state_tracker/st_nir_builtins.c new file mode 100644 index 00000000000..ebfc3502ec2 --- /dev/null +++ b/src/mesa/state_tracker/st_nir_builtins.c @@ -0,0 +1,138 @@ +/* + * Copyright © 2018 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "tgsi/tgsi_from_mesa.h" +#include "st_glsl_types.h" +#include "st_nir.h" +#include "nir_builder.h" + +struct pipe_shader_state * +st_nir_finish_builtin_shader(struct st_context *st, + nir_shader *nir, + const char *name) +{ + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; + enum pipe_shader_type p_stage = pipe_shader_type_from_mesa(nir->info.stage); + bool is_scalar = + screen->get_shader_param(screen, p_stage, PIPE_SHADER_CAP_SCALAR_ISA); + + nir->info.name = ralloc_strdup(nir, name); + nir->info.separate_shader = true; + if (nir->info.stage == MESA_SHADER_FRAGMENT) + nir->info.fs.untyped_color_outputs = true; + + NIR_PASS_V(nir, nir_lower_global_vars_to_local); + NIR_PASS_V(nir, nir_split_var_copies); + NIR_PASS_V(nir, nir_lower_var_copies); + NIR_PASS_V(nir, nir_lower_system_values); + + if (is_scalar) { + nir_variable_mode mask = + (nir->info.stage > MESA_SHADER_VERTEX ? nir_var_shader_in : 0) | + (nir->info.stage < MESA_SHADER_FRAGMENT ? nir_var_shader_out : 0); + + NIR_PASS_V(nir, nir_lower_io_to_scalar_early, mask); + } + + st_nir_opts(nir, is_scalar); + + nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir)); + + st_nir_assign_varying_locations(st, nir); + + if (st->ctx->Const.PackedDriverUniformStorage) { + NIR_PASS_V(nir, nir_lower_io, nir_var_uniform, st_glsl_type_dword_size, + (nir_lower_io_options)0); + NIR_PASS_V(nir, st_nir_lower_uniforms_to_ubo); + } + + struct pipe_shader_state state = { + .type = PIPE_SHADER_IR_NIR, + .ir.nir = nir, + }; + + switch (nir->info.stage) { + case MESA_SHADER_VERTEX: + return pipe->create_vs_state(pipe, &state); + case MESA_SHADER_TESS_CTRL: + return pipe->create_tcs_state(pipe, &state); + case MESA_SHADER_TESS_EVAL: + return pipe->create_tes_state(pipe, &state); + case MESA_SHADER_GEOMETRY: + return pipe->create_gs_state(pipe, &state); + case MESA_SHADER_FRAGMENT: + return pipe->create_fs_state(pipe, &state); + default: + unreachable("unsupported shader stage"); + return NULL; + } +} + +/** + * Make a simple shader that copies inputs to corresponding outputs. + */ +struct pipe_shader_state * +st_nir_make_passthrough_shader(struct st_context *st, + const char *shader_name, + gl_shader_stage stage, + unsigned num_vars, + unsigned *input_locations, + unsigned *output_locations, + unsigned *interpolation_modes, + unsigned sysval_mask) +{ + struct nir_builder b; + const struct glsl_type *vec4 = glsl_vec4_type(); + const nir_shader_compiler_options *options = + st->ctx->Const.ShaderCompilerOptions[stage].NirOptions; + + nir_builder_init_simple_shader(&b, NULL, stage, options); + + char var_name[15]; + + for (unsigned i = 0; i < num_vars; i++) { + nir_variable *in; + if (sysval_mask & (1 << i)) { + snprintf(var_name, sizeof(var_name), "sys_%u", input_locations[i]); + in = nir_variable_create(b.shader, nir_var_system_value, + glsl_int_type(), var_name); + in->data.interpolation = INTERP_MODE_FLAT; + } else { + snprintf(var_name, sizeof(var_name), "in_%u", input_locations[i]); + in = nir_variable_create(b.shader, nir_var_shader_in, vec4, var_name); + } + in->data.location = input_locations[i]; + if (interpolation_modes) + in->data.interpolation = interpolation_modes[i]; + + snprintf(var_name, sizeof(var_name), "out_%u", output_locations[i]); + nir_variable *out = + nir_variable_create(b.shader, nir_var_shader_out, in->type, var_name); + out->data.location = output_locations[i]; + out->data.interpolation = in->data.interpolation; + + nir_copy_var(&b, out, in); + } + + return st_nir_finish_builtin_shader(st, b.shader, shader_name); +} -- 2.30.2