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