From 17201a2eb0b1b8538713691e6a46fb56d76cafe8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 17 Oct 2017 15:18:36 +1000 Subject: [PATCH] radv: port to using updated anv entrypoint/extension generator. This ports radv to using the anv entrypoint/extension generator code. No differences on enabled extensions list in vulkaninfo. Acked-by: Bas Nieuwenhuizen Signed-off-by: Dave Airlie --- 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 2a42d7fda8e..7c02e42bb0b 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 19ec3f47f74..7364e54f61c 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 fbdb7971201..c9d172c3b1b 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 cedb9a4acfc..b9cd6768c68 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, - }, - { - .extensionName = VK_KHX_MULTIVIEW_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, - }, -}; - -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 713a98f700f..f8f99d00b79 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 00000000000..cde91085b55 --- /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, True), + 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 element in + # vk.xml lists it as supported="disabled" and provides only a stub + # definition. Its 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 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 70c5c70aaa5..ad9ea5ed673 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.30.2