diff options
author | Kenneth Graunke <kenneth@whitecape.org> | 2018-10-29 22:30:06 -0700 |
---|---|---|
committer | Kenneth Graunke <kenneth@whitecape.org> | 2019-02-05 13:43:33 -0800 |
commit | cdc53fa81cbeb80373eac33ef7695d9025caf14b (patch) | |
tree | e6b10a9f3dae3aed6a9ecc733305ff1a04003cee /src/mesa/state_tracker/st_nir_builtins.c | |
parent | 4f799264d1ac40769f84d27e945e981a89f4346e (diff) | |
download | mesa-cdc53fa81cbeb80373eac33ef7695d9025caf14b.tar.gz |
st/nir: Make new helpers for constructing built-in NIR shaders.
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 <marek.olsak@amd.com>
Tested-by: Rob Clark <robdclark@gmail.com>
Tested-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'src/mesa/state_tracker/st_nir_builtins.c')
-rw-r--r-- | src/mesa/state_tracker/st_nir_builtins.c | 138 |
1 files changed, 138 insertions, 0 deletions
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); +} |