Home | History | Annotate | Download | only in tgsi
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 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 #ifndef TGSI_TRANSFORM_H
     29 #define TGSI_TRANSFORM_H
     30 
     31 
     32 #include "pipe/p_shader_tokens.h"
     33 #include "tgsi/tgsi_parse.h"
     34 #include "tgsi/tgsi_build.h"
     35 
     36 
     37 
     38 /**
     39  * Subclass this to add caller-specific data
     40  */
     41 struct tgsi_transform_context
     42 {
     43 /**** PUBLIC ***/
     44 
     45    /**
     46     * User-defined callbacks invoked per instruction.
     47     */
     48    void (*transform_instruction)(struct tgsi_transform_context *ctx,
     49                                  struct tgsi_full_instruction *inst);
     50 
     51    void (*transform_declaration)(struct tgsi_transform_context *ctx,
     52                                  struct tgsi_full_declaration *decl);
     53 
     54    void (*transform_immediate)(struct tgsi_transform_context *ctx,
     55                                struct tgsi_full_immediate *imm);
     56    void (*transform_property)(struct tgsi_transform_context *ctx,
     57                               struct tgsi_full_property *prop);
     58 
     59    /**
     60     * Called after last declaration, before first instruction.  This is
     61     * where the user might insert new declarations and/or instructions.
     62     */
     63    void (*prolog)(struct tgsi_transform_context *ctx);
     64 
     65    /**
     66     * Called at end of input program to allow caller to append extra
     67     * instructions.  Return number of tokens emitted.
     68     */
     69    void (*epilog)(struct tgsi_transform_context *ctx);
     70 
     71 
     72 /*** PRIVATE ***/
     73 
     74    /**
     75     * These are setup by tgsi_transform_shader() and cannot be overridden.
     76     * Meant to be called from in the above user callback functions.
     77     */
     78    void (*emit_instruction)(struct tgsi_transform_context *ctx,
     79                             const struct tgsi_full_instruction *inst);
     80    void (*emit_declaration)(struct tgsi_transform_context *ctx,
     81                             const struct tgsi_full_declaration *decl);
     82    void (*emit_immediate)(struct tgsi_transform_context *ctx,
     83                           const struct tgsi_full_immediate *imm);
     84    void (*emit_property)(struct tgsi_transform_context *ctx,
     85                          const struct tgsi_full_property *prop);
     86 
     87    struct tgsi_header *header;
     88    uint max_tokens_out;
     89    struct tgsi_token *tokens_out;
     90    uint ti;
     91 };
     92 
     93 
     94 /**
     95  * Helper for emitting temporary register declarations.
     96  */
     97 static inline void
     98 tgsi_transform_temps_decl(struct tgsi_transform_context *ctx,
     99                           unsigned firstIdx, unsigned lastIdx)
    100 {
    101    struct tgsi_full_declaration decl;
    102 
    103    decl = tgsi_default_full_declaration();
    104    decl.Declaration.File = TGSI_FILE_TEMPORARY;
    105    decl.Range.First = firstIdx;
    106    decl.Range.Last = lastIdx;
    107    ctx->emit_declaration(ctx, &decl);
    108 }
    109 
    110 static inline void
    111 tgsi_transform_temp_decl(struct tgsi_transform_context *ctx,
    112                          unsigned index)
    113 {
    114    tgsi_transform_temps_decl(ctx, index, index);
    115 }
    116 
    117 static inline void
    118 tgsi_transform_const_decl(struct tgsi_transform_context *ctx,
    119                           unsigned firstIdx, unsigned lastIdx)
    120 {
    121    struct tgsi_full_declaration decl;
    122 
    123    decl = tgsi_default_full_declaration();
    124    decl.Declaration.File = TGSI_FILE_CONSTANT;
    125    decl.Range.First = firstIdx;
    126    decl.Range.Last = lastIdx;
    127    ctx->emit_declaration(ctx, &decl);
    128 }
    129 
    130 static inline void
    131 tgsi_transform_input_decl(struct tgsi_transform_context *ctx,
    132                           unsigned index,
    133                           unsigned sem_name, unsigned sem_index,
    134                           unsigned interp)
    135 {
    136    struct tgsi_full_declaration decl;
    137 
    138    decl = tgsi_default_full_declaration();
    139    decl.Declaration.File = TGSI_FILE_INPUT;
    140    decl.Declaration.Interpolate = 1;
    141    decl.Declaration.Semantic = 1;
    142    decl.Semantic.Name = sem_name;
    143    decl.Semantic.Index = sem_index;
    144    decl.Range.First =
    145    decl.Range.Last = index;
    146    decl.Interp.Interpolate = interp;
    147 
    148    ctx->emit_declaration(ctx, &decl);
    149 }
    150 
    151 static inline void
    152 tgsi_transform_output_decl(struct tgsi_transform_context *ctx,
    153                           unsigned index,
    154                           unsigned sem_name, unsigned sem_index,
    155                           unsigned interp)
    156 {
    157    struct tgsi_full_declaration decl;
    158 
    159    decl = tgsi_default_full_declaration();
    160    decl.Declaration.File = TGSI_FILE_OUTPUT;
    161    decl.Declaration.Interpolate = 1;
    162    decl.Declaration.Semantic = 1;
    163    decl.Semantic.Name = sem_name;
    164    decl.Semantic.Index = sem_index;
    165    decl.Range.First =
    166    decl.Range.Last = index;
    167    decl.Interp.Interpolate = interp;
    168 
    169    ctx->emit_declaration(ctx, &decl);
    170 }
    171 
    172 static inline void
    173 tgsi_transform_sampler_decl(struct tgsi_transform_context *ctx,
    174                             unsigned index)
    175 {
    176    struct tgsi_full_declaration decl;
    177 
    178    decl = tgsi_default_full_declaration();
    179    decl.Declaration.File = TGSI_FILE_SAMPLER;
    180    decl.Range.First =
    181    decl.Range.Last = index;
    182    ctx->emit_declaration(ctx, &decl);
    183 }
    184 
    185 static inline void
    186 tgsi_transform_sampler_view_decl(struct tgsi_transform_context *ctx,
    187                                  unsigned index,
    188                                  unsigned target,
    189                                  enum tgsi_return_type type)
    190 {
    191    struct tgsi_full_declaration decl;
    192 
    193    decl = tgsi_default_full_declaration();
    194    decl.Declaration.File = TGSI_FILE_SAMPLER_VIEW;
    195    decl.Declaration.UsageMask = TGSI_WRITEMASK_XYZW;
    196    decl.Range.First =
    197    decl.Range.Last = index;
    198    decl.SamplerView.Resource = target;
    199    decl.SamplerView.ReturnTypeX = type;
    200    decl.SamplerView.ReturnTypeY = type;
    201    decl.SamplerView.ReturnTypeZ = type;
    202    decl.SamplerView.ReturnTypeW = type;
    203 
    204    ctx->emit_declaration(ctx, &decl);
    205 }
    206 
    207 static inline void
    208 tgsi_transform_immediate_decl(struct tgsi_transform_context *ctx,
    209                               float x, float y, float z, float w)
    210 {
    211    struct tgsi_full_immediate immed;
    212    unsigned size = 4;
    213 
    214    immed = tgsi_default_full_immediate();
    215    immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
    216    immed.u[0].Float = x;
    217    immed.u[1].Float = y;
    218    immed.u[2].Float = z;
    219    immed.u[3].Float = w;
    220 
    221    ctx->emit_immediate(ctx, &immed);
    222 }
    223 
    224 static inline void
    225 tgsi_transform_dst_reg(struct tgsi_full_dst_register *reg,
    226                        unsigned file, unsigned index, unsigned writemask)
    227 {
    228    reg->Register.File = file;
    229    reg->Register.Index = index;
    230    reg->Register.WriteMask = writemask;
    231 }
    232 
    233 static inline void
    234 tgsi_transform_src_reg(struct tgsi_full_src_register *reg,
    235                        unsigned file, unsigned index,
    236                        unsigned swizzleX, unsigned swizzleY,
    237                        unsigned swizzleZ, unsigned swizzleW)
    238 {
    239    reg->Register.File = file;
    240    reg->Register.Index = index;
    241    reg->Register.SwizzleX = swizzleX;
    242    reg->Register.SwizzleY = swizzleY;
    243    reg->Register.SwizzleZ = swizzleZ;
    244    reg->Register.SwizzleW = swizzleW;
    245 }
    246 
    247 /**
    248  * Helper for emitting 1-operand instructions.
    249  */
    250 static inline void
    251 tgsi_transform_op1_inst(struct tgsi_transform_context *ctx,
    252                         unsigned opcode,
    253                         unsigned dst_file,
    254                         unsigned dst_index,
    255                         unsigned dst_writemask,
    256                         unsigned src0_file,
    257                         unsigned src0_index)
    258 {
    259    struct tgsi_full_instruction inst;
    260 
    261    inst = tgsi_default_full_instruction();
    262    inst.Instruction.Opcode = opcode;
    263    inst.Instruction.NumDstRegs = 1;
    264    inst.Dst[0].Register.File = dst_file,
    265    inst.Dst[0].Register.Index = dst_index;
    266    inst.Dst[0].Register.WriteMask = dst_writemask;
    267    inst.Instruction.NumSrcRegs = 1;
    268    inst.Src[0].Register.File = src0_file;
    269    inst.Src[0].Register.Index = src0_index;
    270 
    271    ctx->emit_instruction(ctx, &inst);
    272 }
    273 
    274 
    275 static inline void
    276 tgsi_transform_op2_inst(struct tgsi_transform_context *ctx,
    277                         unsigned opcode,
    278                         unsigned dst_file,
    279                         unsigned dst_index,
    280                         unsigned dst_writemask,
    281                         unsigned src0_file,
    282                         unsigned src0_index,
    283                         unsigned src1_file,
    284                         unsigned src1_index,
    285                         bool src1_negate)
    286 {
    287    struct tgsi_full_instruction inst;
    288 
    289    inst = tgsi_default_full_instruction();
    290    inst.Instruction.Opcode = opcode;
    291    inst.Instruction.NumDstRegs = 1;
    292    inst.Dst[0].Register.File = dst_file,
    293    inst.Dst[0].Register.Index = dst_index;
    294    inst.Dst[0].Register.WriteMask = dst_writemask;
    295    inst.Instruction.NumSrcRegs = 2;
    296    inst.Src[0].Register.File = src0_file;
    297    inst.Src[0].Register.Index = src0_index;
    298    inst.Src[1].Register.File = src1_file;
    299    inst.Src[1].Register.Index = src1_index;
    300    inst.Src[1].Register.Negate = src1_negate;
    301 
    302    ctx->emit_instruction(ctx, &inst);
    303 }
    304 
    305 
    306 static inline void
    307 tgsi_transform_op3_inst(struct tgsi_transform_context *ctx,
    308                         unsigned opcode,
    309                         unsigned dst_file,
    310                         unsigned dst_index,
    311                         unsigned dst_writemask,
    312                         unsigned src0_file,
    313                         unsigned src0_index,
    314                         unsigned src1_file,
    315                         unsigned src1_index,
    316                         unsigned src2_file,
    317                         unsigned src2_index)
    318 {
    319    struct tgsi_full_instruction inst;
    320 
    321    inst = tgsi_default_full_instruction();
    322    inst.Instruction.Opcode = opcode;
    323    inst.Instruction.NumDstRegs = 1;
    324    inst.Dst[0].Register.File = dst_file,
    325    inst.Dst[0].Register.Index = dst_index;
    326    inst.Dst[0].Register.WriteMask = dst_writemask;
    327    inst.Instruction.NumSrcRegs = 3;
    328    inst.Src[0].Register.File = src0_file;
    329    inst.Src[0].Register.Index = src0_index;
    330    inst.Src[1].Register.File = src1_file;
    331    inst.Src[1].Register.Index = src1_index;
    332    inst.Src[2].Register.File = src2_file;
    333    inst.Src[2].Register.Index = src2_index;
    334 
    335    ctx->emit_instruction(ctx, &inst);
    336 }
    337 
    338 
    339 
    340 static inline void
    341 tgsi_transform_op1_swz_inst(struct tgsi_transform_context *ctx,
    342                             unsigned opcode,
    343                             unsigned dst_file,
    344                             unsigned dst_index,
    345                             unsigned dst_writemask,
    346                             unsigned src0_file,
    347                             unsigned src0_index,
    348                             unsigned src0_swizzle)
    349 {
    350    struct tgsi_full_instruction inst;
    351 
    352    inst = tgsi_default_full_instruction();
    353    inst.Instruction.Opcode = opcode;
    354    inst.Instruction.NumDstRegs = 1;
    355    inst.Dst[0].Register.File = dst_file,
    356    inst.Dst[0].Register.Index = dst_index;
    357    inst.Dst[0].Register.WriteMask = dst_writemask;
    358    inst.Instruction.NumSrcRegs = 1;
    359    inst.Src[0].Register.File = src0_file;
    360    inst.Src[0].Register.Index = src0_index;
    361    switch (dst_writemask) {
    362    case TGSI_WRITEMASK_X:
    363       inst.Src[0].Register.SwizzleX = src0_swizzle;
    364       break;
    365    case TGSI_WRITEMASK_Y:
    366       inst.Src[0].Register.SwizzleY = src0_swizzle;
    367       break;
    368    case TGSI_WRITEMASK_Z:
    369       inst.Src[0].Register.SwizzleZ = src0_swizzle;
    370       break;
    371    case TGSI_WRITEMASK_W:
    372       inst.Src[0].Register.SwizzleW = src0_swizzle;
    373       break;
    374    default:
    375       ; /* nothing */
    376    }
    377 
    378    ctx->emit_instruction(ctx, &inst);
    379 }
    380 
    381 
    382 static inline void
    383 tgsi_transform_op2_swz_inst(struct tgsi_transform_context *ctx,
    384                             unsigned opcode,
    385                             unsigned dst_file,
    386                             unsigned dst_index,
    387                             unsigned dst_writemask,
    388                             unsigned src0_file,
    389                             unsigned src0_index,
    390                             unsigned src0_swizzle,
    391                             unsigned src1_file,
    392                             unsigned src1_index,
    393                             unsigned src1_swizzle,
    394                             bool src1_negate)
    395 {
    396    struct tgsi_full_instruction inst;
    397 
    398    inst = tgsi_default_full_instruction();
    399    inst.Instruction.Opcode = opcode;
    400    inst.Instruction.NumDstRegs = 1;
    401    inst.Dst[0].Register.File = dst_file,
    402    inst.Dst[0].Register.Index = dst_index;
    403    inst.Dst[0].Register.WriteMask = dst_writemask;
    404    inst.Instruction.NumSrcRegs = 2;
    405    inst.Src[0].Register.File = src0_file;
    406    inst.Src[0].Register.Index = src0_index;
    407    inst.Src[1].Register.File = src1_file;
    408    inst.Src[1].Register.Index = src1_index;
    409    inst.Src[1].Register.Negate = src1_negate;
    410    switch (dst_writemask) {
    411    case TGSI_WRITEMASK_X:
    412       inst.Src[0].Register.SwizzleX = src0_swizzle;
    413       inst.Src[1].Register.SwizzleX = src1_swizzle;
    414       break;
    415    case TGSI_WRITEMASK_Y:
    416       inst.Src[0].Register.SwizzleY = src0_swizzle;
    417       inst.Src[1].Register.SwizzleY = src1_swizzle;
    418       break;
    419    case TGSI_WRITEMASK_Z:
    420       inst.Src[0].Register.SwizzleZ = src0_swizzle;
    421       inst.Src[1].Register.SwizzleZ = src1_swizzle;
    422       break;
    423    case TGSI_WRITEMASK_W:
    424       inst.Src[0].Register.SwizzleW = src0_swizzle;
    425       inst.Src[1].Register.SwizzleW = src1_swizzle;
    426       break;
    427    default:
    428       ; /* nothing */
    429    }
    430 
    431    ctx->emit_instruction(ctx, &inst);
    432 }
    433 
    434 
    435 static inline void
    436 tgsi_transform_op3_swz_inst(struct tgsi_transform_context *ctx,
    437                             unsigned opcode,
    438                             unsigned dst_file,
    439                             unsigned dst_index,
    440                             unsigned dst_writemask,
    441                             unsigned src0_file,
    442                             unsigned src0_index,
    443                             unsigned src0_swizzle,
    444                             unsigned src0_negate,
    445                             unsigned src1_file,
    446                             unsigned src1_index,
    447                             unsigned src1_swizzle,
    448                             unsigned src2_file,
    449                             unsigned src2_index,
    450                             unsigned src2_swizzle)
    451 {
    452    struct tgsi_full_instruction inst;
    453 
    454    inst = tgsi_default_full_instruction();
    455    inst.Instruction.Opcode = opcode;
    456    inst.Instruction.NumDstRegs = 1;
    457    inst.Dst[0].Register.File = dst_file,
    458    inst.Dst[0].Register.Index = dst_index;
    459    inst.Dst[0].Register.WriteMask = dst_writemask;
    460    inst.Instruction.NumSrcRegs = 3;
    461    inst.Src[0].Register.File = src0_file;
    462    inst.Src[0].Register.Index = src0_index;
    463    inst.Src[0].Register.Negate = src0_negate;
    464    inst.Src[1].Register.File = src1_file;
    465    inst.Src[1].Register.Index = src1_index;
    466    inst.Src[2].Register.File = src2_file;
    467    inst.Src[2].Register.Index = src2_index;
    468    switch (dst_writemask) {
    469    case TGSI_WRITEMASK_X:
    470       inst.Src[0].Register.SwizzleX = src0_swizzle;
    471       inst.Src[1].Register.SwizzleX = src1_swizzle;
    472       inst.Src[2].Register.SwizzleX = src2_swizzle;
    473       break;
    474    case TGSI_WRITEMASK_Y:
    475       inst.Src[0].Register.SwizzleY = src0_swizzle;
    476       inst.Src[1].Register.SwizzleY = src1_swizzle;
    477       inst.Src[2].Register.SwizzleY = src2_swizzle;
    478       break;
    479    case TGSI_WRITEMASK_Z:
    480       inst.Src[0].Register.SwizzleZ = src0_swizzle;
    481       inst.Src[1].Register.SwizzleZ = src1_swizzle;
    482       inst.Src[2].Register.SwizzleZ = src2_swizzle;
    483       break;
    484    case TGSI_WRITEMASK_W:
    485       inst.Src[0].Register.SwizzleW = src0_swizzle;
    486       inst.Src[1].Register.SwizzleW = src1_swizzle;
    487       inst.Src[2].Register.SwizzleW = src2_swizzle;
    488       break;
    489    default:
    490       ; /* nothing */
    491    }
    492 
    493    ctx->emit_instruction(ctx, &inst);
    494 }
    495 
    496 
    497 static inline void
    498 tgsi_transform_kill_inst(struct tgsi_transform_context *ctx,
    499                          unsigned src_file,
    500                          unsigned src_index,
    501                          unsigned src_swizzle,
    502                          boolean negate)
    503 {
    504    struct tgsi_full_instruction inst;
    505 
    506    inst = tgsi_default_full_instruction();
    507    inst.Instruction.Opcode = TGSI_OPCODE_KILL_IF;
    508    inst.Instruction.NumDstRegs = 0;
    509    inst.Instruction.NumSrcRegs = 1;
    510    inst.Src[0].Register.File = src_file;
    511    inst.Src[0].Register.Index = src_index;
    512    inst.Src[0].Register.SwizzleX =
    513    inst.Src[0].Register.SwizzleY =
    514    inst.Src[0].Register.SwizzleZ =
    515    inst.Src[0].Register.SwizzleW = src_swizzle;
    516    inst.Src[0].Register.Negate = negate;
    517 
    518    ctx->emit_instruction(ctx, &inst);
    519 }
    520 
    521 
    522 static inline void
    523 tgsi_transform_tex_inst(struct tgsi_transform_context *ctx,
    524                         unsigned dst_file,
    525                         unsigned dst_index,
    526                         unsigned src_file,
    527                         unsigned src_index,
    528                         unsigned tex_target,
    529                         unsigned sampler_index)
    530 {
    531    struct tgsi_full_instruction inst;
    532 
    533    assert(tex_target < TGSI_TEXTURE_COUNT);
    534 
    535    inst = tgsi_default_full_instruction();
    536    inst.Instruction.Opcode = TGSI_OPCODE_TEX;
    537    inst.Instruction.NumDstRegs = 1;
    538    inst.Dst[0].Register.File = dst_file;
    539    inst.Dst[0].Register.Index = dst_index;
    540    inst.Instruction.NumSrcRegs = 2;
    541    inst.Instruction.Texture = TRUE;
    542    inst.Texture.Texture = tex_target;
    543    inst.Src[0].Register.File = src_file;
    544    inst.Src[0].Register.Index = src_index;
    545    inst.Src[1].Register.File = TGSI_FILE_SAMPLER;
    546    inst.Src[1].Register.Index = sampler_index;
    547 
    548    ctx->emit_instruction(ctx, &inst);
    549 }
    550 
    551 
    552 extern int
    553 tgsi_transform_shader(const struct tgsi_token *tokens_in,
    554                       struct tgsi_token *tokens_out,
    555                       uint max_tokens_out,
    556                       struct tgsi_transform_context *ctx);
    557 
    558 
    559 #endif /* TGSI_TRANSFORM_H */
    560