965: remove complex compiler for simple fragment programs.

Keep the simple compiler for complex fragment programs...
This commit is contained in:
Keith Whitwell 2007-12-12 20:07:35 +00:00
parent ea7c533d40
commit 06036bc8c4
6 changed files with 0 additions and 2545 deletions

View file

@ -45,14 +45,8 @@ DRIVER_SOURCES = \
brw_vs_state.c \
brw_vtbl.c \
brw_wm.c \
brw_wm_debug.c \
brw_wm_emit.c \
brw_wm_fp.c \
brw_wm_iz.c \
brw_wm_glsl.c \
brw_wm_pass0.c \
brw_wm_pass1.c \
brw_wm_pass2.c \
brw_wm_sampler_state.c \
brw_wm_state.c \
brw_wm_surface_state.c

View file

@ -1,172 +0,0 @@
/*
Copyright (C) Intel Corp. 2006. All Rights Reserved.
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
develop this 3D driver.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "brw_context.h"
#include "brw_wm.h"
#if 0
void brw_wm_print_value( struct brw_wm_compile *c,
struct brw_wm_value *value )
{
assert(value);
if (c->state >= PASS2_DONE)
brw_print_reg(value->hw_reg);
else if( value == &c->undef_value )
_mesa_printf("undef");
else if( value - c->vreg >= 0 &&
value - c->vreg < BRW_WM_MAX_VREG)
_mesa_printf("r%d", value - c->vreg);
else if (value - c->creg >= 0 &&
value - c->creg < BRW_WM_MAX_PARAM)
_mesa_printf("c%d", value - c->creg);
else if (value - c->payload.input_interp >= 0 &&
value - c->payload.input_interp < FRAG_ATTRIB_MAX)
_mesa_printf("i%d", value - c->payload.input_interp);
else if (value - c->payload.depth >= 0 &&
value - c->payload.depth < FRAG_ATTRIB_MAX)
_mesa_printf("d%d", value - c->payload.depth);
else
_mesa_printf("?");
}
void brw_wm_print_ref( struct brw_wm_compile *c,
struct brw_wm_ref *ref )
{
struct brw_reg hw_reg = ref->hw_reg;
if (ref->unspill_reg)
_mesa_printf("UNSPILL(%x)/", ref->value->spill_slot);
if (c->state >= PASS2_DONE)
brw_print_reg(ref->hw_reg);
else {
_mesa_printf("%s", hw_reg.negate ? "-" : "");
_mesa_printf("%s", hw_reg.abs ? "abs/" : "");
brw_wm_print_value(c, ref->value);
if ((hw_reg.nr&1) || hw_reg.subnr) {
_mesa_printf("->%d.%d", (hw_reg.nr&1), hw_reg.subnr);
}
}
}
void brw_wm_print_insn( struct brw_wm_compile *c,
struct brw_wm_instruction *inst )
{
unsigned i, arg;
unsigned nr_args = brw_wm_nr_args(inst->opcode);
_mesa_printf("[");
for (i = 0; i < 4; i++) {
if (inst->dst[i]) {
brw_wm_print_value(c, inst->dst[i]);
if (inst->dst[i]->spill_slot)
_mesa_printf("/SPILL(%x)",inst->dst[i]->spill_slot);
}
else
_mesa_printf("#");
if (i < 3)
_mesa_printf(",");
}
_mesa_printf("]");
if (inst->writemask != WRITEMASK_XYZW)
_mesa_printf(".%s%s%s%s",
GET_BIT(inst->writemask, 0) ? "x" : "",
GET_BIT(inst->writemask, 1) ? "y" : "",
GET_BIT(inst->writemask, 2) ? "z" : "",
GET_BIT(inst->writemask, 3) ? "w" : "");
switch (inst->opcode) {
case WM_PIXELXY:
_mesa_printf(" = PIXELXY");
break;
case WM_DELTAXY:
_mesa_printf(" = DELTAXY");
break;
case WM_PIXELW:
_mesa_printf(" = PIXELW");
break;
case WM_WPOSXY:
_mesa_printf(" = WPOSXY");
break;
case WM_PINTERP:
_mesa_printf(" = PINTERP");
break;
case WM_LINTERP:
_mesa_printf(" = LINTERP");
break;
case WM_CINTERP:
_mesa_printf(" = CINTERP");
break;
case WM_FB_WRITE:
_mesa_printf(" = FB_WRITE");
break;
default:
_mesa_printf(" = %s", _mesa_opcode_string(inst->opcode));
break;
}
if (inst->saturate)
_mesa_printf("_SAT");
for (arg = 0; arg < nr_args; arg++) {
_mesa_printf(" [");
for (i = 0; i < 4; i++) {
if (inst->src[arg][i]) {
brw_wm_print_ref(c, inst->src[arg][i]);
}
else
_mesa_printf("%%");
if (i < 3)
_mesa_printf(",");
else
_mesa_printf("]");
}
}
_mesa_printf("\n");
}
void brw_wm_print_program( struct brw_wm_compile *c,
const char *stage )
{
unsigned insn;
_mesa_printf("\n\n\n%s:\n", stage);
for (insn = 0; insn < c->nr_insns; insn++)
brw_wm_print_insn(c, &c->instruction[insn]);
_mesa_printf("\n\n\n");
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,466 +0,0 @@
/*
Copyright (C) Intel Corp. 2006. All Rights Reserved.
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
develop this 3D driver.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "brw_context.h"
#include "brw_wm.h"
#if 0
/***********************************************************************
*/
static struct brw_wm_ref *get_ref( struct brw_wm_compile *c )
{
assert(c->nr_refs < BRW_WM_MAX_REF);
return &c->refs[c->nr_refs++];
}
static struct brw_wm_value *get_value( struct brw_wm_compile *c)
{
assert(c->nr_refs < BRW_WM_MAX_VREG);
return &c->vreg[c->nr_vreg++];
}
static struct brw_wm_instruction *get_instruction( struct brw_wm_compile *c )
{
assert(c->nr_insns < BRW_WM_MAX_INSN);
return &c->instruction[c->nr_insns++];
}
/***********************************************************************
*/
static void pass0_init_undef( struct brw_wm_compile *c)
{
struct brw_wm_ref *ref = &c->undef_ref;
ref->value = &c->undef_value;
ref->hw_reg = brw_vec8_grf(0, 0);
ref->insn = 0;
ref->prevuse = NULL;
}
static void pass0_set_fpreg_value( struct brw_wm_compile *c,
unsigned file,
unsigned idx,
unsigned component,
struct brw_wm_value *value )
{
struct brw_wm_ref *ref = get_ref(c);
ref->value = value;
ref->hw_reg = brw_vec8_grf(0, 0);
ref->insn = 0;
ref->prevuse = NULL;
c->pass0_fp_reg[file][idx][component] = ref;
}
static void pass0_set_fpreg_ref( struct brw_wm_compile *c,
unsigned file,
unsigned idx,
unsigned component,
const struct brw_wm_ref *src_ref )
{
c->pass0_fp_reg[file][idx][component] = src_ref;
}
static const struct brw_wm_ref *get_param_ref( struct brw_wm_compile *c,
const float *param_ptr )
{
unsigned i = c->prog_data.nr_params++;
if (i >= BRW_WM_MAX_PARAM) {
_mesa_printf("%s: out of params\n", __FUNCTION__);
c->prog_data.error = 1;
return NULL;
}
else {
struct brw_wm_ref *ref = get_ref(c);
c->prog_data.param[i] = param_ptr;
c->nr_creg = (i+16)/16;
/* Push the offsets into hw_reg. These will be added to the
* real register numbers once one is allocated in pass2.
*/
ref->hw_reg = brw_vec1_grf((i&8)?1:0, i%8);
ref->value = &c->creg[i/16];
ref->insn = 0;
ref->prevuse = NULL;
return ref;
}
}
static const struct brw_wm_ref *get_const_ref( struct brw_wm_compile *c,
const float *constval )
{
unsigned i;
/* Search for an existing const value matching the request:
*/
for (i = 0; i < c->nr_constrefs; i++) {
if (c->constref[i].constval == *constval)
return c->constref[i].ref;
}
/* Else try to add a new one:
*/
if (c->nr_constrefs < BRW_WM_MAX_CONST) {
unsigned i = c->nr_constrefs++;
/* A constant is a special type of parameter:
*/
c->constref[i].constval = *constval;
c->constref[i].ref = get_param_ref(c, constval);
return c->constref[i].ref;
}
else {
_mesa_printf("%s: out of constrefs\n", __FUNCTION__);
c->prog_data.error = 1;
return NULL;
}
}
/* Lookup our internal registers
*/
static const struct brw_wm_ref *pass0_get_reg( struct brw_wm_compile *c,
unsigned file,
unsigned idx,
unsigned component )
{
const struct brw_wm_ref *ref = c->pass0_fp_reg[file][idx][component];
if (!ref) {
switch (file) {
case PROGRAM_INPUT:
case PROGRAM_PAYLOAD:
case PROGRAM_TEMPORARY:
case PROGRAM_OUTPUT:
case PROGRAM_VARYING:
break;
case PROGRAM_LOCAL_PARAM:
ref = get_param_ref(c, &c->fp->program.Base.LocalParams[idx][component]);
break;
case PROGRAM_ENV_PARAM:
ref = get_param_ref(c, &c->env_param[idx][component]);
break;
case PROGRAM_STATE_VAR:
case PROGRAM_UNIFORM:
case PROGRAM_CONSTANT:
case PROGRAM_NAMED_PARAM: {
struct gl_program_parameter_list *plist = c->fp->program.Base.Parameters;
/* There's something really hokey about parameters parsed in
* arb programs - they all end up in here, whether they be
* state values, paramters or constants. This duplicates the
* structure above & also seems to subvert the limits set for
* each type of constant/param.
*/
switch (plist->Parameters[idx].Type) {
case PROGRAM_NAMED_PARAM:
case PROGRAM_CONSTANT:
/* These are invarient:
*/
ref = get_const_ref(c, &plist->ParameterValues[idx][component]);
break;
case PROGRAM_STATE_VAR:
case PROGRAM_UNIFORM:
/* These may change from run to run:
*/
ref = get_param_ref(c, &plist->ParameterValues[idx][component] );
break;
default:
assert(0);
break;
}
break;
}
default:
assert(0);
break;
}
c->pass0_fp_reg[file][idx][component] = ref;
}
if (!ref)
ref = &c->undef_ref;
return ref;
}
/***********************************************************************
* Straight translation to internal instruction format
*/
static void pass0_set_dst( struct brw_wm_compile *c,
struct brw_wm_instruction *out,
const struct prog_instruction *inst,
unsigned writemask )
{
const struct prog_dst_register *dst = &inst->DstReg;
unsigned i;
for (i = 0; i < 4; i++) {
if (writemask & (1<<i)) {
out->dst[i] = get_value(c);
pass0_set_fpreg_value(c, dst->File, dst->Index, i, out->dst[i]);
}
}
out->writemask = writemask;
}
static void pass0_set_dst_scalar( struct brw_wm_compile *c,
struct brw_wm_instruction *out,
const struct prog_instruction *inst,
unsigned writemask )
{
if (writemask) {
const struct prog_dst_register *dst = &inst->DstReg;
unsigned i;
/* Compute only the first (X) value:
*/
out->writemask = WRITEMASK_X;
out->dst[0] = get_value(c);
/* Update our tracking register file for all the components in
* writemask:
*/
for (i = 0; i < 4; i++) {
if (writemask & (1<<i)) {
pass0_set_fpreg_value(c, dst->File, dst->Index, i, out->dst[0]);
}
}
}
else
out->writemask = 0;
}
static const struct brw_wm_ref *get_fp_src_reg_ref( struct brw_wm_compile *c,
struct prog_src_register src,
unsigned i )
{
unsigned component = GET_SWZ(src.Swizzle,i);
const struct brw_wm_ref *src_ref;
static const float const_zero = 0.0;
static const float const_one = 1.0;
if (component == SWIZZLE_ZERO)
src_ref = get_const_ref(c, &const_zero);
else if (component == SWIZZLE_ONE)
src_ref = get_const_ref(c, &const_one);
else
src_ref = pass0_get_reg(c, src.File, src.Index, component);
return src_ref;
}
static struct brw_wm_ref *get_new_ref( struct brw_wm_compile *c,
struct prog_src_register src,
unsigned i,
struct brw_wm_instruction *insn)
{
const struct brw_wm_ref *ref = get_fp_src_reg_ref(c, src, i);
struct brw_wm_ref *newref = get_ref(c);
newref->value = ref->value;
newref->hw_reg = ref->hw_reg;
if (insn) {
newref->insn = insn - c->instruction;
newref->prevuse = newref->value->lastuse;
newref->value->lastuse = newref;
}
if (src.NegateBase & (1<<i))
newref->hw_reg.negate ^= 1;
if (src.Abs) {
newref->hw_reg.negate = 0;
newref->hw_reg.abs = 1;
}
return newref;
}
static struct brw_wm_instruction *translate_insn( struct brw_wm_compile *c,
const struct prog_instruction *inst )
{
struct brw_wm_instruction *out = get_instruction(c);
unsigned writemask = inst->DstReg.WriteMask;
unsigned nr_args = brw_wm_nr_args(inst->Opcode);
unsigned i, j;
/* Copy some data out of the instruction
*/
out->opcode = inst->Opcode;
out->saturate = (inst->SaturateMode != SATURATE_OFF);
out->tex_unit = inst->TexSrcUnit;
out->tex_idx = inst->TexSrcTarget;
/* Args:
*/
for (i = 0; i < nr_args; i++) {
for (j = 0; j < 4; j++) {
out->src[i][j] = get_new_ref(c, inst->SrcReg[i], j, out);
}
}
/* Dst:
*/
if (brw_wm_is_scalar_result(out->opcode))
pass0_set_dst_scalar(c, out, inst, writemask);
else
pass0_set_dst(c, out, inst, writemask);
return out;
}
/***********************************************************************
* Optimize moves and swizzles away:
*/
static void pass0_precalc_mov( struct brw_wm_compile *c,
const struct prog_instruction *inst )
{
const struct prog_dst_register *dst = &inst->DstReg;
unsigned writemask = inst->DstReg.WriteMask;
unsigned i;
/* Get the effect of a MOV by manipulating our register table:
*/
for (i = 0; i < 4; i++) {
if (writemask & (1<<i)) {
pass0_set_fpreg_ref( c, dst->File, dst->Index, i,
get_new_ref(c, inst->SrcReg[0], i, NULL));
}
}
}
/* Initialize payload "registers".
*/
static void pass0_init_payload( struct brw_wm_compile *c )
{
unsigned i;
for (i = 0; i < 4; i++) {
unsigned j = i >= c->key.nr_depth_regs ? 0 : i;
pass0_set_fpreg_value( c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, i,
&c->payload.depth[j] );
}
#if 0
/* This seems to be an alternative to the INTERP_WPOS stuff I do
* elsewhere:
*/
if (c->key.source_depth_reg)
pass0_set_fpreg_value(c, PROGRAM_INPUT, FRAG_ATTRIB_WPOS, 2,
&c->payload.depth[c->key.source_depth_reg/2]);
#endif
for (i = 0; i < FRAG_ATTRIB_MAX; i++)
pass0_set_fpreg_value( c, PROGRAM_PAYLOAD, i, 0,
&c->payload.input_interp[i] );
}
/***********************************************************************
* PASS 0
*
* Work forwards to give each calculated value a unique number. Where
* an instruction produces duplicate values (eg DP3), all are given
* the same number.
*
* Translate away swizzling and eliminate non-saturating moves.
*/
void brw_wm_pass0( struct brw_wm_compile *c )
{
unsigned insn;
c->nr_vreg = 0;
c->nr_insns = 0;
pass0_init_undef(c);
pass0_init_payload(c);
for (insn = 0; insn < c->nr_fp_insns; insn++) {
const struct prog_instruction *inst = &c->prog_instructions[insn];
/* Optimize away moves, otherwise emit translated instruction:
*/
switch (inst->Opcode) {
case OPCODE_MOV:
case OPCODE_SWZ:
if (!inst->SaturateMode) {
pass0_precalc_mov(c, inst);
}
else {
translate_insn(c, inst);
}
break;
default:
translate_insn(c, inst);
break;
}
}
if (BRW_DEBUG & DEBUG_WM) {
brw_wm_print_program(c, "pass0");
}
}
#endif

