Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.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.  
  139. int
  140. main(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, *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.       _debug_printf("Failed to parse TGSI shader\n");
  200.       return 1;
  201.    }
  202.  
  203.    if (chipset >= 0x50) {
  204.       i = nouveau_codegen(chipset, type, tokens, &size, &code);
  205.    } else if (chipset >= 0x30) {
  206.       i = nv30_codegen(chipset, type, tokens, &size, &code);
  207.    } else {
  208.       _debug_printf("chipset NV%02X not supported\n", chipset);
  209.       i = 1;
  210.    }
  211.    if (i)
  212.       return i;
  213.  
  214.    _debug_printf("program binary (%d bytes)\n", size);
  215.    for (i = 0; i < size; i += 4) {
  216.       printf("%08x ", code[i / 4]);
  217.       if (i % (8 * 4) == (7 * 4))
  218.          printf("\n");
  219.    }
  220.    if (i % (8 * 4) != 0)
  221.       printf("\n");
  222.  
  223.    return 0;
  224. }
  225.