diff --git a/example/c/vulkan_tri_glfw.c b/example/c/vulkan_tri_glfw.c index acfed222..f52ce1ad 100644 --- a/example/c/vulkan_tri_glfw.c +++ b/example/c/vulkan_tri_glfw.c @@ -1995,19 +1995,11 @@ static void demo_init_device(struct demo *demo) { err = vkCreateDevice(demo->gpu, &device, NULL, &demo->device); assert(!err); - /* - Currently can't load device pointers here, - since vkGetDeviceProcAddr does **not** return NULL for non-device functions. - This needs to be addressed within the glad loader. - - See: https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/issues/2323 - int glad_vk_version = gladLoadVulkanInternalLoader(demo->inst, demo->device); if (!glad_vk_version) { ERR_EXIT("Unable to re-load Vulkan symbols with device!\n", "gladLoad Failure"); } - */ } static void demo_init_vk_swapchain(struct demo *demo) { diff --git a/glad/generator/c/__init__.py b/glad/generator/c/__init__.py index a0d6eede..0c7cac2a 100644 --- a/glad/generator/c/__init__.py +++ b/glad/generator/c/__init__.py @@ -151,7 +151,16 @@ def collect_alias_information(commands): return alias -_CPP_STYLE_COMMENT_RE = re.compile(r'(^|\s)//(?P<'r'comment>.*)$', flags=re.MULTILINE) +def is_device_command(command): + if len(command.params) == 0: + return False + + first_param = command.params[0] + # See: https://github.com/Igalia/mesa/blob/dda3efb51c26e24eda83f17cf6b9d99402511ee1/src/intel/vulkan/anv_entrypoints_gen.py#L434 + return first_param.type.type in ('VkDevice', 'VkCommandBuffer', 'VkQueue') + + +_CPP_STYLE_COMMENT_RE = re.compile(r'(^|\s|\))//(?P<'r'comment>.*)$', flags=re.MULTILINE) def replace_cpp_style_comments(inp): @@ -246,12 +255,14 @@ def __init__(self, *args, **kwargs): ) def get_additional_template_arguments(self, spec, feature_set, config): - return { - 'loadable': functools.partial(loadable, spec, feature_set), - 'aliases': collect_alias_information(feature_set.commands), - 'apiptrp': 'VKAPI_PTR*' if spec.name == 'vk' else 'APIENTRYP', - 'apicall': 'VKAPI_CALL' if spec.name == 'vk' else 'GLAPI' - } + return dict( + loadable=functools.partial(loadable, spec, feature_set), + aliases=collect_alias_information(feature_set.commands), + apiptrp='VKAPI_PTR*' if spec.name == 'vk' else 'APIENTRYP', + apicall='VKAPI_CALL' if spec.name == 'vk' else 'GLAPI', + # required for vulkan loader: + device_commands=list(filter(is_device_command, feature_set.commands)) + ) def get_templates(self, spec, feature_set, config): header = 'include/glad/{}.h'.format(feature_set.api) diff --git a/glad/generator/c/templates/loader/vulkan.c b/glad/generator/c/templates/loader/vulkan.c index ed7b6955..dc7816e4 100644 --- a/glad/generator/c/templates/loader/vulkan.c +++ b/glad/generator/c/templates/loader/vulkan.c @@ -3,6 +3,30 @@ {% include 'loader/library.c' %} + +static const char* DEVICE_FUNCTIONS[] = { +{% for command in device_commands %} + "{{ command.name }}", +{% endfor %} +}; + +static int glad_vulkan_is_device_function(const char *name) { + /* Exists as a workaround for: + * https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/issues/2323 + * + * `vkGetDeviceProcAddr` does not return NULL for non-device functions. + */ + int i; + + for (i=0; i < sizeof(DEVICE_FUNCTIONS) / sizeof(DEVICE_FUNCTIONS[0]); ++i) { + if (strcmp(DEVICE_FUNCTIONS[i], name) == 0) { + return 1; + } + } + + return 0; +} + struct _glad_vulkan_userptr { void *vk_handle; VkInstance vk_instance; @@ -15,8 +39,7 @@ static void* glad_vulkan_get_proc(const char *name, void *vuserptr) { struct _glad_vulkan_userptr userptr = *(struct _glad_vulkan_userptr*) vuserptr; PFN_vkVoidFunction result = NULL; - {# /* TODO fix: https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/issues/2323 */ #} - if (userptr.vk_device != NULL) { + if (userptr.vk_device != NULL && glad_vulkan_is_device_function(name)) { result = userptr.vkGetDeviceProcAddr(userptr.vk_device, name); }