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 <bas@basnieuwenhuizen.nl>
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Dave Airlie 2017-10-17 15:18:36 +10:00
parent c00256a12c
commit 17201a2eb0
7 changed files with 472 additions and 466 deletions

View File

@ -1,6 +1,7 @@
# Generated source files # Generated source files
/radv_entrypoints.c /radv_entrypoints.c
/radv_entrypoints.h /radv_entrypoints.h
/radv_extensions.c
/radv_timestamp.h /radv_timestamp.h
/dev_icd.json /dev_icd.json
/vk_format_table.c /vk_format_table.c

View File

@ -107,12 +107,19 @@ libvulkan_radeon_la_SOURCES = $(VULKAN_GEM_FILES)
vulkan_api_xml = $(top_srcdir)/src/vulkan/registry/vk.xml 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) $(MKDIR_GEN)
$(AM_V_GEN)$(PYTHON2) $(srcdir)/radv_entrypoints_gen.py \ $(AM_V_GEN)$(PYTHON2) $(srcdir)/radv_entrypoints_gen.py \
--xml $(vulkan_api_xml) --outdir $(builddir) --xml $(vulkan_api_xml) --outdir $(builddir)
radv_entrypoints.h: radv_entrypoints.c 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_table.c: vk_format_table.py \
vk_format_parse.py \ vk_format_parse.py \
vk_format_layout.csv vk_format_layout.csv

View File

@ -77,5 +77,6 @@ VULKAN_WSI_X11_FILES := \
VULKAN_GENERATED_FILES := \ VULKAN_GENERATED_FILES := \
radv_entrypoints.c \ radv_entrypoints.c \
radv_entrypoints.h radv_entrypoints.h \
radv_extensions.c

View File

