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_parse.h"
     31 #include "tgsi_util.h"
     32 #include "tgsi_exec.h"
     33 
     34 union pointer_hack
     35 {
     36    void *pointer;
     37    uint64_t uint64;
     38 };
     39 
     40 void *
     41 tgsi_align_128bit(
     42    void *unaligned )
     43 {
     44    union pointer_hack ph;
     45 
     46    ph.uint64 = 0;
     47    ph.pointer = unaligned;
     48    ph.uint64 = (ph.uint64 + 15) & ~15;
     49    return ph.pointer;
     50 }
     51 
     52 unsigned
     53 tgsi_util_get_src_register_swizzle(
     54    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(
     79       &reg->Register,
     80       component );
     81 }
     82 
     83 void
     84 tgsi_util_set_src_register_swizzle(
     85    struct tgsi_src_register *reg,
     86    unsigned swizzle,
     87    unsigned component )
     88 {
     89    switch( component ) {
     90    case 0:
     91       reg->SwizzleX = swizzle;
     92       break;
     93    case 1:
     94       reg->SwizzleY = swizzle;
     95       break;
     96    case 2:
     97       reg->SwizzleZ = swizzle;
     98       break;
     99    case 3:
    100       reg->SwizzleW = swizzle;
    101       break;
    102    default:
    103       assert( 0 );
    104    }
    105 }
    106 
    107 unsigned
    108 tgsi_util_get_full_src_register_sign_mode(
    109    const struct  tgsi_full_src_register *reg,
    110    unsigned component )
    111 {
    112    unsigned sign_mode;
    113 
    114    if( reg->Register.Absolute ) {
    115       /* Consider only the post-abs negation. */
    116 
    117       if( reg->Register.Negate ) {
    118          sign_mode = TGSI_UTIL_SIGN_SET;
    119       }
    120       else {
    121          sign_mode = TGSI_UTIL_SIGN_CLEAR;
    122       }
    123    }
    124    else {
    125       if( reg->Register.Negate ) {
    126          sign_mode = TGSI_UTIL_SIGN_TOGGLE;
    127       }
    128       else {
    129          sign_mode = TGSI_UTIL_SIGN_KEEP;
    130       }
    131    }
    132 
    133    return sign_mode;
    134 }
    135 
    136 void
    137 tgsi_util_set_full_src_register_sign_mode(
    138    struct tgsi_full_src_register *reg,
    139    unsigned sign_mode )
    140 {
    141    switch (sign_mode)
    142    {
    143    case TGSI_UTIL_SIGN_CLEAR:
    144       reg->Register.Negate = 0;
    145       reg->Register.Absolute = 1;
    146       break;
    147 
    148    case TGSI_UTIL_SIGN_SET:
    149       reg->Register.Absolute = 1;
    150       reg->Register.Negate = 1;
    151       break;
    152 
    153    case TGSI_UTIL_SIGN_TOGGLE:
    154       reg->Register.Negate = 1;
    155       reg->Register.Absolute = 0;
    156       break;
    157 
    158    case TGSI_UTIL_SIGN_KEEP:
    159       reg->Register.Negate = 0;
    160       reg->Register.Absolute = 0;
    161       break;
    162 
    163    default:
    164       assert( 0 );
    165    }
    166 }
    167 
    168 /**
    169  * Determine which channels of the specificed src register are effectively
    170  * used by this instruction.
    171  */
    172 unsigned
    173 tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst,
    174                               unsigned src_idx)
    175 {
    176    const struct tgsi_full_src_register *src = &inst->Src[src_idx];
    177    unsigned write_mask = inst->Dst[0].Register.WriteMask;
    178    unsigned read_mask;
    179    unsigned usage_mask;
    180    unsigned chan;
    181 
    182    switch (inst->Instruction.Opcode) {
    183    case TGSI_OPCODE_MOV:
    184    case TGSI_OPCODE_ARL:
    185    case TGSI_OPCODE_ARR:
    186    case TGSI_OPCODE_RCP:
    187    case TGSI_OPCODE_MUL:
    188    case TGSI_OPCODE_DIV:
    189    case TGSI_OPCODE_ADD:
    190    case TGSI_OPCODE_MIN:
    191    case TGSI_OPCODE_MAX:
    192    case TGSI_OPCODE_SLT:
    193    case TGSI_OPCODE_SGE:
    194    case TGSI_OPCODE_MAD:
    195    case TGSI_OPCODE_LRP:
    196    case TGSI_OPCODE_FMA:
    197    case TGSI_OPCODE_FRC:
    198    case TGSI_OPCODE_CEIL:
    199    case TGSI_OPCODE_CLAMP:
    200    case TGSI_OPCODE_FLR:
    201    case TGSI_OPCODE_ROUND:
    202    case TGSI_OPCODE_POW:
    203    case TGSI_OPCODE_COS:
    204    case TGSI_OPCODE_SIN:
    205    case TGSI_OPCODE_DDX:
    206    case TGSI_OPCODE_DDY:
    207    case TGSI_OPCODE_SEQ:
    208    case TGSI_OPCODE_SGT:
    209    case TGSI_OPCODE_SLE:
    210    case TGSI_OPCODE_SNE:
    211    case TGSI_OPCODE_SSG:
    212    case TGSI_OPCODE_CMP:
    213    case TGSI_OPCODE_TRUNC:
    214    case TGSI_OPCODE_NOT:
    215    case TGSI_OPCODE_AND:
    216    case TGSI_OPCODE_OR:
    217    case TGSI_OPCODE_XOR:
    218    case TGSI_OPCODE_SAD:
    219    case TGSI_OPCODE_FSEQ:
    220    case TGSI_OPCODE_FSGE:
    221    case TGSI_OPCODE_FSLT:
    222    case TGSI_OPCODE_FSNE:
    223    case TGSI_OPCODE_F2I:
    224    case TGSI_OPCODE_IDIV:
    225    case TGSI_OPCODE_IMAX:
    226    case TGSI_OPCODE_IMIN:
    227    case TGSI_OPCODE_INEG:
    228    case TGSI_OPCODE_ISGE:
    229    case TGSI_OPCODE_ISHR:
    230    case TGSI_OPCODE_ISLT:
    231    case TGSI_OPCODE_F2U:
    232    case TGSI_OPCODE_U2F:
    233    case TGSI_OPCODE_UADD:
    234    case TGSI_OPCODE_UDIV:
    235    case TGSI_OPCODE_UMAD:
    236    case TGSI_OPCODE_UMAX:
    237    case TGSI_OPCODE_UMIN:
    238    case TGSI_OPCODE_UMOD:
    239    case TGSI_OPCODE_UMUL:
    240    case TGSI_OPCODE_USEQ:
    241    case TGSI_OPCODE_USGE:
    242    case TGSI_OPCODE_USHR:
    243    case TGSI_OPCODE_USLT:
    244    case TGSI_OPCODE_USNE:
    245    case TGSI_OPCODE_IMUL_HI:
    246    case TGSI_OPCODE_UMUL_HI:
    247    case TGSI_OPCODE_DDX_FINE:
    248    case TGSI_OPCODE_DDY_FINE:
    249       /* Channel-wise operations */
    250       read_mask = write_mask;
    251       break;
    252 
    253    case TGSI_OPCODE_EX2:
    254    case TGSI_OPCODE_LG2:
    255       read_mask = TGSI_WRITEMASK_X;
    256       break;
    257 
    258    case TGSI_OPCODE_SCS:
    259       read_mask = write_mask & TGSI_WRITEMASK_XY ? TGSI_WRITEMASK_X : 0;
    260       break;
    261 
    262    case TGSI_OPCODE_EXP:
    263    case TGSI_OPCODE_LOG:
    264       read_mask = write_mask & TGSI_WRITEMASK_XYZ ? TGSI_WRITEMASK_X : 0;
    265       break;
    266 
    267    case TGSI_OPCODE_DP2A:
    268       read_mask = src_idx == 2 ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_XY;
    269       break;
    270 
    271    case TGSI_OPCODE_DP2:
    272       read_mask = TGSI_WRITEMASK_XY;
    273       break;
    274 
    275    case TGSI_OPCODE_DP3:
    276       read_mask = TGSI_WRITEMASK_XYZ;
    277       break;
    278 
    279    case TGSI_OPCODE_DP4:
    280       read_mask = TGSI_WRITEMASK_XYZW;
    281       break;
    282 
    283    case TGSI_OPCODE_DPH:
    284       read_mask = src_idx == 0 ? TGSI_WRITEMASK_XYZ : TGSI_WRITEMASK_XYZW;
    285       break;
    286 
    287    case TGSI_OPCODE_TEX:
    288    case TGSI_OPCODE_TXD:
    289    case TGSI_OPCODE_TXB:
    290    case TGSI_OPCODE_TXL:
    291    case TGSI_OPCODE_TXP:
    292       if (src_idx == 0) {
    293          /* Note that the SHADOW variants use the Z component too */
    294          switch (inst->Texture.Texture) {
    295          case TGSI_TEXTURE_1D:
    296             read_mask = TGSI_WRITEMASK_X;
    297             break;
    298          case TGSI_TEXTURE_SHADOW1D:
    299             read_mask = TGSI_WRITEMASK_XZ;
    300             break;
    301          case TGSI_TEXTURE_1D_ARRAY:
    302          case TGSI_TEXTURE_2D:
    303          case TGSI_TEXTURE_RECT:
    304             read_mask = TGSI_WRITEMASK_XY;
    305             break;
    306          case TGSI_TEXTURE_SHADOW1D_ARRAY:
    307          case TGSI_TEXTURE_SHADOW2D:
    308          case TGSI_TEXTURE_SHADOWRECT:
    309          case TGSI_TEXTURE_2D_ARRAY:
    310          case TGSI_TEXTURE_3D:
    311          case TGSI_TEXTURE_CUBE:
    312          case TGSI_TEXTURE_2D_MSAA:
    313             read_mask = TGSI_WRITEMASK_XYZ;
    314             break;
    315          case TGSI_TEXTURE_SHADOW2D_ARRAY:
    316          case TGSI_TEXTURE_CUBE_ARRAY:
    317          case TGSI_TEXTURE_SHADOWCUBE:
    318          case TGSI_TEXTURE_2D_ARRAY_MSAA:
    319          case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
    320             read_mask = TGSI_WRITEMASK_XYZW;
    321             break;
    322          default:
    323             assert(0);
    324             read_mask = 0;
    325          }
    326 
    327          if (inst->Instruction.Opcode != TGSI_OPCODE_TEX) {
    328             read_mask |= TGSI_WRITEMASK_W;
    329          }
    330       } else {
    331          /* A safe approximation */
    332          read_mask = TGSI_WRITEMASK_XYZW;
    333       }
    334       break;
    335 
    336    default:
    337       /* Assume all channels are read */
    338       read_mask = TGSI_WRITEMASK_XYZW;
    339       break;
    340    }
    341 
    342    usage_mask = 0;
    343    for (chan = 0; chan < 4; ++chan) {
    344       if (read_mask & (1 << chan)) {
    345          usage_mask |= 1 << tgsi_util_get_full_src_register_swizzle(src, chan);
    346       }
    347    }
    348 
    349    return usage_mask;
    350 }
    351 
    352 /**
    353  * Convert a tgsi_ind_register into a tgsi_src_register
    354  */
    355 struct tgsi_src_register
    356 tgsi_util_get_src_from_ind(const struct tgsi_ind_register *reg)
    357 {
    358    struct tgsi_src_register src = { 0 };
    359 
    360    src.File = reg->File;
    361    src.Index = reg->Index;
    362    src.SwizzleX = reg->Swizzle;
    363    src.SwizzleY = reg->Swizzle;
    364    src.SwizzleZ = reg->Swizzle;
    365    src.SwizzleW = reg->Swizzle;
    366 
    367    return src;
    368 }
    369 
    370 /**
    371  * Return the dimension of the texture coordinates (layer included for array
    372  * textures), as well as the location of the shadow reference value or the
    373  * sample index.
    374  */
    375 int
    376 tgsi_util_get_texture_coord_dim(unsigned tgsi_tex)
    377 {
    378    /*
    379     * Depending on the texture target, (src0.xyzw, src1.x) is interpreted
    380     * differently:
    381     *
    382     *   (s, X, X, X, X),               for BUFFER
    383     *   (s, X, X, X, X),               for 1D
    384     *   (s, t, X, X, X),               for 2D, RECT
    385     *   (s, t, r, X, X),               for 3D, CUBE
    386     *
    387     *   (s, layer, X, X, X),           for 1D_ARRAY
    388     *   (s, t, layer, X, X),           for 2D_ARRAY
    389     *   (s, t, r, layer, X),           for CUBE_ARRAY
    390     *
    391     *   (s, X, shadow, X, X),          for SHADOW1D
    392     *   (s, t, shadow, X, X),          for SHADOW2D, SHADOWRECT
    393     *   (s, t, r, shadow, X),          for SHADOWCUBE
    394     *
    395     *   (s, layer, shadow, X, X),      for SHADOW1D_ARRAY
    396     *   (s, t, layer, shadow, X),      for SHADOW2D_ARRAY
    397     *   (s, t, r, layer, shadow),      for SHADOWCUBE_ARRAY
    398     *
    399     *   (s, t, sample, X, X),          for 2D_MSAA
    400     *   (s, t, layer, sample, X),      for 2D_ARRAY_MSAA
    401     */
    402    switch (tgsi_tex) {
    403    case TGSI_TEXTURE_BUFFER:
    404    case TGSI_TEXTURE_1D:
    405    case TGSI_TEXTURE_SHADOW1D:
    406       return 1;
    407    case TGSI_TEXTURE_2D:
    408    case TGSI_TEXTURE_RECT:
    409    case TGSI_TEXTURE_1D_ARRAY:
    410    case TGSI_TEXTURE_SHADOW2D:
    411    case TGSI_TEXTURE_SHADOWRECT:
    412    case TGSI_TEXTURE_SHADOW1D_ARRAY:
    413    case TGSI_TEXTURE_2D_MSAA:
    414       return 2;
    415    case TGSI_TEXTURE_3D:
    416    case TGSI_TEXTURE_CUBE:
    417    case TGSI_TEXTURE_2D_ARRAY:
    418    case TGSI_TEXTURE_SHADOWCUBE:
    419    case TGSI_TEXTURE_SHADOW2D_ARRAY:
    420    case TGSI_TEXTURE_2D_ARRAY_MSAA:
    421       return 3;
    422    case TGSI_TEXTURE_CUBE_ARRAY:
    423    case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
    424       return 4;
    425    default:
    426       assert(!"unknown texture target");
    427       return 0;
    428    }
    429 }
    430 
    431 
    432 /**
    433  * Given a TGSI_TEXTURE_x target, return the src register index for the
    434  * shadow reference coordinate.
    435  */
    436 int
    437 tgsi_util_get_shadow_ref_src_index(unsigned tgsi_tex)
    438 {
    439    switch (tgsi_tex) {
    440    case TGSI_TEXTURE_SHADOW1D:
    441    case TGSI_TEXTURE_SHADOW2D:
    442    case TGSI_TEXTURE_SHADOWRECT:
    443    case TGSI_TEXTURE_SHADOW1D_ARRAY:
    444       return 2;
    445    case TGSI_TEXTURE_SHADOWCUBE:
    446    case TGSI_TEXTURE_SHADOW2D_ARRAY:
    447    case TGSI_TEXTURE_2D_MSAA:
    448    case TGSI_TEXTURE_2D_ARRAY_MSAA:
    449       return 3;
    450    case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
    451       return 4;
    452    default:
    453       /* no shadow nor sample */
    454       return -1;
    455    }
    456 }
    457 
    458 
    459 boolean
    460 tgsi_is_shadow_target(unsigned target)
    461 {
    462    switch (target) {
    463    case TGSI_TEXTURE_SHADOW1D:
    464    case TGSI_TEXTURE_SHADOW2D:
    465    case TGSI_TEXTURE_SHADOWRECT:
    466    case TGSI_TEXTURE_SHADOW1D_ARRAY:
    467    case TGSI_TEXTURE_SHADOW2D_ARRAY:
    468    case TGSI_TEXTURE_SHADOWCUBE:
    469    case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
    470       return TRUE;
    471    default:
    472       return FALSE;
    473    }
    474 }
    475