Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
  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.  * on the rights to use, copy, modify, merge, publish, distribute, sub
  8.  * license, and/or sell copies of the Software, and to permit persons to whom
  9.  * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
  18.  * THE COPYRIGHT HOLDER(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  21.  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
  22.  
  23. #include "r300_tgsi_to_rc.h"
  24.  
  25. #include "compiler/radeon_compiler.h"
  26.  
  27. #include "tgsi/tgsi_info.h"
  28. #include "tgsi/tgsi_parse.h"
  29. #include "tgsi/tgsi_scan.h"
  30. #include "tgsi/tgsi_util.h"
  31.  
  32. static unsigned translate_opcode(unsigned opcode)
  33. {
  34.     switch(opcode) {
  35.         case TGSI_OPCODE_ARL: return RC_OPCODE_ARL;
  36.         case TGSI_OPCODE_MOV: return RC_OPCODE_MOV;
  37.         case TGSI_OPCODE_LIT: return RC_OPCODE_LIT;
  38.         case TGSI_OPCODE_RCP: return RC_OPCODE_RCP;
  39.         case TGSI_OPCODE_RSQ: return RC_OPCODE_RSQ;
  40.         case TGSI_OPCODE_EXP: return RC_OPCODE_EXP;
  41.         case TGSI_OPCODE_LOG: return RC_OPCODE_LOG;
  42.         case TGSI_OPCODE_MUL: return RC_OPCODE_MUL;
  43.         case TGSI_OPCODE_ADD: return RC_OPCODE_ADD;
  44.         case TGSI_OPCODE_DP3: return RC_OPCODE_DP3;
  45.         case TGSI_OPCODE_DP4: return RC_OPCODE_DP4;
  46.         case TGSI_OPCODE_DST: return RC_OPCODE_DST;
  47.         case TGSI_OPCODE_MIN: return RC_OPCODE_MIN;
  48.         case TGSI_OPCODE_MAX: return RC_OPCODE_MAX;
  49.         case TGSI_OPCODE_SLT: return RC_OPCODE_SLT;
  50.         case TGSI_OPCODE_SGE: return RC_OPCODE_SGE;
  51.         case TGSI_OPCODE_MAD: return RC_OPCODE_MAD;
  52.         case TGSI_OPCODE_SUB: return RC_OPCODE_SUB;
  53.         case TGSI_OPCODE_LRP: return RC_OPCODE_LRP;
  54.         case TGSI_OPCODE_CND: return RC_OPCODE_CND;
  55.      /* case TGSI_OPCODE_DP2A: return RC_OPCODE_DP2A; */
  56.                                         /* gap */
  57.         case TGSI_OPCODE_FRC: return RC_OPCODE_FRC;
  58.         case TGSI_OPCODE_CLAMP: return RC_OPCODE_CLAMP;
  59.         case TGSI_OPCODE_FLR: return RC_OPCODE_FLR;
  60.         case TGSI_OPCODE_ROUND: return RC_OPCODE_ROUND;
  61.         case TGSI_OPCODE_EX2: return RC_OPCODE_EX2;
  62.         case TGSI_OPCODE_LG2: return RC_OPCODE_LG2;
  63.         case TGSI_OPCODE_POW: return RC_OPCODE_POW;
  64.         case TGSI_OPCODE_XPD: return RC_OPCODE_XPD;
  65.                                         /* gap */
  66.         case TGSI_OPCODE_ABS: return RC_OPCODE_ABS;
  67.      /* case TGSI_OPCODE_RCC: return RC_OPCODE_RCC; */
  68.         case TGSI_OPCODE_DPH: return RC_OPCODE_DPH;
  69.         case TGSI_OPCODE_COS: return RC_OPCODE_COS;
  70.         case TGSI_OPCODE_DDX: return RC_OPCODE_DDX;
  71.         case TGSI_OPCODE_DDY: return RC_OPCODE_DDY;
  72.         case TGSI_OPCODE_KILL: return RC_OPCODE_KILP;
  73.      /* case TGSI_OPCODE_PK2H: return RC_OPCODE_PK2H; */
  74.      /* case TGSI_OPCODE_PK2US: return RC_OPCODE_PK2US; */
  75.      /* case TGSI_OPCODE_PK4B: return RC_OPCODE_PK4B; */
  76.      /* case TGSI_OPCODE_PK4UB: return RC_OPCODE_PK4UB; */
  77.      /* case TGSI_OPCODE_RFL: return RC_OPCODE_RFL; */
  78.         case TGSI_OPCODE_SEQ: return RC_OPCODE_SEQ;
  79.         case TGSI_OPCODE_SFL: return RC_OPCODE_SFL;
  80.         case TGSI_OPCODE_SGT: return RC_OPCODE_SGT;
  81.         case TGSI_OPCODE_SIN: return RC_OPCODE_SIN;
  82.         case TGSI_OPCODE_SLE: return RC_OPCODE_SLE;
  83.         case TGSI_OPCODE_SNE: return RC_OPCODE_SNE;
  84.      /* case TGSI_OPCODE_STR: return RC_OPCODE_STR; */
  85.         case TGSI_OPCODE_TEX: return RC_OPCODE_TEX;
  86.         case TGSI_OPCODE_TXD: return RC_OPCODE_TXD;
  87.         case TGSI_OPCODE_TXP: return RC_OPCODE_TXP;
  88.      /* case TGSI_OPCODE_UP2H: return RC_OPCODE_UP2H; */
  89.      /* case TGSI_OPCODE_UP2US: return RC_OPCODE_UP2US; */
  90.      /* case TGSI_OPCODE_UP4B: return RC_OPCODE_UP4B; */
  91.      /* case TGSI_OPCODE_UP4UB: return RC_OPCODE_UP4UB; */
  92.      /* case TGSI_OPCODE_X2D: return RC_OPCODE_X2D; */
  93.      /* case TGSI_OPCODE_ARA: return RC_OPCODE_ARA; */
  94.      /* case TGSI_OPCODE_ARR: return RC_OPCODE_ARR; */
  95.      /* case TGSI_OPCODE_BRA: return RC_OPCODE_BRA; */
  96.      /* case TGSI_OPCODE_CAL: return RC_OPCODE_CAL; */
  97.      /* case TGSI_OPCODE_RET: return RC_OPCODE_RET; */
  98.         case TGSI_OPCODE_SSG: return RC_OPCODE_SSG;
  99.         case TGSI_OPCODE_CMP: return RC_OPCODE_CMP;
  100.         case TGSI_OPCODE_SCS: return RC_OPCODE_SCS;
  101.         case TGSI_OPCODE_TXB: return RC_OPCODE_TXB;
  102.      /* case TGSI_OPCODE_NRM: return RC_OPCODE_NRM; */
  103.      /* case TGSI_OPCODE_DIV: return RC_OPCODE_DIV; */
  104.         case TGSI_OPCODE_DP2: return RC_OPCODE_DP2;
  105.         case TGSI_OPCODE_TXL: return RC_OPCODE_TXL;
  106.         case TGSI_OPCODE_BRK: return RC_OPCODE_BRK;
  107.         case TGSI_OPCODE_IF: return RC_OPCODE_IF;
  108.         case TGSI_OPCODE_BGNLOOP: return RC_OPCODE_BGNLOOP;
  109.         case TGSI_OPCODE_ELSE: return RC_OPCODE_ELSE;
  110.         case TGSI_OPCODE_ENDIF: return RC_OPCODE_ENDIF;
  111.         case TGSI_OPCODE_ENDLOOP: return RC_OPCODE_ENDLOOP;
  112.      /* case TGSI_OPCODE_PUSHA: return RC_OPCODE_PUSHA; */
  113.      /* case TGSI_OPCODE_POPA: return RC_OPCODE_POPA; */
  114.         case TGSI_OPCODE_CEIL: return RC_OPCODE_CEIL;
  115.      /* case TGSI_OPCODE_I2F: return RC_OPCODE_I2F; */
  116.      /* case TGSI_OPCODE_NOT: return RC_OPCODE_NOT; */
  117.         case TGSI_OPCODE_TRUNC: return RC_OPCODE_TRUNC;
  118.      /* case TGSI_OPCODE_SHL: return RC_OPCODE_SHL; */
  119.      /* case TGSI_OPCODE_ISHR: return RC_OPCODE_SHR; */
  120.      /* case TGSI_OPCODE_AND: return RC_OPCODE_AND; */
  121.      /* case TGSI_OPCODE_OR: return RC_OPCODE_OR; */
  122.      /* case TGSI_OPCODE_MOD: return RC_OPCODE_MOD; */
  123.      /* case TGSI_OPCODE_XOR: return RC_OPCODE_XOR; */
  124.      /* case TGSI_OPCODE_SAD: return RC_OPCODE_SAD; */
  125.      /* case TGSI_OPCODE_TXF: return RC_OPCODE_TXF; */
  126.      /* case TGSI_OPCODE_TXQ: return RC_OPCODE_TXQ; */
  127.         case TGSI_OPCODE_CONT: return RC_OPCODE_CONT;
  128.      /* case TGSI_OPCODE_EMIT: return RC_OPCODE_EMIT; */
  129.      /* case TGSI_OPCODE_ENDPRIM: return RC_OPCODE_ENDPRIM; */
  130.      /* case TGSI_OPCODE_BGNLOOP2: return RC_OPCODE_BGNLOOP2; */
  131.      /* case TGSI_OPCODE_BGNSUB: return RC_OPCODE_BGNSUB; */
  132.      /* case TGSI_OPCODE_ENDLOOP2: return RC_OPCODE_ENDLOOP2; */
  133.      /* case TGSI_OPCODE_ENDSUB: return RC_OPCODE_ENDSUB; */
  134.         case TGSI_OPCODE_NOP: return RC_OPCODE_NOP;
  135.                                         /* gap */
  136.      /* case TGSI_OPCODE_NRM4: return RC_OPCODE_NRM4; */
  137.      /* case TGSI_OPCODE_CALLNZ: return RC_OPCODE_CALLNZ; */
  138.      /* case TGSI_OPCODE_BREAKC: return RC_OPCODE_BREAKC; */
  139.         case TGSI_OPCODE_KILL_IF: return RC_OPCODE_KIL;
  140.     }
  141.  
  142.     fprintf(stderr, "r300: Unknown TGSI/RC opcode: %s\n", tgsi_get_opcode_name(opcode));
  143.     return RC_OPCODE_ILLEGAL_OPCODE;
  144. }
  145.  
  146. static unsigned translate_saturate(unsigned saturate)
  147. {
  148.     switch(saturate) {
  149.         default:
  150.             fprintf(stderr, "Unknown saturate mode: %i\n", saturate);
  151.             /* fall-through */
  152.         case TGSI_SAT_NONE: return RC_SATURATE_NONE;
  153.         case TGSI_SAT_ZERO_ONE: return RC_SATURATE_ZERO_ONE;
  154.     }
  155. }
  156.  
  157. static unsigned translate_register_file(unsigned file)
  158. {
  159.     switch(file) {
  160.         case TGSI_FILE_CONSTANT: return RC_FILE_CONSTANT;
  161.         case TGSI_FILE_IMMEDIATE: return RC_FILE_CONSTANT;
  162.         case TGSI_FILE_INPUT: return RC_FILE_INPUT;
  163.         case TGSI_FILE_OUTPUT: return RC_FILE_OUTPUT;
  164.         default:
  165.             fprintf(stderr, "Unhandled register file: %i\n", file);
  166.             /* fall-through */
  167.         case TGSI_FILE_TEMPORARY: return RC_FILE_TEMPORARY;
  168.         case TGSI_FILE_ADDRESS: return RC_FILE_ADDRESS;
  169.     }
  170. }
  171.  
  172. static int translate_register_index(
  173.     struct tgsi_to_rc * ttr,
  174.     unsigned file,
  175.     int index)
  176. {
  177.     if (file == TGSI_FILE_IMMEDIATE)
  178.         return ttr->immediate_offset + index;
  179.  
  180.     return index;
  181. }
  182.  
  183. static void transform_dstreg(
  184.     struct tgsi_to_rc * ttr,
  185.     struct rc_dst_register * dst,
  186.     struct tgsi_full_dst_register * src)
  187. {
  188.     dst->File = translate_register_file(src->Register.File);
  189.     dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index);
  190.     dst->WriteMask = src->Register.WriteMask;
  191.  
  192.     if (src->Register.Indirect) {
  193.         ttr->error = TRUE;
  194.         fprintf(stderr, "r300: Relative addressing of destination operands "
  195.                 "is unsupported.\n");
  196.     }
  197. }
  198.  
  199. static void transform_srcreg(
  200.     struct tgsi_to_rc * ttr,
  201.     struct rc_src_register * dst,
  202.     struct tgsi_full_src_register * src)
  203. {
  204.     unsigned i, j;
  205.  
  206.     dst->File = translate_register_file(src->Register.File);
  207.     dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index);
  208.     dst->RelAddr = src->Register.Indirect;
  209.     dst->Swizzle = tgsi_util_get_full_src_register_swizzle(src, 0);
  210.     dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 1) << 3;
  211.     dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 2) << 6;
  212.     dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 3) << 9;
  213.     dst->Abs = src->Register.Absolute;
  214.     dst->Negate = src->Register.Negate ? RC_MASK_XYZW : 0;
  215.  
  216.     if (src->Register.File == TGSI_FILE_IMMEDIATE) {
  217.         for (i = 0; i < ttr->imms_to_swizzle_count; i++) {
  218.             if (ttr->imms_to_swizzle[i].index == src->Register.Index) {
  219.                 dst->File = RC_FILE_TEMPORARY;
  220.                 dst->Index = 0;
  221.                 dst->Swizzle = 0;
  222.                 for (j = 0; j < 4; j++) {
  223.                     dst->Swizzle |= GET_SWZ(ttr->imms_to_swizzle[i].swizzle,
  224.                         tgsi_util_get_full_src_register_swizzle(src, j)) << (j * 3);
  225.                 }
  226.                 break;
  227.             }
  228.         }
  229.     }
  230. }
  231.  
  232. static void transform_texture(struct rc_instruction * dst, struct tgsi_instruction_texture src,
  233.                               uint32_t *shadowSamplers)
  234. {
  235.     switch(src.Texture) {
  236.         case TGSI_TEXTURE_1D:
  237.             dst->U.I.TexSrcTarget = RC_TEXTURE_1D;
  238.             break;
  239.         case TGSI_TEXTURE_2D:
  240.             dst->U.I.TexSrcTarget = RC_TEXTURE_2D;
  241.             break;
  242.         case TGSI_TEXTURE_3D:
  243.             dst->U.I.TexSrcTarget = RC_TEXTURE_3D;
  244.             break;
  245.         case TGSI_TEXTURE_CUBE:
  246.             dst->U.I.TexSrcTarget = RC_TEXTURE_CUBE;
  247.             break;
  248.         case TGSI_TEXTURE_RECT:
  249.             dst->U.I.TexSrcTarget = RC_TEXTURE_RECT;
  250.             break;
  251.         case TGSI_TEXTURE_SHADOW1D:
  252.             dst->U.I.TexSrcTarget = RC_TEXTURE_1D;
  253.             dst->U.I.TexShadow = 1;
  254.             *shadowSamplers |= 1 << dst->U.I.TexSrcUnit;
  255.             break;
  256.         case TGSI_TEXTURE_SHADOW2D:
  257.             dst->U.I.TexSrcTarget = RC_TEXTURE_2D;
  258.             dst->U.I.TexShadow = 1;
  259.             *shadowSamplers |= 1 << dst->U.I.TexSrcUnit;
  260.             break;
  261.         case TGSI_TEXTURE_SHADOWRECT:
  262.             dst->U.I.TexSrcTarget = RC_TEXTURE_RECT;
  263.             dst->U.I.TexShadow = 1;
  264.             *shadowSamplers |= 1 << dst->U.I.TexSrcUnit;
  265.             break;
  266.     }
  267.     dst->U.I.TexSwizzle = RC_SWIZZLE_XYZW;
  268. }
  269.  
  270. static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_instruction * src)
  271. {
  272.     struct rc_instruction * dst;
  273.     int i;
  274.  
  275.     dst = rc_insert_new_instruction(ttr->compiler, ttr->compiler->Program.Instructions.Prev);
  276.     dst->U.I.Opcode = translate_opcode(src->Instruction.Opcode);
  277.     dst->U.I.SaturateMode = translate_saturate(src->Instruction.Saturate);
  278.  
  279.     if (src->Instruction.NumDstRegs)
  280.         transform_dstreg(ttr, &dst->U.I.DstReg, &src->Dst[0]);
  281.  
  282.     for(i = 0; i < src->Instruction.NumSrcRegs; ++i) {
  283.         if (src->Src[i].Register.File == TGSI_FILE_SAMPLER)
  284.             dst->U.I.TexSrcUnit = src->Src[i].Register.Index;
  285.         else
  286.             transform_srcreg(ttr, &dst->U.I.SrcReg[i], &src->Src[i]);
  287.     }
  288.  
  289.     /* Texturing. */
  290.     if (src->Instruction.Texture)
  291.         transform_texture(dst, src->Texture,
  292.                           &ttr->compiler->Program.ShadowSamplers);
  293. }
  294.  
  295. static void handle_immediate(struct tgsi_to_rc * ttr,
  296.                              struct tgsi_full_immediate * imm,
  297.                              unsigned index)
  298. {
  299.     struct rc_constant constant;
  300.     unsigned swizzle = 0;
  301.     boolean can_swizzle = TRUE;
  302.     unsigned i;
  303.  
  304.     for (i = 0; i < 4; i++) {
  305.         if (imm->u[i].Float == 0.0f) {
  306.             swizzle |= RC_SWIZZLE_ZERO << (i * 3);
  307.         } else if (imm->u[i].Float == 0.5f && ttr->use_half_swizzles) {
  308.             swizzle |= RC_SWIZZLE_HALF << (i * 3);
  309.         } else if (imm->u[i].Float == 1.0f) {
  310.             swizzle |= RC_SWIZZLE_ONE << (i * 3);
  311.         } else {
  312.             can_swizzle = FALSE;
  313.             break;
  314.         }
  315.     }
  316.  
  317.     if (can_swizzle) {
  318.         ttr->imms_to_swizzle[ttr->imms_to_swizzle_count].index = index;
  319.         ttr->imms_to_swizzle[ttr->imms_to_swizzle_count].swizzle = swizzle;
  320.         ttr->imms_to_swizzle_count++;
  321.     } else {
  322.         constant.Type = RC_CONSTANT_IMMEDIATE;
  323.         constant.Size = 4;
  324.         for(i = 0; i < 4; ++i)
  325.             constant.u.Immediate[i] = imm->u[i].Float;
  326.         rc_constants_add(&ttr->compiler->Program.Constants, &constant);
  327.     }
  328. }
  329.  
  330. void r300_tgsi_to_rc(struct tgsi_to_rc * ttr,
  331.                      const struct tgsi_token * tokens)
  332. {
  333.     struct tgsi_full_instruction *inst;
  334.     struct tgsi_parse_context parser;
  335.     unsigned imm_index = 0;
  336.     int i;
  337.  
  338.     ttr->error = FALSE;
  339.  
  340.     /* Allocate constants placeholders.
  341.      *
  342.      * Note: What if declared constants are not contiguous? */
  343.     for(i = 0; i <= ttr->info->file_max[TGSI_FILE_CONSTANT]; ++i) {
  344.         struct rc_constant constant;
  345.         memset(&constant, 0, sizeof(constant));
  346.         constant.Type = RC_CONSTANT_EXTERNAL;
  347.         constant.Size = 4;
  348.         constant.u.External = i;
  349.         rc_constants_add(&ttr->compiler->Program.Constants, &constant);
  350.     }
  351.  
  352.     ttr->immediate_offset = ttr->compiler->Program.Constants.Count;
  353.  
  354.     ttr->imms_to_swizzle = malloc(ttr->info->immediate_count * sizeof(struct swizzled_imms));
  355.     ttr->imms_to_swizzle_count = 0;
  356.  
  357.     tgsi_parse_init(&parser, tokens);
  358.  
  359.     while (!tgsi_parse_end_of_tokens(&parser)) {
  360.         tgsi_parse_token(&parser);
  361.  
  362.         switch (parser.FullToken.Token.Type) {
  363.             case TGSI_TOKEN_TYPE_DECLARATION:
  364.                 break;
  365.             case TGSI_TOKEN_TYPE_IMMEDIATE:
  366.                 handle_immediate(ttr, &parser.FullToken.FullImmediate, imm_index);
  367.                 imm_index++;
  368.                 break;
  369.             case TGSI_TOKEN_TYPE_INSTRUCTION:
  370.                 inst = &parser.FullToken.FullInstruction;
  371.                 if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
  372.                     break;
  373.                 }
  374.  
  375.                 transform_instruction(ttr, inst);
  376.                 break;
  377.         }
  378.     }
  379.  
  380.     tgsi_parse_free(&parser);
  381.  
  382.     free(ttr->imms_to_swizzle);
  383.  
  384.     rc_calculate_inputs_outputs(ttr->compiler);
  385. }
  386.