From 4ee33d2fbd1e7a072c4d8a6cf8f01c4f96d7483d Mon Sep 17 00:00:00 2001 From: Jon Leech Date: Sat, 17 Aug 2019 15:58:46 -0700 Subject: [PATCH] Update for Vulkan-Docs 1.1.120 --- include/vulkan/vulkan.hpp | 57 ++------ include/vulkan/vulkan_android.h | 9 +- include/vulkan/vulkan_core.h | 36 ++--- include/vulkan/vulkan_fuchsia.h | 9 +- include/vulkan/vulkan_ggp.h | 9 +- include/vulkan/vulkan_ios.h | 9 +- include/vulkan/vulkan_macos.h | 9 +- include/vulkan/vulkan_metal.h | 9 +- include/vulkan/vulkan_vi.h | 9 +- include/vulkan/vulkan_wayland.h | 9 +- include/vulkan/vulkan_win32.h | 9 +- include/vulkan/vulkan_xcb.h | 9 +- include/vulkan/vulkan_xlib.h | 9 +- include/vulkan/vulkan_xlib_xrandr.h | 9 +- registry/cgenerator.py | 74 ++++------- registry/conventions.py | 254 +++++++++++++++++++++++++++++++----- registry/generator.py | 244 ++++++++++++++++++++++++---------- registry/genvk.py | 26 ++-- registry/reg.py | 26 +++- registry/validusage.json | 40 ++++-- registry/vk.xml | 9 +- registry/vkconventions.py | 70 +++------- 22 files changed, 598 insertions(+), 346 deletions(-) diff --git a/include/vulkan/vulkan.hpp b/include/vulkan/vulkan.hpp index f3a7df6..a3fbd2a 100644 --- a/include/vulkan/vulkan.hpp +++ b/include/vulkan/vulkan.hpp @@ -56,7 +56,7 @@ # define VULKAN_HPP_ASSERT assert #endif -static_assert( VK_HEADER_VERSION == 119 , "Wrong VK_HEADER_VERSION!" ); +static_assert( VK_HEADER_VERSION == 120 , "Wrong VK_HEADER_VERSION!" ); // 32-bit vulkan is not typesafe for handles, so don't allow copy constructors on this platform by default. // To enable this feature on 32-bit platforms please define VULKAN_HPP_TYPESAFE_CONVERSION @@ -6017,7 +6017,8 @@ namespace VULKAN_HPP_NAMESPACE enum class ValidationFeatureEnableEXT { eGpuAssisted = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT, - eGpuAssistedReserveBindingSlot = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT + eGpuAssistedReserveBindingSlot = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT, + eBestPractices = VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT }; VULKAN_HPP_INLINE std::string to_string( ValidationFeatureEnableEXT value ) @@ -6026,6 +6027,7 @@ namespace VULKAN_HPP_NAMESPACE { case ValidationFeatureEnableEXT::eGpuAssisted : return "GpuAssisted"; case ValidationFeatureEnableEXT::eGpuAssistedReserveBindingSlot : return "GpuAssistedReserveBindingSlot"; + case ValidationFeatureEnableEXT::eBestPractices : return "BestPractices"; default: return "invalid"; } } @@ -23020,8 +23022,8 @@ namespace VULKAN_HPP_NAMESPACE vk::ClearColorValue color; vk::ClearDepthStencilValue depthStencil; #else - Vkvk::ClearColorValue color; - Vkvk::ClearDepthStencilValue depthStencil; + VkClearColorValue color; + VkClearDepthStencilValue depthStencil; #endif /*VULKAN_HPP_HAS_UNRESTRICTED_UNIONS*/ }; @@ -42563,7 +42565,7 @@ namespace VULKAN_HPP_NAMESPACE uint32_t value32; uint64_t value64; float valueFloat; - Vkvk::Bool32 valueBool; + VkBool32 valueBool; const char* valueString; #endif /*VULKAN_HPP_HAS_UNRESTRICTED_UNIONS*/ }; @@ -52291,49 +52293,6 @@ namespace VULKAN_HPP_NAMESPACE union PipelineExecutableStatisticValueKHR { - PipelineExecutableStatisticValueKHR( vk::Bool32 b32_ = 0 ) - { - b32 = b32_; - } - - PipelineExecutableStatisticValueKHR( int64_t i64_ ) - { - i64 = i64_; - } - - PipelineExecutableStatisticValueKHR( uint64_t u64_ ) - { - u64 = u64_; - } - - PipelineExecutableStatisticValueKHR( double f64_ ) - { - f64 = f64_; - } - - PipelineExecutableStatisticValueKHR & setB32( vk::Bool32 b32_ ) - { - b32 = b32_; - return *this; - } - - PipelineExecutableStatisticValueKHR & setI64( int64_t i64_ ) - { - i64 = i64_; - return *this; - } - - PipelineExecutableStatisticValueKHR & setU64( uint64_t u64_ ) - { - u64 = u64_; - return *this; - } - - PipelineExecutableStatisticValueKHR & setF64( double f64_ ) - { - f64 = f64_; - return *this; - } operator VkPipelineExecutableStatisticValueKHR const&() const { return *reinterpret_cast(this); @@ -52350,7 +52309,7 @@ namespace VULKAN_HPP_NAMESPACE uint64_t u64; double f64; #else - Vkvk::Bool32 b32; + VkBool32 b32; int64_t i64; uint64_t u64; double f64; diff --git a/include/vulkan/vulkan_android.h b/include/vulkan/vulkan_android.h index 1861802..9b8d3e2 100644 --- a/include/vulkan/vulkan_android.h +++ b/include/vulkan/vulkan_android.h @@ -1,10 +1,6 @@ #ifndef VULKAN_ANDROID_H_ #define VULKAN_ANDROID_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_KHR_android_surface 1 struct ANativeWindow; diff --git a/include/vulkan/vulkan_core.h b/include/vulkan/vulkan_core.h index e811beb..888674e 100644 --- a/include/vulkan/vulkan_core.h +++ b/include/vulkan/vulkan_core.h @@ -1,10 +1,6 @@ #ifndef VULKAN_CORE_H_ #define VULKAN_CORE_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_VERSION_1_0 1 #include "vk_platform.h" @@ -43,7 +44,7 @@ extern "C" { #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) // Version of this file -#define VK_HEADER_VERSION 119 +#define VK_HEADER_VERSION 120 #define VK_NULL_HANDLE 0 @@ -8446,6 +8447,15 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV) #define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing" #define VK_SHADER_UNUSED_NV (~0U) +typedef enum VkAccelerationStructureTypeNV { + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = 0, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = 1, + VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV, + VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV, + VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV + 1), + VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkAccelerationStructureTypeNV; + typedef enum VkRayTracingShaderGroupTypeNV { VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = 0, VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = 1, @@ -8465,15 +8475,6 @@ typedef enum VkGeometryTypeNV { VK_GEOMETRY_TYPE_MAX_ENUM_NV = 0x7FFFFFFF } VkGeometryTypeNV; -typedef enum VkAccelerationStructureTypeNV { - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = 0, - VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = 1, - VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV, - VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV, - VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV + 1), - VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkAccelerationStructureTypeNV; - typedef enum VkCopyAccelerationStructureModeNV { VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = 0, VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = 1, @@ -9538,15 +9539,16 @@ typedef struct VkImageStencilUsageCreateInfoEXT { #define VK_EXT_validation_features 1 -#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 1 +#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 2 #define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features" typedef enum VkValidationFeatureEnableEXT { VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0, VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1, + VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2, VK_VALIDATION_FEATURE_ENABLE_BEGIN_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT, - VK_VALIDATION_FEATURE_ENABLE_END_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT, - VK_VALIDATION_FEATURE_ENABLE_RANGE_SIZE_EXT = (VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT + 1), + VK_VALIDATION_FEATURE_ENABLE_END_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT, + VK_VALIDATION_FEATURE_ENABLE_RANGE_SIZE_EXT = (VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT + 1), VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF } VkValidationFeatureEnableEXT; diff --git a/include/vulkan/vulkan_fuchsia.h b/include/vulkan/vulkan_fuchsia.h index 4c62a7c..81ebe55 100644 --- a/include/vulkan/vulkan_fuchsia.h +++ b/include/vulkan/vulkan_fuchsia.h @@ -1,10 +1,6 @@ #ifndef VULKAN_FUCHSIA_H_ #define VULKAN_FUCHSIA_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_FUCHSIA_imagepipe_surface 1 #define VK_FUCHSIA_IMAGEPIPE_SURFACE_SPEC_VERSION 1 diff --git a/include/vulkan/vulkan_ggp.h b/include/vulkan/vulkan_ggp.h index 3d67c4b..fd30613 100644 --- a/include/vulkan/vulkan_ggp.h +++ b/include/vulkan/vulkan_ggp.h @@ -1,10 +1,6 @@ #ifndef VULKAN_GGP_H_ #define VULKAN_GGP_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_GGP_stream_descriptor_surface 1 #define VK_GGP_STREAM_DESCRIPTOR_SURFACE_SPEC_VERSION 1 diff --git a/include/vulkan/vulkan_ios.h b/include/vulkan/vulkan_ios.h index 1846df5..72ef1a8 100644 --- a/include/vulkan/vulkan_ios.h +++ b/include/vulkan/vulkan_ios.h @@ -1,10 +1,6 @@ #ifndef VULKAN_IOS_H_ #define VULKAN_IOS_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_MVK_ios_surface 1 #define VK_MVK_IOS_SURFACE_SPEC_VERSION 2 diff --git a/include/vulkan/vulkan_macos.h b/include/vulkan/vulkan_macos.h index dca623b..e6e5dea 100644 --- a/include/vulkan/vulkan_macos.h +++ b/include/vulkan/vulkan_macos.h @@ -1,10 +1,6 @@ #ifndef VULKAN_MACOS_H_ #define VULKAN_MACOS_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_MVK_macos_surface 1 #define VK_MVK_MACOS_SURFACE_SPEC_VERSION 2 diff --git a/include/vulkan/vulkan_metal.h b/include/vulkan/vulkan_metal.h index 1650523..3dec68c 100644 --- a/include/vulkan/vulkan_metal.h +++ b/include/vulkan/vulkan_metal.h @@ -1,10 +1,6 @@ #ifndef VULKAN_METAL_H_ #define VULKAN_METAL_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_EXT_metal_surface 1 diff --git a/include/vulkan/vulkan_vi.h b/include/vulkan/vulkan_vi.h index 50aa27d..6fb66f9 100644 --- a/include/vulkan/vulkan_vi.h +++ b/include/vulkan/vulkan_vi.h @@ -1,10 +1,6 @@ #ifndef VULKAN_VI_H_ #define VULKAN_VI_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_NN_vi_surface 1 #define VK_NN_VI_SURFACE_SPEC_VERSION 1 diff --git a/include/vulkan/vulkan_wayland.h b/include/vulkan/vulkan_wayland.h index 12a5f04..599d05b 100644 --- a/include/vulkan/vulkan_wayland.h +++ b/include/vulkan/vulkan_wayland.h @@ -1,10 +1,6 @@ #ifndef VULKAN_WAYLAND_H_ #define VULKAN_WAYLAND_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_KHR_wayland_surface 1 #define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6 diff --git a/include/vulkan/vulkan_win32.h b/include/vulkan/vulkan_win32.h index a61a7d8..7e6016e 100644 --- a/include/vulkan/vulkan_win32.h +++ b/include/vulkan/vulkan_win32.h @@ -1,10 +1,6 @@ #ifndef VULKAN_WIN32_H_ #define VULKAN_WIN32_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_KHR_win32_surface 1 #define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6 diff --git a/include/vulkan/vulkan_xcb.h b/include/vulkan/vulkan_xcb.h index 7d6905d..4cc0bc0 100644 --- a/include/vulkan/vulkan_xcb.h +++ b/include/vulkan/vulkan_xcb.h @@ -1,10 +1,6 @@ #ifndef VULKAN_XCB_H_ #define VULKAN_XCB_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_KHR_xcb_surface 1 #define VK_KHR_XCB_SURFACE_SPEC_VERSION 6 diff --git a/include/vulkan/vulkan_xlib.h b/include/vulkan/vulkan_xlib.h index 7a05d29..ee2b48a 100644 --- a/include/vulkan/vulkan_xlib.h +++ b/include/vulkan/vulkan_xlib.h @@ -1,10 +1,6 @@ #ifndef VULKAN_XLIB_H_ #define VULKAN_XLIB_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_KHR_xlib_surface 1 #define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6 diff --git a/include/vulkan/vulkan_xlib_xrandr.h b/include/vulkan/vulkan_xlib_xrandr.h index 3a20953..08c4fd7 100644 --- a/include/vulkan/vulkan_xlib_xrandr.h +++ b/include/vulkan/vulkan_xlib_xrandr.h @@ -1,10 +1,6 @@ #ifndef VULKAN_XLIB_XRANDR_H_ #define VULKAN_XLIB_XRANDR_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* ** Copyright (c) 2015-2019 The Khronos Group Inc. ** @@ -27,6 +23,11 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + #define VK_EXT_acquire_xlib_display 1 #define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1 diff --git a/registry/cgenerator.py b/registry/cgenerator.py index 7f2d9bc..75e03cf 100644 --- a/registry/cgenerator.py +++ b/registry/cgenerator.py @@ -134,15 +134,11 @@ class COutputGenerator(OutputGenerator): 'group', 'bitmask', 'funcpointer', 'struct'] ALL_SECTIONS = TYPE_SECTIONS + ['commandPointer', 'command'] - def __init__(self, - errFile = sys.stderr, - warnFile = sys.stderr, - diagFile = sys.stdout): - OutputGenerator.__init__(self, errFile, warnFile, diagFile) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # Internal state - accumulators for different inner block text self.sections = {section: [] for section in self.ALL_SECTIONS} self.feature_not_empty = False - self.need_platform_include = False self.may_alias = None def beginFile(self, genOpts): @@ -156,16 +152,19 @@ class COutputGenerator(OutputGenerator): write('#ifndef', headerSym, file=self.outFile) write('#define', headerSym, '1', file=self.outFile) self.newline() - write('#ifdef __cplusplus', file=self.outFile) - write('extern "C" {', file=self.outFile) - write('#endif', file=self.outFile) - self.newline() # User-supplied prefix text, if any (list of strings) if genOpts.prefixText: for s in genOpts.prefixText: write(s, file=self.outFile) + # C++ extern wrapper - after prefix lines so they can add includes. + self.newline() + write('#ifdef __cplusplus', file=self.outFile) + write('extern "C" {', file=self.outFile) + write('#endif', file=self.outFile) + self.newline() + def endFile(self): # C-specific # Finish C++ wrapper and multiple inclusion protection @@ -206,14 +205,6 @@ class COutputGenerator(OutputGenerator): self.newline() write('#define', self.featureName, '1', file=self.outFile) for section in self.TYPE_SECTIONS: - # OpenXR: - # If we need the explicit include of the external platform header, - # put it right before the function pointer definitions - if section == "funcpointer" and self.need_platform_include: - write('// Include for OpenXR Platform-Specific Types', file=self.outFile) - write('#include "openxr_platform.h"', file=self.outFile) - self.newline() - self.need_platform_include = False contents = self.sections[section] if contents: write('\n'.join(contents), file=self.outFile) @@ -292,27 +283,19 @@ class COutputGenerator(OutputGenerator): def genProtectString(self, protect_str): protect_if_str = '' protect_end_str = '' - protect_list = [] - if protect_str: - if ',' in protect_str: - protect_list.extend(protect_str.split(",")) - protect_def_str = '' - count = 0 - for protect_define in protect_list: - if count > 0: - protect_def_str += ' &&' - protect_def_str += ' defined(%s)' % protect_define - count = count + 1 - count = count + 1 - protect_if_str = '#if' - protect_if_str += protect_def_str - protect_if_str += '\n' - protect_end_str = '#endif //' - protect_end_str += protect_def_str - protect_end_str += '\n' - else: - protect_if_str += '#ifdef %s\n' % protect_str - protect_end_str += '#endif // %s\n' % protect_str + if not protect_str: + return (protect_if_str, protect_end_str) + + if ',' in protect_str: + protect_list = protect_str.split(",") + protect_defs = ('defined(%s)' % d for d in protect_list) + protect_def_str = ' && '.join(protect_defs) + protect_if_str = '#if %s\n' % protect_def_str + protect_end_str = '#endif // %s\n' % protect_def_str + else: + protect_if_str = '#ifdef %s\n' % protect_str + protect_end_str = '#endif // %s\n' % protect_str + return (protect_if_str, protect_end_str) def typeMayAlias(self, typeName): @@ -326,11 +309,10 @@ class COutputGenerator(OutputGenerator): if data.elem.get('mayalias') == 'true') # Every type mentioned in some other type's parentstruct attribute. - self.may_alias.update(set(x for x in - [otherType.elem.get('parentstruct') - for _, otherType in self.registry.typedict.items()] - if x is not None - )) + parent_structs = (otherType.elem.get('parentstruct') + for otherType in self.registry.typedict.values()) + self.may_alias.update(set(x for x in parent_structs + if x is not None)) return typeName in self.may_alias # Struct (e.g. C "struct" type) generation. @@ -364,9 +346,7 @@ class COutputGenerator(OutputGenerator): body += ' ' + typeName + ' {\n' - targetLen = 0 - for member in typeElem.findall('.//member'): - targetLen = max(targetLen, self.getCParamTypeLength(member)) + targetLen = self.getMaxCParamTypeLength(typeinfo) for member in typeElem.findall('.//member'): body += self.makeCParamDecl(member, targetLen + 4) body += ';\n' diff --git a/registry/conventions.py b/registry/conventions.py index b37a494..8991b17 100644 --- a/registry/conventions.py +++ b/registry/conventions.py @@ -17,35 +17,96 @@ # Base class for working-group-specific style conventions, # used in generation. -from abc import ABCMeta, abstractmethod +from enum import Enum -ABC = ABCMeta('ABC', (object,), {}) +# Type categories that respond "False" to isStructAlwaysValid +# basetype is home to typedefs like ..Bool32 +CATEGORIES_REQUIRING_VALIDATION = set(('handle', + 'enum', + 'bitmask', + 'basetype', + None)) -class ConventionsBase(ABC): +# These are basic C types pulled in via openxr_platform_defines.h +TYPES_KNOWN_ALWAYS_VALID = set(('char', + 'float', + 'int8_t', 'uint8_t', + 'int32_t', 'uint32_t', + 'int64_t', 'uint64_t', + 'size_t', + 'uintptr_t', + 'int', + )) + + +class ProseListFormats(Enum): + """A connective, possibly with a quantifier.""" + AND = 0 + EACH_AND = 1 + OR = 2 + ANY_OR = 3 + + @classmethod + def from_string(cls, s): + if s == 'or': + return cls.OR + if s == 'and': + return cls.AND + return None + + @property + def connective(self): + if self in (ProseListFormats.OR, ProseListFormats.ANY_OR): + return 'or' + return 'and' + + def quantifier(self, n): + """Return the desired quantifier for a list of a given length.""" + if self == ProseListFormats.ANY_OR: + if n > 1: + return 'any of ' + elif self == ProseListFormats.EACH_AND: + if n > 2: + return 'each of ' + if n == 2: + return 'both of ' + return '' + + +class ConventionsBase: """WG-specific conventions.""" - @abstractmethod + def __init__(self): + self._command_prefix = None + self._type_prefix = None + def formatExtension(self, name): - """Mark up a name as an extension for the spec.""" + """Mark up a name as an extension for the spec. + + Must implement.""" raise NotImplementedError @property - @abstractmethod def null(self): """Preferred spelling of NULL.""" raise NotImplementedError - def makeProseList(self, elements, connective='and'): + def makeProseList(self, elements, fmt=ProseListFormats.AND, with_verb=False, *args, **kwargs): """Make a (comma-separated) list for use in prose. Adds a connective (by default, 'and') before the last element if there are more than 1. + Adds the right one of "is" or "are" to the end if with_verb is true. + + Optionally adds a quantifier (like 'any') before a list of 2 or more, + if specified by fmt. + Override with a different method or different call to _implMakeProseList if you want to add a comma for two elements, or not use a serial comma. """ - return self._implMakeProseList(elements, connective) + return self._implMakeProseList(elements, fmt, with_verb, *args, **kwargs) @property def struct_macro(self): @@ -55,20 +116,20 @@ class ConventionsBase(ABC): """ return 'sname:' - def makeStructName(self, name): - """Prepend the appropriate format macro for a structure to a structure type name. - - Uses struct_macro, so just override that if you want to change behavior. - """ - return self.struct_macro + name - @property def external_macro(self): """Get the appropriate format macro for an external type like uint32_t. May override. """ - return 'basetype:' + return 'code:' + + def makeStructName(self, name): + """Prepend the appropriate format macro for a structure to a structure type name. + + Uses struct_macro, so just override that if you want to change behavior. + """ + return self.struct_macro + name def makeExternalTypeName(self, name): """Prepend the appropriate format macro for an external type like uint32_t to a type name. @@ -77,7 +138,7 @@ class ConventionsBase(ABC): """ return self.external_macro + name - def _implMakeProseList(self, elements, connective, comma_for_two_elts=False, serial_comma=True): + def _implMakeProseList(self, elements, fmt, with_verb, comma_for_two_elts=False, serial_comma=True): """Internal-use implementation to make a (comma-separated) list for use in prose. Adds a connective (by default, 'and') @@ -85,48 +146,171 @@ class ConventionsBase(ABC): and only includes commas if there are more than 2 (if comma_for_two_elts is False). + Adds the right one of "is" or "are" to the end if with_verb is true. + + Optionally adds a quantifier (like 'any') before a list of 2 or more, + if specified by fmt. + Don't edit these defaults, override self.makeProseList(). """ assert(serial_comma) # didn't implement what we didn't need + if isinstance(fmt, str): + fmt = ProseListFormats.from_string(fmt) + my_elts = list(elements) if len(my_elts) > 1: - my_elts[-1] = '{} {}'.format(connective, my_elts[-1]) + my_elts[-1] = '{} {}'.format(fmt.connective, my_elts[-1]) if not comma_for_two_elts and len(my_elts) <= 2: - return ' '.join(my_elts) - return ', '.join(my_elts) + prose = ' '.join(my_elts) + else: + prose = ', '.join(my_elts) + + quantifier = fmt.quantifier(len(my_elts)) + + parts = [quantifier, prose] + + if with_verb: + if len(my_elts) > 1: + parts.append(' are') + else: + parts.append(' is') + return ''.join(parts) @property - @abstractmethod def file_suffix(self): """Return suffix of generated Asciidoctor files""" raise NotImplementedError - @abstractmethod - def api_name(self, spectype = None): - """Return API name""" + def api_name(self, spectype=None): + """Return API or specification name for citations in ref pages. + + spectype is the spec this refpage is for. + 'api' (the default value) is the main API Specification. + If an unrecognized spectype is given, returns None. + + Must implement.""" raise NotImplementedError + def should_insert_may_alias_macro(self, genOpts): + """Return true if we should insert a "may alias" macro in this file. + + Only used by OpenXR right now.""" + return False + + @property + def command_prefix(self): + """Return the expected prefix of commands/functions. + + Implemented in terms of api_prefix.""" + if not self._command_prefix: + self._command_prefix = self.api_prefix[:].replace('_', '').lower() + return self._command_prefix + + @property + def type_prefix(self): + """Return the expected prefix of type names. + + Implemented in terms of command_prefix (and in turn, api_prefix).""" + if not self._type_prefix: + self._type_prefix = ''.join( + (self.command_prefix[0:1].upper(), self.command_prefix[1:])) + return self._type_prefix + @property - @abstractmethod def api_prefix(self): - """Return API token prefix""" + """Return API token prefix. + + Typically two uppercase letters followed by an underscore. + + Must implement.""" raise NotImplementedError @property - @abstractmethod def api_version_prefix(self): - """Return API core version token prefix""" - raise NotImplementedError + """Return API core version token prefix. + + Implemented in terms of api_prefix. + + May override.""" + return self.api_prefix + 'VERSION_' @property - @abstractmethod def KHR_prefix(self): - """Return extension name prefix for KHR extensions""" - raise NotImplementedError + """Return extension name prefix for KHR extensions. + + Implemented in terms of api_prefix. + + May override.""" + return self.api_prefix + 'KHR_' @property - @abstractmethod def EXT_prefix(self): - """Return extension name prefix for EXT extensions""" - raise NotImplementedError + """Return extension name prefix for EXT extensions. + + Implemented in terms of api_prefix. + + May override.""" + return self.api_prefix + 'EXT_' + + def writeFeature(self, featureExtraProtect, filename): + """Return True if OutputGenerator.endFeature should write this feature. + + Defaults to always True. + Used in COutputGenerator. + + May override.""" + return True + + def requires_error_validation(self, return_type): + """Return True if the return_type element is an API result code + requiring error validation. + + Defaults to always False. + + May override.""" + return False + + @property + def required_errors(self): + """Return a list of required error codes for validation. + + Defaults to an empty list. + + May override.""" + return [] + + def is_voidpointer_alias(self, tag, text, tail): + """Return True if the declaration components (tag,text,tail) of an + element represents a void * type. + + Defaults to a reasonable implementation. + + May override.""" + return tag == 'type' and text == 'void' and tail.startswith('*') + + def make_voidpointer_alias(self, tail): + """Reformat a void * declaration to include the API alias macro. + + Defaults to a no-op. + + Must override if you actually want to use this feature in your project.""" + return tail + + def category_requires_validation(self, category): + """Return True if the given type 'category' always requires validation. + + Defaults to a reasonable implementation. + + May override.""" + return category in CATEGORIES_REQUIRING_VALIDATION + + def type_always_valid(self, typename): + """Return True if the given type name is always valid (never requires validation). + + This is for things like integers. + + Defaults to a reasonable implementation. + + May override.""" + return typename in TYPES_KNOWN_ALWAYS_VALID diff --git a/registry/generator.py b/registry/generator.py index f62b71f..8573655 100644 --- a/registry/generator.py +++ b/registry/generator.py @@ -18,17 +18,20 @@ from __future__ import unicode_literals import io import os -import re import pdb +import re import sys try: from pathlib import Path except ImportError: from pathlib2 import Path -def write( *args, **kwargs ): - file = kwargs.pop('file',sys.stdout) - end = kwargs.pop('end','\n') +from spec_tools.util import getElemName, getElemType + + +def write(*args, **kwargs): + file = kwargs.pop('file', sys.stdout) + end = kwargs.pop('end', '\n') file.write(' '.join(str(arg) for arg in args)) file.write(end) @@ -83,9 +86,10 @@ def regSortExtensionNumberKey(feature): # then by version number (for features) # then by extension number (for extensions) def regSortFeatures(featureList): - featureList.sort(key = regSortExtensionNumberKey) - featureList.sort(key = regSortFeatureVersionKey) - featureList.sort(key = regSortCategoryKey) + featureList.sort(key=regSortExtensionNumberKey) + featureList.sort(key=regSortFeatureVersionKey) + featureList.sort(key=regSortCategoryKey) + # GeneratorOptions - base class for options used during header production # These options are target language independent, and used by @@ -125,18 +129,18 @@ class GeneratorOptions: """Represents options during header production from an API registry""" def __init__(self, - conventions = None, - filename = None, - directory = '.', - apiname = None, - profile = None, - versions = '.*', - emitversions = '.*', - defaultExtensions = None, - addExtensions = None, - removeExtensions = None, - emitExtensions = None, - sortProcedure = regSortFeatures): + conventions=None, + filename=None, + directory='.', + apiname=None, + profile=None, + versions='.*', + emitversions='.*', + defaultExtensions=None, + addExtensions=None, + removeExtensions=None, + emitExtensions=None, + sortProcedure=regSortFeatures): self.conventions = conventions self.filename = filename self.directory = directory @@ -205,19 +209,19 @@ class OutputGenerator: # categoryToPath - map XML 'category' to include file directory name categoryToPath = { - 'bitmask' : 'flags', - 'enum' : 'enums', - 'funcpointer' : 'funcpointers', - 'handle' : 'handles', - 'define' : 'defines', - 'basetype' : 'basetypes', + 'bitmask': 'flags', + 'enum': 'enums', + 'funcpointer': 'funcpointers', + 'handle': 'handles', + 'define': 'defines', + 'basetype': 'basetypes', } # Constructor def __init__(self, - errFile = sys.stderr, - warnFile = sys.stderr, - diagFile = sys.stdout): + errFile=sys.stderr, + warnFile=sys.stderr, + diagFile=sys.stdout): self.outFile = None self.errFile = errFile self.warnFile = warnFile @@ -227,7 +231,7 @@ class OutputGenerator: self.genOpts = None self.registry = None # Used for extension enum value generation - self.extBase = 1000000000 + self.extBase = 1000000000 self.extBlockSize = 1000 self.madeDirs = {} @@ -295,21 +299,21 @@ class OutputGenerator: bitpos = int(value, 0) numVal = 1 << bitpos value = '0x%08x' % numVal - if( bitpos >= 32 ): + if bitpos >= 32: value = value + 'ULL' self.logMsg('diag', 'Enum', name, '-> bitpos [', numVal, ',', value, ']') return [numVal, value] if 'offset' in elem.keys(): # Obtain values in the mapping from the attributes enumNegative = False - offset = int(elem.get('offset'),0) - extnumber = int(elem.get('extnumber'),0) + offset = int(elem.get('offset'), 0) + extnumber = int(elem.get('extnumber'), 0) extends = elem.get('extends') if 'dir' in elem.keys(): enumNegative = True self.logMsg('diag', 'Enum', name, 'offset =', offset, - 'extnumber =', extnumber, 'extends =', extends, - 'enumNegative =', enumNegative) + 'extnumber =', extnumber, 'extends =', extends, + 'enumNegative =', enumNegative) # Now determine the actual enumerant value, as defined # in the "Layers and Extensions" appendix of the spec. numVal = self.extBase + (extnumber - 1) * self.extBlockSize + offset @@ -346,7 +350,7 @@ class OutputGenerator: # happens when defining the same enum conditionally in # several extension blocks. if (strVal2 == strVal or (numVal is not None and - numVal == numVal2)): + numVal == numVal2)): True # self.logMsg('info', 'checkDuplicateEnums: Duplicate enum (' + name + # ') found with the same value:' + strVal) @@ -364,14 +368,14 @@ class OutputGenerator: try: self.logMsg('warn', 'Two enums found with the same value: ' - + name + ' = ' + name2.get('name') + ' = ' + strVal) + + name + ' = ' + name2.get('name') + ' = ' + strVal) except: pdb.set_trace() # Track this enum to detect followon duplicates - nameMap[name] = [ elem, numVal, strVal ] + nameMap[name] = [elem, numVal, strVal] if numVal is not None: - valueMap[numVal] = [ elem, numVal, strVal ] + valueMap[numVal] = [elem, numVal, strVal] # Add this enum to the list stripped.append(elem) @@ -385,7 +389,7 @@ class OutputGenerator: groupElem = groupinfo.elem if self.genOpts.conventions.constFlagBits and groupElem.get('type') == 'bitmask': - return self.buildEnumCDecl_Bitmask( groupinfo, groupName) + return self.buildEnumCDecl_Bitmask(groupinfo, groupName) else: return self.buildEnumCDecl_Enum(expand, groupinfo, groupName) @@ -406,7 +410,7 @@ class OutputGenerator: # Should catch exceptions here for more complex constructs. Not yet. (_, strVal) = self.enumToValue(elem, True) name = elem.get('name') - body += "static const " + flagTypeName + " " + name + " = " + strVal + ";\n" + body += "static const {} {} = {};\n".format(flagTypeName, name, strVal) # Postfix @@ -418,17 +422,17 @@ class OutputGenerator: # Break the group name into prefix and suffix portions for range # enum generation - expandName = re.sub(r'([0-9a-z_])([A-Z0-9])',r'\1_\2',groupName).upper() + expandName = re.sub(r'([0-9a-z_])([A-Z0-9])', r'\1_\2', groupName).upper() expandPrefix = expandName expandSuffix = '' - expandSuffixMatch = re.search(r'[A-Z][A-Z]+$',groupName) + expandSuffixMatch = re.search(r'[A-Z][A-Z]+$', groupName) if expandSuffixMatch: expandSuffix = '_' + expandSuffixMatch.group() # Strip off the suffix from the prefix expandPrefix = expandName.rsplit(expandSuffix, 1)[0] # Prefix - body = "typedef enum " + groupName + " {\n" + body = ["typedef enum %s {" % groupName] # @@ Should use the type="bitmask" attribute instead isEnum = ('FLAG_BITS' not in expandPrefix) @@ -450,22 +454,22 @@ class OutputGenerator: # them following the numeric values, to allow for aliases. # NOTE: this doesn't do a topological sort yet, so aliases of # aliases can still get in the wrong order. - aliasText = "" + aliasText = [] for elem in enums: # Convert the value to an integer and use that to track min/max. # Values of form -(number) are accepted but nothing more complex. # Should catch exceptions here for more complex constructs. Not yet. - (numVal,strVal) = self.enumToValue(elem, True) + (numVal, strVal) = self.enumToValue(elem, True) name = elem.get('name') # Extension enumerants are only included if they are required if self.isEnumRequired(elem): - decl = " " + name + " = " + strVal + ",\n" + decl = " {} = {},".format(name, strVal) if numVal is not None: - body += decl + body.append(decl) else: - aliasText += decl + aliasText.append(decl) # Don't track min/max for non-numbers (numVal is None) if isEnum and numVal is not None and elem.get('extends') is None: @@ -480,20 +484,21 @@ class OutputGenerator: maxValue = numVal # Now append the non-numeric enumerant values - body += aliasText + body.extend(aliasText) # Generate min/max value tokens and a range-padding enum. Need some # additional padding to generate correct names... if isEnum and expand: - body += " " + expandPrefix + "_BEGIN_RANGE" + expandSuffix + " = " + minName + ",\n" - body += " " + expandPrefix + "_END_RANGE" + expandSuffix + " = " + maxName + ",\n" - body += " " + expandPrefix + "_RANGE_SIZE" + expandSuffix + " = (" + maxName + " - " + minName + " + 1),\n" + body.extend((" {}_BEGIN_RANGE{} = {},".format(expandPrefix, expandSuffix, minName), + " {}_END_RANGE{} = {},".format( + expandPrefix, expandSuffix, maxName), + " {}_RANGE_SIZE{} = ({} - {} + 1),".format(expandPrefix, expandSuffix, maxName, minName))) - # Always generate this to make sure the enumerated type is 32 bits - body += " " + expandPrefix + "_MAX_ENUM" + expandSuffix + " = 0x7FFFFFFF\n" + body.append(" {}_MAX_ENUM{} = 0x7FFFFFFF".format( + expandPrefix, expandSuffix)) # Postfix - body += "} " + groupName + ";" + body.append("} %s;" % groupName) # Determine appropriate section for this declaration if groupElem.get('type') == 'bitmask': @@ -501,7 +506,7 @@ class OutputGenerator: else: section = 'group' - return (section, body) + return (section, '\n'.join(body)) def makeDir(self, path): self.logMsg('diag', 'OutputGenerator::makeDir(' + path + ')') @@ -514,6 +519,10 @@ class OutputGenerator: def beginFile(self, genOpts): self.genOpts = genOpts + self.should_insert_may_alias_macro = \ + self.genOpts.conventions.should_insert_may_alias_macro(self.genOpts) + + self.conventions = genOpts.conventions # Open specified output file. Not done in constructor since a # Generator can be used without writing to a file. @@ -603,13 +612,14 @@ class OutputGenerator: # aligncol - if non-zero, attempt to align the nested element # at this column def makeCParamDecl(self, param, aligncol): - paramdecl = ' ' + noneStr(param.text) + indent = ' ' + paramdecl = indent + noneStr(param.text) for elem in param: text = noneStr(elem.text) tail = noneStr(elem.tail) - if self.genOpts.conventions.is_voidpointer_alias(elem.tag, text, tail): - # OpenXR-specific macro insertion + if self.should_insert_may_alias_macro and self.genOpts.conventions.is_voidpointer_alias(elem.tag, text, tail): + # OpenXR-specific macro insertion - but not in apiinc for the spec tail = self.genOpts.conventions.make_voidpointer_alias(tail) if elem.tag == 'name' and aligncol > 0: self.logMsg('diag', 'Aligning parameter', elem.text, 'to column', self.genOpts.alignFuncParam) @@ -619,17 +629,22 @@ class OutputGenerator: # This works around a problem where very long type names - # longer than the alignment column - would run into the tail # text. - paramdecl = paramdecl.ljust(aligncol-1) + ' ' + paramdecl = paramdecl.ljust(aligncol - 1) + ' ' newLen = len(paramdecl) self.logMsg('diag', 'Adjust length of parameter decl from', oldLen, 'to', newLen, ':', paramdecl) paramdecl += text + tail + if aligncol == 0: + # Squeeze out multiple spaces other than the identation + paramdecl = indent + ' '.join(paramdecl.split()) return paramdecl - # getCParamTypeLength - return the length of the type field is an indented, formatted - # declaration for a or block (e.g. function parameter - # or structure/union member). + # getCParamTypeLength - return the length of the type field in an + # indented, formatted declaration for a or block (e.g. + # function parameter or structure/union member). This relies on the + # presence of the tag; if not present, return zero. # param - Element ( or ) to identify def getCParamTypeLength(self, param): + newLen = 0 paramdecl = ' ' + noneStr(param.text) for elem in param: text = noneStr(elem.text) @@ -646,17 +661,106 @@ class OutputGenerator: return newLen + def getMaxCParamTypeLength(self, info): + """Return the length of the longest type field for a member/parameter. + + info - TypeInfo or CommandInfo. + """ + lengths = (self.getCParamTypeLength(member) + for member in info.getMembers()) + return max(lengths) + + def getHandleParent(self, typename): + """Get the parent of a handle object.""" + info = self.registry.typedict.get(typename) + if info is None: + return None + + elem = info.elem + if elem is not None: + return elem.get('parent') + + return None + + def iterateHandleAncestors(self, typename): + """Iterate through the ancestors of a handle type.""" + current = self.getHandleParent(typename) + while current is not None: + yield current + current = self.getHandleParent(current) + + def getHandleAncestors(self, typename): + """Get the ancestors of a handle object.""" + return list(self.iterateHandleAncestors(typename)) + + def getTypeCategory(self, typename): + """Get the category of a type.""" + info = self.registry.typedict.get(typename) + if info is None: + return None + + elem = info.elem + if elem is not None: + return elem.get('category') + return None + + def isStructAlwaysValid(self, structname): + """Try to do check if a structure is always considered valid (i.e. there's no rules to its acceptance).""" + # A conventions object is required for this call. + if not self.conventions: + raise RuntimeError("To use isStructAlwaysValid, be sure your options include a Conventions object.") + + if self.conventions.type_always_valid(structname): + return True + + category = self.getTypeCategory(structname) + if self.conventions.category_requires_validation(category): + return False + + info = self.registry.typedict.get(structname) + assert(info is not None) + + members = info.getMembers() + + for member in members: + member_name = getElemName(member) + if member_name in (self.conventions.structtype_member_name, + self.conventions.nextpointer_member_name): + return False + + if member.get('noautovalidity'): + return False + + member_type = getElemType(member) + + if member_type in ('void', 'char') or self.paramIsArray(member) or self.paramIsPointer(member): + return False + + if self.conventions.type_always_valid(member_type): + continue + + member_category = self.getTypeCategory(member_type) + + if self.conventions.category_requires_validation(member_category): + return False + + if member_category in ('struct', 'union'): + if self.isStructAlwaysValid(member_type) is False: + return False + + return True + # isEnumRequired(elem) - return True if this element is # required, False otherwise # elem - element to test def isEnumRequired(self, elem): required = elem.get('required') is not None self.logMsg('diag', 'isEnumRequired:', elem.get('name'), - '->', required) + '->', required) return required - #@@@ This code is overridden by equivalent code now run in - #@@@ Registry.generateFeature + # @@@ This code is overridden by equivalent code now run in + # @@@ Registry.generateFeature required = False @@ -707,6 +811,12 @@ class OutputGenerator: else: pdecl += text + tail tdecl += text + tail + + if self.genOpts.alignFuncParam == 0: + # Squeeze out multiple spaces - there is no indentation + pdecl = ' '.join(pdecl.split()) + tdecl = ' '.join(tdecl.split()) + # Now add the parameter declaration list, which is identical # for prototypes and typedefs. Concatenate all the text from # a node without the tags. No tree walking required @@ -732,7 +842,7 @@ class OutputGenerator: else: paramdecl += 'void' paramdecl += ");" - return [ pdecl + indentdecl, tdecl + paramdecl ] + return [pdecl + indentdecl, tdecl + paramdecl] def newline(self): write('', file=self.outFile) diff --git a/registry/genvk.py b/registry/genvk.py index 6355f86..84cad3c 100644 --- a/registry/genvk.py +++ b/registry/genvk.py @@ -48,12 +48,14 @@ def endTimer(timeit, msg): write(msg, endTime - startTime, file=sys.stderr) startTime = None -# Turn a list of strings into a regexp string matching exactly those strings -def makeREstring(list, default = None): - if len(list) > 0 or default is None: - return '^(' + '|'.join(list) + ')$' - else: - return default + +def makeREstring(strings, default=None, strings_are_regex=False): + """Turn a list of strings into a regexp string matching exactly those strings.""" + if strings or default is None: + if not strings_are_regex: + strings = (re.escape(s) for s in strings) + return '^(' + '|'.join(strings) + ')$' + return default # Returns a directory of [ generator function, generator options ] indexed # by specified short names. The generator options incorporate the following @@ -275,8 +277,10 @@ def makeGenOpts(args): allPlatformExtensions += platform[1] - addPlatformExtensionsRE = makeREstring(platform[1] + platform[2]) - emitPlatformExtensionsRE = makeREstring(platform[1]) + addPlatformExtensionsRE = makeREstring( + platform[1] + platform[2], strings_are_regex=True) + emitPlatformExtensionsRE = makeREstring( + platform[1], strings_are_regex=True) opts = CGeneratorOptions( conventions = conventions, @@ -312,7 +316,8 @@ def makeGenOpts(args): # It removes all platform extensions (from the platform headers options # constructed above) as well as any explicitly specified removals. - removeExtensionsPat = makeREstring(allPlatformExtensions + removeExtensions, None) + removeExtensionsPat = makeREstring( + allPlatformExtensions + removeExtensions, None, strings_are_regex=True) genOpts['vulkan_core.h'] = [ COutputGenerator, @@ -533,7 +538,8 @@ if __name__ == '__main__': if args.debug: pdb.run('genTarget(args)') elif args.profile: - import cProfile, pstats + import cProfile + import pstats cProfile.run('genTarget(args)', 'profile.txt') p = pstats.Stats('profile.txt') p.strip_dirs().sort_stats('time').print_stats(50) diff --git a/registry/reg.py b/registry/reg.py index 982c04c..fb30ed8 100644 --- a/registry/reg.py +++ b/registry/reg.py @@ -104,8 +104,8 @@ class BaseInfo: # be different when redefining the same interface in different feature # and/or extension blocks. for key in selfKeys: - if (key != 'extname' and key != 'extnumber' and - (self.elem.get(key) != info.elem.get(key))): + if key not in ('extname', 'extnumber') and \ + (self.elem.get(key) != info.elem.get(key)): return False return True @@ -118,6 +118,10 @@ class TypeInfo(BaseInfo): BaseInfo.__init__(self, elem) self.additionalValidity = [] self.removedValidity = [] + + def getMembers(self): + return self.elem.findall('member') + def resetState(self): BaseInfo.resetState(self) self.additionalValidity = [] @@ -148,6 +152,10 @@ class CmdInfo(BaseInfo): BaseInfo.__init__(self, elem) self.additionalValidity = [] self.removedValidity = [] + + def getParams(self): + return self.elem.findall('param') + def resetState(self): BaseInfo.resetState(self) self.additionalValidity = [] @@ -251,6 +259,7 @@ class Registry: self.emitFeatures = False self.breakPat = None # self.breakPat = re.compile('VkFenceImportFlagBits.*') + self.filename = None def loadElementTree(self, tree): """Load ElementTree into a Registry object and parse it""" @@ -259,6 +268,7 @@ class Registry: def loadFile(self, file): """Load an API registry XML file into a Registry object and parse it""" + self.filename = file self.tree = etree.parse(file) self.parseTree() @@ -450,7 +460,11 @@ class Registry: gi.elem.append(enum) # Remove element from parent tag # This should be a no-op in lxml.etree - elem.remove(enum) + try: + elem.remove(enum) + except ValueError: + # Must be lxml.etree + pass else: self.gen.logMsg('warn', 'NO matching group', groupName, 'for enum', enum.get('name'), 'found.') @@ -500,7 +514,11 @@ class Registry: gi.elem.append(enum) # Remove element from parent tag # This should be a no-op in lxml.etree - elem.remove(enum) + try: + elem.remove(enum) + except ValueError: + # Must be lxml.etree + pass else: self.gen.logMsg('warn', 'NO matching group', groupName, 'for enum', enum.get('name'), 'found.') diff --git a/registry/validusage.json b/registry/validusage.json index 8a2ea3e..9240390 100644 --- a/registry/validusage.json +++ b/registry/validusage.json @@ -1,9 +1,9 @@ { "version info": { "schema version": 2, - "api version": "1.1.119", - "comment": "from git branch: github-master commit: 5a1c484b7e65eb7d83b160f8c92b0cfd77ddbd53", - "date": "2019-08-12 06:32:53Z" + "api version": "1.1.120", + "comment": "from git branch: github-master commit: 521e98405f8587ce6506811125c001f1eda26314", + "date": "2019-08-17 22:33:44Z" }, "validation": { "vkGetInstanceProcAddr": { @@ -717,6 +717,10 @@ { "vuid": "VUID-vkAllocateCommandBuffers-pCommandBuffers-parameter", "text": " pCommandBuffers must be a valid pointer to an array of pAllocateInfo::commandBufferCount VkCommandBuffer handles" + }, + { + "vuid": "VUID-vkAllocateCommandBuffers-pAllocateInfo::commandBufferCount-arraylength", + "text": " The value referenced by pAllocateInfo::commandBufferCount must be greater than 0" } ] }, @@ -863,6 +867,14 @@ "text": " If the inherited queries feature is enabled, queryFlags must be a valid combination of VkQueryControlFlagBits values" }, { + "vuid": "VUID-VkCommandBufferInheritanceInfo-queryFlags-02788", + "text": " If the inherited queries feature is not enabled, queryFlags must be 0" + }, + { + "vuid": "VUID-VkCommandBufferInheritanceInfo-pipelineStatistics-02789", + "text": " If the pipeline statistics queries feature is enabled, pipelineStatistics must be a valid combination of VkQueryPipelineStatisticFlagBits values" + }, + { "vuid": "VUID-VkCommandBufferInheritanceInfo-pipelineStatistics-00058", "text": " If the pipeline statistics queries feature is not enabled, pipelineStatistics must be 0" }, @@ -954,7 +966,7 @@ }, { "vuid": "VUID-vkQueueSubmit-pWaitSemaphores-00068", - "text": " When a semaphore unsignal operation defined by any element of the pWaitSemaphores member of any element of pSubmits executes on queue, no other queue must be waiting on the same semaphore." + "text": " When a semaphore unsignal operation defined by any element of the pWaitSemaphores member of any element of pSubmits executes on queue, there must be no other queues waiting on the same semaphore." }, { "vuid": "VUID-vkQueueSubmit-pWaitSemaphores-00069", @@ -6216,7 +6228,7 @@ "(VK_KHR_pipeline_executable_properties)": [ { "vuid": "VUID-VkPipelineExecutableInfoKHR-executableIndex-03275", - "text": " executableIndex must be less than or equal to the number of executables associated with pipeline as returned in the pExecutableCount parameter of vkGetPipelineExecutablePropertiesKHR." + "text": " executableIndex must be less than the number of executables associated with pipeline as returned in the pExecutableCount parameter of vkGetPipelineExecutablePropertiesKHR." }, { "vuid": "VUID-VkPipelineExecutableInfoKHR-sType-sType", @@ -6288,11 +6300,11 @@ }, { "vuid": "VUID-VkPipelineExecutableInternalRepresentationKHR-name-parameter", - "text": " Any given element of name must be a valid" + "text": " name must be a null-terminated UTF-8 string whose length is less than or equal to VK_MAX_DESCRIPTION_SIZE" }, { "vuid": "VUID-VkPipelineExecutableInternalRepresentationKHR-description-parameter", - "text": " Any given element of description must be a valid" + "text": " description must be a null-terminated UTF-8 string whose length is less than or equal to VK_MAX_DESCRIPTION_SIZE" }, { "vuid": "VUID-VkPipelineExecutableInternalRepresentationKHR-pData-parameter", @@ -6339,8 +6351,8 @@ "text": " sType must be VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD" }, { - "vuid": "VUID-VkPipelineCompilerControlCreateInfoAMD-compilerControlFlags-parameter", - "text": " compilerControlFlags must be a valid combination of VkPipelineCompilerControlFlagBitsAMD values" + "vuid": "VUID-VkPipelineCompilerControlCreateInfoAMD-compilerControlFlags-zerobitmask", + "text": " compilerControlFlags must be 0" } ] }, @@ -9256,7 +9268,7 @@ }, { "vuid": "VUID-VkImageViewHandleInfoNVX-imageView-02656", - "text": " If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, the image that imageView was created from must have been created with the VK_IMAGE_USAGE_SAMPLED_BIT usage bit set" + "text": " If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, the image that imageView was created from must have been created with the VK_IMAGE_USAGE_SAMPLED_BIT usage bit set" }, { "vuid": "VUID-VkImageViewHandleInfoNVX-imageView-02657", @@ -11523,6 +11535,10 @@ { "vuid": "VUID-vkAllocateDescriptorSets-pDescriptorSets-parameter", "text": " pDescriptorSets must be a valid pointer to an array of pAllocateInfo::descriptorSetCount VkDescriptorSet handles" + }, + { + "vuid": "VUID-vkAllocateDescriptorSets-pAllocateInfo::descriptorSetCount-arraylength", + "text": " The value referenced by pAllocateInfo::descriptorSetCount must be greater than 0" } ] }, @@ -20578,7 +20594,7 @@ }, { "vuid": "VUID-vkQueueBindSparse-pWaitSemaphores-01116", - "text": " When a semaphore unsignal operation defined by any element of the pWaitSemaphores member of any element of pBindInfo executes on queue, no other queue must be waiting on the same semaphore." + "text": " When a semaphore unsignal operation defined by any element of the pWaitSemaphores member of any element of pBindInfo executes on queue, there must be no other queues waiting on the same semaphore." }, { "vuid": "VUID-vkQueueBindSparse-pWaitSemaphores-01117", @@ -22670,7 +22686,7 @@ }, { "vuid": "VUID-vkQueuePresentKHR-pWaitSemaphores-01294", - "text": " When a semaphore unsignal operation defined by the elements of the pWaitSemaphores member of pPresentInfo executes on queue, no other queue must be waiting on the same semaphore." + "text": " When a semaphore unsignal operation defined by the elements of the pWaitSemaphores member of pPresentInfo executes on queue, there must be no other queues waiting on the same semaphore." }, { "vuid": "VUID-vkQueuePresentKHR-pWaitSemaphores-01295", diff --git a/registry/vk.xml b/registry/vk.xml index f76c0c8..bc1c63d 100644 --- a/registry/vk.xml +++ b/registry/vk.xml @@ -154,7 +154,7 @@ server. // Vulkan 1.1 version number #define VK_API_VERSION_1_1 VK_MAKE_VERSION(1, 1, 0)// Patch version should always be set to 0 // Version of this file -#define VK_HEADER_VERSION 119 +#define VK_HEADER_VERSION 120 #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; @@ -5040,12 +5040,11 @@ typedef void CAMetalLayer; - Placeholder for validation enums to be defined for VK_EXT_Validation_flags extension - Placeholder for validation feature enable enums to be defined for VK_EXT_validation_features extension + @@ -5055,7 +5054,6 @@ typedef void CAMetalLayer; - Placeholder for validation feature disable enums to be defined for VK_EXT_validation_features extension @@ -10412,6 +10410,7 @@ typedef void CAMetalLayer; + @@ -11156,7 +11155,7 @@ typedef void CAMetalLayer; - + diff --git a/registry/vkconventions.py b/registry/vkconventions.py index 37235c1..7230fa2 100644 --- a/registry/vkconventions.py +++ b/registry/vkconventions.py @@ -22,6 +22,10 @@ import re from conventions import ConventionsBase +# Modified from default implementation - see category_requires_validation() below +CATEGORIES_REQUIRING_VALIDATION = set(('handle', 'enum', 'bitmask')) + + class VulkanConventions(ConventionsBase): def formatExtension(self, name): """Mark up a name as an extension for the spec.""" @@ -38,14 +42,6 @@ class VulkanConventions(ConventionsBase): return False @property - def struct_macro(self): - return 'sname:' - - @property - def external_macro(self): - return 'code:' - - @property def structtype_member_name(self): """Return name of the structure type member""" return 'sType' @@ -89,7 +85,7 @@ class VulkanConventions(ConventionsBase): """Return suffix of generated Asciidoctor files""" return '.txt' - def api_name(self, spectype = 'api'): + def api_name(self, spectype='api'): """Return API or specification name for citations in ref pages.ref pages should link to for @@ -113,21 +109,6 @@ class VulkanConventions(ConventionsBase): return 'VK_' @property - def api_version_prefix(self): - """Return API core version token prefix""" - return 'VK_VERSION_' - - @property - def KHR_prefix(self): - """Return extension name prefix for KHR extensions""" - return 'VK_KHR_' - - @property - def EXT_prefix(self): - """Return extension name prefix for EXT extensions""" - return 'VK_EXT_' - - @property def write_contacts(self): """Return whether contact list should be written to extension appendices""" return True @@ -137,22 +118,10 @@ class VulkanConventions(ConventionsBase): """Return whether refpage include should be written to extension appendices""" return True - def writeFeature(self, featureExtraProtect, filename): - """Returns True if OutputGenerator.endFeature should write this feature. - Used in COutputGenerator - """ - return True - - def requires_error_validation(self, return_type): - """Returns True if the return_type element is an API result code - requiring error validation. - """ - return False - @property - def required_errors(self): - """Return a list of required error codes for validation.""" - return [] + def member_used_for_unique_vuid(self): + """Return the member name used in the VUID-...-...-unique ID.""" + return self.structtype_member_name def is_externsync_command(self, protoname): """Returns True if the protoname element is an API command requiring @@ -167,19 +136,7 @@ class VulkanConventions(ConventionsBase): """ return name[0:2].lower() == 'vk' or name[0:6] == 'PFN_vk' - def is_voidpointer_alias(self, tag, text, tail): - """Return True if the declaration components (tag,text,tail) of an - element represents a void * type - """ - return tag == 'type' and text == 'void' and tail.startswith('*') - - def make_voidpointer_alias(self, tail): - """Reformat a void * declaration to include the API alias macro. - Vulkan doesn't have an API alias macro, so do nothing. - """ - return tail - - def specURL(self, spectype = 'api'): + def specURL(self, spectype='api'): """Return public registry URL which ref pages should link to for the current all-extensions HTML specification, so xrefs in the asciidoc source that aren't to ref pages can link into it @@ -232,3 +189,12 @@ class VulkanConventions(ConventionsBase): """ return ('scripts', 'style') + @property + def zero(self): + return '`0`' + + def category_requires_validation(self, category): + """Return True if the given type 'category' always requires validation. + + Overridden because Vulkan doesn't require "valid" text for basetype in the spec right now.""" + return category in CATEGORIES_REQUIRING_VALIDATION -- 2.7.4