From: Keith Whitwell Date: Wed, 28 Oct 2009 21:24:03 +0000 (+0000) Subject: i965g: still working on compilation X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=81b8589f064204d9ddcd7d1f9d43d2dcf5676235;p=mesa.git i965g: still working on compilation --- diff --git a/src/gallium/drivers/i965/brw_vs.c b/src/gallium/drivers/i965/brw_vs.c index 3965ca6c54e..26a28114d98 100644 --- a/src/gallium/drivers/i965/brw_vs.c +++ b/src/gallium/drivers/i965/brw_vs.c @@ -57,7 +57,7 @@ static void do_vs_prog( struct brw_context *brw, c.prog_data.nr_inputs = vp->info.num_inputs; c.prog_data.copy_edgeflag = c.key.copy_edgeflag; - if (0) + if (1) tgsi_dump(c.vp->tokens, 0); /* Emit GEN4 code. diff --git a/src/gallium/drivers/i965/brw_vs.h b/src/gallium/drivers/i965/brw_vs.h index 2a2dbb3457c..b4e450d89bf 100644 --- a/src/gallium/drivers/i965/brw_vs.h +++ b/src/gallium/drivers/i965/brw_vs.h @@ -60,6 +60,9 @@ struct brw_vs_compile { GLuint nr_inputs; GLuint nr_outputs; + GLuint nr_immediates; + GLfloat immediate[128][4]; + GLboolean copy_edgeflag; GLuint first_output; diff --git a/src/gallium/drivers/i965/brw_vs_emit.c b/src/gallium/drivers/i965/brw_vs_emit.c index 5366ab85140..6809bccdecc 100644 --- a/src/gallium/drivers/i965/brw_vs_emit.c +++ b/src/gallium/drivers/i965/brw_vs_emit.c @@ -34,8 +34,7 @@ #include "util/u_memory.h" #include "util/u_math.h" -#include "tgsi/tgsi_ureg.h" -#include "tgsi/tgsi_ureg_parse.h" +#include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_info.h" @@ -67,6 +66,7 @@ static void release_tmps( struct brw_vs_compile *c ) } + /** * Preallocate GRF register before code emit. * Do things as simply as possible. Allocate and populate all regs @@ -83,10 +83,17 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c ) * XXX this heuristic/check may need some fine tuning... */ if (c->vp->info.file_max[TGSI_FILE_CONSTANT] + + c->vp->info.file_max[TGSI_FILE_IMMEDIATE] + c->vp->info.file_max[TGSI_FILE_TEMPORARY] + 21 > BRW_MAX_GRF) c->vp->use_const_buffer = GL_TRUE; - else + else { + /* XXX: immediates can go elsewhere if necessary: + */ + assert(c->vp->info.file_max[TGSI_FILE_IMMEDIATE] + + c->vp->info.file_max[TGSI_FILE_TEMPORARY] + 21 > BRW_MAX_GRF); + c->vp->use_const_buffer = GL_FALSE; + } /*printf("use_const_buffer = %d\n", c->vp->use_const_buffer);*/ @@ -139,6 +146,29 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c ) if (c->nr_inputs == 0) reg++; + /* Allocate a GRF and load immediate values by hand with 4 MOVs!!! + * + * XXX: Try to encode float immediates as brw immediates + * XXX: Put immediates into the CURBE. + * XXX: Make sure ureg sets minimal immediate size and respect it + * here. + */ + for (i = 0; i < c->nr_immediates; i++) { + struct brw_reg r; + int j; + + r = brw_vec8_grf(reg, 0); + + for (j = 0; j < 4; j++) { + brw_MOV(&c->func, + brw_writemask(r, (1<immediate[i][j])); + } + + reg++; + } + + /* Allocate outputs. The non-position outputs go straight into message regs. */ c->nr_outputs = 0; @@ -754,21 +784,20 @@ static void emit_nrm( struct brw_vs_compile *c, static struct brw_reg get_constant(struct brw_vs_compile *c, - const struct ureg_instruction *inst, - GLuint argIndex) + GLuint argIndex, + GLuint index, + GLboolean relAddr) { - const struct ureg_src src = inst->src[argIndex]; struct brw_compile *p = &c->func; struct brw_reg const_reg; struct brw_reg const2_reg; - const GLboolean relAddr = src.Indirect; assert(argIndex < 3); - if (c->current_const[argIndex].index != src.Index || relAddr) { + if (c->current_const[argIndex].index != index || relAddr) { struct brw_reg addrReg = c->regs[TGSI_FILE_ADDRESS][0]; - c->current_const[argIndex].index = src.Index; + c->current_const[argIndex].index = index; #if 0 printf(" fetch const[%d] for arg %d into reg %d\n", @@ -780,7 +809,7 @@ get_constant(struct brw_vs_compile *c, 0, /* oword */ relAddr, /* relative indexing? */ addrReg, /* address register */ - 16 * src.Index, /* byte offset */ + 16 * index, /* byte offset */ SURF_INDEX_VERT_CONST_BUFFER /* binding table index */ ); @@ -797,7 +826,7 @@ get_constant(struct brw_vs_compile *c, 1, /* oword */ relAddr, /* relative indexing? */ addrReg, /* address register */ - 16 * src.Index, /* byte offset */ + 16 * index, /* byte offset */ SURF_INDEX_VERT_CONST_BUFFER ); } @@ -894,12 +923,11 @@ static struct brw_reg deref( struct brw_vs_compile *c, */ static struct brw_reg get_src_reg( struct brw_vs_compile *c, - const struct ureg_instruction *inst, - GLuint argIndex ) + GLuint argIndex, + GLuint file, + GLint index, + GLboolean relAddr ) { - const GLuint file = inst->src[argIndex].File; - const GLint index = inst->src[argIndex].Index; - const GLboolean relAddr = inst->src[argIndex].Indirect; switch (file) { case TGSI_FILE_TEMPORARY: @@ -913,9 +941,12 @@ get_src_reg( struct brw_vs_compile *c, return c->regs[file][index]; } + case TGSI_FILE_IMMEDIATE: + return c->regs[file][index]; + case TGSI_FILE_CONSTANT: if (c->vp->use_const_buffer) { - return get_constant(c, inst, argIndex); + return get_constant(c, argIndex, index, relAddr); } else if (relAddr) { return deref(c, c->regs[TGSI_FILE_CONSTANT][0], index); @@ -962,27 +993,32 @@ static void emit_arl( struct brw_vs_compile *c, * Return the brw reg for the given instruction's src argument. */ static struct brw_reg get_arg( struct brw_vs_compile *c, - const struct ureg_instruction *inst, + const struct tgsi_full_src_register *src, GLuint argIndex ) { - const struct ureg_src src = inst->src[argIndex]; struct brw_reg reg; - if (src.File == TGSI_FILE_NULL) + if (src->SrcRegister.File == TGSI_FILE_NULL) return brw_null_reg(); - reg = get_src_reg(c, inst, argIndex); + reg = get_src_reg(c, argIndex, + src->SrcRegister.File, + src->SrcRegister.Index, + src->SrcRegister.Indirect); /* Convert 3-bit swizzle to 2-bit. */ - reg.dw1.bits.swizzle = BRW_SWIZZLE4(src.SwizzleX, - src.SwizzleY, - src.SwizzleZ, - src.SwizzleW); + reg.dw1.bits.swizzle = BRW_SWIZZLE4(src->SrcRegister.SwizzleX, + src->SrcRegister.SwizzleY, + src->SrcRegister.SwizzleZ, + src->SrcRegister.SwizzleW); /* Note this is ok for non-swizzle instructions: */ - reg.negate = src.Negate ? 1 : 0; + reg.negate = src->SrcRegister.Negate ? 1 : 0; + + /* XXX: abs, absneg + */ return reg; } @@ -992,19 +1028,21 @@ static struct brw_reg get_arg( struct brw_vs_compile *c, * Get brw register for the given program dest register. */ static struct brw_reg get_dst( struct brw_vs_compile *c, - struct ureg_dst dst ) + unsigned file, + unsigned index, + unsigned writemask ) { struct brw_reg reg; - switch (dst.File) { + switch (file) { case TGSI_FILE_TEMPORARY: case TGSI_FILE_OUTPUT: - assert(c->regs[dst.File][dst.Index].nr != 0); - reg = c->regs[dst.File][dst.Index]; + assert(c->regs[file][index].nr != 0); + reg = c->regs[file][index]; break; case TGSI_FILE_ADDRESS: - assert(dst.Index == 0); - reg = c->regs[dst.File][dst.Index]; + assert(index == 0); + reg = c->regs[file][index]; break; case TGSI_FILE_NULL: /* we may hit this for OPCODE_END, OPCODE_KIL, etc */ @@ -1015,7 +1053,7 @@ static struct brw_reg get_dst( struct brw_vs_compile *c, reg = brw_null_reg(); } - reg.dw1.bits.writemask = dst.WriteMask; + reg.dw1.bits.writemask = writemask; return reg; } @@ -1199,7 +1237,7 @@ post_vs_emit( struct brw_vs_compile *c, } static uint32_t -get_predicate(const struct ureg_instruction *inst) +get_predicate(const struct tgsi_full_instruction *inst) { /* XXX: disabling for now */ @@ -1242,8 +1280,10 @@ get_predicate(const struct ureg_instruction *inst) } static void emit_insn(struct brw_vs_compile *c, - const struct ureg_instruction *inst) + const struct tgsi_full_instruction *inst) { + unsigned opcode = inst->Instruction.Opcode; + unsigned label = inst->InstructionExtLabel.Label; struct brw_compile *p = &c->func; struct brw_reg args[3], dst; GLuint i; @@ -1256,20 +1296,25 @@ static void emit_insn(struct brw_vs_compile *c, /* Get argument regs. */ for (i = 0; i < 3; i++) { - args[i] = get_arg(c, inst, i); + args[i] = get_arg(c, &inst->FullSrcRegisters[i], i); } /* Get dest regs. Note that it is possible for a reg to be both * dst and arg, given the static allocation of registers. So * care needs to be taken emitting multi-operation instructions. */ - dst = get_dst(c, inst->dst); + dst = get_dst(c, + inst->FullDstRegisters[0].DstRegister.File, + inst->FullDstRegisters[0].DstRegister.Index, + inst->FullDstRegisters[0].DstRegister.WriteMask); - if (inst->dst.Saturate) { + /* XXX: saturate + */ + if (inst->Instruction.Saturate != TGSI_SAT_NONE) { debug_printf("Unsupported saturate in vertex shader"); } - switch (inst->opcode) { + switch (opcode) { case TGSI_OPCODE_ABS: brw_MOV(p, dst, brw_abs(args[0])); break; @@ -1443,7 +1488,7 @@ static void emit_insn(struct brw_vs_compile *c, brw_set_access_mode(p, BRW_ALIGN_16); brw_ADD(p, get_addr_reg(c->stack_index), get_addr_reg(c->stack_index), brw_imm_d(4)); - brw_save_call(p, inst->label, p->nr_insn); + brw_save_call(p, label, p->nr_insn); brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16)); break; case TGSI_OPCODE_RET: @@ -1468,8 +1513,8 @@ static void emit_insn(struct brw_vs_compile *c, break; default: debug_printf("Unsupported opcode %i (%s) in vertex shader", - inst->opcode, - tgsi_get_opcode_name(inst->opcode)); + opcode, + tgsi_get_opcode_name(opcode)); } /* Set the predication update on the last instruction of the native @@ -1498,11 +1543,12 @@ static void emit_insn(struct brw_vs_compile *c, void brw_vs_emit(struct brw_vs_compile *c) { struct brw_compile *p = &c->func; + const struct tgsi_token *tokens = c->vp->tokens; struct brw_instruction *end_inst, *last_inst; - struct ureg_parse_context parse; - struct ureg_declaration *decl; - struct ureg_declaration *imm; - struct ureg_declaration *insn; + struct tgsi_parse_context parse; + struct tgsi_full_instruction *inst; + boolean done = FALSE; + int i; if (BRW_DEBUG & DEBUG_VS) tgsi_dump(c->vp->tokens, 0); @@ -1512,21 +1558,66 @@ void brw_vs_emit(struct brw_vs_compile *c) brw_set_compression_control(p, BRW_COMPRESSION_NONE); brw_set_access_mode(p, BRW_ALIGN_16); + /* Inputs */ + tgsi_parse_init( &parse, tokens ); + while( !tgsi_parse_end_of_tokens( &parse ) ) { + tgsi_parse_token( &parse ); + + switch( parse.FullToken.Token.Type ) { + case TGSI_TOKEN_TYPE_DECLARATION: + /* Nothing to do -- using info from tgsi_scan(). + */ + break; + + case TGSI_TOKEN_TYPE_IMMEDIATE: { + static const float id[4] = {0,0,0,1}; + const float *imm = &parse.FullToken.FullImmediate.u[i].Float; + unsigned size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1; + + for (i = 0; i < size; i++) + c->immediate[c->nr_immediates][i] = imm[i]; + + for ( ; i < 4; i++) + c->immediate[c->nr_immediates][i] = id[i]; + + c->nr_immediates++; + break; + } + + case TGSI_TOKEN_TYPE_INSTRUCTION: + done = 1; + break; + } + } + /* Static register allocation */ brw_vs_alloc_regs(c); brw_MOV(p, get_addr_reg(c->stack_index), brw_address(c->stack)); - while (ureg_next_decl(&parse, &decl)) { - } - - while (ureg_next_immediate(&parse, &imm)) { - } - - while (ureg_next_instruction(&parse, &insn)) { + /* Instructions + */ + tgsi_parse_init( &parse, tokens ); + while( !tgsi_parse_end_of_tokens( &parse ) ) { + tgsi_parse_token( &parse ); + + switch( parse.FullToken.Token.Type ) { + case TGSI_TOKEN_TYPE_DECLARATION: + case TGSI_TOKEN_TYPE_IMMEDIATE: + break; + + case TGSI_TOKEN_TYPE_INSTRUCTION: + inst = &parse.FullToken.FullInstruction; + emit_insn( c, inst ); + break; + + default: + assert( 0 ); + } } + tgsi_parse_free( &parse ); - end_inst = &p->store[end_offset]; + end_inst = &p->store[c->end_offset]; last_inst = &p->store[p->nr_insn]; /* The END instruction will be patched to jump to this code */ diff --git a/src/gallium/drivers/i965/brw_vs_state.c b/src/gallium/drivers/i965/brw_vs_state.c index 05a91f2de44..549696f7ae7 100644 --- a/src/gallium/drivers/i965/brw_vs_state.c +++ b/src/gallium/drivers/i965/brw_vs_state.c @@ -29,8 +29,10 @@ * Keith Whitwell */ +#include "util/u_math.h" +#include "brw_debug.h" #include "brw_context.h" #include "brw_state.h" #include "brw_defines.h" @@ -64,8 +66,8 @@ vs_unit_populate_key(struct brw_context *brw, struct brw_vs_unit_key *key) /* BRW_NEW_NR_VS_SURFACES */ key->nr_surfaces = brw->vs.nr_surfaces; - /* BRW_NEW_CURBE_OFFSETS, _NEW_TRANSFORM */ - if (ctx->Transform.ClipPlanesEnabled) { + /* PIPE_NEW_CLIP */ + if (brw->curr.ucp.nr) { /* Note that we read in the userclip planes as well, hence * clip_start: */ @@ -86,7 +88,7 @@ vs_unit_create_from_key(struct brw_context *brw, struct brw_vs_unit_key *key) memset(&vs, 0, sizeof(vs)); vs.thread0.kernel_start_pointer = brw->vs.prog_bo->offset >> 6; /* reloc */ - vs.thread0.grf_reg_count = ALIGN(key->total_grf, 16) / 16 - 1; + vs.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1; vs.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754; /* Choosing multiple program flow means that we may get 2-vertex threads, * which will have the channel mask for dwords 4-7 enabled in the thread, @@ -119,6 +121,7 @@ vs_unit_create_from_key(struct brw_context *brw, struct brw_vs_unit_key *key) chipset_max_threads = 32; else chipset_max_threads = 16; + vs.thread4.max_threads = CLAMP(key->nr_urb_entries / 2, 1, chipset_max_threads) - 1; @@ -145,16 +148,16 @@ vs_unit_create_from_key(struct brw_context *brw, struct brw_vs_unit_key *key) NULL, NULL); /* Emit VS program relocation */ - dri_bo_emit_reloc(bo, - I915_GEM_DOMAIN_INSTRUCTION, 0, - vs.thread0.grf_reg_count << 1, - offsetof(struct brw_vs_unit_state, thread0), - brw->vs.prog_bo); + brw->sws->bo_emit_reloc(bo, + I915_GEM_DOMAIN_INSTRUCTION, 0, + vs.thread0.grf_reg_count << 1, + offsetof(struct brw_vs_unit_state, thread0), + brw->vs.prog_bo); return bo; } -static void prepare_vs_unit(struct brw_context *brw) +static int prepare_vs_unit(struct brw_context *brw) { struct brw_vs_unit_key key; @@ -168,11 +171,13 @@ static void prepare_vs_unit(struct brw_context *brw) if (brw->vs.state_bo == NULL) { brw->vs.state_bo = vs_unit_create_from_key(brw, &key); } + + return 0; } const struct brw_tracked_state brw_vs_unit = { .dirty = { - .mesa = _NEW_TRANSFORM, + .mesa = (PIPE_NEW_CLIP), .brw = (BRW_NEW_CURBE_OFFSETS | BRW_NEW_NR_VS_SURFACES | BRW_NEW_URB_FENCE), diff --git a/src/gallium/drivers/i965/brw_vs_surface_state.c b/src/gallium/drivers/i965/brw_vs_surface_state.c index 319e29bfcbc..9a9d47a8a3e 100644 --- a/src/gallium/drivers/i965/brw_vs_surface_state.c +++ b/src/gallium/drivers/i965/brw_vs_surface_state.c @@ -32,6 +32,11 @@ #include "brw_context.h" #include "brw_state.h" #include "brw_defines.h" +#include "brw_winsys.h" + +/* XXX: disabled true constant buffer functionality + */ + /* Creates a new VS constant buffer reflecting the current VS program's * constants, if needed by the VS program. @@ -39,9 +44,12 @@ * Otherwise, constants go through the CURBEs using the brw_constant_buffer * state atom. */ -static drm_intel_bo * +#if 0 +static struct brw_winsys_buffer * brw_vs_update_constant_buffer(struct brw_context *brw) { + /* XXX: true constant buffers + */ struct brw_vertex_program *vp = (struct brw_vertex_program *) brw->vertex_program; const struct gl_program_parameter_list *params = vp->program.Base.Parameters; @@ -61,21 +69,20 @@ brw_vs_update_constant_buffer(struct brw_context *brw) return const_buffer; } +#endif /** * Update the surface state for a VS constant buffer. * * Sets brw->vs.surf_bo[surf] and brw->vp->const_buffer. */ +#if 0 static void brw_update_vs_constant_surface( struct brw_context *brw, GLuint surf) { - struct brw_context *brw = brw_context(ctx); struct brw_surface_key key; - struct brw_vertex_program *vp = - (struct brw_vertex_program *) brw->vertex_program; - const struct gl_program_parameter_list *params = vp->program.Base.Parameters; + struct pipe_buffer *cb = brw->curr.vs_constants; assert(surf == 0); @@ -121,6 +128,7 @@ brw_update_vs_constant_surface( struct brw_context *brw, brw->vs.surf_bo[surf] = brw_create_constant_surface(brw, &key); } } +#endif /** @@ -129,6 +137,7 @@ brw_update_vs_constant_surface( struct brw_context *brw, static struct brw_winsys_buffer * brw_vs_get_binding_table(struct brw_context *brw) { +#if 0 struct brw_winsys_buffer *bind_bo; bind_bo = brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND, @@ -169,6 +178,9 @@ brw_vs_get_binding_table(struct brw_context *brw) } return bind_bo; +#else + return NULL; +#endif } /** @@ -178,8 +190,9 @@ brw_vs_get_binding_table(struct brw_context *brw) * to be updated, and produces BRW_NEW_NR_VS_SURFACES for the VS unit and * CACHE_NEW_SURF_BIND for the binding table upload. */ -static void prepare_vs_surfaces(struct brw_context *brw ) +static int prepare_vs_surfaces(struct brw_context *brw ) { +#if 0 int i; int nr_surfaces = 0; @@ -195,6 +208,7 @@ static void prepare_vs_surfaces(struct brw_context *brw ) brw->state.dirty.brw |= BRW_NEW_NR_VS_SURFACES; brw->vs.nr_surfaces = nr_surfaces; } +#endif /* Note that we don't end up updating the bind_bo if we don't have a * surface to be pointing at. This should be relatively harmless, as it @@ -204,12 +218,15 @@ static void prepare_vs_surfaces(struct brw_context *brw ) brw->sws->bo_unreference(brw->vs.bind_bo); brw->vs.bind_bo = brw_vs_get_binding_table(brw); } + + return 0; } const struct brw_tracked_state brw_vs_surfaces = { .dirty = { - .mesa = (_NEW_PROGRAM_CONSTANTS), - .brw = (BRW_NEW_VERTEX_PROGRAM), + .mesa = (PIPE_NEW_VERTEX_CONSTANTS | + PIPE_NEW_VERTEX_SHADER), + .brw = 0, .cache = 0 }, .prepare = prepare_vs_surfaces, diff --git a/src/gallium/drivers/i965/brw_wm.c b/src/gallium/drivers/i965/brw_wm.c index 3d889699f89..f0dabfcfd0e 100644 --- a/src/gallium/drivers/i965/brw_wm.c +++ b/src/gallium/drivers/i965/brw_wm.c @@ -28,11 +28,14 @@ * Authors: * Keith Whitwell */ - + +#include "tgsi/tgsi_info.h" + #include "brw_context.h" #include "brw_util.h" #include "brw_wm.h" #include "brw_state.h" +#include "brw_debug.h" /** Return number of src args for given instruction */ @@ -54,7 +57,7 @@ GLuint brw_wm_nr_args( GLuint opcode ) return 3; default: assert(opcode < MAX_OPCODE); - return _mesa_num_inst_src_regs(opcode); + return tgsi_get_opcode_info(opcode)->num_src; } } @@ -62,17 +65,17 @@ GLuint brw_wm_nr_args( GLuint 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_DP3: - case OPCODE_DP4: - case OPCODE_DPH: - case OPCODE_DST: + case TGSI_OPCODE_COS: + case TGSI_OPCODE_EX2: + case TGSI_OPCODE_LG2: + case TGSI_OPCODE_POW: + case TGSI_OPCODE_RCP: + case TGSI_OPCODE_RSQ: + case TGSI_OPCODE_SIN: + case TGSI_OPCODE_DP3: + case TGSI_OPCODE_DP4: + case TGSI_OPCODE_DPH: + case TGSI_OPCODE_DST: return 1; default: @@ -134,7 +137,7 @@ brw_wm_non_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c) * we'll use one of two code generators. */ static void do_wm_prog( struct brw_context *brw, - struct brw_fragment_program *fp, + struct brw_fragment_shader *fp, struct brw_wm_prog_key *key) { struct brw_wm_compile *c; @@ -163,7 +166,7 @@ static void do_wm_prog( struct brw_context *brw, brw_init_compile(brw, &c->func); /* temporary sanity check assertion */ - ASSERT(fp->isGLSL == brw_wm_is_glsl(&c->fp->program)); + assert(fp->isGLSL == brw_wm_is_glsl(&c->fp->program)); /* * Shader which use GLSL features such as flow control are handled @@ -200,8 +203,7 @@ static void brw_wm_populate_key( struct brw_context *brw, struct brw_wm_prog_key *key ) { /* BRW_NEW_FRAGMENT_PROGRAM */ - const struct brw_fragment_program *fp = - (struct brw_fragment_program *)brw->fragment_program; + const struct brw_fragment_program *fp = brw->curr.fragment_shader; GLboolean uses_depth = (fp->program.Base.InputsRead & (1 << FRAG_ATTRIB_WPOS)) != 0; GLuint lookup = 0; GLuint line_aa;