Navigation Menu

Skip to content

Commit

Permalink
First shot at preshader interpreter. Completely untested!
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed May 31, 2011
1 parent 8c21288 commit 31cbb0f
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 7 deletions.
18 changes: 11 additions & 7 deletions CMakeLists.txt
Expand Up @@ -72,6 +72,10 @@ ADD_LIBRARY(mojoshader STATIC
mojoshader_opengl.c
)

IF(UNIX)
SET(LIBM -lm)
ENDIF(UNIX)

SET_SOURCE_FILES_PROPERTIES(
mojoshader_compiler.c
PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/mojoshader_parser_hlsl.h"
Expand All @@ -94,15 +98,15 @@ FIND_PACKAGE(SDL)
IF(SDL_FOUND)
INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR})
ADD_EXECUTABLE(glcaps utils/glcaps.c)
TARGET_LINK_LIBRARIES(glcaps ${SDL_LIBRARY})
TARGET_LINK_LIBRARIES(glcaps ${SDL_LIBRARY} ${LIBM})
ADD_EXECUTABLE(bestprofile utils/bestprofile.c)
TARGET_LINK_LIBRARIES(bestprofile mojoshader ${SDL_LIBRARY})
TARGET_LINK_LIBRARIES(bestprofile mojoshader ${SDL_LIBRARY} ${LIBM})
ADD_EXECUTABLE(availableprofiles utils/availableprofiles.c)
TARGET_LINK_LIBRARIES(availableprofiles mojoshader ${SDL_LIBRARY})
TARGET_LINK_LIBRARIES(availableprofiles mojoshader ${SDL_LIBRARY} ${LIBM})
ENDIF(SDL_FOUND)

