diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2023-11-02 04:53:47 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2023-11-02 04:53:47 +0000 |
commit | b44518130b33cadb5c1d619e9e936ae0e0dbf7cb (patch) | |
tree | 6069eb03c39fbc79808a7d94f857118cce75cbe3 /lib/mesa/src/vulkan/util | |
parent | 32aeb3c41fedbbd7b11aacfec48e8f699d16bff0 (diff) |
Merge Mesa 23.1.9
Diffstat (limited to 'lib/mesa/src/vulkan/util')
-rw-r--r-- | lib/mesa/src/vulkan/util/gen_enum_to_str.py | 157 | ||||
-rw-r--r-- | lib/mesa/src/vulkan/util/vk_alloc.h | 2 | ||||
-rw-r--r-- | lib/mesa/src/vulkan/util/vk_physical_device_features.py | 465 | ||||
-rw-r--r-- | lib/mesa/src/vulkan/util/vk_util.h | 18 |
4 files changed, 599 insertions, 43 deletions
diff --git a/lib/mesa/src/vulkan/util/gen_enum_to_str.py b/lib/mesa/src/vulkan/util/gen_enum_to_str.py index 1c3ae327a..fabba6f39 100644 --- a/lib/mesa/src/vulkan/util/gen_enum_to_str.py +++ b/lib/mesa/src/vulkan/util/gen_enum_to_str.py @@ -28,6 +28,7 @@ import textwrap import xml.etree.ElementTree as et from mako.template import Template +from vk_extensions import Extension, filter_api, get_all_required COPYRIGHT = textwrap.dedent(u"""\ * Copyright © 2017 Intel Corporation @@ -58,7 +59,7 @@ C_TEMPLATE = Template(textwrap.dedent(u"""\ */ #include <string.h> - #include <vulkan/vulkan.h> + #include <vulkan/vulkan_core.h> #include <vulkan/vk_android_native_buffer.h> #include <vulkan/vk_layer.h> #include "util/macros.h" @@ -88,6 +89,29 @@ C_TEMPLATE = Template(textwrap.dedent(u"""\ % endif %endfor + % for enum in bitmasks: + + % if enum.guard: +#ifdef ${enum.guard} + % endif + const char * + vk_${enum.name[2:]}_to_str(${enum.name} input) + { + switch((int64_t)input) { + % for v in sorted(enum.values.keys()): + case ${v}: + return "${enum.values[v]}"; + % endfor + default: + return "Unknown ${enum.name} value."; + } + } + + % if enum.guard: +#endif + % endif + %endfor + size_t vk_structure_type_size(const struct VkBaseInStructure *item) { switch((int)item->sType) { @@ -148,6 +172,16 @@ H_TEMPLATE = Template(textwrap.dedent(u"""\ % endif % endfor + % for enum in bitmasks: + % if enum.guard: +#ifdef ${enum.guard} + % endif + const char * vk_${enum.name[2:]}_to_str(${enum.name} input); + % if enum.guard: +#endif + % endif + % endfor + size_t vk_structure_type_size(const struct VkBaseInStructure *item); const char * vk_ObjectType_to_ObjectName(VkObjectType type); @@ -169,7 +203,7 @@ H_DEFINE_TEMPLATE = Template(textwrap.dedent(u"""\ #ifndef MESA_VK_ENUM_DEFINES_H #define MESA_VK_ENUM_DEFINES_H - #include <vulkan/vulkan.h> + #include <vulkan/vulkan_core.h> #include <vulkan/vk_android_native_buffer.h> #ifdef __cplusplus @@ -209,6 +243,12 @@ H_DEFINE_TEMPLATE = Template(textwrap.dedent(u"""\ % endif % endfor + static inline VkFormatFeatureFlags + vk_format_features2_to_features(VkFormatFeatureFlags2 features2) + { + return features2 & VK_ALL_FORMAT_FEATURE_FLAG_BITS; + } + #ifdef __cplusplus } /* extern "C" */ #endif @@ -247,10 +287,12 @@ def CamelCase_to_SHOUT_CASE(s): return (s[:1] + re.sub(r'(?<![A-Z])([A-Z])', r'_\1', s[1:])).upper() def compute_max_enum_name(s): + if s == "VkSwapchainImageUsageFlagBitsANDROID": + return "VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM" max_enum_name = CamelCase_to_SHOUT_CASE(s) last_prefix = max_enum_name.rsplit('_', 1)[-1] # Those special prefixes need to be always at the end - if last_prefix in ['AMD', 'EXT', 'INTEL', 'KHR', 'NV'] : + if last_prefix in ['AMD', 'EXT', 'INTEL', 'KHR', 'NV', 'LUNARG'] : max_enum_name = "_".join(max_enum_name.split('_')[:-1]) max_enum_name = max_enum_name + "_MAX_ENUM_" + last_prefix else: @@ -370,30 +412,59 @@ def parse_xml(enum_factory, ext_factory, struct_factory, bitmask_factory, """ xml = et.parse(filename) + api = 'vulkan' + + required_types = get_all_required(xml, 'type', api) for enum_type in xml.findall('./enums[@type="enum"]'): - enum = enum_factory(enum_type.attrib['name']) + if not filter_api(enum_type, api): + continue + + type_name = enum_type.attrib['name'] + if not type_name in required_types: + continue + + enum = enum_factory(type_name) for value in enum_type.findall('./enum'): - enum.add_value_from_xml(value) + if filter_api(value, api): + enum.add_value_from_xml(value) # For bitmask we only add the Enum selected for convenience. for enum_type in xml.findall('./enums[@type="bitmask"]'): + if not filter_api(enum_type, api): + continue + + type_name = enum_type.attrib['name'] + if not type_name in required_types: + continue + bitwidth = int(enum_type.attrib.get('bitwidth', 32)) - enum = bitmask_factory(enum_type.attrib['name'], bitwidth=bitwidth) + enum = bitmask_factory(type_name, bitwidth=bitwidth) for value in enum_type.findall('./enum'): - enum.add_value_from_xml(value) + if filter_api(value, api): + enum.add_value_from_xml(value) - for value in xml.findall('./feature/require/enum[@extends]'): - extends = value.attrib['extends'] - enum = enum_factory.get(extends) - if enum is not None: - enum.add_value_from_xml(value) - enum = bitmask_factory.get(extends) - if enum is not None: - enum.add_value_from_xml(value) + for feature in xml.findall('./feature'): + if not api in feature.attrib['api'].split(','): + continue + + for value in feature.findall('./require/enum[@extends]'): + extends = value.attrib['extends'] + enum = enum_factory.get(extends) + if enum is not None: + enum.add_value_from_xml(value) + enum = bitmask_factory.get(extends) + if enum is not None: + enum.add_value_from_xml(value) for struct_type in xml.findall('./types/type[@category="struct"]'): + if not filter_api(struct_type, api): + continue + name = struct_type.attrib['name'] + if name not in required_types: + continue + stype = struct_get_stype(struct_type) if stype is not None: struct_factory(name, stype=stype) @@ -404,39 +475,55 @@ def parse_xml(enum_factory, ext_factory, struct_factory, bitmask_factory, define = platform.attrib['protect'] platform_define[name] = define - for ext_elem in xml.findall('./extensions/extension[@supported="vulkan"]'): - define = None - if "platform" in ext_elem.attrib: - define = platform_define[ext_elem.attrib['platform']] - extension = ext_factory(ext_elem.attrib['name'], - number=int(ext_elem.attrib['number']), - define=define) + for ext_elem in xml.findall('./extensions/extension'): + ext = Extension.from_xml(ext_elem) + if api not in ext.supported: + continue - for value in ext_elem.findall('./require/enum[@extends]'): - extends = value.attrib['extends'] - enum = enum_factory.get(extends) - if enum is not None: - enum.add_value_from_xml(value, extension) - enum = bitmask_factory.get(extends) - if enum is not None: - enum.add_value_from_xml(value, extension) - for t in ext_elem.findall('./require/type'): - struct = struct_factory.get(t.attrib['name']) - if struct is not None: - struct.extension = extension + define = platform_define.get(ext.platform, None) + extension = ext_factory(ext.name, number=ext.number, define=define) + + for req_elem in ext_elem.findall('./require'): + if not filter_api(req_elem, api): + continue + + for value in req_elem.findall('./enum[@extends]'): + extends = value.attrib['extends'] + enum = enum_factory.get(extends) + if enum is not None: + enum.add_value_from_xml(value, extension) + enum = bitmask_factory.get(extends) + if enum is not None: + enum.add_value_from_xml(value, extension) + + for t in req_elem.findall('./type'): + struct = struct_factory.get(t.attrib['name']) + if struct is not None: + struct.extension = extension if define: for value in ext_elem.findall('./require/type[@name]'): enum = enum_factory.get(value.attrib['name']) if enum is not None: enum.set_guard(define) + enum = bitmask_factory.get(value.attrib['name']) + if enum is not None: + enum.set_guard(define) + obj_type_enum = enum_factory.get("VkObjectType") obj_types = obj_type_factory("VkObjectType") for object_type in xml.findall('./types/type[@category="handle"]'): for object_name in object_type.findall('./name'): # Convert to int to avoid undefined enums enum = object_type.attrib['objtypeenum'] - enum_val = enum_factory.get("VkObjectType").name_to_value[enum] + + # Annoyingly, object types are hard to filter by API so just + # look for whether or not we can find the enum name in the + # VkObjectType enum. + if enum not in obj_type_enum.name_to_value: + continue + + enum_val = obj_type_enum.name_to_value[enum] obj_types.enum_to_name[enum_val] = object_name.text diff --git a/lib/mesa/src/vulkan/util/vk_alloc.h b/lib/mesa/src/vulkan/util/vk_alloc.h index 973f54c4c..17d1f2f5a 100644 --- a/lib/mesa/src/vulkan/util/vk_alloc.h +++ b/lib/mesa/src/vulkan/util/vk_alloc.h @@ -27,7 +27,7 @@ #include <stdio.h> #include <string.h> -#include <vulkan/vulkan.h> +#include <vulkan/vulkan_core.h> #include "util/u_math.h" #include "util/macros.h" diff --git a/lib/mesa/src/vulkan/util/vk_physical_device_features.py b/lib/mesa/src/vulkan/util/vk_physical_device_features.py new file mode 100644 index 000000000..9aa62653a --- /dev/null +++ b/lib/mesa/src/vulkan/util/vk_physical_device_features.py @@ -0,0 +1,465 @@ +COPYRIGHT=u""" +/* Copyright © 2021 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. + */ +""" + +import argparse +from collections import OrderedDict +from dataclasses import dataclass +import os +import sys +import typing +import xml.etree.ElementTree as et + +import mako +from mako.template import Template +from vk_extensions import get_all_required, filter_api + +def str_removeprefix(s, prefix): + if s.startswith(prefix): + return s[len(prefix):] + return s + +RENAMED_FEATURES = { + # See https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17272#note_1446477 for details + ('BufferDeviceAddressFeaturesEXT', 'bufferDeviceAddressCaptureReplay'): 'bufferDeviceAddressCaptureReplayEXT', + + ('MeshShaderFeaturesNV', 'taskShader'): 'taskShaderNV', + ('MeshShaderFeaturesNV', 'meshShader'): 'meshShaderNV', +} + +KNOWN_ALIASES = [ + (['Vulkan11Features', '16BitStorageFeatures'], ['storageBuffer16BitAccess', 'uniformAndStorageBuffer16BitAccess', 'storagePushConstant16', 'storageInputOutput16']), + (['Vulkan11Features', 'MultiviewFeatures'], ['multiview', 'multiviewGeometryShader', 'multiviewTessellationShader']), + (['Vulkan11Features', 'VariablePointersFeatures'], ['variablePointersStorageBuffer', 'variablePointers']), + (['Vulkan11Features', 'ProtectedMemoryFeatures'], ['protectedMemory']), + (['Vulkan11Features', 'SamplerYcbcrConversionFeatures'], ['samplerYcbcrConversion']), + (['Vulkan11Features', 'ShaderDrawParametersFeatures'], ['shaderDrawParameters']), + + (['Vulkan12Features', '8BitStorageFeatures'], ['storageBuffer8BitAccess', 'uniformAndStorageBuffer8BitAccess', 'storagePushConstant8']), + (['Vulkan12Features', 'ShaderAtomicInt64Features'], ['shaderBufferInt64Atomics', 'shaderSharedInt64Atomics']), + (['Vulkan12Features', 'ShaderFloat16Int8Features'], ['shaderFloat16', 'shaderInt8']), + ( + ['Vulkan12Features', 'DescriptorIndexingFeatures'], + [ + 'shaderInputAttachmentArrayDynamicIndexing', + 'shaderUniformTexelBufferArrayDynamicIndexing', + 'shaderStorageTexelBufferArrayDynamicIndexing', + 'shaderUniformBufferArrayNonUniformIndexing', + 'shaderSampledImageArrayNonUniformIndexing', + 'shaderStorageBufferArrayNonUniformIndexing', + 'shaderStorageImageArrayNonUniformIndexing', + 'shaderInputAttachmentArrayNonUniformIndexing', + 'shaderUniformTexelBufferArrayNonUniformIndexing', + 'shaderStorageTexelBufferArrayNonUniformIndexing', + 'descriptorBindingUniformBufferUpdateAfterBind', + 'descriptorBindingSampledImageUpdateAfterBind', + 'descriptorBindingStorageImageUpdateAfterBind', + 'descriptorBindingStorageBufferUpdateAfterBind', + 'descriptorBindingUniformTexelBufferUpdateAfterBind', + 'descriptorBindingStorageTexelBufferUpdateAfterBind', + 'descriptorBindingUpdateUnusedWhilePending', + 'descriptorBindingPartiallyBound', + 'descriptorBindingVariableDescriptorCount', + 'runtimeDescriptorArray', + ], + ), + (['Vulkan12Features', 'ScalarBlockLayoutFeatures'], ['scalarBlockLayout']), + (['Vulkan12Features', 'ImagelessFramebufferFeatures'], ['imagelessFramebuffer']), + (['Vulkan12Features', 'UniformBufferStandardLayoutFeatures'], ['uniformBufferStandardLayout']), + (['Vulkan12Features', 'ShaderSubgroupExtendedTypesFeatures'], ['shaderSubgroupExtendedTypes']), + (['Vulkan12Features', 'SeparateDepthStencilLayoutsFeatures'], ['separateDepthStencilLayouts']), + (['Vulkan12Features', 'HostQueryResetFeatures'], ['hostQueryReset']), + (['Vulkan12Features', 'TimelineSemaphoreFeatures'], ['timelineSemaphore']), + (['Vulkan12Features', 'BufferDeviceAddressFeatures', 'BufferDeviceAddressFeaturesEXT'], ['bufferDeviceAddress', 'bufferDeviceAddressMultiDevice']), + (['Vulkan12Features', 'BufferDeviceAddressFeatures'], ['bufferDeviceAddressCaptureReplay']), + (['Vulkan12Features', 'VulkanMemoryModelFeatures'], ['vulkanMemoryModel', 'vulkanMemoryModelDeviceScope', 'vulkanMemoryModelAvailabilityVisibilityChains']), + + (['Vulkan13Features', 'ImageRobustnessFeatures'], ['robustImageAccess']), + (['Vulkan13Features', 'InlineUniformBlockFeatures'], ['inlineUniformBlock', 'descriptorBindingInlineUniformBlockUpdateAfterBind']), + (['Vulkan13Features', 'PipelineCreationCacheControlFeatures'], ['pipelineCreationCacheControl']), + (['Vulkan13Features', 'PrivateDataFeatures'], ['privateData']), + (['Vulkan13Features', 'ShaderDemoteToHelperInvocationFeatures'], ['shaderDemoteToHelperInvocation']), + (['Vulkan13Features', 'ShaderTerminateInvocationFeatures'], ['shaderTerminateInvocation']), + (['Vulkan13Features', 'SubgroupSizeControlFeatures'], ['subgroupSizeControl', 'computeFullSubgroups']), + (['Vulkan13Features', 'Synchronization2Features'], ['synchronization2']), + (['Vulkan13Features', 'TextureCompressionASTCHDRFeatures'], ['textureCompressionASTC_HDR']), + (['Vulkan13Features', 'ZeroInitializeWorkgroupMemoryFeatures'], ['shaderZeroInitializeWorkgroupMemory']), + (['Vulkan13Features', 'DynamicRenderingFeatures'], ['dynamicRendering']), + (['Vulkan13Features', 'ShaderIntegerDotProductFeatures'], ['shaderIntegerDotProduct']), + (['Vulkan13Features', 'Maintenance4Features'], ['maintenance4']), +] + +for (feature_structs, features) in KNOWN_ALIASES: + for flag in features: + for f in feature_structs: + rename = (f, flag) + assert rename not in RENAMED_FEATURES, f"{rename} already exists in RENAMED_FEATURES" + RENAMED_FEATURES[rename] = flag + +def get_renamed_feature(c_type, feature): + return RENAMED_FEATURES.get((str_removeprefix(c_type, 'VkPhysicalDevice'), feature), feature) + +@dataclass +class FeatureStruct: + c_type: str + s_type: str + features: typing.List[str] + +TEMPLATE_C = Template(COPYRIGHT + """ +/* This file generated from ${filename}, don't edit directly. */ + +#include "vk_log.h" +#include "vk_physical_device.h" +#include "vk_physical_device_features.h" +#include "vk_util.h" + +static VkResult +check_physical_device_features(struct vk_physical_device *physical_device, + const VkPhysicalDeviceFeatures *supported, + const VkPhysicalDeviceFeatures *enabled, + const char *struct_name) +{ +% for flag in pdev_features: + if (enabled->${flag} && !supported->${flag}) + return vk_errorf(physical_device, VK_ERROR_FEATURE_NOT_PRESENT, + "%s.%s not supported", struct_name, "${flag}"); +% endfor + + return VK_SUCCESS; +} + +VkResult +vk_physical_device_check_device_features(struct vk_physical_device *physical_device, + const VkDeviceCreateInfo *pCreateInfo) +{ + VkPhysicalDevice vk_physical_device = + vk_physical_device_to_handle(physical_device); + + /* Query the device what kind of features are supported. */ + VkPhysicalDeviceFeatures2 supported_features2 = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + }; + +% for f in feature_structs: + ${f.c_type} supported_${f.c_type} = { .pNext = NULL }; +% endfor + + vk_foreach_struct_const(features, pCreateInfo->pNext) { + VkBaseOutStructure *supported = NULL; + switch (features->sType) { +% for f in feature_structs: + case ${f.s_type}: + supported = (VkBaseOutStructure *) &supported_${f.c_type}; + break; +% endfor + default: + break; + } + + /* Not a feature struct. */ + if (!supported) + continue; + + /* Check for cycles in the list */ + if (supported->pNext != NULL || supported->sType != 0) + return VK_ERROR_UNKNOWN; + + supported->sType = features->sType; + __vk_append_struct(&supported_features2, supported); + } + + physical_device->dispatch_table.GetPhysicalDeviceFeatures2( + vk_physical_device, &supported_features2); + + if (pCreateInfo->pEnabledFeatures) { + VkResult result = + check_physical_device_features(physical_device, + &supported_features2.features, + pCreateInfo->pEnabledFeatures, + "VkPhysicalDeviceFeatures"); + if (result != VK_SUCCESS) + return result; + } + + /* Iterate through additional feature structs */ + vk_foreach_struct_const(features, pCreateInfo->pNext) { + /* Check each feature boolean for given structure. */ + switch (features->sType) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: { + const VkPhysicalDeviceFeatures2 *features2 = (const void *)features; + VkResult result = + check_physical_device_features(physical_device, + &supported_features2.features, + &features2->features, + "VkPhysicalDeviceFeatures2.features"); + if (result != VK_SUCCESS) + return result; + break; + } +% for f in feature_structs: + case ${f.s_type}: { + const ${f.c_type} *a = &supported_${f.c_type}; + const ${f.c_type} *b = (const void *) features; +% for flag in f.features: + if (b->${flag} && !a->${flag}) + return vk_errorf(physical_device, VK_ERROR_FEATURE_NOT_PRESENT, + "%s.%s not supported", "${f.c_type}", "${flag}"); +% endfor + break; + } +% endfor + default: + break; + } + } // for each extension structure + return VK_SUCCESS; +} + +void +vk_set_physical_device_features_1_0(struct vk_features *all_features, + const VkPhysicalDeviceFeatures *pFeatures) +{ +% for flag in pdev_features: + if (pFeatures->${flag}) + all_features->${flag} = true; +% endfor +} + +void +vk_set_physical_device_features(struct vk_features *all_features, + const VkPhysicalDeviceFeatures2 *pFeatures) +{ + vk_foreach_struct_const(ext, pFeatures) { + switch (ext->sType) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: { + const VkPhysicalDeviceFeatures2 *features = (const void *) ext; + vk_set_physical_device_features_1_0(all_features, &features->features); + break; + } + +% for f in feature_structs: + case ${f.s_type}: { + const ${f.c_type} *features = (const void *) ext; +% for flag in f.features: + if (features->${flag}) + all_features->${get_renamed_feature(f.c_type, flag)} = true; +% endfor + break; + } + +% endfor + default: + break; + } + } +} + +void +vk_get_physical_device_features(VkPhysicalDeviceFeatures2 *pFeatures, + const struct vk_features *all_features) +{ +% for flag in pdev_features: + pFeatures->features.${flag} = all_features->${flag}; +% endfor + + vk_foreach_struct(ext, pFeatures) { + switch (ext->sType) { +% for f in feature_structs: + case ${f.s_type}: { + ${f.c_type} *features = (void *) ext; +% for flag in f.features: + features->${flag} = all_features->${get_renamed_feature(f.c_type, flag)}; +% endfor + break; + } + +% endfor + default: + break; + } + } +} +""", output_encoding='utf-8') + +TEMPLATE_H = Template(COPYRIGHT + """ +/* This file generated from ${filename}, don't edit directly. */ +#ifndef VK_FEATURES_H +#define VK_FEATURES_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct vk_features { +% for flag in all_flags: + bool ${flag}; +% endfor +}; + +void +vk_set_physical_device_features_1_0(struct vk_features *all_features, + const VkPhysicalDeviceFeatures *pFeatures); + +void +vk_set_physical_device_features(struct vk_features *all_features, + const VkPhysicalDeviceFeatures2 *pFeatures); + +void +vk_get_physical_device_features(VkPhysicalDeviceFeatures2 *pFeatures, + const struct vk_features *all_features); + +#ifdef __cplusplus +} +#endif + +#endif +""", output_encoding='utf-8') + +def get_pdev_features(doc): + _type = doc.find(".types/type[@name='VkPhysicalDeviceFeatures']") + if _type is not None: + flags = [] + for p in _type.findall('./member'): + assert p.find('./type').text == 'VkBool32' + flags.append(p.find('./name').text) + return flags + return None + +def filter_api(elem, api): + if 'api' not in elem.attrib: + return True + + return api in elem.attrib['api'].split(',') + +def get_feature_structs(doc, api): + feature_structs = OrderedDict() + + required = get_all_required(doc, 'type', api) + + # parse all struct types where structextends VkPhysicalDeviceFeatures2 + for _type in doc.findall('./types/type[@category="struct"]'): + if _type.attrib.get('structextends') != 'VkPhysicalDeviceFeatures2,VkDeviceCreateInfo': + continue + if _type.attrib['name'] not in required: + continue + + # find Vulkan structure type + for elem in _type: + if "STRUCTURE_TYPE" in str(elem.attrib): + s_type = elem.attrib.get('values') + + # collect a list of feature flags + flags = [] + + for p in _type.findall('./member'): + if not filter_api(p, api): + continue + + m_name = p.find('./name').text + if m_name == 'pNext': + pass + elif m_name == 'sType': + s_type = p.attrib.get('values') + else: + assert p.find('./type').text == 'VkBool32' + flags.append(m_name) + + feature_struct = FeatureStruct(c_type=_type.attrib.get('name'), s_type=s_type, features=flags) + feature_structs[feature_struct.c_type] = feature_struct + + return feature_structs.values() + +def get_feature_structs_from_xml(xml_files, api='vulkan'): + diagnostics = [] + + pdev_features = None + feature_structs = [] + + for filename in xml_files: + doc = et.parse(filename) + feature_structs += get_feature_structs(doc, api) + if not pdev_features: + pdev_features = get_pdev_features(doc) + + unused_renames = {**RENAMED_FEATURES} + + features = OrderedDict() + + for flag in pdev_features: + features[flag] = 'VkPhysicalDeviceFeatures' + + for f in feature_structs: + for flag in f.features: + renamed_flag = get_renamed_feature(f.c_type, flag) + if renamed_flag not in features: + features[renamed_flag] = f.c_type + else: + a = str_removeprefix(features[renamed_flag], 'VkPhysicalDevice') + b = str_removeprefix(f.c_type, 'VkPhysicalDevice') + if (a, flag) not in RENAMED_FEATURES or (b, flag) not in RENAMED_FEATURES: + diagnostics.append(f'{a} and {b} both define {flag}') + + unused_renames.pop((str_removeprefix(f.c_type, 'VkPhysicalDevice'), flag), None) + + for rename in unused_renames: + diagnostics.append(f'unused rename {rename}') + + assert len(diagnostics) == 0, '\n'.join(diagnostics) + + return pdev_features, feature_structs, features + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--out-c', required=True, help='Output C file.') + parser.add_argument('--out-h', required=True, help='Output H file.') + parser.add_argument('--xml', + help='Vulkan API XML file.', + required=True, action='append', dest='xml_files') + args = parser.parse_args() + + pdev_features, feature_structs, all_flags = get_feature_structs_from_xml(args.xml_files) + + environment = { + 'filename': os.path.basename(__file__), + 'pdev_features': pdev_features, + 'feature_structs': feature_structs, + 'all_flags': all_flags, + 'get_renamed_feature': get_renamed_feature, + } + + try: + with open(args.out_c, 'wb') as f: + f.write(TEMPLATE_C.render(**environment)) + with open(args.out_h, 'wb') as f: + f.write(TEMPLATE_H.render(**environment)) + except Exception: + # In the event there's an error, this uses some helpers from mako + # to print a useful stack trace and prints it, then exits with + # status 1, if python is run with debug; otherwise it just raises + # the exception + print(mako.exceptions.text_error_template().render(), file=sys.stderr) + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/lib/mesa/src/vulkan/util/vk_util.h b/lib/mesa/src/vulkan/util/vk_util.h index ac6061034..b1a65c1b8 100644 --- a/lib/mesa/src/vulkan/util/vk_util.h +++ b/lib/mesa/src/vulkan/util/vk_util.h @@ -29,13 +29,15 @@ #include <stdlib.h> #include <string.h> +#include "vk_struct_type_cast.h" + #ifdef __cplusplus extern "C" { #endif /* common inlines and macros for vulkan drivers */ -#include <vulkan/vulkan.h> +#include <vulkan/vulkan_core.h> struct vk_pnext_iterator { VkBaseOutStructure *pos; @@ -269,11 +271,13 @@ __vk_find_struct(void *start, VkStructureType sType) return NULL; } -#define vk_find_struct(__start, __sType) \ - __vk_find_struct((__start), VK_STRUCTURE_TYPE_##__sType) +#define vk_find_struct(__start, __sType) \ + (VK_STRUCTURE_TYPE_##__sType##_cast *)__vk_find_struct( \ + (__start), VK_STRUCTURE_TYPE_##__sType) -#define vk_find_struct_const(__start, __sType) \ - (const void *)__vk_find_struct((void *)(__start), VK_STRUCTURE_TYPE_##__sType) +#define vk_find_struct_const(__start, __sType) \ + (const VK_STRUCTURE_TYPE_##__sType##_cast *)__vk_find_struct( \ + (void *)(__start), VK_STRUCTURE_TYPE_##__sType) static inline void __vk_append_struct(void *start, void *element) @@ -328,14 +332,14 @@ mesa_to_vk_shader_stage(gl_shader_stage mesa_stage) /* iterate over a sequence of indexed multidraws for VK_EXT_multi_draw extension */ /* 'i' must be explicitly declared */ #define vk_foreach_multi_draw_indexed(_draw, _i, _pDrawInfo, _num_draws, _stride) \ - for (const VkMultiDrawIndexedInfoEXT *_draw = (const void*)(_pDrawInfo); \ + for (const VkMultiDrawIndexedInfoEXT *_draw = (const VkMultiDrawIndexedInfoEXT*)(_pDrawInfo); \ (_i) < (_num_draws); \ (_i)++, (_draw) = (const VkMultiDrawIndexedInfoEXT*)((const uint8_t*)(_draw) + (_stride))) /* iterate over a sequence of multidraws for VK_EXT_multi_draw extension */ /* 'i' must be explicitly declared */ #define vk_foreach_multi_draw(_draw, _i, _pDrawInfo, _num_draws, _stride) \ - for (const VkMultiDrawInfoEXT *_draw = (const void*)(_pDrawInfo); \ + for (const VkMultiDrawInfoEXT *_draw = (const VkMultiDrawInfoEXT*)(_pDrawInfo); \ (_i) < (_num_draws); \ (_i)++, (_draw) = (const VkMultiDrawInfoEXT*)((const uint8_t*)(_draw) + (_stride))) |