default: assert(!"unknown system value");
}
+#if HAVE_LLVM >= 0x0304
+ ctx->system_values[index] = LLVMBuildExtractElement(ctx->gallivm.builder,
+ LLVMGetParam(ctx->main_fn, 0), lp_build_const_int32(&(ctx->gallivm), chan),
+ "");
+#else
LLVMValueRef reg = lp_build_const_int32(
ctx->soa.bld_base.base.gallivm, chan);
ctx->system_values[index] = build_intrinsic(
"llvm.R600.load.input",
ctx->soa.bld_base.base.elem_type, ®, 1,
LLVMReadNoneAttribute);
+#endif
}
+#if HAVE_LLVM >= 0x0304
+static LLVMValueRef
+llvm_load_input_vector(
+ struct radeon_llvm_context * ctx, unsigned location, unsigned ijregs,
+ boolean interp)
+{
+ LLVMTypeRef VecType;
+ LLVMValueRef Args[3] = {
+ lp_build_const_int32(&(ctx->gallivm), location)
+ };
+ unsigned ArgCount = 1;
+ if (interp) {
+ VecType = LLVMVectorType(ctx->soa.bld_base.base.elem_type, 2);
+ LLVMValueRef IJIndex = LLVMGetParam(ctx->main_fn, ijregs / 2);
+ Args[ArgCount++] = LLVMBuildExtractElement(ctx->gallivm.builder, IJIndex,
+ lp_build_const_int32(&(ctx->gallivm), 2 * (ijregs % 2)), "");
+ Args[ArgCount++] = LLVMBuildExtractElement(ctx->gallivm.builder, IJIndex,
+ lp_build_const_int32(&(ctx->gallivm), 2 * (ijregs % 2) + 1), "");
+ LLVMValueRef HalfVec[2] = {
+ build_intrinsic(ctx->gallivm.builder, "llvm.R600.interp.xy",
+ VecType, Args, ArgCount, LLVMReadNoneAttribute),
+ build_intrinsic(ctx->gallivm.builder, "llvm.R600.interp.zw",
+ VecType, Args, ArgCount, LLVMReadNoneAttribute)
+ };
+ LLVMValueRef MaskInputs[4] = {
+ lp_build_const_int32(&(ctx->gallivm), 0),
+ lp_build_const_int32(&(ctx->gallivm), 1),
+ lp_build_const_int32(&(ctx->gallivm), 2),
+ lp_build_const_int32(&(ctx->gallivm), 3)
+ };
+ LLVMValueRef Mask = LLVMConstVector(MaskInputs, 4);
+ return LLVMBuildShuffleVector(ctx->gallivm.builder, HalfVec[0], HalfVec[1],
+ Mask, "");
+ } else {
+ VecType = LLVMVectorType(ctx->soa.bld_base.base.elem_type, 4);
+ return build_intrinsic(ctx->gallivm.builder, "llvm.R600.interp.const",
+ VecType, Args, ArgCount, LLVMReadNoneAttribute);
+ }
+}
+#else
static LLVMValueRef
llvm_load_input_helper(
struct radeon_llvm_context * ctx,
return build_intrinsic(bb->gallivm->builder, intrinsic,
bb->elem_type, &arg[0], arg_count, LLVMReadNoneAttribute);
}
+#endif
+#if HAVE_LLVM >= 0x0304
+static LLVMValueRef
+llvm_face_select_helper(
+ struct radeon_llvm_context * ctx,
+ LLVMValueRef face, LLVMValueRef front_color, LLVMValueRef back_color)
+{
+ const struct lp_build_context * bb = &ctx->soa.bld_base.base;
+ LLVMValueRef is_front = LLVMBuildFCmp(
+ bb->gallivm->builder, LLVMRealUGT, face,
+ lp_build_const_float(bb->gallivm, 0.0f), "");
+ return LLVMBuildSelect(bb->gallivm->builder, is_front,
+ front_color, back_color, "");
+}
+#else
static LLVMValueRef
llvm_face_select_helper(
struct radeon_llvm_context * ctx,
return LLVMBuildSelect(bb->gallivm->builder, is_front,
front_color, back_color, "");
}
+#endif
static void llvm_load_input(
struct radeon_llvm_context * ctx,
{
const struct r600_shader_io * input = &ctx->r600_inputs[input_index];
unsigned chan;
+#if HAVE_LLVM < 0x0304
unsigned interp = 0;
int ij_index;
+#endif
int two_side = (ctx->two_side && input->name == TGSI_SEMANTIC_COLOR);
LLVMValueRef v;
+#if HAVE_LLVM >= 0x0304
+ boolean require_interp_intrinsic = ctx->chip_class >= EVERGREEN &&
+ ctx->type == TGSI_PROCESSOR_FRAGMENT;
+#endif
+
+#if HAVE_LLVM >= 0x0304
+ 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], "");
+ }
+}
+#else
if (ctx->chip_class >= EVERGREEN && ctx->type == TGSI_PROCESSOR_FRAGMENT &&
input->spi_sid) {
interp = 1;
ctx->inputs[soa_index] = v;
}
+#endif
}
static void llvm_emit_prologue(struct lp_build_tgsi_context * bld_base)
struct tgsi_shader_info shader_info;
struct lp_build_tgsi_context * bld_base = &ctx->soa.bld_base;
radeon_llvm_context_init(ctx);
+#if HAVE_LLVM >= 0x0304
+ LLVMTypeRef Arguments[32];
+ unsigned ArgumentsCount = 0;
+ for (unsigned i = 0; i < ctx->inputs_count; i++)
+ Arguments[ArgumentsCount++] = LLVMVectorType(bld_base->base.elem_type, 4);
+ radeon_llvm_create_func(ctx, Arguments, ArgumentsCount);
+ for (unsigned i = 0; i < ctx->inputs_count; i++) {
+ LLVMValueRef P = LLVMGetParam(ctx->main_fn, i);
+ LLVMAddAttribute(P, LLVMInRegAttribute);
+ }
+#else
radeon_llvm_create_func(ctx, NULL, 0);
+#endif
tgsi_scan_shader(tokens, &shader_info);
bld_base->info = &shader_info;