Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
  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 (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21.  * SOFTWARE.
  22.  *
  23.  * Authors:
  24.  *    Rob Clark <robclark@freedesktop.org>
  25.  */
  26.  
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <sys/mman.h>
  30. #include <fcntl.h>
  31. #include <stdint.h>
  32. #include <stdlib.h>
  33. #include <err.h>
  34.  
  35. #include "tgsi/tgsi_parse.h"
  36. #include "tgsi/tgsi_text.h"
  37. #include "tgsi/tgsi_dump.h"
  38.  
  39. #include "freedreno_util.h"
  40.  
  41. #include "ir3_compiler.h"
  42. #include "instr-a3xx.h"
  43. #include "ir3.h"
  44.  
  45. static void dump_reg(const char *name, uint32_t r)
  46. {
  47.         if (r != regid(63,0))
  48.                 debug_printf("; %s: r%d.%c\n", name, r >> 2, "xyzw"[r & 0x3]);
  49. }
  50.  
  51. static void dump_semantic(struct ir3_shader_variant *so,
  52.                 unsigned sem, const char *name)
  53. {
  54.         uint32_t regid;
  55.         regid = ir3_find_output_regid(so, ir3_semantic_name(sem, 0));
  56.         dump_reg(name, regid);
  57. }
  58.  
  59. static void dump_info(struct ir3_shader_variant *so, const char *str)
  60. {
  61.         uint32_t *bin;
  62.         const char *type = (so->type == SHADER_VERTEX) ? "VERT" : "FRAG";
  63.  
  64.         // for debug, dump some before/after info:
  65.         // TODO make gpu_id configurable on cmdline
  66.         bin = ir3_shader_assemble(so, 320);
  67.         if (fd_mesa_debug & FD_DBG_DISASM) {
  68.                 struct ir3_block *block = so->ir->block;
  69.                 struct ir3_register *reg;
  70.                 uint8_t regid;
  71.                 unsigned i;
  72.  
  73.                 debug_printf("; %s: %s\n", type, str);
  74.  
  75.                 for (i = 0; i < block->ninputs; i++) {
  76.                         if (!block->inputs[i]) {
  77.                                 debug_printf("; in%d unused\n", i);
  78.                                 continue;
  79.                         }
  80.                         reg = block->inputs[i]->regs[0];
  81.                         regid = reg->num;
  82.                         debug_printf("@in(%sr%d.%c)\tin%d\n",
  83.                                         (reg->flags & IR3_REG_HALF) ? "h" : "",
  84.                                         (regid >> 2), "xyzw"[regid & 0x3], i);
  85.                 }
  86.  
  87.                 for (i = 0; i < block->noutputs; i++) {
  88.                         if (!block->outputs[i]) {
  89.                                 debug_printf("; out%d unused\n", i);
  90.                                 continue;
  91.                         }
  92.                         /* kill shows up as a virtual output.. skip it! */
  93.                         if (is_kill(block->outputs[i]))
  94.                                 continue;
  95.                         reg = block->outputs[i]->regs[0];
  96.                         regid = reg->num;
  97.                         debug_printf("@out(%sr%d.%c)\tout%d\n",
  98.                                         (reg->flags & IR3_REG_HALF) ? "h" : "",
  99.                                         (regid >> 2), "xyzw"[regid & 0x3], i);
  100.                 }
  101.  
  102.                 for (i = 0; i < so->immediates_count; i++) {
  103.                         debug_printf("@const(c%d.x)\t", so->first_immediate + i);
  104.                         debug_printf("0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
  105.                                         so->immediates[i].val[0],
  106.                                         so->immediates[i].val[1],
  107.                                         so->immediates[i].val[2],
  108.                                         so->immediates[i].val[3]);
  109.                 }
  110.  
  111.                 disasm_a3xx(bin, so->info.sizedwords, 0, so->type);
  112.  
  113.                 debug_printf("; %s: outputs:", type);
  114.                 for (i = 0; i < so->outputs_count; i++) {
  115.                         uint8_t regid = so->outputs[i].regid;
  116.                         ir3_semantic sem = so->outputs[i].semantic;
  117.                         debug_printf(" r%d.%c (%u:%u)",
  118.                                         (regid >> 2), "xyzw"[regid & 0x3],
  119.                                         sem2name(sem), sem2idx(sem));
  120.                 }
  121.                 debug_printf("\n");
  122.                 debug_printf("; %s: inputs:", type);
  123.                 for (i = 0; i < so->inputs_count; i++) {
  124.                         uint8_t regid = so->inputs[i].regid;
  125.                         ir3_semantic sem = so->inputs[i].semantic;
  126.                         debug_printf(" r%d.%c (%u:%u,cm=%x,il=%u,b=%u)",
  127.                                         (regid >> 2), "xyzw"[regid & 0x3],
  128.                                         sem2name(sem), sem2idx(sem),
  129.                                         so->inputs[i].compmask,
  130.                                         so->inputs[i].inloc,
  131.                                         so->inputs[i].bary);
  132.                 }
  133.                 debug_printf("\n");
  134.         }
  135.  
  136.         /* print generic shader info: */
  137.         debug_printf("; %s: %u instructions, %d half, %d full\n", type,
  138.                         so->info.instrs_count,
  139.                         so->info.max_half_reg + 1,
  140.                         so->info.max_reg + 1);
  141.  
  142.         /* print shader type specific info: */
  143.         switch (so->type) {
  144.         case SHADER_VERTEX:
  145.                 dump_semantic(so, TGSI_SEMANTIC_POSITION, "pos");
  146.                 dump_semantic(so, TGSI_SEMANTIC_PSIZE, "psize");
  147.                 break;
  148.         case SHADER_FRAGMENT:
  149.                 dump_reg("pos (bary)", so->pos_regid);
  150.                 dump_semantic(so, TGSI_SEMANTIC_POSITION, "posz");
  151.                 dump_semantic(so, TGSI_SEMANTIC_COLOR, "color");
  152.                 /* these two are hard-coded since we don't know how to
  153.                  * program them to anything but all 0's...
  154.                  */
  155.                 if (so->frag_coord)
  156.                         debug_printf("; fragcoord: r0.x\n");
  157.                 if (so->frag_face)
  158.                         debug_printf("; fragface: hr0.x\n");
  159.                 break;
  160.         case SHADER_COMPUTE:
  161.                 break;
  162.         }
  163.         free(bin);
  164.  
  165.         debug_printf("\n");
  166. }
  167.  
  168.  
  169. static int
  170. read_file(const char *filename, void **ptr, size_t *size)
  171. {
  172.         int fd, ret;
  173.         struct stat st;
  174.  
  175.         *ptr = MAP_FAILED;
  176.  
  177.         fd = open(filename, O_RDONLY);
  178.         if (fd == -1) {
  179.                 warnx("couldn't open `%s'", filename);
  180.                 return 1;
  181.         }
  182.  
  183.         ret = fstat(fd, &st);
  184.         if (ret)
  185.                 errx(1, "couldn't stat `%s'", filename);
  186.  
  187.         *size = st.st_size;
  188.         *ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
  189.         if (*ptr == MAP_FAILED)
  190.                 errx(1, "couldn't map `%s'", filename);
  191.  
  192.         close(fd);
  193.  
  194.         return 0;
  195. }
  196.  
  197. static void reset_variant(struct ir3_shader_variant *v, const char *msg)
  198. {
  199.         printf("; %s\n", msg);
  200.         v->inputs_count = 0;
  201.         v->outputs_count = 0;
  202.         v->total_in = 0;
  203.         v->has_samp = false;
  204.         v->immediates_count = 0;
  205. }
  206.  
  207. static void print_usage(void)
  208. {
  209.         printf("Usage: ir3_compiler [OPTIONS]... FILE\n");
  210.         printf("    --verbose         - verbose compiler/debug messages\n");
  211.         printf("    --binning-pass    - generate binning pass shader (VERT)\n");
  212.         printf("    --color-two-side  - emulate two-sided color (FRAG)\n");
  213.         printf("    --half-precision  - use half-precision\n");
  214.         printf("    --saturate-s MASK - bitmask of samplers to saturate S coord\n");
  215.         printf("    --saturate-t MASK - bitmask of samplers to saturate T coord\n");
  216.         printf("    --saturate-r MASK - bitmask of samplers to saturate R coord\n");
  217.         printf("    --nocp            - disable copy propagation\n");
  218.         printf("    --nir             - use NIR compiler\n");
  219.         printf("    --help            - show this message\n");
  220. }
  221.  
  222. int main(int argc, char **argv)
  223. {
  224.         int ret = 0, n = 1;
  225.         const char *filename;
  226.         struct tgsi_token toks[65536];
  227.         struct tgsi_parse_context parse;
  228.         struct ir3_shader_variant v;
  229.         struct ir3_shader_key key = {};
  230.         const char *info;
  231.         void *ptr;
  232.         size_t size;
  233.         int use_nir = 0;
  234.  
  235.         fd_mesa_debug |= FD_DBG_DISASM;
  236.  
  237.         /* cmdline args which impact shader variant get spit out in a
  238.          * comment on the first line..  a quick/dirty way to preserve
  239.          * that info so when ir3test recompiles the shader with a new
  240.          * compiler version, we use the same shader-key settings:
  241.          */
  242.         debug_printf("; options:");
  243.  
  244.         while (n < argc) {
  245.                 if (!strcmp(argv[n], "--verbose")) {
  246.                         fd_mesa_debug |=  FD_DBG_OPTDUMP | FD_DBG_MSGS | FD_DBG_OPTMSGS;
  247.                         n++;
  248.                         continue;
  249.                 }
  250.  
  251.                 if (!strcmp(argv[n], "--binning-pass")) {
  252.                         debug_printf(" %s", argv[n]);
  253.                         key.binning_pass = true;
  254.                         n++;
  255.                         continue;
  256.                 }
  257.  
  258.                 if (!strcmp(argv[n], "--color-two-side")) {
  259.                         debug_printf(" %s", argv[n]);
  260.                         key.color_two_side = true;
  261.                         n++;
  262.                         continue;
  263.                 }
  264.  
  265.                 if (!strcmp(argv[n], "--half-precision")) {
  266.                         debug_printf(" %s", argv[n]);
  267.                         key.half_precision = true;
  268.                         n++;
  269.                         continue;
  270.                 }
  271.  
  272.                 if (!strcmp(argv[n], "--saturate-s")) {
  273.                         debug_printf(" %s %s", argv[n], argv[n+1]);
  274.                         key.vsaturate_s = key.fsaturate_s = strtol(argv[n+1], NULL, 0);
  275.                         n += 2;
  276.                         continue;
  277.                 }
  278.  
  279.                 if (!strcmp(argv[n], "--saturate-t")) {
  280.                         debug_printf(" %s %s", argv[n], argv[n+1]);
  281.                         key.vsaturate_t = key.fsaturate_t = strtol(argv[n+1], NULL, 0);
  282.                         n += 2;
  283.                         continue;
  284.                 }
  285.  
  286.                 if (!strcmp(argv[n], "--saturate-r")) {
  287.                         debug_printf(" %s %s", argv[n], argv[n+1]);
  288.                         key.vsaturate_r = key.fsaturate_r = strtol(argv[n+1], NULL, 0);
  289.                         n += 2;
  290.                         continue;
  291.                 }
  292.  
  293.                 if (!strcmp(argv[n], "--nocp")) {
  294.                         fd_mesa_debug |= FD_DBG_NOCP;
  295.                         n++;
  296.                         continue;
  297.                 }
  298.                 if (!strcmp(argv[n], "--nir")) {
  299.                         use_nir = true;
  300.                         n++;
  301.                         continue;
  302.                 }
  303.  
  304.                 if (!strcmp(argv[n], "--help")) {
  305.                         print_usage();
  306.                         return 0;
  307.                 }
  308.  
  309.                 break;
  310.         }
  311.         debug_printf("\n");
  312.  
  313.         filename = argv[n];
  314.  
  315.         memset(&v, 0, sizeof(v));
  316.         v.key = key;
  317.  
  318.         ret = read_file(filename, &ptr, &size);
  319.         if (ret) {
  320.                 print_usage();
  321.                 return ret;
  322.         }
  323.  
  324.         if (fd_mesa_debug & FD_DBG_OPTMSGS)
  325.                 debug_printf("%s\n", (char *)ptr);
  326.  
  327.         if (!tgsi_text_translate(ptr, toks, Elements(toks)))
  328.                 errx(1, "could not parse `%s'", filename);
  329.  
  330.         tgsi_parse_init(&parse, toks);
  331.         switch (parse.FullHeader.Processor.Processor) {
  332.         case TGSI_PROCESSOR_FRAGMENT:
  333.                 v.type = SHADER_FRAGMENT;
  334.                 break;
  335.         case TGSI_PROCESSOR_VERTEX:
  336.                 v.type = SHADER_VERTEX;
  337.                 break;
  338.         case TGSI_PROCESSOR_COMPUTE:
  339.                 v.type = SHADER_COMPUTE;
  340.                 break;
  341.         }
  342.  
  343.         if (use_nir) {
  344.                 info = "NIR compiler";
  345.                 ret = ir3_compile_shader_nir(&v, toks, key);
  346.         } else {
  347.                 info = "TGSI compiler";
  348.                 ret = ir3_compile_shader(&v, toks, key, true);
  349.         }
  350.  
  351.         if (ret) {
  352.                 reset_variant(&v, "compiler failed, trying without copy propagation!");
  353.                 info = "compiler (no copy propagation)";
  354.                 ret = ir3_compile_shader(&v, toks, key, false);
  355.         }
  356.  
  357.         if (ret) {
  358.                 fprintf(stderr, "compiler failed!\n");
  359.                 return ret;
  360.         }
  361.         dump_info(&v, info);
  362. }
  363.  
  364. void _mesa_error_no_memory(const char *caller);
  365.  
  366. void
  367. _mesa_error_no_memory(const char *caller)
  368. {
  369.         fprintf(stderr, "Mesa error: out of memory in %s", caller);
  370. }
  371.