diff --git a/src/gallium/drivers/r600/r600_llvm.c b/src/gallium/drivers/r600/r600_llvm.c index 5afe3cb51f7..a2ff0ec237d 100644 --- a/src/gallium/drivers/r600/r600_llvm.c +++ b/src/gallium/drivers/r600/r600_llvm.c @@ -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, ®, 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; diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index aed21007384..1ea4ae6c056 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -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; diff --git a/src/gallium/drivers/radeon/radeon_llvm.h b/src/gallium/drivers/radeon/radeon_llvm.h index ef09dc891dc..2cab6b013cd 100644 --- a/src/gallium/drivers/radeon/radeon_llvm.h +++ b/src/gallium/drivers/radeon/radeon_llvm.h @@ -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;