#include "i915_fpc.h"
-
-
-void
-i915_program_error(struct i915_fp_compile *p, const char *msg)
-{
- fprintf(stderr, "i915_program_error: %s", msg);
- p->fp->error = 1;
-}
-
-
-static struct i915_fp_compile *
-i915_init_compile(struct i915_context *i915, struct i915_fragment_program *fp)
-{
- struct i915_fp_compile *p = CALLOC_STRUCT(i915_fp_compile);
-
- p->fp = fp;
-#if 0
- p->env_param = NULL; /*i915->intel.ctx.FragmentProgram.Parameters;*/
-#endif
- p->constants = i915->fs.constants;
- p->nr_tex_indirect = 1; /* correct? */
- p->nr_tex_insn = 0;
- p->nr_alu_insn = 0;
- p->nr_decl_insn = 0;
-
- memset(p->constant_flags, 0, sizeof(p->constant_flags));
-
- p->csr = p->program;
- p->decl = p->declarations;
- p->decl_s = 0;
- p->decl_t = 0;
- p->temp_flag = 0xffff000;
- p->utemp_flag = ~0x7;
-
-#if 0
- p->fp->translated = 0;
- p->fp->error = 0;
- p->fp->nr_constants = 0;
-#endif
- p->fp->wpos_tex = -1;
- p->fp->nr_params = 0;
-
- *(p->decl++) = _3DSTATE_PIXEL_SHADER_PROGRAM;
-
- return p;
-}
-
-/* Copy compile results to the fragment program struct and destroy the
- * compilation context.
- */
-static void
-i915_fini_compile(struct i915_fp_compile *p)
-{
- uint program_size = p->csr - p->program;
- uint decl_size = p->decl - p->declarations;
-
- if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT)
- i915_program_error(p, "Exceeded max nr indirect texture lookups");
-
- if (p->nr_tex_insn > I915_MAX_TEX_INSN)
- i915_program_error(p, "Exceeded max TEX instructions");
-
- if (p->nr_alu_insn > I915_MAX_ALU_INSN)
- i915_program_error(p, "Exceeded max ALU instructions");
-
- if (p->nr_decl_insn > I915_MAX_DECL_INSN)
- i915_program_error(p, "Exceeded max DECL instructions");
-
- if (p->fp->error) {
- p->fp->NumNativeInstructions = 0;
- p->fp->NumNativeAluInstructions = 0;
- p->fp->NumNativeTexInstructions = 0;
- p->fp->NumNativeTexIndirections = 0;
- return;
- }
- else {
- p->fp->NumNativeInstructions = (p->nr_alu_insn +
- p->nr_tex_insn +
- p->nr_decl_insn);
- p->fp->NumNativeAluInstructions = p->nr_alu_insn;
- p->fp->NumNativeTexInstructions = p->nr_tex_insn;
- p->fp->NumNativeTexIndirections = p->nr_tex_indirect;
- }
-
- p->declarations[0] |= program_size + decl_size - 2;
-
- /* Copy compilation results to fragment program struct:
- */
- memcpy(p->fp->program,
- p->declarations,
- decl_size * sizeof(uint));
-
- memcpy(p->fp->program + decl_size,
- p->program,
- program_size * sizeof(uint));
-
- p->fp->program_size = program_size + decl_size;
-
- /* Release the compilation struct:
- */
- free(p);
-}
-
-
-/**
- * Find an unused texture coordinate slot to use for fragment WPOS.
- * Update p->fp->wpos_tex with the result (-1 if no used texcoord slot is found).
- */
-static void
-find_wpos_space(struct i915_fp_compile *p)
-{
- const uint inputs = p->shader->inputs_read;
- uint i;
-
- p->fp->wpos_tex = -1;
-
- if (inputs & FRAG_BIT_WPOS) {
- for (i = 0; i < I915_TEX_UNITS; i++) {
- if ((inputs & (FRAG_BIT_TEX0 << i)) == 0) {
- p->fp->wpos_tex = i;
- return;
- }
- }
-
- i915_program_error(p, "No free texcoord for wpos value");
- }
-}
-
-
-
-void i915_compile_fragment_program( struct i915_context *i915,
- struct i915_fragment_program *fp )
-{
- struct i915_fp_compile *p = i915_init_compile(i915, fp);
- struct tgsi_token *tokens = i915->fs.tokens;
-
- find_wpos_space(p);
-
- i915_translate_program(p, tokens);
- i915_fixup_depth_write(p);
-
- i915_fini_compile(p);
-#if 0
- fp->translated = 1;
-#endif
-}
-#if 1 /*XXX temp */
-/* Hardware version of a parsed fragment program. "Derived" from the
- * mesa fragment_program struct.
- */
-struct i915_fragment_program
-{
-#if 0
- struct gl_fragment_program Base;
-#else
- uint NumNativeInstructions;
- uint NumNativeAluInstructions;
- uint NumNativeTexInstructions;
- uint NumNativeTexIndirections;
-#endif
-
- boolean error; /**< Set if i915_program_error() is called */
-#if 0
- uint id; /**< String id */
- boolean translated;
-#endif
-
- /* Decls + instructions:
- */
- uint program[I915_PROGRAM_SIZE];
- uint program_size;
-
-#if 0
- /* Constant buffer:
- */
- float constant[I915_MAX_CONSTANT][4];
- uint nr_constants;
-#endif
-
- /* Some of which are parameters:
- */
- struct
- {
- uint reg; /* Hardware constant idx */
- const float *values; /* Pointer to tracked values */
- } param[I915_MAX_CONSTANT];
- uint nr_params;
-
-#if 0
- uint param_state;
-#endif
- uint wpos_tex;
-};
-#endif
-
-
-/***********************************************************************
- * Public interface for the compiler
- */
-
-void i915_compile_fragment_program( struct i915_context *i915,
- struct i915_fragment_program *fp );
-
-
-/***********************************************************************
- * Private details of the compiler
+/**
+ * Program translation state
*/
-
struct i915_fp_compile {
- struct i915_fragment_program *fp;
-
struct pipe_shader_state *shader;
uint declarations[I915_PROGRAM_SIZE];
uint nr_alu_insn;
uint nr_decl_insn;
-#if 0
- float (*env_param)[4];
-#endif
+ boolean error; /**< Set if i915_program_error() is called */
+ uint wpos_tex;
+ uint NumNativeInstructions;
+ uint NumNativeAluInstructions;
+ uint NumNativeTexInstructions;
+ uint NumNativeTexIndirections;
};
}
+
+/***********************************************************************
+ * Public interface for the compiler
+ */
+extern void i915_translate_fragment_program( struct i915_context *i915 );
+
+
+
extern uint i915_get_temp(struct i915_fp_compile *p);
extern uint i915_get_utemp(struct i915_fp_compile *p);
extern void i915_release_utemps(struct i915_fp_compile *p);
float c2, float c3);
-#if 0
-extern uint i915_emit_param4fv(struct i915_fp_compile *p,
- const float * values);
-#endif
-
-
-
-/*======================================================================
- * i915_fpc_debug.c
- */
-extern void i915_program_error(struct i915_fp_compile *p,
- const char *msg);
-
-
/*======================================================================
* i915_fpc_debug.c
*/
extern void i915_disassemble_program(const uint * program, uint sz);
-#if 0
-extern void i915_print_mesa_instructions( const struct prog_instruction *insn,
- uint nr );
-#endif
/*======================================================================
* i915_fpc_translate.c
*/
-void i915_fixup_depth_write(struct i915_fp_compile *p);
extern void
-i915_translate_program(struct i915_fp_compile *p, const struct tgsi_token *token);
+i915_program_error(struct i915_fp_compile *p, const char *msg);
+extern void
+i915_translate_fragment_program(struct i915_context *i915);
#endif
#include "pipe/tgsi/core/tgsi_token.h"
#include "pipe/tgsi/core/tgsi_parse.h"
+/**
+ * Simple pass-through fragment shader to use when we don't have
+ * a real shader (or it fails to compile for some reason).
+ */
+static unsigned passthrough[] =
+{
+ _3DSTATE_PIXEL_SHADER_PROGRAM | ((2*3)-1),
+
+ /* declare input color:
+ */
+ (D0_DCL |
+ (REG_TYPE_T << D0_TYPE_SHIFT) |
+ (T_DIFFUSE << D0_NR_SHIFT) |
+ D0_CHANNEL_ALL),
+ 0,
+ 0,
+
+ /* move to output color:
+ */
+ (A0_MOV |
+ (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
+ A0_DEST_CHANNEL_ALL |
+ (REG_TYPE_T << A0_SRC0_TYPE_SHIFT) |
+ (T_DIFFUSE << A0_SRC0_NR_SHIFT)),
+ 0x01230000, /* .xyzw */
+ 0
+};
+
/* 1, -1/3!, 1/5!, -1/7! */
static const float sin_constants[4] = { 1.0,
};
+
+static void
+i915_use_passthrough_shader(struct i915_context *i915)
+{
+ fprintf(stderr, "**** Using i915 pass-through fragment shader\n");
+
+ i915->current.program = (uint *) malloc(sizeof(passthrough));
+ memcpy(i915->current.program, passthrough, sizeof(passthrough));
+ i915->current.program_len = Elements(passthrough);
+
+ i915->current.constants = NULL;
+ i915->current.num_constants = 0;
+}
+
+
+void
+i915_program_error(struct i915_fp_compile *p, const char *msg)
+{
+ fprintf(stderr, "i915_program_error: %s\n", msg);
+ p->error = 1;
+}
+
+
+
/**
* Construct a ureg for the given source register. Will emit
* constants, apply swizzling and negation as needed.
const uint index = source->SrcRegister.Index;
uint src;
- switch (source->SrcRegisterInd.File) {
+ switch (source->SrcRegister.File) {
case TGSI_FILE_TEMPORARY:
if (source->SrcRegister.Index >= I915_MAX_TEMPORARY) {
i915_program_error(p, "Exceeded max temporary reg");
*/
switch (index) {
case FRAG_ATTRIB_WPOS:
- src = i915_emit_decl(p, REG_TYPE_T, p->fp->wpos_tex, D0_CHANNEL_ALL);
+ src = i915_emit_decl(p, REG_TYPE_T, p->wpos_tex, D0_CHANNEL_ALL);
break;
case FRAG_ATTRIB_COL0:
src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL);
}
break;
- /* Various parameters and env values. All emitted to
- * hardware as program constants.
- */
-#if 0
- case PROGRAM_LOCAL_PARAM:
- src = i915_emit_param4fv(p, program->Base.LocalParams[index]);
- break;
- case PROGRAM_ENV_PARAM:
- src = i915_emit_param4fv(p, p->env_param[index]);
- break;
- case PROGRAM_CONSTANT:
- case PROGRAM_STATE_VAR:
- case PROGRAM_NAMED_PARAM:
- src = i915_emit_param4fv(
- p, program->Base.Parameters->ParameterValues[index]);
- break;
-#else
case TGSI_FILE_CONSTANT:
src = UREG(REG_TYPE_CONST, index);
break;
-#endif
default:
i915_program_error(p, "Bad source->File");
assert(!source->SrcRegisterExtSwz.NegateW);
assert(!source->SrcRegisterExtMod.Absolute);
assert(!source->SrcRegisterExtMod.Negate);
-#if 0
- if (source->SrcRegister.Negate)
- negate all
-
- if (extended source swiz per component)
- src = negate(src,
- source->SrcRegisterExtSwz.NegateX,
- source->SrcRegisterExtSwz.NegateY,
- source->SrcRegisterExtSwz.NegateZ,
- source->SrcRegisterExtSwz.NegateW);
- if (mod.abs)
- absolute value
-
- if (mod.negate)
- another negate;
-#endif
+
return src;
}
+/**
+ * Construct a ureg for a destination register.
+ */
static uint
get_result_vector(struct i915_fp_compile *p,
const struct tgsi_full_dst_register *dest)
switch (dest->DstRegister.File) {
case TGSI_FILE_OUTPUT:
switch (dest->DstRegister.Index) {
- case FRAG_RESULT_COLR:
+ case 1: /*COLOR*/ /*FRAG_RESULT_COLR:*/
return UREG(REG_TYPE_OC, 0);
- case FRAG_RESULT_DEPR:
+ case 0: /*DEPTH*/ /*FRAG_RESULT_DEPR:*/
return UREG(REG_TYPE_OD, 0);
default:
i915_program_error(p, "Bad inst->DstReg.Index");
}
-#define EMIT_1ARG_ARITH( OP ) emit_simple_arith(p, inst, OP, 1)
-#define EMIT_2ARG_ARITH( OP ) emit_simple_arith(p, inst, OP, 2)
-#define EMIT_3ARG_ARITH( OP ) emit_simple_arith(p, inst, OP, 3)
-
-
-
+/*
+ * Translate TGSI instruction to i915 instruction.
+ *
+ * Possible concerns:
+ *
+ * SIN, COS -- could use another taylor step?
+ * LIT -- results seem a little different to sw mesa
+ * LOG -- different to mesa on negative numbers, but this is conformant.
+ */
static void
i915_translate_instruction(struct i915_fp_compile *p,
const struct tgsi_full_instruction *inst)
break;
case TGSI_OPCODE_ADD:
- EMIT_2ARG_ARITH(A0_ADD);
+ emit_simple_arith(p, inst, A0_ADD, 2);
break;
case TGSI_OPCODE_CMP:
break;
case TGSI_OPCODE_DP3:
- EMIT_2ARG_ARITH(A0_DP3);
+ emit_simple_arith(p, inst, A0_DP3, 2);
break;
case TGSI_OPCODE_DP4:
- EMIT_2ARG_ARITH(A0_DP4);
+ emit_simple_arith(p, inst, A0_DP4, 2);
break;
case TGSI_OPCODE_DPH:
break;
case TGSI_OPCODE_FLR:
- EMIT_1ARG_ARITH(A0_FLR);
+ emit_simple_arith(p, inst, A0_FLR, 1);
break;
case TGSI_OPCODE_FRC:
- EMIT_1ARG_ARITH(A0_FRC);
+ emit_simple_arith(p, inst, A0_FRC, 1);
break;
case TGSI_OPCODE_KIL:
break;
case TGSI_OPCODE_MAD:
- EMIT_3ARG_ARITH(A0_MAD);
+ emit_simple_arith(p, inst, A0_MAD, 3);
break;
case TGSI_OPCODE_MAX:
- EMIT_2ARG_ARITH(A0_MAX);
+ emit_simple_arith(p, inst, A0_MAX, 2);
break;
case TGSI_OPCODE_MIN:
case TGSI_OPCODE_MOV:
/* aka TGSI_OPCODE_SWZ */
- EMIT_1ARG_ARITH(A0_MOV);
+ emit_simple_arith(p, inst, A0_MOV, 1);
break;
case TGSI_OPCODE_MUL:
- EMIT_2ARG_ARITH(A0_MUL);
+ emit_simple_arith(p, inst, A0_MUL, 2);
break;
case TGSI_OPCODE_POW:
break;
case TGSI_OPCODE_SGE:
- EMIT_2ARG_ARITH(A0_SGE);
+ emit_simple_arith(p, inst, A0_SGE, 2);
break;
case TGSI_OPCODE_SIN:
break;
case TGSI_OPCODE_SLT:
- EMIT_2ARG_ARITH(A0_SLT);
+ emit_simple_arith(p, inst, A0_SLT, 2);
break;
case TGSI_OPCODE_SUB:
/**
* Translate TGSI fragment shader into i915 hardware instructions.
- *
- * Possible concerns:
- *
- * SIN, COS -- could use another taylor step?
- * LIT -- results seem a little different to sw mesa
- * LOG -- different to mesa on negative numbers, but this is conformant.
- *
- * Parse failures -- Mesa doesn't currently give a good indication
- * internally whether a particular program string parsed or not. This
- * can lead to confusion -- hopefully we cope with it ok now.
+ * \param p the translation state
+ * \param tokens the TGSI token array
*/
-void
-i915_translate_program(struct i915_fp_compile *p,
- const struct tgsi_token *tokens)
+static void
+i915_translate_instructions(struct i915_fp_compile *p,
+ const struct tgsi_token *tokens)
{
struct tgsi_parse_context parse;
switch( parse.FullToken.Token.Type ) {
case TGSI_TOKEN_TYPE_DECLARATION:
- assert(0);
+ /* XXX no-op? */
break;
case TGSI_TOKEN_TYPE_IMMEDIATE:
+ /* XXX no-op? */
assert(0);
break;
}
+static struct i915_fp_compile *
+i915_init_compile(struct i915_context *i915,
+ struct pipe_shader_state *fs)
+{
+ struct i915_fp_compile *p = CALLOC_STRUCT(i915_fp_compile);
+
+ p->shader = &i915->fs;
+
+ /* a bit of a hack, need to improve constant buffer infrastructure */
+ if (i915->fs.constants)
+ p->constants = i915->fs.constants;
+ else
+ p->constants = &i915->temp_constants;
+
+ p->nr_tex_indirect = 1; /* correct? */
+ p->nr_tex_insn = 0;
+ p->nr_alu_insn = 0;
+ p->nr_decl_insn = 0;
+
+ memset(p->constant_flags, 0, sizeof(p->constant_flags));
+
+ p->csr = p->program;
+ p->decl = p->declarations;
+ p->decl_s = 0;
+ p->decl_t = 0;
+ p->temp_flag = 0xffff000;
+ p->utemp_flag = ~0x7;
+
+ p->wpos_tex = -1;
+
+ /* initialize the first program word */
+ *(p->decl++) = _3DSTATE_PIXEL_SHADER_PROGRAM;
+
+ return p;
+}
+
+/* Copy compile results to the fragment program struct and destroy the
+ * compilation context.
+ */
+static void
+i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
+{
+ uint program_size = p->csr - p->program;
+ uint decl_size = p->decl - p->declarations;
+
+ if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT)
+ i915_program_error(p, "Exceeded max nr indirect texture lookups");
+
+ if (p->nr_tex_insn > I915_MAX_TEX_INSN)
+ i915_program_error(p, "Exceeded max TEX instructions");
+
+ if (p->nr_alu_insn > I915_MAX_ALU_INSN)
+ i915_program_error(p, "Exceeded max ALU instructions");
+
+ if (p->nr_decl_insn > I915_MAX_DECL_INSN)
+ i915_program_error(p, "Exceeded max DECL instructions");
+
+ if (p->error) {
+ p->NumNativeInstructions = 0;
+ p->NumNativeAluInstructions = 0;
+ p->NumNativeTexInstructions = 0;
+ p->NumNativeTexIndirections = 0;
+
+ i915_use_passthrough_shader(i915);
+ }
+ else {
+ p->NumNativeInstructions = (p->nr_alu_insn +
+ p->nr_tex_insn +
+ p->nr_decl_insn);
+ p->NumNativeAluInstructions = p->nr_alu_insn;
+ p->NumNativeTexInstructions = p->nr_tex_insn;
+ p->NumNativeTexIndirections = p->nr_tex_indirect;
+
+ /* patch in the program length */
+ p->declarations[0] |= program_size + decl_size - 2;
+
+ /* Copy compilation results to fragment program struct:
+ */
+ i915->current.program
+ = (uint *) malloc((program_size + decl_size) * sizeof(uint));
+ i915->current.program_len = program_size + decl_size;
+
+ memcpy(i915->current.program,
+ p->declarations,
+ decl_size * sizeof(uint));
+ memcpy(i915->current.program + decl_size,
+ p->program,
+ program_size * sizeof(uint));
-/* Rather than trying to intercept and jiggle depth writes during
+ i915->current.constants = (uint *) p->constants->constant;
+ i915->current.num_constants = p->constants->nr_constants;
+ }
+
+ /* Release the compilation struct:
+ */
+ free(p);
+}
+
+
+/**
+ * Find an unused texture coordinate slot to use for fragment WPOS.
+ * Update p->fp->wpos_tex with the result (-1 if no used texcoord slot is found).
+ */
+static void
+i915_find_wpos_space(struct i915_fp_compile *p)
+{
+ const uint inputs = p->shader->inputs_read;
+ uint i;
+
+ p->wpos_tex = -1;
+
+ if (inputs & FRAG_BIT_WPOS) {
+ for (i = 0; i < I915_TEX_UNITS; i++) {
+ if ((inputs & (FRAG_BIT_TEX0 << i)) == 0) {
+ p->wpos_tex = i;
+ return;
+ }
+ }
+
+ i915_program_error(p, "No free texcoord for wpos value");
+ }
+}
+
+
+
+
+/**
+ * Rather than trying to intercept and jiggle depth writes during
* emit, just move the value into its correct position at the end of
* the program:
*/
-void
+static void
i915_fixup_depth_write(struct i915_fp_compile *p)
{
if (p->shader->outputs_written & (1<<FRAG_RESULT_DEPR)) {
}
+void
+i915_translate_fragment_program( struct i915_context *i915 )
+{
+ struct i915_fp_compile *p = i915_init_compile(i915, &i915->fs);
+ const struct tgsi_token *tokens = i915->fs.tokens;
+ i915_find_wpos_space(p);
+ i915_translate_instructions(p, tokens);
+ i915_fixup_depth_write(p);
+
+ i915_fini_compile(i915, p);
+}