i965: Remove the old ARB_fragment_program backend.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
Eric Anholt
2012-09-18 02:29:43 -07:00
parent 97615b2d8c
commit 098acf6c84
9 changed files with 0 additions and 4810 deletions

View File

@@ -74,13 +74,7 @@ i965_C_FILES = \
brw_vs_surface_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_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

@@ -39,52 +39,6 @@
#include "glsl/ralloc.h"
/** Return number of src args for given instruction */
GLuint brw_wm_nr_args( GLuint opcode )
{
switch (opcode) {
case WM_FRONTFACING:
case WM_PIXELXY:
return 0;
case WM_CINTERP:
case WM_WPOSXY:
case WM_DELTAXY:
return 1;
case WM_LINTERP:
case WM_PIXELW:
return 2;
case WM_FB_WRITE:
case WM_PINTERP:
return 3;
default:
assert(opcode < MAX_OPCODE);
return _mesa_num_inst_src_regs(opcode);
}
}
GLuint brw_wm_is_scalar_result( GLuint opcode )
{
switch (opcode) {
case OPCODE_COS:
case OPCODE_EX2:
case OPCODE_LG2:
case OPCODE_POW:
case OPCODE_RCP:
case OPCODE_RSQ:
case OPCODE_SIN:
case OPCODE_DP2:
case OPCODE_DP3:
case OPCODE_DP4:
case OPCODE_DPH:
case OPCODE_DST:
return 1;
default:
return 0;
}
}
/**
* Return a bitfield where bit n is set if barycentric interpolation mode n
* (see enum brw_wm_barycentric_interp_mode) is needed by the fragment shader.
@@ -273,15 +227,7 @@ bool do_wm_prog(struct brw_context *brw,
return false;
}
} else {
void *instruction = c->instruction;
void *prog_instructions = c->prog_instructions;
void *vreg = c->vreg;
void *refs = c->refs;
memset(c, 0, sizeof(*brw->wm.compile_data));
c->instruction = instruction;
c->prog_instructions = prog_instructions;
c->vreg = vreg;
c->refs = refs;
}
/* Allocate the references to the uniforms that will end up in the
@@ -308,7 +254,6 @@ bool do_wm_prog(struct brw_context *brw,
memcpy(&c->key, key, sizeof(*key));
c->fp = fp;
c->env_param = brw->intel.ctx.FragmentProgram.Parameters;
brw_init_compile(brw, &c->func, c);

View File

@@ -40,8 +40,6 @@
#include "brw_eu.h"
#include "brw_program.h"
#define SATURATE (1<<5)
/* A big lookup table is used to figure out which and how many
* additional regs will inserted before the main payload in the WM
* program execution. These mainly relate to depth and stencil
@@ -78,112 +76,6 @@ struct brw_wm_prog_key {
struct brw_sampler_prog_key_data tex;
};
/* A bit of a glossary:
*
* brw_wm_value: A computed value or program input. Values are
* constant, they are created once and are never modified. When a
* fragment program register is written or overwritten, new values are
* created fresh, preserving the rule that values are constant.
*
* brw_wm_ref: A reference to a value. Wherever a value used is by an
* instruction or as a program output, that is tracked with an
* instance of this struct. All references to a value occur after it
* is created. After the last reference, a value is dead and can be
* discarded.
*
* brw_wm_grf: Represents a physical hardware register. May be either
* empty or hold a value. Register allocation is the process of
* assigning values to grf registers. This occurs in pass2 and the
* brw_wm_grf struct is not used before that.
*
* Fragment program registers: These are time-varying constructs that
* are hard to reason about and which we translate away in pass0. A
* single fragment program register element (eg. temp[0].x) will be
* translated to one or more brw_wm_value structs, one for each time
* that temp[0].x is written to during the program.
*/
/* Used in pass2 to track register allocation.
*/
struct brw_wm_grf {
struct brw_wm_value *value;
GLuint nextuse;
};
struct brw_wm_value {
struct brw_reg hw_reg; /* emitted to this reg, may not always be there */
struct brw_wm_ref *lastuse;
struct brw_wm_grf *resident;
GLuint contributes_to_output:1;
GLuint spill_slot:16; /* if non-zero, spill immediately after calculation */
};
struct brw_wm_ref {
struct brw_reg hw_reg; /* nr filled in in pass2, everything else, pass0 */
struct brw_wm_value *value;
struct brw_wm_ref *prevuse;
GLuint unspill_reg:7; /* unspill to reg */
GLuint emitted:1;
GLuint insn:24;
};
struct brw_wm_constref {
const struct brw_wm_ref *ref;
GLfloat constval;
};
struct brw_wm_instruction {
struct brw_wm_value *dst[4];
struct brw_wm_ref *src[3][4];
GLuint opcode:8;
GLuint saturate:1;
GLuint writemask:4;
GLuint tex_unit:4; /* texture unit for TEX, TXD, TXP instructions */
GLuint tex_idx:4; /* TEXTURE_1D,2D,3D,CUBE,RECT_INDEX source target */
GLuint tex_shadow:1; /* do shadow comparison? */
GLuint eot:1; /* End of thread indicator for FB_WRITE*/
GLuint target:10; /* target binding table index for FB_WRITE*/
};
#define BRW_WM_MAX_INSN (MAX_PROGRAM_INSTRUCTIONS*3 + FRAG_ATTRIB_MAX + 3)
#define BRW_WM_MAX_GRF 128 /* hardware limit */
#define BRW_WM_MAX_VREG (BRW_WM_MAX_INSN * 4)
#define BRW_WM_MAX_REF (BRW_WM_MAX_INSN * 12)
#define BRW_WM_MAX_PARAM 256
#define BRW_WM_MAX_CONST 256
#define BRW_WM_MAX_SUBROUTINE 16
/* used in masks next to WRITEMASK_*. */
#define SATURATE (1<<5)
/* New opcodes to track internal operations required for WM unit.
* These are added early so that the registers used can be tracked,
* freed and reused like those of other instructions.
*/
#define WM_PIXELXY (MAX_OPCODE)
#define WM_DELTAXY (MAX_OPCODE + 1)
#define WM_PIXELW (MAX_OPCODE + 2)
#define WM_LINTERP (MAX_OPCODE + 3)
#define WM_PINTERP (MAX_OPCODE + 4)
#define WM_CINTERP (MAX_OPCODE + 5)
#define WM_WPOSXY (MAX_OPCODE + 6)
#define WM_FB_WRITE (MAX_OPCODE + 7)
#define WM_FRONTFACING (MAX_OPCODE + 8)
#define MAX_WM_OPCODE (MAX_OPCODE + 9)
#define PROGRAM_PAYLOAD (PROGRAM_FILE_MAX)
#define NUM_FILES (PROGRAM_PAYLOAD + 1)
#define PAYLOAD_DEPTH (FRAG_ATTRIB_MAX)
#define PAYLOAD_W (FRAG_ATTRIB_MAX + 1)
#define PAYLOAD_FP_REG_MAX (FRAG_ATTRIB_MAX + 2)
struct brw_wm_compile {
struct brw_compile func;
struct brw_wm_prog_key key;
@@ -191,13 +83,6 @@ struct brw_wm_compile {
struct brw_fragment_program *fp;
GLfloat (*env_param)[4];
enum {
START,
PASS2_DONE
} state;
uint8_t source_depth_reg;
uint8_t source_w_reg;
uint8_t aa_dest_stencil_reg;
@@ -208,266 +93,17 @@ struct brw_wm_compile {
GLuint source_depth_to_render_target:1;
GLuint runtime_check_aads_emit:1;
/* Initial pass - translate fp instructions to fp instructions,
* simplifying and adding instructions for interpolation and
* framebuffer writes.
*/
struct prog_instruction *prog_instructions;
GLuint nr_fp_insns;
GLuint fp_temp;
GLuint fp_interp_emitted;
struct prog_src_register pixel_xy;
struct prog_src_register delta_xy;
struct prog_src_register pixel_w;
struct brw_wm_value *vreg;
GLuint nr_vreg;
struct brw_wm_value creg[BRW_WM_MAX_PARAM];
GLuint nr_creg;
struct {
struct brw_wm_value depth[4]; /* includes r0/r1 */
struct brw_wm_value input_interp[FRAG_ATTRIB_MAX];
} payload;
const struct brw_wm_ref *pass0_fp_reg[NUM_FILES][256][4];
struct brw_wm_ref undef_ref;
struct brw_wm_value undef_value;
struct brw_wm_ref *refs;
GLuint nr_refs;
struct brw_wm_instruction *instruction;
GLuint nr_insns;
struct brw_wm_constref constref[BRW_WM_MAX_CONST];
GLuint nr_constrefs;
struct brw_wm_grf pass2_grf[BRW_WM_MAX_GRF/2];
GLuint grf_limit;
GLuint max_wm_grf;
GLuint last_scratch;
GLuint cur_inst; /**< index of current instruction */
bool out_of_regs; /**< ran out of GRF registers? */
/** Mapping from Mesa registers to hardware registers */
struct {
bool inited;
struct brw_reg reg;
} wm_regs[NUM_FILES][256][4];
bool used_grf[BRW_WM_MAX_GRF];
GLuint first_free_grf;
struct brw_reg stack;
struct brw_reg emit_mask_reg;
GLuint tmp_regs[BRW_WM_MAX_GRF];
GLuint tmp_index;
GLuint tmp_max;
GLuint subroutines[BRW_WM_MAX_SUBROUTINE];
GLuint dispatch_width;
/** we may need up to 3 constants per instruction (if use_const_buffer) */
struct {
GLint index;
struct brw_reg reg;
} current_const[3];
};
/** Bits for prog_instruction::Aux field */
#define INST_AUX_EOT 0x1
#define INST_AUX_TARGET(T) (T << 1)
#define INST_AUX_GET_TARGET(AUX) ((AUX) >> 1)
GLuint brw_wm_nr_args( GLuint opcode );
GLuint brw_wm_is_scalar_result( GLuint opcode );
void brw_wm_pass_fp( struct brw_wm_compile *c );
void brw_wm_pass0( struct brw_wm_compile *c );
void brw_wm_pass1( struct brw_wm_compile *c );
void brw_wm_pass2( struct brw_wm_compile *c );
void brw_wm_emit( struct brw_wm_compile *c );
bool brw_wm_arg_can_be_immediate(enum prog_opcode, int arg);
void brw_wm_print_value( struct brw_wm_compile *c,
struct brw_wm_value *value );
void brw_wm_print_ref( struct brw_wm_compile *c,
struct brw_wm_ref *ref );
void brw_wm_print_insn( struct brw_wm_compile *c,
struct brw_wm_instruction *inst );
void brw_wm_print_program( struct brw_wm_compile *c,
const char *stage );
void brw_wm_lookup_iz(struct intel_context *intel,
struct brw_wm_compile *c);
bool brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c,
struct gl_shader_program *prog);
/* brw_wm_emit.c */
void emit_alu1(struct brw_compile *p,
struct brw_instruction *(*func)(struct brw_compile *,
struct brw_reg,
struct brw_reg),
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0);
void emit_alu2(struct brw_compile *p,
struct brw_instruction *(*func)(struct brw_compile *,
struct brw_reg,
struct brw_reg,
struct brw_reg),
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *arg1);
void emit_cinterp(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0);
void emit_cmp(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *arg1,
const struct brw_reg *arg2);
void emit_ddxy(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
bool is_ddx,
const struct brw_reg *arg0,
bool negate_value);
void emit_delta_xy(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0);
void emit_dp2(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *arg1);
void emit_dp3(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *arg1);
void emit_dp4(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *arg1);
void emit_dph(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *arg1);
void emit_fb_write(struct brw_wm_compile *c,
struct brw_reg *arg0,
struct brw_reg *arg1,
struct brw_reg *arg2,
GLuint target,
GLuint eot);
void emit_frontfacing(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask);
void emit_linterp(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *deltas);
void emit_lrp(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *arg1,
const struct brw_reg *arg2);
void emit_mad(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *arg1,
const struct brw_reg *arg2);
void emit_math1(struct brw_wm_compile *c,
GLuint function,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0);
void emit_math2(struct brw_wm_compile *c,
GLuint function,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *arg1);
void emit_min(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *arg1);
void emit_max(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *arg1);
void emit_pinterp(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *deltas,
const struct brw_reg *w);
void emit_pixel_xy(struct brw_wm_compile *c,
const struct brw_reg *dst,
GLuint mask);
void emit_pixel_w(struct brw_wm_compile *c,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *deltas);
void emit_sop(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
GLuint cond,
const struct brw_reg *arg0,
const struct brw_reg *arg1);
void emit_sign(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0);
void emit_tex(struct brw_wm_compile *c,
struct brw_reg *dst,
GLuint dst_flags,
struct brw_reg *arg,
struct brw_reg depth_payload,
GLuint tex_idx,
GLuint sampler,
bool shadow);
void emit_txb(struct brw_wm_compile *c,
struct brw_reg *dst,
GLuint dst_flags,
struct brw_reg *arg,
struct brw_reg depth_payload,
GLuint tex_idx,
GLuint sampler);
void emit_wpos_xy(struct brw_wm_compile *c,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0);
void emit_xpd(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0,
const struct brw_reg *arg1);
GLboolean brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog);
struct gl_shader *brw_new_shader(struct gl_context *ctx, GLuint name, GLuint type);
struct gl_shader_program *brw_new_shader_program(struct gl_context *ctx, GLuint name);

