Home | History | Annotate | Download | only in tgsi
      1 /**************************************************************************
      2  *
      3  * Copyright 2007 VMware, Inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 #include "util/u_debug.h"
     29 #include "pipe/p_shader_tokens.h"
     30 #include "tgsi_info.h"
     31 #include "tgsi_parse.h"
     32 #include "tgsi_util.h"
     33 #include "tgsi_exec.h"
     34 #include "util/bitscan.h"
     35 
     36 union pointer_hack
     37 {
     38    void *pointer;
     39    uint64_t uint64;
     40 };
     41 
     42 void *
     43 tgsi_align_128bit(void *unaligned)
     44 {
     45    union pointer_hack ph;
     46 
     47    ph.uint64 = 0;
     48    ph.pointer = unaligned;
     49    ph.uint64 = (ph.uint64 + 15) & ~15;
     50    return ph.pointer;
     51 }
     52 
     53 unsigned
     54 tgsi_util_get_src_register_swizzle(const struct tgsi_src_register *reg,
     55                                    unsigned component)
     56 {
     57    switch (component) {
     58    case TGSI_CHAN_X:
     59       return reg->SwizzleX;
     60    case TGSI_CHAN_Y:
     61       return reg->SwizzleY;
     62    case TGSI_CHAN_Z:
     63       return reg->SwizzleZ;
     64    case TGSI_CHAN_W:
     65       return reg->SwizzleW;
     66    default:
     67       assert(0);
     68    }
     69    return 0;
     70 }
     71 
     72 
     73 unsigned
     74 tgsi_util_get_full_src_register_swizzle(
     75    const struct tgsi_full_src_register *reg,
     76    unsigned component)
     77 {
     78    return tgsi_util_get_src_register_swizzle(&reg->Register, component);
     79 }
     80 
     81 
     82 void
     83 tgsi_util_set_src_register_swizzle(struct tgsi_src_register *reg,
     84                                    unsigned swizzle,
     85                                    unsigned component)
     86 {
     87    switch (component) {
     88    case 0:
     89       reg->SwizzleX = swizzle;
     90       break;
     91    case 1:
     92       reg->SwizzleY = swizzle;
     93       break;
     94    case 2:
     95       reg->SwizzleZ = swizzle;
     96       break;
     97    case 3:
     98       reg->SwizzleW = swizzle;
     99       break;
    100    default:
    101       assert(0);
    102    }
    103 }
    104 
    105 
    106 unsigned
    107 tgsi_util_get_full_src_register_sign_mode(
    108    const struct tgsi_full_src_register *reg,
    109    unsigned component)
    110 {
    111    unsigned sign_mode;
    112 
    113    if (reg->Register.Absolute) {
    114       /* Consider only the post-abs negation. */
    115 
    116       if (reg->Register.Negate) {
    117          sign_mode = TGSI_UTIL_SIGN_SET;
    118       }
    119       else {
    120          sign_mode = TGSI_UTIL_SIGN_CLEAR;
    121       }
    122    }
    123    else {
    124       if (reg->Register.Negate) {
    125          sign_mode = TGSI_UTIL_SIGN_TOGGLE;
    126       }
    127       else {
    128          sign_mode = TGSI_UTIL_SIGN_KEEP;
    129       }
    130    }
    131 
    132    return sign_mode;
    133 }
    134 
    135 
    136 void
    137 tgsi_util_set_full_src_register_sign_mode(struct tgsi_full_src_register *reg,
    138                                           unsigned sign_mode)
    139 {
    140    switch (sign_mode) {
    141    case TGSI_UTIL_SIGN_CLEAR:
    142       reg->Register.Negate = 0;
    143       reg->Register.Absolute = 1;
    144       break;
    145 
    146    case TGSI_UTIL_SIGN_SET:
    147       reg->Register.Absolute = 1;
    148       reg->Register.Negate = 1;
    149       break;
    150 
    151    case TGSI_UTIL_SIGN_TOGGLE:
    152       reg->Register.Negate = 1;
    153       reg->Register.Absolute = 0;
    154       break;
    155 
    156    case TGSI_UTIL_SIGN_KEEP:
    157       reg->Register.Negate = 0;
    158       reg->Register.Absolute = 0;
    159       break;
    160 
    161    default:
    162       assert(0);
    163    }
    164 }
    165 
    166 
    167 /**
    168  * Determine which channels of the specificed src register are effectively
    169  * used by this instruction.
    170  */
    171 unsigned
    172 tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst,
    173                               unsigned src_idx)
    174 {
    175    const struct tgsi_full_src_register *src = &inst->Src[src_idx];
    176    unsigned write_mask = inst->Dst[0].Register.WriteMask;
    177    unsigned read_mask;
    178    unsigned usage_mask;
    179    unsigned chan;
    180 
    181    switch (inst->Instruction.Opcode) {
    182    case TGSI_OPCODE_IF:
    183    case TGSI_OPCODE_UIF:
    184    case TGSI_OPCODE_EMIT:
    185    case TGSI_OPCODE_ENDPRIM:
    186    case TGSI_OPCODE_RCP:
    187    case TGSI_OPCODE_RSQ:
    188    case TGSI_OPCODE_SQRT:
    189    case TGSI_OPCODE_EX2:
    190    case TGSI_OPCODE_LG2:
    191    case TGSI_OPCODE_SIN:
    192    case TGSI_OPCODE_COS:
    193    case TGSI_OPCODE_POW: /* reads src0.x and src1.x */
    194    case TGSI_OPCODE_UP2H:
    195    case TGSI_OPCODE_UP2US:
    196    case TGSI_OPCODE_UP4B:
    197    case TGSI_OPCODE_UP4UB:
    198    case TGSI_OPCODE_MEMBAR:
    199    case TGSI_OPCODE_BALLOT:
    200       read_mask = TGSI_WRITEMASK_X;
    201       break;
    202 
    203    case TGSI_OPCODE_DP2:
    204    case TGSI_OPCODE_PK2H:
    205    case TGSI_OPCODE_PK2US:
    206    case TGSI_OPCODE_DFRACEXP:
    207    case TGSI_OPCODE_F2D:
    208    case TGSI_OPCODE_I2D:
    209    case TGSI_OPCODE_U2D:
    210    case TGSI_OPCODE_F2U64:
    211    case TGSI_OPCODE_F2I64:
    212    case TGSI_OPCODE_U2I64:
    213    case TGSI_OPCODE_I2I64:
    214    case TGSI_OPCODE_TXQS: /* bindless handle possible */
    215    case TGSI_OPCODE_RESQ: /* bindless handle possible */
    216       read_mask = TGSI_WRITEMASK_XY;
    217       break;
    218 
    219    case TGSI_OPCODE_TXQ:
    220       if (src_idx == 0)
    221          read_mask = TGSI_WRITEMASK_X;
    222       else
    223          read_mask = TGSI_WRITEMASK_XY;  /* bindless handle possible */
    224       break;
    225 
    226    case TGSI_OPCODE_DP3:
    227       read_mask = TGSI_WRITEMASK_XYZ;
    228       break;
    229 
    230    case TGSI_OPCODE_DSEQ:
    231    case TGSI_OPCODE_DSNE:
    232    case TGSI_OPCODE_DSLT:
    233    case TGSI_OPCODE_DSGE:
    234    case TGSI_OPCODE_DP4:
    235    case TGSI_OPCODE_PK4B:
    236    case TGSI_OPCODE_PK4UB:
    237    case TGSI_OPCODE_D2F:
    238    case TGSI_OPCODE_D2I:
    239    case TGSI_OPCODE_D2U:
    240    case TGSI_OPCODE_I2F:
    241    case TGSI_OPCODE_U2F:
    242    case TGSI_OPCODE_U64SEQ:
    243    case TGSI_OPCODE_U64SNE:
    244    case TGSI_OPCODE_U64SLT:
    245    case TGSI_OPCODE_U64SGE:
    246    case TGSI_OPCODE_U642F:
    247    case TGSI_OPCODE_I64SLT:
    248    case TGSI_OPCODE_I64SGE:
    249    case TGSI_OPCODE_I642F:
    250       read_mask = TGSI_WRITEMASK_XYZW;
    251       break;
    252 
    253    case TGSI_OPCODE_LIT:
    254       read_mask = write_mask & TGSI_WRITEMASK_YZ ?
    255                      TGSI_WRITEMASK_XY | TGSI_WRITEMASK_W : 0;
    256       break;
    257 
    258    case TGSI_OPCODE_EXP:
    259    case TGSI_OPCODE_LOG:
    260       read_mask = write_mask & TGSI_WRITEMASK_XYZ ? TGSI_WRITEMASK_X : 0;
    261       break;
    262 
    263    case TGSI_OPCODE_DST:
    264       if (src_idx == 0)
    265          read_mask = TGSI_WRITEMASK_YZ;
    266       else
    267          read_mask = TGSI_WRITEMASK_YW;
    268       break;
    269 
    270    case TGSI_OPCODE_DLDEXP:
    271       if (src_idx == 0) {
    272          read_mask = write_mask;
    273       } else {
    274          read_mask =
    275             (write_mask & TGSI_WRITEMASK_XY ? TGSI_WRITEMASK_X : 0) |
    276             (write_mask & TGSI_WRITEMASK_ZW ? TGSI_WRITEMASK_Z : 0);
    277       }
    278       break;
    279 
    280    case TGSI_OPCODE_READ_INVOC:
    281       if (src_idx == 0)
    282          read_mask = write_mask;
    283       else
    284          read_mask = TGSI_WRITEMASK_X;
    285       break;
    286 
    287    case TGSI_OPCODE_FBFETCH:
    288       read_mask = 0; /* not a real register read */
    289       break;
    290 
    291    case TGSI_OPCODE_TEX:
    292    case TGSI_OPCODE_TEX_LZ:
    293    case TGSI_OPCODE_TXF_LZ:
    294    case TGSI_OPCODE_TXF:
    295    case TGSI_OPCODE_TXB:
    296    case TGSI_OPCODE_TXL:
    297    case TGSI_OPCODE_TXP:
    298    case TGSI_OPCODE_TXD:
    299    case TGSI_OPCODE_TEX2:
    300    case TGSI_OPCODE_TXB2:
    301    case TGSI_OPCODE_TXL2:
    302    case TGSI_OPCODE_LODQ:
    303    case TGSI_OPCODE_TG4: {
    304       unsigned dim_layer =
    305          tgsi_util_get_texture_coord_dim(inst->Texture.Texture);
    306       unsigned dim_layer_shadow, dim;
    307 
    308       /* Add shadow. */
    309       if (tgsi_is_shadow_target(inst->Texture.Texture)) {
    310          dim_layer_shadow = dim_layer + 1;
    311          if (inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D)
    312             dim_layer_shadow = 3;
    313       } else {
    314          dim_layer_shadow = dim_layer;
    315       }
    316 
    317       /* Remove layer. */
    318       if (tgsi_is_array_sampler(inst->Texture.Texture))
    319          dim = dim_layer - 1;
    320       else
    321          dim = dim_layer;
    322 
    323       read_mask = TGSI_WRITEMASK_XY; /* bindless handle in the last operand */
    324 
    325       switch (src_idx) {
    326       case 0:
    327          if (inst->Instruction.Opcode == TGSI_OPCODE_LODQ)
    328             read_mask = u_bit_consecutive(0, dim);
    329          else
    330             read_mask = u_bit_consecutive(0, dim_layer_shadow) & 0xf;
    331 
    332          if (inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D)
    333             read_mask &= ~TGSI_WRITEMASK_Y;
    334 
    335          if (inst->Instruction.Opcode == TGSI_OPCODE_TXF ||
    336              inst->Instruction.Opcode == TGSI_OPCODE_TXB ||
    337              inst->Instruction.Opcode == TGSI_OPCODE_TXL ||
    338              inst->Instruction.Opcode == TGSI_OPCODE_TXP)
    339             read_mask |= TGSI_WRITEMASK_W;
    340          break;
    341 
    342       case 1:
    343          if (inst->Instruction.Opcode == TGSI_OPCODE_TXD)
    344             read_mask = u_bit_consecutive(0, dim);
    345          else if (inst->Instruction.Opcode == TGSI_OPCODE_TEX2 ||
    346                   inst->Instruction.Opcode == TGSI_OPCODE_TXB2 ||
    347                   inst->Instruction.Opcode == TGSI_OPCODE_TXL2 ||
    348                   inst->Instruction.Opcode == TGSI_OPCODE_TG4)
    349             read_mask = TGSI_WRITEMASK_X;
    350          break;
    351 
    352       case 2:
    353          if (inst->Instruction.Opcode == TGSI_OPCODE_TXD)
    354             read_mask = u_bit_consecutive(0, dim);
    355          break;
    356       }
    357       break;
    358    }
    359 
    360    case TGSI_OPCODE_LOAD:
    361       if (src_idx == 0) {
    362          read_mask = TGSI_WRITEMASK_XY; /* bindless handle possible */
    363       } else {
    364          unsigned dim = tgsi_util_get_texture_coord_dim(inst->Memory.Texture);
    365          read_mask = u_bit_consecutive(0, dim);
    366       }
    367       break;
    368 
    369    case TGSI_OPCODE_STORE:
    370       if (src_idx == 0) {
    371          unsigned dim = tgsi_util_get_texture_coord_dim(inst->Memory.Texture);
    372          read_mask = u_bit_consecutive(0, dim);
    373       } else {
    374          read_mask = TGSI_WRITEMASK_XYZW;
    375       }
    376       break;
    377 
    378    case TGSI_OPCODE_ATOMUADD:
    379    case TGSI_OPCODE_ATOMXCHG:
    380    case TGSI_OPCODE_ATOMCAS:
    381    case TGSI_OPCODE_ATOMAND:
    382    case TGSI_OPCODE_ATOMOR:
    383    case TGSI_OPCODE_ATOMXOR:
    384    case TGSI_OPCODE_ATOMUMIN:
    385    case TGSI_OPCODE_ATOMUMAX:
    386    case TGSI_OPCODE_ATOMIMIN:
    387    case TGSI_OPCODE_ATOMIMAX:
    388       if (src_idx == 0) {
    389          read_mask = TGSI_WRITEMASK_XY; /* bindless handle possible */
    390       } else if (src_idx == 1) {
    391          unsigned dim = tgsi_util_get_texture_coord_dim(inst->Memory.Texture);
    392          read_mask = u_bit_consecutive(0, dim);
    393       } else {
    394          read_mask = TGSI_WRITEMASK_XYZW;
    395       }
    396       break;
    397 
    398    case TGSI_OPCODE_INTERP_CENTROID:
    399    case TGSI_OPCODE_INTERP_SAMPLE:
    400    case TGSI_OPCODE_INTERP_OFFSET:
    401       if (src_idx == 0)
    402          read_mask = write_mask;
    403       else if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_OFFSET)
    404          read_mask = TGSI_WRITEMASK_XY; /* offset */
    405       else
    406          read_mask = TGSI_WRITEMASK_X; /* sample */
    407       break;
    408 
    409    default:
    410       if (tgsi_get_opcode_info(inst->Instruction.Opcode)->output_mode ==
    411           TGSI_OUTPUT_COMPONENTWISE)
    412          read_mask = write_mask;
    413       else
    414          read_mask = TGSI_WRITEMASK_XYZW; /* assume all channels are read */
    415       break;
    416    }
    417 
    418    usage_mask = 0;
    419    for (chan = 0; chan < 4; ++chan) {
    420       if (read_mask & (1 << chan)) {
    421          usage_mask |= 1 << tgsi_util_get_full_src_register_swizzle(src, chan);
    422       }
    423    }
    424 
    425    return usage_mask;
    426 }
    427 
    428 /**
    429  * Convert a tgsi_ind_register into a tgsi_src_register
    430  */
    431 struct tgsi_src_register
    432 tgsi_util_get_src_from_ind(const struct tgsi_ind_register *reg)
    433 {
    434    struct tgsi_src_register src = { 0 };
    435 
    436    src.File = reg->File;
    437    src.Index = reg->Index;
    438    src.SwizzleX = reg->Swizzle;
    439    src.SwizzleY = reg->Swizzle;
    440    src.SwizzleZ = reg->Swizzle;
    441    src.SwizzleW = reg->Swizzle;
    442 
    443    return src;
    444 }
    445 
    446 /**
    447  * Return the dimension of the texture coordinates (layer included for array
    448  * textures), as well as the location of the shadow reference value or the
    449  * sample index.
    450  */
    451 int
    452 tgsi_util_get_texture_coord_dim(enum tgsi_texture_type tgsi_tex)
    453 {
    454    /*
    455     * Depending on the texture target, (src0.xyzw, src1.x) is interpreted
    456     * differently:
    457     *
    458     *   (s, X, X, X, X),               for BUFFER
    459     *   (s, X, X, X, X),               for 1D
    460     *   (s, t, X, X, X),               for 2D, RECT
    461     *   (s, t, r, X, X),               for 3D, CUBE
    462     *
    463     *   (s, layer, X, X, X),           for 1D_ARRAY
    464     *   (s, t, layer, X, X),           for 2D_ARRAY
    465     *   (s, t, r, layer, X),           for CUBE_ARRAY
    466     *
    467     *   (s, X, shadow, X, X),          for SHADOW1D
    468     *   (s, t, shadow, X, X),          for SHADOW2D, SHADOWRECT
    469     *   (s, t, r, shadow, X),          for SHADOWCUBE
    470     *
    471     *   (s, layer, shadow, X, X),      for SHADOW1D_ARRAY
    472     *   (s, t, layer, shadow, X),      for SHADOW2D_ARRAY
    473     *   (s, t, r, layer, shadow),      for SHADOWCUBE_ARRAY
    474     *
    475     *   (s, t, sample, X, X),          for 2D_MSAA
    476     *   (s, t, layer, sample, X),      for 2D_ARRAY_MSAA
    477     */
    478    switch (tgsi_tex) {
    479    case TGSI_TEXTURE_BUFFER:
    480    case TGSI_TEXTURE_1D:
    481    case TGSI_TEXTURE_SHADOW1D:
    482       return 1;
    483    case TGSI_TEXTURE_2D:
    484    case TGSI_TEXTURE_RECT:
    485    case TGSI_TEXTURE_1D_ARRAY:
    486    case TGSI_TEXTURE_SHADOW2D:
    487    case TGSI_TEXTURE_SHADOWRECT:
    488    case TGSI_TEXTURE_SHADOW1D_ARRAY:
    489    case TGSI_TEXTURE_2D_MSAA:
    490       return 2;
    491    case TGSI_TEXTURE_3D:
    492    case TGSI_TEXTURE_CUBE:
    493    case TGSI_TEXTURE_2D_ARRAY:
    494    case TGSI_TEXTURE_SHADOWCUBE:
    495    case TGSI_TEXTURE_SHADOW2D_ARRAY:
    496    case TGSI_TEXTURE_2D_ARRAY_MSAA:
    497       return 3;
    498    case TGSI_TEXTURE_CUBE_ARRAY:
    499    case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
    500       return 4;
    501    default:
    502       assert(!"unknown texture target");
    503       return 0;
    504    }
    505 }
    506 
    507 
    508 /**
    509  * Given a TGSI_TEXTURE_x target, return register component where the
    510  * shadow reference/distance coordinate is found.  Typically, components
    511  * 0 and 1 are the (s,t) texcoords and component 2 or 3 hold the shadow
    512  * reference value.  But if we return 4, it means the reference value is
    513  * found in the 0th component of the second coordinate argument to the
    514  * TEX2 instruction.
    515  */
    516 int
    517 tgsi_util_get_shadow_ref_src_index(enum tgsi_texture_type tgsi_tex)
    518 {
    519    switch (tgsi_tex) {
    520    case TGSI_TEXTURE_SHADOW1D:
    521    case TGSI_TEXTURE_SHADOW2D:
    522    case TGSI_TEXTURE_SHADOWRECT:
    523    case TGSI_TEXTURE_SHADOW1D_ARRAY:
    524       return 2;
    525    case TGSI_TEXTURE_SHADOWCUBE:
    526    case TGSI_TEXTURE_SHADOW2D_ARRAY:
    527    case TGSI_TEXTURE_2D_MSAA:
    528    case TGSI_TEXTURE_2D_ARRAY_MSAA:
    529       return 3;
    530    case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
    531       return 4;
    532    default:
    533       /* no shadow nor sample */
    534       return -1;
    535    }
    536 }
    537 
    538 
    539 boolean
    540 tgsi_is_shadow_target(enum tgsi_texture_type target)
    541 {
    542    switch (target) {
    543    case TGSI_TEXTURE_SHADOW1D:
    544    case TGSI_TEXTURE_SHADOW2D:
    545    case TGSI_TEXTURE_SHADOWRECT:
    546    case TGSI_TEXTURE_SHADOW1D_ARRAY:
    547    case TGSI_TEXTURE_SHADOW2D_ARRAY:
    548    case TGSI_TEXTURE_SHADOWCUBE:
    549    case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
    550       return TRUE;
    551    default:
    552       return FALSE;
    553    }
    554 }
    555