From db1fddcf0fa91a71282b439fe0406d26585eab9f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Timur=20Krist=C3=B3f?= Date: Wed, 25 Sep 2019 14:10:18 +0200 Subject: [PATCH] amd/common: Extract some helper functions to ac_shader_util. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This commit moves ac_get_tbuffer_format, ac_get_sampler_dim and ac_get_image_dim into ac_shader_util, thus enabling them to be used by compilers other than LLVM. Signed-off-by: Timur Kristóf Reviewed-by: Bas Nieuwenhuizen Reviewed-by: Marek Olšák --- src/amd/common/ac_llvm_build.c | 50 +---------------- src/amd/common/ac_llvm_build.h | 12 +--- src/amd/common/ac_nir_to_llvm.c | 65 +++------------------- src/amd/common/ac_shader_util.c | 97 +++++++++++++++++++++++++++++++++ src/amd/common/ac_shader_util.h | 24 ++++++++ 5 files changed, 131 insertions(+), 117 deletions(-) diff --git a/src/amd/common/ac_llvm_build.c b/src/amd/common/ac_llvm_build.c index fb5479c8948..44092a39487 100644 --- a/src/amd/common/ac_llvm_build.c +++ b/src/amd/common/ac_llvm_build.c @@ -1383,52 +1383,6 @@ LLVMValueRef ac_build_buffer_load_format(struct ac_llvm_context *ctx, true, true); } -/// Translate a (dfmt, nfmt) pair into a chip-appropriate combined format -/// value for LLVM8+ tbuffer intrinsics. -static unsigned -ac_get_tbuffer_format(struct ac_llvm_context *ctx, - unsigned dfmt, unsigned nfmt) -{ - if (ctx->chip_class >= GFX10) { - unsigned format; - switch (dfmt) { - default: unreachable("bad dfmt"); - case V_008F0C_BUF_DATA_FORMAT_INVALID: format = V_008F0C_IMG_FORMAT_INVALID; break; - case V_008F0C_BUF_DATA_FORMAT_8: format = V_008F0C_IMG_FORMAT_8_UINT; break; - case V_008F0C_BUF_DATA_FORMAT_8_8: format = V_008F0C_IMG_FORMAT_8_8_UINT; break; - case V_008F0C_BUF_DATA_FORMAT_8_8_8_8: format = V_008F0C_IMG_FORMAT_8_8_8_8_UINT; break; - case V_008F0C_BUF_DATA_FORMAT_16: format = V_008F0C_IMG_FORMAT_16_UINT; break; - case V_008F0C_BUF_DATA_FORMAT_16_16: format = V_008F0C_IMG_FORMAT_16_16_UINT; break; - case V_008F0C_BUF_DATA_FORMAT_16_16_16_16: format = V_008F0C_IMG_FORMAT_16_16_16_16_UINT; break; - case V_008F0C_BUF_DATA_FORMAT_32: format = V_008F0C_IMG_FORMAT_32_UINT; break; - case V_008F0C_BUF_DATA_FORMAT_32_32: format = V_008F0C_IMG_FORMAT_32_32_UINT; break; - case V_008F0C_BUF_DATA_FORMAT_32_32_32: format = V_008F0C_IMG_FORMAT_32_32_32_UINT; break; - case V_008F0C_BUF_DATA_FORMAT_32_32_32_32: format = V_008F0C_IMG_FORMAT_32_32_32_32_UINT; break; - case V_008F0C_BUF_DATA_FORMAT_2_10_10_10: format = V_008F0C_IMG_FORMAT_2_10_10_10_UINT; break; - } - - // Use the regularity properties of the combined format enum. - // - // Note: float is incompatible with 8-bit data formats, - // [us]{norm,scaled} are incomparible with 32-bit data formats. - // [us]scaled are not writable. - switch (nfmt) { - case V_008F0C_BUF_NUM_FORMAT_UNORM: format -= 4; break; - case V_008F0C_BUF_NUM_FORMAT_SNORM: format -= 3; break; - case V_008F0C_BUF_NUM_FORMAT_USCALED: format -= 2; break; - case V_008F0C_BUF_NUM_FORMAT_SSCALED: format -= 1; break; - default: unreachable("bad nfmt"); - case V_008F0C_BUF_NUM_FORMAT_UINT: break; - case V_008F0C_BUF_NUM_FORMAT_SINT: format += 1; break; - case V_008F0C_BUF_NUM_FORMAT_FLOAT: format += 2; break; - } - - return format; - } else { - return dfmt | (nfmt << 4); - } -} - static LLVMValueRef ac_build_tbuffer_load(struct ac_llvm_context *ctx, LLVMValueRef rsrc, @@ -1452,7 +1406,7 @@ ac_build_tbuffer_load(struct ac_llvm_context *ctx, args[idx++] = vindex ? vindex : ctx->i32_0; args[idx++] = voffset ? voffset : ctx->i32_0; args[idx++] = soffset ? soffset : ctx->i32_0; - args[idx++] = LLVMConstInt(ctx->i32, ac_get_tbuffer_format(ctx, dfmt, nfmt), 0); + args[idx++] = LLVMConstInt(ctx->i32, ac_get_tbuffer_format(ctx->chip_class, dfmt, nfmt), 0); args[idx++] = LLVMConstInt(ctx->i32, get_load_cache_policy(ctx, cache_policy), 0); unsigned func = !ac_has_vec3_support(ctx->chip_class, true) && num_channels == 3 ? 4 : num_channels; const char *indexing_kind = structurized ? "struct" : "raw"; @@ -1896,7 +1850,7 @@ ac_build_tbuffer_store(struct ac_llvm_context *ctx, args[idx++] = vindex ? vindex : ctx->i32_0; args[idx++] = voffset ? voffset : ctx->i32_0; args[idx++] = soffset ? soffset : ctx->i32_0; - args[idx++] = LLVMConstInt(ctx->i32, ac_get_tbuffer_format(ctx, dfmt, nfmt), 0); + args[idx++] = LLVMConstInt(ctx->i32, ac_get_tbuffer_format(ctx->chip_class, dfmt, nfmt), 0); args[idx++] = LLVMConstInt(ctx->i32, cache_policy, 0); unsigned func = !ac_has_vec3_support(ctx->chip_class, true) && num_channels == 3 ? 4 : num_channels; const char *indexing_kind = structurized ? "struct" : "raw"; diff --git a/src/amd/common/ac_llvm_build.h b/src/amd/common/ac_llvm_build.h index 676c1ee2758..8d85ae62fc7 100644 --- a/src/amd/common/ac_llvm_build.h +++ b/src/amd/common/ac_llvm_build.h @@ -29,6 +29,7 @@ #include #include "compiler/nir/nir.h" #include "amd_family.h" +#include "ac_shader_util.h" #ifdef __cplusplus extern "C" { @@ -521,17 +522,6 @@ enum ac_atomic_op { ac_atomic_dec_wrap, }; -enum ac_image_dim { - ac_image_1d, - ac_image_2d, - ac_image_3d, - ac_image_cube, // includes cube arrays - ac_image_1darray, - ac_image_2darray, - ac_image_2dmsaa, - ac_image_2darraymsaa, -}; - /* These cache policy bits match the definitions used by the LLVM intrinsics. */ enum ac_image_cache_policy { ac_glc = 1 << 0, /* per-CU cache control */ diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c index 074584227c1..781f9ae1258 100644 --- a/src/amd/common/ac_nir_to_llvm.c +++ b/src/amd/common/ac_nir_to_llvm.c @@ -83,57 +83,6 @@ build_store_values_extended(struct ac_llvm_context *ac, } } -static enum ac_image_dim -get_ac_sampler_dim(const struct ac_llvm_context *ctx, enum glsl_sampler_dim dim, - bool is_array) -{ - switch (dim) { - case GLSL_SAMPLER_DIM_1D: - if (ctx->chip_class == GFX9) - return is_array ? ac_image_2darray : ac_image_2d; - return is_array ? ac_image_1darray : ac_image_1d; - case GLSL_SAMPLER_DIM_2D: - case GLSL_SAMPLER_DIM_RECT: - case GLSL_SAMPLER_DIM_EXTERNAL: - return is_array ? ac_image_2darray : ac_image_2d; - case GLSL_SAMPLER_DIM_3D: - return ac_image_3d; - case GLSL_SAMPLER_DIM_CUBE: - return ac_image_cube; - case GLSL_SAMPLER_DIM_MS: - return is_array ? ac_image_2darraymsaa : ac_image_2dmsaa; - case GLSL_SAMPLER_DIM_SUBPASS: - return ac_image_2darray; - case GLSL_SAMPLER_DIM_SUBPASS_MS: - return ac_image_2darraymsaa; - default: - unreachable("bad sampler dim"); - } -} - -static enum ac_image_dim -get_ac_image_dim(const struct ac_llvm_context *ctx, enum glsl_sampler_dim sdim, - bool is_array) -{ - enum ac_image_dim dim = get_ac_sampler_dim(ctx, sdim, is_array); - - /* Match the resource type set in the descriptor. */ - if (dim == ac_image_cube || - (ctx->chip_class <= GFX8 && dim == ac_image_3d)) - dim = ac_image_2darray; - else if (sdim == GLSL_SAMPLER_DIM_2D && !is_array && ctx->chip_class == GFX9) { - /* When a single layer of a 3D texture is bound, the shader - * will refer to a 2D target, but the descriptor has a 3D type. - * Since the HW ignores BASE_ARRAY in this case, we need to - * send 3 coordinates. This doesn't hurt when the underlying - * texture is non-3D. - */ - dim = ac_image_3d; - } - - return dim; -} - static LLVMTypeRef get_def_type(struct ac_nir_context *ctx, const nir_ssa_def *def) { @@ -1282,7 +1231,7 @@ static LLVMValueRef lower_gather4_integer(struct ac_llvm_context *ctx, } /* Query the texture size. */ - resinfo.dim = get_ac_sampler_dim(ctx, instr->sampler_dim, instr->is_array); + resinfo.dim = ac_get_sampler_dim(ctx->chip_class, instr->sampler_dim, instr->is_array); resinfo.opcode = ac_image_get_resinfo; resinfo.dmask = 0xf; resinfo.lod = ctx->i32_0; @@ -2612,7 +2561,7 @@ static LLVMValueRef visit_image_load(struct ac_nir_context *ctx, args.opcode = ac_image_load; args.resource = get_image_descriptor(ctx, instr, AC_DESC_IMAGE, false); get_image_coords(ctx, instr, &args, dim, is_array); - args.dim = get_ac_image_dim(&ctx->ac, dim, is_array); + args.dim = ac_get_image_dim(ctx->ac.chip_class, dim, is_array); args.dmask = 15; args.attributes = AC_FUNC_ATTR_READONLY; @@ -2669,7 +2618,7 @@ static void visit_image_store(struct ac_nir_context *ctx, args.data[0] = ac_to_float(&ctx->ac, get_src(ctx, instr->src[3])); args.resource = get_image_descriptor(ctx, instr, AC_DESC_IMAGE, true); get_image_coords(ctx, instr, &args, dim, is_array); - args.dim = get_ac_image_dim(&ctx->ac, dim, is_array); + args.dim = ac_get_image_dim(ctx->ac.chip_class, dim, is_array); args.dmask = 15; ac_build_image_opcode(&ctx->ac, &args); @@ -2822,7 +2771,7 @@ static LLVMValueRef visit_image_atomic(struct ac_nir_context *ctx, args.data[1] = params[1]; args.resource = get_image_descriptor(ctx, instr, AC_DESC_IMAGE, true); get_image_coords(ctx, instr, &args, dim, is_array); - args.dim = get_ac_image_dim(&ctx->ac, dim, is_array); + args.dim = ac_get_image_dim(ctx->ac.chip_class, dim, is_array); return ac_build_image_opcode(&ctx->ac, &args); } @@ -2844,7 +2793,7 @@ static LLVMValueRef visit_image_samples(struct ac_nir_context *ctx, } struct ac_image_args args = { 0 }; - args.dim = get_ac_sampler_dim(&ctx->ac, dim, is_array); + args.dim = ac_get_sampler_dim(ctx->ac.chip_class, dim, is_array); args.dmask = 0xf; args.resource = get_image_descriptor(ctx, instr, AC_DESC_IMAGE, false); args.opcode = ac_image_get_resinfo; @@ -2876,7 +2825,7 @@ static LLVMValueRef visit_image_size(struct ac_nir_context *ctx, struct ac_image_args args = { 0 }; - args.dim = get_ac_image_dim(&ctx->ac, dim, is_array); + args.dim = ac_get_image_dim(ctx->ac.chip_class, dim, is_array); args.dmask = 0xf; args.resource = get_image_descriptor(ctx, instr, AC_DESC_IMAGE, false); args.opcode = ac_image_get_resinfo; @@ -4267,7 +4216,7 @@ static void visit_tex(struct ac_nir_context *ctx, nir_tex_instr *instr) } if (instr->sampler_dim != GLSL_SAMPLER_DIM_BUF) { - args.dim = get_ac_sampler_dim(&ctx->ac, instr->sampler_dim, instr->is_array); + args.dim = ac_get_sampler_dim(ctx->ac.chip_class, instr->sampler_dim, instr->is_array); args.unorm = instr->sampler_dim == GLSL_SAMPLER_DIM_RECT; } result = build_tex_intrinsic(ctx, instr, &args); diff --git a/src/amd/common/ac_shader_util.c b/src/amd/common/ac_shader_util.c index c94feb06f17..e9fcae6469a 100644 --- a/src/amd/common/ac_shader_util.c +++ b/src/amd/common/ac_shader_util.c @@ -108,3 +108,100 @@ ac_vgt_gs_mode(unsigned gs_max_vert_out, enum chip_class chip_class) S_028A40_ONCHIP(chip_class >= GFX9 ? 1 : 0); } +/// Translate a (dfmt, nfmt) pair into a chip-appropriate combined format +/// value for LLVM8+ tbuffer intrinsics. +unsigned +ac_get_tbuffer_format(enum chip_class chip_class, + unsigned dfmt, unsigned nfmt) +{ + if (chip_class >= GFX10) { + unsigned format; + switch (dfmt) { + default: unreachable("bad dfmt"); + case V_008F0C_BUF_DATA_FORMAT_INVALID: format = V_008F0C_IMG_FORMAT_INVALID; break; + case V_008F0C_BUF_DATA_FORMAT_8: format = V_008F0C_IMG_FORMAT_8_UINT; break; + case V_008F0C_BUF_DATA_FORMAT_8_8: format = V_008F0C_IMG_FORMAT_8_8_UINT; break; + case V_008F0C_BUF_DATA_FORMAT_8_8_8_8: format = V_008F0C_IMG_FORMAT_8_8_8_8_UINT; break; + case V_008F0C_BUF_DATA_FORMAT_16: format = V_008F0C_IMG_FORMAT_16_UINT; break; + case V_008F0C_BUF_DATA_FORMAT_16_16: format = V_008F0C_IMG_FORMAT_16_16_UINT; break; + case V_008F0C_BUF_DATA_FORMAT_16_16_16_16: format = V_008F0C_IMG_FORMAT_16_16_16_16_UINT; break; + case V_008F0C_BUF_DATA_FORMAT_32: format = V_008F0C_IMG_FORMAT_32_UINT; break; + case V_008F0C_BUF_DATA_FORMAT_32_32: format = V_008F0C_IMG_FORMAT_32_32_UINT; break; + case V_008F0C_BUF_DATA_FORMAT_32_32_32: format = V_008F0C_IMG_FORMAT_32_32_32_UINT; break; + case V_008F0C_BUF_DATA_FORMAT_32_32_32_32: format = V_008F0C_IMG_FORMAT_32_32_32_32_UINT; break; + case V_008F0C_BUF_DATA_FORMAT_2_10_10_10: format = V_008F0C_IMG_FORMAT_2_10_10_10_UINT; break; + } + + // Use the regularity properties of the combined format enum. + // + // Note: float is incompatible with 8-bit data formats, + // [us]{norm,scaled} are incomparible with 32-bit data formats. + // [us]scaled are not writable. + switch (nfmt) { + case V_008F0C_BUF_NUM_FORMAT_UNORM: format -= 4; break; + case V_008F0C_BUF_NUM_FORMAT_SNORM: format -= 3; break; + case V_008F0C_BUF_NUM_FORMAT_USCALED: format -= 2; break; + case V_008F0C_BUF_NUM_FORMAT_SSCALED: format -= 1; break; + default: unreachable("bad nfmt"); + case V_008F0C_BUF_NUM_FORMAT_UINT: break; + case V_008F0C_BUF_NUM_FORMAT_SINT: format += 1; break; + case V_008F0C_BUF_NUM_FORMAT_FLOAT: format += 2; break; + } + + return format; + } else { + return dfmt | (nfmt << 4); + } +} + +enum ac_image_dim +ac_get_sampler_dim(enum chip_class chip_class, enum glsl_sampler_dim dim, + bool is_array) +{ + switch (dim) { + case GLSL_SAMPLER_DIM_1D: + if (chip_class == GFX9) + return is_array ? ac_image_2darray : ac_image_2d; + return is_array ? ac_image_1darray : ac_image_1d; + case GLSL_SAMPLER_DIM_2D: + case GLSL_SAMPLER_DIM_RECT: + case GLSL_SAMPLER_DIM_EXTERNAL: + return is_array ? ac_image_2darray : ac_image_2d; + case GLSL_SAMPLER_DIM_3D: + return ac_image_3d; + case GLSL_SAMPLER_DIM_CUBE: + return ac_image_cube; + case GLSL_SAMPLER_DIM_MS: + return is_array ? ac_image_2darraymsaa : ac_image_2dmsaa; + case GLSL_SAMPLER_DIM_SUBPASS: + return ac_image_2darray; + case GLSL_SAMPLER_DIM_SUBPASS_MS: + return ac_image_2darraymsaa; + default: + unreachable("bad sampler dim"); + } +} + +enum ac_image_dim +ac_get_image_dim(enum chip_class chip_class, enum glsl_sampler_dim sdim, + bool is_array) +{ + enum ac_image_dim dim = ac_get_sampler_dim(chip_class, sdim, is_array); + + /* Match the resource type set in the descriptor. */ + if (dim == ac_image_cube || + (chip_class <= GFX8 && dim == ac_image_3d)) + dim = ac_image_2darray; + else if (sdim == GLSL_SAMPLER_DIM_2D && !is_array && chip_class == GFX9) { + /* When a single layer of a 3D texture is bound, the shader + * will refer to a 2D target, but the descriptor has a 3D type. + * Since the HW ignores BASE_ARRAY in this case, we need to + * send 3 coordinates. This doesn't hurt when the underlying + * texture is non-3D. + */ + dim = ac_image_3d; + } + + return dim; +} + diff --git a/src/amd/common/ac_shader_util.h b/src/amd/common/ac_shader_util.h index 1bdf909e099..9a9d3f1b232 100644 --- a/src/amd/common/ac_shader_util.h +++ b/src/amd/common/ac_shader_util.h @@ -28,6 +28,18 @@ #include #include "amd_family.h" +#include "compiler/nir/nir.h" + +enum ac_image_dim { + ac_image_1d, + ac_image_2d, + ac_image_3d, + ac_image_cube, // includes cube arrays + ac_image_1darray, + ac_image_2darray, + ac_image_2dmsaa, + ac_image_2darraymsaa, +}; unsigned ac_get_spi_shader_z_format(bool writes_z, bool writes_stencil, @@ -39,4 +51,16 @@ ac_get_cb_shader_mask(unsigned spi_shader_col_format); uint32_t ac_vgt_gs_mode(unsigned gs_max_vert_out, enum chip_class chip_class); +unsigned +ac_get_tbuffer_format(enum chip_class chip_class, + unsigned dfmt, unsigned nfmt); + +enum ac_image_dim +ac_get_sampler_dim(enum chip_class chip_class, enum glsl_sampler_dim dim, + bool is_array); + +enum ac_image_dim +ac_get_image_dim(enum chip_class chip_class, enum glsl_sampler_dim sdim, + bool is_array); + #endif -- 2.30.2