1/* 2 * Copyright (c) 2017 Lima Project 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sub license, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the 12 * next paragraph) shall be included in all copies or substantial portions 13 * of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 */ 24 25#include <err.h> 26#include <stdio.h> 27#include <string.h> 28 29#include "main/mtypes.h" 30 31#include "compiler/glsl/standalone.h" 32#include "compiler/glsl/glsl_to_nir.h" 33#include "compiler/glsl/gl_nir.h" 34#include "compiler/nir_types.h" 35 36#include "lima_context.h" 37#include "lima_program.h" 38#include "ir/lima_ir.h" 39#include "standalone/glsl.h" 40 41static void 42print_usage(void) 43{ 44 printf("Usage: lima_compiler [OPTIONS]... FILE\n"); 45 printf(" --help - show this message\n"); 46} 47 48static void 49insert_sorted(struct exec_list *var_list, nir_variable *new_var) 50{ 51 nir_foreach_variable_in_list(var, var_list) { 52 if (var->data.location > new_var->data.location && 53 new_var->data.location >= 0) { 54 exec_node_insert_node_before(&var->node, &new_var->node); 55 return; 56 } 57 } 58 exec_list_push_tail(var_list, &new_var->node); 59} 60 61static void 62sort_varyings(nir_shader *nir, nir_variable_mode mode) 63{ 64 struct exec_list new_list; 65 exec_list_make_empty(&new_list); 66 nir_foreach_variable_with_modes_safe(var, nir, mode) { 67 exec_node_remove(&var->node); 68 insert_sorted(&new_list, var); 69 } 70 exec_list_append(&nir->variables, &new_list); 71} 72 73static void 74fixup_varying_slots(nir_shader *nir, nir_variable_mode mode) 75{ 76 nir_foreach_variable_with_modes(var, nir, mode) { 77 if (var->data.location >= VARYING_SLOT_VAR0) { 78 var->data.location += 9; 79 } else if ((var->data.location >= VARYING_SLOT_TEX0) && 80 (var->data.location <= VARYING_SLOT_TEX7)) { 81 var->data.location += VARYING_SLOT_VAR0 - VARYING_SLOT_TEX0; 82 } 83 } 84} 85 86static nir_shader * 87load_glsl(unsigned num_files, char* const* files, gl_shader_stage stage) 88{ 89 static const struct standalone_options options = { 90 .glsl_version = 110, 91 .do_link = false, 92 }; 93 unsigned shader = 0; 94 switch (stage) { 95 case MESA_SHADER_FRAGMENT: 96 shader = PIPE_SHADER_FRAGMENT; 97 break; 98 case MESA_SHADER_VERTEX: 99 shader = PIPE_SHADER_VERTEX; 100 break; 101 default: 102 unreachable("bad stage"); 103 } 104 struct gl_shader_program *prog; 105 const nir_shader_compiler_options *nir_options = 106 lima_program_get_compiler_options(shader); 107 static struct gl_context local_ctx; 108 109 prog = standalone_compile_shader(&options, num_files, files, &local_ctx); 110 if (!prog) 111 errx(1, "couldn't parse `%s'", files[0]); 112 113 lima_do_glsl_optimizations(prog->_LinkedShaders[stage]->ir); 114 115 nir_shader *nir = glsl_to_nir(&local_ctx, prog, stage, nir_options); 116 117 /* required NIR passes: */ 118 if (nir_options->lower_all_io_to_temps || 119 nir->info.stage == MESA_SHADER_VERTEX || 120 nir->info.stage == MESA_SHADER_GEOMETRY) { 121 NIR_PASS_V(nir, nir_lower_io_to_temporaries, 122 nir_shader_get_entrypoint(nir), 123 true, true); 124 } else if (nir->info.stage == MESA_SHADER_FRAGMENT) { 125 NIR_PASS_V(nir, nir_lower_io_to_temporaries, 126 nir_shader_get_entrypoint(nir), 127 true, false); 128 } 129 130 NIR_PASS_V(nir, nir_lower_global_vars_to_local); 131 NIR_PASS_V(nir, nir_split_var_copies); 132 NIR_PASS_V(nir, nir_lower_var_copies); 133 134 NIR_PASS_V(nir, nir_split_var_copies); 135 NIR_PASS_V(nir, nir_lower_var_copies); 136 nir_print_shader(nir, stdout); 137 NIR_PASS_V(nir, gl_nir_lower_atomics, prog, true); 138 NIR_PASS_V(nir, nir_lower_atomics_to_ssbo); 139 nir_print_shader(nir, stdout); 140 141 switch (stage) { 142 case MESA_SHADER_VERTEX: 143 nir_assign_var_locations(nir, nir_var_shader_in, &nir->num_inputs, 144 st_glsl_type_size); 145 146 /* Re-lower global vars, to deal with any dead VS inputs. */ 147 NIR_PASS_V(nir, nir_lower_global_vars_to_local); 148 149 sort_varyings(nir, nir_var_shader_out); 150 nir_assign_var_locations(nir, nir_var_shader_out, &nir->num_outputs, 151 st_glsl_type_size); 152 fixup_varying_slots(nir, nir_var_shader_out); 153 break; 154 case MESA_SHADER_FRAGMENT: 155 sort_varyings(nir, nir_var_shader_in); 156 nir_assign_var_locations(nir, nir_var_shader_in, &nir->num_inputs, 157 st_glsl_type_size); 158 fixup_varying_slots(nir, nir_var_shader_in); 159 nir_assign_var_locations(nir, nir_var_shader_out, &nir->num_outputs, 160 st_glsl_type_size); 161 break; 162 default: 163 errx(1, "unhandled shader stage: %d", stage); 164 } 165 166 nir_assign_var_locations(nir, nir_var_uniform, 167 &nir->num_uniforms, 168 st_glsl_type_size); 169 170 NIR_PASS_V(nir, nir_lower_system_values); 171 NIR_PASS_V(nir, nir_lower_frexp); 172 NIR_PASS_V(nir, gl_nir_lower_samplers, prog); 173 174 return nir; 175} 176 177int 178main(int argc, char **argv) 179{ 180 int n; 181 182 lima_debug = LIMA_DEBUG_GP | LIMA_DEBUG_PP; 183 184 if (argc < 2) { 185 print_usage(); 186 return 1; 187 } 188 189 for (n = 1; n < argc; n++) { 190 if (!strcmp(argv[n], "--help")) { 191 print_usage(); 192 return 1; 193 } 194 195 break; 196 } 197 198 char *filename[10] = {0}; 199 filename[0] = argv[n]; 200 201 char *ext = rindex(filename[0], '.'); 202 unsigned stage = 0; 203 204 if (!strcmp(ext, ".frag")) { 205 stage = MESA_SHADER_FRAGMENT; 206 } 207 else if (!strcmp(ext, ".vert")) { 208 stage = MESA_SHADER_VERTEX; 209 } 210 else { 211 print_usage(); 212 return -1; 213 } 214 215 struct nir_lower_tex_options tex_options = { 216 .lower_txp = ~0u, 217 }; 218 219 nir_shader *nir = load_glsl(1, filename, stage); 220 221 switch (stage) { 222 case MESA_SHADER_VERTEX: 223 lima_program_optimize_vs_nir(nir); 224 225 nir_print_shader(nir, stdout); 226 227 struct lima_vs_compiled_shader *vs = ralloc(nir, struct lima_vs_compiled_shader); 228 gpir_compile_nir(vs, nir, NULL); 229 break; 230 case MESA_SHADER_FRAGMENT: 231 lima_program_optimize_fs_nir(nir, &tex_options); 232 233 nir_print_shader(nir, stdout); 234 235 struct lima_fs_compiled_shader *so = rzalloc(NULL, struct lima_fs_compiled_shader); 236 struct ra_regs *ra = ppir_regalloc_init(NULL); 237 ppir_compile_nir(so, nir, ra, NULL); 238 break; 239 default: 240 errx(1, "unhandled shader stage: %d", stage); 241 } 242 243 ralloc_free(nir); 244 return 0; 245} 246