summaryrefslogtreecommitdiff
path: root/lib/mesa/src/vulkan/util
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2023-11-02 04:53:47 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2023-11-02 04:53:47 +0000
commitb44518130b33cadb5c1d619e9e936ae0e0dbf7cb (patch)
tree6069eb03c39fbc79808a7d94f857118cce75cbe3 /lib/mesa/src/vulkan/util
parent32aeb3c41fedbbd7b11aacfec48e8f699d16bff0 (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.py157
-rw-r--r--lib/mesa/src/vulkan/util/vk_alloc.h2
-rw-r--r--lib/mesa/src/vulkan/util/vk_physical_device_features.py465
-rw-r--r--lib/mesa/src/vulkan/util/vk_util.h18
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)))