#include "draw/draw_vertex.h"
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
/**
* 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[] =
+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_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 |
+ (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 */
-1.0f / (6 * 5 * 4 * 3 * 2 * 1)
};
-/* 1, -1/3!, 1/5!, -1/7! */
+/* 2*pi, -(2*pi)^3/3!, (2*pi)^5/5!, -(2*pi)^7/7! */
static const float sin_constants[4] = { 2.0 * M_PI,
-8.0f * M_PI * M_PI * M_PI / (3 * 2 * 1),
32.0f * M_PI * M_PI * M_PI * M_PI * M_PI / (5 * 4 * 3 * 2 * 1),
-128.0f * M_PI * M_PI * M_PI * M_PI * M_PI * M_PI * M_PI / (7 * 6 * 5 * 4 * 3 * 2 * 1)
};
-/* 1, -1/2!, 1/4!, -1/6! */
+/* 1, -(2*pi)^2/2!, (2*pi)^4/4!, -(2*pi)^6/6! */
static const float cos_constants[4] = { 1.0,
-4.0f * M_PI * M_PI / (2 * 1),
16.0f * M_PI * M_PI * M_PI * M_PI / (4 * 3 * 2 * 1),
char buffer[1024];
debug_printf("i915_program_error: ");
- va_start( args, msg );
+ va_start( args, msg );
util_vsnprintf( buffer, sizeof(buffer), msg, args );
va_end( args );
debug_printf("%s", buffer);
*/
static uint
src_vector(struct i915_fp_compile *p,
- const struct tgsi_full_src_register *source,
+ const struct i915_full_src_register *source,
struct i915_fragment_shader* fs)
{
uint index = source->Register.Index;
assert(!source->Register.Absolute);
#endif
if (source->Register.Absolute)
- debug_printf("Exceeded max generics\n");
+ debug_printf("Unhandled absolute value\n");
return src;
}
*/
static uint
get_result_vector(struct i915_fp_compile *p,
- const struct tgsi_full_dst_register *dest)
+ const struct i915_full_dst_register *dest)
{
switch (dest->Register.File) {
case TGSI_FILE_OUTPUT:
* Compute flags for saturation and writemask.
*/
static uint
-get_result_flags(const struct tgsi_full_instruction *inst)
+get_result_flags(const struct i915_full_instruction *inst)
{
const uint writeMask
= inst->Dst[0].Register.WriteMask;
}
}
+/**
+ * Return the number of coords needed to access a given TGSI_TEXTURE_*
+ */
+static uint
+texture_num_coords(struct i915_fp_compile *p, uint tex)
+{
+ switch (tex) {
+ case TGSI_TEXTURE_SHADOW1D:
+ case TGSI_TEXTURE_1D:
+ return 1;
+
+ case TGSI_TEXTURE_SHADOW2D:
+ case TGSI_TEXTURE_2D:
+ case TGSI_TEXTURE_SHADOWRECT:
+ case TGSI_TEXTURE_RECT:
+ return 2;
+
+ case TGSI_TEXTURE_3D:
+ case TGSI_TEXTURE_CUBE:
+ return 3;
+
+ default:
+ i915_program_error(p, "Num coords");
+ return 2;
+ }
+}
+
/**
* Generate texel lookup instruction.
*/
static void
emit_tex(struct i915_fp_compile *p,
- const struct tgsi_full_instruction *inst,
+ const struct i915_full_instruction *inst,
uint opcode,
struct i915_fragment_shader* fs)
{
get_result_flags( inst ),
sampler,
coord,
- opcode);
+ opcode,
+ texture_num_coords(p, texture) );
}
*/
static void
emit_simple_arith(struct i915_fp_compile *p,
- const struct tgsi_full_instruction *inst,
+ const struct i915_full_instruction *inst,
uint opcode, uint numArgs,
struct i915_fragment_shader* fs)
{
/** As above, but swap the first two src regs */
static void
emit_simple_arith_swap2(struct i915_fp_compile *p,
- const struct tgsi_full_instruction *inst,
+ const struct i915_full_instruction *inst,
uint opcode, uint numArgs,
struct i915_fragment_shader* fs)
{
- struct tgsi_full_instruction inst2;
+ struct i915_full_instruction inst2;
assert(numArgs == 2);
emit_simple_arith(p, &inst2, opcode, numArgs, fs);
}
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
/*
* Translate TGSI instruction to i915 instruction.
*
* Possible concerns:
*
+ * DDX, DDY -- return 0
* 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,
+ const struct i915_full_instruction *inst,
struct i915_fragment_shader *fs)
{
uint writemask;
src0 = src_vector(p, &inst->Src[0], fs);
src1 = src_vector(p, &inst->Src[1], fs);
src2 = src_vector(p, &inst->Src[2], fs);
- i915_emit_arith(p, A0_CMP,
+ i915_emit_arith(p, A0_CMP,
get_result_vector(p, &inst->Dst[0]),
- get_result_flags(inst),
+ get_result_flags(inst),
0, src0, src2, src1); /* NOTE: order of src2, src1 */
break;
i915_emit_arith(p, A0_MOD, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0);
/*
- * t0.xy = MUL x.xx11, x.x1111 ; x^2, x, 1, 1
+ * t0.xy = MUL x.xx11, x.x111 ; x^2, x, 1, 1
* t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, 1
* t0 = MUL t0.xxz1 t0.z111 ; x^6 x^4 x^2 1
* result = DP4 t0, cos_constants
A0_DEST_CHANNEL_ALL, /* dest writemask */
0, /* sampler */
src0, /* coord*/
- T0_TEXKILL); /* opcode */
+ T0_TEXKILL, /* opcode */
+ 1); /* num_coord */
break;
case TGSI_OPCODE_KILP:
- assert(0); /* not tested yet */
+ /* We emit an unconditional kill; we may want to revisit
+ * if we ever implement conditionals.
+ */
+ tmp = i915_get_utemp(p);
+
+ i915_emit_texld(p,
+ tmp, /* dest reg: a dummy reg */
+ A0_DEST_CHANNEL_ALL, /* dest writemask */
+ 0, /* sampler */
+ negate(swizzle(0, ONE, ONE, ONE, ONE), 1, 1, 1, 1), /* coord */
+ T0_TEXKILL, /* opcode */
+ 1); /* num_coord */
break;
case TGSI_OPCODE_LG2:
emit_simple_arith(p, inst, A0_MUL, 2, fs);
break;
+ case TGSI_OPCODE_NOP:
+ break;
+
case TGSI_OPCODE_POW:
src0 = src_vector(p, &inst->Src[0], fs);
src1 = src_vector(p, &inst->Src[1], fs);
get_result_vector(p, &inst->Dst[0]),
flags, 0, swizzle(tmp, X, X, X, X), 0, 0);
break;
-
+
case TGSI_OPCODE_RET:
/* XXX: no-op? */
break;
-
+
case TGSI_OPCODE_RCP:
src0 = src_vector(p, &inst->Src[0], fs);
}
-/**
- * Translate TGSI fragment shader into i915 hardware instructions.
- * \param p the translation state
- * \param tokens the TGSI token array
- */
-static void
-i915_translate_instructions(struct i915_fp_compile *p,
- const struct tgsi_token *tokens,
- struct i915_fragment_shader *fs)
+static void i915_translate_token(struct i915_fp_compile *p,
+ const union i915_full_token* token,
+ struct i915_fragment_shader *fs)
{
struct i915_fragment_shader *ifs = p->shader;
- struct tgsi_parse_context parse;
-
- tgsi_parse_init( &parse, tokens );
-
- while( !tgsi_parse_end_of_tokens( &parse ) ) {
-
- tgsi_parse_token( &parse );
+ switch( token->Token.Type ) {
+ case TGSI_TOKEN_TYPE_PROPERTY:
+ /*
+ * We only support one cbuf, but we still need to ignore the property
+ * correctly so we don't hit the assert at the end of the switch case.
+ */
+ assert(token->FullProperty.Property.PropertyName ==
+ TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS);
+ break;
- switch( parse.FullToken.Token.Type ) {
- case TGSI_TOKEN_TYPE_PROPERTY:
- /*
- * We only support one cbuf, but we still need to ignore the property
- * correctly so we don't hit the assert at the end of the switch case.
- */
- assert(parse.FullToken.FullProperty.Property.PropertyName ==
- TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS);
- break;
- case TGSI_TOKEN_TYPE_DECLARATION:
- if (parse.FullToken.FullDeclaration.Declaration.File
- == TGSI_FILE_CONSTANT) {
- uint i;
- for (i = parse.FullToken.FullDeclaration.Range.First;
- i <= parse.FullToken.FullDeclaration.Range.Last;
- i++) {
- assert(ifs->constant_flags[i] == 0x0);
- ifs->constant_flags[i] = I915_CONSTFLAG_USER;
- ifs->num_constants = MAX2(ifs->num_constants, i + 1);
- }
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ if (token->FullDeclaration.Declaration.File
+ == TGSI_FILE_CONSTANT) {
+ uint i;
+ for (i = token->FullDeclaration.Range.First;
+ i <= token->FullDeclaration.Range.Last;
+ i++) {
+ assert(ifs->constant_flags[i] == 0x0);
+ ifs->constant_flags[i] = I915_CONSTFLAG_USER;
+ ifs->num_constants = MAX2(ifs->num_constants, i + 1);
}
- else if (parse.FullToken.FullDeclaration.Declaration.File
- == TGSI_FILE_TEMPORARY) {
- uint i;
- for (i = parse.FullToken.FullDeclaration.Range.First;
- i <= parse.FullToken.FullDeclaration.Range.Last;
- i++) {
- assert(i < I915_MAX_TEMPORARY);
+ }
+ else if (token->FullDeclaration.Declaration.File
+ == TGSI_FILE_TEMPORARY) {
+ uint i;
+ for (i = token->FullDeclaration.Range.First;
+ i <= token->FullDeclaration.Range.Last;
+ i++) {
+ if (i >= I915_MAX_TEMPORARY)
+ debug_printf("Too many temps (%d)\n",i);
+ else
/* XXX just use shader->info->file_mask[TGSI_FILE_TEMPORARY] */
p->temp_flag |= (1 << i); /* mark temp as used */
- }
}
- break;
+ }
+ break;
- case TGSI_TOKEN_TYPE_IMMEDIATE:
- {
- const struct tgsi_full_immediate *imm
- = &parse.FullToken.FullImmediate;
- const uint pos = p->num_immediates++;
- uint j;
- assert( imm->Immediate.NrTokens <= 4 + 1 );
- for (j = 0; j < imm->Immediate.NrTokens - 1; j++) {
- p->immediates[pos][j] = imm->u[j].Float;
- }
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ const struct tgsi_full_immediate *imm
+ = &token->FullImmediate;
+ const uint pos = p->num_immediates++;
+ uint j;
+ assert( imm->Immediate.NrTokens <= 4 + 1 );
+ for (j = 0; j < imm->Immediate.NrTokens - 1; j++) {
+ p->immediates[pos][j] = imm->u[j].Float;
}
- break;
+ }
+ break;
- case TGSI_TOKEN_TYPE_INSTRUCTION:
- if (p->first_instruction) {
- /* resolve location of immediates */
- uint i, j;
- for (i = 0; i < p->num_immediates; i++) {
- /* find constant slot for this immediate */
- for (j = 0; j < I915_MAX_CONSTANT; j++) {
- if (ifs->constant_flags[j] == 0x0) {
- memcpy(ifs->constants[j],
- p->immediates[i],
- 4 * sizeof(float));
- /*printf("immediate %d maps to const %d\n", i, j);*/
- ifs->constant_flags[j] = 0xf; /* all four comps used */
- p->immediates_map[i] = j;
- ifs->num_constants = MAX2(ifs->num_constants, j + 1);
- break;
- }
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ if (p->first_instruction) {
+ /* resolve location of immediates */
+ uint i, j;
+ for (i = 0; i < p->num_immediates; i++) {
+ /* find constant slot for this immediate */
+ for (j = 0; j < I915_MAX_CONSTANT; j++) {
+ if (ifs->constant_flags[j] == 0x0) {
+ memcpy(ifs->constants[j],
+ p->immediates[i],
+ 4 * sizeof(float));
+ /*printf("immediate %d maps to const %d\n", i, j);*/
+ ifs->constant_flags[j] = 0xf; /* all four comps used */
+ p->immediates_map[i] = j;
+ ifs->num_constants = MAX2(ifs->num_constants, j + 1);
+ break;
}
}
-
- p->first_instruction = FALSE;
}
- i915_translate_instruction(p, &parse.FullToken.FullInstruction, fs);
- break;
-
- default:
- assert( 0 );
+ p->first_instruction = FALSE;
}
- } /* while */
+ i915_translate_instruction(p, &token->FullInstruction, fs);
+ break;
+
+ default:
+ assert( 0 );
+ }
- tgsi_parse_free (&parse);
+}
+
+/**
+ * Translate TGSI fragment shader into i915 hardware instructions.
+ * \param p the translation state
+ * \param tokens the TGSI token array
+ */
+static void
+i915_translate_instructions(struct i915_fp_compile *p,
+ const struct i915_token_list *tokens,
+ struct i915_fragment_shader *fs)
+{
+ int i;
+ for(i = 0; i<tokens->NumTokens; i++) {
+ i915_translate_token(p, &tokens->Tokens[i], fs);
+ }
}
ifs->num_constants = 0;
memset(ifs->constant_flags, 0, sizeof(ifs->constant_flags));
+ memset(&p->register_phases, 0, sizeof(p->register_phases));
+
for (i = 0; i < I915_TEX_UNITS; i++)
ifs->generic_mapping[i] = -1;
unsigned long decl_size = (unsigned long) (p->decl - p->declarations);
if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT)
- i915_program_error(p, "Exceeded max nr indirect texture lookups");
+ debug_printf("Exceeded max nr indirect texture lookups\n");
if (p->nr_tex_insn > I915_MAX_TEX_INSN)
i915_program_error(p, "Exceeded max TEX instructions");
/* Copy compilation results to fragment program struct:
*/
+ assert(!ifs->decl);
assert(!ifs->program);
+
+ ifs->decl
+ = (uint *) MALLOC(decl_size * sizeof(uint));
ifs->program
- = (uint *) MALLOC((program_size + decl_size) * sizeof(uint));
- if (ifs->program) {
- ifs->program_len = program_size + decl_size;
+ = (uint *) MALLOC(program_size * sizeof(uint));
- memcpy(ifs->program,
- p->declarations,
+ if (ifs->decl) {
+ ifs->decl_len = decl_size;
+
+ memcpy(ifs->decl,
+ p->declarations,
decl_size * sizeof(uint));
+ }
- memcpy(ifs->program + decl_size,
- p->program,
+ if (ifs->program) {
+ ifs->program_len = program_size;
+
+ memcpy(ifs->program,
+ p->program,
program_size * sizeof(uint));
}
}
{
struct i915_fp_compile *p;
const struct tgsi_token *tokens = fs->state.tokens;
+ struct i915_token_list* i_tokens;
#if 0
tgsi_dump(tokens, 0);
p = i915_init_compile(i915, fs);
- i915_translate_instructions(p, tokens, fs);
+ i_tokens = i915_optimize(tokens);
+ i915_translate_instructions(p, i_tokens, fs);
i915_fixup_depth_write(p);
i915_fini_compile(i915, p);
+ i915_optimize_free(i_tokens);
+
+#if 0
+ i915_disassemble_program(NULL, fs->program, fs->program_len);
+#endif
}