mojoshader_effects.c
changeset 1036 8a3597b44ff7
parent 1021 cad933999680
child 1037 b102a563d9cb
equal deleted inserted replaced
1035:5855d767e4b2 1036:8a3597b44ff7
     7  *  This file written by Ryan C. Gordon.
     7  *  This file written by Ryan C. Gordon.
     8  */
     8  */
     9 
     9 
    10 #define __MOJOSHADER_INTERNAL__ 1
    10 #define __MOJOSHADER_INTERNAL__ 1
    11 #include "mojoshader_internal.h"
    11 #include "mojoshader_internal.h"
       
    12 
       
    13 #include <math.h>
       
    14 
       
    15 void run_preshader(const MOJOSHADER_preshader *preshader, float *regs)
       
    16 {
       
    17     // this is fairly straightforward, as there aren't any branching
       
    18     //  opcodes in the preshader instruction set (at the moment, at least).
       
    19     const int scalarstart = (int) MOJOSHADER_PRESHADEROP_SCALAR_OPS;
       
    20 
       
    21     double *temps = (double *) alloca(sizeof (double) * preshader->temp_count);
       
    22     memset(temps, '\0', sizeof (double) * preshader->temp_count);
       
    23 
       
    24     double dst[4];
       
    25     double src[3][4];
       
    26     const double *src0 = src[0];
       
    27     const double *src1 = src[1];
       
    28     const double *src2 = src[2];
       
    29 
       
    30     MOJOSHADER_preshaderInstruction *inst = preshader->instructions;
       
    31     int instit;
       
    32 
       
    33     for (instit = 0; instit < preshader->instruction_count; instit++, inst++)
       
    34     {
       
    35         const MOJOSHADER_preshaderOperand *operand = inst->operands;
       
    36         const int isscalar = (inst->opcode >= scalarstart);
       
    37         const int elems = inst->element_count;
       
    38         const int elemsbytes = sizeof (double) * elems;
       
    39 
       
    40         // load up our operands...
       
    41         int opiter, elemiter;
       
    42         for (opiter = 1; opiter < inst->operand_count; opiter++, operand++)
       
    43         {
       
    44             const unsigned int index = operand->index;
       
    45             switch (operand->type)
       
    46             {
       
    47                 case MOJOSHADER_PRESHADEROPERAND_LITERAL:
       
    48                 {
       
    49                     const double *lit = &preshader->literals[index];
       
    50                     if (!isscalar)
       
    51                         memcpy(src[opiter], lit, elemsbytes);
       
    52                     else
       
    53                     {
       
    54                         const double val = *lit;
       
    55                         for (elemiter = 0; elemiter < elems; elemiter++)
       
    56                             src[opiter][elemiter] = val;
       
    57                     } // else
       
    58                     break;
       
    59                 } // case
       
    60 
       
    61                 case MOJOSHADER_PRESHADEROPERAND_INPUT:
       
    62                 case MOJOSHADER_PRESHADEROPERAND_OUTPUT:
       
    63                     if (isscalar)
       
    64                         src[opiter][0] = regs[index];
       
    65                     else
       
    66                     {
       
    67                         int cpy;
       
    68                         for (cpy = 0; cpy < elems; cpy++)
       
    69                             src[opiter][cpy] = regs[index+cpy];
       
    70                     } // else
       
    71                     break;
       
    72 
       
    73                 case MOJOSHADER_PRESHADEROPERAND_TEMP:
       
    74                     if (isscalar)
       
    75                         src[opiter][0] = temps[index];
       
    76                     else
       
    77                         memcpy(src[opiter], temps + index, elemsbytes);
       
    78                     break;
       
    79 
       
    80                 default:
       
    81                     assert(0 && "unexpected preshader operand type.");
       
    82                     break;
       
    83             } // switch
       
    84         } // for
       
    85 
       
    86         // run the actual instruction, store result to dst.
       
    87         int i;
       
    88         switch (inst->opcode)
       
    89         {
       
    90             #define OPCODE_CASE(op, val) \
       
    91                 case MOJOSHADER_PRESHADEROP_##op: \
       
    92                     for (i = 0; i < elems; i++) { dst[i] = val; } \
       
    93                     break;
       
    94 
       
    95             //OPCODE_CASE(NOP, 0.0)  // not a real instruction.
       
    96             OPCODE_CASE(MOV, src0[i])
       
    97             OPCODE_CASE(NEG, -src0[i])
       
    98             OPCODE_CASE(RCP, 1.0 / src0[i])
       
    99             OPCODE_CASE(FRC, src0[i] - floor(src0[i]))
       
   100             OPCODE_CASE(EXP, exp(src0[i]))
       
   101             OPCODE_CASE(LOG, log(src0[i]))
       
   102             OPCODE_CASE(RSQ, 1.0 / sqrt(src0[i]))
       
   103             OPCODE_CASE(SIN, sin(src0[i]))
       
   104             OPCODE_CASE(COS, cos(src0[i]))
       
   105             OPCODE_CASE(ASIN, asin(src0[i]))
       
   106             OPCODE_CASE(ACOS, acos(src0[i]))
       
   107             OPCODE_CASE(ATAN, atan(src0[i]))
       
   108             OPCODE_CASE(MIN, (src0[i] < src1[i]) ? src0[i] : src1[i])
       
   109             OPCODE_CASE(MAX, (src0[i] > src1[i]) ? src0[i] : src1[i])
       
   110             OPCODE_CASE(LT, (src0[i] < src1[i]) ? 1.0 : 0.0)
       
   111             OPCODE_CASE(GE, (src0[i] >= src1[i]) ? 1.0 : 0.0)
       
   112             OPCODE_CASE(ADD, src0[i] + src1[i])
       
   113             OPCODE_CASE(MUL,  src0[i] * src1[i])
       
   114             OPCODE_CASE(ATAN2, atan2(src0[i], src1[i]))
       
   115             OPCODE_CASE(DIV, src0[i] / src1[i])
       
   116             OPCODE_CASE(CMP, (src0[i] >= 0.0) ? src1[i] : src2[i])
       
   117             //OPCODE_CASE(NOISE, ???)  // !!! FIXME: don't know what this does
       
   118             //OPCODE_CASE(MOVC, ???)  // !!! FIXME: don't know what this does
       
   119             #undef OPCODE_CASE
       
   120 
       
   121             case MOJOSHADER_PRESHADEROP_DOT:
       
   122             {
       
   123                 double final = 0.0;
       
   124                 for (i = 0; i < elems; i++)
       
   125                     final += src0[i] * src1[i];
       
   126                 for (i = 0; i < elems; i++)
       
   127                     dst[i] = final;  // !!! FIXME: is this right?
       
   128             } // case
       
   129 
       
   130             #define OPCODE_CASE_SCALAR(op, val) \
       
   131                 case MOJOSHADER_PRESHADEROP_##op##_SCALAR: { \
       
   132                     const double final = val; \
       
   133                     for (i = 0; i < elems; i++) { dst[i] = final; } \
       
   134                     break; \
       
   135                 }
       
   136 
       
   137             OPCODE_CASE_SCALAR(MIN, (src0[0] < src1[0]) ? src0[0] : src1[0])
       
   138             OPCODE_CASE_SCALAR(MAX, (src0[0] > src1[0]) ? src0[0] : src1[0])
       
   139             OPCODE_CASE_SCALAR(LT, (src0[0] < src1[0]) ? 1.0 : 0.0)
       
   140             OPCODE_CASE_SCALAR(GE, (src0[0] >= src1[0]) ? 1.0 : 0.0)
       
   141             OPCODE_CASE_SCALAR(ADD, src0[0] + src1[0])
       
   142             OPCODE_CASE_SCALAR(MUL, src0[0] * src1[0])
       
   143             OPCODE_CASE_SCALAR(ATAN2, atan2(src0[0], src1[0]))
       
   144             OPCODE_CASE_SCALAR(DIV, src0[0] / src1[0])
       
   145             //OPCODE_CASE_SCALAR(DOT)  // !!! FIXME: isn't this just a MUL?
       
   146             //OPCODE_CASE_SCALAR(NOISE, ???)  // !!! FIXME: ?
       
   147             #undef OPCODE_CASE_SCALAR
       
   148 
       
   149             default:
       
   150                 assert(0 && "Unhandled preshader opcode!");
       
   151                 break;
       
   152         } // switch
       
   153 
       
   154         // Figure out where dst wants to be stored.
       
   155         operand = inst->operands;
       
   156         if (operand->type == MOJOSHADER_PRESHADEROPERAND_TEMP)
       
   157             memcpy(temps + operand->index, dst, elemsbytes);
       
   158         else
       
   159         {
       
   160             assert(operand->type == MOJOSHADER_PRESHADEROPERAND_OUTPUT);
       
   161             for (i = 0; i < elems; i++)
       
   162                 regs[operand->index + i] = (float) dst[i];
       
   163         } // else
       
   164     } // for
       
   165 } // run_preshader
    12 
   166 
    13 
   167 
    14 static MOJOSHADER_effect MOJOSHADER_out_of_mem_effect = {
   168 static MOJOSHADER_effect MOJOSHADER_out_of_mem_effect = {
    15     1, &MOJOSHADER_out_of_mem_error, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   169     1, &MOJOSHADER_out_of_mem_error, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    16 };
   170 };