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