X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_state_fs.c;h=b00be0cc32af5635c1a40028be93457397c3587e;hb=5d2413fca4c252ec5c7880fa7f983b5df3d762ba;hp=a9b2d48244614dc31560a0e5f1a79dd6c680575d;hpb=5811ed87d732101ab8cfbd087bc99d8c6c963f30;p=mesa.git diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index a9b2d482446..b00be0cc32a 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -69,9 +69,12 @@ #include "tgsi/tgsi_scan.h" #include "tgsi/tgsi_parse.h" #include "lp_bld_type.h" +#include "lp_bld_const.h" #include "lp_bld_conv.h" +#include "lp_bld_intr.h" #include "lp_bld_logic.h" #include "lp_bld_depth.h" +#include "lp_bld_interp.h" #include "lp_bld_tgsi.h" #include "lp_bld_alpha.h" #include "lp_bld_blend.h" @@ -82,28 +85,23 @@ #include "lp_context.h" #include "lp_state.h" #include "lp_quad.h" +#include "lp_tex_sample.h" static const unsigned char quad_offset_x[4] = {0, 1, 0, 1}; static const unsigned char quad_offset_y[4] = {0, 0, 1, 1}; -/** - * Generate the position vectors. - * - * TODO: This should be called only once per fragment pipeline, for the first - * quad, and the neighboring quad positions obtained by additions. - * - * Parameter x, y are the integer values with the quad upper left coordinates. +/* + * Derive from the quad's upper left scalar coordinates the coordinates for + * all other quad pixels */ static void -generate_pos(LLVMBuilderRef builder, - LLVMValueRef x, - LLVMValueRef y, - LLVMValueRef a0_ptr, - LLVMValueRef dadx_ptr, - LLVMValueRef dady_ptr, - LLVMValueRef *pos) +generate_pos0(LLVMBuilderRef builder, + LLVMValueRef x, + LLVMValueRef y, + LLVMValueRef *x0, + LLVMValueRef *y0) { LLVMTypeRef int_elem_type = LLVMInt32Type(); LLVMTypeRef int_vec_type = LLVMVectorType(int_elem_type, QUAD_SIZE); @@ -111,14 +109,8 @@ generate_pos(LLVMBuilderRef builder, LLVMTypeRef vec_type = LLVMVectorType(elem_type, QUAD_SIZE); LLVMValueRef x_offsets[QUAD_SIZE]; LLVMValueRef y_offsets[QUAD_SIZE]; - unsigned chan; unsigned i; - /* - * Derive from the quad's upper left scalar coordinates the coordinates for - * all other quad pixels - */ - x = lp_build_broadcast(builder, int_vec_type, x); y = lp_build_broadcast(builder, int_vec_type, y); @@ -130,33 +122,8 @@ generate_pos(LLVMBuilderRef builder, x = LLVMBuildAdd(builder, x, LLVMConstVector(x_offsets, QUAD_SIZE), ""); y = LLVMBuildAdd(builder, y, LLVMConstVector(y_offsets, QUAD_SIZE), ""); - x = LLVMBuildSIToFP(builder, x, vec_type, ""); - y = LLVMBuildSIToFP(builder, y, vec_type, ""); - - pos[0] = x; - pos[1] = y; - - /* - * Calculate z and w from the interpolation factors. - */ - - for(chan = 2; chan < NUM_CHANNELS; ++chan) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0); - LLVMValueRef a0 = LLVMBuildLoad(builder, LLVMBuildGEP(builder, a0_ptr, &index, 1, ""), ""); - LLVMValueRef dadx = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dadx_ptr, &index, 1, ""), ""); - LLVMValueRef dady = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dady_ptr, &index, 1, ""), ""); - LLVMValueRef res; - a0 = lp_build_broadcast(builder, vec_type, a0); - dadx = lp_build_broadcast(builder, vec_type, dadx); - dady = lp_build_broadcast(builder, vec_type, dady); - res = a0; - res = LLVMBuildAdd(builder, res, LLVMBuildMul(builder, dadx, x, ""), ""); - res = LLVMBuildAdd(builder, res, LLVMBuildMul(builder, dady, y, ""), ""); - pos[chan] = res; - } - - for(chan = 0; chan < NUM_CHANNELS; ++chan) - lp_build_name(pos[chan], "pos.%c", "xyzw"[chan]); + *x0 = LLVMBuildSIToFP(builder, x, vec_type, ""); + *y0 = LLVMBuildSIToFP(builder, y, vec_type, ""); } @@ -164,21 +131,20 @@ generate_pos(LLVMBuilderRef builder, * Generate the depth test. */ static void -generate_depth(struct llvmpipe_context *lp, - LLVMBuilderRef builder, - const struct pipe_depth_state *state, - union lp_type src_type, +generate_depth(LLVMBuilderRef builder, + const struct lp_fragment_shader_variant_key *key, + struct lp_type src_type, struct lp_build_mask_context *mask, LLVMValueRef src, LLVMValueRef dst_ptr) { const struct util_format_description *format_desc; - union lp_type dst_type; + struct lp_type dst_type; - if(!lp->framebuffer.zsbuf) + if(!key->depth.enabled) return; - format_desc = util_format_description(lp->framebuffer.zsbuf->format); + format_desc = util_format_description(key->zsbuf_format); assert(format_desc); /* Pick the depth type. */ @@ -198,7 +164,7 @@ generate_depth(struct llvmpipe_context *lp, #endif lp_build_depth_test(builder, - state, + &key->depth, dst_type, format_desc, mask, @@ -215,25 +181,23 @@ generate_fs(struct llvmpipe_context *lp, struct lp_fragment_shader *shader, const struct lp_fragment_shader_variant_key *key, LLVMBuilderRef builder, - union lp_type type, + struct lp_type type, + LLVMValueRef context_ptr, unsigned i, - LLVMValueRef x, - LLVMValueRef y, - LLVMValueRef a0_ptr, - LLVMValueRef dadx_ptr, - LLVMValueRef dady_ptr, - LLVMValueRef consts_ptr, + const struct lp_build_interp_soa_context *interp, + struct lp_build_sampler_soa *sampler, LLVMValueRef *pmask, LLVMValueRef *color, - LLVMValueRef depth_ptr, - LLVMValueRef samplers_ptr) + LLVMValueRef depth_ptr) { const struct tgsi_token *tokens = shader->base.tokens; LLVMTypeRef elem_type; LLVMTypeRef vec_type; LLVMTypeRef int_vec_type; - LLVMValueRef pos[NUM_CHANNELS]; + LLVMValueRef consts_ptr; LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS]; + LLVMValueRef z = interp->pos[2]; + struct lp_build_flow_context *flow; struct lp_build_mask_context mask; boolean early_depth_test; unsigned attrib; @@ -243,27 +207,37 @@ generate_fs(struct llvmpipe_context *lp, vec_type = lp_build_vec_type(type); int_vec_type = lp_build_int_vec_type(type); - generate_pos(builder, x, y, a0_ptr, dadx_ptr, dady_ptr, pos); + consts_ptr = lp_jit_context_constants(builder, context_ptr); + + flow = lp_build_flow_create(builder); + + memset(outputs, 0, sizeof outputs); + + lp_build_flow_scope_begin(flow); - lp_build_mask_begin(&mask, builder, type, *pmask); + /* Declare the color and z variables */ + for(chan = 0; chan < NUM_CHANNELS; ++chan) { + color[chan] = LLVMGetUndef(vec_type); + lp_build_flow_scope_declare(flow, &color[chan]); + } + lp_build_flow_scope_declare(flow, &z); + + lp_build_mask_begin(&mask, flow, type, *pmask); early_depth_test = - lp->depth_stencil->depth.enabled && - lp->framebuffer.zsbuf && - !lp->depth_stencil->alpha.enabled && - !lp->fs->info.uses_kill && - !lp->fs->info.writes_z; + key->depth.enabled && + !key->alpha.enabled && + !shader->info.uses_kill && + !shader->info.writes_z; if(early_depth_test) - generate_depth(lp, builder, &key->depth, - type, &mask, - pos[2], depth_ptr); - - memset(outputs, 0, sizeof outputs); + generate_depth(builder, key, + type, &mask, + z, depth_ptr); lp_build_tgsi_soa(builder, tokens, type, &mask, - pos, a0_ptr, dadx_ptr, dady_ptr, - consts_ptr, outputs, samplers_ptr); + consts_ptr, interp->pos, interp->inputs, + outputs, sampler); for (attrib = 0; attrib < shader->info.num_outputs; ++attrib) { for(chan = 0; chan < NUM_CHANNELS; ++chan) { @@ -279,10 +253,14 @@ generate_fs(struct llvmpipe_context *lp, /* Alpha test */ /* XXX: should the alpha reference value be passed separately? */ - if(cbuf == 0 && chan == 3) + if(cbuf == 0 && chan == 3) { + LLVMValueRef alpha = outputs[attrib][chan]; + LLVMValueRef alpha_ref_value; + alpha_ref_value = lp_jit_context_alpha_ref_value(builder, context_ptr); + alpha_ref_value = lp_build_broadcast(builder, vec_type, alpha_ref_value); lp_build_alpha_test(builder, &key->alpha, type, - &mask, - outputs[attrib][chan]); + &mask, alpha, alpha_ref_value); + } if(cbuf == 0) color[chan] = outputs[attrib][chan]; @@ -292,7 +270,7 @@ generate_fs(struct llvmpipe_context *lp, case TGSI_SEMANTIC_POSITION: if(chan == 2) - pos[2] = outputs[attrib][chan]; + z = outputs[attrib][chan]; break; } } @@ -300,12 +278,16 @@ generate_fs(struct llvmpipe_context *lp, } if(!early_depth_test) - generate_depth(lp, builder, &key->depth, - type, &mask, - pos[2], depth_ptr); + generate_depth(builder, key, + type, &mask, + z, depth_ptr); lp_build_mask_end(&mask); + lp_build_flow_scope_end(flow); + + lp_build_flow_destroy(flow); + *pmask = mask.value; } @@ -317,32 +299,38 @@ generate_fs(struct llvmpipe_context *lp, static void generate_blend(const struct pipe_blend_state *blend, LLVMBuilderRef builder, - union lp_type type, + struct lp_type type, + LLVMValueRef context_ptr, LLVMValueRef mask, LLVMValueRef *src, - LLVMValueRef const_ptr, LLVMValueRef dst_ptr) { struct lp_build_context bld; + struct lp_build_flow_context *flow; + struct lp_build_mask_context mask_ctx; LLVMTypeRef vec_type; LLVMTypeRef int_vec_type; + LLVMValueRef const_ptr; LLVMValueRef con[4]; LLVMValueRef dst[4]; LLVMValueRef res[4]; unsigned chan; + lp_build_context_init(&bld, builder, type); + + flow = lp_build_flow_create(builder); + lp_build_mask_begin(&mask_ctx, flow, type, mask); + vec_type = lp_build_vec_type(type); int_vec_type = lp_build_int_vec_type(type); - lp_build_context_init(&bld, builder, type); + const_ptr = lp_jit_context_blend_color(builder, context_ptr); + const_ptr = LLVMBuildBitCast(builder, const_ptr, + LLVMPointerType(vec_type, 0), ""); for(chan = 0; chan < 4; ++chan) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0); - - if(const_ptr) - con[chan] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, const_ptr, &index, 1, ""), ""); - else - con[chan] = LLVMGetUndef(vec_type); /* FIXME */ + con[chan] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, const_ptr, &index, 1, ""), ""); dst[chan] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dst_ptr, &index, 1, ""), ""); @@ -353,11 +341,16 @@ generate_blend(const struct pipe_blend_state *blend, lp_build_blend_soa(builder, blend, type, src, dst, con, res); for(chan = 0; chan < 4; ++chan) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0); - lp_build_name(res[chan], "res.%c", "rgba"[chan]); - res[chan] = lp_build_select(&bld, mask, res[chan], dst[chan]); - LLVMBuildStore(builder, res[chan], LLVMBuildGEP(builder, dst_ptr, &index, 1, "")); + if(blend->colormask & (1 << chan)) { + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0); + lp_build_name(res[chan], "res.%c", "rgba"[chan]); + res[chan] = lp_build_select(&bld, mask, res[chan], dst[chan]); + LLVMBuildStore(builder, res[chan], LLVMBuildGEP(builder, dst_ptr, &index, 1, "")); + } } + + lp_build_mask_end(&mask_ctx); + lp_build_flow_destroy(flow); } @@ -371,32 +364,34 @@ generate_fragment(struct llvmpipe_context *lp, { struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen); struct lp_fragment_shader_variant *variant; - union lp_type fs_type; - union lp_type blend_type; + struct lp_type fs_type; + struct lp_type blend_type; LLVMTypeRef fs_elem_type; LLVMTypeRef fs_vec_type; LLVMTypeRef fs_int_vec_type; LLVMTypeRef blend_vec_type; LLVMTypeRef blend_int_vec_type; - LLVMTypeRef arg_types[10]; + LLVMTypeRef arg_types[9]; LLVMTypeRef func_type; + LLVMValueRef context_ptr; LLVMValueRef x; LLVMValueRef y; LLVMValueRef a0_ptr; LLVMValueRef dadx_ptr; LLVMValueRef dady_ptr; - LLVMValueRef consts_ptr; LLVMValueRef mask_ptr; LLVMValueRef color_ptr; LLVMValueRef depth_ptr; - LLVMValueRef samplers_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; + LLVMValueRef x0; + LLVMValueRef y0; + struct lp_build_sampler_soa *sampler; + struct lp_build_interp_soa_context interp; LLVMValueRef fs_mask[LP_MAX_VECTOR_LENGTH]; LLVMValueRef fs_out_color[NUM_CHANNELS][LP_MAX_VECTOR_LENGTH]; LLVMValueRef blend_mask; LLVMValueRef blend_in_color[NUM_CHANNELS]; - LLVMValueRef fetch_texel; unsigned num_fs; unsigned i; unsigned chan; @@ -406,7 +401,6 @@ generate_fragment(struct llvmpipe_context *lp, if(key->depth.enabled) { debug_printf("depth.func = %s\n", debug_dump_func(key->depth.func, TRUE)); debug_printf("depth.writemask = %u\n", key->depth.writemask); - debug_printf("depth.occlusion_count = %u\n", key->depth.occlusion_count); } if(key->alpha.enabled) { debug_printf("alpha.func = %s\n", debug_dump_func(key->alpha.func, TRUE)); @@ -436,7 +430,7 @@ generate_fragment(struct llvmpipe_context *lp, /* TODO: actually pick these based on the fs and color buffer * characteristics. */ - fs_type.value = 0; + memset(&fs_type, 0, sizeof fs_type); fs_type.floating = TRUE; /* floating point values */ fs_type.sign = TRUE; /* values are signed */ fs_type.norm = FALSE; /* values are not limited to [0,1] or [-1,1] */ @@ -444,7 +438,7 @@ generate_fragment(struct llvmpipe_context *lp, fs_type.length = 4; /* 4 element per vector */ num_fs = 4; - blend_type.value = 0; + memset(&blend_type, 0, sizeof blend_type); blend_type.floating = FALSE; /* values are integers */ blend_type.sign = FALSE; /* values are unsigned */ blend_type.norm = TRUE; /* values are in [0,1] or [-1,1] */ @@ -453,7 +447,7 @@ generate_fragment(struct llvmpipe_context *lp, /* * Generate the function prototype. Any change here must be reflected in - * lp_state.h's lp_shader_fs_func function pointer type, and vice-versa. + * lp_jit.h's lp_jit_frag_func function pointer type, and vice-versa. */ fs_elem_type = lp_build_elem_type(fs_type); @@ -463,16 +457,15 @@ generate_fragment(struct llvmpipe_context *lp, blend_vec_type = lp_build_vec_type(blend_type); blend_int_vec_type = lp_build_int_vec_type(blend_type); - arg_types[0] = LLVMInt32Type(); /* x */ - arg_types[1] = LLVMInt32Type(); /* y */ - arg_types[2] = LLVMPointerType(fs_elem_type, 0); /* a0 */ - arg_types[3] = LLVMPointerType(fs_elem_type, 0); /* dadx */ - arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* dady */ - arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* consts */ + arg_types[0] = screen->context_ptr_type; /* context */ + arg_types[1] = LLVMInt32Type(); /* x */ + arg_types[2] = LLVMInt32Type(); /* y */ + arg_types[3] = LLVMPointerType(fs_elem_type, 0); /* a0 */ + arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* dadx */ + arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dady */ arg_types[6] = LLVMPointerType(fs_int_vec_type, 0); /* mask */ arg_types[7] = LLVMPointerType(blend_vec_type, 0); /* color */ arg_types[8] = LLVMPointerType(fs_int_vec_type, 0); /* depth */ - arg_types[9] = LLVMPointerType(LLVMInt8Type(), 0); /* samplers */ func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); @@ -482,27 +475,25 @@ generate_fragment(struct llvmpipe_context *lp, if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) LLVMAddAttribute(LLVMGetParam(variant->function, i), LLVMNoAliasAttribute); - x = LLVMGetParam(variant->function, 0); - y = LLVMGetParam(variant->function, 1); - a0_ptr = LLVMGetParam(variant->function, 2); - dadx_ptr = LLVMGetParam(variant->function, 3); - dady_ptr = LLVMGetParam(variant->function, 4); - consts_ptr = LLVMGetParam(variant->function, 5); + context_ptr = LLVMGetParam(variant->function, 0); + x = LLVMGetParam(variant->function, 1); + y = LLVMGetParam(variant->function, 2); + a0_ptr = LLVMGetParam(variant->function, 3); + dadx_ptr = LLVMGetParam(variant->function, 4); + dady_ptr = LLVMGetParam(variant->function, 5); mask_ptr = LLVMGetParam(variant->function, 6); color_ptr = LLVMGetParam(variant->function, 7); depth_ptr = LLVMGetParam(variant->function, 8); - samplers_ptr = LLVMGetParam(variant->function, 9); + lp_build_name(context_ptr, "context"); lp_build_name(x, "x"); lp_build_name(y, "y"); lp_build_name(a0_ptr, "a0"); lp_build_name(dadx_ptr, "dadx"); lp_build_name(dady_ptr, "dady"); - lp_build_name(consts_ptr, "consts"); lp_build_name(mask_ptr, "mask"); lp_build_name(color_ptr, "color"); lp_build_name(depth_ptr, "depth"); - lp_build_name(samplers_ptr, "samplers"); /* * Function body @@ -512,39 +503,48 @@ generate_fragment(struct llvmpipe_context *lp, builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, block); + generate_pos0(builder, x, y, &x0, &y0); + + lp_build_interp_soa_init(&interp, shader->base.tokens, builder, fs_type, + a0_ptr, dadx_ptr, dady_ptr, + x0, y0, 2, 0); + +#if 0 + /* C texture sampling */ + sampler = lp_c_sampler_soa_create(context_ptr); +#else + /* code generated texture sampling */ + sampler = lp_llvm_sampler_soa_create(key->sampler, context_ptr); +#endif + for(i = 0; i < num_fs; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); LLVMValueRef out_color[NUM_CHANNELS]; - LLVMValueRef x_i; LLVMValueRef depth_ptr_i; - /* TODO: Reuse position interpolation */ - x_i = LLVMBuildAdd(builder, x, LLVMConstInt(LLVMInt32Type(), 2*i, 0), ""); + if(i != 0) + lp_build_interp_soa_update(&interp); fs_mask[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, mask_ptr, &index, 1, ""), ""); depth_ptr_i = LLVMBuildGEP(builder, depth_ptr, &index, 1, ""); - generate_fs(lp, - shader, - key, + generate_fs(lp, shader, key, builder, fs_type, + context_ptr, i, - x_i, - y, - a0_ptr, - dadx_ptr, - dady_ptr, - consts_ptr, + &interp, + sampler, &fs_mask[i], out_color, - depth_ptr_i, - samplers_ptr); + depth_ptr_i); for(chan = 0; chan < NUM_CHANNELS; ++chan) fs_out_color[chan][i] = out_color[chan]; } + sampler->destroy(sampler); + /* * Convert the fs's output color and mask to fit to the blending type. */ @@ -554,6 +554,7 @@ generate_fragment(struct llvmpipe_context *lp, fs_out_color[chan], num_fs, &blend_in_color[chan], 1); lp_build_name(blend_in_color[chan], "color.%c", "rgba"[chan]); + } lp_build_conv_mask(builder, fs_type, blend_type, @@ -567,9 +568,9 @@ generate_fragment(struct llvmpipe_context *lp, generate_blend(&key->blend, builder, blend_type, + context_ptr, blend_mask, blend_in_color, - NULL /* FIXME: blend_const_color */, color_ptr); LLVMBuildRetVoid(builder); @@ -580,6 +581,11 @@ generate_fragment(struct llvmpipe_context *lp, * Translate the LLVM IR into machine code. */ + if(LLVMVerifyFunction(variant->function, LLVMPrintMessageAction)) { + LLVMDumpValue(variant->function); + abort(); + } + LLVMRunFunctionPassManager(screen->pass, variant->function); #ifdef DEBUG @@ -587,24 +593,7 @@ generate_fragment(struct llvmpipe_context *lp, debug_printf("\n"); #endif - if(LLVMVerifyFunction(variant->function, LLVMPrintMessageAction)) { - LLVMDumpValue(variant->function); - abort(); - } - - /* Tell where the fetch_texel function is, if the shader refers to it. - * TODO: this should be done elsewhere. - */ - fetch_texel = LLVMGetNamedFunction(screen->module, "fetch_texel"); - if(fetch_texel) { - static boolean first_time = TRUE; - if(first_time) { - LLVMAddGlobalMapping(screen->engine, fetch_texel, lp_build_tgsi_fetch_texel_soa); - first_time = FALSE; - } - } - - variant->jit_function = (lp_shader_fs_func)LLVMGetPointerToGlobal(screen->engine, variant->function); + variant->jit_function = (lp_jit_frag_func)LLVMGetPointerToGlobal(screen->engine, variant->function); #ifdef DEBUG lp_disassemble(variant->jit_function); @@ -697,6 +686,57 @@ llvmpipe_set_constant_buffer(struct pipe_context *pipe, } +/** + * We need to generate several variants of the fragment pipeline to match + * all the combinations of the contributing state atoms. + * + * TODO: there is actually no reason to tie this to context state -- the + * generated code could be cached globally in the screen. + */ +static void +make_variant_key(struct llvmpipe_context *lp, + struct lp_fragment_shader *shader, + struct lp_fragment_shader_variant_key *key) +{ + unsigned i; + + memset(key, 0, sizeof *key); + + if(lp->framebuffer.zsbuf && + lp->depth_stencil->depth.enabled) { + key->zsbuf_format = lp->framebuffer.zsbuf->format; + memcpy(&key->depth, &lp->depth_stencil->depth, sizeof key->depth); + } + + key->alpha.enabled = lp->depth_stencil->alpha.enabled; + if(key->alpha.enabled) + key->alpha.func = lp->depth_stencil->alpha.func; + /* alpha.ref_value is passed in jit_context */ + + if(lp->framebuffer.cbufs[0]) { + const struct util_format_description *format_desc; + unsigned chan; + + memcpy(&key->blend, lp->blend, sizeof key->blend); + + format_desc = util_format_description(lp->framebuffer.cbufs[0]->format); + assert(format_desc->layout == UTIL_FORMAT_COLORSPACE_RGB || + format_desc->layout == UTIL_FORMAT_COLORSPACE_SRGB); + + /* mask out color channels not present in the color buffer */ + for(chan = 0; chan < 4; ++chan) { + enum util_format_swizzle swizzle = format_desc->swizzle[chan]; + if(swizzle > 4) + key->blend.colormask &= ~(1 << chan); + } + } + + for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) + if(shader->info.file_mask[TGSI_FILE_SAMPLER] & (1 << i)) + lp_sampler_static_state(&key->sampler[i], lp->texture[i], lp->sampler[i]); +} + + void llvmpipe_update_fs(struct llvmpipe_context *lp) { @@ -704,17 +744,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) struct lp_fragment_shader_variant_key key; struct lp_fragment_shader_variant *variant; - /* We need to generate several variants of the fragment pipeline to match - * all the combinations of the contributing state atoms. - * - * TODO: there is actually no reason to tie this to context state -- the - * generated code could be cached globally in the screen. - */ - - memset(&key, 0, sizeof key); - memcpy(&key.depth, &lp->depth_stencil->depth, sizeof &key.depth); - memcpy(&key.alpha, &lp->depth_stencil->alpha, sizeof &key.alpha); - memcpy(&key.blend, &lp->blend->base, sizeof &key.blend); + make_variant_key(lp, shader, &key); variant = shader->variants; while(variant) {