On Tue, Oct 17, 2017 at 7:36 AM, Dave Airlie <airl...@gmail.com> wrote: > From: Dave Airlie <airl...@redhat.com> > > This ports radv to using the anv entrypoint/extension generator > code. > > No differences on enabled extensions list in vulkaninfo. > > Signed-off-by: Dave Airlie <airl...@redhat.com> > --- > src/amd/vulkan/.gitignore | 1 + > src/amd/vulkan/Makefile.am | 9 +- > src/amd/vulkan/Makefile.sources | 3 +- > src/amd/vulkan/radv_device.c | 271 +---------------------- > src/amd/vulkan/radv_entrypoints_gen.py | 381 > ++++++++++++++++----------------- > src/amd/vulkan/radv_extensions.py | 278 ++++++++++++++++++++++++ > src/amd/vulkan/radv_private.h | 11 +- > 7 files changed, 480 insertions(+), 474 deletions(-) > create mode 100644 src/amd/vulkan/radv_extensions.py > > diff --git a/src/amd/vulkan/.gitignore b/src/amd/vulkan/.gitignore > index 2a42d7f..7c02e42 100644 > --- a/src/amd/vulkan/.gitignore > +++ b/src/amd/vulkan/.gitignore > @@ -1,6 +1,7 @@ > # Generated source files > /radv_entrypoints.c > /radv_entrypoints.h > +/radv_extensions.c > /radv_timestamp.h > /dev_icd.json > /vk_format_table.c > diff --git a/src/amd/vulkan/Makefile.am b/src/amd/vulkan/Makefile.am > index 19ec3f4..7364e54 100644 > --- a/src/amd/vulkan/Makefile.am > +++ b/src/amd/vulkan/Makefile.am > @@ -107,12 +107,19 @@ libvulkan_radeon_la_SOURCES = $(VULKAN_GEM_FILES) > > vulkan_api_xml = $(top_srcdir)/src/vulkan/registry/vk.xml > > -radv_entrypoints.c: radv_entrypoints_gen.py $(vulkan_api_xml) > +radv_entrypoints.c: radv_entrypoints_gen.py radv_extensions.py > $(vulkan_api_xml) > $(MKDIR_GEN) > $(AM_V_GEN)$(PYTHON2) $(srcdir)/radv_entrypoints_gen.py \ > --xml $(vulkan_api_xml) --outdir $(builddir) > radv_entrypoints.h: radv_entrypoints.c > > +radv_extensions.c: radv_extensions.py \ > + $(vulkan_api_xml) > + $(MKDIR_GEN) > + $(AM_V_GEN)$(PYTHON2) $(srcdir)/radv_extensions.py \ > + --xml $(vulkan_api_xml) \ > + --out $@ > + > vk_format_table.c: vk_format_table.py \ > vk_format_parse.py \ > vk_format_layout.csv > diff --git a/src/amd/vulkan/Makefile.sources b/src/amd/vulkan/Makefile.sources > index fbdb797..c9d172c 100644 > --- a/src/amd/vulkan/Makefile.sources > +++ b/src/amd/vulkan/Makefile.sources > @@ -77,5 +77,6 @@ VULKAN_WSI_X11_FILES := \ > > VULKAN_GENERATED_FILES := \ > radv_entrypoints.c \ > - radv_entrypoints.h > + radv_entrypoints.h \ > + radv_extensions.c > > diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c > index b2aef2a..b9cd676 100644 > --- a/src/amd/vulkan/radv_device.c > +++ b/src/amd/vulkan/radv_device.c > @@ -76,198 +76,6 @@ radv_get_device_uuid(struct radeon_info *info, void *uuid) > ac_compute_device_uuid(info, uuid, VK_UUID_SIZE); > } > > -static const VkExtensionProperties instance_extensions[] = { > - { > - .extensionName = VK_KHR_SURFACE_EXTENSION_NAME, > - .specVersion = 25, > - }, > -#ifdef VK_USE_PLATFORM_XCB_KHR > - { > - .extensionName = VK_KHR_XCB_SURFACE_EXTENSION_NAME, > - .specVersion = 6, > - }, > -#endif > -#ifdef VK_USE_PLATFORM_XLIB_KHR > - { > - .extensionName = VK_KHR_XLIB_SURFACE_EXTENSION_NAME, > - .specVersion = 6, > - }, > -#endif > -#ifdef VK_USE_PLATFORM_WAYLAND_KHR > - { > - .extensionName = VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, > - .specVersion = 6, > - }, > -#endif > - { > - .extensionName = > VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = > VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = > VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME, > - .specVersion = 1, > - }, > -}; > - > -static const VkExtensionProperties common_device_extensions[] = { > - { > - .extensionName = > VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_MAINTENANCE1_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = > VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_SWAPCHAIN_EXTENSION_NAME, > - .specVersion = 68, > - }, > - { > - .extensionName = VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = > VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = > VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_MAINTENANCE2_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME, > - .specVersion = 1, > - }, > -}; > - > -static const VkExtensionProperties rasterization_order_extension[] ={ > - { > - .extensionName = VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME, > - .specVersion = 1, > - }, > -}; > - > -static const VkExtensionProperties ext_sema_device_extensions[] = { > - { > - .extensionName = VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, > - .specVersion = 1, > - }, > - { > - .extensionName = VK_KHX_MULTIVIEW_EXTENSION_NAME, > - .specVersion = 1, > - }, > -}; > - > -static VkResult > -radv_extensions_register(struct radv_instance *instance, > - struct radv_extensions *extensions, > - const VkExtensionProperties *new_ext, > - uint32_t num_ext) > -{ > - size_t new_size; > - VkExtensionProperties *new_ptr; > - > - assert(new_ext && num_ext > 0); > - > - if (!new_ext) > - return VK_ERROR_INITIALIZATION_FAILED; > - > - new_size = (extensions->num_ext + num_ext) * > sizeof(VkExtensionProperties); > - new_ptr = vk_realloc(&instance->alloc, extensions->ext_array, > - new_size, 8, > VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); > - > - /* Old array continues to be valid, update nothing */ > - if (!new_ptr) > - return VK_ERROR_OUT_OF_HOST_MEMORY; > - > - memcpy(&new_ptr[extensions->num_ext], new_ext, > - num_ext * sizeof(VkExtensionProperties)); > - extensions->ext_array = new_ptr; > - extensions->num_ext += num_ext; > - > - return VK_SUCCESS; > -} > - > -static void > -radv_extensions_finish(struct radv_instance *instance, > - struct radv_extensions *extensions) > -{ > - assert(extensions); > - > - if (!extensions) > - radv_loge("Attemted to free invalid extension struct\n"); > - > - if (extensions->ext_array) > - vk_free(&instance->alloc, extensions->ext_array); > -} > - > -static bool > -is_extension_enabled(const VkExtensionProperties *extensions, > - size_t num_ext, > - const char *name) > -{ > - assert(extensions && name); > - > - for (uint32_t i = 0; i < num_ext; i++) { > - if (strcmp(name, extensions[i].extensionName) == 0) > - return true; > - } > - > - return false; > -} > - > static const char * > get_chip_name(enum radeon_family family) > { > @@ -364,31 +172,6 @@ radv_physical_device_init(struct radv_physical_device > *device, > disk_cache_format_hex_id(buf, device->cache_uuid, VK_UUID_SIZE); > device->disk_cache = disk_cache_create("radv", buf, shader_env_flags); > > - result = radv_extensions_register(instance, > - &device->extensions, > - common_device_extensions, > - ARRAY_SIZE(common_device_extensions)); > - if (result != VK_SUCCESS) > - goto fail; > - > - if (device->rad_info.chip_class >= VI && device->rad_info.max_se >= > 2) { > - result = radv_extensions_register(instance, > - &device->extensions, > - rasterization_order_extension, > - > ARRAY_SIZE(rasterization_order_extension)); > - if (result != VK_SUCCESS) > - goto fail; > - } > - > - if (device->rad_info.has_syncobj) { > - result = radv_extensions_register(instance, > - &device->extensions, > - ext_sema_device_extensions, > - > ARRAY_SIZE(ext_sema_device_extensions)); > - if (result != VK_SUCCESS) > - goto fail; > - } > - > fprintf(stderr, "WARNING: radv is not a conformant vulkan > implementation, testing use only.\n"); > device->name = get_chip_name(device->rad_info.family); > > @@ -416,7 +199,6 @@ fail: > static void > radv_physical_device_finish(struct radv_physical_device *device) > { > - radv_extensions_finish(device->instance, &device->extensions); > radv_finish_wsi(device); > device->ws->destroy(device->ws); > disk_cache_destroy(device->disk_cache); > @@ -515,9 +297,8 @@ VkResult radv_CreateInstance( > } > > for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { > - if (!is_extension_enabled(instance_extensions, > - ARRAY_SIZE(instance_extensions), > - > pCreateInfo->ppEnabledExtensionNames[i])) > + const char *ext_name = > pCreateInfo->ppEnabledExtensionNames[i]; > + if (!radv_instance_extension_supported(ext_name)) > return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT); > } > > @@ -851,7 +632,7 @@ void radv_GetPhysicalDeviceProperties( > }; > > *pProperties = (VkPhysicalDeviceProperties) { > - .apiVersion = VK_MAKE_VERSION(1, 0, 42), > + .apiVersion = radv_physical_device_api_version(pdevice), > .driverVersion = vk_get_driver_version(), > .vendorID = ATI_VENDOR_ID, > .deviceID = pdevice->rad_info.pci_id, > @@ -1141,9 +922,8 @@ VkResult radv_CreateDevice( > struct radv_device *device; > > for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { > - if > (!is_extension_enabled(physical_device->extensions.ext_array, > - physical_device->extensions.num_ext, > - > pCreateInfo->ppEnabledExtensionNames[i])) > + const char *ext_name = > pCreateInfo->ppEnabledExtensionNames[i]; > + if > (!radv_physical_device_extension_supported(physical_device, ext_name)) > return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT); > } > > @@ -1331,47 +1111,6 @@ void radv_DestroyDevice( > vk_free(&device->alloc, device); > } > > -VkResult radv_EnumerateInstanceExtensionProperties( > - const char* pLayerName, > - uint32_t* pPropertyCount, > - VkExtensionProperties* pProperties) > -{ > - if (pProperties == NULL) { > - *pPropertyCount = ARRAY_SIZE(instance_extensions); > - return VK_SUCCESS; > - } > - > - *pPropertyCount = MIN2(*pPropertyCount, > ARRAY_SIZE(instance_extensions)); > - typed_memcpy(pProperties, instance_extensions, *pPropertyCount); > - > - if (*pPropertyCount < ARRAY_SIZE(instance_extensions)) > - return VK_INCOMPLETE; > - > - return VK_SUCCESS; > -} > - > -VkResult radv_EnumerateDeviceExtensionProperties( > - VkPhysicalDevice physicalDevice, > - const char* pLayerName, > - uint32_t* pPropertyCount, > - VkExtensionProperties* pProperties) > -{ > - RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice); > - > - if (pProperties == NULL) { > - *pPropertyCount = pdevice->extensions.num_ext; > - return VK_SUCCESS; > - } > - > - *pPropertyCount = MIN2(*pPropertyCount, pdevice->extensions.num_ext); > - typed_memcpy(pProperties, pdevice->extensions.ext_array, > *pPropertyCount); > - > - if (*pPropertyCount < pdevice->extensions.num_ext) > - return VK_INCOMPLETE; > - > - return VK_SUCCESS; > -} > - > VkResult radv_EnumerateInstanceLayerProperties( > uint32_t* pPropertyCount, > VkLayerProperties* pProperties) > diff --git a/src/amd/vulkan/radv_entrypoints_gen.py > b/src/amd/vulkan/radv_entrypoints_gen.py > index 713a98f..f8f99d0 100644 > --- a/src/amd/vulkan/radv_entrypoints_gen.py > +++ b/src/amd/vulkan/radv_entrypoints_gen.py > @@ -25,214 +25,184 @@ > import argparse > import functools > import os > -import textwrap > import xml.etree.cElementTree as et > > from mako.template import Template > > -MAX_API_VERSION = 1.0 > - > -SUPPORTED_EXTENSIONS = [ > - 'VK_AMD_draw_indirect_count', > - 'VK_NV_dedicated_allocation', > - 'VK_KHR_descriptor_update_template', > - 'VK_KHR_get_physical_device_properties2', > - 'VK_KHR_incremental_present', > - 'VK_KHR_maintenance1', > - 'VK_KHR_push_descriptor', > - 'VK_KHR_sampler_mirror_clamp_to_edge', > - 'VK_KHR_shader_draw_parameters', > - 'VK_KHR_surface', > - 'VK_KHR_swapchain', > - 'VK_KHR_wayland_surface', > - 'VK_KHR_xcb_surface', > - 'VK_KHR_xlib_surface', > - 'VK_KHR_get_memory_requirements2', > - 'VK_KHR_dedicated_allocation', > - 'VK_KHR_external_memory_capabilities', > - 'VK_KHR_external_memory', > - 'VK_KHR_external_memory_fd', > - 'VK_KHR_storage_buffer_storage_class', > - 'VK_KHR_variable_pointers', > - 'VK_KHR_external_semaphore_capabilities', > - 'VK_KHR_external_semaphore', > - 'VK_KHR_external_semaphore_fd', > - 'VK_KHR_bind_memory2', > - 'VK_KHR_maintenance2', > -] > +from radv_extensions import * > > # We generate a static hash table for entry point lookup > # (vkGetProcAddress). We use a linear congruential generator for our hash > # function and a power-of-two size table. The prime numbers are determined > # experimentally. > > -TEMPLATE_H = Template(textwrap.dedent("""\ > - /* This file generated from ${filename}, don't edit directly. */ > - > - struct radv_dispatch_table { > - union { > - void *entrypoints[${len(entrypoints)}]; > - struct { > - % for _, name, _, _, _, guard in entrypoints: > - % if guard is not None: > - #ifdef ${guard} > - PFN_vk${name} ${name}; > - #else > - void *${name}; > - # endif > - % else: > - PFN_vk${name} ${name}; > - % endif > - % endfor > - }; > - }; > - }; > - > - % for type_, name, args, num, h, guard in entrypoints: > - % if guard is not None: > - #ifdef ${guard} > - % endif > - ${type_} radv_${name}(${args}); > - % if guard is not None: > - #endif // ${guard} > - % endif > - % endfor > - """), output_encoding='utf-8') > - > -TEMPLATE_C = Template(textwrap.dedent(u"""\ > - /* > - * Copyright © 2015 Intel Corporation > - * > - * Permission is hereby granted, free of charge, to any person obtaining > a > - * copy of this software and associated documentation files (the > "Software"), > - * to deal in the Software without restriction, including without > limitation > - * the rights to use, copy, modify, merge, publish, distribute, > sublicense, > - * and/or sell copies of the Software, and to permit persons to whom the > - * Software is furnished to do so, subject to the following conditions: > - * > - * The above copyright notice and this permission notice (including the > next > - * paragraph) shall be included in all copies or substantial portions of > the > - * Software. > - * > - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > EXPRESS OR > - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > MERCHANTABILITY, > - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT > SHALL > - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR > OTHER > - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, > ARISING > - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER > DEALINGS > - * IN THE SOFTWARE. > - */ > - > - /* This file generated from ${filename}, don't edit directly. */ > - > - #include "radv_private.h" > - > - struct radv_entrypoint { > - uint32_t name; > - uint32_t hash; > - }; > - > - /* We use a big string constant to avoid lots of reloctions from the > entry > - * point table to lots of little strings. The entries in the entry point > table > - * store the index into this big string. > - */ > - > - static const char strings[] = > - % for _, name, _, _, _, _ in entrypoints: > - "vk${name}\\0" > - % endfor > - ; > - > - static const struct radv_entrypoint entrypoints[] = { > - % for _, _, _, num, h, _ in entrypoints: > - { ${offsets[num]}, ${'{:0=#8x}'.format(h)} }, > - % endfor > - }; > - > - /* Weak aliases for all potential implementations. These will resolve to > - * NULL if they're not defined, which lets the resolve_entrypoint() > function > - * either pick the correct entry point. > - */ > - > - % for layer in ['radv']: > - % for type_, name, args, _, _, guard in entrypoints: > - % if guard is not None: > - #ifdef ${guard} > - % endif > - ${type_} ${layer}_${name}(${args}) __attribute__ ((weak)); > - % if guard is not None: > - #endif // ${guard} > - % endif > - % endfor > +TEMPLATE_H = Template("""\ > +/* This file generated from ${filename}, don't edit directly. */ > > - const struct radv_dispatch_table ${layer}_layer = { > - % for _, name, args, _, _, guard in entrypoints: > - % if guard is not None: > - #ifdef ${guard} > - % endif > - .${name} = ${layer}_${name}, > +struct radv_dispatch_table { > + union { > + void *entrypoints[${len(entrypoints)}]; > + struct { > + % for _, name, _, _, _, guard in entrypoints: > % if guard is not None: > - #endif // ${guard} > - % endif > - % endfor > - }; > - % endfor > - > - static void * __attribute__ ((noinline)) > - radv_resolve_entrypoint(uint32_t index) > - { > - return radv_layer.entrypoints[index]; > - } > - > - /* Hash table stats: > - * size ${hash_size} entries > - * collisions entries: > - % for i in xrange(10): > - * ${i}${'+' if i == 9 else ''} ${collisions[i]} > - % endfor > - */ > - > - #define none ${'{:#x}'.format(none)} > - static const uint16_t map[] = { > - % for i in xrange(0, hash_size, 8): > - % for j in xrange(i, i + 8): > - ## This is 6 because the 0x is counted in the length > - % if mapping[j] & 0xffff == 0xffff: > - none, > +#ifdef ${guard} > + PFN_vk${name} ${name}; > +#else > + void *${name}; > +# endif > % else: > - ${'{:0=#6x}'.format(mapping[j] & 0xffff)}, > + PFN_vk${name} ${name}; > % endif > % endfor > - % endfor > - }; > - > - void * > - radv_lookup_entrypoint(const char *name) > - { > - static const uint32_t prime_factor = ${prime_factor}; > - static const uint32_t prime_step = ${prime_step}; > - const struct radv_entrypoint *e; > - uint32_t hash, h, i; > - const char *p; > - > - hash = 0; > - for (p = name; *p; p++) > - hash = hash * prime_factor + *p; > - > - h = hash; > - do { > - i = map[h & ${hash_mask}]; > - if (i == none) > - return NULL; > - e = &entrypoints[i]; > - h += prime_step; > - } while (e->hash != hash); > - > - if (strcmp(name, strings + e->name) != 0) > - return NULL; > - > - return radv_resolve_entrypoint(i); > - }"""), output_encoding='utf-8') > + }; > + }; > +}; > + > +% for type_, name, args, num, h, guard in entrypoints: > + % if guard is not None: > +#ifdef ${guard} > + % endif > + ${type_} radv_${name}(${args}); > + % if guard is not None: > +#endif // ${guard} > + % endif > +% endfor > +""", output_encoding='utf-8') > + > +TEMPLATE_C = Template(u"""\ > +/* > + * Copyright © 2015 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER > DEALINGS > + * IN THE SOFTWARE. > + */ > + > +/* This file generated from ${filename}, don't edit directly. */ > + > +#include "radv_private.h" > + > +struct radv_entrypoint { > + uint32_t name; > + uint32_t hash; > +}; > + > +/* We use a big string constant to avoid lots of reloctions from the entry > + * point table to lots of little strings. The entries in the entry point > table > + * store the index into this big string. > + */ > + > +static const char strings[] = > +% for _, name, _, _, _, _ in entrypoints: > + "vk${name}\\0" > +% endfor > +; > + > +static const struct radv_entrypoint entrypoints[] = { > +% for _, name, _, num, h, _ in entrypoints: > + [${num}] = { ${offsets[num]}, ${'{:0=#8x}'.format(h)} }, /* vk${name} */ > +% endfor > +}; > + > +/* Weak aliases for all potential implementations. These will resolve to > + * NULL if they're not defined, which lets the resolve_entrypoint() function > + * either pick the correct entry point. > + */ > + > +% for layer in ['radv']: > + % for type_, name, args, _, _, guard in entrypoints: > + % if guard is not None: > +#ifdef ${guard} > + % endif > + ${type_} ${layer}_${name}(${args}) __attribute__ ((weak)); > + % if guard is not None: > +#endif // ${guard} > + % endif > + % endfor > + > + const struct radv_dispatch_table ${layer}_layer = { > + % for _, name, args, _, _, guard in entrypoints: > + % if guard is not None: > +#ifdef ${guard} > + % endif > + .${name} = ${layer}_${name}, > + % if guard is not None: > +#endif // ${guard} > + % endif > + % endfor > + }; > +% endfor > + > +static void * __attribute__ ((noinline)) > +radv_resolve_entrypoint(uint32_t index) > +{ > + return radv_layer.entrypoints[index]; > +} > + > +/* Hash table stats: > + * size ${hash_size} entries > + * collisions entries: > +% for i in xrange(10): > + * ${i}${'+' if i == 9 else ''} ${collisions[i]} > +% endfor > + */ > + > +#define none ${'{:#x}'.format(none)} > +static const uint16_t map[] = { > +% for i in xrange(0, hash_size, 8): > + % for j in xrange(i, i + 8): > + ## This is 6 because the 0x is counted in the length > + % if mapping[j] & 0xffff == 0xffff: > + none, > + % else: > + ${'{:0=#6x}'.format(mapping[j] & 0xffff)}, > + % endif > + % endfor > +% endfor > +}; > + > +void * > +radv_lookup_entrypoint(const char *name) > +{ > + static const uint32_t prime_factor = ${prime_factor}; > + static const uint32_t prime_step = ${prime_step}; > + const struct radv_entrypoint *e; > + uint32_t hash, h, i; > + const char *p; > + > + hash = 0; > + for (p = name; *p; p++) > + hash = hash * prime_factor + *p; > + > + h = hash; > + do { > + i = map[h & ${hash_mask}]; > + if (i == none) > + return NULL; > + e = &entrypoints[i]; > + h += prime_step; > + } while (e->hash != hash); > + > + if (strcmp(name, strings + e->name) != 0) > + return NULL; > + > + return radv_resolve_entrypoint(i); > +}""", output_encoding='utf-8') > > NONE = 0xffff > HASH_SIZE = 256 > @@ -249,28 +219,29 @@ def cal_hash(name): > lambda h, c: (h * PRIME_FACTOR + ord(c)) & U32_MASK, name, 0) > > > -def get_entrypoints(doc, entrypoints_to_defines): > +def get_entrypoints(doc, entrypoints_to_defines, start_index): > """Extract the entry points from the registry.""" > entrypoints = [] > > enabled_commands = set() > for feature in doc.findall('./feature'): > assert feature.attrib['api'] == 'vulkan' > - if float(feature.attrib['number']) > MAX_API_VERSION: > + if VkVersion(feature.attrib['number']) > MAX_API_VERSION: > continue > > for command in feature.findall('./require/command'): > enabled_commands.add(command.attrib['name']) > > + supported = set(ext.name for ext in EXTENSIONS) > for extension in doc.findall('.extensions/extension'): > - if extension.attrib['name'] not in SUPPORTED_EXTENSIONS: > + if extension.attrib['name'] not in supported: > continue > > assert extension.attrib['supported'] == 'vulkan' > for command in extension.findall('./require/command'): > enabled_commands.add(command.attrib['name']) > > - index = 0 > + index = start_index > for command in doc.findall('./commands/command'): > type = command.find('./proto/type').text > fullname = command.find('./proto/name').text > @@ -339,12 +310,22 @@ def main(): > parser = argparse.ArgumentParser() > parser.add_argument('--outdir', help='Where to write the files.', > required=True) > - parser.add_argument('--xml', help='Vulkan API XML file.', required=True) > + parser.add_argument('--xml', > + help='Vulkan API XML file.', > + required=True, > + action='append', > + dest='xml_files') > args = parser.parse_args() > > - doc = et.parse(args.xml) > - entrypoints = get_entrypoints(doc, get_entrypoints_defines(doc)) > + entrypoints = [] > + > + for filename in args.xml_files: > + doc = et.parse(filename) > + entrypoints += get_entrypoints(doc, get_entrypoints_defines(doc), > + start_index=len(entrypoints)) > > + # For outputting entrypoints.h we generate a radv_EntryPoint() prototype > + # per entry point. > with open(os.path.join(args.outdir, 'radv_entrypoints.h'), 'wb') as f: > f.write(TEMPLATE_H.render(entrypoints=entrypoints, > filename=os.path.basename(__file__))) > diff --git a/src/amd/vulkan/radv_extensions.py > b/src/amd/vulkan/radv_extensions.py > new file mode 100644 > index 0000000..0c916c3 > --- /dev/null > +++ b/src/amd/vulkan/radv_extensions.py > @@ -0,0 +1,278 @@ > +COPYRIGHT = """\ > +/* > + * Copyright 2017 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the > + * "Software"), to deal in the Software without restriction, including > + * without limitation the rights to use, copy, modify, merge, publish, > + * distribute, sub license, and/or sell copies of the Software, and to > + * permit persons to whom the Software is furnished to do so, subject to > + * the following conditions: > + * > + * The above copyright notice and this permission notice (including the > + * next paragraph) shall be included in all copies or substantial portions > + * of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS > + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. > + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR > + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, > + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE > + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. > + */ > +""" > + > +import argparse > +import copy > +import re > +import xml.etree.cElementTree as et > + > +from mako.template import Template > + > +MAX_API_VERSION = '1.0.57' > + > +class Extension: > + def __init__(self, name, ext_version, enable): > + self.name = name > + self.ext_version = int(ext_version) > + if enable is True: > + self.enable = 'true'; > + elif enable is False: > + self.enable = 'false'; > + else: > + self.enable = enable; > + > +# On Android, we disable all surface and swapchain extensions. Android's > Vulkan > +# loader implements VK_KHR_surface and VK_KHR_swapchain, and applications > +# cannot access the driver's implementation. Moreoever, if the driver exposes > +# the those extension strings, then tests > dEQP-VK.api.info.instance.extensions > +# and dEQP-VK.api.info.device fail due to the duplicated strings. > +EXTENSIONS = [ > + Extension('VK_KHR_bind_memory2', 1, True), > + Extension('VK_KHR_dedicated_allocation', 1, True), > + Extension('VK_KHR_descriptor_update_template', 1, True), > + Extension('VK_KHR_external_memory', 1, True), > + Extension('VK_KHR_external_memory_capabilities', 1, True), > + Extension('VK_KHR_external_memory_fd', 1, True), > + Extension('VK_KHR_external_semaphore', 1, > 'device->rad_info.has_syncobj'), > + Extension('VK_KHR_external_semaphore_capabilities', 1, True), > + Extension('VK_KHR_external_semaphore_fd', 1, > 'device->rad_info.has_syncobj'), > + Extension('VK_KHR_get_memory_requirements2', 1, True), > + Extension('VK_KHR_get_physical_device_properties2', 1, True), > + Extension('VK_KHR_image_format_list', 1, True), > + Extension('VK_KHR_incremental_present', 1, True), > + Extension('VK_KHR_maintenance1', 1, True), > + Extension('VK_KHR_maintenance2', 1, True), > + Extension('VK_KHR_push_descriptor', 1, True), > + Extension('VK_KHR_relaxed_block_layout', 1, True), > + Extension('VK_KHR_sampler_mirror_clamp_to_edge', 1, True), > + Extension('VK_KHR_shader_draw_parameters', 1, True), > + Extension('VK_KHR_storage_buffer_storage_class', 1, True), > + Extension('VK_KHR_surface', 25, > 'RADV_HAS_SURFACE'), > + Extension('VK_KHR_swapchain', 68, > 'RADV_HAS_SURFACE'), > + Extension('VK_KHR_variable_pointers', 1, True), > + Extension('VK_KHR_wayland_surface', 6, > 'VK_USE_PLATFORM_WAYLAND_KHR'), > + Extension('VK_KHR_xcb_surface', 6, > 'VK_USE_PLATFORM_XCB_KHR'), > + Extension('VK_KHR_xlib_surface', 6, > 'VK_USE_PLATFORM_XLIB_KHR'), > + Extension('VK_KHX_multiview', 1, > 'device->rad_info.has_syncobj'),
Woops, seems I put this in the wrong bucket. Should be enabled unconditionally. Otherwise Acked-by: Bas Nieuwenhuizen <b...@basnieuwenhuizen.nl> > + Extension('VK_EXT_debug_report', 8, True), > + Extension('VK_AMD_draw_indirect_count', 1, True), > + Extension('VK_AMD_rasterization_order', 1, > 'device->rad_info.chip_class >= VI && device->rad_info.max_se >= 2'), > +] > + > +class VkVersion: > + def __init__(self, string): > + split = string.split('.') > + self.major = int(split[0]) > + self.minor = int(split[1]) > + if len(split) > 2: > + assert len(split) == 3 > + self.patch = int(split[2]) > + else: > + self.patch = None > + > + # Sanity check. The range bits are required by the definition of the > + # VK_MAKE_VERSION macro > + assert self.major < 1024 and self.minor < 1024 > + assert self.patch is None or self.patch < 4096 > + assert(str(self) == string) > + > + def __str__(self): > + ver_list = [str(self.major), str(self.minor)] > + if self.patch is not None: > + ver_list.append(str(self.patch)) > + return '.'.join(ver_list) > + > + def c_vk_version(self): > + ver_list = [str(self.major), str(self.minor), str(self.patch)] > + return 'VK_MAKE_VERSION(' + ', '.join(ver_list) + ')' > + > + def __int_ver(self): > + # This is just an expansion of VK_VERSION > + patch = self.patch if self.patch is not None else 0 > + return (self.major << 22) | (self.minor << 12) | patch > + > + def __cmp__(self, other): > + # If only one of them has a patch version, "ignore" it by making > + # other's patch version match self. > + if (self.patch is None) != (other.patch is None): > + other = copy.copy(other) > + other.patch = self.patch > + > + return self.__int_ver().__cmp__(other.__int_ver()) > + > +MAX_API_VERSION = VkVersion(MAX_API_VERSION) > + > +def _init_exts_from_xml(xml): > + """ Walk the Vulkan XML and fill out extra extension information. """ > + > + xml = et.parse(xml) > + > + ext_name_map = {} > + for ext in EXTENSIONS: > + ext_name_map[ext.name] = ext > + > + for ext_elem in xml.findall('.extensions/extension'): > + ext_name = ext_elem.attrib['name'] > + if ext_name not in ext_name_map: > + continue > + > + # Workaround for VK_ANDROID_native_buffer. Its <extension> element in > + # vk.xml lists it as supported="disabled" and provides only a stub > + # definition. Its <extension> element in Mesa's custom > + # vk_android_native_buffer.xml, though, lists it as > + # supported='android-vendor' and fully defines the extension. We want > + # to skip the <extension> element in vk.xml. > + if ext_elem.attrib['supported'] == 'disabled': > + assert ext_name == 'VK_ANDROID_native_buffer' > + continue > + > + ext = ext_name_map[ext_name] > + ext.type = ext_elem.attrib['type'] > + > +_TEMPLATE = Template(COPYRIGHT + """ > +#include "radv_private.h" > + > +#include "vk_util.h" > + > +/* Convert the VK_USE_PLATFORM_* defines to booleans */ > +%for platform in ['ANDROID', 'WAYLAND', 'XCB', 'XLIB']: > +#ifdef VK_USE_PLATFORM_${platform}_KHR > +# undef VK_USE_PLATFORM_${platform}_KHR > +# define VK_USE_PLATFORM_${platform}_KHR true > +#else > +# define VK_USE_PLATFORM_${platform}_KHR false > +#endif > +%endfor > + > +/* And ANDROID too */ > +#ifdef ANDROID > +# undef ANDROID > +# define ANDROID true > +#else > +# define ANDROID false > +#endif > + > +#define RADV_HAS_SURFACE (VK_USE_PLATFORM_WAYLAND_KHR || \\ > + VK_USE_PLATFORM_XCB_KHR || \\ > + VK_USE_PLATFORM_XLIB_KHR) > + > +bool > +radv_instance_extension_supported(const char *name) > +{ > +%for ext in instance_extensions: > + if (strcmp(name, "${ext.name}") == 0) > + return ${ext.enable}; > +%endfor > + return false; > +} > + > +VkResult radv_EnumerateInstanceExtensionProperties( > + const char* pLayerName, > + uint32_t* pPropertyCount, > + VkExtensionProperties* pProperties) > +{ > + VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount); > + > +%for ext in instance_extensions: > + if (${ext.enable}) { > + vk_outarray_append(&out, prop) { > + *prop = (VkExtensionProperties) { > + .extensionName = "${ext.name}", > + .specVersion = ${ext.ext_version}, > + }; > + } > + } > +%endfor > + > + return vk_outarray_status(&out); > +} > + > +uint32_t > +radv_physical_device_api_version(struct radv_physical_device *dev) > +{ > + return ${MAX_API_VERSION.c_vk_version()}; > +} > + > +bool > +radv_physical_device_extension_supported(struct radv_physical_device *device, > + const char *name) > +{ > +%for ext in device_extensions: > + if (strcmp(name, "${ext.name}") == 0) > + return ${ext.enable}; > +%endfor > + return false; > +} > + > +VkResult radv_EnumerateDeviceExtensionProperties( > + VkPhysicalDevice physicalDevice, > + const char* pLayerName, > + uint32_t* pPropertyCount, > + VkExtensionProperties* pProperties) > +{ > + RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); > + VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount); > + (void)device; > + > +%for ext in device_extensions: > + if (${ext.enable}) { > + vk_outarray_append(&out, prop) { > + *prop = (VkExtensionProperties) { > + .extensionName = "${ext.name}", > + .specVersion = ${ext.ext_version}, > + }; > + } > + } > +%endfor > + > + return vk_outarray_status(&out); > +} > +""") > + > +if __name__ == '__main__': > + parser = argparse.ArgumentParser() > + parser.add_argument('--out', help='Output C file.', required=True) > + parser.add_argument('--xml', > + help='Vulkan API XML file.', > + required=True, > + action='append', > + dest='xml_files') > + args = parser.parse_args() > + > + for filename in args.xml_files: > + _init_exts_from_xml(filename) > + > + for ext in EXTENSIONS: > + assert ext.type == 'instance' or ext.type == 'device' > + > + template_env = { > + 'MAX_API_VERSION': MAX_API_VERSION, > + 'instance_extensions': [e for e in EXTENSIONS if e.type == > 'instance'], > + 'device_extensions': [e for e in EXTENSIONS if e.type == 'device'], > + } > + > + with open(args.out, 'w') as f: > + f.write(_TEMPLATE.render(**template_env)) > diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h > index 70c5c70..ad9ea5e 100644 > --- a/src/amd/vulkan/radv_private.h > +++ b/src/amd/vulkan/radv_private.h > @@ -253,11 +253,6 @@ void radv_loge_v(const char *format, va_list va); > > void *radv_lookup_entrypoint(const char *name); > > -struct radv_extensions { > - VkExtensionProperties *ext_array; > - uint32_t num_ext; > -}; > - > struct radv_physical_device { > VK_LOADER_DATA _loader_data; > > @@ -273,7 +268,6 @@ struct radv_physical_device { > > int local_fd; > struct wsi_device wsi_device; > - struct radv_extensions extensions; > > bool has_rbplus; /* if RB+ register exist */ > bool rbplus_allowed; /* if RB+ is allowed */ > @@ -301,6 +295,11 @@ struct radv_instance { > VkResult radv_init_wsi(struct radv_physical_device *physical_device); > void radv_finish_wsi(struct radv_physical_device *physical_device); > > +bool radv_instance_extension_supported(const char *name); > +uint32_t radv_physical_device_api_version(struct radv_physical_device *dev); > +bool radv_physical_device_extension_supported(struct radv_physical_device > *dev, > + const char *name); > + > struct cache_entry; > > struct radv_pipeline_cache { > -- > 2.9.5 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev