LLVMValueRef ac_build_clamp(struct ac_llvm_context *ctx, LLVMValueRef value) { if (HAVE_LLVM >= 0x0500) { LLVMValueRef max[2] = { value, LLVMConstReal(ctx->f32, 0), }; LLVMValueRef min[2] = { LLVMConstReal(ctx->f32, 1), }; min[1] = ac_build_intrinsic(ctx, "llvm.maxnum.f32", ctx->f32, max, 2, AC_FUNC_ATTR_READNONE); return ac_build_intrinsic(ctx, "llvm.minnum.f32", ctx->f32, min, 2, AC_FUNC_ATTR_READNONE); } LLVMValueRef args[3] = { value, LLVMConstReal(ctx->f32, 0), LLVMConstReal(ctx->f32, 1), }; return ac_build_intrinsic(ctx, "llvm.AMDGPU.clamp.", ctx->f32, args, 3, AC_FUNC_ATTR_READNONE | AC_FUNC_ATTR_LEGACY); }
static void emit_ssg(const struct lp_build_tgsi_action *action, struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { LLVMBuilderRef builder = bld_base->base.gallivm->builder; LLVMValueRef cmp, val; if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_I64SSG) { cmp = LLVMBuildICmp(builder, LLVMIntSGT, emit_data->args[0], bld_base->int64_bld.zero, ""); val = LLVMBuildSelect(builder, cmp, bld_base->int64_bld.one, emit_data->args[0], ""); cmp = LLVMBuildICmp(builder, LLVMIntSGE, val, bld_base->int64_bld.zero, ""); val = LLVMBuildSelect(builder, cmp, val, LLVMConstInt(bld_base->int64_bld.elem_type, -1, true), ""); } else if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_ISSG) { cmp = LLVMBuildICmp(builder, LLVMIntSGT, emit_data->args[0], bld_base->int_bld.zero, ""); val = LLVMBuildSelect(builder, cmp, bld_base->int_bld.one, emit_data->args[0], ""); cmp = LLVMBuildICmp(builder, LLVMIntSGE, val, bld_base->int_bld.zero, ""); val = LLVMBuildSelect(builder, cmp, val, LLVMConstInt(bld_base->int_bld.elem_type, -1, true), ""); } else { // float SSG cmp = LLVMBuildFCmp(builder, LLVMRealOGT, emit_data->args[0], bld_base->base.zero, ""); val = LLVMBuildSelect(builder, cmp, bld_base->base.one, emit_data->args[0], ""); cmp = LLVMBuildFCmp(builder, LLVMRealOGE, val, bld_base->base.zero, ""); val = LLVMBuildSelect(builder, cmp, val, LLVMConstReal(bld_base->base.elem_type, -1), ""); } emit_data->output[emit_data->chan] = val; }
LLVMValueRef gen_float(compile_t* c, ast_t* ast) { ast_t* type = ast_type(ast); reach_type_t* t = reach_type(c->reach, type); return LLVMConstReal(t->primitive, ast_float(ast)); }
LLVMValueRef gen_float(compile_t* c, ast_t* ast) { ast_t* type = deferred_reify(c->frame->reify, ast_type(ast), c->opt); reach_type_t* t = reach_type(c->reach, type); ast_free_unattached(type); compile_type_t* c_t = (compile_type_t*)t->c_type; return LLVMConstReal(c_t->primitive, ast_float(ast)); }
/* Initialize module-independent parts of the context. * * The caller is responsible for initializing ctx::module and ctx::builder. */ void ac_llvm_context_init(struct ac_llvm_context *ctx, LLVMContextRef context) { LLVMValueRef args[1]; ctx->context = context; ctx->module = NULL; ctx->builder = NULL; ctx->voidt = LLVMVoidTypeInContext(ctx->context); ctx->i1 = LLVMInt1TypeInContext(ctx->context); ctx->i8 = LLVMInt8TypeInContext(ctx->context); ctx->i16 = LLVMIntTypeInContext(ctx->context, 16); ctx->i32 = LLVMIntTypeInContext(ctx->context, 32); ctx->i64 = LLVMIntTypeInContext(ctx->context, 64); ctx->f16 = LLVMHalfTypeInContext(ctx->context); ctx->f32 = LLVMFloatTypeInContext(ctx->context); ctx->f64 = LLVMDoubleTypeInContext(ctx->context); ctx->v4i32 = LLVMVectorType(ctx->i32, 4); ctx->v4f32 = LLVMVectorType(ctx->f32, 4); ctx->v8i32 = LLVMVectorType(ctx->i32, 8); ctx->i32_0 = LLVMConstInt(ctx->i32, 0, false); ctx->i32_1 = LLVMConstInt(ctx->i32, 1, false); ctx->f32_0 = LLVMConstReal(ctx->f32, 0.0); ctx->f32_1 = LLVMConstReal(ctx->f32, 1.0); ctx->range_md_kind = LLVMGetMDKindIDInContext(ctx->context, "range", 5); ctx->invariant_load_md_kind = LLVMGetMDKindIDInContext(ctx->context, "invariant.load", 14); ctx->fpmath_md_kind = LLVMGetMDKindIDInContext(ctx->context, "fpmath", 6); args[0] = LLVMConstReal(ctx->f32, 2.5); ctx->fpmath_md_2p5_ulp = LLVMMDNodeInContext(ctx->context, args, 1); ctx->uniform_md_kind = LLVMGetMDKindIDInContext(ctx->context, "amdgpu.uniform", 14); ctx->empty_md = LLVMMDNodeInContext(ctx->context, NULL, 0); }
LLVMValueRef gen_float(compile_t* c, ast_t* ast) { ast_t* type = ast_type(ast); gentype_t g; if(!gentype(c, type, &g)) return NULL; return LLVMConstReal(g.primitive, ast_float(ast)); }
/** * Build a manual selection sequence for cube face sc/tc coordinates and * major axis vector (multiplied by 2 for consistency) for the given * vec3 \p coords, for the face implied by \p selcoords. * * For the major axis, we always adjust the sign to be in the direction of * selcoords.ma; i.e., a positive out_ma means that coords is pointed towards * the selcoords major axis. */ static void build_cube_select(LLVMBuilderRef builder, const struct cube_selection_coords *selcoords, const LLVMValueRef *coords, LLVMValueRef *out_st, LLVMValueRef *out_ma) { LLVMTypeRef f32 = LLVMTypeOf(coords[0]); LLVMValueRef is_ma_positive; LLVMValueRef sgn_ma; LLVMValueRef is_ma_z, is_not_ma_z; LLVMValueRef is_ma_y; LLVMValueRef is_ma_x; LLVMValueRef sgn; LLVMValueRef tmp; is_ma_positive = LLVMBuildFCmp(builder, LLVMRealUGE, selcoords->ma, LLVMConstReal(f32, 0.0), ""); sgn_ma = LLVMBuildSelect(builder, is_ma_positive, LLVMConstReal(f32, 1.0), LLVMConstReal(f32, -1.0), ""); is_ma_z = LLVMBuildFCmp(builder, LLVMRealUGE, selcoords->id, LLVMConstReal(f32, 4.0), ""); is_not_ma_z = LLVMBuildNot(builder, is_ma_z, ""); is_ma_y = LLVMBuildAnd(builder, is_not_ma_z, LLVMBuildFCmp(builder, LLVMRealUGE, selcoords->id, LLVMConstReal(f32, 2.0), ""), ""); is_ma_x = LLVMBuildAnd(builder, is_not_ma_z, LLVMBuildNot(builder, is_ma_y, ""), ""); /* Select sc */ tmp = LLVMBuildSelect(builder, is_ma_z, coords[2], coords[0], ""); sgn = LLVMBuildSelect(builder, is_ma_y, LLVMConstReal(f32, 1.0), LLVMBuildSelect(builder, is_ma_x, sgn_ma, LLVMBuildFNeg(builder, sgn_ma, ""), ""), ""); out_st[0] = LLVMBuildFMul(builder, tmp, sgn, ""); /* Select tc */ tmp = LLVMBuildSelect(builder, is_ma_y, coords[2], coords[1], ""); sgn = LLVMBuildSelect(builder, is_ma_y, LLVMBuildFNeg(builder, sgn_ma, ""), LLVMConstReal(f32, -1.0), ""); out_st[1] = LLVMBuildFMul(builder, tmp, sgn, ""); /* Select ma */ tmp = LLVMBuildSelect(builder, is_ma_z, coords[2], LLVMBuildSelect(builder, is_ma_y, coords[1], coords[0], ""), ""); sgn = LLVMBuildSelect(builder, is_ma_positive, LLVMConstReal(f32, 2.0), LLVMConstReal(f32, -2.0), ""); *out_ma = LLVMBuildFMul(builder, tmp, sgn, ""); }
/** * Do the one or two-sided stencil test comparison. * \sa lp_build_stencil_test_single * \param face an integer indicating front (+) or back (-) facing polygon. * If NULL, assume front-facing. */ static LLVMValueRef lp_build_stencil_test(struct lp_build_context *bld, const struct pipe_stencil_state stencil[2], LLVMValueRef stencilRefs[2], LLVMValueRef stencilVals, LLVMValueRef face) { LLVMValueRef res; assert(stencil[0].enabled); if (stencil[1].enabled && face) { /* do two-sided test */ struct lp_build_flow_context *flow_ctx; struct lp_build_if_state if_ctx; LLVMValueRef front_facing; LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0); LLVMValueRef result = bld->undef; flow_ctx = lp_build_flow_create(bld->builder); lp_build_flow_scope_begin(flow_ctx); lp_build_flow_scope_declare(flow_ctx, &result); /* front_facing = face > 0.0 */ front_facing = LLVMBuildFCmp(bld->builder, LLVMRealUGT, face, zero, ""); lp_build_if(&if_ctx, flow_ctx, bld->builder, front_facing); { result = lp_build_stencil_test_single(bld, &stencil[0], stencilRefs[0], stencilVals); } lp_build_else(&if_ctx); { result = lp_build_stencil_test_single(bld, &stencil[1], stencilRefs[1], stencilVals); } lp_build_endif(&if_ctx); lp_build_flow_scope_end(flow_ctx); lp_build_flow_destroy(flow_ctx); res = result; } else { /* do single-side test */ res = lp_build_stencil_test_single(bld, &stencil[0], stencilRefs[0], stencilVals); } return res; }
LLVMValueRef lp_build_const_aos(struct gallivm_state *gallivm, struct lp_type type, double r, double g, double b, double a, const unsigned char *swizzle) { const unsigned char default_swizzle[4] = {0, 1, 2, 3}; LLVMTypeRef elem_type; LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; unsigned i; assert(type.length % 4 == 0); assert(type.length <= LP_MAX_VECTOR_LENGTH); elem_type = lp_build_elem_type(gallivm, type); if(swizzle == NULL) swizzle = default_swizzle; if(type.floating) { elems[swizzle[0]] = LLVMConstReal(elem_type, r); elems[swizzle[1]] = LLVMConstReal(elem_type, g); elems[swizzle[2]] = LLVMConstReal(elem_type, b); elems[swizzle[3]] = LLVMConstReal(elem_type, a); } else { double dscale = lp_const_scale(type); elems[swizzle[0]] = LLVMConstInt(elem_type, r*dscale + 0.5, 0); elems[swizzle[1]] = LLVMConstInt(elem_type, g*dscale + 0.5, 0); elems[swizzle[2]] = LLVMConstInt(elem_type, b*dscale + 0.5, 0); elems[swizzle[3]] = LLVMConstInt(elem_type, a*dscale + 0.5, 0); } for(i = 4; i < type.length; ++i) elems[i] = elems[i % 4]; return LLVMConstVector(elems, type.length); }
LLVMValueRef lp_build_zero(struct lp_type type) { if (type.length == 1) { if (type.floating) return LLVMConstReal(LLVMFloatType(), 0.0); else return LLVMConstInt(LLVMIntType(type.width), 0, 0); } else { LLVMTypeRef vec_type = lp_build_vec_type(type); return LLVMConstNull(vec_type); } }
TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { LLVMValueRef value = dst[chan_index]; if (inst->Instruction.Saturate != TGSI_SAT_NONE) { struct lp_build_emit_data clamp_emit_data; memset(&clamp_emit_data, 0, sizeof(clamp_emit_data)); clamp_emit_data.arg_count = 3; clamp_emit_data.args[0] = value; clamp_emit_data.args[2] = base.one; switch(inst->Instruction.Saturate) { case TGSI_SAT_ZERO_ONE: clamp_emit_data.args[1] = base.zero; break; case TGSI_SAT_MINUS_PLUS_ONE: clamp_emit_data.args[1] = LLVMConstReal( base.elem_type, -1.0f); break; default: assert(0); } value = lp_build_emit_llvm(bld_base, TGSI_OPCODE_CLAMP, &clamp_emit_data); } switch(reg->Register.File) { case TGSI_FILE_ADDRESS: temp_ptr = bld->addr[reg->Register.Index][chan_index]; LLVMBuildStore(builder, value, temp_ptr); continue; case TGSI_FILE_OUTPUT: temp_ptr = bld->outputs[reg->Register.Index][chan_index]; break; case TGSI_FILE_TEMPORARY: temp_ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, chan_index); break; default: return; } value = bitcast(bld_base, TGSI_TYPE_FLOAT, value); LLVMBuildStore(builder, value, temp_ptr); }
struct vm_value * vm_value_new_from_float_constant(float float_constant) { struct vm_value *vmval; vmval = calloc(1, sizeof(struct vm_value)); if (!vmval) { fprintf(stderr, "Memory allocation request failed.\n"); exit(EXIT_FAILURE); } vmval->type_specifier = TYPE_FLOAT; vmval->llvm_type = get_llvm_type(TYPE_FLOAT); vmval->llvm_value = LLVMConstReal(vmval->llvm_type, float_constant); return vmval; }
LLVMValueRef ett_default_value(EagleComplexType *type) { switch(type->type) { case ETInt1: case ETInt8: case ETUInt8: case ETInt16: case ETUInt16: case ETInt32: case ETUInt32: case ETInt64: case ETUInt64: case ETEnum: return LLVMConstInt(ett_llvm_type(type), 0, 0); case ETFloat: case ETDouble: return LLVMConstReal(ett_llvm_type(type), 0.0); case ETPointer: return LLVMConstPointerNull(ett_llvm_type(type)); case ETStruct: { Arraylist *types; ty_struct_get_members(type, NULL, &types); LLVMValueRef vals[types->count]; for(int i = 0; i < types->count; i++) vals[i] = ett_default_value(types->items[i]); return LLVMConstNamedStruct(ett_llvm_type(type), vals, types->count); } case ETArray: { EagleArrayType *at = (EagleArrayType *)type; LLVMValueRef val = ett_default_value(at->of); LLVMValueRef vals[at->ct]; for(int i = 0; i < at->ct; i++) vals[i] = val; return LLVMConstArray(ett_llvm_type(at->of), vals, at->ct); } default: return NULL; } }
/** * Build constant-valued element from a scalar value. */ LLVMValueRef lp_build_const_elem(struct lp_type type, double val) { LLVMTypeRef elem_type = lp_build_elem_type(type); LLVMValueRef elem; if(type.floating) { elem = LLVMConstReal(elem_type, val); } else { double dscale = lp_const_scale(type); elem = LLVMConstInt(elem_type, val*dscale + 0.5, 0); } return elem; }
LLVMValueRef lp_build_one(struct lp_type type) { LLVMTypeRef elem_type; LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; unsigned i; assert(type.length <= LP_MAX_VECTOR_LENGTH); elem_type = lp_build_elem_type(type); if(type.floating) elems[0] = LLVMConstReal(elem_type, 1.0); else if(type.fixed) elems[0] = LLVMConstInt(elem_type, 1LL << (type.width/2), 0); else if(!type.norm) elems[0] = LLVMConstInt(elem_type, 1, 0); else if(type.sign) elems[0] = LLVMConstInt(elem_type, (1LL << (type.width - 1)) - 1, 0); else { /* special case' -- 1.0 for normalized types is more easily attained if * we start with a vector consisting of all bits set */ LLVMTypeRef vec_type = LLVMVectorType(elem_type, type.length); LLVMValueRef vec = LLVMConstAllOnes(vec_type); #if 0 if(type.sign) /* TODO: Unfortunately this caused "Tried to create a shift operation * on a non-integer type!" */ vec = LLVMConstLShr(vec, lp_build_const_int_vec(type, 1)); #endif return vec; } for(i = 1; i < type.length; ++i) elems[i] = elems[0]; if (type.length == 1) return elems[0]; else return LLVMConstVector(elems, type.length); }
static LLVMValueRef scm_to_llvm_value(int type, SCM scm_value) { switch (type) { case SCM_FOREIGN_TYPE_FLOAT: case SCM_FOREIGN_TYPE_DOUBLE: return LLVMConstReal(llvm_type(type), scm_to_double(scm_value)); case SCM_FOREIGN_TYPE_BOOL: return LLVMConstInt(llvm_type(type), scm_is_true(scm_value), 0); case SCM_FOREIGN_TYPE_UINT8: case SCM_FOREIGN_TYPE_UINT16: case SCM_FOREIGN_TYPE_UINT32: case SCM_FOREIGN_TYPE_UINT64: return LLVMConstInt(llvm_type(type), scm_to_uint64(scm_value), 0); case SCM_FOREIGN_TYPE_INT8: case SCM_FOREIGN_TYPE_INT16: case SCM_FOREIGN_TYPE_INT32: case SCM_FOREIGN_TYPE_INT64: return LLVMConstInt(llvm_type(type), scm_to_int64(scm_value), 1); default: return NULL; }; }
static void si_llvm_cube_to_2d_coords(struct lp_build_tgsi_context *bld_base, LLVMValueRef *in, LLVMValueRef *out) { struct gallivm_state *gallivm = bld_base->base.gallivm; LLVMBuilderRef builder = gallivm->builder; LLVMTypeRef type = bld_base->base.elem_type; LLVMValueRef coords[4]; LLVMValueRef mad_args[3]; LLVMValueRef v; unsigned i; v = build_cube_intrinsic(gallivm, in); for (i = 0; i < 4; ++i) coords[i] = LLVMBuildExtractElement(builder, v, lp_build_const_int32(gallivm, i), ""); coords[2] = lp_build_intrinsic(builder, "llvm.fabs.f32", type, &coords[2], 1, LLVMReadNoneAttribute); coords[2] = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_RCP, coords[2]); mad_args[1] = coords[2]; mad_args[2] = LLVMConstReal(type, 1.5); mad_args[0] = coords[0]; coords[0] = lp_build_emit_llvm_ternary(bld_base, TGSI_OPCODE_MAD, mad_args[0], mad_args[1], mad_args[2]); mad_args[0] = coords[1]; coords[1] = lp_build_emit_llvm_ternary(bld_base, TGSI_OPCODE_MAD, mad_args[0], mad_args[1], mad_args[2]); /* apply xyz = yxw swizzle to cooords */ out[0] = coords[1]; out[1] = coords[0]; out[2] = coords[3]; }
static LLVMValueRef translateFloatLit(ASTNode *Node) { LLVMValueRef Container = LLVMBuildAlloca(Builder, LLVMFloatType(), ""); LLVMBuildStore(Builder, LLVMConstReal(LLVMFloatType(), *((float*)Node->Value)), Container); return Container; }
void ac_prepare_cube_coords(struct ac_llvm_context *ctx, bool is_deriv, bool is_array, LLVMValueRef *coords_arg, LLVMValueRef *derivs_arg) { LLVMBuilderRef builder = ctx->builder; struct cube_selection_coords selcoords; LLVMValueRef coords[3]; LLVMValueRef invma; build_cube_intrinsic(ctx, coords_arg, &selcoords); invma = ac_build_intrinsic(ctx, "llvm.fabs.f32", ctx->f32, &selcoords.ma, 1, AC_FUNC_ATTR_READNONE); invma = ac_build_fdiv(ctx, LLVMConstReal(ctx->f32, 1.0), invma); for (int i = 0; i < 2; ++i) coords[i] = LLVMBuildFMul(builder, selcoords.stc[i], invma, ""); coords[2] = selcoords.id; if (is_deriv && derivs_arg) { LLVMValueRef derivs[4]; int axis; /* Convert cube derivatives to 2D derivatives. */ for (axis = 0; axis < 2; axis++) { LLVMValueRef deriv_st[2]; LLVMValueRef deriv_ma; /* Transform the derivative alongside the texture * coordinate. Mathematically, the correct formula is * as follows. Assume we're projecting onto the +Z face * and denote by dx/dh the derivative of the (original) * X texture coordinate with respect to horizontal * window coordinates. The projection onto the +Z face * plane is: * * f(x,z) = x/z * * Then df/dh = df/dx * dx/dh + df/dz * dz/dh * = 1/z * dx/dh - x/z * 1/z * dz/dh. * * This motivatives the implementation below. * * Whether this actually gives the expected results for * apps that might feed in derivatives obtained via * finite differences is anyone's guess. The OpenGL spec * seems awfully quiet about how textureGrad for cube * maps should be handled. */ build_cube_select(builder, &selcoords, &derivs_arg[axis * 3], deriv_st, &deriv_ma); deriv_ma = LLVMBuildFMul(builder, deriv_ma, invma, ""); for (int i = 0; i < 2; ++i) derivs[axis * 2 + i] = LLVMBuildFSub(builder, LLVMBuildFMul(builder, deriv_st[i], invma, ""), LLVMBuildFMul(builder, deriv_ma, coords[i], ""), ""); } memcpy(derivs_arg, derivs, sizeof(derivs)); } /* Shift the texture coordinate. This must be applied after the * derivative calculation. */ for (int i = 0; i < 2; ++i) coords[i] = LLVMBuildFAdd(builder, coords[i], LLVMConstReal(ctx->f32, 1.5), ""); if (is_array) { /* for cube arrays coord.z = coord.w(array_index) * 8 + face */ /* coords_arg.w component - array_index for cube arrays */ LLVMValueRef tmp = LLVMBuildFMul(ctx->builder, coords_arg[3], LLVMConstReal(ctx->f32, 8.0), ""); coords[2] = LLVMBuildFAdd(ctx->builder, tmp, coords[2], ""); } memcpy(coords_arg, coords, sizeof(coords)); }
/* Perform view culling and small primitive elimination and return true * if the primitive is accepted and initially_accepted == true. */ static LLVMValueRef cull_bbox(struct ac_llvm_context *ctx, LLVMValueRef pos[3][4], LLVMValueRef initially_accepted, struct ac_position_w_info *w, LLVMValueRef vp_scale[2], LLVMValueRef vp_translate[2], LLVMValueRef small_prim_precision, bool cull_view_xy, bool cull_view_near_z, bool cull_view_far_z, bool cull_small_prims, bool use_halfz_clip_space) { LLVMBuilderRef builder = ctx->builder; if (!cull_view_xy && !cull_view_near_z && !cull_view_far_z && !cull_small_prims) return ctx->i1true; /* Skip the culling if the primitive has already been rejected or * if any W is negative. The bounding box culling doesn't work when * W is negative. */ LLVMValueRef cond = LLVMBuildAnd(builder, initially_accepted, w->all_w_positive, ""); LLVMValueRef accepted_var = ac_build_alloca_undef(ctx, ctx->i1, ""); LLVMBuildStore(builder, initially_accepted, accepted_var); ac_build_ifcc(ctx, cond, 10000000 /* does this matter? */); { LLVMValueRef bbox_min[3], bbox_max[3]; LLVMValueRef accepted = initially_accepted; /* Compute the primitive bounding box for easy culling. */ for (unsigned chan = 0; chan < 3; chan++) { bbox_min[chan] = ac_build_fmin(ctx, pos[0][chan], pos[1][chan]); bbox_min[chan] = ac_build_fmin(ctx, bbox_min[chan], pos[2][chan]); bbox_max[chan] = ac_build_fmax(ctx, pos[0][chan], pos[1][chan]); bbox_max[chan] = ac_build_fmax(ctx, bbox_max[chan], pos[2][chan]); } /* View culling. */ if (cull_view_xy || cull_view_near_z || cull_view_far_z) { for (unsigned chan = 0; chan < 3; chan++) { LLVMValueRef visible; if ((cull_view_xy && chan <= 1) || (cull_view_near_z && chan == 2)) { float t = chan == 2 && use_halfz_clip_space ? 0 : -1; visible = LLVMBuildFCmp(builder, LLVMRealOGE, bbox_max[chan], LLVMConstReal(ctx->f32, t), ""); accepted = LLVMBuildAnd(builder, accepted, visible, ""); } if ((cull_view_xy && chan <= 1) || (cull_view_far_z && chan == 2)) { visible = LLVMBuildFCmp(builder, LLVMRealOLE, bbox_min[chan], ctx->f32_1, ""); accepted = LLVMBuildAnd(builder, accepted, visible, ""); } } } /* Small primitive elimination. */ if (cull_small_prims) { /* Assuming a sample position at (0.5, 0.5), if we round * the bounding box min/max extents and the results of * the rounding are equal in either the X or Y direction, * the bounding box does not intersect the sample. * * See these GDC slides for pictures: * https://frostbite-wp-prd.s3.amazonaws.com/wp-content/uploads/2016/03/29204330/GDC_2016_Compute.pdf */ LLVMValueRef min, max, not_equal[2], visible; for (unsigned chan = 0; chan < 2; chan++) { /* Convert the position to screen-space coordinates. */ min = ac_build_fmad(ctx, bbox_min[chan], vp_scale[chan], vp_translate[chan]); max = ac_build_fmad(ctx, bbox_max[chan], vp_scale[chan], vp_translate[chan]); /* Scale the bounding box according to the precision of * the rasterizer and the number of MSAA samples. */ min = LLVMBuildFSub(builder, min, small_prim_precision, ""); max = LLVMBuildFAdd(builder, max, small_prim_precision, ""); /* Determine if the bbox intersects the sample point. * It also works for MSAA, but vp_scale, vp_translate, * and small_prim_precision are computed differently. */ min = ac_build_round(ctx, min); max = ac_build_round(ctx, max); not_equal[chan] = LLVMBuildFCmp(builder, LLVMRealONE, min, max, ""); } visible = LLVMBuildAnd(builder, not_equal[0], not_equal[1], ""); accepted = LLVMBuildAnd(builder, accepted, visible, ""); } LLVMBuildStore(builder, accepted, accepted_var); } ac_build_endif(ctx, 10000000); return LLVMBuildLoad(builder, accepted_var, ""); }
TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { LLVMValueRef value = dst[chan_index]; if (inst->Instruction.Saturate != TGSI_SAT_NONE) { struct lp_build_emit_data clamp_emit_data; memset(&clamp_emit_data, 0, sizeof(clamp_emit_data)); clamp_emit_data.arg_count = 3; clamp_emit_data.args[0] = value; clamp_emit_data.args[2] = base.one; switch(inst->Instruction.Saturate) { case TGSI_SAT_ZERO_ONE: clamp_emit_data.args[1] = base.zero; break; case TGSI_SAT_MINUS_PLUS_ONE: clamp_emit_data.args[1] = LLVMConstReal( base.elem_type, -1.0f); break; default: assert(0); } value = lp_build_emit_llvm(bld_base, TGSI_OPCODE_CLAMP, &clamp_emit_data); } if (reg->Register.File == TGSI_FILE_ADDRESS) { temp_ptr = bld->addr[reg->Register.Index][chan_index]; LLVMBuildStore(builder, value, temp_ptr); continue; } value = bitcast(bld_base, TGSI_TYPE_FLOAT, value); if (reg->Register.Indirect) { struct tgsi_declaration_range range = get_array_range(bld_base, reg->Register.File, ®->Indirect); unsigned i, size = range.Last - range.First + 1; LLVMValueRef array = LLVMBuildInsertElement(builder, emit_array_fetch(bld_base, reg->Register.File, TGSI_TYPE_FLOAT, range, chan_index), value, emit_array_index(bld, ®->Indirect, reg->Register.Index - range.First), ""); for (i = 0; i < size; ++i) { switch(reg->Register.File) { case TGSI_FILE_OUTPUT: temp_ptr = bld->outputs[i + range.First][chan_index]; break; case TGSI_FILE_TEMPORARY: temp_ptr = lp_get_temp_ptr_soa(bld, i + range.First, chan_index); break; default: return; } value = LLVMBuildExtractElement(builder, array, lp_build_const_int32(gallivm, i), ""); LLVMBuildStore(builder, value, temp_ptr); } } else { switch(reg->Register.File) { case TGSI_FILE_OUTPUT: temp_ptr = bld->outputs[reg->Register.Index][chan_index]; break; case TGSI_FILE_TEMPORARY: temp_ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, chan_index); break; default: return; } LLVMBuildStore(builder, value, temp_ptr); } }
/* This function returns an i1 1 if the value is not equal to 0 and an i1 0 if the value is equal to 0. */ struct cl2llvm_val_t *cl2llvm_to_bool_ne_0(struct cl2llvm_val_t *value) { LLVMValueRef const_zero; LLVMValueRef zero_vec[16]; LLVMTypeRef switch_type; int i; int veclength; struct cl2llvm_val_t *bool_val = cl2llvm_val_create_w_init(value->val, cl2llvmTypeWrapGetSign(value->type)); /* if value is i1 no conversion necessary */ if (LLVMTypeOf(value->val) == LLVMInt1Type()) return bool_val; /* If value is a vector create a vector of constant zeros, else create a scalar 0. */ if (LLVMGetTypeKind(cl2llvmTypeWrapGetLlvmType(value->type)) == LLVMVectorTypeKind) { switch_type = LLVMGetElementType(cl2llvmTypeWrapGetLlvmType(value->type)); veclength = LLVMGetVectorSize(cl2llvmTypeWrapGetLlvmType(value->type)); switch (LLVMGetTypeKind(LLVMGetElementType(cl2llvmTypeWrapGetLlvmType(value->type)))) { case LLVMIntegerTypeKind: /* Create zero vector */ for (i = 0; i < veclength; i++) zero_vec[i] = LLVMConstInt(switch_type, 0, 0); break; case LLVMFloatTypeKind: case LLVMDoubleTypeKind: case LLVMHalfTypeKind: /* Create zero vector */ for (i = 0; i < veclength; i++) zero_vec[i] = LLVMConstReal(switch_type, 0); break; default: cl2llvm_yyerror("unreachable code reached"); } const_zero = LLVMConstVector(zero_vec, veclength); } else if (LLVMGetTypeKind(cl2llvmTypeWrapGetLlvmType(value->type)) == LLVMIntegerTypeKind) { const_zero = LLVMConstInt(cl2llvmTypeWrapGetLlvmType(value->type), 0, 0); switch_type = cl2llvmTypeWrapGetLlvmType(value->type); } else if (LLVMGetTypeKind(cl2llvmTypeWrapGetLlvmType(value->type)) == LLVMFloatTypeKind || LLVMGetTypeKind(cl2llvmTypeWrapGetLlvmType(value->type)) == LLVMDoubleTypeKind || LLVMGetTypeKind(cl2llvmTypeWrapGetLlvmType(value->type)) == LLVMHalfTypeKind) { const_zero = LLVMConstReal(cl2llvmTypeWrapGetLlvmType(value->type), 0); switch_type = cl2llvmTypeWrapGetLlvmType(value->type); } /* Create comparison */ snprintf(temp_var_name, sizeof temp_var_name, "tmp_%d", temp_var_count++); switch (LLVMGetTypeKind(switch_type)) { case LLVMFloatTypeKind: case LLVMDoubleTypeKind: case LLVMHalfTypeKind: bool_val->val = LLVMBuildFCmp(cl2llvm_builder, LLVMRealONE, value->val, const_zero, temp_var_name); break; case LLVMIntegerTypeKind: bool_val->val = LLVMBuildICmp(cl2llvm_builder, LLVMIntNE, value->val, const_zero, temp_var_name); break; default: cl2llvm_yyerror("unreachable code reached"); break; } cl2llvmTypeWrapSetLlvmType(bool_val->type, LLVMInt1Type()); cl2llvmTypeWrapSetSign(bool_val->type, 0); return bool_val; }