diff options
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_bld_interp.c | 165 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_bld_interp.h | 11 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_context.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_tri.c | 77 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_derived.c | 3 | ||||
-rw-r--r-- | 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); |