comparison fuhtark_test/Vulkan-Headers-1.4.334/registry/vkconventions.py @ 1501:f40d9d814c08 default tip

did: correct vulkan-api generator
author sam <sam@basx.dev>
date Wed, 26 Nov 2025 23:34:29 +0700
parents
children
comparison
equal deleted inserted replaced
1500:91c8c3b7cbf0 1501:f40d9d814c08
1 #!/usr/bin/env python3 -i
2 #
3 # Copyright 2013-2025 The Khronos Group Inc.
4 #
5 # SPDX-License-Identifier: Apache-2.0
6
7 # Working-group-specific style conventions,
8 # used in generation.
9
10 import re
11 import os
12
13 from spec_tools.conventions import ConventionsBase
14
15 # Modified from default implementation - see category_requires_validation() below
16 CATEGORIES_REQUIRING_VALIDATION = set(('handle', 'enum', 'bitmask'))
17
18 # Tokenize into "words" for structure types, approximately per spec "Implicit Valid Usage" section 2.7.2
19 # This first set is for things we recognize explicitly as words,
20 # as exceptions to the general regex.
21 # Ideally these would be listed in the spec as exceptions, as OpenXR does.
22 SPECIAL_WORDS = set((
23 '16Bit', # VkPhysicalDevice16BitStorageFeatures
24 '2D', # VkPhysicalDeviceImage2DViewOf3DFeaturesEXT
25 '3D', # VkPhysicalDeviceImage2DViewOf3DFeaturesEXT
26 '8Bit', # VkPhysicalDevice8BitStorageFeaturesKHR
27 'AABB', # VkGeometryAABBNV
28 'ASTC', # VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT
29 'D3D12', # VkD3D12FenceSubmitInfoKHR
30 'Float16', # VkPhysicalDeviceShaderFloat16Int8FeaturesKHR
31 'Bfloat16', # VkPhysicalDeviceShaderBfloat16FeaturesKHR
32 'Float8', # VkPhysicalDeviceShaderFloat8FeaturesEXT
33 'ImagePipe', # VkImagePipeSurfaceCreateInfoFUCHSIA
34 'Int64', # VkPhysicalDeviceShaderAtomicInt64FeaturesKHR
35 'Int8', # VkPhysicalDeviceShaderFloat16Int8FeaturesKHR
36 'MacOS', # VkMacOSSurfaceCreateInfoMVK
37 'RGBA10X6', # VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT
38 'Uint8', # VkPhysicalDeviceIndexTypeUint8FeaturesEXT
39 'Win32', # VkWin32SurfaceCreateInfoKHR
40 ))
41 # A regex to match any of the SPECIAL_WORDS
42 EXCEPTION_PATTERN = r'(?P<exception>{})'.format(
43 '|'.join(f'({re.escape(w)})' for w in SPECIAL_WORDS))
44 MAIN_RE = re.compile(
45 # the negative lookahead is to prevent the all-caps pattern from being too greedy.
46 r'({}|([0-9]+)|([A-Z][a-z]+)|([A-Z][A-Z]*(?![a-z])))'.format(EXCEPTION_PATTERN))
47
48
49 class VulkanConventions(ConventionsBase):
50 @property
51 def null(self):
52 """Preferred spelling of NULL."""
53 return '`NULL`'
54
55 def formatVersion(self, name, apivariant, major, minor):
56 """Mark up an API version name as a link in the spec."""
57 version = f'{major}.{minor}'
58 if apivariant == 'VKSC':
59 # Vulkan SC has a different anchor pattern for version appendices
60 if version == '1.0':
61 return 'Vulkan SC 1.0'
62 else:
63 return f'<<versions-sc-{version}, Vulkan SC Version {version}>>'
64 else:
65 return f'<<versions-{version}, Vulkan Version {version}>>'
66
67 def formatExtension(self, name):
68 """Mark up an extension name as a link in the spec."""
69 return f'apiext:{name}'
70
71 @property
72 def struct_macro(self):
73 """Get the appropriate format macro for a structure.
74
75 Primarily affects generated valid usage statements.
76 """
77
78 return 'slink:'
79
80 @property
81 def constFlagBits(self):
82 """Returns True if static const flag bits should be generated, False if an enumerated type should be generated."""
83 return False
84
85 @property
86 def structtype_member_name(self):
87 """Return name of the structure type member"""
88 return 'sType'
89
90 @property
91 def nextpointer_member_name(self):
92 """Return name of the structure pointer chain member"""
93 return 'pNext'
94
95 @property
96 def valid_pointer_prefix(self):
97 """Return prefix to pointers which must themselves be valid"""
98 return 'valid'
99
100 def is_structure_type_member(self, paramtype, paramname):
101 """Determine if member type and name match the structure type member."""
102 return paramtype == 'VkStructureType' and paramname == self.structtype_member_name
103
104 def is_nextpointer_member(self, paramtype, paramname):
105 """Determine if member type and name match the next pointer chain member."""
106 return paramtype == 'void' and paramname == self.nextpointer_member_name
107
108 def generate_structure_type_from_name(self, structname):
109 """Generate a structure type name, like VK_STRUCTURE_TYPE_CREATE_INSTANCE_INFO"""
110
111 structure_type_parts = []
112 # Tokenize into "words"
113 for elem in MAIN_RE.findall(structname):
114 word = elem[0]
115 if word == 'Vk':
116 structure_type_parts.append('VK_STRUCTURE_TYPE')
117 else:
118 structure_type_parts.append(word.upper())
119 name = '_'.join(structure_type_parts)
120
121 # The simple-minded rules need modification for some structure names
122 subpats = [
123 [ r'_H_(26[45])_', r'_H\1_' ],
124 [ r'_VP_9_', r'_VP9_' ],
125 [ r'_AV_1_', r'_AV1_' ],
126 [ r'_VULKAN_([0-9])([0-9])_', r'_VULKAN_\1_\2_' ],
127 [ r'_VULKAN_SC_([0-9])([0-9])_',r'_VULKAN_SC_\1_\2_' ],
128 [ r'_DIRECT_FB_', r'_DIRECTFB_' ],
129 [ r'_VULKAN_SC_10', r'_VULKAN_SC_1_0' ],
130
131 ]
132
133 for subpat in subpats:
134 name = re.sub(subpat[0], subpat[1], name)
135 return name
136
137 @property
138 def warning_comment(self):
139 """Return warning comment to be placed in header of generated Asciidoctor files"""
140 return '// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry'
141
142 @property
143 def file_suffix(self):
144 """Return suffix of generated Asciidoctor files"""
145 return '.adoc'
146
147 def api_name(self, spectype='api'):
148 """Return API or specification name for citations in ref pages.ref
149 pages should link to for
150
151 spectype is the spec this refpage is for: 'api' is the Vulkan API
152 Specification. Defaults to 'api'. If an unrecognized spectype is
153 given, returns None.
154 """
155 if spectype == 'api' or spectype is None:
156 return 'Vulkan'
157 else:
158 return None
159
160 @property
161 def api_prefix(self):
162 """Return API token prefix"""
163 return 'VK_'
164
165 @property
166 def write_contacts(self):
167 """Return whether contact list should be written to extension appendices"""
168 return True
169
170 @property
171 def write_refpage_include(self):
172 """Return whether refpage include should be written to extension appendices"""
173 return True
174
175 @property
176 def member_used_for_unique_vuid(self):
177 """Return the member name used in the VUID-...-...-unique ID."""
178 return self.structtype_member_name
179
180 def is_externsync_command(self, protoname):
181 """Returns True if the protoname element is an API command requiring
182 external synchronization
183 """
184 return protoname is not None and 'vkCmd' in protoname
185
186 def is_api_name(self, name):
187 """Returns True if name is in the reserved API namespace.
188 For Vulkan, these are names with a case-insensitive 'vk' prefix, or
189 a 'PFN_vk' function pointer type prefix.
190 """
191 return name[0:2].lower() == 'vk' or name.startswith('PFN_vk')
192
193 def specURL(self, spectype='api'):
194 """Return public registry URL which ref pages should link to for the
195 current all-extensions HTML specification, so xrefs in the
196 asciidoc source that are not to ref pages can link into it
197 instead. N.b. this may need to change on a per-refpage basis if
198 there are multiple documents involved.
199 """
200 return 'https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html'
201
202 @property
203 def xml_api_name(self):
204 """Return the name used in the default API XML registry for the default API"""
205 return 'vulkan'
206
207 @property
208 def registry_path(self):
209 """Return relpath to the default API XML registry in this project."""
210 return 'xml/vk.xml'
211
212 @property
213 def specification_path(self):
214 """Return relpath to the Asciidoctor specification sources in this project."""
215 return '{generated}/meta'
216
217 @property
218 def special_use_section_anchor(self):
219 """Return asciidoctor anchor name in the API Specification of the
220 section describing extension special uses in detail."""
221 return 'extendingvulkan-compatibility-specialuse'
222
223 @property
224 def extension_index_prefixes(self):
225 """Return a list of extension prefixes used to group extension refpages."""
226 return ['VK_KHR', 'VK_EXT', 'VK']
227
228 @property
229 def unified_flag_refpages(self):
230 """Return True if Flags/FlagBits refpages are unified, False if
231 they are separate.
232 """
233 return False
234
235 @property
236 def spec_reflow_path(self):
237 """Return the path to the spec source folder to reflow"""
238 return os.getcwd()
239
240 @property
241 def spec_no_reflow_dirs(self):
242 """Return a set of directories not to automatically descend into
243 when reflowing spec text
244 """
245 return ('scripts', 'style')
246
247 @property
248 def zero(self):
249 return '`0`'
250
251 def category_requires_validation(self, category):
252 """Return True if the given type 'category' always requires validation.
253
254 Overridden because Vulkan does not require "valid" text for basetype
255 in the spec right now."""
256 return category in CATEGORIES_REQUIRING_VALIDATION
257
258 @property
259 def should_skip_checking_codes(self):
260 """Return True if more than the basic validation of return codes should
261 be skipped for a command.
262
263 Vulkan mostly relies on the validation layers rather than API
264 builtin error checking, so these checks are not appropriate.
265
266 For example, passing in a VkFormat parameter will not potentially
267 generate a VK_ERROR_FORMAT_NOT_SUPPORTED code."""
268
269 return True
270
271 def extension_file_path(self, name):
272 """Return file path to an extension appendix relative to a directory
273 containing all such appendices.
274 - name - extension name"""
275
276 return f'{name}{self.file_suffix}'
277
278 def valid_flag_bit(self, bitpos):
279 """Return True if bitpos is an allowed numeric bit position for
280 an API flag bit.
281
282 Vulkan uses 32 bit Vk*Flags types, and assumes C compilers may
283 cause Vk*FlagBits values with bit 31 set to result in a 64 bit
284 enumerated type, so disallows such flags."""
285 return bitpos >= 0 and bitpos < 31
286
287 @property
288 def extra_refpage_headers(self):
289 """Return any extra text to add to refpage headers."""
290 return 'include::{config}/attribs.adoc[]'
291
292 @property
293 def extra_refpage_body(self):
294 """Return any extra text (following the title) for generated
295 reference pages."""
296 return 'include::{generated}/specattribs.adoc[]'
297
298
299 class VulkanSCConventions(VulkanConventions):
300
301 def specURL(self, spectype='api'):
302 """Return public registry URL which ref pages should link to for the
303 current all-extensions HTML specification, so xrefs in the
304 asciidoc source that are not to ref pages can link into it
305 instead. N.b. this may need to change on a per-refpage basis if
306 there are multiple documents involved.
307 """
308 return 'https://registry.khronos.org/vulkansc/specs/1.0-extensions/html/vkspec.html'
309
310 @property
311 def xml_api_name(self):
312 """Return the name used in the default API XML registry for the default API"""
313 return 'vulkansc'
314
315 class VulkanBaseConventions(VulkanConventions):
316
317 def specURL(self, spectype='api'):
318 """Return public registry URL which ref pages should link to for the
319 current all-extensions HTML specification, so xrefs in the
320 asciidoc source that are not to ref pages can link into it
321 instead. N.b. this may need to change on a per-refpage basis if
322 there are multiple documents involved.
323 """
324 return 'https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html'
325
326 @property
327 def xml_api_name(self):
328 """Return the name used in the default API XML registry for the default API"""
329 return 'vulkanbase'
330