Example #1
0
/**
 * This just eliminates instructions with null dst so far.
 */
static void
eliminate_dead_code(struct toy_compiler *tc)
{
   struct toy_inst *inst;

   tc_head(tc);
   while ((inst = tc_next(tc)) != NULL) {
      switch (inst->opcode) {
      case GEN6_OPCODE_IF:
      case GEN6_OPCODE_ELSE:
      case GEN6_OPCODE_ENDIF:
      case GEN6_OPCODE_WHILE:
      case GEN6_OPCODE_BREAK:
      case GEN6_OPCODE_CONT:
      case GEN6_OPCODE_SEND:
      case GEN6_OPCODE_SENDC:
      case GEN6_OPCODE_NOP:
         /* never eliminated */
         break;
      default:
         if (tdst_is_null(inst->dst) || !inst->dst.writemask) {
            /* math is always GEN6_COND_NORMAL */
            if ((inst->opcode == GEN6_OPCODE_MATH ||
                 inst->cond_modifier == GEN6_COND_NORMAL) &&
                !inst->acc_wr_ctrl)
               tc_discard_inst(tc, inst);
         }
         break;
      }
   }
}
Example #2
0
/**
 * Compile the shader.
 */
static bool
gs_compile(struct gs_compile_context *gcc)
{
   struct toy_compiler *tc = &gcc->tc;
   struct ilo_shader *sh = gcc->shader;

   get_num_prims_static(gcc);

   if (gcc->is_static) {
      tc_head(tc);

      gs_init_vars(gcc);
      gs_ff_sync(gcc, tdst_d(gcc->vars.tmp), tsrc_imm_d(gcc->static_data.total_prims));
      gs_COPY1(tc, gcc->vars.urb_write_header, 0, tsrc_from(tdst_d(gcc->vars.tmp)), 0);
      if (gcc->write_so)
         gs_COPY4(tc, gcc->vars.so_index, 0, tsrc_from(tdst_d(gcc->vars.tmp)), 1);

      tc_tail(tc);
   }
   else {
      tc_fail(tc, "no control flow support");
      return false;
   }

   if (!gcc->write_vue)
      gs_discard(gcc);

   gs_lower_virtual_opcodes(gcc);
   toy_compiler_legalize_for_ra(tc);
   toy_compiler_optimize(tc);
   toy_compiler_allocate_registers(tc,
         gcc->first_free_grf,
         gcc->last_free_grf,
         1);
   toy_compiler_legalize_for_asm(tc);

   if (tc->fail) {
      ilo_err("failed to legalize GS instructions: %s\n", tc->reason);
      return false;
   }

   if (ilo_debug & ILO_DEBUG_GS) {
      ilo_printf("legalized instructions:\n");
      toy_compiler_dump(tc);
      ilo_printf("\n");
   }

   sh->kernel = toy_compiler_assemble(tc, &sh->kernel_size);
   if (!sh->kernel)
      return false;

   if (ilo_debug & ILO_DEBUG_GS) {
      ilo_printf("disassembly:\n");
      toy_compiler_disassemble(tc->dev, sh->kernel, sh->kernel_size, false);
      ilo_printf("\n");
   }

   return true;
}
Example #3
0
/**
 * Get the number of (tessellated) primitives generated by this shader.
 * Return false if that is unknown until runtime.
 */
