From 6ce68ad3ca242076bbb93fdd99bb448f87a31d15 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Tue, 1 Jun 2010 21:27:18 +0100 Subject: [PATCH] llvmpipe: Use struct lp_shader_input in the interpolator. Eliminates all this identical yet slightly different code to decide how shader inputs should be interpolated. As bonus, don't interpolate the position twice when it is listed in the TGSI shader inputs. --- src/gallium/drivers/llvmpipe/lp_bld_interp.c | 165 ++++++++++-------- src/gallium/drivers/llvmpipe/lp_bld_interp.h | 11 +- src/gallium/drivers/llvmpipe/lp_context.h | 5 + src/gallium/drivers/llvmpipe/lp_setup_tri.c | 77 +++++--- .../drivers/llvmpipe/lp_state_derived.c | 3 +- src/gallium/drivers/llvmpipe/lp_state_fs.c | 9 +- 6 files changed, 160 insertions(+), 110 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.c b/src/gallium/drivers/llvmpipe/lp_bld_interp.c index 07c9e646630..d1f0185684d 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_interp.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.c @@ -105,15 +105,15 @@ coeffs_init(struct lp_build_interp_soa_context *bld, for(chan = 0; chan < NUM_CHANNELS; ++chan) { if(mask & (1 << chan)) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), attrib*NUM_CHANNELS + chan, 0); - LLVMValueRef a0 = NULL; - LLVMValueRef dadx = NULL; - LLVMValueRef dady = NULL; + LLVMValueRef a0 = bld->base.undef; + LLVMValueRef dadx = bld->base.undef; + LLVMValueRef dady = bld->base.undef; switch( interp ) { - case TGSI_INTERPOLATE_PERSPECTIVE: + case LP_INTERP_PERSPECTIVE: /* fall-through */ - case TGSI_INTERPOLATE_LINEAR: + case LP_INTERP_LINEAR: dadx = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dadx_ptr, &index, 1, ""), ""); dady = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dady_ptr, &index, 1, ""), ""); dadx = lp_build_broadcast_scalar(&bld->base, dadx); @@ -122,12 +122,17 @@ coeffs_init(struct lp_build_interp_soa_context *bld, attrib_name(dady, attrib, chan, ".dady"); /* fall-through */ - case TGSI_INTERPOLATE_CONSTANT: + case LP_INTERP_CONSTANT: + case LP_INTERP_FACING: a0 = LLVMBuildLoad(builder, LLVMBuildGEP(builder, a0_ptr, &index, 1, ""), ""); a0 = lp_build_broadcast_scalar(&bld->base, a0); attrib_name(a0, attrib, chan, ".a0"); break; + case LP_INTERP_POSITION: + /* Nothing to do as the position coeffs are already setup in slot 0 */ + break; + default: assert(0); break; @@ -163,36 +168,44 @@ attribs_init(struct lp_build_interp_soa_context *bld) const unsigned interp = bld->interp[attrib]; for(chan = 0; chan < NUM_CHANNELS; ++chan) { if(mask & (1 << chan)) { - LLVMValueRef a0 = bld->a0 [attrib][chan]; - LLVMValueRef dadx = bld->dadx[attrib][chan]; - LLVMValueRef dady = bld->dady[attrib][chan]; - LLVMValueRef res; - - res = a0; - - if (interp != TGSI_INTERPOLATE_CONSTANT) { - /* res = res + x * dadx */ - res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, x, dadx)); - /* res = res + y * dady */ - res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, y, dady)); + if (interp == LP_INTERP_POSITION) { + assert(attrib > 0); + bld->attribs[attrib][chan] = bld->attribs[0][chan]; } + else { + LLVMValueRef a0 = bld->a0 [attrib][chan]; + LLVMValueRef dadx = bld->dadx[attrib][chan]; + LLVMValueRef dady = bld->dady[attrib][chan]; + LLVMValueRef res; - /* Keep the value of the attribute before perspective divide - * for faster updates. - */ - bld->attribs_pre[attrib][chan] = res; - - if (interp == TGSI_INTERPOLATE_PERSPECTIVE) { - LLVMValueRef w = bld->pos[3]; - assert(attrib != 0); - if(!oow) - oow = lp_build_rcp(&bld->base, w); - res = lp_build_mul(&bld->base, res, oow); - } + res = a0; + + if (interp != LP_INTERP_CONSTANT && + interp != LP_INTERP_FACING) { + /* res = res + x * dadx */ + res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, x, dadx)); + /* res = res + y * dady */ + res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, y, dady)); + } - attrib_name(res, attrib, chan, ""); + /* Keep the value of the attribute before perspective divide + * for faster updates. + */ + bld->attribs_pre[attrib][chan] = res; - bld->attribs[attrib][chan] = res; + if (interp == LP_INTERP_PERSPECTIVE) { + LLVMValueRef w = bld->pos[3]; + assert(attrib != 0); + assert(bld->mask[0] & TGSI_WRITEMASK_W); + if(!oow) + oow = lp_build_rcp(&bld->base, w); + res = lp_build_mul(&bld->base, res, oow); + } + + attrib_name(res, attrib, chan, ""); + + bld->attribs[attrib][chan] = res; + } } } } @@ -216,40 +229,48 @@ attribs_update(struct lp_build_interp_soa_context *bld, int quad_index) const unsigned mask = bld->mask[attrib]; const unsigned interp = bld->interp[attrib]; - if (interp != TGSI_INTERPOLATE_CONSTANT) { + if (interp != LP_INTERP_CONSTANT && + interp != LP_INTERP_FACING) { for(chan = 0; chan < NUM_CHANNELS; ++chan) { if(mask & (1 << chan)) { - LLVMValueRef dadx = bld->dadx[attrib][chan]; - LLVMValueRef dady = bld->dady[attrib][chan]; - LLVMValueRef res; - - res = bld->attribs_pre[attrib][chan]; - - if (quad_index == 1 || quad_index == 3) { - /* top-right or bottom-right quad */ - /* build res = res + dadx + dadx */ - res = lp_build_add(&bld->base, res, dadx); - res = lp_build_add(&bld->base, res, dadx); + if (interp == LP_INTERP_POSITION) { + assert(attrib > 0); + bld->attribs[attrib][chan] = bld->attribs[0][chan]; } - - if (quad_index == 2 || quad_index == 3) { - /* bottom-left or bottom-right quad */ - /* build res = res + dady + dady */ - res = lp_build_add(&bld->base, res, dady); - res = lp_build_add(&bld->base, res, dady); + else { + LLVMValueRef dadx = bld->dadx[attrib][chan]; + LLVMValueRef dady = bld->dady[attrib][chan]; + LLVMValueRef res; + + res = bld->attribs_pre[attrib][chan]; + + if (quad_index == 1 || quad_index == 3) { + /* top-right or bottom-right quad */ + /* build res = res + dadx + dadx */ + res = lp_build_add(&bld->base, res, dadx); + res = lp_build_add(&bld->base, res, dadx); + } + + if (quad_index == 2 || quad_index == 3) { + /* bottom-left or bottom-right quad */ + /* build res = res + dady + dady */ + res = lp_build_add(&bld->base, res, dady); + res = lp_build_add(&bld->base, res, dady); + } + + if (interp == LP_INTERP_PERSPECTIVE) { + LLVMValueRef w = bld->pos[3]; + assert(attrib != 0); + assert(bld->mask[0] & TGSI_WRITEMASK_W); + if(!oow) + oow = lp_build_rcp(&bld->base, w); + res = lp_build_mul(&bld->base, res, oow); + } + + attrib_name(res, attrib, chan, ""); + + bld->attribs[attrib][chan] = res; } - - if (interp == TGSI_INTERPOLATE_PERSPECTIVE) { - LLVMValueRef w = bld->pos[3]; - assert(attrib != 0); - if(!oow) - oow = lp_build_rcp(&bld->base, w); - res = lp_build_mul(&bld->base, res, oow); - } - - attrib_name(res, attrib, chan, ""); - - bld->attribs[attrib][chan] = res; } } } @@ -315,8 +336,8 @@ pos_update(struct lp_build_interp_soa_context *bld, int quad_index) */ void lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, - const struct tgsi_shader_info *info, - boolean flatshade, + unsigned num_inputs, + const struct lp_shader_input *inputs, LLVMBuilderRef builder, struct lp_type type, LLVMValueRef a0_ptr, @@ -339,20 +360,14 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, /* Position */ bld->num_attribs = 1; bld->mask[0] = TGSI_WRITEMASK_ZW; - bld->interp[0] = TGSI_INTERPOLATE_LINEAR; + bld->interp[0] = LP_INTERP_LINEAR; /* Inputs */ - for (attrib = 0; attrib < info->num_inputs; ++attrib) { - bld->mask[1 + attrib] = info->input_usage_mask[attrib]; - - if (info->input_semantic_name[attrib] == TGSI_SEMANTIC_COLOR && - flatshade) - bld->interp[1 + attrib] = TGSI_INTERPOLATE_CONSTANT; - else - bld->interp[1 + attrib] = info->input_interpolate[attrib]; - + for (attrib = 0; attrib < num_inputs; ++attrib) { + bld->mask[1 + attrib] = inputs[attrib].usage_mask; + bld->interp[1 + attrib] = inputs[attrib].interp; } - bld->num_attribs = 1 + info->num_inputs; + bld->num_attribs = 1 + num_inputs; /* Ensure all masked out input channels have a valid value */ for (attrib = 0; attrib < bld->num_attribs; ++attrib) { diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.h b/src/gallium/drivers/llvmpipe/lp_bld_interp.h index 2d41fefd47b..79d1e51605a 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_interp.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.h @@ -46,10 +46,7 @@ #include "tgsi/tgsi_exec.h" - - -struct tgsi_token; -struct tgsi_shader_info; +#include "lp_setup.h" struct lp_build_interp_soa_context @@ -58,7 +55,7 @@ struct lp_build_interp_soa_context unsigned num_attribs; unsigned mask[1 + PIPE_MAX_SHADER_INPUTS]; /**< TGSI_WRITE_MASK_x */ - unsigned interp[1 + PIPE_MAX_SHADER_INPUTS]; /**< TGSI_INTERPOLATE_x */ + enum lp_interp interp[1 + PIPE_MAX_SHADER_INPUTS]; LLVMValueRef a0 [1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; LLVMValueRef dadx[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; @@ -79,8 +76,8 @@ struct lp_build_interp_soa_context void lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, - const struct tgsi_shader_info *info, - boolean flatshade, + unsigned num_inputs, + const struct lp_shader_input *inputs, LLVMBuilderRef builder, struct lp_type type, LLVMValueRef a0_ptr, diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index de7fe7a1796..689265fa30d 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -37,6 +37,7 @@ #include "lp_tex_sample.h" #include "lp_jit.h" +#include "lp_setup.h" struct llvmpipe_vbuf_render; @@ -90,6 +91,10 @@ struct llvmpipe_context { /** Vertex format */ struct vertex_info vertex_info; + /** Fragment shader input interpolation info */ + unsigned num_inputs; + struct lp_shader_input inputs[PIPE_MAX_SHADER_INPUTS]; + /** The tiling engine */ struct lp_setup_context *setup; diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c index b5600615420..0557d35f8b1 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -147,20 +147,32 @@ setup_fragcoord_coef(struct lp_setup_context *setup, unsigned slot, const float (*v1)[4], const float (*v2)[4], - const float (*v3)[4]) + const float (*v3)[4], + unsigned usage_mask) { /*X*/ - tri->inputs.a0[slot][0] = 0.0; - tri->inputs.dadx[slot][0] = 1.0; - tri->inputs.dady[slot][0] = 0.0; + if (usage_mask & TGSI_WRITEMASK_X) { + tri->inputs.a0[slot][0] = 0.0; + tri->inputs.dadx[slot][0] = 1.0; + tri->inputs.dady[slot][0] = 0.0; + } + /*Y*/ - tri->inputs.a0[slot][1] = 0.0; - tri->inputs.dadx[slot][1] = 0.0; - tri->inputs.dady[slot][1] = 1.0; + if (usage_mask & TGSI_WRITEMASK_Y) { + tri->inputs.a0[slot][1] = 0.0; + tri->inputs.dadx[slot][1] = 0.0; + tri->inputs.dady[slot][1] = 1.0; + } + /*Z*/ - linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 2); + if (usage_mask & TGSI_WRITEMASK_Z) { + linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 2); + } + /*W*/ - linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 3); + if (usage_mask & TGSI_WRITEMASK_W) { + linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 3); + } } @@ -171,13 +183,21 @@ setup_fragcoord_coef(struct lp_setup_context *setup, static void setup_facing_coef( struct lp_setup_context *setup, struct lp_rast_triangle *tri, unsigned slot, - boolean frontface ) + boolean frontface, + unsigned usage_mask) { /* convert TRUE to 1.0 and FALSE to -1.0 */ - constant_coef( setup, tri, slot, 2.0f * frontface - 1.0f, 0 ); - constant_coef( setup, tri, slot, 0.0f, 1 ); /* wasted */ - constant_coef( setup, tri, slot, 0.0f, 2 ); /* wasted */ - constant_coef( setup, tri, slot, 0.0f, 3 ); /* wasted */ + if (usage_mask & TGSI_WRITEMASK_X) + constant_coef( setup, tri, slot, 2.0f * frontface - 1.0f, 0 ); + + if (usage_mask & TGSI_WRITEMASK_Y) + constant_coef( setup, tri, slot, 0.0f, 1 ); /* wasted */ + + if (usage_mask & TGSI_WRITEMASK_Z) + constant_coef( setup, tri, slot, 0.0f, 2 ); /* wasted */ + + if (usage_mask & TGSI_WRITEMASK_W) + constant_coef( setup, tri, slot, 0.0f, 3 ); /* wasted */ } @@ -192,58 +212,65 @@ static void setup_tri_coefficients( struct lp_setup_context *setup, const float (*v3)[4], boolean frontface) { + unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ; unsigned slot; - /* The internal position input is in slot zero: - */ - setup_fragcoord_coef(setup, tri, oneoverarea, 0, v1, v2, v3); - /* setup interpolation for all the remaining attributes: */ for (slot = 0; slot < setup->fs.nr_inputs; slot++) { unsigned vert_attr = setup->fs.input[slot].src_index; + unsigned usage_mask = setup->fs.input[slot].usage_mask; unsigned i; switch (setup->fs.input[slot].interp) { case LP_INTERP_CONSTANT: if (setup->flatshade_first) { for (i = 0; i < NUM_CHANNELS; i++) - if (setup->fs.input[slot].usage_mask & (1 << i)) + if (usage_mask & (1 << i)) constant_coef(setup, tri, slot+1, v1[vert_attr][i], i); } else { for (i = 0; i < NUM_CHANNELS; i++) - if (setup->fs.input[slot].usage_mask & (1 << i)) + if (usage_mask & (1 << i)) constant_coef(setup, tri, slot+1, v3[vert_attr][i], i); } break; case LP_INTERP_LINEAR: for (i = 0; i < NUM_CHANNELS; i++) - if (setup->fs.input[slot].usage_mask & (1 << i)) + if (usage_mask & (1 << i)) linear_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i); break; case LP_INTERP_PERSPECTIVE: for (i = 0; i < NUM_CHANNELS; i++) - if (setup->fs.input[slot].usage_mask & (1 << i)) + if (usage_mask & (1 << i)) perspective_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i); + fragcoord_usage_mask |= TGSI_WRITEMASK_W; break; case LP_INTERP_POSITION: - /* XXX: fix me - duplicates the values in slot zero. + /* + * The generated pixel interpolators will pick up the coeffs from + * slot 0, so all need to ensure that the usage mask is covers all + * usages. */ - setup_fragcoord_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3); + fragcoord_usage_mask |= usage_mask; break; case LP_INTERP_FACING: - setup_facing_coef(setup, tri, slot+1, frontface); + setup_facing_coef(setup, tri, slot+1, frontface, usage_mask); break; default: assert(0); } } + + /* The internal position input is in slot zero: + */ + setup_fragcoord_coef(setup, tri, oneoverarea, 0, v1, v2, v3, + fragcoord_usage_mask); } diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index 773aadc92d9..46a96536075 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -50,7 +50,7 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe) { const struct lp_fragment_shader *lpfs = llvmpipe->fs; struct vertex_info *vinfo = &llvmpipe->vertex_info; - struct lp_shader_input inputs[1 + PIPE_MAX_SHADER_INPUTS]; + struct lp_shader_input *inputs = llvmpipe->inputs; unsigned vs_index; uint i; @@ -124,6 +124,7 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe) inputs[i].src_index = vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); } + llvmpipe->num_inputs = lpfs->info.num_inputs; draw_compute_vertex_size(vinfo); diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index d3f2eb2421e..835175db138 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -759,9 +759,14 @@ generate_fragment(struct llvmpipe_context *lp, generate_pos0(builder, x, y, &x0, &y0); + /* + * The shader input interpolation info is not explicitely baked in the + * shader key, but everything it derives from (TGSI, and flatshade) is + * already included in the shader key. + */ lp_build_interp_soa_init(&interp, - &shader->info, - key->flatshade, + lp->num_inputs, + lp->inputs, builder, fs_type, a0_ptr, dadx_ptr, dady_ptr, x0, y0); -- 2.30.2