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