1 /* 2 * Copyright 2014 Ilia Mirkin 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, sublicense, 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 shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 #include <errno.h> 24 25 #include "tgsi/tgsi_text.h" 26 #include "util/u_debug.h" 27 28 #include "codegen/nv50_ir_driver.h" 29 #include "nv50/nv50_context.h" 30 31 /* these headers weren't really meant to be included together */ 32 #undef SB_DATA 33 34 #include "nv30/nv30_state.h" 35 #include "nv30/nvfx_shader.h" 36 37 static int 38 nv30_fp(int chipset, struct tgsi_token tokens[], 39 unsigned *size, unsigned **code) { 40 struct nv30_fragprog fp; 41 memset(&fp, 0, sizeof(fp)); 42 fp.pipe.tokens = tokens; 43 tgsi_scan_shader(fp.pipe.tokens, &fp.info); 44 _nvfx_fragprog_translate(chipset >= 0x40 ? 0x4097 : 0x3097, &fp); 45 *size = fp.insn_len * 4; 46 *code = fp.insn; 47 return !fp.translated; 48 } 49 50 static int 51 nv30_vp(int chipset, struct tgsi_token tokens[], 52 unsigned *size, unsigned **code) { 53 struct nv30_vertprog vp; 54 memset(&vp, 0, sizeof(vp)); 55 56 vp.pipe.tokens = tokens; 57 tgsi_scan_shader(vp.pipe.tokens, &vp.info); 58 _nvfx_vertprog_translate(chipset >= 0x40 ? 0x4097 : 0x3097, &vp); 59 *size = vp.nr_insns * 16; 60 *code = (unsigned *)vp.insns; 61 return !vp.translated; 62 } 63 64 static int 65 nv30_codegen(int chipset, int type, struct tgsi_token tokens[], 66 unsigned *size, unsigned **code) { 67 switch (type) { 68 case PIPE_SHADER_FRAGMENT: 69 return nv30_fp(chipset, tokens, size, code); 70 case PIPE_SHADER_VERTEX: 71 return nv30_vp(chipset, tokens, size, code); 72 } 73 _debug_printf("Unexpected shader type: %d\n", type); 74 return 1; 75 } 76 77 static int 78 dummy_assign_slots(struct nv50_ir_prog_info *info) 79 { 80 unsigned i, n, c; 81 82 n = 0; 83 for (i = 0; i < info->numInputs; ++i) { 84 for (c = 0; c < 4; ++c) 85 if (info->in[i].mask & (1 << c)) 86 info->in[i].slot[c] = n++; 87 } 88 89 /* VertexID before InstanceID */ 90 if (info->io.vertexId < info->numSysVals) 91 info->sv[info->io.vertexId].slot[0] = n++; 92 if (info->io.instanceId < info->numSysVals) 93 info->sv[info->io.instanceId].slot[0] = n++; 94 95 n = 0; 96 for (i = 0; i < info->numOutputs; ++i) { 97 for (c = 0; c < 4; ++c) 98 if (info->out[i].mask & (1 << c)) 99 info->out[i].slot[c] = n++; 100 } 101 return 0; 102 } 103 104 static int 105 nouveau_codegen(int chipset, int type, struct tgsi_token tokens[], 106 unsigned *size, unsigned **code) { 107 struct nv50_ir_prog_info info = {0}; 108 int ret; 109 110 info.type = type; 111 info.target = chipset; 112 info.bin.sourceRep = NV50_PROGRAM_IR_TGSI; 113 info.bin.source = tokens; 114 115 info.io.auxCBSlot = 15; 116 info.io.ucpBase = NV50_CB_AUX_UCP_OFFSET; 117 info.io.suInfoBase = NV50_CB_AUX_TEX_MS_OFFSET; 118 info.io.msInfoCBSlot = 15; 119 info.io.msInfoBase = NV50_CB_AUX_MS_OFFSET; 120 121 info.assignSlots = dummy_assign_slots; 122 123 info.optLevel = debug_get_num_option("NV50_PROG_OPTIMIZE", 3); 124 info.dbgFlags = debug_get_num_option("NV50_PROG_DEBUG", 0); 125 126 ret = nv50_ir_generate_code(&info); 127 if (ret) { 128 _debug_printf("Error compiling program: %d\n", ret); 129 return ret; 130 } 131 132 *size = info.bin.codeSize; 133 *code = info.bin.code; 134 return 0; 135 } 136 137 int 138 main(int argc, char *argv[]) 139 { 140 struct tgsi_token tokens[4096]; 141 int i, chipset = 0, type = -1; 142 const char *filename = NULL; 143 FILE *f; 144 char text[65536] = {0}; 145 unsigned size = 0, *code = NULL; 146 147 for (i = 1; i < argc; i++) { 148 if (!strcmp(argv[i], "-a")) 149 chipset = strtol(argv[++i], NULL, 16); 150 else 151 filename = argv[i]; 152 } 153 154 if (!chipset) { 155 _debug_printf("Must specify a chipset (-a)\n"); 156 return 1; 157 } 158 159 if (!filename) { 160 _debug_printf("Must specify a filename\n"); 161 return 1; 162 } 163 164 if (!strcmp(filename, "-")) 165 f = stdin; 166 else 167 f = fopen(filename, "r"); 168 169 if (!f) { 170 _debug_printf("Error opening file '%s': %s\n", filename, strerror(errno)); 171 return 1; 172 } 173 174 if (!fread(text, 1, sizeof(text), f) || ferror(f)) { 175 _debug_printf("Error reading file '%s'\n", filename); 176 fclose(f); 177 return 1; 178 } 179 fclose(f); 180 181 _debug_printf("Compiling for NV%X\n", chipset); 182 183 if (!strncmp(text, "FRAG", 4)) 184 type = PIPE_SHADER_FRAGMENT; 185 else if (!strncmp(text, "VERT", 4)) 186 type = PIPE_SHADER_VERTEX; 187 else if (!strncmp(text, "GEOM", 4)) 188 type = PIPE_SHADER_GEOMETRY; 189 else if (!strncmp(text, "COMP", 4)) 190 type = PIPE_SHADER_COMPUTE; 191 else if (!strncmp(text, "TESS_CTRL", 9)) 192 type = PIPE_SHADER_TESS_CTRL; 193 else if (!strncmp(text, "TESS_EVAL", 9)) 194 type = PIPE_SHADER_TESS_EVAL; 195 else { 196 _debug_printf("Unrecognized TGSI header\n"); 197 return 1; 198 } 199 200 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 201 _debug_printf("Failed to parse TGSI shader\n"); 202 return 1; 203 } 204 205 if (chipset >= 0x50) { 206 i = nouveau_codegen(chipset, type, tokens, &size, &code); 207 } else if (chipset >= 0x30) { 208 i = nv30_codegen(chipset, type, tokens, &size, &code); 209 } else { 210 _debug_printf("chipset NV%02X not supported\n", chipset); 211 i = 1; 212 } 213 if (i) 214 return i; 215 216 _debug_printf("program binary (%d bytes)\n", size); 217 for (i = 0; i < size; i += 4) { 218 printf("%08x ", code[i / 4]); 219 if (i % (8 * 4) == (7 * 4)) 220 printf("\n"); 221 } 222 if (i % (8 * 4) != 0) 223 printf("\n"); 224 225 return 0; 226 } 227