@ -76,198 +76,6 @@ radv_get_device_uuid(struct radeon_info *info, void *uuid)
ac_compute_device_uuid(info, uuid, VK_UUID_SIZE); 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 * static const char *
get_chip_name(enum radeon_family family) 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); disk_cache_format_hex_id(buf, device->cache_uuid, VK_UUID_SIZE);
device->disk_cache = disk_cache_create("radv", buf, shader_env_flags); 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"); fprintf(stderr, "WARNING: radv is not a conformant vulkan implementation, testing use only.\n");
device->name = get_chip_name(device->rad_info.family); device->name = get_chip_name(device->rad_info.family);
@ -416,7 +199,6 @@ fail:
static void static void
radv_physical_device_finish(struct radv_physical_device *device) radv_physical_device_finish(struct radv_physical_device *device)
{ {
radv_extensions_finish(device->instance, &device->extensions);
radv_finish_wsi(device); radv_finish_wsi(device);
device->ws->destroy(device->ws); device->ws->destroy(device->ws);
disk_cache_destroy(device->disk_cache); disk_cache_destroy(device->disk_cache);
@ -515,9 +297,8 @@ VkResult radv_CreateInstance(
} }
for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
if (!is_extension_enabled(instance_extensions, const char *ext_name = pCreateInfo->ppEnabledExtensionNames[i];
ARRAY_SIZE(instance_extensions), if (!radv_instance_extension_supported(ext_name))
pCreateInfo->ppEnabledExtensionNames[i]))
return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT); return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT);
} }
@ -851,7 +632,7 @@ void radv_GetPhysicalDeviceProperties(
}; };
*pProperties = (VkPhysicalDeviceProperties) { *pProperties = (VkPhysicalDeviceProperties) {
.apiVersion = VK_MAKE_VERSION(1, 0, 42), .apiVersion = radv_physical_device_api_version(pdevice),
.driverVersion = vk_get_driver_version(), .driverVersion = vk_get_driver_version(),
.vendorID = ATI_VENDOR_ID, .vendorID = ATI_VENDOR_ID,
.deviceID = pdevice->rad_info.pci_id, .deviceID = pdevice->rad_info.pci_id,
@ -1141,9 +922,8 @@ VkResult radv_CreateDevice(
struct radv_device *device; struct radv_device *device;
for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
if (!is_extension_enabled(physical_device->extensions.ext_array, const char *ext_name = pCreateInfo->ppEnabledExtensionNames[i];
physical_device->extensions.num_ext, if (!radv_physical_device_extension_supported(physical_device, ext_name))
pCreateInfo->ppEnabledExtensionNames[i]))
return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT); return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT);
} }
@ -1331,47 +1111,6 @@ void radv_DestroyDevice(
vk_free(&device->alloc, device); 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( VkResult radv_EnumerateInstanceLayerProperties(
uint32_t* pPropertyCount, uint32_t* pPropertyCount,
VkLayerProperties* pProperties) VkLayerProperties* pProperties)

View File

@ -25,214 +25,184 @@
import argparse import argparse
import functools import functools
import os import os
import textwrap
import xml.etree.cElementTree as et import xml.etree.cElementTree as et
from mako.template import Template from mako.template import Template
MAX_API_VERSION = 1.0 from radv_extensions import *
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',
]
# We generate a static hash table for entry point lookup # We generate a static hash table for entry point lookup
# (vkGetProcAddress). We use a linear congruential generator for our hash # (vkGetProcAddress). We use a linear congruential generator for our hash
# function and a power-of-two size table. The prime numbers are determined # function and a power-of-two size table. The prime numbers are determined
# experimentally. # experimentally.
TEMPLATE_H = Template(textwrap.dedent("""\ TEMPLATE_H = Template("""\
/* This file generated from ${filename}, don't edit directly. */ /* This file generated from ${filename}, don't edit directly. */
struct radv_dispatch_table { struct radv_dispatch_table {
union { union {
void *entrypoints[${len(entrypoints)}]; void *entrypoints[${len(entrypoints)}];
struct { struct {
% for _, name, _, _, _, guard in entrypoints: % 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: % if guard is not None:
#ifdef ${guard} #ifdef ${guard}
% endif PFN_vk${name} ${name};
${type_} ${layer}_${name}(${args}) __attribute__ ((weak)); #else
% if guard is not None: void *${name};
#endif // ${guard} # endif
% endif % else:
% endfor PFN_vk${name} ${name};
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 % endif
% endfor % endfor
}; };
% endfor };
};
static void * __attribute__ ((noinline)) % for type_, name, args, num, h, guard in entrypoints:
radv_resolve_entrypoint(uint32_t index) % if guard is not None:
{ #ifdef ${guard}
return radv_layer.entrypoints[index]; % endif
} ${type_} radv_${name}(${args});
% if guard is not None:
#endif // ${guard}
% endif
% endfor
""", output_encoding='utf-8')
/* Hash table stats: TEMPLATE_C = Template(u"""\
* size ${hash_size} entries /*
* collisions entries: * Copyright © 2015 Intel Corporation
% for i in xrange(10): *
* ${i}${'+' if i == 9 else ''} ${collisions[i]} * Permission is hereby granted, free of charge, to any person obtaining a
% endfor * 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.
*/
#define none ${'{:#x}'.format(none)} /* This file generated from ${filename}, don't edit directly. */
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 * #include "radv_private.h"
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; struct radv_entrypoint {
for (p = name; *p; p++) uint32_t name;
hash = hash * prime_factor + *p; uint32_t hash;
};
h = hash; /* We use a big string constant to avoid lots of reloctions from the entry
do { * point table to lots of little strings. The entries in the entry point table
i = map[h & ${hash_mask}]; * store the index into this big string.
if (i == none) */
return NULL;
e = &entrypoints[i];
h += prime_step;
} while (e->hash != hash);
if (strcmp(name, strings + e->name) != 0) static const char strings[] =
return NULL; % for _, name, _, _, _, _ in entrypoints:
"vk${name}\\0"
% endfor
;
return radv_resolve_entrypoint(i); static const struct radv_entrypoint entrypoints[] = {
}"""), output_encoding='utf-8') % 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 NONE = 0xffff
HASH_SIZE = 256 HASH_SIZE = 256
@ -249,28 +219,29 @@ def cal_hash(name):
lambda h, c: (h * PRIME_FACTOR + ord(c)) & U32_MASK, name, 0) 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.""" """Extract the entry points from the registry."""
entrypoints = [] entrypoints = []
enabled_commands = set() enabled_commands = set()
for feature in doc.findall('./feature'): for feature in doc.findall('./feature'):
assert feature.attrib['api'] == 'vulkan' assert feature.attrib['api'] == 'vulkan'
if float(feature.attrib['number']) > MAX_API_VERSION: if VkVersion(feature.attrib['number']) > MAX_API_VERSION:
continue continue
for command in feature.findall('./require/command'): for command in feature.findall('./require/command'):
enabled_commands.add(command.attrib['name']) enabled_commands.add(command.attrib['name'])
supported = set(ext.name for ext in EXTENSIONS)
for extension in doc.findall('.extensions/extension'): for extension in doc.findall('.extensions/extension'):
if extension.attrib['name'] not in SUPPORTED_EXTENSIONS: if extension.attrib['name'] not in supported:
continue continue
assert extension.attrib['supported'] == 'vulkan' assert extension.attrib['supported'] == 'vulkan'
for command in extension.findall('./require/command'): for command in extension.findall('./require/command'):
enabled_commands.add(command.attrib['name']) enabled_commands.add(command.attrib['name'])
index = 0 index = start_index
for command in doc.findall('./commands/command'): for command in doc.findall('./commands/command'):
type = command.find('./proto/type').text type = command.find('./proto/type').text
fullname = command.find('./proto/name').text fullname = command.find('./proto/name').text
@ -339,12 +310,22 @@ def main():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('--outdir', help='Where to write the files.', parser.add_argument('--outdir', help='Where to write the files.',
required=True) 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() args = parser.parse_args()
doc = et.parse(args.xml) entrypoints = []
entrypoints = get_entrypoints(doc, get_entrypoints_defines(doc))
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: with open(os.path.join(args.outdir, 'radv_entrypoints.h'), 'wb') as f:
f.write(TEMPLATE_H.render(entrypoints=entrypoints, f.write(TEMPLATE_H.render(entrypoints=entrypoints,
filename=os.path.basename(__file__))) filename=os.path.basename(__file__)))

View File

@ -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 <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))

View File

@ -253,11 +253,6 @@ void radv_loge_v(const char *format, va_list va);
void *radv_lookup_entrypoint(const char *name); void *radv_lookup_entrypoint(const char *name);
struct radv_extensions {
VkExtensionProperties *ext_array;
uint32_t num_ext;
};
struct radv_physical_device { struct radv_physical_device {
VK_LOADER_DATA _loader_data; VK_LOADER_DATA _loader_data;
@ -273,7 +268,6 @@ struct radv_physical_device {
int local_fd; int local_fd;
struct wsi_device wsi_device; struct wsi_device wsi_device;
struct radv_extensions extensions;
bool has_rbplus; /* if RB+ register exist */ bool has_rbplus; /* if RB+ register exist */
bool rbplus_allowed; /* if RB+ is allowed */ bool rbplus_allowed; /* if RB+ is allowed */
@ -301,6 +295,11 @@ struct radv_instance {
VkResult radv_init_wsi(struct radv_physical_device *physical_device); VkResult radv_init_wsi(struct radv_physical_device *physical_device);
void radv_finish_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 cache_entry;
struct radv_pipeline_cache { struct radv_pipeline_cache {