nouveau_compiler.c revision af69d88d
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 = NV50_PROGRAM_IR_TGSI; 113 info.bin.source = tokens; 114 115 info.io.ucpCBSlot = 15; 116 info.io.ucpBase = NV50_CB_AUX_UCP_OFFSET; 117 118 info.io.resInfoCBSlot = 15; 119 info.io.suInfoBase = NV50_CB_AUX_TEX_MS_OFFSET; 120 info.io.msInfoCBSlot = 15; 121 info.io.msInfoBase = NV50_CB_AUX_MS_OFFSET; 122 123 info.assignSlots = dummy_assign_slots; 124 125 info.optLevel = debug_get_num_option("NV50_PROG_OPTIMIZE", 3); 126 info.dbgFlags = debug_get_num_option("NV50_PROG_DEBUG", 0); 127 128 ret = nv50_ir_generate_code(&info); 129 if (ret) { 130 _debug_printf("Error compiling program: %d\n", ret); 131 return ret; 132 } 133 134 *size = info.bin.codeSize; 135 *code = info.bin.code; 136 return 0; 137} 138 139int 140main(int argc, char *argv[]) 141{ 142 struct tgsi_token tokens[1024]; 143 int i, chipset = 0, type = -1; 144 const char *filename = NULL; 145 FILE *f; 146 char text[65536] = {0}; 147 unsigned size, *code; 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 == NULL) { 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 { 194 _debug_printf("Unrecognized TGSI header\n"); 195 return 1; 196 } 197 198 if (!tgsi_text_translate(text, tokens, Elements(tokens))) 199 return 1; 200 201 if (chipset >= 0x50) { 202 i = nouveau_codegen(chipset, type, tokens, &size, &code); 203 } else if (chipset >= 0x30) { 204 i = nv30_codegen(chipset, type, tokens, &size, &code); 205 } else { 206 _debug_printf("chipset NV%02X not supported\n", chipset); 207 i = 1; 208 } 209 if (i) 210 return i; 211 212 _debug_printf("program binary (%d bytes)\n", size); 213 for (i = 0; i < size; i += 4) { 214 printf("%08x ", code[i / 4]); 215 if (i % (8 * 4) == (7 * 4)) 216 printf("\n"); 217 } 218 if (i % (8 * 4) != 0) 219 printf("\n"); 220 221 return 0; 222} 223