1b8e80941Smrg/*
2b8e80941Smrg * Copyright (c) 2017-2019 Lima Project
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sub license,
8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
9b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice (including the
12b8e80941Smrg * next paragraph) shall be included in all copies or substantial portions
13b8e80941Smrg * of the Software.
14b8e80941Smrg *
15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21b8e80941Smrg * DEALINGS IN THE SOFTWARE.
22b8e80941Smrg *
23b8e80941Smrg */
24b8e80941Smrg
25b8e80941Smrg#include "util/u_memory.h"
26b8e80941Smrg#include "util/ralloc.h"
27b8e80941Smrg#include "util/u_debug.h"
28b8e80941Smrg
29b8e80941Smrg#include "tgsi/tgsi_dump.h"
30b8e80941Smrg#include "compiler/nir/nir.h"
31b8e80941Smrg#include "nir/tgsi_to_nir.h"
32b8e80941Smrg
33b8e80941Smrg#include "pipe/p_state.h"
34b8e80941Smrg
35b8e80941Smrg#include "lima_screen.h"
36b8e80941Smrg#include "lima_context.h"
37b8e80941Smrg#include "lima_program.h"
38b8e80941Smrg#include "lima_bo.h"
39b8e80941Smrg#include "ir/lima_ir.h"
40b8e80941Smrg
41b8e80941Smrgstatic const nir_shader_compiler_options vs_nir_options = {
42b8e80941Smrg   .lower_ffma = true,
43b8e80941Smrg   .lower_fpow = true,
44b8e80941Smrg   .lower_ffract = true,
45b8e80941Smrg   .lower_fdiv = true,
46b8e80941Smrg   .lower_fsqrt = true,
47b8e80941Smrg   .lower_sub = true,
48b8e80941Smrg   .lower_flrp32 = true,
49b8e80941Smrg   .lower_flrp64 = true,
50b8e80941Smrg   /* could be implemented by clamp */
51b8e80941Smrg   .lower_fsat = true,
52b8e80941Smrg};
53b8e80941Smrg
54b8e80941Smrgstatic const nir_shader_compiler_options fs_nir_options = {
55b8e80941Smrg   .lower_fpow = true,
56b8e80941Smrg   .lower_fdiv = true,
57b8e80941Smrg   .lower_sub = true,
58b8e80941Smrg   .lower_flrp32 = true,
59b8e80941Smrg   .lower_flrp64 = true,
60b8e80941Smrg   .lower_fsign = true,
61b8e80941Smrg};
62b8e80941Smrg
63b8e80941Smrgconst void *
64b8e80941Smrglima_program_get_compiler_options(enum pipe_shader_type shader)
65b8e80941Smrg{
66b8e80941Smrg   switch (shader) {
67b8e80941Smrg   case PIPE_SHADER_VERTEX:
68b8e80941Smrg      return &vs_nir_options;
69b8e80941Smrg   case PIPE_SHADER_FRAGMENT:
70b8e80941Smrg      return &fs_nir_options;
71b8e80941Smrg   default:
72b8e80941Smrg      return NULL;
73b8e80941Smrg   }
74b8e80941Smrg}
75b8e80941Smrg
76b8e80941Smrgstatic int
77b8e80941Smrgtype_size(const struct glsl_type *type, bool bindless)
78b8e80941Smrg{
79b8e80941Smrg   return glsl_count_attribute_slots(type, false);
80b8e80941Smrg}
81b8e80941Smrg
82b8e80941Smrgstatic void
83b8e80941Smrglima_program_optimize_vs_nir(struct nir_shader *s)
84b8e80941Smrg{
85b8e80941Smrg   bool progress;
86b8e80941Smrg
87b8e80941Smrg   NIR_PASS_V(s, nir_lower_io, nir_var_all, type_size, 0);
88b8e80941Smrg   NIR_PASS_V(s, nir_lower_regs_to_ssa);
89b8e80941Smrg   NIR_PASS_V(s, nir_lower_load_const_to_scalar);
90b8e80941Smrg   NIR_PASS_V(s, lima_nir_lower_uniform_to_scalar);
91b8e80941Smrg   NIR_PASS_V(s, nir_lower_io_to_scalar,
92b8e80941Smrg              nir_var_shader_in|nir_var_shader_out);
93b8e80941Smrg   NIR_PASS_V(s, nir_lower_bool_to_float);
94b8e80941Smrg
95b8e80941Smrg   do {
96b8e80941Smrg      progress = false;
97b8e80941Smrg
98b8e80941Smrg      NIR_PASS_V(s, nir_lower_vars_to_ssa);
99b8e80941Smrg      NIR_PASS(progress, s, nir_lower_alu_to_scalar);
100b8e80941Smrg      NIR_PASS(progress, s, nir_lower_phis_to_scalar);
101b8e80941Smrg      NIR_PASS(progress, s, nir_copy_prop);
102b8e80941Smrg      NIR_PASS(progress, s, nir_opt_remove_phis);
103b8e80941Smrg      NIR_PASS(progress, s, nir_opt_dce);
104b8e80941Smrg      NIR_PASS(progress, s, nir_opt_dead_cf);
105b8e80941Smrg      NIR_PASS(progress, s, nir_opt_cse);
106b8e80941Smrg      NIR_PASS(progress, s, nir_opt_peephole_select, 8, true, true);
107b8e80941Smrg      NIR_PASS(progress, s, nir_opt_algebraic);
108b8e80941Smrg      NIR_PASS(progress, s, nir_opt_constant_folding);
109b8e80941Smrg      NIR_PASS(progress, s, nir_opt_undef);
110b8e80941Smrg      NIR_PASS(progress, s, nir_opt_loop_unroll,
111b8e80941Smrg               nir_var_shader_in |
112b8e80941Smrg               nir_var_shader_out |
113b8e80941Smrg               nir_var_function_temp);
114b8e80941Smrg   } while (progress);
115b8e80941Smrg
116b8e80941Smrg   NIR_PASS_V(s, nir_lower_locals_to_regs);
117b8e80941Smrg   NIR_PASS_V(s, nir_convert_from_ssa, true);
118b8e80941Smrg   NIR_PASS_V(s, nir_remove_dead_variables, nir_var_function_temp);
119b8e80941Smrg   nir_sweep(s);
120b8e80941Smrg}
121b8e80941Smrg
122b8e80941Smrgstatic void
123b8e80941Smrglima_program_optimize_fs_nir(struct nir_shader *s)
124b8e80941Smrg{
125b8e80941Smrg   bool progress;
126b8e80941Smrg
127b8e80941Smrg   NIR_PASS_V(s, nir_lower_fragcoord_wtrans);
128b8e80941Smrg   NIR_PASS_V(s, nir_lower_io, nir_var_all, type_size, 0);
129b8e80941Smrg   NIR_PASS_V(s, nir_lower_regs_to_ssa);
130b8e80941Smrg   NIR_PASS_V(s, nir_lower_bool_to_float);
131b8e80941Smrg
132b8e80941Smrg   do {
133b8e80941Smrg      progress = false;
134b8e80941Smrg
135b8e80941Smrg      NIR_PASS_V(s, nir_lower_vars_to_ssa);
136b8e80941Smrg      //NIR_PASS(progress, s, nir_lower_alu_to_scalar);
137b8e80941Smrg      NIR_PASS(progress, s, nir_lower_phis_to_scalar);
138b8e80941Smrg      NIR_PASS(progress, s, nir_copy_prop);
139b8e80941Smrg      NIR_PASS(progress, s, nir_opt_remove_phis);
140b8e80941Smrg      NIR_PASS(progress, s, nir_opt_dce);
141b8e80941Smrg      NIR_PASS(progress, s, nir_opt_dead_cf);
142b8e80941Smrg      NIR_PASS(progress, s, nir_opt_cse);
143b8e80941Smrg      NIR_PASS(progress, s, nir_opt_peephole_select, 8, true, true);
144b8e80941Smrg      NIR_PASS(progress, s, nir_opt_algebraic);
145b8e80941Smrg      NIR_PASS(progress, s, nir_opt_constant_folding);
146b8e80941Smrg      NIR_PASS(progress, s, nir_opt_undef);
147b8e80941Smrg      NIR_PASS(progress, s, nir_opt_loop_unroll,
148b8e80941Smrg               nir_var_shader_in |
149b8e80941Smrg               nir_var_shader_out |
150b8e80941Smrg               nir_var_function_temp);
151b8e80941Smrg   } while (progress);
152b8e80941Smrg
153b8e80941Smrg   /* Lower modifiers */
154b8e80941Smrg   NIR_PASS_V(s, nir_lower_to_source_mods, nir_lower_all_source_mods);
155b8e80941Smrg   NIR_PASS_V(s, nir_copy_prop);
156b8e80941Smrg   NIR_PASS_V(s, nir_opt_dce);
157b8e80941Smrg
158b8e80941Smrg   NIR_PASS_V(s, nir_lower_locals_to_regs);
159b8e80941Smrg   NIR_PASS_V(s, nir_convert_from_ssa, true);
160b8e80941Smrg   NIR_PASS_V(s, nir_remove_dead_variables, nir_var_function_temp);
161b8e80941Smrg
162b8e80941Smrg   NIR_PASS_V(s, nir_move_vec_src_uses_to_dest);
163b8e80941Smrg   NIR_PASS_V(s, nir_lower_vec_to_movs);
164b8e80941Smrg
165b8e80941Smrg   nir_sweep(s);
166b8e80941Smrg}
167b8e80941Smrg
168b8e80941Smrgstatic void *
169b8e80941Smrglima_create_fs_state(struct pipe_context *pctx,
170b8e80941Smrg                     const struct pipe_shader_state *cso)
171b8e80941Smrg{
172b8e80941Smrg   struct lima_screen *screen = lima_screen(pctx->screen);
173b8e80941Smrg   struct lima_fs_shader_state *so = rzalloc(NULL, struct lima_fs_shader_state);
174b8e80941Smrg
175b8e80941Smrg   if (!so)
176b8e80941Smrg      return NULL;
177b8e80941Smrg
178b8e80941Smrg   nir_shader *nir;
179b8e80941Smrg   if (cso->type == PIPE_SHADER_IR_NIR)
180b8e80941Smrg      nir = cso->ir.nir;
181b8e80941Smrg   else {
182b8e80941Smrg      assert(cso->type == PIPE_SHADER_IR_TGSI);
183b8e80941Smrg
184b8e80941Smrg      nir = tgsi_to_nir(cso->tokens, pctx->screen);
185b8e80941Smrg   }
186b8e80941Smrg
187b8e80941Smrg   lima_program_optimize_fs_nir(nir);
188b8e80941Smrg
189b8e80941Smrg   if (lima_debug & LIMA_DEBUG_PP)
190b8e80941Smrg      nir_print_shader(nir, stdout);
191b8e80941Smrg
192b8e80941Smrg   if (!ppir_compile_nir(so, nir, screen->pp_ra)) {
193b8e80941Smrg      ralloc_free(so);
194b8e80941Smrg      return NULL;
195b8e80941Smrg   }
196b8e80941Smrg
197b8e80941Smrg   return so;
198b8e80941Smrg}
199b8e80941Smrg
200b8e80941Smrgstatic void
201b8e80941Smrglima_bind_fs_state(struct pipe_context *pctx, void *hwcso)
202b8e80941Smrg{
203b8e80941Smrg   struct lima_context *ctx = lima_context(pctx);
204b8e80941Smrg
205b8e80941Smrg   ctx->fs = hwcso;
206b8e80941Smrg   ctx->dirty |= LIMA_CONTEXT_DIRTY_SHADER_FRAG;
207b8e80941Smrg}
208b8e80941Smrg
209b8e80941Smrgstatic void
210b8e80941Smrglima_delete_fs_state(struct pipe_context *pctx, void *hwcso)
211b8e80941Smrg{
212b8e80941Smrg   struct lima_fs_shader_state *so = hwcso;
213b8e80941Smrg
214b8e80941Smrg   if (so->bo)
215b8e80941Smrg      lima_bo_free(so->bo);
216b8e80941Smrg
217b8e80941Smrg   ralloc_free(so);
218b8e80941Smrg}
219b8e80941Smrg
220b8e80941Smrgbool
221b8e80941Smrglima_update_vs_state(struct lima_context *ctx)
222b8e80941Smrg{
223b8e80941Smrg   struct lima_vs_shader_state *vs = ctx->vs;
224b8e80941Smrg   if (!vs->bo) {
225b8e80941Smrg      struct lima_screen *screen = lima_screen(ctx->base.screen);
226b8e80941Smrg      vs->bo = lima_bo_create(screen, vs->shader_size, 0);
227b8e80941Smrg      if (!vs->bo) {
228b8e80941Smrg         fprintf(stderr, "lima: create vs shader bo fail\n");
229b8e80941Smrg         return false;
230b8e80941Smrg      }
231b8e80941Smrg
232b8e80941Smrg      memcpy(lima_bo_map(vs->bo), vs->shader, vs->shader_size);
233b8e80941Smrg      ralloc_free(vs->shader);
234b8e80941Smrg      vs->shader = NULL;
235b8e80941Smrg   }
236b8e80941Smrg
237b8e80941Smrg   return true;
238b8e80941Smrg}
239b8e80941Smrg
240b8e80941Smrgbool
241b8e80941Smrglima_update_fs_state(struct lima_context *ctx)
242b8e80941Smrg{
243b8e80941Smrg   struct lima_fs_shader_state *fs = ctx->fs;
244b8e80941Smrg   if (!fs->bo) {
245b8e80941Smrg      struct lima_screen *screen = lima_screen(ctx->base.screen);
246b8e80941Smrg      fs->bo = lima_bo_create(screen, fs->shader_size, 0);
247b8e80941Smrg      if (!fs->bo) {
248b8e80941Smrg         fprintf(stderr, "lima: create fs shader bo fail\n");
249b8e80941Smrg         return false;
250b8e80941Smrg      }
251b8e80941Smrg
252b8e80941Smrg      memcpy(lima_bo_map(fs->bo), fs->shader, fs->shader_size);
253b8e80941Smrg      ralloc_free(fs->shader);
254b8e80941Smrg      fs->shader = NULL;
255b8e80941Smrg   }
256b8e80941Smrg
257b8e80941Smrg   return true;
258b8e80941Smrg}
259b8e80941Smrg
260b8e80941Smrgstatic void *
261b8e80941Smrglima_create_vs_state(struct pipe_context *pctx,
262b8e80941Smrg                     const struct pipe_shader_state *cso)
263b8e80941Smrg{
264b8e80941Smrg   struct lima_vs_shader_state *so = rzalloc(NULL, struct lima_vs_shader_state);
265b8e80941Smrg
266b8e80941Smrg   if (!so)
267b8e80941Smrg      return NULL;
268b8e80941Smrg
269b8e80941Smrg   nir_shader *nir;
270b8e80941Smrg   if (cso->type == PIPE_SHADER_IR_NIR)
271b8e80941Smrg      nir = cso->ir.nir;
272b8e80941Smrg   else {
273b8e80941Smrg      assert(cso->type == PIPE_SHADER_IR_TGSI);
274b8e80941Smrg
275b8e80941Smrg      nir = tgsi_to_nir(cso->tokens, pctx->screen);
276b8e80941Smrg   }
277b8e80941Smrg
278b8e80941Smrg   lima_program_optimize_vs_nir(nir);
279b8e80941Smrg
280b8e80941Smrg   if (lima_debug & LIMA_DEBUG_GP)
281b8e80941Smrg      nir_print_shader(nir, stdout);
282b8e80941Smrg
283b8e80941Smrg   if (!gpir_compile_nir(so, nir)) {
284b8e80941Smrg      ralloc_free(so);
285b8e80941Smrg      return NULL;
286b8e80941Smrg   }
287b8e80941Smrg
288b8e80941Smrg   return so;
289b8e80941Smrg}
290b8e80941Smrg
291b8e80941Smrgstatic void
292b8e80941Smrglima_bind_vs_state(struct pipe_context *pctx, void *hwcso)
293b8e80941Smrg{
294b8e80941Smrg   struct lima_context *ctx = lima_context(pctx);
295b8e80941Smrg
296b8e80941Smrg   ctx->vs = hwcso;
297b8e80941Smrg   ctx->dirty |= LIMA_CONTEXT_DIRTY_SHADER_VERT;
298b8e80941Smrg}
299b8e80941Smrg
300b8e80941Smrgstatic void
301b8e80941Smrglima_delete_vs_state(struct pipe_context *pctx, void *hwcso)
302b8e80941Smrg{
303b8e80941Smrg   struct lima_vs_shader_state *so = hwcso;
304b8e80941Smrg
305b8e80941Smrg   if (so->bo)
306b8e80941Smrg      lima_bo_free(so->bo);
307b8e80941Smrg
308b8e80941Smrg   ralloc_free(so);
309b8e80941Smrg}
310b8e80941Smrg
311b8e80941Smrgvoid
312b8e80941Smrglima_program_init(struct lima_context *ctx)
313b8e80941Smrg{
314b8e80941Smrg   ctx->base.create_fs_state = lima_create_fs_state;
315b8e80941Smrg   ctx->base.bind_fs_state = lima_bind_fs_state;
316b8e80941Smrg   ctx->base.delete_fs_state = lima_delete_fs_state;
317b8e80941Smrg
318b8e80941Smrg   ctx->base.create_vs_state = lima_create_vs_state;
319b8e80941Smrg   ctx->base.bind_vs_state = lima_bind_vs_state;
320b8e80941Smrg   ctx->base.delete_vs_state = lima_delete_vs_state;
321b8e80941Smrg}
322