From 6fcd071c7bcb8c9a5e0a7d0e7a6ef6363e43627e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 14 Aug 2019 23:43:03 +0200 Subject: GPU: Vertex Format: Increase number of byte per attribute name This reduces the risks of hash collision while maintaining a small number of character per attrib. --- source/blender/gpu/GPU_vertex_format.h | 2 +- source/blender/gpu/intern/gpu_vertex_format.c | 49 +++++++++++++-------------- 2 files changed, 24 insertions(+), 27 deletions(-) (limited to 'source') diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h index 97c1828b593..8c22e3e1104 100644 --- a/source/blender/gpu/GPU_vertex_format.h +++ b/source/blender/gpu/GPU_vertex_format.h @@ -35,7 +35,7 @@ #define GPU_VERT_ATTR_NAMES_BUF_LEN 256 #define GPU_VERT_FORMAT_MAX_NAMES 63 /* More than enough, actual max is ~30. */ /* Computed as GPU_VERT_ATTR_NAMES_BUF_LEN / 30 (actual max format name). */ -#define GPU_MAX_SAFE_ATTRIB_NAME 8 +#define GPU_MAX_SAFE_ATTRIB_NAME 12 typedef enum { GPU_COMP_I8, diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c index 2cfb17b1568..11df86c0b3a 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.c +++ b/source/blender/gpu/intern/gpu_vertex_format.c @@ -220,20 +220,6 @@ int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name) return -1; } -/* Encode 4 original bytes into 6 safe bytes. */ -static void safe_bytes(char out[6], const char data[4]) -{ - char safe_chars[63] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; - - uint32_t in = *(uint32_t *)data; - for (int i = 0; i < 6; i++) { - /* Encoding in base63 */ - out[i] = safe_chars[in % 63u]; - in /= 63u; - } -} - -#if 0 /* For when we can use 11chars names. */ /* Encode 8 original bytes into 11 safe bytes. */ static void safe_bytes(char out[11], const char data[8]) { @@ -246,7 +232,6 @@ static void safe_bytes(char out[11], const char data[8]) in /= 63lu; } } -#endif /* Warning: Always add a prefix to the result of this function as * the generated string can start with a number and not be a valid attribute name. */ @@ -254,22 +239,34 @@ void GPU_vertformat_safe_attrib_name(const char *attrib_name, char *r_safe_name, uint UNUSED(max_len)) { - char data[4] = {0}; - /* We use a hash to identify each data layer based on its name. - * NOTE: This is still prone to hash collision but the risks are very low.*/ - *(uint *)data = BLI_ghashutil_strhash_p_murmur(attrib_name); + char data[8] = {0}; + uint len = strlen(attrib_name); + + if (len > 8) { + /* Start with the first 4 chars of the name; */ + for (int i = 0; i < 4; i++) { + data[i] = attrib_name[i]; + } + /* We use a hash to identify each data layer based on its name. + * NOTE: This is still prone to hash collision but the risks are very low.*/ + /* Start hashing after the first 2 chars. */ + *(uint *)&data[4] = BLI_ghashutil_strhash_p_murmur(attrib_name + 4); + } + else { + /* Copy the whole name. Collision is barelly possible + * (hash would have to be equal to the last 4 bytes). */ + for (int i = 0; i < 8 && attrib_name[i] != '\0'; i++) { + data[i] = attrib_name[i]; + } + } /* Convert to safe bytes characters. */ safe_bytes(r_safe_name, data); /* End the string */ - r_safe_name[6] = '\0'; - - /* TOOD(fclem) When UV and Tangent buffers will be separated, name buffer will have plenty more - * space. In this case, we can think of having ~13 chars for each name which would be enough to - * encode some of the input string along with the hash to reduce colision possibility. */ + r_safe_name[11] = '\0'; - BLI_assert(GPU_MAX_SAFE_ATTRIB_NAME >= 7); + BLI_assert(GPU_MAX_SAFE_ATTRIB_NAME >= 12); #if 0 /* For debugging */ - printf("%s > %x > %s\n", attrib_name, *(uint32_t *)data, r_safe_name); + printf("%s > %lx > %s\n", attrib_name, *(uint64_t *)data, r_safe_name); #endif } -- cgit v1.2.3