View file

@ -1,277 +0,0 @@
/*
Copyright (C) Intel Corp. 2006. All Rights Reserved.
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
develop this 3D driver.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "brw_context.h"
#include "brw_wm.h"
#if 0
static unsigned get_tracked_mask(struct brw_wm_compile *c,
struct brw_wm_instruction *inst)
{
unsigned i;
for (i = 0; i < 4; i++) {
if (inst->writemask & (1<<i)) {
if (!inst->dst[i]->contributes_to_output) {
inst->writemask &= ~(1<<i);
inst->dst[i] = 0;
}
}
}
return inst->writemask;
}
/* Remove a reference from a value's usage chain.
*/
static void unlink_ref(struct brw_wm_ref *ref)
{
struct brw_wm_value *value = ref->value;
if (ref == value->lastuse) {
value->lastuse = ref->prevuse;
} else {
struct brw_wm_ref *i = value->lastuse;
while (i->prevuse != ref) i = i->prevuse;
i->prevuse = ref->prevuse;
}
}
static void track_arg(struct brw_wm_compile *c,
struct brw_wm_instruction *inst,
unsigned arg,
unsigned readmask)
{
unsigned i;
for (i = 0; i < 4; i++) {
struct brw_wm_ref *ref = inst->src[arg][i];
if (ref) {
if (readmask & (1<<i))
ref->value->contributes_to_output = 1;
else {
unlink_ref(ref);
inst->src[arg][i] = NULL;
}
}
}
}
static unsigned get_texcoord_mask( unsigned tex_idx )
{
switch (tex_idx) {
case TEXTURE_1D_INDEX: return WRITEMASK_X;
case TEXTURE_2D_INDEX: return WRITEMASK_XY;
case TEXTURE_3D_INDEX: return WRITEMASK_XYZ;
case TEXTURE_CUBE_INDEX: return WRITEMASK_XYZ;
case TEXTURE_RECT_INDEX: return WRITEMASK_XY;
default: return 0;
}
}
/* Step two: Basically this is dead code elimination.
*
* Iterate backwards over instructions, noting which values
* contribute to the final result. Adjust writemasks to only
* calculate these values.
*/
void brw_wm_pass1( struct brw_wm_compile *c )
{
int insn;
for (insn = c->nr_insns-1; insn >= 0; insn--) {
struct brw_wm_instruction *inst = &c->instruction[insn];
unsigned writemask;
unsigned read0, read1, read2;
if (inst->opcode == OPCODE_KIL) {
track_arg(c, inst, 0, WRITEMASK_XYZW); /* All args contribute to final */
continue;
}
if (inst->opcode == WM_FB_WRITE) {
track_arg(c, inst, 0, WRITEMASK_XYZW);
track_arg(c, inst, 1, WRITEMASK_XYZW);
if (c->key.source_depth_to_render_target &&
c->key.computes_depth)
track_arg(c, inst, 2, WRITEMASK_Z);
else
track_arg(c, inst, 2, 0);
continue;
}
/* Lookup all the registers which were written by this
* instruction and get a mask of those that contribute to the output:
*/
writemask = get_tracked_mask(c, inst);
if (!writemask) {
unsigned arg;
for (arg = 0; arg < 3; arg++)
track_arg(c, inst, arg, 0);
continue;
}
read0 = 0;
read1 = 0;
read2 = 0;
/* Mark all inputs which contribute to the marked outputs:
*/
switch (inst->opcode) {
case OPCODE_ABS:
case OPCODE_FLR:
case OPCODE_FRC:
case OPCODE_MOV:
read0 = writemask;
break;
case OPCODE_SUB:
case OPCODE_SLT:
case OPCODE_SLE:
case OPCODE_SGE:
case OPCODE_SGT:
case OPCODE_SEQ:
case OPCODE_SNE:
case OPCODE_ADD:
case OPCODE_MAX:
case OPCODE_MIN:
case OPCODE_MUL:
read0 = writemask;
read1 = writemask;
break;
case OPCODE_MAD:
case OPCODE_CMP:
case OPCODE_LRP:
read0 = writemask;
read1 = writemask;
read2 = writemask;
break;
case OPCODE_XPD:
if (writemask & WRITEMASK_X) read0 |= WRITEMASK_YZ;
if (writemask & WRITEMASK_Y) read0 |= WRITEMASK_XZ;
if (writemask & WRITEMASK_Z) read0 |= WRITEMASK_XY;
read1 = read0;
break;
case OPCODE_COS:
case OPCODE_EX2:
case OPCODE_LG2:
case OPCODE_RCP:
case OPCODE_RSQ:
case OPCODE_SIN:
case OPCODE_SCS:
case WM_CINTERP:
case WM_PIXELXY:
read0 = WRITEMASK_X;
break;
case OPCODE_POW:
read0 = WRITEMASK_X;
read1 = WRITEMASK_X;
break;
case OPCODE_TEX:
read0 = get_texcoord_mask(inst->tex_idx);
if (c->key.shadowtex_mask & (1<<inst->tex_unit))
read0 |= WRITEMASK_Z;
break;
case OPCODE_TXB:
/* Shadow ignored for txb.
*/
read0 = get_texcoord_mask(inst->tex_idx) | WRITEMASK_W;
break;
case WM_WPOSXY:
read0 = writemask & WRITEMASK_XY;
break;
case WM_DELTAXY:
read0 = writemask & WRITEMASK_XY;
read1 = WRITEMASK_X;
break;
case WM_PIXELW:
read0 = WRITEMASK_X;
read1 = WRITEMASK_XY;
break;
case WM_LINTERP:
read0 = WRITEMASK_X;
read1 = WRITEMASK_XY;
break;
case WM_PINTERP:
read0 = WRITEMASK_X; /* interpolant */
read1 = WRITEMASK_XY; /* deltas */
read2 = WRITEMASK_W; /* pixel w */
break;
case OPCODE_DP3:
read0 = WRITEMASK_XYZ;
read1 = WRITEMASK_XYZ;
break;
case OPCODE_DPH:
read0 = WRITEMASK_XYZ;
read1 = WRITEMASK_XYZW;
break;
case OPCODE_DP4:
read0 = WRITEMASK_XYZW;
read1 = WRITEMASK_XYZW;
break;
case OPCODE_LIT:
read0 = WRITEMASK_XYW;
break;
case OPCODE_SWZ:
case OPCODE_DST:
case OPCODE_TXP:
default:
break;
}
track_arg(c, inst, 0, read0);
track_arg(c, inst, 1, read1);
track_arg(c, inst, 2, read2);
}
if (BRW_DEBUG & DEBUG_WM) {
brw_wm_print_program(c, "pass1");
}
}
#endif