View File

@@ -1,174 +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"
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 )
printf("undef");
else if( value - c->vreg >= 0 &&
value - c->vreg < BRW_WM_MAX_VREG)
printf("r%ld", (long) (value - c->vreg));
else if (value - c->creg >= 0 &&
value - c->creg < BRW_WM_MAX_PARAM)
printf("c%ld", (long) (value - c->creg));
else if (value - c->payload.input_interp >= 0 &&
value - c->payload.input_interp < FRAG_ATTRIB_MAX)
printf("i%ld", (long) (value - c->payload.input_interp));
else if (value - c->payload.depth >= 0 &&
value - c->payload.depth < FRAG_ATTRIB_MAX)
printf("d%ld", (long) (value - c->payload.depth));
else
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)
printf("UNSPILL(%x)/", ref->value->spill_slot);
if (c->state >= PASS2_DONE)
brw_print_reg(ref->hw_reg);
else {
printf("%s", hw_reg.negate ? "-" : "");
printf("%s", hw_reg.abs ? "abs/" : "");
brw_wm_print_value(c, ref->value);
if ((hw_reg.nr&1) || hw_reg.subnr) {
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 )
{
GLuint i, arg;
GLuint nr_args = brw_wm_nr_args(inst->opcode);
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)
printf("/SPILL(%x)",inst->dst[i]->spill_slot);
}
else
printf("#");
if (i < 3)
printf(",");
}
printf("]");
if (inst->writemask != WRITEMASK_XYZW)
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:
printf(" = PIXELXY");
break;
case WM_DELTAXY:
printf(" = DELTAXY");
break;
case WM_PIXELW:
printf(" = PIXELW");
break;
case WM_WPOSXY:
printf(" = WPOSXY");
break;
case WM_PINTERP:
printf(" = PINTERP");
break;
case WM_LINTERP:
printf(" = LINTERP");
break;
case WM_CINTERP:
printf(" = CINTERP");
break;
case WM_FB_WRITE:
printf(" = FB_WRITE");
break;
case WM_FRONTFACING:
printf(" = FRONTFACING");
break;
default:
printf(" = %s", _mesa_opcode_string(inst->opcode));
break;
}
if (inst->saturate)
printf("_SAT");
for (arg = 0; arg < nr_args; arg++) {
printf(" [");
for (i = 0; i < 4; i++) {
if (inst->src[arg][i]) {
brw_wm_print_ref(c, inst->src[arg][i]);
}
else
printf("%%");
if (i < 3)
printf(",");
else
printf("]");
}
}
printf("\n");
}
void brw_wm_print_program( struct brw_wm_compile *c,
const char *stage )
{
GLuint insn;
printf("%s:\n", stage);
for (insn = 0; insn < c->nr_insns; insn++)
brw_wm_print_insn(c, &c->instruction[insn]);
printf("\n");
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,445 +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"
#include "program/prog_parameter.h"
/***********************************************************************
*/
static struct brw_wm_ref *get_ref( struct brw_wm_compile *c )
{
assert(c->nr_refs < BRW_WM_MAX_REF);
memset(&c->refs[c->nr_refs], 0, sizeof(*c->refs));
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);
memset(&c->vreg[c->nr_vreg], 0, sizeof(*c->vreg));
return &c->vreg[c->nr_vreg++];
}
/** return pointer to a newly allocated instruction */
static struct brw_wm_instruction *get_instruction( struct brw_wm_compile *c )
{
assert(c->nr_insns < BRW_WM_MAX_INSN);
memset(&c->instruction[c->nr_insns], 0, sizeof(*c->instruction));
return &c->instruction[c->nr_insns++];
}
/***********************************************************************
*/
/** Init the "undef" register */
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;
}
/** Set a FP register to a value */
static void pass0_set_fpreg_value( struct brw_wm_compile *c,
GLuint file,
GLuint idx,
GLuint 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;
}
/** Set a FP register to a ref */
static void pass0_set_fpreg_ref( struct brw_wm_compile *c,
GLuint file,
GLuint idx,
GLuint 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 GLfloat *param_ptr )
{
GLuint i = c->prog_data.nr_params++;
if (i >= BRW_WM_MAX_PARAM) {
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;
}
}
/** Return a ref to a constant/literal value */
static const struct brw_wm_ref *get_const_ref( struct brw_wm_compile *c,
const GLfloat *constval )
{
GLuint 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) {
GLuint 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 {
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,
GLuint file,
GLuint idx,
GLuint 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, parameters 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 invariant:
*/
ref = get_const_ref(c, &plist->ParameterValues[idx][component].f);
break;
case PROGRAM_STATE_VAR:
case PROGRAM_UNIFORM:
/* These may change from run to run:
*/
ref = get_param_ref(c, &plist->ParameterValues[idx][component].f );
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,
GLuint writemask )
{
const struct prog_dst_register *dst = &inst->DstReg;
GLuint 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 const struct brw_wm_ref *get_fp_src_reg_ref( struct brw_wm_compile *c,
struct prog_src_register src,
GLuint i )
{
GLuint component = GET_SWZ(src.Swizzle,i);
const struct brw_wm_ref *src_ref;
static const GLfloat const_zero = 0.0;
static const GLfloat 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,
GLuint 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.Negate & (1 << i))
newref->hw_reg.negate ^= 1;
if (src.Abs) {
newref->hw_reg.negate = 0;
newref->hw_reg.abs = 1;
}
return newref;
}
static void
translate_insn(struct brw_wm_compile *c,
const struct prog_instruction *inst)
{
struct brw_wm_instruction *out = get_instruction(c);
GLuint writemask = inst->DstReg.WriteMask;
GLuint nr_args = brw_wm_nr_args(inst->Opcode);
GLuint 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;
out->tex_shadow = inst->TexShadow;
out->eot = inst->Aux & INST_AUX_EOT;
out->target = INST_AUX_GET_TARGET(inst->Aux);
/* 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:
*/
pass0_set_dst(c, out, inst, writemask);
}
/***********************************************************************
* 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;
GLuint writemask = inst->DstReg.WriteMask;
struct brw_wm_ref *refs[4];
GLuint i;
/* Get the effect of a MOV by manipulating our register table:
* First get all refs, then assign refs. This ensures that "in-place"
* swizzles such as:
* MOV t, t.xxyx
* are handled correctly. Previously, these two steps were done in
* one loop and the above case was incorrectly handled.
*/
for (i = 0; i < 4; i++) {
refs[i] = get_new_ref(c, inst->SrcReg[0], i, NULL);
}
for (i = 0; i < 4; i++) {
if (writemask & (1 << i)) {
pass0_set_fpreg_ref( c, dst->File, dst->Index, i, refs[i]);
}
}
}
/* Initialize payload "registers".
*/
static void pass0_init_payload( struct brw_wm_compile *c )
{
GLuint i;
for (i = 0; i < 4; i++) {
GLuint j = i >= (c->nr_payload_regs + 1) / 2 ? 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 )
{
GLuint 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 (unlikely(INTEL_DEBUG & DEBUG_WM)) {
brw_wm_print_program(c, "pass0");
}
}

View File

@@ -1,298 +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"
static GLuint get_tracked_mask(struct brw_wm_compile *c,
struct brw_wm_instruction *inst)
{
GLuint 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,
GLuint arg,
GLuint readmask)
{
GLuint 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 GLuint get_texcoord_mask( GLuint tex_idx )
{
switch (tex_idx) {
case TEXTURE_1D_INDEX:
return WRITEMASK_X;
case TEXTURE_2D_INDEX:
case TEXTURE_1D_ARRAY_INDEX:
case TEXTURE_EXTERNAL_INDEX:
return WRITEMASK_XY;
case TEXTURE_3D_INDEX:
case TEXTURE_2D_ARRAY_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 )
{
GLint insn;
for (insn = c->nr_insns-1; insn >= 0; insn--) {
struct brw_wm_instruction *inst = &c->instruction[insn];
GLuint writemask;
GLuint 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->source_depth_to_render_target && c->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) {
GLuint 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:
case OPCODE_SSG:
case OPCODE_SWZ:
case OPCODE_TRUNC:
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_DDX:
case OPCODE_DDY:
read0 = 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:
case OPCODE_TXP:
read0 = get_texcoord_mask(inst->tex_idx);
if (inst->tex_shadow)
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_DP2:
read0 = WRITEMASK_XY;
read1 = WRITEMASK_XY;
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_DST:
case WM_FRONTFACING:
default:
break;
}
track_arg(c, inst, 0, read0);
track_arg(c, inst, 1, read1);
track_arg(c, inst, 2, read2);
}
if (unlikely(INTEL_DEBUG & DEBUG_WM)) {
brw_wm_print_program(c, "pass1");
}
}

View File

@@ -1,359 +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"
/* 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,
GLuint 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 )
{
struct brw_context *brw = c->func.brw;
struct intel_context *intel = &brw->intel;
GLuint nr_interp_regs = 0;
GLuint i = 0;
GLuint j;
for (j = 0; j < c->grf_limit; j++)
c->pass2_grf[j].nextuse = BRW_WM_MAX_INSN;
for (j = 0; j < (c->nr_payload_regs + 1) / 2; j++)
prealloc_reg(c, &c->payload.depth[j], i++);
for (j = 0; j < c->nr_creg; j++)
prealloc_reg(c, &c->creg[j], i++);
if (intel->gen >= 6) {
for (unsigned int j = 0; j < FRAG_ATTRIB_MAX; j++) {
if (c->fp->program.Base.InputsRead & BITFIELD64_BIT(j)) {
nr_interp_regs++;
prealloc_reg(c, &c->payload.input_interp[j], i++);
}
}
} else {
for (j = 0; j < VERT_RESULT_MAX; j++) {
/* Point size is packed into the header, not as a general attribute */
if (j == VERT_RESULT_PSIZ)
continue;
if (c->key.vp_outputs_written & BITFIELD64_BIT(j)) {
int fp_index = _mesa_vert_result_to_frag_attrib(j);
nr_interp_regs++;
/* The back color slot is skipped when the front color is
* also written to. In addition, some slots can be
* written in the vertex shader and not read in the
* fragment shader. So the register number must always be
* incremented, mapped or not.
*/
if (fp_index >= 0)
prealloc_reg(c, &c->payload.input_interp[fp_index], i);
i++;
}
}
assert(nr_interp_regs >= 1);
}
c->prog_data.first_curbe_grf = ALIGN(c->nr_payload_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,
GLuint thisinsn)
{
GLuint 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) {
const 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 GLuint search_contiguous_regs(struct brw_wm_compile *c,
GLuint nr,
GLuint thisinsn)
{
struct brw_wm_grf *grf = c->pass2_grf;
GLuint furthest = 0;
GLuint reg = 0;
GLuint 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++) {
GLuint 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[],
GLuint nr,
GLuint thisinsn)
{
GLuint reg = search_contiguous_regs(c, nr, thisinsn);
GLuint 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)
{
GLuint thisinsn = inst - c->instruction;
GLuint 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.
*/
GLuint 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 )
{
GLuint insn;
GLuint 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 (unlikely(INTEL_DEBUG & DEBUG_WM)) {
brw_wm_print_program(c, "pass2");
}
c->state = PASS2_DONE;
if (unlikely(INTEL_DEBUG & DEBUG_WM)) {
brw_wm_print_program(c, "pass2/done");
}
}