static void
get_num_prims_static(struct gs_compile_context *gcc)
{
   struct toy_compiler *tc = &gcc->tc;
   const struct toy_inst *inst;
   int num_vertices_in_prim = 0, if_depth = 0, do_depth = 0;
   bool is_static = true;

   tc_head(tc);
   while ((inst = tc_next_no_skip(tc)) != NULL) {
      switch (inst->opcode) {
      case GEN6_OPCODE_IF:
         if_depth++;
         break;
      case GEN6_OPCODE_ENDIF:
         if_depth--;
         break;
      case TOY_OPCODE_DO:
         do_depth++;
         break;
      case GEN6_OPCODE_WHILE:
         do_depth--;
         break;
      case TOY_OPCODE_EMIT:
         if (if_depth || do_depth) {
            is_static = false;
         }
         else {
            gcc->static_data.total_vertices++;

            num_vertices_in_prim++;
            if (num_vertices_in_prim >= gcc->out_vue_min_count)
               gcc->static_data.total_prims++;
         }
         break;
      case TOY_OPCODE_ENDPRIM:
         if (if_depth || do_depth) {
            is_static = false;
         }
         else {
            const int vertidx = gcc->static_data.total_vertices - 1;
            const int idx = vertidx / 32;
            const int subidx = vertidx % 32;

            gcc->static_data.last_vertex[idx] |= 1 << subidx;
            num_vertices_in_prim = 0;
         }
         break;
      default:
         break;
      }

      if (!is_static)
         break;
   }

   gcc->is_static = is_static;
}
Example #4
0
/**
 * Dump the instructions added to the compiler.
 */