View file

@ -1,335 +0,0 @@
/*
Copyright (C) Intel Corp. 2006. All Rights Reserved.
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
develop this 3D driver.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "brw_context.h"
#include "brw_wm.h"
#if 0
/* Use these to force spilling so that that functionality can be
* tested with known-good examples rather than having to construct new
* tests.
*/
#define TEST_PAYLOAD_SPILLS 0
#define TEST_DST_SPILLS 0
static void spill_value(struct brw_wm_compile *c,
struct brw_wm_value *value);
static void prealloc_reg(struct brw_wm_compile *c,
struct brw_wm_value *value,
unsigned reg)
{
if (value->lastuse) {
/* Set nextuse to zero, it will be corrected by
* update_register_usage().
*/
c->pass2_grf[reg].value = value;
c->pass2_grf[reg].nextuse = 0;
value->resident = &c->pass2_grf[reg];
value->hw_reg = brw_vec8_grf(reg*2, 0);
if (TEST_PAYLOAD_SPILLS)
spill_value(c, value);
}
}
/* Initialize all the register values. Do the initial setup
* calculations for interpolants.
*/
static void init_registers( struct brw_wm_compile *c )
{
unsigned inputs = FRAG_BIT_WPOS | c->fp_interp_emitted;
unsigned nr_interp_regs = 0;
unsigned i = 0;
unsigned j;
for (j = 0; j < c->grf_limit; j++)
c->pass2_grf[j].nextuse = BRW_WM_MAX_INSN;
for (j = 0; j < c->key.nr_depth_regs; j++)
prealloc_reg(c, &c->payload.depth[j], i++);
for (j = 0; j < c->nr_creg; j++)
prealloc_reg(c, &c->creg[j], i++);
for (j = 0; j < FRAG_ATTRIB_MAX; j++)
if (inputs & (1<<j)) {
nr_interp_regs++;
prealloc_reg(c, &c->payload.input_interp[j], i++);
}
assert(nr_interp_regs >= 1);
c->prog_data.first_curbe_grf = c->key.nr_depth_regs * 2;
c->prog_data.urb_read_length = nr_interp_regs * 2;
c->prog_data.curb_read_length = c->nr_creg * 2;
c->max_wm_grf = i * 2;
}
/* Update the nextuse value for each register in our file.
*/
static void update_register_usage(struct brw_wm_compile *c,
unsigned thisinsn)
{
unsigned i;
for (i = 1; i < c->grf_limit; i++) {
struct brw_wm_grf *grf = &c->pass2_grf[i];
/* Only search those which can change:
*/
if (grf->nextuse < thisinsn) {
struct brw_wm_ref *ref = grf->value->lastuse;
/* Has last use of value been passed?
*/
if (ref->insn < thisinsn) {
grf->value->resident = 0;
grf->value = 0;
grf->nextuse = BRW_WM_MAX_INSN;
}
else {
/* Else loop through chain to update:
*/
while (ref->prevuse && ref->prevuse->insn >= thisinsn)
ref = ref->prevuse;
grf->nextuse = ref->insn;
}
}
}
}
static void spill_value(struct brw_wm_compile *c,
struct brw_wm_value *value)
{
/* Allocate a spill slot. Note that allocations start from 0x40 -
* the first slot is reserved to mean "undef" in brw_wm_emit.c
*/
if (!value->spill_slot) {
c->last_scratch += 0x40;
value->spill_slot = c->last_scratch;
}
/* The spill will be done in brw_wm_emit.c immediately after the
* value is calculated, so we can just take this reg without any
* further work.
*/
value->resident->value = NULL;
value->resident->nextuse = BRW_WM_MAX_INSN;
value->resident = NULL;
}
/* Search for contiguous region with the most distant nearest
* member. Free regs count as very distant.
*
* TODO: implement spill-to-reg so that we can rearrange discontigous
* free regs and then spill the oldest non-free regs in sequence.
* This would mean inserting instructions in this pass.
*/
static unsigned search_contiguous_regs(struct brw_wm_compile *c,
unsigned nr,
unsigned thisinsn)
{
struct brw_wm_grf *grf = c->pass2_grf;
unsigned furthest = 0;
unsigned reg = 0;
unsigned i, j;
/* Start search at 1: r0 is special and can't be used or spilled.
*/
for (i = 1; i < c->grf_limit && furthest < BRW_WM_MAX_INSN; i++) {
unsigned group_nextuse = BRW_WM_MAX_INSN;
for (j = 0; j < nr; j++) {
if (grf[i+j].nextuse < group_nextuse)
group_nextuse = grf[i+j].nextuse;
}
if (group_nextuse > furthest) {
furthest = group_nextuse;
reg = i;
}
}
assert(furthest != thisinsn);
/* Any non-empty regs will need to be spilled:
*/
for (j = 0; j < nr; j++)
if (grf[reg+j].value)
spill_value(c, grf[reg+j].value);
return reg;
}
static void alloc_contiguous_dest(struct brw_wm_compile *c,
struct brw_wm_value *dst[],
unsigned nr,
unsigned thisinsn)
{
unsigned reg = search_contiguous_regs(c, nr, thisinsn);
unsigned i;
for (i = 0; i < nr; i++) {
if (!dst[i]) {
/* Need to grab a dummy value in TEX case. Don't introduce
* it into the tracking scheme.
*/
dst[i] = &c->vreg[c->nr_vreg++];
}
else {
assert(!dst[i]->resident);
assert(c->pass2_grf[reg+i].nextuse != thisinsn);
c->pass2_grf[reg+i].value = dst[i];
c->pass2_grf[reg+i].nextuse = thisinsn;
dst[i]->resident = &c->pass2_grf[reg+i];
}
dst[i]->hw_reg = brw_vec8_grf((reg+i)*2, 0);
}
if ((reg+nr)*2 > c->max_wm_grf)
c->max_wm_grf = (reg+nr) * 2;
}
static void load_args(struct brw_wm_compile *c,
struct brw_wm_instruction *inst)
{
unsigned thisinsn = inst - c->instruction;
unsigned i,j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++) {
struct brw_wm_ref *ref = inst->src[i][j];
if (ref) {
if (!ref->value->resident) {
/* Need to bring the value in from scratch space. The code for
* this will be done in brw_wm_emit.c, here we just do the
* register allocation and mark the ref as requiring a fill.
*/
unsigned reg = search_contiguous_regs(c, 1, thisinsn);
c->pass2_grf[reg].value = ref->value;
c->pass2_grf[reg].nextuse = thisinsn;
ref->value->resident = &c->pass2_grf[reg];
/* Note that a fill is required:
*/
ref->unspill_reg = reg*2;
}
/* Adjust the hw_reg to point at the value's current location:
*/
assert(ref->value == ref->value->resident->value);
ref->hw_reg.nr += (ref->value->resident - c->pass2_grf) * 2;
}
}
}
}
/* Step 3: Work forwards once again. Perform register allocations,
* taking into account instructions like TEX which require contiguous
* result registers. Where necessary spill registers to scratch space
* and reload later.
*/
void brw_wm_pass2( struct brw_wm_compile *c )
{
unsigned insn;
unsigned i;
init_registers(c);
for (insn = 0; insn < c->nr_insns; insn++) {
struct brw_wm_instruction *inst = &c->instruction[insn];
/* Update registers' nextuse values:
*/
update_register_usage(c, insn);
/* May need to unspill some args.
*/
load_args(c, inst);
/* Allocate registers to hold results:
*/
switch (inst->opcode) {
case OPCODE_TEX:
case OPCODE_TXB:
case OPCODE_TXP:
alloc_contiguous_dest(c, inst->dst, 4, insn);
break;
default:
for (i = 0; i < 4; i++) {
if (inst->writemask & (1<<i)) {
assert(inst->dst[i]);
alloc_contiguous_dest(c, &inst->dst[i], 1, insn);
}
}
break;
}
if (TEST_DST_SPILLS && inst->opcode != WM_PIXELXY)
for (i = 0; i < 4; i++)
if (inst->dst[i])
spill_value(c, inst->dst[i]);
}
if (BRW_DEBUG & DEBUG_WM) {
brw_wm_print_program(c, "pass2");
}
c->state = PASS2_DONE;
if (BRW_DEBUG & DEBUG_WM) {
brw_wm_print_program(c, "pass2/done");
}
}
#endif