void lp_emit_declaration_aos( struct lp_build_tgsi_aos_context *bld, const struct tgsi_full_declaration *decl) { struct gallivm_state *gallivm = bld->bld_base.base.gallivm; LLVMTypeRef vec_type = lp_build_vec_type(bld->bld_base.base.gallivm, bld->bld_base.base.type); unsigned first = decl->Range.First; unsigned last = decl->Range.Last; unsigned idx; for (idx = first; idx <= last; ++idx) { switch (decl->Declaration.File) { case TGSI_FILE_TEMPORARY: assert(idx < LP_MAX_INLINED_TEMPS); if (bld->indirect_files & (1 << TGSI_FILE_TEMPORARY)) { LLVMValueRef array_size = lp_build_const_int32(gallivm, last + 1); bld->temps_array = lp_build_array_alloca(bld->bld_base.base.gallivm, vec_type, array_size, ""); } else { bld->temps[idx] = lp_build_alloca(gallivm, vec_type, ""); } break; case TGSI_FILE_OUTPUT: bld->outputs[idx] = lp_build_alloca(gallivm, vec_type, ""); break; case TGSI_FILE_ADDRESS: assert(idx < LP_MAX_TGSI_ADDRS); bld->addr[idx] = lp_build_alloca(gallivm, vec_type, ""); break; case TGSI_FILE_PREDICATE: assert(idx < LP_MAX_TGSI_PREDS); bld->preds[idx] = lp_build_alloca(gallivm, vec_type, ""); break; case TGSI_FILE_SAMPLER_VIEW: /* * The target stored here MUST match whatever there actually * is in the set sampler views (what about return type?). */ assert(last < PIPE_MAX_SHADER_SAMPLER_VIEWS); for (idx = first; idx <= last; ++idx) { bld->sv[idx] = decl->SamplerView; } break; default: /* don't need to declare other vars */ break; } } }
static void emit_declaration( struct lp_build_tgsi_aos_context *bld, const struct tgsi_full_declaration *decl) { LLVMTypeRef vec_type = lp_build_vec_type(bld->base.type); unsigned first = decl->Range.First; unsigned last = decl->Range.Last; unsigned idx; for (idx = first; idx <= last; ++idx) { switch (decl->Declaration.File) { case TGSI_FILE_TEMPORARY: assert(idx < LP_MAX_TGSI_TEMPS); if (bld->indirect_files & (1 << TGSI_FILE_TEMPORARY)) { LLVMValueRef array_size = LLVMConstInt(LLVMInt32Type(), last + 1, 0); bld->temps_array = lp_build_array_alloca(bld->base.builder, vec_type, array_size, ""); } else { bld->temps[idx] = lp_build_alloca(bld->base.builder, vec_type, ""); } break; case TGSI_FILE_OUTPUT: bld->outputs[idx] = lp_build_alloca(bld->base.builder, vec_type, ""); break; case TGSI_FILE_ADDRESS: assert(idx < LP_MAX_TGSI_ADDRS); bld->addr[idx] = lp_build_alloca(bld->base.builder, vec_type, ""); break; case TGSI_FILE_PREDICATE: assert(idx < LP_MAX_TGSI_PREDS); bld->preds[idx] = lp_build_alloca(bld->base.builder, vec_type, ""); break; default: /* don't need to declare other vars */ break; } } }
/** * Initialize fragment shader input attribute info. */ void lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, struct gallivm_state *gallivm, unsigned num_inputs, const struct lp_shader_input *inputs, boolean pixel_center_integer, LLVMBuilderRef builder, struct lp_type type, LLVMValueRef a0_ptr, LLVMValueRef dadx_ptr, LLVMValueRef dady_ptr, LLVMValueRef x0, LLVMValueRef y0) { struct lp_type coeff_type; struct lp_type setup_type; unsigned attrib; unsigned chan; memset(bld, 0, sizeof *bld); memset(&coeff_type, 0, sizeof coeff_type); coeff_type.floating = TRUE; coeff_type.sign = TRUE; coeff_type.width = 32; coeff_type.length = type.length; memset(&setup_type, 0, sizeof setup_type); setup_type.floating = TRUE; setup_type.sign = TRUE; setup_type.width = 32; setup_type.length = TGSI_NUM_CHANNELS; /* XXX: we don't support interpolating into any other types */ assert(memcmp(&coeff_type, &type, sizeof coeff_type) == 0); lp_build_context_init(&bld->coeff_bld, gallivm, coeff_type); lp_build_context_init(&bld->setup_bld, gallivm, setup_type); /* For convenience */ bld->pos = bld->attribs[0]; bld->inputs = (const LLVMValueRef (*)[TGSI_NUM_CHANNELS]) bld->attribs[1]; /* Position */ bld->mask[0] = TGSI_WRITEMASK_XYZW; bld->interp[0] = LP_INTERP_LINEAR; /* Inputs */ 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 + num_inputs; /* Ensure all masked out input channels have a valid value */ for (attrib = 0; attrib < bld->num_attribs; ++attrib) { for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) { bld->attribs[attrib][chan] = bld->coeff_bld.undef; } } if (pixel_center_integer) { bld->pos_offset = 0.0; } else { bld->pos_offset = 0.5; } pos_init(bld, x0, y0); /* * Simple method (single step interpolation) may be slower if vector length * is just 4, but the results are different (generally less accurate) with * the other method, so always use more accurate version. */ if (1) { bld->simple_interp = TRUE; { /* XXX this should use a global static table */ unsigned i; unsigned num_loops = 16 / type.length; LLVMValueRef pixoffx, pixoffy, index; LLVMValueRef ptr; bld->xoffset_store = lp_build_array_alloca(gallivm, lp_build_vec_type(gallivm, type), lp_build_const_int32(gallivm, num_loops), ""); bld->yoffset_store = lp_build_array_alloca(gallivm, lp_build_vec_type(gallivm, type), lp_build_const_int32(gallivm, num_loops), ""); for (i = 0; i < num_loops; i++) { index = lp_build_const_int32(gallivm, i); calc_offsets(&bld->coeff_bld, i*type.length/4, &pixoffx, &pixoffy); ptr = LLVMBuildGEP(builder, bld->xoffset_store, &index, 1, ""); LLVMBuildStore(builder, pixoffx, ptr); ptr = LLVMBuildGEP(builder, bld->yoffset_store, &index, 1, ""); LLVMBuildStore(builder, pixoffy, ptr); } } coeffs_init_simple(bld, a0_ptr, dadx_ptr, dady_ptr); } else { bld->simple_interp = FALSE; coeffs_init(bld, a0_ptr, dadx_ptr, dady_ptr); } }
static void update_cached_block(struct gallivm_state *gallivm, const struct util_format_description *format_desc, LLVMValueRef ptr_addr, LLVMValueRef hash_index, LLVMValueRef cache) { LLVMBuilderRef builder = gallivm->builder; LLVMTypeRef i8t = LLVMInt8TypeInContext(gallivm->context); LLVMTypeRef pi8t = LLVMPointerType(i8t, 0); LLVMTypeRef i32t = LLVMInt32TypeInContext(gallivm->context); LLVMTypeRef i32x4 = LLVMVectorType(LLVMInt32TypeInContext(gallivm->context), 4); LLVMValueRef function; LLVMValueRef tag_value, tmp_ptr; LLVMValueRef col[4]; unsigned i, j; /* * Use format_desc->fetch_rgba_8unorm() for each pixel in the block. * This doesn't actually make any sense whatsoever, someone would need * to write a function doing this for all pixels in a block (either as * an external c function or with generated code). Don't ask. */ { /* * Function to call looks like: * fetch(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) */ LLVMTypeRef ret_type; LLVMTypeRef arg_types[4]; LLVMTypeRef function_type; assert(format_desc->fetch_rgba_8unorm); ret_type = LLVMVoidTypeInContext(gallivm->context); arg_types[0] = pi8t; arg_types[1] = pi8t; arg_types[2] = i32t; arg_types[3] = i32t; function_type = LLVMFunctionType(ret_type, arg_types, ARRAY_SIZE(arg_types), 0); /* make const pointer for the C fetch_rgba_8unorm function */ function = lp_build_const_int_pointer(gallivm, func_to_pointer((func_pointer) format_desc->fetch_rgba_8unorm)); /* cast the callee pointer to the function's type */ function = LLVMBuildBitCast(builder, function, LLVMPointerType(function_type, 0), "cast callee"); } tmp_ptr = lp_build_array_alloca(gallivm, i32x4, lp_build_const_int32(gallivm, 16), "tmp_decode_store"); tmp_ptr = LLVMBuildBitCast(builder, tmp_ptr, pi8t, ""); /* * Invoke format_desc->fetch_rgba_8unorm() for each pixel. * This is going to be really really slow. * Note: the block store format is actually * x0y0x0y1x0y2x0y3 x1y0x1y1x1y2x1y3 ... */ for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { LLVMValueRef args[4]; LLVMValueRef dst_offset = lp_build_const_int32(gallivm, (i * 4 + j) * 4); /* * Note we actually supply a pointer to the start of the block, * not the start of the texture. */ args[0] = LLVMBuildGEP(gallivm->builder, tmp_ptr, &dst_offset, 1, ""); args[1] = ptr_addr; args[2] = LLVMConstInt(i32t, i, 0); args[3] = LLVMConstInt(i32t, j, 0); LLVMBuildCall(builder, function, args, ARRAY_SIZE(args), ""); } } /* Finally store the block - pointless mem copy + update tag. */ tmp_ptr = LLVMBuildBitCast(builder, tmp_ptr, LLVMPointerType(i32x4, 0), ""); for (i = 0; i < 4; ++i) { LLVMValueRef tmp_offset = lp_build_const_int32(gallivm, i); LLVMValueRef ptr = LLVMBuildGEP(gallivm->builder, tmp_ptr, &tmp_offset, 1, ""); col[i] = LLVMBuildLoad(builder, ptr, ""); } tag_value = LLVMBuildPtrToInt(gallivm->builder, ptr_addr, LLVMInt64TypeInContext(gallivm->context), ""); store_cached_block(gallivm, col, tag_value, hash_index, cache); }