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.
This commit is contained in:
parent
80e9eb66d5
commit
6fcd071c7b
|
@ -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,
|
||||
|
|
|
@ -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';
|
||||
r_safe_name[11] = '\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. */
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue