/** * Helper used by lp_build_cube_lookup() * \param sign scalar +1 or -1 * \param coord float vector * \param ima float vector */ static LLVMValueRef lp_build_cube_coord(struct lp_build_context *coord_bld, LLVMValueRef sign, int negate_coord, LLVMValueRef coord, LLVMValueRef ima) { /* return negate(coord) * ima * sign + 0.5; */ LLVMValueRef half = lp_build_const_vec(coord_bld->gallivm, coord_bld->type, 0.5); LLVMValueRef res; assert(negate_coord == +1 || negate_coord == -1); if (negate_coord == -1) { coord = lp_build_negate(coord_bld, coord); } res = lp_build_mul(coord_bld, coord, ima); if (sign) { sign = lp_build_broadcast_scalar(coord_bld, sign); res = lp_build_mul(coord_bld, res, sign); } res = lp_build_add(coord_bld, res, half); return res; }
/** * Register fetch. */ static LLVMValueRef emit_fetch( struct lp_build_tgsi_aos_context *bld, const struct tgsi_full_instruction *inst, unsigned src_op) { struct lp_type type = bld->base.type; const struct tgsi_full_src_register *reg = &inst->Src[src_op]; LLVMValueRef res; unsigned chan; assert(!reg->Register.Indirect); /* * Fetch the from the register file. */ switch (reg->Register.File) { case TGSI_FILE_CONSTANT: /* * Get the constants components */ res = bld->base.undef; for (chan = 0; chan < 4; ++chan) { LLVMValueRef index; LLVMValueRef scalar_ptr; LLVMValueRef scalar; LLVMValueRef swizzle; index = LLVMConstInt(LLVMInt32Type(), reg->Register.Index*4 + chan, 0); scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->consts_ptr, &index, 1, ""); scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, ""); lp_build_name(scalar, "const[%u].%c", reg->Register.Index, "xyzw"[chan]); /* * NOTE: constants array is always assumed to be RGBA */ swizzle = LLVMConstInt(LLVMInt32Type(), chan, 0); res = LLVMBuildInsertElement(bld->base.builder, res, scalar, swizzle, ""); } /* * Broadcast the first quaternion to all others. * * XXX: could be factored into a reusable function. */ if (type.length > 4) { LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH]; unsigned i; for (chan = 0; chan < 4; ++chan) { shuffles[chan] = LLVMConstInt(LLVMInt32Type(), chan, 0); } for (i = 4; i < type.length; ++i) { shuffles[i] = shuffles[i % 4]; } res = LLVMBuildShuffleVector(bld->base.builder, res, bld->base.undef, LLVMConstVector(shuffles, type.length), ""); } break; case TGSI_FILE_IMMEDIATE: res = bld->immediates[reg->Register.Index]; assert(res); break; case TGSI_FILE_INPUT: res = bld->inputs[reg->Register.Index]; assert(res); break; case TGSI_FILE_TEMPORARY: { LLVMValueRef temp_ptr; temp_ptr = bld->temps[reg->Register.Index]; res = LLVMBuildLoad(bld->base.builder, temp_ptr, ""); if (!res) return bld->base.undef; } break; default: assert(0 && "invalid src register in emit_fetch()"); return bld->base.undef; } /* * Apply sign modifier. */ if (reg->Register.Absolute) { res = lp_build_abs(&bld->base, res); } if(reg->Register.Negate) { res = lp_build_negate(&bld->base, res); } /* * Swizzle the argument */ res = swizzle_aos(bld, res, reg->Register.SwizzleX, reg->Register.SwizzleY, reg->Register.SwizzleZ, reg->Register.SwizzleW); return res; }