void
toy_compiler_dump(struct toy_compiler *tc)
{
   struct toy_inst *inst;
   int pc;

   pc = 0;
   tc_head(tc);
   while ((inst = tc_next_no_skip(tc)) != NULL) {
      /* we do not generate code for markers */
      if (inst->marker)
         ilo_printf("marker:");
      else
         ilo_printf("%6d:", pc++);

      tc_dump_inst(tc, inst);
   }
}
Example #5
0
static void
gs_lower_virtual_opcodes(struct gs_compile_context *gcc)
{
   struct toy_compiler *tc = &gcc->tc;
   struct toy_inst *inst;

   tc_head(tc);
   while ((inst = tc_next(tc)) != NULL) {
      switch (inst->opcode) {
      case TOY_OPCODE_TGSI_IN:
      case TOY_OPCODE_TGSI_CONST:
      case TOY_OPCODE_TGSI_SV:
      case TOY_OPCODE_TGSI_IMM:
         gs_lower_opcode_tgsi_direct(gcc, inst);
         break;
      case TOY_OPCODE_TGSI_INDIRECT_FETCH:
      case TOY_OPCODE_TGSI_INDIRECT_STORE:
         /* TODO similar to VS */
         tc_fail(tc, "no indirection support");
         tc_discard_inst(tc, inst);
         break;
      case TOY_OPCODE_TGSI_TEX:
      case TOY_OPCODE_TGSI_TXB:
      case TOY_OPCODE_TGSI_TXD:
      case TOY_OPCODE_TGSI_TXL:
      case TOY_OPCODE_TGSI_TXP:
      case TOY_OPCODE_TGSI_TXF:
      case TOY_OPCODE_TGSI_TXQ:
      case TOY_OPCODE_TGSI_TXQ_LZ:
      case TOY_OPCODE_TGSI_TEX2:
      case TOY_OPCODE_TGSI_TXB2:
      case TOY_OPCODE_TGSI_TXL2:
      case TOY_OPCODE_TGSI_SAMPLE:
      case TOY_OPCODE_TGSI_SAMPLE_I:
      case TOY_OPCODE_TGSI_SAMPLE_I_MS:
      case TOY_OPCODE_TGSI_SAMPLE_B:
      case TOY_OPCODE_TGSI_SAMPLE_C:
      case TOY_OPCODE_TGSI_SAMPLE_C_LZ:
      case TOY_OPCODE_TGSI_SAMPLE_D:
      case TOY_OPCODE_TGSI_SAMPLE_L:
      case TOY_OPCODE_TGSI_GATHER4:
      case TOY_OPCODE_TGSI_SVIEWINFO:
      case TOY_OPCODE_TGSI_SAMPLE_POS:
      case TOY_OPCODE_TGSI_SAMPLE_INFO:
         /* TODO similar to VS */
         tc_fail(tc, "no sampling support");
         tc_discard_inst(tc, inst);
         break;
      case TOY_OPCODE_EMIT:
         gs_lower_opcode_emit(gcc, inst);
         tc_discard_inst(tc, inst);
         break;
      case TOY_OPCODE_ENDPRIM:
         gs_lower_opcode_endprim(gcc, inst);
         tc_discard_inst(tc, inst);
         break;
      default:
         break;
      }
   }

   tc_head(tc);
   while ((inst = tc_next(tc)) != NULL) {
      switch (inst->opcode) {
      case TOY_OPCODE_INV:
      case TOY_OPCODE_LOG:
      case TOY_OPCODE_EXP:
      case TOY_OPCODE_SQRT:
      case TOY_OPCODE_RSQ:
      case TOY_OPCODE_SIN:
      case TOY_OPCODE_COS:
      case TOY_OPCODE_FDIV:
      case TOY_OPCODE_POW:
      case TOY_OPCODE_INT_DIV_QUOTIENT:
      case TOY_OPCODE_INT_DIV_REMAINDER:
         toy_compiler_lower_math(tc, inst);
         break;
      case TOY_OPCODE_URB_WRITE:
         toy_compiler_lower_to_send(tc, inst, false, GEN6_SFID_URB);
         break;
      default:
         if (inst->opcode > 127)
            tc_fail(tc, "unhandled virtual opcode");
         break;
      }
   }
}
static void
vs_lower_virtual_opcodes(struct vs_compile_context *vcc)
{
   struct toy_compiler *tc = &vcc->tc;
   struct toy_inst *inst;

   tc_head(tc);
   while ((inst = tc_next(tc)) != NULL) {
      switch (inst->opcode) {
      case TOY_OPCODE_TGSI_IN:
      case TOY_OPCODE_TGSI_CONST:
      case TOY_OPCODE_TGSI_SV:
      case TOY_OPCODE_TGSI_IMM:
         vs_lower_opcode_tgsi_direct(vcc, inst);
         break;
      case TOY_OPCODE_TGSI_INDIRECT_FETCH:
      case TOY_OPCODE_TGSI_INDIRECT_STORE:
         vs_lower_opcode_tgsi_indirect(vcc, inst);
         break;
      case TOY_OPCODE_TGSI_TEX:
      case TOY_OPCODE_TGSI_TXB:
      case TOY_OPCODE_TGSI_TXD:
      case TOY_OPCODE_TGSI_TXL:
      case TOY_OPCODE_TGSI_TXP:
      case TOY_OPCODE_TGSI_TXF:
      case TOY_OPCODE_TGSI_TXQ:
      case TOY_OPCODE_TGSI_TXQ_LZ:
      case TOY_OPCODE_TGSI_TEX2:
      case TOY_OPCODE_TGSI_TXB2:
      case TOY_OPCODE_TGSI_TXL2:
      case TOY_OPCODE_TGSI_SAMPLE:
      case TOY_OPCODE_TGSI_SAMPLE_I:
      case TOY_OPCODE_TGSI_SAMPLE_I_MS:
      case TOY_OPCODE_TGSI_SAMPLE_B:
      case TOY_OPCODE_TGSI_SAMPLE_C:
      case TOY_OPCODE_TGSI_SAMPLE_C_LZ:
      case TOY_OPCODE_TGSI_SAMPLE_D:
      case TOY_OPCODE_TGSI_SAMPLE_L:
      case TOY_OPCODE_TGSI_GATHER4:
      case TOY_OPCODE_TGSI_SVIEWINFO:
      case TOY_OPCODE_TGSI_SAMPLE_POS:
      case TOY_OPCODE_TGSI_SAMPLE_INFO:
         vs_lower_opcode_tgsi_sampling(vcc, inst);
         break;
      case TOY_OPCODE_INV:
      case TOY_OPCODE_LOG:
      case TOY_OPCODE_EXP:
      case TOY_OPCODE_SQRT:
      case TOY_OPCODE_RSQ:
      case TOY_OPCODE_SIN:
      case TOY_OPCODE_COS:
      case TOY_OPCODE_FDIV:
      case TOY_OPCODE_POW:
      case TOY_OPCODE_INT_DIV_QUOTIENT:
      case TOY_OPCODE_INT_DIV_REMAINDER:
         toy_compiler_lower_math(tc, inst);
         break;
      case TOY_OPCODE_URB_WRITE:
         vs_lower_opcode_urb_write(tc, inst);
         break;
      default:
         if (inst->opcode > 127)
            tc_fail(tc, "unhandled virtual opcode");
         break;
      }
   }
}
Example #7
0
static void
fs_lower_virtual_opcodes(struct fs_compile_context *fcc)
{
   struct toy_compiler *tc = &fcc->tc;
   struct toy_inst *inst;

   /* lower TGSI's first, as they might be lowered to other virtual opcodes */
   tc_head(tc);
   while ((inst = tc_next(tc)) != NULL) {
      switch (inst->opcode) {
      case TOY_OPCODE_TGSI_IN:
      case TOY_OPCODE_TGSI_CONST:
      case TOY_OPCODE_TGSI_SV:
      case TOY_OPCODE_TGSI_IMM:
         fs_lower_opcode_tgsi_direct(fcc, inst);
         break;
      case TOY_OPCODE_TGSI_INDIRECT_FETCH:
      case TOY_OPCODE_TGSI_INDIRECT_STORE:
         fs_lower_opcode_tgsi_indirect(fcc, inst);
         break;
      case TOY_OPCODE_TGSI_TEX:
      case TOY_OPCODE_TGSI_TXB:
      case TOY_OPCODE_TGSI_TXD:
      case TOY_OPCODE_TGSI_TXL:
      case TOY_OPCODE_TGSI_TXP:
      case TOY_OPCODE_TGSI_TXF:
      case TOY_OPCODE_TGSI_TXQ:
      case TOY_OPCODE_TGSI_TXQ_LZ:
      case TOY_OPCODE_TGSI_TEX2:
      case TOY_OPCODE_TGSI_TXB2:
      case TOY_OPCODE_TGSI_TXL2:
      case TOY_OPCODE_TGSI_SAMPLE:
      case TOY_OPCODE_TGSI_SAMPLE_I:
      case TOY_OPCODE_TGSI_SAMPLE_I_MS:
      case TOY_OPCODE_TGSI_SAMPLE_B:
      case TOY_OPCODE_TGSI_SAMPLE_C:
      case TOY_OPCODE_TGSI_SAMPLE_C_LZ:
      case TOY_OPCODE_TGSI_SAMPLE_D:
      case TOY_OPCODE_TGSI_SAMPLE_L:
      case TOY_OPCODE_TGSI_GATHER4:
      case TOY_OPCODE_TGSI_SVIEWINFO:
      case TOY_OPCODE_TGSI_SAMPLE_POS:
      case TOY_OPCODE_TGSI_SAMPLE_INFO:
         fs_lower_opcode_tgsi_sampling(fcc, inst);
         break;
      }
   }

   tc_head(tc);
   while ((inst = tc_next(tc)) != NULL) {
      switch (inst->opcode) {
      case TOY_OPCODE_INV:
      case TOY_OPCODE_LOG:
      case TOY_OPCODE_EXP:
      case TOY_OPCODE_SQRT:
      case TOY_OPCODE_RSQ:
      case TOY_OPCODE_SIN:
      case TOY_OPCODE_COS:
      case TOY_OPCODE_FDIV:
      case TOY_OPCODE_POW:
      case TOY_OPCODE_INT_DIV_QUOTIENT:
      case TOY_OPCODE_INT_DIV_REMAINDER:
         toy_compiler_lower_math(tc, inst);
         break;
      case TOY_OPCODE_DDX:
      case TOY_OPCODE_DDY:
         fs_lower_opcode_derivative(tc, inst);
         break;
      case TOY_OPCODE_FB_WRITE:
         fs_lower_opcode_fb_write(tc, inst);
         break;
      case TOY_OPCODE_KIL:
         fs_lower_opcode_kil(tc, inst);
         break;
      default:
         if (inst->opcode > 127)
            tc_fail(tc, "unhandled virtual opcode");
         break;
      }
   }
}