ADD_EXECUTABLE(finderrors utils/finderrors.c)
TARGET_LINK_LIBRARIES(finderrors mojoshader ${SDL_LIBRARY})
TARGET_LINK_LIBRARIES(finderrors mojoshader ${SDL_LIBRARY} ${LIBM})
IF(SDL_FOUND)
SET_SOURCE_FILES_PROPERTIES(
utils/finderrors.c
Expand All @@ -111,11 +115,11 @@ IF(SDL_FOUND)
ENDIF(SDL_FOUND)

ADD_EXECUTABLE(testparse utils/testparse.c)
TARGET_LINK_LIBRARIES(testparse mojoshader)
TARGET_LINK_LIBRARIES(testparse mojoshader ${LIBM})
ADD_EXECUTABLE(testoutput utils/testoutput.c)
TARGET_LINK_LIBRARIES(testoutput mojoshader)
TARGET_LINK_LIBRARIES(testoutput mojoshader ${LIBM})
ADD_EXECUTABLE(mojoshader-compiler utils/mojoshader-compiler.c)
TARGET_LINK_LIBRARIES(mojoshader-compiler mojoshader)
TARGET_LINK_LIBRARIES(mojoshader-compiler mojoshader ${LIBM})

# Unit tests...
ADD_CUSTOM_TARGET(
Expand Down
154 changes: 154 additions & 0 deletions mojoshader_effects.c
Expand Up @@ -10,6 +10,160 @@
#define __MOJOSHADER_INTERNAL__ 1
#include "mojoshader_internal.h"

#include <math.h>

void run_preshader(const MOJOSHADER_preshader *preshader, float *regs)
{
// this is fairly straightforward, as there aren't any branching
// opcodes in the preshader instruction set (at the moment, at least).
const int scalarstart = (int) MOJOSHADER_PRESHADEROP_SCALAR_OPS;

double *temps = (double *) alloca(sizeof (double) * preshader->temp_count);
memset(temps, '\0', sizeof (double) * preshader->temp_count);

double dst[4];
double src[3][4];
const double *src0 = src[0];
const double *src1 = src[1];
const double *src2 = src[2];

MOJOSHADER_preshaderInstruction *inst = preshader->instructions;
int instit;

for (instit = 0; instit < preshader->instruction_count; instit++, inst++)
{
const MOJOSHADER_preshaderOperand *operand = inst->operands;
const int isscalar = (inst->opcode >= scalarstart);
const int elems = inst->element_count;
const int elemsbytes = sizeof (double) * elems;

// load up our operands...
int opiter, elemiter;
for (opiter = 1; opiter < inst->operand_count; opiter++, operand++)
{
const unsigned int index = operand->index;
switch (operand->type)
{
case MOJOSHADER_PRESHADEROPERAND_LITERAL:
{
const double *lit = &preshader->literals[index];
if (!isscalar)
memcpy(src[opiter], lit, elemsbytes);
else
{
const double val = *lit;
for (elemiter = 0; elemiter < elems; elemiter++)
src[opiter][elemiter] = val;
} // else
break;
} // case

case MOJOSHADER_PRESHADEROPERAND_INPUT:
case MOJOSHADER_PRESHADEROPERAND_OUTPUT:
if (isscalar)
src[opiter][0] = regs[index];
else
{
int cpy;
for (cpy = 0; cpy < elems; cpy++)
src[opiter][cpy] = regs[index+cpy];
} // else
break;

case MOJOSHADER_PRESHADEROPERAND_TEMP:
if (isscalar)
src[opiter][0] = temps[index];
else
memcpy(src[opiter], temps + index, elemsbytes);
break;

default:
assert(0 && "unexpected preshader operand type.");
break;
} // switch
} // for

// run the actual instruction, store result to dst.
int i;
switch (inst->opcode)
{
#define OPCODE_CASE(op, val) \
case MOJOSHADER_PRESHADEROP_##op: \
for (i = 0; i < elems; i++) { dst[i] = val; } \
break;

//OPCODE_CASE(NOP, 0.0) // not a real instruction.
OPCODE_CASE(MOV, src0[i])
OPCODE_CASE(NEG, -src0[i])
OPCODE_CASE(RCP, 1.0 / src0[i])
OPCODE_CASE(FRC, src0[i] - floor(src0[i]))
OPCODE_CASE(EXP, exp(src0[i]))
OPCODE_CASE(LOG, log(src0[i]))
OPCODE_CASE(RSQ, 1.0 / sqrt(src0[i]))
OPCODE_CASE(SIN, sin(src0[i]))
OPCODE_CASE(COS, cos(src0[i]))
OPCODE_CASE(ASIN, asin(src0[i]))
OPCODE_CASE(ACOS, acos(src0[i]))
OPCODE_CASE(ATAN, atan(src0[i]))
OPCODE_CASE(MIN, (src0[i] < src1[i]) ? src0[i] : src1[i])
OPCODE_CASE(MAX, (src0[i] > src1[i]) ? src0[i] : src1[i])
OPCODE_CASE(LT, (src0[i] < src1[i]) ? 1.0 : 0.0)
OPCODE_CASE(GE, (src0[i] >= src1[i]) ? 1.0 : 0.0)
OPCODE_CASE(ADD, src0[i] + src1[i])
OPCODE_CASE(MUL, src0[i] * src1[i])
OPCODE_CASE(ATAN2, atan2(src0[i], src1[i]))
OPCODE_CASE(DIV, src0[i] / src1[i])
OPCODE_CASE(CMP, (src0[i] >= 0.0) ? src1[i] : src2[i])
//OPCODE_CASE(NOISE, ???) // !!! FIXME: don't know what this does
//OPCODE_CASE(MOVC, ???) // !!! FIXME: don't know what this does
#undef OPCODE_CASE

case MOJOSHADER_PRESHADEROP_DOT:
{
double final = 0.0;
for (i = 0; i < elems; i++)
final += src0[i] * src1[i];
for (i = 0; i < elems; i++)
dst[i] = final; // !!! FIXME: is this right?
} // case

#define OPCODE_CASE_SCALAR(op, val) \
case MOJOSHADER_PRESHADEROP_##op##_SCALAR: { \
const double final = val; \
for (i = 0; i < elems; i++) { dst[i] = final; } \
break; \
}

OPCODE_CASE_SCALAR(MIN, (src0[0] < src1[0]) ? src0[0] : src1[0])
OPCODE_CASE_SCALAR(MAX, (src0[0] > src1[0]) ? src0[0] : src1[0])
OPCODE_CASE_SCALAR(LT, (src0[0] < src1[0]) ? 1.0 : 0.0)
OPCODE_CASE_SCALAR(GE, (src0[0] >= src1[0]) ? 1.0 : 0.0)
OPCODE_CASE_SCALAR(ADD, src0[0] + src1[0])
OPCODE_CASE_SCALAR(MUL, src0[0] * src1[0])
OPCODE_CASE_SCALAR(ATAN2, atan2(src0[0], src1[0]))
OPCODE_CASE_SCALAR(DIV, src0[0] / src1[0])
//OPCODE_CASE_SCALAR(DOT) // !!! FIXME: isn't this just a MUL?
//OPCODE_CASE_SCALAR(NOISE, ???) // !!! FIXME: ?
#undef OPCODE_CASE_SCALAR

default:
assert(0 && "Unhandled preshader opcode!");
break;
} // switch

// Figure out where dst wants to be stored.
operand = inst->operands;
if (operand->type == MOJOSHADER_PRESHADEROPERAND_TEMP)
memcpy(temps + operand->index, dst, elemsbytes);
else
{
assert(operand->type == MOJOSHADER_PRESHADEROPERAND_OUTPUT);
for (i = 0; i < elems; i++)
regs[operand->index + i] = (float) dst[i];
} // else
} // for
} // run_preshader


static MOJOSHADER_effect MOJOSHADER_out_of_mem_effect = {
1, &MOJOSHADER_out_of_mem_error, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Expand Down

0 comments on commit 31cbb0f

Please sign in to comment.