Mesa (main): ac/gpu_info: add AMD_CU_MASK environment variable to set CU_EN
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Wed Jan 5 07:07:30 UTC 2022
Module: Mesa
Branch: main
Commit: 470b61f3a972e9ae8fc8d2715a110490576d6be3
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=470b61f3a972e9ae8fc8d2715a110490576d6be3
Author: Marek Olšák <marek.olsak at amd.com>
Date: Wed Dec 8 00:33:10 2021 -0500
ac/gpu_info: add AMD_CU_MASK environment variable to set CU_EN
requested internally
Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14122>
---
src/amd/common/ac_gpu_info.c | 155 ++++++++++++++++++++++++++++++++++++++++++-
src/amd/common/ac_gpu_info.h | 4 ++
2 files changed, 157 insertions(+), 2 deletions(-)
diff --git a/src/amd/common/ac_gpu_info.c b/src/amd/common/ac_gpu_info.c
index a1cc9e1eefb..3e51eecebbd 100644
--- a/src/amd/common/ac_gpu_info.c
+++ b/src/amd/common/ac_gpu_info.c
@@ -24,12 +24,15 @@
*/
#include "ac_gpu_info.h"
+#include "ac_shader_util.h"
#include "addrlib/src/amdgpu_asic_addr.h"
#include "sid.h"
#include "util/macros.h"
#include "util/u_cpu_detect.h"
#include "util/u_math.h"
+#include "util/os_misc.h"
+#include "util/bitset.h"
#include <stdio.h>
#include <ctype.h>
@@ -330,6 +333,151 @@ has_tmz_support(amdgpu_device_handle dev,
return true;
}
+static void set_custom_cu_en_mask(struct radeon_info *info)
+{
+ info->spi_cu_en = ~0;
+
+ const char *cu_env_var = os_get_option("AMD_CU_MASK");
+ if (!cu_env_var)
+ return;
+
+ int size = strlen(cu_env_var);
+ char *str = alloca(size + 1);
+ memset(str, 0, size + 1);
+
+ size = 0;
+
+ /* Strip whitespace. */
+ for (unsigned src = 0; cu_env_var[src]; src++) {
+ if (cu_env_var[src] != ' ' && cu_env_var[src] != '\t' &&
+ cu_env_var[src] != '\n' && cu_env_var[src] != '\r') {
+ str[size++] = cu_env_var[src];
+ }
+ }
+
+ /* The following syntax is used, all whitespace is ignored:
+ * ID = [0-9][0-9]* ex. base 10 numbers
+ * ID_list = (ID | ID-ID)[, (ID | ID-ID)]* ex. 0,2-4,7
+ * CU_list = 0x[0-F]* | ID_list ex. 0x337F OR 0,2-4,7
+ * AMD_CU_MASK = CU_list
+ *
+ * It's a CU mask within a shader array. It's applied to all shader arrays.
+ */
+ bool is_good_form = true;
+ uint32_t spi_cu_en = 0;
+
+ if (size > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
+ str += 2;
+ size -= 2;
+
+ for (unsigned i = 0; i < size; i++)
+ is_good_form &= isxdigit(str[i]) != 0;
+
+ if (!is_good_form) {
+ fprintf(stderr, "amd: invalid AMD_CU_MASK: ill-formed hex value\n");
+ } else {
+ spi_cu_en = strtol(str, NULL, 16);
+ }
+ } else {
+ /* Parse ID_list. */
+ long first = 0, last = -1;
+
+ if (!isdigit(*str)) {
+ is_good_form = false;
+ } else {
+ while (*str) {
+ bool comma = false;
+
+ if (isdigit(*str)) {
+ first = last = strtol(str, &str, 10);
+ } else if (*str == '-') {
+ str++;
+ /* Parse a digit after a dash. */
+ if (isdigit(*str)) {
+ last = strtol(str, &str, 10);
+ } else {
+ fprintf(stderr, "amd: invalid AMD_CU_MASK: expected a digit after -\n");
+ is_good_form = false;
+ break;
+ }
+ } else if (*str == ',') {
+ comma = true;
+ str++;
+ if (!isdigit(*str)) {
+ fprintf(stderr, "amd: invalid AMD_CU_MASK: expected a digit after ,\n");
+ is_good_form = false;
+ break;
+ }
+ }
+
+ if (comma || !*str) {
+ if (first > last) {
+ fprintf(stderr, "amd: invalid AMD_CU_MASK: range not increasing (%li, %li)\n", first, last);
+ is_good_form = false;
+ break;
+ }
+ if (last > 31) {
+ fprintf(stderr, "amd: invalid AMD_CU_MASK: index too large (%li)\n", last);
+ is_good_form = false;
+ break;
+ }
+
+ spi_cu_en |= BITFIELD_RANGE(first, last - first + 1);
+ last = -1;
+ }
+ }
+ }
+ }
+
+ /* The mask is parsed. Now assign bits to CUs. */
+ if (is_good_form) {
+ bool error = false;
+
+ /* Clear bits that have no effect. */
+ spi_cu_en &= BITFIELD_MASK(info->max_good_cu_per_sa);
+
+ if (!spi_cu_en) {
+ fprintf(stderr, "amd: invalid AMD_CU_MASK: at least 1 CU in each SA must be enabled\n");
+ error = true;
+ }
+
+ if (info->has_graphics) {
+ uint32_t min_full_cu_mask = BITFIELD_MASK(info->min_good_cu_per_sa);
+
+ /* The hw ignores all non-compute CU masks if any of them is 0. Disallow that. */
+ if ((spi_cu_en & min_full_cu_mask) == 0) {
+ fprintf(stderr, "amd: invalid AMD_CU_MASK: at least 1 CU from 0x%x per SA must be "
+ "enabled (SPI limitation)\n", min_full_cu_mask);
+ error = true;
+ }
+
+ /* We usually disable 1 or 2 CUs for VS and GS, which means at last 1 other CU
+ * must be enabled.
+ */
+ uint32_t cu_mask_ge, unused;
+ ac_compute_late_alloc(info, false, false, false, &unused, &cu_mask_ge);
+ cu_mask_ge &= min_full_cu_mask;
+
+ if ((spi_cu_en & cu_mask_ge) == 0) {
+ fprintf(stderr, "amd: invalid AMD_CU_MASK: at least 1 CU from 0x%x per SA must be "
+ "enabled (late alloc constraint for GE)\n", cu_mask_ge);
+ error = true;
+ }
+
+ if ((min_full_cu_mask & spi_cu_en & ~cu_mask_ge) == 0) {
+ fprintf(stderr, "amd: invalid AMD_CU_MASK: at least 1 CU from 0x%x per SA must be "
+ "enabled (late alloc constraint for PS)\n",
+ min_full_cu_mask & ~cu_mask_ge);
+ error = true;
+ }
+ }
+
+ if (!error) {
+ info->spi_cu_en = spi_cu_en;
+ info->spi_cu_en_has_effect = spi_cu_en & BITFIELD_MASK(info->max_good_cu_per_sa);
+ }
+ }
+}
bool ac_query_gpu_info(int fd, void *dev_p, struct radeon_info *info,
struct amdgpu_gpu_info *amdinfo)
@@ -1095,6 +1243,7 @@ bool ac_query_gpu_info(int fd, void *dev_p, struct radeon_info *info,
info->num_physical_wave64_vgprs_per_simd = info->chip_class >= GFX10 ? 512 : 256;
info->num_simd_per_compute_unit = info->chip_class >= GFX10 ? 2 : 4;
+ set_custom_cu_en_mask(info);
return true;
}
@@ -1253,10 +1402,12 @@ void ac_print_gpu_info(struct radeon_info *info, FILE *f)
fprintf(f, "Shader core info:\n");
for (unsigned i = 0; i < info->max_se; i++) {
for (unsigned j = 0; j < info->max_sa_per_se; j++) {
- fprintf(f, " cu_mask[SE%u][SA%u] = 0x%x \t(%u)\n",
- i, j, info->cu_mask[i][j], util_bitcount(info->cu_mask[i][j]));
+ fprintf(f, " cu_mask[SE%u][SA%u] = 0x%x \t(%u)\tCU_EN = 0x%x\n", i, j,
+ info->cu_mask[i][j], util_bitcount(info->cu_mask[i][j]),
+ info->spi_cu_en & BITFIELD_MASK(util_bitcount(info->cu_mask[i][j])));
}
}
+ fprintf(f, " spi_cu_en_has_effect = %i\n", info->spi_cu_en_has_effect);
fprintf(f, " max_shader_clock = %i\n", info->max_shader_clock);
fprintf(f, " num_good_compute_units = %i\n", info->num_good_compute_units);
fprintf(f, " max_good_cu_per_sa = %i\n", info->max_good_cu_per_sa);
diff --git a/src/amd/common/ac_gpu_info.h b/src/amd/common/ac_gpu_info.h
index fd89af0a887..51e27f027cd 100644
--- a/src/amd/common/ac_gpu_info.h
+++ b/src/amd/common/ac_gpu_info.h
@@ -232,6 +232,10 @@ struct radeon_info {
/* Tile modes. */
uint32_t si_tile_mode_array[32];
uint32_t cik_macrotile_mode_array[16];
+
+ /* AMD_CU_MASK environment variable or ~0. */
+ bool spi_cu_en_has_effect;
+ uint32_t spi_cu_en;
};
bool ac_query_gpu_info(int fd, void *dev_p, struct radeon_info *info,
More information about the mesa-commit
mailing list