From 877bb52dc95c8504935d48fffe93b5c52bfc7e16 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 25 Jun 2014 03:12:46 +0200 Subject: [PATCH] radeonsi: properly implement texture opcodes that take an offset Instead of using intr_name in lp_build_tgsi_action, this selects the names with a switch statement in the emit function. This allows emitting llvm.SI.sample for instructions without offsets and llvm.SI.image.sample.*.o otherwise. This depends on my LLVM changes. When LLVM 3.5 is released, I'll switch all texture instructions to the new intrinsics. --- src/gallium/drivers/radeonsi/si_shader.c | 188 +++++++++++++---------- 1 file changed, 104 insertions(+), 84 deletions(-) diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index ed09efef39d..4c0309b1390 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -1532,8 +1532,6 @@ static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base) last_args, 9); } -static const struct lp_build_tgsi_action txf_action; - static void build_tex_intrinsic(const struct lp_build_tgsi_action * action, struct lp_build_tgsi_context * bld_base, struct lp_build_emit_data * emit_data); @@ -1549,6 +1547,8 @@ static bool tgsi_is_shadow_sampler(unsigned target) target == TGSI_TEXTURE_SHADOWRECT; } +static const struct lp_build_tgsi_action tex_action; + static void tex_fetch_args( struct lp_build_tgsi_context * bld_base, struct lp_build_emit_data * emit_data) @@ -1566,6 +1566,7 @@ static void tex_fetch_args( unsigned chan; unsigned sampler_src = emit_data->inst->Instruction.NumSrcRegs - 1; unsigned sampler_index = emit_data->inst->Src[sampler_src].Register.Index; + bool has_offset = HAVE_LLVM >= 0x0305 ? inst->Texture.NumOffsets > 0 : false; if (target == TGSI_TEXTURE_BUFFER) { LLVMTypeRef i128 = LLVMIntTypeInContext(gallivm->context, 128); @@ -1604,8 +1605,7 @@ static void tex_fetch_args( coords[3] = bld_base->base.one; /* Pack offsets. */ - if (opcode == TGSI_OPCODE_TG4 && - inst->Texture.NumOffsets) { + if (has_offset && opcode != TGSI_OPCODE_TXF) { /* The offsets are six-bit signed integers packed like this: * X=[5:0], Y=[13:8], and Z=[21:16]. */ @@ -1730,6 +1730,7 @@ static void tex_fetch_args( struct lp_build_emit_data txf_emit_data = *emit_data; LLVMValueRef txf_address[4]; unsigned txf_count = count; + struct tgsi_full_instruction inst = {}; memcpy(txf_address, address, sizeof(txf_address)); @@ -1743,16 +1744,18 @@ static void tex_fetch_args( txf_address[txf_count++] = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context)); /* Read FMASK using TXF. */ + inst.Instruction.Opcode = TGSI_OPCODE_TXF; + inst.Texture.Texture = target == TGSI_TEXTURE_2D_MSAA ? TGSI_TEXTURE_2D : TGSI_TEXTURE_2D_ARRAY; + txf_emit_data.inst = &inst; txf_emit_data.chan = 0; txf_emit_data.dst_type = LLVMVectorType( LLVMInt32TypeInContext(gallivm->context), 4); txf_emit_data.args[0] = lp_build_gather_values(gallivm, txf_address, txf_count); txf_emit_data.args[1] = si_shader_ctx->resources[FMASK_TEX_OFFSET + sampler_index]; - txf_emit_data.args[2] = lp_build_const_int32(gallivm, - target == TGSI_TEXTURE_2D_MSAA ? TGSI_TEXTURE_2D : TGSI_TEXTURE_2D_ARRAY); + txf_emit_data.args[2] = lp_build_const_int32(gallivm, inst.Texture.Texture); txf_emit_data.arg_count = 3; - build_tex_intrinsic(&txf_action, bld_base, &txf_emit_data); + build_tex_intrinsic(&tex_action, bld_base, &txf_emit_data); /* Initialize some constants. */ LLVMValueRef four = LLVMConstInt(uint_bld->elem_type, 4, 0); @@ -1843,7 +1846,8 @@ static void tex_fetch_args( LLVMInt32TypeInContext(gallivm->context), 4); } else if (opcode == TGSI_OPCODE_TG4 || - opcode == TGSI_OPCODE_LODQ) { + opcode == TGSI_OPCODE_LODQ || + has_offset) { unsigned is_array = target == TGSI_TEXTURE_1D_ARRAY || target == TGSI_TEXTURE_SHADOW1D_ARRAY || target == TGSI_TEXTURE_2D_ARRAY || @@ -1924,9 +1928,13 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action * action, struct lp_build_emit_data * emit_data) { struct lp_build_context * base = &bld_base->base; + unsigned opcode = emit_data->inst->Instruction.Opcode; + unsigned target = emit_data->inst->Texture.Texture; char intr_name[127]; + bool has_offset = HAVE_LLVM >= 0x0305 ? + emit_data->inst->Texture.NumOffsets > 0 : false; - if (emit_data->inst->Texture.Texture == TGSI_TEXTURE_BUFFER) { + if (target == TGSI_TEXTURE_BUFFER) { emit_data->output[emit_data->chan] = build_intrinsic( base->gallivm->builder, "llvm.SI.vs.load.input", emit_data->dst_type, @@ -1935,36 +1943,87 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action * action, return; } - sprintf(intr_name, "%sv%ui32", action->intr_name, - LLVMGetVectorSize(LLVMTypeOf(emit_data->args[0]))); + if (opcode == TGSI_OPCODE_TG4 || + opcode == TGSI_OPCODE_LODQ || + (opcode != TGSI_OPCODE_TXF && has_offset)) { + bool is_shadow = tgsi_is_shadow_sampler(target); + const char *name = "llvm.SI.image.sample"; + const char *infix = ""; - emit_data->output[emit_data->chan] = build_intrinsic( - base->gallivm->builder, intr_name, emit_data->dst_type, - emit_data->args, emit_data->arg_count, - LLVMReadNoneAttribute | LLVMNoUnwindAttribute); -} + switch (opcode) { + case TGSI_OPCODE_TEX: + case TGSI_OPCODE_TEX2: + case TGSI_OPCODE_TXP: + break; + case TGSI_OPCODE_TXB: + case TGSI_OPCODE_TXB2: + infix = ".b"; + break; + case TGSI_OPCODE_TXL: + case TGSI_OPCODE_TXL2: + infix = ".l"; + break; + case TGSI_OPCODE_TXD: + infix = ".d"; + break; + case TGSI_OPCODE_TG4: + name = "llvm.SI.gather4"; + break; + case TGSI_OPCODE_LODQ: + name = "llvm.SI.getlod"; + is_shadow = false; + has_offset = false; + break; + default: + assert(0); + return; + } -static void build_new_tex_intrinsic(const struct lp_build_tgsi_action * action, - struct lp_build_tgsi_context * bld_base, - struct lp_build_emit_data * emit_data) -{ - struct lp_build_context * base = &bld_base->base; - char intr_name[127]; - unsigned target = emit_data->inst->Texture.Texture; - bool is_shadow = tgsi_is_shadow_sampler(target) && - emit_data->inst->Instruction.Opcode != TGSI_OPCODE_LODQ; - - /* Add the type and suffixes .c, .o if needed. */ - sprintf(intr_name, "%s%s%s.v%ui32", - action->intr_name, - is_shadow ? ".c" : "", - emit_data->inst->Texture.NumOffsets ? ".o" : "", - LLVMGetVectorSize(LLVMTypeOf(emit_data->args[0]))); - - emit_data->output[emit_data->chan] = build_intrinsic( - base->gallivm->builder, intr_name, emit_data->dst_type, - emit_data->args, emit_data->arg_count, - LLVMReadNoneAttribute | LLVMNoUnwindAttribute); + /* Add the type and suffixes .c, .o if needed. */ + sprintf(intr_name, "%s%s%s%s.v%ui32", name, + is_shadow ? ".c" : "", infix, has_offset ? ".o" : "", + LLVMGetVectorSize(LLVMTypeOf(emit_data->args[0]))); + + emit_data->output[emit_data->chan] = build_intrinsic( + base->gallivm->builder, intr_name, emit_data->dst_type, + emit_data->args, emit_data->arg_count, + LLVMReadNoneAttribute | LLVMNoUnwindAttribute); + } else { + const char *name; + + switch (opcode) { + case TGSI_OPCODE_TEX: + case TGSI_OPCODE_TEX2: + case TGSI_OPCODE_TXP: + name = "llvm.SI.sample"; + break; + case TGSI_OPCODE_TXB: + case TGSI_OPCODE_TXB2: + name = "llvm.SI.sampleb"; + break; + case TGSI_OPCODE_TXD: + name = "llvm.SI.sampled"; + break; + case TGSI_OPCODE_TXF: + name = "llvm.SI.imageload"; + break; + case TGSI_OPCODE_TXL: + case TGSI_OPCODE_TXL2: + name = "llvm.SI.samplel"; + break; + default: + assert(0); + return; + } + + sprintf(intr_name, "%s.v%ui32", name, + LLVMGetVectorSize(LLVMTypeOf(emit_data->args[0]))); + + emit_data->output[emit_data->chan] = build_intrinsic( + base->gallivm->builder, intr_name, emit_data->dst_type, + emit_data->args, emit_data->arg_count, + LLVMReadNoneAttribute | LLVMNoUnwindAttribute); + } } static void txq_fetch_args( @@ -2226,33 +2285,6 @@ static void si_llvm_emit_primitive( static const struct lp_build_tgsi_action tex_action = { .fetch_args = tex_fetch_args, .emit = build_tex_intrinsic, - .intr_name = "llvm.SI.sample." -}; - -static const struct lp_build_tgsi_action txb_action = { - .fetch_args = tex_fetch_args, - .emit = build_tex_intrinsic, - .intr_name = "llvm.SI.sampleb." -}; - -#if HAVE_LLVM >= 0x0304 -static const struct lp_build_tgsi_action txd_action = { - .fetch_args = tex_fetch_args, - .emit = build_tex_intrinsic, - .intr_name = "llvm.SI.sampled." -}; -#endif - -static const struct lp_build_tgsi_action txf_action = { - .fetch_args = tex_fetch_args, - .emit = build_tex_intrinsic, - .intr_name = "llvm.SI.imageload." -}; - -static const struct lp_build_tgsi_action txl_action = { - .fetch_args = tex_fetch_args, - .emit = build_tex_intrinsic, - .intr_name = "llvm.SI.samplel." }; static const struct lp_build_tgsi_action txq_action = { @@ -2261,18 +2293,6 @@ static const struct lp_build_tgsi_action txq_action = { .intr_name = "llvm.SI.resinfo" }; -static const struct lp_build_tgsi_action tg4_action = { - .fetch_args = tex_fetch_args, - .emit = build_new_tex_intrinsic, - .intr_name = "llvm.SI.gather4" -}; - -static const struct lp_build_tgsi_action lodq_action = { - .fetch_args = tex_fetch_args, - .emit = build_new_tex_intrinsic, - .intr_name = "llvm.SI.getlod" -}; - static void create_meta_data(struct si_shader_context *si_shader_ctx) { struct gallivm_state *gallivm = si_shader_ctx->radeon_bld.soa.bld_base.base.gallivm; @@ -2727,18 +2747,18 @@ int si_pipe_shader_create( bld_base->op_actions[TGSI_OPCODE_TEX] = tex_action; bld_base->op_actions[TGSI_OPCODE_TEX2] = tex_action; - bld_base->op_actions[TGSI_OPCODE_TXB] = txb_action; - bld_base->op_actions[TGSI_OPCODE_TXB2] = txb_action; + bld_base->op_actions[TGSI_OPCODE_TXB] = tex_action; + bld_base->op_actions[TGSI_OPCODE_TXB2] = tex_action; #if HAVE_LLVM >= 0x0304 - bld_base->op_actions[TGSI_OPCODE_TXD] = txd_action; + bld_base->op_actions[TGSI_OPCODE_TXD] = tex_action; #endif - bld_base->op_actions[TGSI_OPCODE_TXF] = txf_action; - bld_base->op_actions[TGSI_OPCODE_TXL] = txl_action; - bld_base->op_actions[TGSI_OPCODE_TXL2] = txl_action; + bld_base->op_actions[TGSI_OPCODE_TXF] = tex_action; + bld_base->op_actions[TGSI_OPCODE_TXL] = tex_action; + bld_base->op_actions[TGSI_OPCODE_TXL2] = tex_action; bld_base->op_actions[TGSI_OPCODE_TXP] = tex_action; bld_base->op_actions[TGSI_OPCODE_TXQ] = txq_action; - bld_base->op_actions[TGSI_OPCODE_TG4] = tg4_action; - bld_base->op_actions[TGSI_OPCODE_LODQ] = lodq_action; + bld_base->op_actions[TGSI_OPCODE_TG4] = tex_action; + bld_base->op_actions[TGSI_OPCODE_LODQ] = tex_action; #if HAVE_LLVM >= 0x0304 bld_base->op_actions[TGSI_OPCODE_DDX].emit = si_llvm_emit_ddxy; -- 2.30.2