From: Marek Olšák <marek.ol...@amd.com> --- src/amd/common/ac_llvm_build.c | 80 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+)
diff --git a/src/amd/common/ac_llvm_build.c b/src/amd/common/ac_llvm_build.c index 3a1ef93..187c2cb 100644 --- a/src/amd/common/ac_llvm_build.c +++ b/src/amd/common/ac_llvm_build.c @@ -107,20 +107,34 @@ ac_emit_llvm_intrinsic(struct ac_llvm_context *ctx, const char *name, if (!set_callsite_attrs) ac_add_func_attributes(ctx->context, function, attrib_mask); } call = LLVMBuildCall(ctx->builder, function, params, param_count, ""); if (set_callsite_attrs) ac_add_func_attributes(ctx->context, call, attrib_mask); return call; } +static LLVMValueRef bitcast_to_float(struct ac_llvm_context *ctx, + LLVMValueRef value) +{ + LLVMTypeRef type = LLVMTypeOf(value); + LLVMTypeRef new_type; + + if (LLVMGetTypeKind(type) == LLVMVectorTypeKind) + new_type = LLVMVectorType(ctx->f32, LLVMGetVectorSize(type)); + else + new_type = ctx->f32; + + return LLVMBuildBitCast(ctx->builder, value, new_type, ""); +} + /** * Given the i32 or vNi32 \p type, generate the textual name (e.g. for use with * intrinsic names). */ void ac_build_type_name_for_intr(LLVMTypeRef type, char *buf, unsigned bufsize) { LLVMTypeRef elem_type = type; assert(bufsize >= 8); @@ -935,20 +949,86 @@ void ac_emit_export(struct ac_llvm_context *ctx, struct ac_export_args *a) LLVMValueRef ac_emit_image_opcode(struct ac_llvm_context *ctx, struct ac_image_args *a) { LLVMTypeRef dst_type; LLVMValueRef args[11]; unsigned num_args = 0; const char *name; char intr_name[128], type[64]; + if (HAVE_LLVM >= 0x0400) { + bool sample = a->opcode == ac_image_sample || + a->opcode == ac_image_gather4 || + a->opcode == ac_image_get_lod; + + if (sample) + args[num_args++] = bitcast_to_float(ctx, a->addr); + else + args[num_args++] = a->addr; + + args[num_args++] = a->resource; + if (sample) + args[num_args++] = a->sampler; + args[num_args++] = LLVMConstInt(ctx->i32, a->dmask, 0); + if (sample) + args[num_args++] = LLVMConstInt(ctx->i1, a->unorm, 0); + args[num_args++] = LLVMConstInt(ctx->i1, 0, 0); /* glc */ + args[num_args++] = LLVMConstInt(ctx->i1, 0, 0); /* slc */ + args[num_args++] = LLVMConstInt(ctx->i1, 0, 0); /* lwe */ + args[num_args++] = LLVMConstInt(ctx->i1, a->da, 0); + + switch (a->opcode) { + case ac_image_sample: + name = "llvm.amdgcn.image.sample"; + break; + case ac_image_gather4: + name = "llvm.amdgcn.image.gather4"; + break; + case ac_image_load: + name = "llvm.amdgcn.image.load"; + break; + case ac_image_load_mip: + name = "llvm.amdgcn.image.load.mip"; + break; + case ac_image_get_lod: + name = "llvm.amdgcn.image.getlod"; + break; + case ac_image_get_resinfo: + name = "llvm.amdgcn.image.getresinfo"; + break; + } + + ac_build_type_name_for_intr(LLVMTypeOf(args[0]), type, + sizeof(type)); + + snprintf(intr_name, sizeof(intr_name), "%s%s%s%s.v4f32.%s.v8i32", + name, + a->compare ? ".c" : "", + a->bias ? ".b" : + a->lod ? ".l" : + a->deriv ? ".d" : + a->level_zero ? ".lz" : "", + a->offset ? ".o" : "", + type); + + LLVMValueRef result = + ac_emit_llvm_intrinsic(ctx, intr_name, + ctx->v4f32, args, num_args, + AC_FUNC_ATTR_READNONE); + if (!sample) { + result = LLVMBuildBitCast(ctx->builder, result, + ctx->v4i32, ""); + } + return result; + } + args[num_args++] = a->addr; args[num_args++] = a->resource; if (a->opcode == ac_image_load || a->opcode == ac_image_load_mip || a->opcode == ac_image_get_resinfo) { dst_type = ctx->v4i32; } else { dst_type = ctx->v4f32; args[num_args++] = a->sampler; -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev