[Mesa-dev] [PATCH 4/4] radv: Integrate with common generators.
Bas Nieuwenhuizen
bas at basnieuwenhuizen.nl
Tue Aug 7 23:14:34 UTC 2018
Replace some functions to use the anv idioms. However, I did not
introduce dispatch tables in the instance/device since that seemed
like overkill.
---
src/amd/vulkan/Android.mk | 16 +-
src/amd/vulkan/Makefile.am | 29 +-
src/amd/vulkan/meson.build | 91 +++--
src/amd/vulkan/radv_device.c | 56 ++-
src/amd/vulkan/radv_entrypoints_gen.py | 462 +------------------------
src/amd/vulkan/radv_extensions.py | 236 +------------
src/amd/vulkan/radv_extensions_gen.py | 44 +++
src/amd/vulkan/radv_icd.py | 1 +
src/amd/vulkan/radv_private.h | 9 +-
src/amd/vulkan/radv_wsi.c | 6 +-
10 files changed, 211 insertions(+), 739 deletions(-)
create mode 100644 src/amd/vulkan/radv_extensions_gen.py
diff --git a/src/amd/vulkan/Android.mk b/src/amd/vulkan/Android.mk
index cee3744f40b..a6aae160e0b 100644
--- a/src/amd/vulkan/Android.mk
+++ b/src/amd/vulkan/Android.mk
@@ -83,24 +83,34 @@ LOCAL_GENERATED_SOURCES += $(intermediates)/vk_format_table.c
RADV_ENTRYPOINTS_SCRIPT := $(MESA_TOP)/src/amd/vulkan/radv_entrypoints_gen.py
RADV_EXTENSIONS_SCRIPT := $(MESA_TOP)/src/amd/vulkan/radv_extensions.py
+RADV_EXTENSIONS_GEN_SCRIPT := $(MESA_TOP)/src/amd/vulkan/radv_extensions_gen.py
VK_FORMAT_TABLE_SCRIPT := $(MESA_TOP)/src/amd/vulkan/vk_format_table.py
VK_FORMAT_PARSE_SCRIPT := $(MESA_TOP)/src/amd/vulkan/vk_format_parse.py
+vulkan_api_generators_py := \
+ $(MESA_TOP)/src/vulkan/util/vk_entrypoints_gen.py \
+ $(MESA_TOP)/src/vulkan/util/vk_extensions_gen.py \
+ $(MESA_TOP)/src/vulkan/util/vk_extensions.py
+
vulkan_api_xml = $(MESA_TOP)/src/vulkan/registry/vk.xml
vk_format_layout_csv = $(MESA_TOP)/src/amd/vulkan/vk_format_layout.csv
$(intermediates)/radv_entrypoints.c: $(RADV_ENTRYPOINTS_SCRIPT) \
$(RADV_EXTENSIONS_SCRIPT) \
- $(vulkan_api_xml)
+ $(vulkan_api_xml) \
+ $(vulkan_api_generators_py)
@mkdir -p $(dir $@)
+ PYTHONPATH=$(MESA_TOP)/src/vulkan/util \
$(MESA_PYTHON2) $(RADV_ENTRYPOINTS_SCRIPT) \
--xml $(vulkan_api_xml) \
--outdir $(dir $@)
$(intermediates)/radv_entrypoints.h: $(intermediates)/radv_entrypoints.c
-$(intermediates)/radv_extensions.c: $(RADV_EXTENSIONS_SCRIPT) $(vulkan_api_xml)
- @mkdir -p $(dir $@)
+$(intermediates)/radv_extensions.c: $(RADV_EXTENSIONS_GEN_SCRIPT) $(RADV_EXTENSIONS_SCRIPT) \
+ $(vulkan_api_xml) $(vulkan_api_generators_py)
+ @mkdir -p $(dir $@)\
+ PYTHONPATH=$(MESA_TOP)/src/vulkan/util \
$(MESA_PYTHON2) $(RADV_EXTENSIONS_SCRIPT) \
--xml $(vulkan_api_xml) \
--out-c $@ \
diff --git a/src/amd/vulkan/Makefile.am b/src/amd/vulkan/Makefile.am
index e7ccc58a28e..88e5b1de2fd 100644
--- a/src/amd/vulkan/Makefile.am
+++ b/src/amd/vulkan/Makefile.am
@@ -21,6 +21,11 @@
include Makefile.sources
+vulkan_api_generators_py = \
+ $(top_srcdir)/src/vulkan/util/vk_entrypoints_gen.py \
+ $(top_srcdir)/src/vulkan/util/vk_extensions_gen.py \
+ $(top_srcdir)/src/vulkan/util/vk_extensions.py
+
noinst_HEADERS = \
$(top_srcdir)/include/vulkan/vk_platform.h \
$(top_srcdir)/include/vulkan/vulkan_core.h \
@@ -138,17 +143,20 @@ libvulkan_radeon_la_SOURCES = $(VULKAN_GEM_FILES)
vulkan_api_xml = $(top_srcdir)/src/vulkan/registry/vk.xml
-radv_entrypoints.c: radv_entrypoints_gen.py radv_extensions.py $(vulkan_api_xml)
+radv_entrypoints.c: radv_entrypoints_gen.py radv_extensions.py $(vulkan_api_xml) \
+ $(vulkan_api_generators_py)
$(MKDIR_GEN)
- $(AM_V_GEN)$(PYTHON2) $(srcdir)/radv_entrypoints_gen.py \
+ $(AM_V_GEN) PYTHONPATH=$(top_srcdir)/src/vulkan/util \
+ $(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)
+radv_extensions.c: radv_extensions_gen.py radv_extensions.py \
+ $(vulkan_api_xml) $(vulkan_api_generators_py)
$(MKDIR_GEN)
- $(AM_V_GEN)$(PYTHON2) $(srcdir)/radv_extensions.py \
+ $(AM_V_GEN) PYTHONPATH=$(top_srcdir)/src/vulkan/util \
+ $(PYTHON2) $(srcdir)/radv_extensions_gen.py \
--xml $(vulkan_api_xml) \
--out-c radv_extensions.c \
--out-h radv_extensions.h
@@ -164,6 +172,7 @@ CLEANFILES = $(BUILT_SOURCES) dev_icd.json radeon_icd. at host_cpu@.json
EXTRA_DIST = \
$(top_srcdir)/include/vulkan/vk_icd.h \
radv_entrypoints_gen.py \
+ radv_extensions_gen.py \
radv_extensions.py \
radv_icd.py \
vk_format_layout.csv \
@@ -189,12 +198,14 @@ icdconf_DATA = radeon_icd. at host_cpu@.json
# The following is used for development purposes, by setting VK_ICD_FILENAMES.
noinst_DATA = dev_icd.json
-dev_icd.json : radv_extensions.py radv_icd.py
- $(AM_V_GEN)$(PYTHON2) $(srcdir)/radv_icd.py \
+dev_icd.json : radv_extensions.py radv_icd.py $(vulkan_api_generators_py)
+ $(AM_V_GEN) PYTHONPATH=$(top_srcdir)/src/vulkan/util \
+ $(PYTHON2) $(srcdir)/radv_icd.py \
--lib-path="${abs_top_builddir}/${LIB_DIR}" --out $@
-radeon_icd. at host_cpu@.json : radv_extensions.py radv_icd.py
- $(AM_V_GEN)$(PYTHON2) $(srcdir)/radv_icd.py \
+radeon_icd. at host_cpu@.json : radv_extensions.py radv_icd.py $(vulkan_api_generators_py)
+ $(AM_V_GEN) PYTHONPATH=$(top_srcdir)/src/vulkan/util \
+ $(PYTHON2) $(srcdir)/radv_icd.py \
--lib-path="${libdir}" --out $@
include $(top_srcdir)/install-lib-links.mk
diff --git a/src/amd/vulkan/meson.build b/src/amd/vulkan/meson.build
index 9f2842182e7..da5055b0693 100644
--- a/src/amd/vulkan/meson.build
+++ b/src/amd/vulkan/meson.build
@@ -18,25 +18,72 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
+radv_extensions_py = files('radv_extensions.py')
+
radv_entrypoints = custom_target(
'radv_entrypoints.[ch]',
input : ['radv_entrypoints_gen.py', vk_api_xml],
output : ['radv_entrypoints.h', 'radv_entrypoints.c'],
command : [
- prog_python2, '@INPUT0@', '--xml', '@INPUT1@', '--outdir',
- meson.current_build_dir()
+ 'env', 'PYTHONPATH=@0@'.format(join_paths(meson.source_root(), 'src/vulkan/util/')),
+ prog_python2, '@INPUT0@', '--xml', '@INPUT1@',
+ '--outdir', meson.current_build_dir(),
],
- depend_files : files('radv_extensions.py'),
+ depend_files : [radv_extensions_py, vk_api_generators_py],
)
radv_extensions_c = custom_target(
'radv_extensions.c',
- input : ['radv_extensions.py', vk_api_xml],
- output : ['radv_extensions.c', 'radv_extensions.h'],
+ input : ['radv_extensions_gen.py', vk_api_xml],
+ output : 'radv_extensions.c',
+ command : [
+ 'env', 'PYTHONPATH=@0@'.format(join_paths(meson.source_root(), 'src/vulkan/util/')),
+ prog_python2, '@INPUT0@', '--xml', '@INPUT1@',
+ '--out-c', '@OUTPUT@',
+ ],
+ depend_files : [radv_extensions_py, vk_api_generators_py],
+)
+
+radv_extensions_h = custom_target(
+ 'radv_extensions.h',
+ input : ['radv_extensions_gen.py', vk_api_xml],
+ output : 'radv_extensions.h',
+ command : [
+ 'env', 'PYTHONPATH=@0@'.format(join_paths(meson.source_root(), 'src/vulkan/util/')),
+ prog_python2, '@INPUT0@', '--xml', '@INPUT1@',
+ '--out-h', '@OUTPUT@',
+ ],
+ depend_files : [radv_extensions_py, vk_api_generators_py],
+)
+
+radeon_icd = custom_target(
+ 'radeon_icd',
+ input : 'radv_icd.py',
+ output : 'radeon_icd. at 0@.json'.format(host_machine.cpu()),
command : [
- prog_python2, '@INPUT0@', '--xml', '@INPUT1@', '--out-c', '@OUTPUT0@',
- '--out-h', '@OUTPUT1@'
+ 'env', 'PYTHONPATH=@0@'.format(join_paths(meson.source_root(), 'src/vulkan/util/')),
+ prog_python2, '@INPUT@',
+ '--lib-path', join_paths(get_option('prefix'), get_option('libdir')),
+ '--out', '@OUTPUT@',
],
+ depend_files : [radv_extensions_py, vk_api_generators_py],
+ build_by_default : true,
+ install_dir : with_vulkan_icd_dir,
+ install : true,
+)
+
+radv_dev_icd = custom_target(
+ 'radv_dev_icd',
+ input : 'radv_icd.py',
+ output : 'dev_icd. at 0@.json'.format(host_machine.cpu()),
+ command : [
+ 'env', 'PYTHONPATH=@0@'.format(join_paths(meson.source_root(), 'src/vulkan/util/')),
+ prog_python2, '@INPUT@', '--lib-path', meson.current_build_dir(),
+ '--out', '@OUTPUT@'
+ ],
+ depend_files : [radv_extensions_py, vk_api_generators_py],
+ build_by_default : true,
+ install : false,
)
vk_format_table_c = custom_target(
@@ -129,7 +176,7 @@ endif
libvulkan_radeon = shared_library(
'vulkan_radeon',
- [libradv_files, radv_entrypoints, radv_extensions_c, vk_format_table_c],
+ [libradv_files, radv_entrypoints, radv_extensions_c, radv_extensions_h, vk_format_table_c],
include_directories : [
inc_common, inc_amd, inc_amd_common, inc_compiler, inc_vulkan_util,
inc_vulkan_wsi,
@@ -147,31 +194,3 @@ libvulkan_radeon = shared_library(
link_args : [ld_args_bsymbolic, ld_args_gc_sections],
install : true,
)
-
-radeon_icd = custom_target(
- 'radeon_icd',
- input : 'radv_icd.py',
- output : 'radeon_icd. at 0@.json'.format(host_machine.cpu()),
- command : [
- prog_python2, '@INPUT@',
- '--lib-path', join_paths(get_option('prefix'), get_option('libdir')),
- '--out', '@OUTPUT@',
- ],
- depend_files : files('radv_extensions.py'),
- build_by_default : true,
- install_dir : with_vulkan_icd_dir,
- install : true,
-)
-
-radv_dev_icd = custom_target(
- 'radv_dev_icd',
- input : 'radv_icd.py',
- output : 'dev_icd.json',
- command : [
- prog_python2, '@INPUT@', '--lib-path', meson.current_build_dir(),
- '--out', '@OUTPUT@'
- ],
- depend_files : files('radv_extensions.py'),
- build_by_default : true,
- install : false,
-)
diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index 33f24b9d302..3c1de690ade 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -354,7 +354,7 @@ radv_physical_device_init(struct radv_physical_device *device,
(device->instance->perftest_flags & RADV_PERFTEST_DCC_MSAA);
radv_physical_device_init_mem_types(device);
- radv_fill_device_extension_table(device, &device->supported_extensions);
+ radv_physical_device_get_supported_extensions(device, &device->supported_extensions);
result = radv_init_wsi(device);
if (result != VK_SUCCESS) {
@@ -540,7 +540,7 @@ VkResult radv_CreateInstance(
const char *ext_name = pCreateInfo->ppEnabledExtensionNames[i];
int index = radv_get_instance_extension_index(ext_name);
- if (index < 0 || !radv_supported_instance_extensions.extensions[index]) {
+ if (index < 0 || !radv_instance_extensions_supported.extensions[index]) {
vk_free2(&default_alloc, pAllocator, instance);
return vk_error(instance, VK_ERROR_EXTENSION_NOT_PRESENT);
}
@@ -2677,7 +2677,7 @@ VkResult radv_EnumerateInstanceExtensionProperties(
VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
for (int i = 0; i < RADV_INSTANCE_EXTENSION_COUNT; i++) {
- if (radv_supported_instance_extensions.extensions[i]) {
+ if (radv_instance_extensions_supported.extensions[i]) {
vk_outarray_append(&out, prop) {
*prop = radv_instance_extensions[i];
}
@@ -2713,10 +2713,35 @@ PFN_vkVoidFunction radv_GetInstanceProcAddr(
{
RADV_FROM_HANDLE(radv_instance, instance, _instance);
- return radv_lookup_entrypoint_checked(pName,
- instance ? instance->apiVersion : 0,
- instance ? &instance->enabled_extensions : NULL,
- NULL);
+ /* The Vulkan 1.0 spec for vkGetInstanceProcAddr has a table of exactly
+ * when we have to return valid function pointers, NULL, or it's left
+ * undefined. See the table for exact details.
+ */
+ if (pName == NULL)
+ return NULL;
+
+#define LOOKUP_RADV_ENTRYPOINT(entrypoint) \
+ if (strcmp(pName, "vk" #entrypoint) == 0) \
+ return (PFN_vkVoidFunction)radv_##entrypoint
+
+ LOOKUP_RADV_ENTRYPOINT(EnumerateInstanceExtensionProperties);
+ LOOKUP_RADV_ENTRYPOINT(EnumerateInstanceLayerProperties);
+ LOOKUP_RADV_ENTRYPOINT(EnumerateInstanceVersion);
+ LOOKUP_RADV_ENTRYPOINT(CreateInstance);
+
+#undef LOOKUP_RADV_ENTRYPOINT
+
+ if (instance == NULL)
+ return NULL;
+
+ int idx = radv_get_entrypoint_index(pName);
+ if (idx < 0)
+ return NULL;
+
+ if (!radv_entrypoint_is_enabled(idx, instance->apiVersion, &instance->enabled_extensions, NULL))
+ return NULL;
+
+ return radv_dispatch_table.entrypoints[idx];
}
/* The loader wants us to expose a second GetInstanceProcAddr function
@@ -2741,10 +2766,19 @@ PFN_vkVoidFunction radv_GetDeviceProcAddr(
{
RADV_FROM_HANDLE(radv_device, device, _device);
- return radv_lookup_entrypoint_checked(pName,
- device->instance->apiVersion,
- &device->instance->enabled_extensions,
- &device->enabled_extensions);
+ if (!device || !pName)
+ return NULL;
+
+ int idx = radv_get_entrypoint_index(pName);
+ if (idx < 0)
+ return NULL;
+
+ if (!radv_entrypoint_is_enabled(idx, device->instance->apiVersion,
+ &device->instance->enabled_extensions,
+ &device->enabled_extensions))
+ return NULL;
+
+ return radv_dispatch_table.entrypoints[idx];
}
bool radv_get_memory_fd(struct radv_device *device,
diff --git a/src/amd/vulkan/radv_entrypoints_gen.py b/src/amd/vulkan/radv_entrypoints_gen.py
index 377b544c2aa..46a12c50e75 100644
--- a/src/amd/vulkan/radv_entrypoints_gen.py
+++ b/src/amd/vulkan/radv_entrypoints_gen.py
@@ -23,454 +23,20 @@
#
import argparse
-import functools
-import math
import os
-import xml.etree.cElementTree as et
-from collections import OrderedDict, namedtuple
-from mako.template import Template
-
-from radv_extensions import *
+from radv_extensions import MAX_API_VERSION, EXTENSIONS
+import vk_entrypoints_gen
# 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.
-# We currently don't use layers in radv, but keeping the ability for anv
-# anyways, so we can use it for device groups.
LAYERS = [
- 'radv'
+ 'radv',
]
-TEMPLATE_H = Template("""\
-/* This file generated from ${filename}, don't edit directly. */
-
-struct radv_dispatch_table {
- union {
- void *entrypoints[${len(entrypoints)}];
- struct {
- % for e in entrypoints:
- % if e.guard is not None:
-#ifdef ${e.guard}
- PFN_${e.name} ${e.name};
-#else
- void *${e.name};
-# endif
- % else:
- PFN_${e.name} ${e.name};
- % endif
- % endfor
- };
- };
-};
-
-% for e in entrypoints:
- % if e.alias:
- <% continue %>
- % endif
- % if e.guard is not None:
-#ifdef ${e.guard}
- % endif
- % for layer in LAYERS:
- ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()});
- % endfor
- % if e.guard is not None:
-#endif // ${e.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 string_map_entry {
- uint32_t name;
- uint32_t hash;
- uint32_t num;
-};
-
-/* We use a big string constant to avoid lots of relocations 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 s in strmap.sorted_strings:
- "${s.string}\\0"
-% endfor
-;
-
-static const struct string_map_entry string_map_entries[] = {
-% for s in strmap.sorted_strings:
- { ${s.offset}, ${'{:0=#8x}'.format(s.hash)}, ${s.num} }, /* ${s.string} */
-% endfor
-};
-
-/* Hash table stats:
- * size ${len(strmap.sorted_strings)} entries
- * collisions entries:
-% for i in range(10):
- * ${i}${'+' if i == 9 else ' '} ${strmap.collisions[i]}
-% endfor
- */
-
-#define none 0xffff
-static const uint16_t string_map[${strmap.hash_size}] = {
-% for e in strmap.mapping:
- ${ '{:0=#6x}'.format(e) if e >= 0 else 'none' },
-% 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 LAYERS:
- % for e in entrypoints:
- % if e.alias:
- <% continue %>
- % endif
- % if e.guard is not None:
-#ifdef ${e.guard}
- % endif
- ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}) __attribute__ ((weak));
- % if e.guard is not None:
-#endif // ${e.guard}
- % endif
- % endfor
-
- const struct radv_dispatch_table ${layer}_layer = {
- % for e in entrypoints:
- % if e.guard is not None:
-#ifdef ${e.guard}
- % endif
- .${e.name} = ${e.prefixed_name(layer)},
- % if e.guard is not None:
-#endif // ${e.guard}
- % endif
- % endfor
- };
-% endfor
-
-static void * __attribute__ ((noinline))
-radv_resolve_entrypoint(uint32_t index)
-{
- return radv_layer.entrypoints[index];
-}
-
-/** Return true if the core version or extension in which the given entrypoint
- * is defined is enabled.
- *
- * If instance is NULL, we only allow the 3 commands explicitly allowed by the vk
- * spec.
- *
- * If device is NULL, all device extensions are considered enabled.
- */
-static bool
-radv_entrypoint_is_enabled(int index, uint32_t core_version,
- const struct radv_instance_extension_table *instance,
- const struct radv_device_extension_table *device)
-{
- switch (index) {
-% for e in entrypoints:
- case ${e.num}:
- % if not e.device_command:
- if (device) return false;
- % endif
- % if e.name == 'vkCreateInstance' or e.name == 'vkEnumerateInstanceExtensionProperties' or e.name == 'vkEnumerateInstanceLayerProperties' or e.name == 'vkEnumerateInstanceVersion':
- return !device;
- % elif e.core_version:
- return instance && ${e.core_version.c_vk_version()} <= core_version;
- % elif e.extensions:
- % for ext in e.extensions:
- % if ext.type == 'instance':
- if (instance && instance->${ext.name[3:]}) return true;
- % else:
- if (instance && (!device || device->${ext.name[3:]})) return true;
- % endif
- %endfor
- return false;
- % else:
- return instance;
- % endif
-% endfor
- default:
- return false;
- }
-}
-
-static int
-radv_lookup_entrypoint(const char *name)
-{
- static const uint32_t prime_factor = ${strmap.prime_factor};
- static const uint32_t prime_step = ${strmap.prime_step};
- const struct string_map_entry *e;
- uint32_t hash, h;
- uint16_t i;
- const char *p;
-
- hash = 0;
- for (p = name; *p; p++)
- hash = hash * prime_factor + *p;
-
- h = hash;
- while (1) {
- i = string_map[h & ${strmap.hash_mask}];
- if (i == none)
- return -1;
- e = &string_map_entries[i];
- if (e->hash == hash && strcmp(name, strings + e->name) == 0)
- return e->num;
- h += prime_step;
- }
-
- return -1;
-}
-
-void *
-radv_lookup_entrypoint_unchecked(const char *name)
-{
- int index = radv_lookup_entrypoint(name);
- if (index < 0)
- return NULL;
- return radv_resolve_entrypoint(index);
-}
-
-void *
-radv_lookup_entrypoint_checked(const char *name,
- uint32_t core_version,
- const struct radv_instance_extension_table *instance,
- const struct radv_device_extension_table *device)
-{
- int index = radv_lookup_entrypoint(name);
- if (index < 0 || !radv_entrypoint_is_enabled(index, core_version, instance, device))
- return NULL;
- return radv_resolve_entrypoint(index);
-}""", output_encoding='utf-8')
-
-U32_MASK = 2**32 - 1
-
-PRIME_FACTOR = 5024183
-PRIME_STEP = 19
-
-def round_to_pow2(x):
- return 2**int(math.ceil(math.log(x, 2)))
-
-class StringIntMapEntry(object):
- def __init__(self, string, num):
- self.string = string
- self.num = num
-
- # Calculate the same hash value that we will calculate in C.
- h = 0
- for c in string:
- h = ((h * PRIME_FACTOR) + ord(c)) & U32_MASK
- self.hash = h
-
- self.offset = None
-
-class StringIntMap(object):
- def __init__(self):
- self.baked = False
- self.strings = dict()
-
- def add_string(self, string, num):
- assert not self.baked
- assert string not in self.strings
- assert num >= 0 and num < 2**31
- self.strings[string] = StringIntMapEntry(string, num)
-
- def bake(self):
- self.sorted_strings = \
- sorted(self.strings.values(), key=lambda x: x.string)
- offset = 0
- for entry in self.sorted_strings:
- entry.offset = offset
- offset += len(entry.string) + 1
-
- # Save off some values that we'll need in C
- self.hash_size = round_to_pow2(len(self.strings) * 1.25)
- self.hash_mask = self.hash_size - 1
- self.prime_factor = PRIME_FACTOR
- self.prime_step = PRIME_STEP
-
- self.mapping = [-1] * self.hash_size
- self.collisions = [0] * 10
- for idx, s in enumerate(self.sorted_strings):
- level = 0
- h = s.hash
- while self.mapping[h & self.hash_mask] >= 0:
- h = h + PRIME_STEP
- level = level + 1
- self.collisions[min(level, 9)] += 1
- self.mapping[h & self.hash_mask] = idx
-
-EntrypointParam = namedtuple('EntrypointParam', 'type name decl')
-
-class EntrypointBase(object):
- def __init__(self, name):
- self.name = name
- self.alias = None
- self.guard = None
- self.enabled = False
- self.num = None
- # Extensions which require this entrypoint
- self.core_version = None
- self.extensions = []
-
-class Entrypoint(EntrypointBase):
- def __init__(self, name, return_type, params, guard = None):
- super(Entrypoint, self).__init__(name)
- self.return_type = return_type
- self.params = params
- self.guard = guard
- self.device_command = len(params) > 0 and (params[0].type == 'VkDevice' or params[0].type == 'VkQueue' or params[0].type == 'VkCommandBuffer')
-
- def prefixed_name(self, prefix):
- assert self.name.startswith('vk')
- return prefix + '_' + self.name[2:]
-
- def decl_params(self):
- return ', '.join(p.decl for p in self.params)
-
- def call_params(self):
- return ', '.join(p.name for p in self.params)
-
-class EntrypointAlias(EntrypointBase):
- def __init__(self, name, entrypoint):
- super(EntrypointAlias, self).__init__(name)
- self.alias = entrypoint
- self.device_command = entrypoint.device_command
-
- def prefixed_name(self, prefix):
- return self.alias.prefixed_name(prefix)
-
-def get_entrypoints(doc, entrypoints_to_defines, start_index):
- """Extract the entry points from the registry."""
- entrypoints = OrderedDict()
-
- for command in doc.findall('./commands/command'):
- if 'alias' in command.attrib:
- alias = command.attrib['name']
- target = command.attrib['alias']
- entrypoints[alias] = EntrypointAlias(alias, entrypoints[target])
- else:
- name = command.find('./proto/name').text
- ret_type = command.find('./proto/type').text
- params = [EntrypointParam(
- type = p.find('./type').text,
- name = p.find('./name').text,
- decl = ''.join(p.itertext())
- ) for p in command.findall('./param')]
- guard = entrypoints_to_defines.get(name)
- # They really need to be unique
- assert name not in entrypoints
- entrypoints[name] = Entrypoint(name, ret_type, params, guard)
-
- for feature in doc.findall('./feature'):
- assert feature.attrib['api'] == 'vulkan'
- version = VkVersion(feature.attrib['number'])
- if version > MAX_API_VERSION:
- continue
-
- for command in feature.findall('./require/command'):
- e = entrypoints[command.attrib['name']]
- e.enabled = True
- assert e.core_version is None
- e.core_version = version
-
- supported_exts = dict((ext.name, ext) for ext in EXTENSIONS)
- for extension in doc.findall('.extensions/extension'):
- ext_name = extension.attrib['name']
- if ext_name not in supported_exts:
- continue
-
- ext = supported_exts[ext_name]
- ext.type = extension.attrib['type']
-
- for command in extension.findall('./require/command'):
- e = entrypoints[command.attrib['name']]
- e.enabled = True
- assert e.core_version is None
- e.extensions.append(ext)
-
- # if the base command is not supported by the driver yet, don't alias aliases
- for e in entrypoints.values():
- if e.alias and not e.alias.enabled:
- e_clone = copy.deepcopy(e.alias)
- e_clone.enabled = True
- e_clone.name = e.name
- entrypoints[e.name] = e_clone
-
- return [e for e in entrypoints.values() if e.enabled]
-
-
-def get_entrypoints_defines(doc):
- """Maps entry points to extension defines."""
- entrypoints_to_defines = {}
-
- for extension in doc.findall('./extensions/extension[@protect]'):
- define = extension.attrib['protect']
-
- for entrypoint in extension.findall('./require/command'):
- fullname = entrypoint.attrib['name']
- entrypoints_to_defines[fullname] = define
-
- for extension in doc.findall('./extensions/extension[@platform]'):
- platform = extension.attrib['platform']
- ext = '_KHR'
- if platform.upper() == 'XLIB_XRANDR':
- ext = '_EXT'
- define = 'VK_USE_PLATFORM_' + platform.upper() + ext
-
- for entrypoint in extension.findall('./require/command'):
- fullname = entrypoint.attrib['name']
- entrypoints_to_defines[fullname] = define
-
- return entrypoints_to_defines
-
-
-def gen_code(entrypoints):
- """Generate the C code."""
- strmap = StringIntMap()
- for e in entrypoints:
- strmap.add_string(e.name, e.num)
- strmap.bake()
-
- return TEMPLATE_C.render(entrypoints=entrypoints,
- LAYERS=LAYERS,
- strmap=strmap,
- filename=os.path.basename(__file__))
-
-
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--outdir', help='Where to write the files.',
@@ -482,24 +48,10 @@ def main():
dest='xml_files')
args = parser.parse_args()
- entrypoints = []
-
- for filename in args.xml_files:
- doc = et.parse(filename)
- entrypoints += get_entrypoints(doc, get_entrypoints_defines(doc),
- start_index=len(entrypoints))
-
- for num, e in enumerate(entrypoints):
- e.num = num
-
- # 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,
- LAYERS=LAYERS,
- filename=os.path.basename(__file__)))
- with open(os.path.join(args.outdir, 'radv_entrypoints.c'), 'wb') as f:
- f.write(gen_code(entrypoints))
+ vk_entrypoints_gen.generate_entrypoints(MAX_API_VERSION, EXTENSIONS, LAYERS, 'radv', args.xml_files,
+ os.path.join(args.outdir, 'radv_entrypoints.c'),
+ os.path.join(args.outdir, 'radv_entrypoints.h'),
+ generate_trampolines=False)
if __name__ == '__main__':
diff --git a/src/amd/vulkan/radv_extensions.py b/src/amd/vulkan/radv_extensions.py
index 8b5eee867ac..b5a17b364a2 100644
--- a/src/amd/vulkan/radv_extensions.py
+++ b/src/amd/vulkan/radv_extensions.py
@@ -24,25 +24,20 @@ COPYRIGHT = """\
*/
"""
-import argparse
-import copy
-import re
-import xml.etree.cElementTree as et
+from vk_extensions import ApiVersion, Extension, VkVersion
-from mako.template import Template
+API_PATCH_VERSION = 80
-MAX_API_VERSION = '1.1.70'
+# Supported API versions. Each one is the maximum patch version for the given
+# version. Version come in increasing order and each version is available if
+# it's provided "enable" condition is true and all previous versions are
+# available.
+API_VERSIONS = [
+ ApiVersion('1.0', True),
+ ApiVersion('1.1', '!ANDROID && device->rad_info.has_syncobj_wait_for_submit'),
+]
-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;
+MAX_API_VERSION = None # Computed later
# On Android, we disable all surface and swapchain extensions. Android's Vulkan
# loader implements VK_KHR_surface and VK_KHR_swapchain, and applications
@@ -114,206 +109,9 @@ EXTENSIONS = [
Extension('VK_AMD_shader_trinary_minmax', 1, True),
]
-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):
- patch = self.patch if self.patch is not None else 0
- ver_list = [str(self.major), str(self.minor), str(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 __gt__(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() > 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
-
- ext = ext_name_map[ext_name]
- ext.type = ext_elem.attrib['type']
-
-_TEMPLATE_H = Template(COPYRIGHT + """
-#ifndef RADV_EXTENSIONS_H
-#define RADV_EXTENSIONS_H
-
-enum {
- RADV_INSTANCE_EXTENSION_COUNT = ${len(instance_extensions)},
- RADV_DEVICE_EXTENSION_COUNT = ${len(device_extensions)},
-};
-
-struct radv_instance_extension_table {
- union {
- bool extensions[RADV_INSTANCE_EXTENSION_COUNT];
- struct {
-%for ext in instance_extensions:
- bool ${ext.name[3:]};
-%endfor
- };
- };
-};
-
-struct radv_device_extension_table {
- union {
- bool extensions[RADV_DEVICE_EXTENSION_COUNT];
- struct {
-%for ext in device_extensions:
- bool ${ext.name[3:]};
-%endfor
- };
- };
-};
-
-extern const VkExtensionProperties radv_instance_extensions[RADV_INSTANCE_EXTENSION_COUNT];
-extern const VkExtensionProperties radv_device_extensions[RADV_DEVICE_EXTENSION_COUNT];
-extern const struct radv_instance_extension_table radv_supported_instance_extensions;
-
-
-struct radv_physical_device;
-
-void radv_fill_device_extension_table(const struct radv_physical_device *device,
- struct radv_device_extension_table* table);
-#endif
-""")
-
-_TEMPLATE_C = Template(COPYRIGHT + """
-#include "radv_private.h"
-
-#include "vk_util.h"
-
-/* Convert the VK_USE_PLATFORM_* defines to booleans */
-%for platform in ['ANDROID_KHR', 'WAYLAND_KHR', 'XCB_KHR', 'XLIB_KHR', 'DISPLAY_KHR', 'XLIB_XRANDR_EXT']:
-#ifdef VK_USE_PLATFORM_${platform}
-# undef VK_USE_PLATFORM_${platform}
-# define VK_USE_PLATFORM_${platform} true
-#else
-# define VK_USE_PLATFORM_${platform} 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 || \\
- VK_USE_PLATFORM_DISPLAY_KHR)
-
-
-const VkExtensionProperties radv_instance_extensions[RADV_INSTANCE_EXTENSION_COUNT] = {
-%for ext in instance_extensions:
- {"${ext.name}", ${ext.ext_version}},
-%endfor
-};
-
-const VkExtensionProperties radv_device_extensions[RADV_DEVICE_EXTENSION_COUNT] = {
-%for ext in device_extensions:
- {"${ext.name}", ${ext.ext_version}},
-%endfor
-};
-
-const struct radv_instance_extension_table radv_supported_instance_extensions = {
-%for ext in instance_extensions:
- .${ext.name[3:]} = ${ext.enable},
-%endfor
-};
-
-void radv_fill_device_extension_table(const struct radv_physical_device *device,
- struct radv_device_extension_table* table)
-{
-%for ext in device_extensions:
- table->${ext.name[3:]} = ${ext.enable};
-%endfor
-}
-
-VkResult radv_EnumerateInstanceVersion(
- uint32_t* pApiVersion)
-{
- *pApiVersion = ${MAX_API_VERSION.c_vk_version()};
- return VK_SUCCESS;
-}
-
-uint32_t
-radv_physical_device_api_version(struct radv_physical_device *dev)
-{
- if (!ANDROID && dev->rad_info.has_syncobj_wait_for_submit)
- return VK_MAKE_VERSION(1, 1, 70);
- return VK_MAKE_VERSION(1, 0, 68);
-}
-""")
-
-if __name__ == '__main__':
- parser = argparse.ArgumentParser()
- parser.add_argument('--out-c', help='Output C file.', required=True)
- parser.add_argument('--out-h', help='Output H 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_c, 'w') as f:
- f.write(_TEMPLATE_C.render(**template_env))
- with open(args.out_h, 'w') as f:
- f.write(_TEMPLATE_H.render(**template_env))
+MAX_API_VERSION = VkVersion('0.0.0')
+for version in API_VERSIONS:
+ version.version = VkVersion(version.version)
+ version.version.patch = API_PATCH_VERSION
+ assert version.version > MAX_API_VERSION
+ MAX_API_VERSION = version.version
diff --git a/src/amd/vulkan/radv_extensions_gen.py b/src/amd/vulkan/radv_extensions_gen.py
new file mode 100644
index 00000000000..071e175ad9e
--- /dev/null
+++ b/src/amd/vulkan/radv_extensions_gen.py
@@ -0,0 +1,44 @@
+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
+
+from radv_extensions import *
+import vk_extensions_gen
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--out-c', help='Output C file.')
+ parser.add_argument('--out-h', help='Output H file.')
+ parser.add_argument('--xml',
+ help='Vulkan API XML file.',
+ required=True,
+ action='append',
+ dest='xml_files')
+ args = parser.parse_args()
+
+ vk_extensions_gen.generate_extensions(MAX_API_VERSION, API_VERSIONS, EXTENSIONS, 'radv',
+ args.xml_files, args.out_c, args.out_h)
diff --git a/src/amd/vulkan/radv_icd.py b/src/amd/vulkan/radv_icd.py
index cc86bbfa56c..5b1a0237d09 100644
--- a/src/amd/vulkan/radv_icd.py
+++ b/src/amd/vulkan/radv_icd.py
@@ -20,6 +20,7 @@
# 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 json
import os.path
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index a187f76be49..36101db52c3 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -267,11 +267,10 @@ void radv_logi_v(const char *format, va_list va);
return; \
} while (0)
-void *radv_lookup_entrypoint_unchecked(const char *name);
-void *radv_lookup_entrypoint_checked(const char *name,
- uint32_t core_version,
- const struct radv_instance_extension_table *instance,
- const struct radv_device_extension_table *device);
+int radv_get_entrypoint_index(const char *name);
+bool radv_entrypoint_is_enabled(int index, uint32_t core_version,
+ const struct radv_instance_extension_table *instance,
+ const struct radv_device_extension_table *device);
struct radv_physical_device {
VK_LOADER_DATA _loader_data;
diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c
index 20484177135..73994bcc358 100644
--- a/src/amd/vulkan/radv_wsi.c
+++ b/src/amd/vulkan/radv_wsi.c
@@ -32,7 +32,11 @@
static PFN_vkVoidFunction
radv_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName)
{
- return radv_lookup_entrypoint_unchecked(pName);
+ int idx = radv_get_entrypoint_index(pName);
+ if (idx < 0)
+ return NULL;
+
+ return radv_dispatch_table.entrypoints[idx];
}
VkResult
--
2.18.0
More information about the mesa-dev
mailing list