diff --git a/glad/generator/c/templates/base_template.c b/glad/generator/c/templates/base_template.c index 29d82169..d4fc4bcc 100644 --- a/glad/generator/c/templates/base_template.c +++ b/glad/generator/c/templates/base_template.c @@ -3,6 +3,7 @@ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 */ {% block includes %} +#include #include #include #include @@ -54,25 +55,49 @@ static uint64_t GLAD_{{ feature_set.name|api }}_ext_hashes[] = { {% endfor %} }; -static int32_t glad_hash_search(const uint64_t *arr, uint32_t size, uint64_t target) { - int32_t left = 0; - int32_t right = (int32_t)size - 1; +static bool glad_hash_search_linear(const uint64_t *arr, uint32_t size, uint64_t target) { + /* Linear search. This may look awful, but Clang can vectorize this yielding + * a very high IPC. */ + uint32_t i; + bool found = false; + for (i = 0; i < size; ++i) { + if (arr[i] == target) + found = true; + } + return found; +} + +GLAD_NO_INLINE static bool glad_hash_search(const uint64_t *arr, uint32_t size, uint64_t target) { + /* Binary search approach. arr[] must be sorted for this to work. */ + uint32_t left; + uint32_t right; + + if (size < 1) + return false; + + left = 0; + right = size - 1; while (left <= right) { - int32_t mid = left + (right - left) / 2; + uint32_t rangesize = (right - left); + uint32_t mid = left + rangesize / 2; if (arr[mid] == target) { - return mid; + return true; + } + + if (rangesize <= 256) { + return glad_hash_search_linear(&arr[left], rangesize, target); } + if (arr[mid] < target) { left = mid + 1; - } - else { + } else { right = mid - 1; } } - return -1; + return false; } static int glad_hash_compare(const void *_l, const void *_r) diff --git a/glad/generator/c/templates/egl.c b/glad/generator/c/templates/egl.c index d2cb08fd..618ae83f 100644 --- a/glad/generator/c/templates/egl.c +++ b/glad/generator/c/templates/egl.c @@ -71,12 +71,7 @@ static int glad_egl_get_extensions({{ template_utils.context_arg(', ') }}EGLDisp } static int glad_egl_has_extension(uint64_t *exts, uint32_t num_exts, uint64_t extension) { - int32_t match = glad_hash_search(exts, num_exts, extension); - - if (match >= 0) - return 1; - - return 0; + return glad_hash_search(exts, num_exts, extension); } static GLADapiproc glad_egl_get_proc_from_userptr(void *userptr, const char *name) { diff --git a/glad/generator/c/templates/gl.c b/glad/generator/c/templates/gl.c index de26fad1..862d445e 100644 --- a/glad/generator/c/templates/gl.c +++ b/glad/generator/c/templates/gl.c @@ -89,13 +89,7 @@ static void glad_gl_free_extensions(uint64_t *exts) { } static int glad_gl_has_extension(uint64_t *exts, uint32_t num_exts, uint64_t ext) { - - int32_t match = glad_hash_search(exts, num_exts, ext); - - if (match >= 0) - return 1; - - return 0; + return glad_hash_search(exts, num_exts, ext); } static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name) { diff --git a/glad/generator/c/templates/loader/vulkan.c b/glad/generator/c/templates/loader/vulkan.c index a7f6a2a8..33222985 100644 --- a/glad/generator/c/templates/loader/vulkan.c +++ b/glad/generator/c/templates/loader/vulkan.c @@ -16,14 +16,7 @@ static int glad_vulkan_is_device_function(const char *name) { * * `vkGetDeviceProcAddr` does not return NULL for non-device functions. */ - const uint32_t length = GLAD_ARRAYSIZE(DEVICE_FUNCTIONS); - int32_t match; - - match = glad_hash_search(DEVICE_FUNCTIONS, length, glad_hash_string(name, strlen(name))); - if (match >= 0) - return 1; - - return 0; + return glad_hash_search(DEVICE_FUNCTIONS, GLAD_ARRAYSIZE(DEVICE_FUNCTIONS), glad_hash_string(name, strlen(name))); } struct _glad_vulkan_userptr { diff --git a/glad/generator/c/templates/vk.c b/glad/generator/c/templates/vk.c index 904d04f1..471a8d7c 100644 --- a/glad/generator/c/templates/vk.c +++ b/glad/generator/c/templates/vk.c @@ -92,13 +92,7 @@ static void glad_vk_free_extensions(uint64_t *extensions) { } static int glad_vk_has_extension(uint64_t name, uint32_t extension_count, uint64_t *extensions) { - int match; - - match = glad_hash_search(extensions, extension_count, name); - if (match >= 0) - return 1; - - return 0; + return glad_hash_search(extensions, extension_count, name); } static GLADapiproc glad_vk_get_proc_from_userptr(void *userptr, const char* name) {