r600/llvm: Store inputs in function arguments
authorVincent Lejeune <vljn@ovi.com>
Wed, 30 Oct 2013 17:35:58 +0000 (18:35 +0100)
committerVincent Lejeune <vljn@ovi.com>
Mon, 11 Nov 2013 22:14:42 +0000 (23:14 +0100)
src/gallium/drivers/r600/r600_llvm.c
src/gallium/drivers/r600/r600_shader.c
src/gallium/drivers/radeon/radeon_llvm.h

index 5afe3cb51f775dd40d4fea291c92c5d5997f2b9c..a2ff0ec237da9a414dc82f0f80aebc0e26a5400c 100644 (file)
@@ -77,6 +77,11 @@ static void llvm_load_system_value(
        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(
@@ -84,8 +89,49 @@ static void llvm_load_system_value(
                        "llvm.R600.load.input",
                        ctx->soa.bld_base.base.elem_type, &reg, 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,
@@ -110,7 +156,22 @@ llvm_load_input_helper(
        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,
@@ -124,6 +185,7 @@ llvm_face_select_helper(
        return LLVMBuildSelect(bb->gallivm->builder, is_front,
                front_color, back_color, "");
 }
+#endif
 
 static void llvm_load_input(
        struct radeon_llvm_context * ctx,
@@ -132,11 +194,55 @@ static void llvm_load_input(
 {
        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;
@@ -177,6 +283,7 @@ static void llvm_load_input(
 
                ctx->inputs[soa_index] = v;
        }
+#endif
 }
 
 static void llvm_emit_prologue(struct lp_build_tgsi_context * bld_base)
@@ -657,7 +764,19 @@ LLVMModuleRef r600_tgsi_llvm(
        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;
index aed2100738436ade195fd94223956532cdf1c818..1ea4ae6c05617de5c0e9318668d283199bee38cb 100644 (file)
@@ -1102,6 +1102,7 @@ static int r600_shader_from_tgsi(struct r600_screen *rscreen,
                radeon_llvm_ctx.type = ctx.type;
                radeon_llvm_ctx.two_side = shader->two_side;
                radeon_llvm_ctx.face_gpr = ctx.face_gpr;
+               radeon_llvm_ctx.inputs_count = ctx.shader->ninput + 1;
                radeon_llvm_ctx.r600_inputs = ctx.shader->input;
                radeon_llvm_ctx.r600_outputs = ctx.shader->output;
                radeon_llvm_ctx.color_buffer_count = max_color_exports;
index ef09dc891dc2bd4634483d61513379cde35a414b..2cab6b013cd412ce14e4b89d78a2232962f0b012 100644 (file)
@@ -60,6 +60,7 @@ struct radeon_llvm_context {
        unsigned face_gpr;
        unsigned two_side;
        unsigned clip_vertex;
+       unsigned inputs_count;
        struct r600_shader_io * r600_inputs;
        struct r600_shader_io * r600_outputs;
        struct pipe_stream_output_info *stream_outputs;