Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2011-2012 Advanced Micro Devices, Inc.
  4.  * Copyright 2010 VMware, Inc.
  5.  * Copyright 2009 VMware, Inc.
  6.  * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  7.  * All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the
  11.  * "Software"), to deal in the Software without restriction, including
  12.  * without limitation the rights to use, copy, modify, merge, publish,
  13.  * distribute, sub license, and/or sell copies of the Software, and to
  14.  * permit persons to whom the Software is furnished to do so, subject to
  15.  * the following conditions:
  16.  *
  17.  * The above copyright notice and this permission notice (including the
  18.  * next paragraph) shall be included in all copies or substantial portions
  19.  * of the Software.
  20.  *
  21.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  22.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  24.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  25.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  26.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  27.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28.  *
  29.  **************************************************************************/
  30.  
  31. #include "gallivm/lp_bld_tgsi.h"
  32.  
  33. #include "gallivm/lp_bld_arit.h"
  34. #include "gallivm/lp_bld_gather.h"
  35. #include "gallivm/lp_bld_init.h"
  36. #include "gallivm/lp_bld_intr.h"
  37. #include "tgsi/tgsi_info.h"
  38. #include "tgsi/tgsi_parse.h"
  39. #include "tgsi/tgsi_util.h"
  40. #include "util/u_memory.h"
  41.  
  42. /* The user is responsible for freeing list->instructions */
  43. unsigned lp_bld_tgsi_list_init(struct lp_build_tgsi_context * bld_base)
  44. {
  45.    bld_base->instructions = (struct tgsi_full_instruction *)
  46.          MALLOC( LP_MAX_INSTRUCTIONS * sizeof(struct tgsi_full_instruction) );
  47.    if (!bld_base->instructions) {
  48.       return 0;
  49.    }
  50.    bld_base->max_instructions = LP_MAX_INSTRUCTIONS;
  51.    return 1;
  52. }
  53.  
  54.  
  55. unsigned lp_bld_tgsi_add_instruction(
  56.    struct lp_build_tgsi_context * bld_base,
  57.    struct tgsi_full_instruction *inst_to_add)
  58. {
  59.  
  60.    if (bld_base->num_instructions == bld_base->max_instructions) {
  61.       struct tgsi_full_instruction *instructions;
  62.       instructions = REALLOC(bld_base->instructions, bld_base->max_instructions
  63.                                       * sizeof(struct tgsi_full_instruction),
  64.                                       (bld_base->max_instructions + LP_MAX_INSTRUCTIONS)
  65.                                       * sizeof(struct tgsi_full_instruction));
  66.       if (!instructions) {
  67.          return 0;
  68.       }
  69.       bld_base->instructions = instructions;
  70.       bld_base->max_instructions += LP_MAX_INSTRUCTIONS;
  71.    }
  72.    memcpy(bld_base->instructions + bld_base->num_instructions, inst_to_add,
  73.           sizeof(bld_base->instructions[0]));
  74.  
  75.    bld_base->num_instructions++;
  76.  
  77.    return 1;
  78. }
  79.  
  80.  
  81. /**
  82.  * This function assumes that all the args in emit_data have been set.
  83.  */
  84. static void
  85. lp_build_action_set_dst_type(
  86.    struct lp_build_emit_data * emit_data,
  87.    struct lp_build_tgsi_context *bld_base,
  88.    unsigned tgsi_opcode)
  89. {
  90.    if (emit_data->arg_count == 0) {
  91.       emit_data->dst_type = LLVMVoidTypeInContext(bld_base->base.gallivm->context);
  92.    } else {
  93.       /* XXX: Not all opcodes have the same src and dst types. */
  94.       emit_data->dst_type = LLVMTypeOf(emit_data->args[0]);
  95.    }
  96. }
  97.  
  98. void
  99. lp_build_tgsi_intrinsic(
  100.  const struct lp_build_tgsi_action * action,
  101.  struct lp_build_tgsi_context * bld_base,
  102.  struct lp_build_emit_data * emit_data)
  103. {
  104.    struct lp_build_context * base = &bld_base->base;
  105.    emit_data->output[emit_data->chan] = lp_build_intrinsic(
  106.                base->gallivm->builder, action->intr_name,
  107.                emit_data->dst_type, emit_data->args, emit_data->arg_count);
  108. }
  109.  
  110. LLVMValueRef
  111. lp_build_emit_llvm(
  112.    struct lp_build_tgsi_context *bld_base,
  113.    unsigned tgsi_opcode,
  114.    struct lp_build_emit_data * emit_data)
  115. {
  116.    struct lp_build_tgsi_action * action = &bld_base->op_actions[tgsi_opcode];
  117.    /* XXX: Assert that this is a componentwise or replicate instruction */
  118.  
  119.    lp_build_action_set_dst_type(emit_data, bld_base, tgsi_opcode);
  120.    emit_data->chan = 0;
  121.    assert(action->emit);
  122.    action->emit(action, bld_base, emit_data);
  123.    return emit_data->output[0];
  124. }
  125.  
  126. LLVMValueRef
  127. lp_build_emit_llvm_unary(
  128.    struct lp_build_tgsi_context *bld_base,
  129.    unsigned tgsi_opcode,
  130.    LLVMValueRef arg0)
  131. {
  132.    struct lp_build_emit_data emit_data;
  133.    emit_data.arg_count = 1;
  134.    emit_data.args[0] = arg0;
  135.    return lp_build_emit_llvm(bld_base, tgsi_opcode, &emit_data);
  136. }
  137.  
  138. LLVMValueRef
  139. lp_build_emit_llvm_binary(
  140.    struct lp_build_tgsi_context *bld_base,
  141.    unsigned tgsi_opcode,
  142.    LLVMValueRef arg0,
  143.    LLVMValueRef arg1)
  144. {
  145.    struct lp_build_emit_data emit_data;
  146.    emit_data.arg_count = 2;
  147.    emit_data.args[0] = arg0;
  148.    emit_data.args[1] = arg1;
  149.    return lp_build_emit_llvm(bld_base, tgsi_opcode, &emit_data);
  150. }
  151.  
  152. LLVMValueRef
  153. lp_build_emit_llvm_ternary(
  154.    struct lp_build_tgsi_context *bld_base,
  155.    unsigned tgsi_opcode,
  156.    LLVMValueRef arg0,
  157.    LLVMValueRef arg1,
  158.    LLVMValueRef arg2)
  159. {
  160.    struct lp_build_emit_data emit_data;
  161.    emit_data.arg_count = 3;
  162.    emit_data.args[0] = arg0;
  163.    emit_data.args[1] = arg1;
  164.    emit_data.args[2] = arg2;
  165.    return lp_build_emit_llvm(bld_base, tgsi_opcode, &emit_data);
  166. }
  167.  
  168. /**
  169.  * The default fetch implementation.
  170.  */
  171. void lp_build_fetch_args(
  172.    struct lp_build_tgsi_context * bld_base,
  173.    struct lp_build_emit_data * emit_data)
  174. {
  175.    unsigned src;
  176.    for (src = 0; src < emit_data->info->num_src; src++) {
  177.       emit_data->args[src] = lp_build_emit_fetch(bld_base, emit_data->inst, src,
  178.                                                emit_data->chan);
  179.    }
  180.    emit_data->arg_count = emit_data->info->num_src;
  181.    lp_build_action_set_dst_type(emit_data, bld_base,
  182.                 emit_data->inst->Instruction.Opcode);
  183. }
  184.  
  185. /* XXX: COMMENT
  186.  * It should be assumed that this function ignores writemasks
  187.  */
  188. boolean
  189. lp_build_tgsi_inst_llvm(
  190.    struct lp_build_tgsi_context * bld_base,
  191.    const struct tgsi_full_instruction * inst)
  192. {
  193.    unsigned tgsi_opcode = inst->Instruction.Opcode;
  194.    const struct tgsi_opcode_info * info = tgsi_get_opcode_info(tgsi_opcode);
  195.    const struct lp_build_tgsi_action * action =
  196.                                          &bld_base->op_actions[tgsi_opcode];
  197.    struct lp_build_emit_data emit_data;
  198.    unsigned chan_index;
  199.    LLVMValueRef val;
  200.  
  201.    bld_base->pc++;
  202.  
  203.    /* Ignore deprecated instructions */
  204.    switch (inst->Instruction.Opcode) {
  205.  
  206.    case TGSI_OPCODE_RCC:
  207.    case TGSI_OPCODE_UP2H:
  208.    case TGSI_OPCODE_UP2US:
  209.    case TGSI_OPCODE_UP4B:
  210.    case TGSI_OPCODE_UP4UB:
  211.    case TGSI_OPCODE_X2D:
  212.    case TGSI_OPCODE_ARA:
  213.    case TGSI_OPCODE_BRA:
  214.    case TGSI_OPCODE_PUSHA:
  215.    case TGSI_OPCODE_POPA:
  216.    case TGSI_OPCODE_SAD:
  217.       /* deprecated? */
  218.       assert(0);
  219.       return FALSE;
  220.       break;
  221.    }
  222.  
  223.    /* Check if the opcode has been implemented */
  224.    if (!action->emit) {
  225.       return FALSE;
  226.    }
  227.  
  228.    memset(&emit_data, 0, sizeof(emit_data));
  229.  
  230.    assert(info->num_dst <= 1);
  231.    if (info->num_dst) {
  232.       TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
  233.          emit_data.output[chan_index] = bld_base->base.undef;
  234.       }
  235.    }
  236.  
  237.    emit_data.inst = inst;
  238.    emit_data.info = info;
  239.  
  240.    /* Emit the instructions */
  241.    if (info->output_mode == TGSI_OUTPUT_COMPONENTWISE && bld_base->soa) {
  242.       TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) {
  243.          emit_data.chan = chan_index;
  244.          if (!action->fetch_args) {
  245.             lp_build_fetch_args(bld_base, &emit_data);
  246.          } else {
  247.              action->fetch_args(bld_base, &emit_data);
  248.          }
  249.          action->emit(action, bld_base, &emit_data);
  250.       }
  251.    } else {
  252.       emit_data.chan = LP_CHAN_ALL;
  253.       if (action->fetch_args) {
  254.          action->fetch_args(bld_base, &emit_data);
  255.       }
  256.       /* Make sure the output value is stored in emit_data.output[0], unless
  257.        * the opcode is channel dependent */
  258.       if (info->output_mode != TGSI_OUTPUT_CHAN_DEPENDENT) {
  259.          emit_data.chan = 0;
  260.       }
  261.       action->emit(action, bld_base, &emit_data);
  262.  
  263.       /* Replicate the output values */
  264.       if (info->output_mode == TGSI_OUTPUT_REPLICATE && bld_base->soa) {
  265.          val = emit_data.output[0];
  266.          memset(emit_data.output, 0, sizeof(emit_data.output));
  267.          TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) {
  268.             emit_data.output[chan_index] = val;
  269.          }
  270.       }
  271.    }
  272.  
  273.    if (info->num_dst > 0) {
  274.       bld_base->emit_store(bld_base, inst, info, emit_data.output);
  275.    }
  276.    return TRUE;
  277. }
  278.  
  279.  
  280. LLVMValueRef
  281. lp_build_emit_fetch(
  282.    struct lp_build_tgsi_context *bld_base,
  283.    const struct tgsi_full_instruction *inst,
  284.    unsigned src_op,
  285.    const unsigned chan_index)
  286. {
  287.    const struct tgsi_full_src_register *reg = &inst->Src[src_op];
  288.    unsigned swizzle;
  289.    LLVMValueRef res;
  290.    enum tgsi_opcode_type stype = tgsi_opcode_infer_src_type(inst->Instruction.Opcode);
  291.  
  292.    if (chan_index == LP_CHAN_ALL) {
  293.       swizzle = ~0;
  294.    } else {
  295.       swizzle = tgsi_util_get_full_src_register_swizzle(reg, chan_index);
  296.       if (swizzle > 3) {
  297.          assert(0 && "invalid swizzle in emit_fetch()");
  298.          return bld_base->base.undef;
  299.       }
  300.    }
  301.  
  302.    assert(reg->Register.Index <= bld_base->info->file_max[reg->Register.File]);
  303.  
  304.    if (bld_base->emit_fetch_funcs[reg->Register.File]) {
  305.       res = bld_base->emit_fetch_funcs[reg->Register.File](bld_base, reg, stype,
  306.                                                            swizzle);
  307.    } else {
  308.       assert(0 && "invalid src register in emit_fetch()");
  309.       return bld_base->base.undef;
  310.    }
  311.  
  312.    if (reg->Register.Absolute) {
  313.       switch (stype) {
  314.       case TGSI_TYPE_FLOAT:
  315.       case TGSI_TYPE_DOUBLE:
  316.       case TGSI_TYPE_UNTYPED:
  317.           /* modifiers on movs assume data is float */
  318.          res = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_ABS, res);
  319.          break;
  320.       case TGSI_TYPE_UNSIGNED:
  321.       case TGSI_TYPE_SIGNED:
  322.       case TGSI_TYPE_VOID:
  323.       default:
  324.          /* abs modifier is only legal on floating point types */
  325.          assert(0);
  326.          break;
  327.       }
  328.    }
  329.  
  330.    if (reg->Register.Negate) {
  331.       switch (stype) {
  332.       case TGSI_TYPE_FLOAT:
  333.       case TGSI_TYPE_UNTYPED:
  334.          /* modifiers on movs assume data is float */
  335.          res = lp_build_negate( &bld_base->base, res );
  336.          break;
  337.       case TGSI_TYPE_DOUBLE:
  338.          /* no double build context */
  339.          assert(0);
  340.          break;
  341.       case TGSI_TYPE_SIGNED:
  342.       case TGSI_TYPE_UNSIGNED:
  343.          res = lp_build_negate( &bld_base->int_bld, res );
  344.          break;
  345.       case TGSI_TYPE_VOID:
  346.       default:
  347.          assert(0);
  348.          break;
  349.       }
  350.    }
  351.  
  352.    /*
  353.     * Swizzle the argument
  354.     */
  355.  
  356.    if (swizzle == ~0) {
  357.       res = bld_base->emit_swizzle(bld_base, res,
  358.                      reg->Register.SwizzleX,
  359.                      reg->Register.SwizzleY,
  360.                      reg->Register.SwizzleZ,
  361.                      reg->Register.SwizzleW);
  362.    }
  363.  
  364.    return res;
  365.  
  366. }
  367.  
  368.  
  369. LLVMValueRef
  370. lp_build_emit_fetch_texoffset(
  371.    struct lp_build_tgsi_context *bld_base,
  372.    const struct tgsi_full_instruction *inst,
  373.    unsigned tex_off_op,
  374.    const unsigned chan_index)
  375. {
  376.    const struct tgsi_texture_offset *off = &inst->TexOffsets[tex_off_op];
  377.    struct tgsi_full_src_register reg;
  378.    unsigned swizzle;
  379.    LLVMValueRef res;
  380.    enum tgsi_opcode_type stype = TGSI_TYPE_SIGNED;
  381.  
  382.    /* convert offset "register" to ordinary register so can use normal emit funcs */
  383.    memset(&reg, 0, sizeof(reg));
  384.    reg.Register.File = off->File;
  385.    reg.Register.Index = off->Index;
  386.    reg.Register.SwizzleX = off->SwizzleX;
  387.    reg.Register.SwizzleY = off->SwizzleY;
  388.    reg.Register.SwizzleZ = off->SwizzleZ;
  389.  
  390.    if (chan_index == LP_CHAN_ALL) {
  391.       swizzle = ~0;
  392.    } else {
  393.       assert(chan_index < TGSI_SWIZZLE_W);
  394.       swizzle = tgsi_util_get_src_register_swizzle(&reg.Register, chan_index);
  395.    }
  396.  
  397.    assert(off->Index <= bld_base->info->file_max[off->File]);
  398.  
  399.    if (bld_base->emit_fetch_funcs[off->File]) {
  400.       res = bld_base->emit_fetch_funcs[off->File](bld_base, &reg, stype,
  401.                                                            swizzle);
  402.    } else {
  403.       assert(0 && "invalid src register in emit_fetch_texoffset()");
  404.       return bld_base->base.undef;
  405.    }
  406.  
  407.    /*
  408.     * Swizzle the argument
  409.     */
  410.  
  411.    if (swizzle == ~0) {
  412.       res = bld_base->emit_swizzle(bld_base, res,
  413.                                    off->SwizzleX,
  414.                                    off->SwizzleY,
  415.                                    off->SwizzleZ,
  416.                                    /* there's no 4th channel */
  417.                                    off->SwizzleX);
  418.    }
  419.  
  420.    return res;
  421.  
  422. }
  423.  
  424.  
  425. boolean
  426. lp_build_tgsi_llvm(
  427.    struct lp_build_tgsi_context * bld_base,
  428.    const struct tgsi_token *tokens)
  429. {
  430.    struct tgsi_parse_context parse;
  431.  
  432.    if (bld_base->emit_prologue) {
  433.       bld_base->emit_prologue(bld_base);
  434.    }
  435.  
  436.    if (!lp_bld_tgsi_list_init(bld_base)) {
  437.       return FALSE;
  438.    }
  439.  
  440.    tgsi_parse_init( &parse, tokens );
  441.  
  442.    while( !tgsi_parse_end_of_tokens( &parse ) ) {
  443.       tgsi_parse_token( &parse );
  444.  
  445.       switch( parse.FullToken.Token.Type ) {
  446.       case TGSI_TOKEN_TYPE_DECLARATION:
  447.          /* Inputs already interpolated */
  448.          bld_base->emit_declaration(bld_base, &parse.FullToken.FullDeclaration);
  449.          break;
  450.  
  451.       case TGSI_TOKEN_TYPE_INSTRUCTION:
  452.          lp_bld_tgsi_add_instruction(bld_base, &parse.FullToken.FullInstruction);
  453.          break;
  454.  
  455.       case TGSI_TOKEN_TYPE_IMMEDIATE:
  456.          bld_base->emit_immediate(bld_base, &parse.FullToken.FullImmediate);
  457.          break;
  458.  
  459.       case TGSI_TOKEN_TYPE_PROPERTY:
  460.          break;
  461.  
  462.       default:
  463.          assert( 0 );
  464.       }
  465.    }
  466.  
  467.    while (bld_base->pc != -1) {
  468.       struct tgsi_full_instruction *instr = bld_base->instructions +
  469.                                                         bld_base->pc;
  470.       const struct tgsi_opcode_info *opcode_info =
  471.          tgsi_get_opcode_info(instr->Instruction.Opcode);
  472.       if (!lp_build_tgsi_inst_llvm(bld_base, instr)) {
  473.          _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n",
  474.                        opcode_info->mnemonic);
  475.          return FALSE;
  476.       }
  477.    }
  478.  
  479.    tgsi_parse_free(&parse);
  480.  
  481.    FREE(bld_base->instructions);
  482.  
  483.    if (bld_base->emit_epilogue) {
  484.       bld_base->emit_epilogue(bld_base);
  485.    }
  486.  
  487.    return TRUE;
  488. }
  489.