diff options
author | Nicolai Hähnle <[email protected]> | 2018-04-20 09:29:57 +0200 |
---|---|---|
committer | Nicolai Hähnle <[email protected]> | 2018-04-20 09:29:57 +0200 |
commit | 74063431f125df450029ec9202d376b4a77f30c6 (patch) | |
tree | 6f5ebf30281d41d9debbe34b9f1276a71c23f21f /src/amd | |
parent | 625dcbbc45665459737c9d028f268fd6782472f3 (diff) |
radeonsi: generate image load/store/atomic ops using ac_build_image_opcode
In preparation of dimension-aware LLVM image intrinsics.
Acked-by: Marek Olšák <[email protected]>
Diffstat (limited to 'src/amd')
-rw-r--r-- | src/amd/common/ac_llvm_build.c | 105 | ||||
-rw-r--r-- | src/amd/common/ac_llvm_build.h | 37 |
2 files changed, 110 insertions, 32 deletions
diff --git a/src/amd/common/ac_llvm_build.c b/src/amd/common/ac_llvm_build.c index 22aac7cbdb7..64b47e7343d 100644 --- a/src/amd/common/ac_llvm_build.c +++ b/src/amd/common/ac_llvm_build.c @@ -1489,12 +1489,15 @@ LLVMValueRef ac_build_image_opcode(struct ac_llvm_context *ctx, struct ac_image_args *a) { LLVMValueRef args[16]; + LLVMTypeRef retty = ctx->v4f32; const char *name = NULL; - char intr_name[128], type[64]; + const char *atomic_subop = ""; + char intr_name[128], coords_type[64]; assert(!a->lod || a->lod == ctx->i32_0 || a->lod == ctx->f32_0 || !a->level_zero); - assert((a->opcode != ac_image_get_resinfo && a->opcode != ac_image_load_mip) || + assert((a->opcode != ac_image_get_resinfo && a->opcode != ac_image_load_mip && + a->opcode != ac_image_store_mip) || a->lod); assert((a->bias ? 1 : 0) + (a->lod ? 1 : 0) + @@ -1504,6 +1507,8 @@ LLVMValueRef ac_build_image_opcode(struct ac_llvm_context *ctx, bool sample = a->opcode == ac_image_sample || a->opcode == ac_image_gather4 || a->opcode == ac_image_get_lod; + bool atomic = a->opcode == ac_image_atomic || + a->opcode == ac_image_atomic_cmpswap; bool da = a->dim == ac_image_cube || a->dim == ac_image_1darray || a->dim == ac_image_2darray || @@ -1539,6 +1544,13 @@ LLVMValueRef ac_build_image_opcode(struct ac_llvm_context *ctx, addr = ac_build_gather_values(ctx, args, num_addr); unsigned num_args = 0; + if (atomic || a->opcode == ac_image_store || a->opcode == ac_image_store_mip) { + args[num_args++] = a->data[0]; + if (a->opcode == ac_image_atomic_cmpswap) + args[num_args++] = a->data[1]; + } + + unsigned coords_arg = num_args; if (sample) args[num_args++] = ac_to_float(ctx, addr); else @@ -1547,13 +1559,19 @@ LLVMValueRef ac_build_image_opcode(struct ac_llvm_context *ctx, 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++] = ctx->i1false; /* glc */ - args[num_args++] = ctx->i1false; /* slc */ - args[num_args++] = ctx->i1false; /* lwe */ - args[num_args++] = LLVMConstInt(ctx->i1, da, 0); + if (!atomic) { + args[num_args++] = LLVMConstInt(ctx->i32, a->dmask, 0); + if (sample) + args[num_args++] = LLVMConstInt(ctx->i1, a->unorm, 0); + args[num_args++] = a->cache_policy & ac_glc ? ctx->i1true : ctx->i1false; + args[num_args++] = a->cache_policy & ac_slc ? ctx->i1true : ctx->i1false; + args[num_args++] = ctx->i1false; /* lwe */ + args[num_args++] = LLVMConstInt(ctx->i1, da, 0); + } else { + args[num_args++] = ctx->i1false; /* r128 */ + args[num_args++] = LLVMConstInt(ctx->i1, da, 0); + args[num_args++] = a->cache_policy & ac_slc ? ctx->i1true : ctx->i1false; + } switch (a->opcode) { case ac_image_sample: @@ -1568,6 +1586,35 @@ LLVMValueRef ac_build_image_opcode(struct ac_llvm_context *ctx, case ac_image_load_mip: name = "llvm.amdgcn.image.load.mip"; break; + case ac_image_store: + name = "llvm.amdgcn.image.store"; + retty = ctx->voidt; + break; + case ac_image_store_mip: + name = "llvm.amdgcn.image.store.mip"; + retty = ctx->voidt; + break; + case ac_image_atomic: + case ac_image_atomic_cmpswap: + name = "llvm.amdgcn.image.atomic."; + retty = ctx->i32; + if (a->opcode == ac_image_atomic_cmpswap) { + atomic_subop = "cmpswap"; + } else { + switch (a->atomic) { + case ac_atomic_swap: atomic_subop = "swap"; break; + case ac_atomic_add: atomic_subop = "add"; break; + case ac_atomic_sub: atomic_subop = "sub"; break; + case ac_atomic_smin: atomic_subop = "smin"; break; + case ac_atomic_umin: atomic_subop = "umin"; break; + case ac_atomic_smax: atomic_subop = "smax"; break; + case ac_atomic_umax: atomic_subop = "umax"; break; + case ac_atomic_and: atomic_subop = "and"; break; + case ac_atomic_or: atomic_subop = "or"; break; + case ac_atomic_xor: atomic_subop = "xor"; break; + } + } + break; case ac_image_get_lod: name = "llvm.amdgcn.image.getlod"; break; @@ -1578,27 +1625,31 @@ LLVMValueRef ac_build_image_opcode(struct ac_llvm_context *ctx, unreachable("invalid image opcode"); } - ac_build_type_name_for_intr(LLVMTypeOf(args[0]), type, - sizeof(type)); + ac_build_type_name_for_intr(LLVMTypeOf(args[coords_arg]), coords_type, + sizeof(coords_type)); - bool lod_suffix = - a->lod && (a->opcode == ac_image_sample || a->opcode == ac_image_gather4); - - snprintf(intr_name, sizeof(intr_name), "%s%s%s%s.v4f32.%s.v8i32", - name, - a->compare ? ".c" : "", - a->bias ? ".b" : - lod_suffix ? ".l" : - a->derivs[0] ? ".d" : - a->level_zero ? ".lz" : "", - a->offset ? ".o" : "", - type); + if (atomic) { + snprintf(intr_name, sizeof(intr_name), "llvm.amdgcn.image.atomic.%s.%s", + atomic_subop, coords_type); + } else { + bool lod_suffix = + a->lod && (a->opcode == ac_image_sample || a->opcode == ac_image_gather4); + + snprintf(intr_name, sizeof(intr_name), "%s%s%s%s.v4f32.%s.v8i32", + name, + a->compare ? ".c" : "", + a->bias ? ".b" : + lod_suffix ? ".l" : + a->derivs[0] ? ".d" : + a->level_zero ? ".lz" : "", + a->offset ? ".o" : "", + coords_type); + } LLVMValueRef result = - ac_build_intrinsic(ctx, intr_name, - ctx->v4f32, args, num_args, - AC_FUNC_ATTR_READNONE); - if (!sample) { + ac_build_intrinsic(ctx, intr_name, retty, args, num_args, + a->attributes); + if (!sample && retty == ctx->v4f32) { result = LLVMBuildBitCast(ctx->builder, result, ctx->v4i32, ""); } diff --git a/src/amd/common/ac_llvm_build.h b/src/amd/common/ac_llvm_build.h index 1691a809381..b676adba65f 100644 --- a/src/amd/common/ac_llvm_build.h +++ b/src/amd/common/ac_llvm_build.h @@ -313,8 +313,25 @@ enum ac_image_opcode { ac_image_gather4, ac_image_load, ac_image_load_mip, + ac_image_store, + ac_image_store_mip, ac_image_get_lod, ac_image_get_resinfo, + ac_image_atomic, + ac_image_atomic_cmpswap, +}; + +enum ac_atomic_op { + ac_atomic_swap, + ac_atomic_add, + ac_atomic_sub, + ac_atomic_smin, + ac_atomic_umin, + ac_atomic_smax, + ac_atomic_umax, + ac_atomic_and, + ac_atomic_or, + ac_atomic_xor, }; enum ac_image_dim { @@ -328,21 +345,31 @@ enum ac_image_dim { ac_image_2darraymsaa, }; +/* These cache policy bits match the definitions used by the LLVM intrinsics. */ +enum ac_image_cache_policy { + ac_glc = 1 << 0, + ac_slc = 1 << 1, +}; + struct ac_image_args { - enum ac_image_opcode opcode; - enum ac_image_dim dim; + enum ac_image_opcode opcode : 4; + enum ac_atomic_op atomic : 4; /* for the ac_image_atomic opcode */ + enum ac_image_dim dim : 3; + unsigned dmask : 4; + unsigned cache_policy : 2; + bool unorm : 1; + bool level_zero : 1; + unsigned attributes; /* additional call-site specific AC_FUNC_ATTRs */ LLVMValueRef resource; LLVMValueRef sampler; + LLVMValueRef data[2]; /* data[0] is source data (vector); data[1] is cmp for cmpswap */ LLVMValueRef offset; LLVMValueRef bias; LLVMValueRef compare; LLVMValueRef derivs[6]; LLVMValueRef coords[4]; LLVMValueRef lod; // also used by ac_image_get_resinfo - unsigned dmask; - bool unorm; - bool level_zero; }; LLVMValueRef ac_build_image_opcode(struct ac_llvm_context *ctx, |