Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
0
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));
}
Пример #4
0
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));
}
Пример #5
0
/* 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);
}
Пример #6
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));
}
Пример #7
0
/**
 * 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, "");
}
Пример #8
0
/**
 * 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;
}
Пример #9
0
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);
}
Пример #10
0
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);
   }
}
Пример #11
0
	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);
	}
Пример #12
0
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;
}
Пример #13
0
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;
    }
}
Пример #14
0
/**
 * 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;
}
Пример #15
0
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);
}
Пример #16
0
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;
  };
}
Пример #17
0
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];
}
Пример #18
0
static LLVMValueRef 
translateFloatLit(ASTNode *Node) {
  LLVMValueRef Container = LLVMBuildAlloca(Builder, LLVMFloatType(), "");
  LLVMBuildStore(Builder, LLVMConstReal(LLVMFloatType(), *((float*)Node->Value)), Container);
  return Container;
}
Пример #19
0
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));
}
Пример #20
0
/* 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, "");
}
Пример #21
0
	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, &reg->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, &reg->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);
		}
	}
Пример #22
0
/* 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;
}