Beispiel #1
0
/**
 * Generate a / b
 */
LLVMValueRef
lp_build_div(struct lp_build_context *bld,
             LLVMValueRef a,
             LLVMValueRef b)
{
   const struct lp_type type = bld->type;

   if(a == bld->zero)
      return bld->zero;
   if(a == bld->one)
      return lp_build_rcp(bld, b);
   if(b == bld->zero)
      return bld->undef;
   if(b == bld->one)
      return a;
   if(a == bld->undef || b == bld->undef)
      return bld->undef;

   if(LLVMIsConstant(a) && LLVMIsConstant(b))
      return LLVMConstFDiv(a, b);

   if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4)
      return lp_build_mul(bld, a, lp_build_rcp(bld, b));

   return LLVMBuildFDiv(bld->builder, a, b, "");
}
Beispiel #2
0
LLVMValueRef
ac_build_fdiv(struct ac_llvm_context *ctx,
	      LLVMValueRef num,
	      LLVMValueRef den)
{
	LLVMValueRef ret = LLVMBuildFDiv(ctx->builder, num, den, "");

	if (!LLVMIsConstant(ret))
		LLVMSetMetadata(ret, ctx->fpmath_md_kind, ctx->fpmath_md_2p5_ulp);
	return ret;
}
static void llvm_load_input(
	struct radeon_llvm_context * ctx,
	unsigned input_index,
	const struct tgsi_full_declaration *decl)
{
	const struct r600_shader_io * input = &ctx->r600_inputs[input_index];
	unsigned chan;
	int two_side = (ctx->two_side && input->name == TGSI_SEMANTIC_COLOR);
	LLVMValueRef v;
	boolean require_interp_intrinsic = ctx->chip_class >= EVERGREEN &&
		ctx->type == TGSI_PROCESSOR_FRAGMENT;

	if (require_interp_intrinsic && input->spi_sid) {
		v = llvm_load_input_vector(ctx, input->lds_pos, input->ij_index,
			(input->interpolate > 0));
	} else
		v = LLVMGetParam(ctx->main_fn, input->gpr);

	if (two_side) {
		struct r600_shader_io * back_input =
			&ctx->r600_inputs[input->back_color_input];
		LLVMValueRef v2;
		LLVMValueRef face = LLVMGetParam(ctx->main_fn, ctx->face_gpr);
		face = LLVMBuildExtractElement(ctx->gallivm.builder, face,
			lp_build_const_int32(&(ctx->gallivm), 0), "");

		if (require_interp_intrinsic && back_input->spi_sid)
			v2 = llvm_load_input_vector(ctx, back_input->lds_pos,
				back_input->ij_index, (back_input->interpolate > 0));
		else
			v2 = LLVMGetParam(ctx->main_fn, back_input->gpr);
		v = llvm_face_select_helper(ctx, face, v, v2);
	}

	for (chan = 0; chan < 4; chan++) {
		unsigned soa_index = radeon_llvm_reg_index_soa(input_index, chan);

		ctx->inputs[soa_index] = LLVMBuildExtractElement(ctx->gallivm.builder, v,
			lp_build_const_int32(&(ctx->gallivm), chan), "");

		if (input->name == TGSI_SEMANTIC_POSITION &&
				ctx->type == TGSI_PROCESSOR_FRAGMENT && chan == 3) {
		/* RCP for fragcoord.w */
		ctx->inputs[soa_index] = LLVMBuildFDiv(ctx->gallivm.builder,
				lp_build_const_float(&(ctx->gallivm), 1.0f),
				ctx->inputs[soa_index], "");
	}
	}
}
Beispiel #4
0
static LLVMValueRef
translateFloatBinOp(NodeKind Op, LLVMValueRef ValueE1, LLVMValueRef ValueE2) {
  switch (Op) {
    case SumOp:  return LLVMBuildFAdd(Builder, ValueE1, ValueE2, ""); 
    case SubOp:  return LLVMBuildFSub(Builder, ValueE1, ValueE2, ""); 
    case MultOp: return LLVMBuildFMul(Builder, ValueE1, ValueE2, ""); 
    case DivOp:  return LLVMBuildFDiv(Builder, ValueE1, ValueE2, ""); 
    case LtOp:   return LLVMBuildFCmp(Builder, LLVMRealOLT, ValueE1, ValueE2, ""); 
    case LeOp:   return LLVMBuildFCmp(Builder, LLVMRealOLE, ValueE1, ValueE2, ""); 
    case GtOp:   return LLVMBuildFCmp(Builder, LLVMRealOGT, ValueE1, ValueE2, ""); 
    case GeOp:   return LLVMBuildFCmp(Builder, LLVMRealOGE, ValueE1, ValueE2, ""); 
    case EqOp:   return LLVMBuildFCmp(Builder, LLVMRealOEQ, ValueE1, ValueE2, ""); 
    case DiffOp: return LLVMBuildFCmp(Builder, LLVMRealONE, ValueE1, ValueE2, ""); 
    default:     return NULL;
  }
}
static void emit_fdiv(const struct lp_build_tgsi_action *action,
		      struct lp_build_tgsi_context *bld_base,
		      struct lp_build_emit_data *emit_data)
{
	struct si_shader_context *ctx = si_shader_context(bld_base);

