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 37static int 38nv30_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 50static int 51nv30_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 64static int 65nv30_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 77static int 78dummy_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 104static int 105nouveau_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 = PIPE_SHADER_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 info.omitLineNum = debug_get_num_option("NV50_PROG_DEBUG_OMIT_LINENUM", 0); 126 127 ret = nv50_ir_generate_code(&info); 128 if (ret) { 129 _debug_printf("Error compiling program: %d\n", ret); 130 return ret; 131 } 132 133 *size = info.bin.codeSize; 134 *code = info.bin.code; 135 return 0; 136} 137 138int 139main(int argc, char *argv[]) 140{ 141 struct tgsi_token tokens[4096]; 142 int i, chipset = 0, type = -1; 143 const char *filename = NULL; 144 FILE *f; 145 char text[65536] = {0}; 146 unsigned size = 0, *code = NULL; 147 148 for (i = 1; i < argc; i++) { 149 if (!strcmp(argv[i], "-a")) 150 chipset = strtol(argv[++i], NULL, 16); 151 else 152 filename = argv[i]; 153 } 154 155 if (!chipset) { 156 _debug_printf("Must specify a chipset (-a)\n"); 157 return 1; 158 } 159 160 if (!filename) { 161 _debug_printf("Must specify a filename\n"); 162 return 1; 163 } 164 165 if (!strcmp(filename, "-")) 166 f = stdin; 167 else 168 f = fopen(filename, "r"); 169 170 if (!f) { 171 _debug_printf("Error opening file '%s': %s\n", filename, strerror(errno)); 172 return 1; 173 } 174 175 if (!fread(text, 1, sizeof(text), f) || ferror(f)) { 176 _debug_printf("Error reading file '%s'\n", filename); 177 fclose(f); 178 return 1; 179 } 180 fclose(f); 181 182 _debug_printf("Compiling for NV%X\n", chipset); 183 184 if (!strncmp(text, "FRAG", 4)) 185 type = PIPE_SHADER_FRAGMENT; 186 else if (!strncmp(text, "VERT", 4)) 187 type = PIPE_SHADER_VERTEX; 188 else if (!strncmp(text, "GEOM", 4)) 189 type = PIPE_SHADER_GEOMETRY; 190 else if (!strncmp(text, "COMP", 4)) 191 type = PIPE_SHADER_COMPUTE; 192 else if (!strncmp(text, "TESS_CTRL", 9)) 193 type = PIPE_SHADER_TESS_CTRL; 194 else if (!strncmp(text, "TESS_EVAL", 9)) 195 type = PIPE_SHADER_TESS_EVAL; 196 else { 197 _debug_printf("Unrecognized TGSI header\n"); 198 return 1; 199 } 200 201 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 202 _debug_printf("Failed to parse TGSI shader\n"); 203 return 1; 204 } 205 206 if (chipset >= 0x50) { 207 i = nouveau_codegen(chipset, type, tokens, &size, &code); 208 } else if (chipset >= 0x30) { 209 i = nv30_codegen(chipset, type, tokens, &size, &code); 210 } else { 211 _debug_printf("chipset NV%02X not supported\n", chipset); 212 i = 1; 213 } 214 if (i) 215 return i; 216 217 _debug_printf("program binary (%d bytes)\n", size); 218 for (i = 0; i < size; i += 4) { 219 printf("%08x ", code[i / 4]); 220 if (i % (8 * 4) == (7 * 4)) 221 printf("\n"); 222 } 223 if (i % (8 * 4) != 0) 224 printf("\n"); 225 226 return 0; 227} 228