1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2018 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
12bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
21bf215546Sopenharmony_ci */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#include "tgsi/tgsi_from_mesa.h"
24bf215546Sopenharmony_ci#include "st_nir.h"
25bf215546Sopenharmony_ci#include "st_program.h"
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "compiler/nir/nir_builder.h"
28bf215546Sopenharmony_ci#include "compiler/glsl/gl_nir.h"
29bf215546Sopenharmony_ci#include "compiler/glsl/gl_nir_linker.h"
30bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_cistruct pipe_shader_state *
33bf215546Sopenharmony_cist_nir_finish_builtin_shader(struct st_context *st,
34bf215546Sopenharmony_ci                             nir_shader *nir)
35bf215546Sopenharmony_ci{
36bf215546Sopenharmony_ci   struct pipe_screen *screen = st->screen;
37bf215546Sopenharmony_ci   gl_shader_stage stage = nir->info.stage;
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci   nir->info.separate_shader = true;
40bf215546Sopenharmony_ci   if (stage == MESA_SHADER_FRAGMENT)
41bf215546Sopenharmony_ci      nir->info.fs.untyped_color_outputs = true;
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci   NIR_PASS_V(nir, nir_lower_global_vars_to_local);
44bf215546Sopenharmony_ci   NIR_PASS_V(nir, nir_split_var_copies);
45bf215546Sopenharmony_ci   NIR_PASS_V(nir, nir_lower_var_copies);
46bf215546Sopenharmony_ci   NIR_PASS_V(nir, nir_lower_system_values);
47bf215546Sopenharmony_ci   NIR_PASS_V(nir, nir_lower_compute_system_values, NULL);
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   if (nir->options->lower_to_scalar) {
50bf215546Sopenharmony_ci      nir_variable_mode mask =
51bf215546Sopenharmony_ci          (stage > MESA_SHADER_VERTEX ? nir_var_shader_in : 0) |
52bf215546Sopenharmony_ci          (stage < MESA_SHADER_FRAGMENT ? nir_var_shader_out : 0);
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci      NIR_PASS_V(nir, nir_lower_io_to_scalar_early, mask);
55bf215546Sopenharmony_ci   }
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci   if (st->lower_rect_tex) {
58bf215546Sopenharmony_ci      const struct nir_lower_tex_options opts = { .lower_rect = true, };
59bf215546Sopenharmony_ci      NIR_PASS_V(nir, nir_lower_tex, &opts);
60bf215546Sopenharmony_ci   }
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci   nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci   st_nir_assign_vs_in_locations(nir);
65bf215546Sopenharmony_ci   st_nir_assign_varying_locations(st, nir);
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci   st_nir_lower_samplers(screen, nir, NULL, NULL);
68bf215546Sopenharmony_ci   st_nir_lower_uniforms(st, nir);
69bf215546Sopenharmony_ci   if (!screen->get_param(screen, PIPE_CAP_NIR_IMAGES_AS_DEREF))
70bf215546Sopenharmony_ci      NIR_PASS_V(nir, gl_nir_lower_images, false);
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   if (screen->finalize_nir) {
73bf215546Sopenharmony_ci      char *msg = screen->finalize_nir(screen, nir);
74bf215546Sopenharmony_ci      free(msg);
75bf215546Sopenharmony_ci   } else {
76bf215546Sopenharmony_ci      gl_nir_opts(nir);
77bf215546Sopenharmony_ci   }
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci   struct pipe_shader_state state = {
80bf215546Sopenharmony_ci      .type = PIPE_SHADER_IR_NIR,
81bf215546Sopenharmony_ci      .ir.nir = nir,
82bf215546Sopenharmony_ci   };
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   return st_create_nir_shader(st, &state);
85bf215546Sopenharmony_ci}
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci/**
88bf215546Sopenharmony_ci * Make a simple shader that copies inputs to corresponding outputs.
89bf215546Sopenharmony_ci */
90bf215546Sopenharmony_cistruct pipe_shader_state *
91bf215546Sopenharmony_cist_nir_make_passthrough_shader(struct st_context *st,
92bf215546Sopenharmony_ci                               const char *shader_name,
93bf215546Sopenharmony_ci                               gl_shader_stage stage,
94bf215546Sopenharmony_ci                               unsigned num_vars,
95bf215546Sopenharmony_ci                               unsigned *input_locations,
96bf215546Sopenharmony_ci                               unsigned *output_locations,
97bf215546Sopenharmony_ci                               unsigned *interpolation_modes,
98bf215546Sopenharmony_ci                               unsigned sysval_mask)
99bf215546Sopenharmony_ci{
100bf215546Sopenharmony_ci   const struct glsl_type *vec4 = glsl_vec4_type();
101bf215546Sopenharmony_ci   const nir_shader_compiler_options *options =
102bf215546Sopenharmony_ci      st_get_nir_compiler_options(st, stage);
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   nir_builder b = nir_builder_init_simple_shader(stage, options,
105bf215546Sopenharmony_ci                                                  "%s", shader_name);
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   char var_name[15];
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_vars; i++) {
110bf215546Sopenharmony_ci      nir_variable *in;
111bf215546Sopenharmony_ci      if (sysval_mask & (1 << i)) {
112bf215546Sopenharmony_ci         snprintf(var_name, sizeof(var_name), "sys_%u", input_locations[i]);
113bf215546Sopenharmony_ci         in = nir_variable_create(b.shader, nir_var_system_value,
114bf215546Sopenharmony_ci                                  glsl_int_type(), var_name);
115bf215546Sopenharmony_ci      } else {
116bf215546Sopenharmony_ci         snprintf(var_name, sizeof(var_name), "in_%u", input_locations[i]);
117bf215546Sopenharmony_ci         in = nir_variable_create(b.shader, nir_var_shader_in, vec4, var_name);
118bf215546Sopenharmony_ci      }
119bf215546Sopenharmony_ci      in->data.location = input_locations[i];
120bf215546Sopenharmony_ci      if (interpolation_modes)
121bf215546Sopenharmony_ci         in->data.interpolation = interpolation_modes[i];
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci      snprintf(var_name, sizeof(var_name), "out_%u", output_locations[i]);
124bf215546Sopenharmony_ci      nir_variable *out =
125bf215546Sopenharmony_ci         nir_variable_create(b.shader, nir_var_shader_out, in->type, var_name);
126bf215546Sopenharmony_ci      out->data.location = output_locations[i];
127bf215546Sopenharmony_ci      out->data.interpolation = in->data.interpolation;
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci      nir_copy_var(&b, out, in);
130bf215546Sopenharmony_ci   }
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   return st_nir_finish_builtin_shader(st, b.shader);
133bf215546Sopenharmony_ci}
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci/**
136bf215546Sopenharmony_ci * Make a simple shader that reads color value from a constant buffer
137bf215546Sopenharmony_ci * and uses it to clear all color buffers.
138bf215546Sopenharmony_ci */
139bf215546Sopenharmony_cistruct pipe_shader_state *
140bf215546Sopenharmony_cist_nir_make_clearcolor_shader(struct st_context *st)
141bf215546Sopenharmony_ci{
142bf215546Sopenharmony_ci   const nir_shader_compiler_options *options =
143bf215546Sopenharmony_ci      st_get_nir_compiler_options(st, MESA_SHADER_FRAGMENT);
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, options,
146bf215546Sopenharmony_ci                                                  "clear color FS");
147bf215546Sopenharmony_ci   b.shader->info.num_ubos = 1;
148bf215546Sopenharmony_ci   b.shader->num_outputs = 1;
149bf215546Sopenharmony_ci   b.shader->num_uniforms = 1;
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   /* Read clear color from constant buffer */
152bf215546Sopenharmony_ci   nir_ssa_def *clear_color = nir_load_uniform(&b, 4, 32, nir_imm_int(&b,0),
153bf215546Sopenharmony_ci                                               .range = 16,
154bf215546Sopenharmony_ci                                               .dest_type = nir_type_float32);
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci   nir_variable *color_out =
157bf215546Sopenharmony_ci      nir_variable_create(b.shader, nir_var_shader_out, glsl_vec_type(4),
158bf215546Sopenharmony_ci                             "outcolor");
159bf215546Sopenharmony_ci   color_out->data.location = FRAG_RESULT_COLOR;
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   /* Write out the color */
162bf215546Sopenharmony_ci   nir_store_var(&b, color_out, clear_color, 0xf);
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci   return st_nir_finish_builtin_shader(st, b.shader);
165bf215546Sopenharmony_ci}
166