Home | History | Annotate | Download | only in r300
      1 /*
      2  * Copyright 2009 Nicolai Hhnle <nhaehnle (at) 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_KILP: 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_IFC: return RC_OPCODE_IFC; */
    139      /* case TGSI_OPCODE_BREAKC: return RC_OPCODE_BREAKC; */
    140         case TGSI_OPCODE_KIL: return RC_OPCODE_KIL;
    141     }
    142 
    143     fprintf(stderr, "r300: Unknown TGSI/RC opcode: %s\n", tgsi_get_opcode_name(opcode));
    144     return RC_OPCODE_ILLEGAL_OPCODE;
    145 }
    146 
    147 static unsigned translate_saturate(unsigned saturate)
    148 {
    149     switch(saturate) {
    150         default:
    151             fprintf(stderr, "Unknown saturate mode: %i\n", saturate);
    152             /* fall-through */
    153         case TGSI_SAT_NONE: return RC_SATURATE_NONE;
    154         case TGSI_SAT_ZERO_ONE: return RC_SATURATE_ZERO_ONE;
    155     }
    156 }
    157 
    158 static unsigned translate_register_file(unsigned file)
    159 {
    160     switch(file) {
    161         case TGSI_FILE_CONSTANT: return RC_FILE_CONSTANT;
    162         case TGSI_FILE_IMMEDIATE: return RC_FILE_CONSTANT;
    163         case TGSI_FILE_INPUT: return RC_FILE_INPUT;
    164         case TGSI_FILE_OUTPUT: return RC_FILE_OUTPUT;
    165         default:
    166             fprintf(stderr, "Unhandled register file: %i\n", file);
    167             /* fall-through */
    168         case TGSI_FILE_TEMPORARY: return RC_FILE_TEMPORARY;
    169         case TGSI_FILE_ADDRESS: return RC_FILE_ADDRESS;
    170     }
    171 }
    172 
    173 static int translate_register_index(
    174     struct tgsi_to_rc * ttr,
    175     unsigned file,
    176     int index)
    177 {
    178     if (file == TGSI_FILE_IMMEDIATE)
    179         return ttr->immediate_offset + index;
    180 
    181     return index;
    182 }
    183 
    184 static void transform_dstreg(
    185     struct tgsi_to_rc * ttr,
    186     struct rc_dst_register * dst,
    187     struct tgsi_full_dst_register * src)
    188 {
    189     dst->File = translate_register_file(src->Register.File);
    190     dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index);
    191     dst->WriteMask = src->Register.WriteMask;
    192 
    193     if (src->Register.Indirect) {
    194         ttr->error = TRUE;
    195         fprintf(stderr, "r300: Relative addressing of destination operands "
    196                 "is unsupported.\n");
    197     }
    198 }
    199 
    200 static void transform_srcreg(
    201     struct tgsi_to_rc * ttr,
    202     struct rc_src_register * dst,
    203     struct tgsi_full_src_register * src)
    204 {
    205     unsigned i, j;
    206 
    207     dst->File = translate_register_file(src->Register.File);
    208     dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index);
    209     dst->RelAddr = src->Register.Indirect;
    210     dst->Swizzle = tgsi_util_get_full_src_register_swizzle(src, 0);
    211     dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 1) << 3;
    212     dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 2) << 6;
    213     dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 3) << 9;
    214     dst->Abs = src->Register.Absolute;
    215     dst->Negate = src->Register.Negate ? RC_MASK_XYZW : 0;
    216 
    217     if (src->Register.File == TGSI_FILE_IMMEDIATE) {
    218         for (i = 0; i < ttr->imms_to_swizzle_count; i++) {
    219             if (ttr->imms_to_swizzle[i].index == src->Register.Index) {
    220                 dst->File = RC_FILE_TEMPORARY;
    221                 dst->Index = 0;
    222                 dst->Swizzle = 0;
    223                 for (j = 0; j < 4; j++) {
    224                     dst->Swizzle |= GET_SWZ(ttr->imms_to_swizzle[i].swizzle,
    225                         tgsi_util_get_full_src_register_swizzle(src, j)) << (j * 3);
    226                 }
    227                 break;
    228             }
    229         }
    230     }
    231 }
    232 
    233 static void transform_texture(struct rc_instruction * dst, struct tgsi_instruction_texture src,
    234                               uint32_t *shadowSamplers)
    235 {
    236     switch(src.Texture) {
    237         case TGSI_TEXTURE_1D:
    238             dst->U.I.TexSrcTarget = RC_TEXTURE_1D;
    239             break;
    240         case TGSI_TEXTURE_2D:
    241             dst->U.I.TexSrcTarget = RC_TEXTURE_2D;
    242             break;
    243         case TGSI_TEXTURE_3D:
    244             dst->U.I.TexSrcTarget = RC_TEXTURE_3D;
    245             break;
    246         case TGSI_TEXTURE_CUBE:
    247             dst->U.I.TexSrcTarget = RC_TEXTURE_CUBE;
    248             break;
    249         case TGSI_TEXTURE_RECT:
    250             dst->U.I.TexSrcTarget = RC_TEXTURE_RECT;
    251             break;
    252         case TGSI_TEXTURE_SHADOW1D:
    253             dst->U.I.TexSrcTarget = RC_TEXTURE_1D;
    254             dst->U.I.TexShadow = 1;
    255             *shadowSamplers |= 1 << dst->U.I.TexSrcUnit;
    256             break;
    257         case TGSI_TEXTURE_SHADOW2D:
    258             dst->U.I.TexSrcTarget = RC_TEXTURE_2D;
    259             dst->U.I.TexShadow = 1;
    260             *shadowSamplers |= 1 << dst->U.I.TexSrcUnit;
    261             break;
    262         case TGSI_TEXTURE_SHADOWRECT:
    263             dst->U.I.TexSrcTarget = RC_TEXTURE_RECT;
    264             dst->U.I.TexShadow = 1;
    265             *shadowSamplers |= 1 << dst->U.I.TexSrcUnit;
    266             break;
    267     }
    268     dst->U.I.TexSwizzle = RC_SWIZZLE_XYZW;
    269 }
    270 
    271 static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_instruction * src)
    272 {
    273     struct rc_instruction * dst;
    274     int i;
    275 
    276     dst = rc_insert_new_instruction(ttr->compiler, ttr->compiler->Program.Instructions.Prev);
    277     dst->U.I.Opcode = translate_opcode(src->Instruction.Opcode);
    278     dst->U.I.SaturateMode = translate_saturate(src->Instruction.Saturate);
    279 
    280     if (src->Instruction.NumDstRegs)
    281         transform_dstreg(ttr, &dst->U.I.DstReg, &src->Dst[0]);
    282 
    283     for(i = 0; i < src->Instruction.NumSrcRegs; ++i) {
    284         if (src->Src[i].Register.File == TGSI_FILE_SAMPLER)
    285             dst->U.I.TexSrcUnit = src->Src[i].Register.Index;
    286         else
    287             transform_srcreg(ttr, &dst->U.I.SrcReg[i], &src->Src[i]);
    288     }
    289 
    290     /* Texturing. */
    291     if (src->Instruction.Texture)
    292         transform_texture(dst, src->Texture,
    293                           &ttr->compiler->Program.ShadowSamplers);
    294 }
    295 
    296 static void handle_immediate(struct tgsi_to_rc * ttr,
    297                              struct tgsi_full_immediate * imm,
    298                              unsigned index)
    299 {
    300     struct rc_constant constant;
    301     unsigned swizzle = 0;
    302     boolean can_swizzle = TRUE;
    303     unsigned i;
    304 
    305     for (i = 0; i < 4; i++) {
    306         if (imm->u[i].Float == 0.0f) {
    307             swizzle |= RC_SWIZZLE_ZERO << (i * 3);
    308         } else if (imm->u[i].Float == 0.5f && ttr->use_half_swizzles) {
    309             swizzle |= RC_SWIZZLE_HALF << (i * 3);
    310         } else if (imm->u[i].Float == 1.0f) {
    311             swizzle |= RC_SWIZZLE_ONE << (i * 3);
    312         } else {
    313             can_swizzle = FALSE;
    314             break;
    315         }
    316     }
    317 
    318     if (can_swizzle) {
    319         ttr->imms_to_swizzle[ttr->imms_to_swizzle_count].index = index;
    320         ttr->imms_to_swizzle[ttr->imms_to_swizzle_count].swizzle = swizzle;
    321         ttr->imms_to_swizzle_count++;
    322     } else {
    323         constant.Type = RC_CONSTANT_IMMEDIATE;
    324         constant.Size = 4;
    325         for(i = 0; i < 4; ++i)
    326             constant.u.Immediate[i] = imm->u[i].Float;
    327         rc_constants_add(&ttr->compiler->Program.Constants, &constant);
    328     }
    329 }
    330 
    331 void r300_tgsi_to_rc(struct tgsi_to_rc * ttr,
    332                      const struct tgsi_token * tokens)
    333 {
    334     struct tgsi_full_instruction *inst;
    335     struct tgsi_parse_context parser;
    336     unsigned imm_index = 0;
    337     int i;
    338 
    339     ttr->error = FALSE;
    340 
    341     /* Allocate constants placeholders.
    342      *
    343      * Note: What if declared constants are not contiguous? */
    344     for(i = 0; i <= ttr->info->file_max[TGSI_FILE_CONSTANT]; ++i) {
    345         struct rc_constant constant;
    346         memset(&constant, 0, sizeof(constant));
    347         constant.Type = RC_CONSTANT_EXTERNAL;
    348         constant.Size = 4;
    349         constant.u.External = i;
    350         rc_constants_add(&ttr->compiler->Program.Constants, &constant);
    351     }
    352 
    353     ttr->immediate_offset = ttr->compiler->Program.Constants.Count;
    354 
    355     ttr->imms_to_swizzle = malloc(ttr->info->immediate_count * sizeof(struct swizzled_imms));
    356     ttr->imms_to_swizzle_count = 0;
    357 
    358     tgsi_parse_init(&parser, tokens);
    359 
    360     while (!tgsi_parse_end_of_tokens(&parser)) {
    361         tgsi_parse_token(&parser);
    362 
    363         switch (parser.FullToken.Token.Type) {
    364             case TGSI_TOKEN_TYPE_DECLARATION:
    365                 break;
    366             case TGSI_TOKEN_TYPE_IMMEDIATE:
    367                 handle_immediate(ttr, &parser.FullToken.FullImmediate, imm_index);
    368                 imm_index++;
    369                 break;
    370             case TGSI_TOKEN_TYPE_INSTRUCTION:
    371                 inst = &parser.FullToken.FullInstruction;
    372                 if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
    373                     break;
    374                 }
    375 
    376                 transform_instruction(ttr, inst);
    377                 break;
    378         }
    379     }
    380 
    381     tgsi_parse_free(&parser);
    382 
    383     free(ttr->imms_to_swizzle);
    384 
    385     rc_calculate_inputs_outputs(ttr->compiler);
    386 }
    387