	emit_data->output[emit_data->chan] =
		LLVMBuildFDiv(bld_base->base.gallivm->builder,
			      emit_data->args[0], emit_data->args[1], "");

	/* Use v_rcp_f32 instead of precise division. */
	if (HAVE_LLVM >= 0x0309 &&
	    !LLVMIsConstant(emit_data->output[emit_data->chan]))
		LLVMSetMetadata(emit_data->output[emit_data->chan],
				ctx->fpmath_md_kind, ctx->fpmath_md_2p5_ulp);
}
Beispiel #6
0
LLVMValueRef
lp_build_rcp(struct lp_build_context *bld,
             LLVMValueRef a)
{
   const struct lp_type type = bld->type;

   if(a == bld->zero)
      return bld->undef;
   if(a == bld->one)
      return bld->one;
   if(a == bld->undef)
      return bld->undef;

   assert(type.floating);

   if(LLVMIsConstant(a))
      return LLVMConstFDiv(bld->one, a);

   if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4)
      /* FIXME: improve precision */
      return lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rcp.ps", lp_build_vec_type(type), a);

   return LLVMBuildFDiv(bld->builder, bld->one, a, "");
}
Beispiel #7
0
static void declare_input_fs(
	struct si_shader_context * si_shader_ctx,
	unsigned input_index,
	const struct tgsi_full_declaration *decl)
{
	struct si_shader *shader = &si_shader_ctx->shader->shader;
	struct lp_build_context * base =
				&si_shader_ctx->radeon_bld.soa.bld_base.base;
	struct gallivm_state * gallivm = base->gallivm;
	LLVMTypeRef input_type = LLVMFloatTypeInContext(gallivm->context);
	LLVMValueRef main_fn = si_shader_ctx->radeon_bld.main_fn;

	LLVMValueRef interp_param;
	const char * intr_name;

	/* This value is:
	 * [15:0] NewPrimMask (Bit mask for each quad.  It is set it the
	 *                     quad begins a new primitive.  Bit 0 always needs
	 *                     to be unset)
	 * [32:16] ParamOffset
	 *
	 */
	LLVMValueRef params = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_PRIM_MASK);
	LLVMValueRef attr_number;

	unsigned chan;

	if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION) {
		for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
			unsigned soa_index =
				radeon_llvm_reg_index_soa(input_index, chan);
			si_shader_ctx->radeon_bld.inputs[soa_index] =
				LLVMGetParam(main_fn, SI_PARAM_POS_X_FLOAT + chan);

			if (chan == 3)
				/* RCP for fragcoord.w */
				si_shader_ctx->radeon_bld.inputs[soa_index] =
					LLVMBuildFDiv(gallivm->builder,
						      lp_build_const_float(gallivm, 1.0f),
						      si_shader_ctx->radeon_bld.inputs[soa_index],
						      "");
		}
		return;
	}

	if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) {
		LLVMValueRef face, is_face_positive;

		face = LLVMGetParam(main_fn, SI_PARAM_FRONT_FACE);

		is_face_positive = LLVMBuildFCmp(gallivm->builder,
						 LLVMRealUGT, face,
						 lp_build_const_float(gallivm, 0.0f),
						 "");

		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, 0)] =
			LLVMBuildSelect(gallivm->builder,
					is_face_positive,
					lp_build_const_float(gallivm, 1.0f),
					lp_build_const_float(gallivm, 0.0f),
					"");
		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, 1)] =
		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, 2)] =
			lp_build_const_float(gallivm, 0.0f);
		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, 3)] =
			lp_build_const_float(gallivm, 1.0f);

		return;
	}

	shader->input[input_index].param_offset = shader->ninterp++;
	attr_number = lp_build_const_int32(gallivm,
					   shader->input[input_index].param_offset);

	/* XXX: Handle all possible interpolation modes */
	switch (decl->Interp.Interpolate) {
	case TGSI_INTERPOLATE_COLOR:
		if (si_shader_ctx->shader->key.ps.flatshade) {
			interp_param = 0;
		} else {
			if (decl->Interp.Centroid)
				interp_param = LLVMGetParam(main_fn, SI_PARAM_PERSP_CENTROID);
			else
				interp_param = LLVMGetParam(main_fn, SI_PARAM_PERSP_CENTER);
		}
		break;
	case TGSI_INTERPOLATE_CONSTANT:
		interp_param = 0;
		break;
	case TGSI_INTERPOLATE_LINEAR:
		if (decl->Interp.Centroid)
			interp_param = LLVMGetParam(main_fn, SI_PARAM_LINEAR_CENTROID);
		else
			interp_param = LLVMGetParam(main_fn, SI_PARAM_LINEAR_CENTER);
		break;
	case TGSI_INTERPOLATE_PERSPECTIVE:
		if (decl->Interp.Centroid)
			interp_param = LLVMGetParam(main_fn, SI_PARAM_PERSP_CENTROID);
		else
			interp_param = LLVMGetParam(main_fn, SI_PARAM_PERSP_CENTER);
		break;
	default:
		fprintf(stderr, "Warning: Unhandled interpolation mode.\n");
		return;
	}

	intr_name = interp_param ? "llvm.SI.fs.interp" : "llvm.SI.fs.constant";

	/* XXX: Could there be more than TGSI_NUM_CHANNELS (4) ? */
	if (decl->Semantic.Name == TGSI_SEMANTIC_COLOR &&
	    si_shader_ctx->shader->key.ps.color_two_side) {
		LLVMValueRef args[4];
		LLVMValueRef face, is_face_positive;
		LLVMValueRef back_attr_number =
			lp_build_const_int32(gallivm,
					     shader->input[input_index].param_offset + 1);

		face = LLVMGetParam(main_fn, SI_PARAM_FRONT_FACE);

		is_face_positive = LLVMBuildFCmp(gallivm->builder,
						 LLVMRealUGT, face,
						 lp_build_const_float(gallivm, 0.0f),
						 "");

		args[2] = params;
		args[3] = interp_param;
		for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
			LLVMValueRef llvm_chan = lp_build_const_int32(gallivm, chan);
			unsigned soa_index = radeon_llvm_reg_index_soa(input_index, chan);
			LLVMValueRef front, back;

			args[0] = llvm_chan;
			args[1] = attr_number;
			front = build_intrinsic(base->gallivm->builder, intr_name,
						input_type, args, args[3] ? 4 : 3,
						LLVMReadNoneAttribute | LLVMNoUnwindAttribute);

			args[1] = back_attr_number;
			back = build_intrinsic(base->gallivm->builder, intr_name,
					       input_type, args, args[3] ? 4 : 3,
					       LLVMReadNoneAttribute | LLVMNoUnwindAttribute);

			si_shader_ctx->radeon_bld.inputs[soa_index] =
				LLVMBuildSelect(gallivm->builder,
						is_face_positive,
						front,
						back,
						"");
		}

		shader->ninterp++;
	} else {
		for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
			LLVMValueRef args[4];
			LLVMValueRef llvm_chan = lp_build_const_int32(gallivm, chan);
			unsigned soa_index = radeon_llvm_reg_index_soa(input_index, chan);
			args[0] = llvm_chan;
			args[1] = attr_number;
			args[2] = params;
			args[3] = interp_param;
			si_shader_ctx->radeon_bld.inputs[soa_index] =
				build_intrinsic(base->gallivm->builder, intr_name,
						input_type, args, args[3] ? 4 : 3,
						LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
		}
	}
}
Beispiel #8
0
static void llvm_load_input(
	struct radeon_llvm_context * ctx,
	unsigned input_index,
	const struct tgsi_full_declaration *decl)
{
	unsigned chan;

	const char *intrinsics = "llvm.R600.load.input";
	unsigned offset = 4 * ctx->reserved_reg_count;

	if (ctx->type == TGSI_PROCESSOR_FRAGMENT && ctx->chip_class >= EVERGREEN) {
		switch (decl->Interp.Interpolate) {
		case TGSI_INTERPOLATE_COLOR:
		case TGSI_INTERPOLATE_PERSPECTIVE:
			offset = 0;
			intrinsics = "llvm.R600.load.input.perspective";
			break;
		case TGSI_INTERPOLATE_LINEAR:
			offset = 0;
			intrinsics = "llvm.R600.load.input.linear";
			break;
		case TGSI_INTERPOLATE_CONSTANT:
			offset = 0;
			intrinsics = "llvm.R600.load.input.constant";
			break;
		default:
			assert(0 && "Unknow Interpolate mode");
		}
	}

	for (chan = 0; chan < 4; chan++) {
		unsigned soa_index = radeon_llvm_reg_index_soa(input_index,
								chan);

		switch (decl->Semantic.Name) {
		case TGSI_SEMANTIC_FACE:
			ctx->inputs[soa_index] = llvm_load_input_helper(ctx,
				"llvm.R600.load.input",
				4 * ctx->face_input);
			break;
		case TGSI_SEMANTIC_POSITION:
			if (ctx->type != TGSI_PROCESSOR_FRAGMENT || chan != 3) {
				ctx->inputs[soa_index] = llvm_load_input_helper(ctx,
					"llvm.R600.load.input",
					soa_index + (ctx->reserved_reg_count * 4));
			} else {
				LLVMValueRef w_coord = llvm_load_input_helper(ctx,
				"llvm.R600.load.input",
				soa_index + (ctx->reserved_reg_count * 4));
				ctx->inputs[soa_index] = LLVMBuildFDiv(ctx->gallivm.builder,
				lp_build_const_float(&(ctx->gallivm), 1.0f), w_coord, "");
			}
			break;
		case TGSI_SEMANTIC_COLOR:
			if (ctx->two_side) {
				unsigned front_location, back_location;
				unsigned back_reg = ctx->r600_inputs[input_index]
					.potential_back_facing_reg;
				if (ctx->chip_class >= EVERGREEN) {
					front_location = 4 * ctx->r600_inputs[input_index].lds_pos + chan;
					back_location = 4 * ctx->r600_inputs[back_reg].lds_pos + chan;
				} else {
					front_location = soa_index + 4 * ctx->reserved_reg_count;
					back_location = radeon_llvm_reg_index_soa(
						ctx->r600_inputs[back_reg].gpr,
						chan);
				}
				ctx->inputs[soa_index] = llvm_face_select_helper(ctx,
					intrinsics,
					4 * ctx->face_input, front_location, back_location);
				break;
			}
		default:
			{
				unsigned location;
				if (ctx->chip_class >= EVERGREEN) {
					location = 4 * ctx->r600_inputs[input_index].lds_pos + chan;
				} else {
					location = soa_index + 4 * ctx->reserved_reg_count;
				}
				/* The * 4 is assuming that we are in soa mode. */
				ctx->inputs[soa_index] = llvm_load_input_helper(ctx,
					intrinsics, location);
					
			break;
			}
		}
	}
}