[Mesa-dev] [PATCH] radv: port to using updated anv entrypoint/extension generator.

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Tue Oct 17 06:42:51 UTC 2017


On Tue, Oct 17, 2017 at 7:36 AM, Dave Airlie <airlied at gmail.com> wrote:
> From: Dave Airlie <airlied at 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 <airlied at 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 <bas at 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 at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list