1e5c31af7Sopenharmony_ci# -*- coding: utf-8 -*-
2e5c31af7Sopenharmony_ci
3e5c31af7Sopenharmony_ci#-------------------------------------------------------------------------
4e5c31af7Sopenharmony_ci# Vulkan CTS
5e5c31af7Sopenharmony_ci# ----------
6e5c31af7Sopenharmony_ci#
7e5c31af7Sopenharmony_ci# Copyright (c) 2015 Google Inc.
8e5c31af7Sopenharmony_ci#
9e5c31af7Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
10e5c31af7Sopenharmony_ci# you may not use this file except in compliance with the License.
11e5c31af7Sopenharmony_ci# You may obtain a copy of the License at
12e5c31af7Sopenharmony_ci#
13e5c31af7Sopenharmony_ci#      http://www.apache.org/licenses/LICENSE-2.0
14e5c31af7Sopenharmony_ci#
15e5c31af7Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
16e5c31af7Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
17e5c31af7Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18e5c31af7Sopenharmony_ci# See the License for the specific language governing permissions and
19e5c31af7Sopenharmony_ci# limitations under the License.
20e5c31af7Sopenharmony_ci#
21e5c31af7Sopenharmony_ci#-------------------------------------------------------------------------
22e5c31af7Sopenharmony_ci
23e5c31af7Sopenharmony_ciimport os
24e5c31af7Sopenharmony_ciimport re
25e5c31af7Sopenharmony_ciimport sys
26e5c31af7Sopenharmony_ciimport glob
27e5c31af7Sopenharmony_ciimport json
28e5c31af7Sopenharmony_ciimport argparse
29e5c31af7Sopenharmony_ciimport datetime
30e5c31af7Sopenharmony_ciimport collections
31e5c31af7Sopenharmony_cifrom lxml import etree
32e5c31af7Sopenharmony_ci
33e5c31af7Sopenharmony_ciscriptPath = os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts")
34e5c31af7Sopenharmony_cisys.path.insert(0, scriptPath)
35e5c31af7Sopenharmony_ci
36e5c31af7Sopenharmony_cifrom ctsbuild.common import DEQP_DIR, execute
37e5c31af7Sopenharmony_cifrom khr_util.format import indentLines, writeInlFile
38e5c31af7Sopenharmony_ci
39e5c31af7Sopenharmony_cisys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "vulkan-docs", "src", "scripts"))
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_cifrom reg import stripNonmatchingAPIs
42e5c31af7Sopenharmony_ci
43e5c31af7Sopenharmony_ciVULKAN_XML_DIR				= os.path.join(os.path.dirname(__file__), "..", "..", "vulkan-docs", "src", "xml")
44e5c31af7Sopenharmony_ciSCRIPTS_SRC_DIR				= os.path.join(os.path.dirname(__file__), "src")
45e5c31af7Sopenharmony_ciDEFAULT_OUTPUT_DIR			= { "" :	os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan", "generated", "vulkan"),
46e5c31af7Sopenharmony_ci								"SC" :	os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan", "generated", "vulkansc") }
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_ciINL_HEADER = """\
49e5c31af7Sopenharmony_ci/* WARNING: This is auto-generated file. Do not modify, since changes will
50e5c31af7Sopenharmony_ci * be lost! Modify the generating script instead.
51e5c31af7Sopenharmony_ci * This file was generated by /scripts/gen_framework.py
52e5c31af7Sopenharmony_ci */\
53e5c31af7Sopenharmony_ci
54e5c31af7Sopenharmony_ci"""
55e5c31af7Sopenharmony_ci
56e5c31af7Sopenharmony_ciDEFINITIONS			= {
57e5c31af7Sopenharmony_ci	"VK_MAX_PHYSICAL_DEVICE_NAME_SIZE":		"size_t",
58e5c31af7Sopenharmony_ci	"VK_MAX_EXTENSION_NAME_SIZE":			"size_t",
59e5c31af7Sopenharmony_ci	"VK_MAX_DRIVER_NAME_SIZE":				"size_t",
60e5c31af7Sopenharmony_ci	"VK_MAX_DRIVER_INFO_SIZE":				"size_t",
61e5c31af7Sopenharmony_ci	"VK_UUID_SIZE":							"size_t",
62e5c31af7Sopenharmony_ci	"VK_LUID_SIZE":							"size_t",
63e5c31af7Sopenharmony_ci	"VK_MAX_MEMORY_TYPES":					"size_t",
64e5c31af7Sopenharmony_ci	"VK_MAX_MEMORY_HEAPS":					"size_t",
65e5c31af7Sopenharmony_ci	"VK_MAX_DESCRIPTION_SIZE":				"size_t",
66e5c31af7Sopenharmony_ci	"VK_MAX_DEVICE_GROUP_SIZE":				"size_t",
67e5c31af7Sopenharmony_ci	"VK_ATTACHMENT_UNUSED":					"uint32_t",
68e5c31af7Sopenharmony_ci	"VK_SUBPASS_EXTERNAL":					"uint32_t",
69e5c31af7Sopenharmony_ci	"VK_QUEUE_FAMILY_IGNORED":				"uint32_t",
70e5c31af7Sopenharmony_ci	"VK_QUEUE_FAMILY_EXTERNAL":				"uint32_t",
71e5c31af7Sopenharmony_ci	"VK_REMAINING_MIP_LEVELS":				"uint32_t",
72e5c31af7Sopenharmony_ci	"VK_REMAINING_ARRAY_LAYERS":			"uint32_t",
73e5c31af7Sopenharmony_ci	"VK_WHOLE_SIZE":						"vk::VkDeviceSize",
74e5c31af7Sopenharmony_ci	"VK_TRUE":								"vk::VkBool32",
75e5c31af7Sopenharmony_ci	"VK_FALSE":								"vk::VkBool32",
76e5c31af7Sopenharmony_ci}
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_ciPLATFORM_TYPES		= [
79e5c31af7Sopenharmony_ci	# VK_KHR_xlib_surface
80e5c31af7Sopenharmony_ci	(["Display","*"],						["XlibDisplayPtr"],				"void*"),
81e5c31af7Sopenharmony_ci	(["Window"],							["XlibWindow"],					"uintptr_t",),
82e5c31af7Sopenharmony_ci	(["VisualID"],							["XlibVisualID"],				"uint32_t"),
83e5c31af7Sopenharmony_ci
84e5c31af7Sopenharmony_ci	# VK_KHR_xcb_surface
85e5c31af7Sopenharmony_ci	(["xcb_connection_t", "*"],				["XcbConnectionPtr"],			"void*"),
86e5c31af7Sopenharmony_ci	(["xcb_window_t"],						["XcbWindow"],					"uintptr_t"),
87e5c31af7Sopenharmony_ci	(["xcb_visualid_t"],					["XcbVisualid"],				"uint32_t"),
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_ci	# VK_KHR_wayland_surface
90e5c31af7Sopenharmony_ci	(["struct", "wl_display","*"],			["WaylandDisplayPtr"],			"void*"),
91e5c31af7Sopenharmony_ci	(["struct", "wl_surface", "*"],			["WaylandSurfacePtr"],			"void*"),
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_ci	# VK_KHR_mir_surface
94e5c31af7Sopenharmony_ci	(["MirConnection", "*"],				["MirConnectionPtr"],			"void*"),
95e5c31af7Sopenharmony_ci	(["MirSurface", "*"],					["MirSurfacePtr"],				"void*"),
96e5c31af7Sopenharmony_ci
97e5c31af7Sopenharmony_ci	# VK_KHR_android_surface
98e5c31af7Sopenharmony_ci	(["ANativeWindow", "*"],				["AndroidNativeWindowPtr"],		"void*"),
99e5c31af7Sopenharmony_ci
100e5c31af7Sopenharmony_ci	# VK_KHR_win32_surface
101e5c31af7Sopenharmony_ci	(["HINSTANCE"],							["Win32InstanceHandle"],		"void*"),
102e5c31af7Sopenharmony_ci	(["HWND"],								["Win32WindowHandle"],			"void*"),
103e5c31af7Sopenharmony_ci	(["HANDLE"],							["Win32Handle"],				"void*"),
104e5c31af7Sopenharmony_ci	(["const", "SECURITY_ATTRIBUTES", "*"],	["Win32SecurityAttributesPtr"],	"const void*"),
105e5c31af7Sopenharmony_ci	(["AHardwareBuffer", "*"],				["AndroidHardwareBufferPtr"],	"void*"),
106e5c31af7Sopenharmony_ci	(["HMONITOR"],							["Win32MonitorHandle"],			"void*"),
107e5c31af7Sopenharmony_ci	(["LPCWSTR"],							["Win32LPCWSTR"],				"const void*"),
108e5c31af7Sopenharmony_ci
109e5c31af7Sopenharmony_ci	# VK_EXT_acquire_xlib_display
110e5c31af7Sopenharmony_ci	(["RROutput"],							["RROutput"],					"void*"),
111e5c31af7Sopenharmony_ci
112e5c31af7Sopenharmony_ci	(["zx_handle_t"],						["zx_handle_t"],				"uint32_t"),
113e5c31af7Sopenharmony_ci	(["GgpFrameToken"],						["GgpFrameToken"],				"int32_t"),
114e5c31af7Sopenharmony_ci	(["GgpStreamDescriptor"],				["GgpStreamDescriptor"],		"int32_t"),
115e5c31af7Sopenharmony_ci	(["CAMetalLayer"],						["CAMetalLayer"],				"void*"),
116e5c31af7Sopenharmony_ci	(["struct", "_screen_context", "*"],	["QNXScreenContextPtr"],		"void*"),
117e5c31af7Sopenharmony_ci	(["struct", "_screen_window", "*"],		["QNXScreenWindowPtr"],			"void*"),
118e5c31af7Sopenharmony_ci
119e5c31af7Sopenharmony_ci	# VK_EXT_metal_objects
120e5c31af7Sopenharmony_ci	(["MTLDevice_id"],						["MTLDevice_id"],				"void*"),
121e5c31af7Sopenharmony_ci	(["MTLCommandQueue_id"],				["MTLCommandQueue_id"],			"void*"),
122e5c31af7Sopenharmony_ci	(["MTLBuffer_id"],						["MTLBuffer_id"],				"void*"),
123e5c31af7Sopenharmony_ci	(["MTLTexture_id"],						["MTLTexture_id"],				"void*"),
124e5c31af7Sopenharmony_ci	(["IOSurfaceRef"],						["IOSurfaceRef"],				"void*"),
125e5c31af7Sopenharmony_ci	(["MTLSharedEvent_id"],					["MTLSharedEvent_id"],			"void*"),
126e5c31af7Sopenharmony_ci
127e5c31af7Sopenharmony_ci	# VK_NV_external_sci_sync
128e5c31af7Sopenharmony_ci	(["NvSciBufObj"],						["NvSciBufObj"],				"int"),
129e5c31af7Sopenharmony_ci	(["NvSciSyncObj"],						["NvSciSyncObj"],				"int"),
130e5c31af7Sopenharmony_ci	(["NvSciSyncFence"],					["NvSciSyncFence"],				"int"),
131e5c31af7Sopenharmony_ci	(["NvSciBufAttrList"],					["NvSciBufAttrList"],			"int"),
132e5c31af7Sopenharmony_ci	(["NvSciSyncAttrList"],					["NvSciSyncAttrList"],			"int"),
133e5c31af7Sopenharmony_ci]
134e5c31af7Sopenharmony_ci
135e5c31af7Sopenharmony_ciPLATFORM_TYPE_NAMESPACE	= "pt"
136e5c31af7Sopenharmony_ci
137e5c31af7Sopenharmony_ciTYPE_SUBSTITUTIONS		= [
138e5c31af7Sopenharmony_ci	# Platform-specific
139e5c31af7Sopenharmony_ci	("DWORD",		"uint32_t"),
140e5c31af7Sopenharmony_ci	("HANDLE*",		PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"),
141e5c31af7Sopenharmony_ci]
142e5c31af7Sopenharmony_ci
143e5c31af7Sopenharmony_ciEXTENSION_POSTFIXES_STANDARD	= ["KHR", "EXT"]
144e5c31af7Sopenharmony_ciEXTENSION_POSTFIXES_VENDOR		= ["AMD", "ARM", "NV", 'INTEL', "NVX", "KHX", "NN", "MVK", "FUCHSIA", 'QCOM', "GGP", "QNX", "ANDROID", 'VALVE', 'HUAWEI']
145e5c31af7Sopenharmony_ciEXTENSION_POSTFIXES				= EXTENSION_POSTFIXES_STANDARD + EXTENSION_POSTFIXES_VENDOR
146e5c31af7Sopenharmony_ci
147e5c31af7Sopenharmony_cidef substituteType(object):		# both CompositeMember and FunctionArgument can be passed to this function
148e5c31af7Sopenharmony_ci	for src, dst in TYPE_SUBSTITUTIONS:
149e5c31af7Sopenharmony_ci		object.type = object.type.replace(src, dst)
150e5c31af7Sopenharmony_ci	for platformType, substitute, _ in PLATFORM_TYPES:
151e5c31af7Sopenharmony_ci		platformTypeName = platformType[0]
152e5c31af7Sopenharmony_ci		platformTypeName = platformType[-2] if "*" in platformType else platformType[0]
153e5c31af7Sopenharmony_ci		if object.type == platformTypeName:
154e5c31af7Sopenharmony_ci			object.type = PLATFORM_TYPE_NAMESPACE + '::' + substitute[0]
155e5c31af7Sopenharmony_ci			object.qualifiers = None if 'struct' in platformType else object.qualifiers
156e5c31af7Sopenharmony_ci			object.qualifiers = None if 'const' in platformType else object.qualifiers
157e5c31af7Sopenharmony_ci			if "*" in platformType:
158e5c31af7Sopenharmony_ci				object.pointer = "*" if object.pointer == "**" else None
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_ciclass Define:
161e5c31af7Sopenharmony_ci	def __init__ (self, name, aType, alias, value):
162e5c31af7Sopenharmony_ci		self.name			= name
163e5c31af7Sopenharmony_ci		self.type			= aType
164e5c31af7Sopenharmony_ci		self.alias			= alias
165e5c31af7Sopenharmony_ci		self.value			= value
166e5c31af7Sopenharmony_ci
167e5c31af7Sopenharmony_ciclass Handle:
168e5c31af7Sopenharmony_ci	def __init__ (self, name, aType, alias, parent, objtypeenum):
169e5c31af7Sopenharmony_ci		self.name			= name
170e5c31af7Sopenharmony_ci		self.type			= aType
171e5c31af7Sopenharmony_ci		self.alias			= alias
172e5c31af7Sopenharmony_ci		self.parent			= parent
173e5c31af7Sopenharmony_ci		self.objtypeenum	= objtypeenum
174e5c31af7Sopenharmony_ci
175e5c31af7Sopenharmony_ciclass Bitmask:
176e5c31af7Sopenharmony_ci	def __init__ (self, name, aType, requires, bitvalues):
177e5c31af7Sopenharmony_ci		self.name		= name
178e5c31af7Sopenharmony_ci		self.type		= aType
179e5c31af7Sopenharmony_ci		self.alias		= None					# initialy None but may be filled while parsing next tag
180e5c31af7Sopenharmony_ci		self.requires	= requires
181e5c31af7Sopenharmony_ci		self.bitvalues	= bitvalues
182e5c31af7Sopenharmony_ci
183e5c31af7Sopenharmony_ciclass Enumerator:
184e5c31af7Sopenharmony_ci	def __init__ (self, name, value, bitpos):
185e5c31af7Sopenharmony_ci		self.name		= name
186e5c31af7Sopenharmony_ci		self.aliasList	= []					# list of strings
187e5c31af7Sopenharmony_ci		self.value		= value					# some enums specify value and some bitpos
188e5c31af7Sopenharmony_ci		self.bitpos		= bitpos
189e5c31af7Sopenharmony_ci		self.extension	= None					# name of extension that added this enumerator
190e5c31af7Sopenharmony_ci
191e5c31af7Sopenharmony_ciclass Enum:
192e5c31af7Sopenharmony_ci	def __init__ (self, name):
193e5c31af7Sopenharmony_ci		self.name				= name
194e5c31af7Sopenharmony_ci		self.alias				= None			# name of enum alias or None
195e5c31af7Sopenharmony_ci		self.type				= None			# enum or bitmask
196e5c31af7Sopenharmony_ci		self.bitwidth			= "32"
197e5c31af7Sopenharmony_ci		self.enumeratorList		= []			# list of Enumerator objects
198e5c31af7Sopenharmony_ci
199e5c31af7Sopenharmony_ci	def areValuesLinear (self):
200e5c31af7Sopenharmony_ci		if self.type == 'bitmask':
201e5c31af7Sopenharmony_ci			return False
202e5c31af7Sopenharmony_ci		curIndex = 0
203e5c31af7Sopenharmony_ci		for enumerator in self.enumeratorList:
204e5c31af7Sopenharmony_ci			intValue = parseInt(enumerator.value)
205e5c31af7Sopenharmony_ci			if intValue != curIndex:
206e5c31af7Sopenharmony_ci				return False
207e5c31af7Sopenharmony_ci			curIndex += 1
208e5c31af7Sopenharmony_ci		return True
209e5c31af7Sopenharmony_ci
210e5c31af7Sopenharmony_ciclass CompositeMember:
211e5c31af7Sopenharmony_ci	def __init__ (self, name, aType, pointer, qualifiers, arraySizeList, optional, limittype, values, fieldWidth):
212e5c31af7Sopenharmony_ci		self.name			= name
213e5c31af7Sopenharmony_ci		self.type			= aType					# member type
214e5c31af7Sopenharmony_ci		self.pointer		= pointer				# None, '*' or '**'
215e5c31af7Sopenharmony_ci		self.qualifiers		= qualifiers			# 'const' or 'struct' or None
216e5c31af7Sopenharmony_ci		self.arraySizeList	= arraySizeList			# can contain digits or enums
217e5c31af7Sopenharmony_ci		self.optional		= optional
218e5c31af7Sopenharmony_ci		self.limittype		= limittype
219e5c31af7Sopenharmony_ci		self.values			= values				# allowed member values
220e5c31af7Sopenharmony_ci		self.fieldWidth		= fieldWidth			# ':' followed by number of bits
221e5c31af7Sopenharmony_ci
222e5c31af7Sopenharmony_ci		# check if type should be swaped
223e5c31af7Sopenharmony_ci		substituteType(self)
224e5c31af7Sopenharmony_ci
225e5c31af7Sopenharmony_ciclass Composite:
226e5c31af7Sopenharmony_ci	def __init__ (self, name, category, allowduplicate, structextends, returnedonly, members):
227e5c31af7Sopenharmony_ci		self.name			= name
228e5c31af7Sopenharmony_ci		self.category		= category			# is it struct or union
229e5c31af7Sopenharmony_ci		self.aliasList		= []				# most composite types have single alias but there are cases like VkPhysicalDeviceVariablePointersFeatures that have 3
230e5c31af7Sopenharmony_ci		self.allowduplicate	= allowduplicate
231e5c31af7Sopenharmony_ci		self.structextends	= structextends
232e5c31af7Sopenharmony_ci		self.returnedonly	= returnedonly
233e5c31af7Sopenharmony_ci		self.members		= members			# list of CompositeMember objects
234e5c31af7Sopenharmony_ci
235e5c31af7Sopenharmony_ciclass FunctionArgument:
236e5c31af7Sopenharmony_ci	def __init__ (self, name, qualifiers, aType, pointer = None, secondPointerIsConst = False, arraySize = None, len = None):
237e5c31af7Sopenharmony_ci		self.name					= name
238e5c31af7Sopenharmony_ci		self.qualifiers				= qualifiers
239e5c31af7Sopenharmony_ci		self.type					= aType
240e5c31af7Sopenharmony_ci		self.pointer				= pointer			# None, '*' or '**'
241e5c31af7Sopenharmony_ci		self.secondPointerIsConst	= secondPointerIsConst
242e5c31af7Sopenharmony_ci		self.arraySize				= arraySize
243e5c31af7Sopenharmony_ci		self.len					= len
244e5c31af7Sopenharmony_ci
245e5c31af7Sopenharmony_ci		# check if type should be swaped
246e5c31af7Sopenharmony_ci		substituteType(self)
247e5c31af7Sopenharmony_ci
248e5c31af7Sopenharmony_ciclass Function:
249e5c31af7Sopenharmony_ci	TYPE_PLATFORM		= 0 # Not bound to anything
250e5c31af7Sopenharmony_ci	TYPE_INSTANCE		= 1 # Bound to VkInstance
251e5c31af7Sopenharmony_ci	TYPE_DEVICE			= 2 # Bound to VkDevice
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_ci	def __init__ (self, name, returnType = None, arguments = None):
254e5c31af7Sopenharmony_ci		self.name			= name
255e5c31af7Sopenharmony_ci		self.aliasList		= []
256e5c31af7Sopenharmony_ci		self.returnType		= returnType
257e5c31af7Sopenharmony_ci		self.arguments		= arguments				# list of FunctionArgument objects
258e5c31af7Sopenharmony_ci		self.functionType	= Function.TYPE_PLATFORM
259e5c31af7Sopenharmony_ci
260e5c31af7Sopenharmony_ci		# Determine function type based on first argument but use TYPE_PLATFORM for vkGetInstanceProcAddr
261e5c31af7Sopenharmony_ci		if self.name == "vkGetInstanceProcAddr":
262e5c31af7Sopenharmony_ci			return
263e5c31af7Sopenharmony_ci		assert len(self.arguments) > 0
264e5c31af7Sopenharmony_ci		firstArgType = self.arguments[0].type
265e5c31af7Sopenharmony_ci		if firstArgType in ["VkInstance", "VkPhysicalDevice"]:
266e5c31af7Sopenharmony_ci			self.functionType = Function.TYPE_INSTANCE
267e5c31af7Sopenharmony_ci		elif firstArgType in ["VkDevice", "VkCommandBuffer", "VkQueue"]:
268e5c31af7Sopenharmony_ci			self.functionType = Function.TYPE_DEVICE
269e5c31af7Sopenharmony_ci
270e5c31af7Sopenharmony_ci	def getType (self):
271e5c31af7Sopenharmony_ci		return self.functionType
272e5c31af7Sopenharmony_ci
273e5c31af7Sopenharmony_ciclass FeatureEnumerator:
274e5c31af7Sopenharmony_ci	def __init__ (self, name, extends):
275e5c31af7Sopenharmony_ci		self.name		= name
276e5c31af7Sopenharmony_ci		self.extends	= extends
277e5c31af7Sopenharmony_ci
278e5c31af7Sopenharmony_ciclass FeatureRequirement:
279e5c31af7Sopenharmony_ci	def __init__ (self, operation, comment, enumList, typeList, commandList):
280e5c31af7Sopenharmony_ci		self.operation			= operation				# "require" or "remove"
281e5c31af7Sopenharmony_ci		self.comment			= comment
282e5c31af7Sopenharmony_ci		self.enumList			= enumList				# list of FeatureEnumerator objects
283e5c31af7Sopenharmony_ci		self.typeList			= typeList				# list of strings, each representing required structure name
284e5c31af7Sopenharmony_ci		self.commandList		= commandList			# list of strings, each representing required function name
285e5c31af7Sopenharmony_ci
286e5c31af7Sopenharmony_ciclass Feature:
287e5c31af7Sopenharmony_ci	def __init__ (self, api, name, number, requirementsList):
288e5c31af7Sopenharmony_ci		self.api				= api
289e5c31af7Sopenharmony_ci		self.name				= name
290e5c31af7Sopenharmony_ci		self.number				= number
291e5c31af7Sopenharmony_ci		self.requirementsList	= requirementsList		# list of FeatureRequirement objects
292e5c31af7Sopenharmony_ci
293e5c31af7Sopenharmony_ciclass ExtensionEnumerator:
294e5c31af7Sopenharmony_ci	def __init__ (self, name, extends, alias, value, extnumber, offset, bitpos, vdir, comment):
295e5c31af7Sopenharmony_ci		self.name		= name
296e5c31af7Sopenharmony_ci		self.extends	= extends
297e5c31af7Sopenharmony_ci		self.alias		= alias
298e5c31af7Sopenharmony_ci		self.value		= value
299e5c31af7Sopenharmony_ci		self.extnumber	= extnumber
300e5c31af7Sopenharmony_ci		self.offset		= offset
301e5c31af7Sopenharmony_ci		self.bitpos		= bitpos
302e5c31af7Sopenharmony_ci		self.dir		= vdir
303e5c31af7Sopenharmony_ci		self.comment	= comment						# note: comment is used to mark not promoted features for partially promoted extensions
304e5c31af7Sopenharmony_ci
305e5c31af7Sopenharmony_ciclass ExtensionCommand:
306e5c31af7Sopenharmony_ci	def __init__ (self, name, comment):
307e5c31af7Sopenharmony_ci		self.name		= name
308e5c31af7Sopenharmony_ci		self.comment	= comment
309e5c31af7Sopenharmony_ci
310e5c31af7Sopenharmony_ciclass ExtensionType:
311e5c31af7Sopenharmony_ci	def __init__ (self, name, comment):
312e5c31af7Sopenharmony_ci		self.name		= name
313e5c31af7Sopenharmony_ci		self.comment	= comment
314e5c31af7Sopenharmony_ci
315e5c31af7Sopenharmony_ciclass ExtensionRequirements:
316e5c31af7Sopenharmony_ci	def __init__ (self, depends, extendedEnums, newCommands, newTypes):
317e5c31af7Sopenharmony_ci		self.depends		= depends						# None when requirement apply to all implementations of extension or string with dependencies
318e5c31af7Sopenharmony_ci															# string with extension name when requirements apply to implementations that also support given extension
319e5c31af7Sopenharmony_ci		self.extendedEnums	= extendedEnums					# list of ExtensionEnumerator objects
320e5c31af7Sopenharmony_ci		self.newCommands	= newCommands					# list of ExtensionCommand objects
321e5c31af7Sopenharmony_ci		self.newTypes		= newTypes						# list of ExtensionType objects
322e5c31af7Sopenharmony_ci
323e5c31af7Sopenharmony_ciclass Extension:
324e5c31af7Sopenharmony_ci	def __init__ (self, name, number, type, depends, platform, promotedto, partiallyPromoted, requirementsList):
325e5c31af7Sopenharmony_ci		self.name				= name						# extension name
326e5c31af7Sopenharmony_ci		self.number				= number					# extension version
327e5c31af7Sopenharmony_ci		self.type				= type						# extension type - "device" or "instance"
328e5c31af7Sopenharmony_ci		self.depends			= depends					# string containig grammar for required core vulkan version and/or other extensions
329e5c31af7Sopenharmony_ci		self.platform			= platform					# None, "win32", "ios", "android" etc.
330e5c31af7Sopenharmony_ci		self.promotedto			= promotedto				# vulkan version, other extension or None
331e5c31af7Sopenharmony_ci		self.partiallyPromoted	= partiallyPromoted			# when True then some of requirements were not promoted
332e5c31af7Sopenharmony_ci		self.requirementsList	= requirementsList			# list of ExtensionRequirements objects
333e5c31af7Sopenharmony_ci
334e5c31af7Sopenharmony_ciclass API:
335e5c31af7Sopenharmony_ci	def __init__ (self, apiName):
336e5c31af7Sopenharmony_ci		self.apiName				= apiName	# string "vulkan" or "vulkansc"
337e5c31af7Sopenharmony_ci		self.versions				= []
338e5c31af7Sopenharmony_ci		self.basetypes				= {}		# dictionary, e.g. one of keys is VkFlags and its value is uint32_t
339e5c31af7Sopenharmony_ci		self.defines				= []
340e5c31af7Sopenharmony_ci		self.handles				= []		# list of Handle objects
341e5c31af7Sopenharmony_ci		self.bitmasks				= []		# list of Bitmask objects
342e5c31af7Sopenharmony_ci		self.enums					= []		# list of Enum objects - each contains individual enum definition (including extension enums)
343e5c31af7Sopenharmony_ci		self.compositeTypes			= []		# list of Composite objects - each contains individual structure/union definition (including extension structures)
344e5c31af7Sopenharmony_ci		self.functions				= []		# list of Function objects - each contains individual command definition (including extension functions)
345e5c31af7Sopenharmony_ci		self.features				= []		# list of Feature objects
346e5c31af7Sopenharmony_ci		self.extensions				= []		# list of Extension objects - each contains individual, supported extension definition
347e5c31af7Sopenharmony_ci		self.notSupportedExtensions	= []		# list of Extension objects - it contains NOT supported extensions; this is filled and needed only for SC
348e5c31af7Sopenharmony_ci		self.basicCTypes			= []		# list of basic C types e.g. 'void', 'int8_t'
349e5c31af7Sopenharmony_ci		self.tempAliasesList		= []		# list of aliases for enums that could not be added because enum is defined later than its alias; this is needed for SC
350e5c31af7Sopenharmony_ci
351e5c31af7Sopenharmony_ci		# read all files from extensions directory
352e5c31af7Sopenharmony_ci		additionalExtensionData	= {}
353e5c31af7Sopenharmony_ci		for fileName in glob.glob(os.path.join(SCRIPTS_SRC_DIR, "extensions", "*.json")):
354e5c31af7Sopenharmony_ci			if "schema.json" in fileName:
355e5c31af7Sopenharmony_ci				continue
356e5c31af7Sopenharmony_ci			extensionName	= os.path.basename(fileName)[:-5]
357e5c31af7Sopenharmony_ci			fileContent		= readFile(fileName)
358e5c31af7Sopenharmony_ci			try:
359e5c31af7Sopenharmony_ci				additionalExtensionData[extensionName] = json.loads(fileContent)
360e5c31af7Sopenharmony_ci			except ValueError as err:
361e5c31af7Sopenharmony_ci				print("Error in %s: %s" % (os.path.basename(fileName), str(err)))
362e5c31af7Sopenharmony_ci				sys.exit(-1)
363e5c31af7Sopenharmony_ci		self.additionalExtensionData = sorted(additionalExtensionData.items(), key=lambda e: e[0])
364e5c31af7Sopenharmony_ci
365e5c31af7Sopenharmony_ci	def addEnumerator(self, targetEnum, name, value, offset, extnumber, bitpos, dir = None):
366e5c31af7Sopenharmony_ci		# calculate enumerator value if offset attribute is present
367e5c31af7Sopenharmony_ci		if value is None and offset is not None:
368e5c31af7Sopenharmony_ci			value = 1000000000 + (int(extnumber) - 1) * 1000 + int(offset)
369e5c31af7Sopenharmony_ci			# check if value should be negative
370e5c31af7Sopenharmony_ci			value = -value if dir == "-" else value
371e5c31af7Sopenharmony_ci			# convert to string so that type matches the type in which values
372e5c31af7Sopenharmony_ci			# are stored for enums that were read from enums xml section
373e5c31af7Sopenharmony_ci			value = str(value)
374e5c31af7Sopenharmony_ci		# add new enumerator
375e5c31af7Sopenharmony_ci		targetEnum.enumeratorList.append(Enumerator(name, value, bitpos))
376e5c31af7Sopenharmony_ci
377e5c31af7Sopenharmony_ci	def addAliasToEnumerator (self, targetEnum, name, alias):
378e5c31af7Sopenharmony_ci		assert(alias is not None)
379e5c31af7Sopenharmony_ci		for e in reversed(targetEnum.enumeratorList):
380e5c31af7Sopenharmony_ci			if alias == e.name or alias in e.aliasList:
381e5c31af7Sopenharmony_ci				# make sure same alias is not already on the list; this handles special case like
382e5c31af7Sopenharmony_ci				# VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR alais which is defined in three places
383e5c31af7Sopenharmony_ci				if name not in e.aliasList:
384e5c31af7Sopenharmony_ci					e.aliasList.append(name)
385e5c31af7Sopenharmony_ci				return True
386e5c31af7Sopenharmony_ci		return False
387e5c31af7Sopenharmony_ci
388e5c31af7Sopenharmony_ci	def readEnum (self, enumsNode):
389e5c31af7Sopenharmony_ci		enumName = enumsNode.get("name")
390e5c31af7Sopenharmony_ci		# special case for vulkan hardcoded constants that are specified as enum in vk.xml
391e5c31af7Sopenharmony_ci		if enumName == "API Constants":
392e5c31af7Sopenharmony_ci			for enumItem in enumsNode:
393e5c31af7Sopenharmony_ci				self.defines.append(Define(
394e5c31af7Sopenharmony_ci					enumItem.get("name"),
395e5c31af7Sopenharmony_ci					enumItem.get("type"),
396e5c31af7Sopenharmony_ci					enumItem.get("alias"),
397e5c31af7Sopenharmony_ci					enumItem.get("value")
398e5c31af7Sopenharmony_ci				))
399e5c31af7Sopenharmony_ci			return
400e5c31af7Sopenharmony_ci		# initial enum definition is read while processing types section;
401e5c31af7Sopenharmony_ci		# we need to find this enum definition and add data to it
402e5c31af7Sopenharmony_ci		enumDefinition = [enumDef for enumDef in self.enums if enumName == enumDef.name][0]
403e5c31af7Sopenharmony_ci		# add type and bitwidth to enum definition
404e5c31af7Sopenharmony_ci		enumDefinition.type		= enumsNode.get("type")
405e5c31af7Sopenharmony_ci		enumDefinition.bitwidth	= enumsNode.get("bitwidth")
406e5c31af7Sopenharmony_ci		if enumDefinition.bitwidth is None:
407e5c31af7Sopenharmony_ci			enumDefinition.bitwidth = "32"
408e5c31af7Sopenharmony_ci		# add components to enum definition
409e5c31af7Sopenharmony_ci		for enumeratorItem in enumsNode:
410e5c31af7Sopenharmony_ci			# skip comment tags
411e5c31af7Sopenharmony_ci			if enumeratorItem.tag != "enum":
412e5c31af7Sopenharmony_ci				continue
413e5c31af7Sopenharmony_ci			name	= enumeratorItem.get("name")
414e5c31af7Sopenharmony_ci			alias	= enumeratorItem.get("alias")
415e5c31af7Sopenharmony_ci			if alias is None:
416e5c31af7Sopenharmony_ci				self.addEnumerator(
417e5c31af7Sopenharmony_ci					enumDefinition,
418e5c31af7Sopenharmony_ci					name,
419e5c31af7Sopenharmony_ci					enumeratorItem.get("value"),
420e5c31af7Sopenharmony_ci					enumeratorItem.get("offset"),
421e5c31af7Sopenharmony_ci					enumeratorItem.get("extnumber"),
422e5c31af7Sopenharmony_ci					enumeratorItem.get("bitpos"),
423e5c31af7Sopenharmony_ci					enumeratorItem.get("dir"))
424e5c31af7Sopenharmony_ci			else:
425e5c31af7Sopenharmony_ci				self.addAliasToEnumerator(enumDefinition, name, alias)
426e5c31af7Sopenharmony_ci
427e5c31af7Sopenharmony_ci	def readCommand (self, commandNode):
428e5c31af7Sopenharmony_ci		protoNode = None					# proto is a first child of every command node
429e5c31af7Sopenharmony_ci		# check if this is alias
430e5c31af7Sopenharmony_ci		alias = commandNode.get("alias")
431e5c31af7Sopenharmony_ci		# if node is alias then use the fact that alias definition follows aliased structure
432e5c31af7Sopenharmony_ci		if alias is not None:
433e5c31af7Sopenharmony_ci			# aliased command has usually been added recently, so we iterate in reverse order
434e5c31af7Sopenharmony_ci			found = False
435e5c31af7Sopenharmony_ci			for f in reversed(self.functions):
436e5c31af7Sopenharmony_ci				found = (f.name == alias)
437e5c31af7Sopenharmony_ci				if found:
438e5c31af7Sopenharmony_ci					f.aliasList.append(commandNode.get("name"))
439e5c31af7Sopenharmony_ci					break
440e5c31af7Sopenharmony_ci			assert found
441e5c31af7Sopenharmony_ci			# go to next node
442e5c31af7Sopenharmony_ci			return
443e5c31af7Sopenharmony_ci		# memorize all parameters
444e5c31af7Sopenharmony_ci		functionParams = []
445e5c31af7Sopenharmony_ci		for paramNode in commandNode:
446e5c31af7Sopenharmony_ci			# memorize prototype node
447e5c31af7Sopenharmony_ci			if paramNode.tag == "proto":
448e5c31af7Sopenharmony_ci				protoNode = paramNode
449e5c31af7Sopenharmony_ci				continue
450e5c31af7Sopenharmony_ci			# skip implicitexternsyncparams
451e5c31af7Sopenharmony_ci			if paramNode.tag != "param":
452e5c31af7Sopenharmony_ci				continue
453e5c31af7Sopenharmony_ci			nameNode	= paramNode.find("name")
454e5c31af7Sopenharmony_ci			typeNode	= paramNode.find("type")
455e5c31af7Sopenharmony_ci			starCount	= typeNode.tail.count('*')
456e5c31af7Sopenharmony_ci			lenAttr		= paramNode.get("len")
457e5c31af7Sopenharmony_ci			functionParams.append(FunctionArgument(
458e5c31af7Sopenharmony_ci				nameNode.text,
459e5c31af7Sopenharmony_ci				paramNode.text,
460e5c31af7Sopenharmony_ci				paramNode.find("type").text,
461e5c31af7Sopenharmony_ci				'*' * starCount if starCount > 0 else None,
462e5c31af7Sopenharmony_ci				'const' in typeNode.tail,
463e5c31af7Sopenharmony_ci				nameNode.tail,
464e5c31af7Sopenharmony_ci				lenAttr
465e5c31af7Sopenharmony_ci			))
466e5c31af7Sopenharmony_ci		# memorize whole function
467e5c31af7Sopenharmony_ci		self.functions.append(Function(
468e5c31af7Sopenharmony_ci			protoNode.find("name").text,
469e5c31af7Sopenharmony_ci			protoNode.find("type").text,
470e5c31af7Sopenharmony_ci			functionParams,
471e5c31af7Sopenharmony_ci		))
472e5c31af7Sopenharmony_ci
473e5c31af7Sopenharmony_ci	def readExtension (self, extensionNode):
474e5c31af7Sopenharmony_ci		# check to which list this extension should be added
475e5c31af7Sopenharmony_ci		supportedList			= extensionNode.get("supported")
476e5c31af7Sopenharmony_ci		isExtensionSupported	= self.apiName in supportedList.split(',')
477e5c31af7Sopenharmony_ci		targetExtensionList		= self.extensions if isExtensionSupported else self.notSupportedExtensions
478e5c31af7Sopenharmony_ci		# read extension definition to proper list
479e5c31af7Sopenharmony_ci		extensionName		= extensionNode.get("name")
480e5c31af7Sopenharmony_ci		extensionNumber		= extensionNode.get("number")
481e5c31af7Sopenharmony_ci		partiallyPromoted	= False
482e5c31af7Sopenharmony_ci		# before reading extension data first read extension
483e5c31af7Sopenharmony_ci		# requirements by iterating over all require tags
484e5c31af7Sopenharmony_ci		requirementsList = []
485e5c31af7Sopenharmony_ci		for requireItem in extensionNode:
486e5c31af7Sopenharmony_ci			extendedEnums	= []
487e5c31af7Sopenharmony_ci			newCommands		= []
488e5c31af7Sopenharmony_ci			newTypes		= []
489e5c31af7Sopenharmony_ci			# iterate over all children in current require tag
490e5c31af7Sopenharmony_ci			# and add them to proper list
491e5c31af7Sopenharmony_ci			for individualRequirement in requireItem:
492e5c31af7Sopenharmony_ci				requirementName = individualRequirement.get("name")
493e5c31af7Sopenharmony_ci				requirementComment = individualRequirement.get("comment")
494e5c31af7Sopenharmony_ci				# check if this requirement was not promoted and mark
495e5c31af7Sopenharmony_ci				# this extension as not fully promoted
496e5c31af7Sopenharmony_ci				if requirementComment is not None and "Not promoted to" in requirementComment:
497e5c31af7Sopenharmony_ci					partiallyPromoted = True
498e5c31af7Sopenharmony_ci				# check if this requirement describes enum, command or type
499e5c31af7Sopenharmony_ci				if individualRequirement.tag == "enum":
500e5c31af7Sopenharmony_ci					extendedEnumName = individualRequirement.get("extends")
501e5c31af7Sopenharmony_ci					extendedEnums.append(ExtensionEnumerator(
502e5c31af7Sopenharmony_ci						requirementName,
503e5c31af7Sopenharmony_ci						extendedEnumName,
504e5c31af7Sopenharmony_ci						individualRequirement.get("alias"),
505e5c31af7Sopenharmony_ci						individualRequirement.get("value"),
506e5c31af7Sopenharmony_ci						individualRequirement.get("extnumber"),
507e5c31af7Sopenharmony_ci						individualRequirement.get("offset"),
508e5c31af7Sopenharmony_ci						individualRequirement.get("bitpos"),
509e5c31af7Sopenharmony_ci						individualRequirement.get("dir"),
510e5c31af7Sopenharmony_ci						requirementComment))
511e5c31af7Sopenharmony_ci				elif individualRequirement.tag == "command":
512e5c31af7Sopenharmony_ci					newCommands.append(ExtensionCommand(requirementName, requirementComment))
513e5c31af7Sopenharmony_ci				elif individualRequirement.tag == "type":
514e5c31af7Sopenharmony_ci					newTypes.append(ExtensionType(requirementName, requirementComment))
515e5c31af7Sopenharmony_ci				elif individualRequirement.tag == "comment" and "not promoted to" in individualRequirement.text:
516e5c31af7Sopenharmony_ci					# partial promotion of VK_EXT_ycbcr_2plane_444_formats and VK_EXT_4444_formats
517e5c31af7Sopenharmony_ci					# is marked with comment tag in first require section
518e5c31af7Sopenharmony_ci					partiallyPromoted = True
519e5c31af7Sopenharmony_ci			# construct requirement object and add it to the list
520e5c31af7Sopenharmony_ci			requirementsList.append(ExtensionRequirements(
521e5c31af7Sopenharmony_ci				requireItem.get("depends"),		# dependencies that can include "and/or" grammar
522e5c31af7Sopenharmony_ci				extendedEnums,					# extendedEnums
523e5c31af7Sopenharmony_ci				newCommands,					# newCommands
524e5c31af7Sopenharmony_ci				newTypes						# newTypes
525e5c31af7Sopenharmony_ci			))
526e5c31af7Sopenharmony_ci		# add extension definition to proper api object
527e5c31af7Sopenharmony_ci		targetExtensionList.append(Extension(
528e5c31af7Sopenharmony_ci			extensionName,						# name
529e5c31af7Sopenharmony_ci			extensionNumber,					# number
530e5c31af7Sopenharmony_ci			extensionNode.get("type"),			# type
531e5c31af7Sopenharmony_ci			extensionNode.get("depends"),		# depends
532e5c31af7Sopenharmony_ci			extensionNode.get("platform"),		# platform
533e5c31af7Sopenharmony_ci			extensionNode.get("promotedto"),	# promotedto
534e5c31af7Sopenharmony_ci			partiallyPromoted,					# partiallyPromoted
535e5c31af7Sopenharmony_ci			requirementsList					# requirementsList
536e5c31af7Sopenharmony_ci		))
537e5c31af7Sopenharmony_ci
538e5c31af7Sopenharmony_ci	def readFeature (self, featureNode):
539e5c31af7Sopenharmony_ci		requirementsList = []
540e5c31af7Sopenharmony_ci		for requirementGroup in featureNode:
541e5c31af7Sopenharmony_ci			enumList	= []
542e5c31af7Sopenharmony_ci			typeList	= []
543e5c31af7Sopenharmony_ci			commandList	= []
544e5c31af7Sopenharmony_ci			for requirement in requirementGroup:
545e5c31af7Sopenharmony_ci				requirementName = requirement.get("name")
546e5c31af7Sopenharmony_ci				if requirement.tag == "enum":
547e5c31af7Sopenharmony_ci					extendedEnumName = requirement.get("extends")
548e5c31af7Sopenharmony_ci					enumList.append(FeatureEnumerator(requirementName, extendedEnumName))
549e5c31af7Sopenharmony_ci					if extendedEnumName is not None:
550e5c31af7Sopenharmony_ci						# find extended enum in api.enums list
551e5c31af7Sopenharmony_ci						for e in self.enums:
552e5c31af7Sopenharmony_ci							if extendedEnumName == e.name:
553e5c31af7Sopenharmony_ci								# read enumerator and add it to enum
554e5c31af7Sopenharmony_ci								alias = requirement.get("alias")
555e5c31af7Sopenharmony_ci								if alias is None:
556e5c31af7Sopenharmony_ci									self.addEnumerator(
557e5c31af7Sopenharmony_ci										e,
558e5c31af7Sopenharmony_ci										requirementName,
559e5c31af7Sopenharmony_ci										requirement.get("value"),
560e5c31af7Sopenharmony_ci										requirement.get("offset"),
561e5c31af7Sopenharmony_ci										requirement.get("extnumber"),
562e5c31af7Sopenharmony_ci										requirement.get("bitpos"),
563e5c31af7Sopenharmony_ci										requirement.get("dir"))
564e5c31af7Sopenharmony_ci								elif not self.addAliasToEnumerator(e, requirementName, alias):
565e5c31af7Sopenharmony_ci									self.tempAliasesList.append((e, requirementName, alias))
566e5c31af7Sopenharmony_ci								break
567e5c31af7Sopenharmony_ci				elif requirement.tag == "type":
568e5c31af7Sopenharmony_ci					typeList.append(requirementName)
569e5c31af7Sopenharmony_ci				elif requirement.tag == "command":
570e5c31af7Sopenharmony_ci					commandList.append(requirementName)
571e5c31af7Sopenharmony_ci			requirementsList.append(FeatureRequirement(
572e5c31af7Sopenharmony_ci				requirementGroup.tag,
573e5c31af7Sopenharmony_ci				requirementGroup.get("comment"),
574e5c31af7Sopenharmony_ci				enumList,
575e5c31af7Sopenharmony_ci				typeList,
576e5c31af7Sopenharmony_ci				commandList
577e5c31af7Sopenharmony_ci			))
578e5c31af7Sopenharmony_ci		self.features.append(Feature(
579e5c31af7Sopenharmony_ci			featureNode.get("api"),
580e5c31af7Sopenharmony_ci			featureNode.get("name"),
581e5c31af7Sopenharmony_ci			featureNode.get("number"),
582e5c31af7Sopenharmony_ci			requirementsList
583e5c31af7Sopenharmony_ci		))
584e5c31af7Sopenharmony_ci
585e5c31af7Sopenharmony_ci	def readType (self, typeNode):
586e5c31af7Sopenharmony_ci		name		= typeNode.get("name")
587e5c31af7Sopenharmony_ci		alias		= typeNode.get("alias")
588e5c31af7Sopenharmony_ci		category	= typeNode.get("category")
589e5c31af7Sopenharmony_ci		if category == "enum":
590e5c31af7Sopenharmony_ci			if alias is None:
591e5c31af7Sopenharmony_ci				self.enums.append(Enum(name))
592e5c31af7Sopenharmony_ci			else:
593e5c31af7Sopenharmony_ci				for e in reversed(self.enums):
594e5c31af7Sopenharmony_ci					if alias == e.name:
595e5c31af7Sopenharmony_ci						e.alias = name
596e5c31af7Sopenharmony_ci						break
597e5c31af7Sopenharmony_ci		elif category == "handle":
598e5c31af7Sopenharmony_ci			type = None
599e5c31af7Sopenharmony_ci			if alias is None:
600e5c31af7Sopenharmony_ci				name = typeNode.find("name").text
601e5c31af7Sopenharmony_ci				type = typeNode.find("type").text
602e5c31af7Sopenharmony_ci				self.handles.append(Handle(
603e5c31af7Sopenharmony_ci					name,
604e5c31af7Sopenharmony_ci					type,
605e5c31af7Sopenharmony_ci					alias,
606e5c31af7Sopenharmony_ci					typeNode.get("parent"),
607e5c31af7Sopenharmony_ci					typeNode.get("objtypeenum"),
608e5c31af7Sopenharmony_ci				))
609e5c31af7Sopenharmony_ci			else:
610e5c31af7Sopenharmony_ci				for h in reversed(self.handles):
611e5c31af7Sopenharmony_ci					if alias == h.name:
612e5c31af7Sopenharmony_ci						h.alias = name
613e5c31af7Sopenharmony_ci						break
614e5c31af7Sopenharmony_ci		elif category == "basetype":
615e5c31af7Sopenharmony_ci			# processing only those basetypes that have type child
616e5c31af7Sopenharmony_ci			type = typeNode.find("type")
617e5c31af7Sopenharmony_ci			if type is not None:
618e5c31af7Sopenharmony_ci				self.basetypes[typeNode.find("name").text] = type.text
619e5c31af7Sopenharmony_ci		elif category == "bitmask":
620e5c31af7Sopenharmony_ci			# if node is alias then use the fact that alias definition follows aliased bitmasks;
621e5c31af7Sopenharmony_ci			# in majoriti of cases it follows directly aliased bitmasks but in some cases there
622e5c31af7Sopenharmony_ci			# is a unrelated bitmasks definition in between - to handle this traverse in reverse order
623e5c31af7Sopenharmony_ci			if alias is not None:
624e5c31af7Sopenharmony_ci				for bm in reversed(self.bitmasks):
625e5c31af7Sopenharmony_ci					if alias == bm.name:
626e5c31af7Sopenharmony_ci						bm.alias = name
627e5c31af7Sopenharmony_ci						break
628e5c31af7Sopenharmony_ci			else:
629e5c31af7Sopenharmony_ci				self.bitmasks.append(Bitmask(
630e5c31af7Sopenharmony_ci					typeNode.find("name").text,
631e5c31af7Sopenharmony_ci					typeNode.find("type").text,
632e5c31af7Sopenharmony_ci					typeNode.get("requires"),
633e5c31af7Sopenharmony_ci					typeNode.get("bitvalues")
634e5c31af7Sopenharmony_ci				))
635e5c31af7Sopenharmony_ci		elif category in ["struct", "union"]:
636e5c31af7Sopenharmony_ci			# if node is alias then use the fact that alias definition follows aliased structure;
637e5c31af7Sopenharmony_ci			# in majoriti of cases it follows directly aliased structure but in some cases there
638e5c31af7Sopenharmony_ci			# is a unrelated structure definition in between - to handle this traverse in reverse order
639e5c31af7Sopenharmony_ci			if alias is not None:
640e5c31af7Sopenharmony_ci				for ct in reversed(self.compositeTypes):
641e5c31af7Sopenharmony_ci					if alias == ct.name:
642e5c31af7Sopenharmony_ci						ct.aliasList.append(name)
643e5c31af7Sopenharmony_ci						break
644e5c31af7Sopenharmony_ci				# go to next node
645e5c31af7Sopenharmony_ci				return
646e5c31af7Sopenharmony_ci			# read structure members
647e5c31af7Sopenharmony_ci			structMembers = []
648e5c31af7Sopenharmony_ci			for memberNode in typeNode:
649e5c31af7Sopenharmony_ci				if memberNode.tag != "member":
650e5c31af7Sopenharmony_ci					continue
651e5c31af7Sopenharmony_ci				# handle enum nodes that can be used for array dimensions
652e5c31af7Sopenharmony_ci				arraySizeList = []
653e5c31af7Sopenharmony_ci				for node in memberNode:
654e5c31af7Sopenharmony_ci					if node.tag == "enum":
655e5c31af7Sopenharmony_ci						arraySizeList.append(node.text)
656e5c31af7Sopenharmony_ci						# check if there are array dimension that are not enums
657e5c31af7Sopenharmony_ci						if '[' in node.tail and len(node.tail) > 2:
658e5c31af7Sopenharmony_ci							arraySizeList += node.tail.replace(']', ' ').replace('[', ' ').split()
659e5c31af7Sopenharmony_ci				# handle additional text after name tag; it can represent array
660e5c31af7Sopenharmony_ci				# size like in VkPipelineFragmentShadingRateEnumStateCreateInfoNV
661e5c31af7Sopenharmony_ci				# or number of bits like in VkAccelerationStructureInstanceKHR
662e5c31af7Sopenharmony_ci				nameNode	= memberNode.find("name")
663e5c31af7Sopenharmony_ci				nameTail	= nameNode.tail
664e5c31af7Sopenharmony_ci				fieldWidth	= None
665e5c31af7Sopenharmony_ci				if nameTail:
666e5c31af7Sopenharmony_ci					if ':' in nameTail:
667e5c31af7Sopenharmony_ci						fieldWidth = nameTail.replace(':', '').replace(' ', '')
668e5c31af7Sopenharmony_ci					elif '[' in nameTail and ']' in nameTail:
669e5c31af7Sopenharmony_ci						nameTail = nameTail.replace(']', ' ').replace('[', ' ')
670e5c31af7Sopenharmony_ci						arraySizeList = nameTail.split() + arraySizeList
671e5c31af7Sopenharmony_ci				# handle additional text after type tag; it can represent pointers like *pNext
672e5c31af7Sopenharmony_ci				memberTypeNode	= memberNode.find("type")
673e5c31af7Sopenharmony_ci				pointer			= memberTypeNode.tail.strip() if memberTypeNode.tail is not None else None
674e5c31af7Sopenharmony_ci				structMembers.append(CompositeMember(
675e5c31af7Sopenharmony_ci					nameNode.text,					# name
676e5c31af7Sopenharmony_ci					memberTypeNode.text,			# type
677e5c31af7Sopenharmony_ci					pointer,						# pointer
678e5c31af7Sopenharmony_ci					memberNode.text,				# qualifiers
679e5c31af7Sopenharmony_ci					arraySizeList,					# arraySizeList
680e5c31af7Sopenharmony_ci					memberNode.get("optional"),		# optional
681e5c31af7Sopenharmony_ci					memberNode.get("limittype"),	# limittype
682e5c31af7Sopenharmony_ci					memberNode.get("values"),		# values
683e5c31af7Sopenharmony_ci					fieldWidth						# fieldWidth
684e5c31af7Sopenharmony_ci				))
685e5c31af7Sopenharmony_ci			# create structure definition
686e5c31af7Sopenharmony_ci			self.compositeTypes.append(Composite(
687e5c31af7Sopenharmony_ci				name,
688e5c31af7Sopenharmony_ci				category,
689e5c31af7Sopenharmony_ci				typeNode.get("allowduplicate"),
690e5c31af7Sopenharmony_ci				typeNode.get("structextends"),
691e5c31af7Sopenharmony_ci				typeNode.get("returnedonly"),
692e5c31af7Sopenharmony_ci				structMembers
693e5c31af7Sopenharmony_ci			))
694e5c31af7Sopenharmony_ci		elif category == "define":
695e5c31af7Sopenharmony_ci			nNode = typeNode.find("name")
696e5c31af7Sopenharmony_ci			tNode = typeNode.find("type")
697e5c31af7Sopenharmony_ci			if nNode == None or tNode == None:
698e5c31af7Sopenharmony_ci				return
699e5c31af7Sopenharmony_ci			requires = typeNode.get("requires")
700e5c31af7Sopenharmony_ci			name = nNode.text
701e5c31af7Sopenharmony_ci			if "API_VERSION_" in name or requires == "VK_MAKE_VIDEO_STD_VERSION":
702e5c31af7Sopenharmony_ci				value = tNode.tail
703e5c31af7Sopenharmony_ci				value = tNode.text + value[:value.find(')')+1]
704e5c31af7Sopenharmony_ci				value = value.replace('VKSC_API_VARIANT', '1')
705e5c31af7Sopenharmony_ci				self.defines.append(Define(
706e5c31af7Sopenharmony_ci					name,
707e5c31af7Sopenharmony_ci					"uint32_t",
708e5c31af7Sopenharmony_ci					None,
709e5c31af7Sopenharmony_ci					value
710e5c31af7Sopenharmony_ci				))
711e5c31af7Sopenharmony_ci		else:
712e5c31af7Sopenharmony_ci			requires = typeNode.get("requires")
713e5c31af7Sopenharmony_ci			if requires == 'vk_platform':
714e5c31af7Sopenharmony_ci				self.basicCTypes.append(name)
715e5c31af7Sopenharmony_ci
716e5c31af7Sopenharmony_ci	def build (self, rawVkXml):
717e5c31af7Sopenharmony_ci		# iterate over all *.xml root children
718e5c31af7Sopenharmony_ci		for rootChild in rawVkXml.getroot():
719e5c31af7Sopenharmony_ci
720e5c31af7Sopenharmony_ci			# each enum is defined in separate enums node directly under root node
721e5c31af7Sopenharmony_ci			if rootChild.tag == "enums":
722e5c31af7Sopenharmony_ci				self.readEnum(rootChild)
723e5c31af7Sopenharmony_ci
724e5c31af7Sopenharmony_ci			# read function definitions
725e5c31af7Sopenharmony_ci			if rootChild.tag == "commands":
726e5c31af7Sopenharmony_ci				commandsNode = rootChild
727e5c31af7Sopenharmony_ci				for commandItem in commandsNode:
728e5c31af7Sopenharmony_ci					self.readCommand(commandItem)
729e5c31af7Sopenharmony_ci
730e5c31af7Sopenharmony_ci			# read vulkan versions
731e5c31af7Sopenharmony_ci			if rootChild.tag == "feature":
732e5c31af7Sopenharmony_ci				self.readFeature(rootChild)
733e5c31af7Sopenharmony_ci
734e5c31af7Sopenharmony_ci			# read extensions
735e5c31af7Sopenharmony_ci			if rootChild.tag == "extensions":
736e5c31af7Sopenharmony_ci				extensionsNode = rootChild
737e5c31af7Sopenharmony_ci				for extensionItem in extensionsNode:
738e5c31af7Sopenharmony_ci					self.readExtension(extensionItem)
739e5c31af7Sopenharmony_ci
740e5c31af7Sopenharmony_ci			# "types" is a first child of root so it's optimal to check for it
741e5c31af7Sopenharmony_ci			# last and don't repeat this check for all other iterations
742e5c31af7Sopenharmony_ci			if rootChild.tag == "types":
743e5c31af7Sopenharmony_ci				typesNode = rootChild
744e5c31af7Sopenharmony_ci				for typeItem in typesNode:
745e5c31af7Sopenharmony_ci					self.readType(typeItem)
746e5c31af7Sopenharmony_ci
747e5c31af7Sopenharmony_ci		# Verify that promotedto extensions are supported by the api
748e5c31af7Sopenharmony_ci		for ext in self.extensions:
749e5c31af7Sopenharmony_ci			if ext.promotedto is not None and "VK_VERSION" not in ext.promotedto:
750e5c31af7Sopenharmony_ci				if not any(x.name == ext.promotedto for x in self.extensions):
751e5c31af7Sopenharmony_ci					ext.promotedto = None
752e5c31af7Sopenharmony_ci
753e5c31af7Sopenharmony_ci	def postProcess (self):
754e5c31af7Sopenharmony_ci
755e5c31af7Sopenharmony_ci		# temporary workaround for extensions that are marked only for vulkan api in xml while
756e5c31af7Sopenharmony_ci		# they are need by vulkan_json_data.hpp and vulkan_json_parser.hpp in vulkansc
757e5c31af7Sopenharmony_ci		if self.apiName == "vulkansc":
758e5c31af7Sopenharmony_ci			deviceDiagnosticCheckpoints = [e for e in self.notSupportedExtensions if e.name == "VK_NV_device_diagnostic_checkpoints"]
759e5c31af7Sopenharmony_ci			if len(deviceDiagnosticCheckpoints):
760e5c31af7Sopenharmony_ci				deviceDiagnosticCheckpoints = deviceDiagnosticCheckpoints[0]
761e5c31af7Sopenharmony_ci				self.extensions.append(deviceDiagnosticCheckpoints)
762e5c31af7Sopenharmony_ci				self.notSupportedExtensions.remove(deviceDiagnosticCheckpoints)
763e5c31af7Sopenharmony_ci			formatFeatureFlags2 = [e for e in self.notSupportedExtensions if e.name == "VK_KHR_format_feature_flags2"]
764e5c31af7Sopenharmony_ci			if len(formatFeatureFlags2):
765e5c31af7Sopenharmony_ci				formatFeatureFlags2 = formatFeatureFlags2[0]
766e5c31af7Sopenharmony_ci				self.extensions.append(formatFeatureFlags2)
767e5c31af7Sopenharmony_ci				self.notSupportedExtensions.remove(formatFeatureFlags2)
768e5c31af7Sopenharmony_ci
769e5c31af7Sopenharmony_ci		# add new enumerators that were added by extensions to api.enums
770e5c31af7Sopenharmony_ci		# we have to do it at the end for SC becouse some enums are dependednt from extensions/api versions
771e5c31af7Sopenharmony_ci		# and those dependencies can be checked only after all extensions were read
772e5c31af7Sopenharmony_ci		for ext in self.extensions:
773e5c31af7Sopenharmony_ci			for requirement in ext.requirementsList:
774e5c31af7Sopenharmony_ci				# check if this requirement is supported by current implementation
775e5c31af7Sopenharmony_ci				isRequirementSupported = True
776e5c31af7Sopenharmony_ci				dependencies = requirement.depends
777e5c31af7Sopenharmony_ci				if dependencies is not None:
778e5c31af7Sopenharmony_ci					# check if dependency extension or api version is part of this api
779e5c31af7Sopenharmony_ci					# note: this logic will have to changed if there are dependencies with "and/or" grammar
780e5c31af7Sopenharmony_ci					assert((',' not in dependencies) or ('+' not in dependencies))
781e5c31af7Sopenharmony_ci					isRequirementSupported = '_VERSION_' in dependencies
782e5c31af7Sopenharmony_ci					if isRequirementSupported == False:
783e5c31af7Sopenharmony_ci						for e in self.extensions:
784e5c31af7Sopenharmony_ci							if e.name in dependencies:
785e5c31af7Sopenharmony_ci								isRequirementSupported = True
786e5c31af7Sopenharmony_ci								break
787e5c31af7Sopenharmony_ci				# add enumerator to proper enum from api.enums
788e5c31af7Sopenharmony_ci				if isRequirementSupported:
789e5c31af7Sopenharmony_ci					for enumerator in requirement.extendedEnums:
790e5c31af7Sopenharmony_ci						if enumerator.extends is None:
791e5c31af7Sopenharmony_ci							continue
792e5c31af7Sopenharmony_ci						# find enum in api.enums
793e5c31af7Sopenharmony_ci						matchedEnum = [enum for enum in api.enums if enumerator.extends == enum.name][0]
794e5c31af7Sopenharmony_ci						# add enumerator only when it is not already in enum
795e5c31af7Sopenharmony_ci						if len([e for e in matchedEnum.enumeratorList if e.name == enumerator.name]) == 0:
796e5c31af7Sopenharmony_ci							if enumerator.alias == None:
797e5c31af7Sopenharmony_ci								self.addEnumerator(
798e5c31af7Sopenharmony_ci										matchedEnum,
799e5c31af7Sopenharmony_ci										enumerator.name,
800e5c31af7Sopenharmony_ci										enumerator.value,
801e5c31af7Sopenharmony_ci										enumerator.offset,
802e5c31af7Sopenharmony_ci										enumerator.extnumber if enumerator.extnumber else ext.number,
803e5c31af7Sopenharmony_ci										enumerator.bitpos,
804e5c31af7Sopenharmony_ci										enumerator.dir)
805e5c31af7Sopenharmony_ci							elif not self.addAliasToEnumerator(matchedEnum, enumerator.name, enumerator.alias):
806e5c31af7Sopenharmony_ci								# we might not be able to add alias as we might be missing what we are aliasing
807e5c31af7Sopenharmony_ci								# this will hapen when aliased enum is added later then definition of alias
808e5c31af7Sopenharmony_ci								self.tempAliasesList.append((matchedEnum, enumerator.name, enumerator.alias))
809e5c31af7Sopenharmony_ci
810e5c31af7Sopenharmony_ci		# add aliases to enumerators that were defined after alias definition
811e5c31af7Sopenharmony_ci		for enum, name, alias in self.tempAliasesList:
812e5c31af7Sopenharmony_ci			if not self.addAliasToEnumerator(enum, name, alias):
813e5c31af7Sopenharmony_ci				# if enumerator that should be aliased was not found then try to insert it without alias
814e5c31af7Sopenharmony_ci				# (this happens for vulkansc as in xml enumerator might be defined in extension that is not supported by sc)
815e5c31af7Sopenharmony_ci				def tryToFindEnumValue(searchedName):
816e5c31af7Sopenharmony_ci					for nsExt in self.notSupportedExtensions:
817e5c31af7Sopenharmony_ci						for r in nsExt.requirementsList:
818e5c31af7Sopenharmony_ci							for enumerator in r.extendedEnums:
819e5c31af7Sopenharmony_ci								if enumerator.name == searchedName:
820e5c31af7Sopenharmony_ci									self.addEnumerator(
821e5c31af7Sopenharmony_ci										enum,
822e5c31af7Sopenharmony_ci										name,
823e5c31af7Sopenharmony_ci										enumerator.value,
824e5c31af7Sopenharmony_ci										enumerator.offset,
825e5c31af7Sopenharmony_ci										enumerator.extnumber if enumerator.extnumber else ext.number,
826e5c31af7Sopenharmony_ci										enumerator.bitpos,
827e5c31af7Sopenharmony_ci										enumerator.dir)
828e5c31af7Sopenharmony_ci									# there are ~2 cases where alias that is not part of SC still needs to be added for SC
829e5c31af7Sopenharmony_ci									self.addAliasToEnumerator(enum, alias, name)
830e5c31af7Sopenharmony_ci									return
831e5c31af7Sopenharmony_ci				# using function for easy stack unwinding
832e5c31af7Sopenharmony_ci				tryToFindEnumValue(alias)
833e5c31af7Sopenharmony_ci		self.tempAliasesList = None
834e5c31af7Sopenharmony_ci
835e5c31af7Sopenharmony_ci		if self.apiName == "vulkan":
836e5c31af7Sopenharmony_ci			def removeExtensionFromApi(extName, structureNameList, commandNameList):
837e5c31af7Sopenharmony_ci				extObjectList = [e for e in api.extensions if e.name == extName]
838e5c31af7Sopenharmony_ci				if len(extObjectList) > 0:
839e5c31af7Sopenharmony_ci					api.extensions.remove(extObjectList[0])
840e5c31af7Sopenharmony_ci				structObjectList = [ct for ct in api.compositeTypes if ct.name in structureNameList]
841e5c31af7Sopenharmony_ci				for s in structObjectList:
842e5c31af7Sopenharmony_ci					api.compositeTypes.remove(s)
843e5c31af7Sopenharmony_ci				commandObjectList = [f for f in api.functions if f.name in commandNameList]
844e5c31af7Sopenharmony_ci				for f in commandObjectList:
845e5c31af7Sopenharmony_ci					api.functions.remove(f)
846e5c31af7Sopenharmony_ci
847e5c31af7Sopenharmony_ci			# remove structures and commands added by VK_EXT_directfb_surface extension
848e5c31af7Sopenharmony_ci			removeExtensionFromApi("VK_EXT_directfb_surface",
849e5c31af7Sopenharmony_ci								   ["VkDirectFBSurfaceCreateFlagsEXT", "VkDirectFBSurfaceCreateInfoEXT"],
850e5c31af7Sopenharmony_ci								   ["vkCreateDirectFBSurfaceEXT", "vkGetPhysicalDeviceDirectFBPresentationSupportEXT"])
851e5c31af7Sopenharmony_ci
852e5c31af7Sopenharmony_ci			# remove structures and commands added by disabled VK_ANDROID_native_buffer extension;
853e5c31af7Sopenharmony_ci			# disabled extensions aren't read but their structures and commands will be in types and commands sections in vk.xml
854e5c31af7Sopenharmony_ci			removeExtensionFromApi("VK_ANDROID_native_buffer",
855e5c31af7Sopenharmony_ci								   ["VkNativeBufferANDROID", "VkSwapchainImageCreateInfoANDROID",
856e5c31af7Sopenharmony_ci									"VkPhysicalDevicePresentationPropertiesANDROID", "VkNativeBufferUsage2ANDROID",
857e5c31af7Sopenharmony_ci									"VkSwapchainImageUsageFlagBitsANDROID", "VkSwapchainImageUsageFlagsANDROID"],
858e5c31af7Sopenharmony_ci								   ["vkGetSwapchainGrallocUsageANDROID", "vkAcquireImageANDROID",
859e5c31af7Sopenharmony_ci									"vkQueueSignalReleaseImageANDROID", "vkGetSwapchainGrallocUsage2ANDROID"])
860e5c31af7Sopenharmony_ci
861e5c31af7Sopenharmony_ci			# remove empty enums e.g. VkQueryPoolCreateFlagBits, VkDeviceCreateFlagBits
862e5c31af7Sopenharmony_ci			enumsToRemove = [enum for enum in self.enums if len(enum.enumeratorList) == 0]
863e5c31af7Sopenharmony_ci			for er in enumsToRemove:
864e5c31af7Sopenharmony_ci				self.enums.remove(er)
865e5c31af7Sopenharmony_ci
866e5c31af7Sopenharmony_ci			# add alias for VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR (in vk.xml for this struct alias is defined before struct
867e5c31af7Sopenharmony_ci			# where in all other cases it is defined after structure definition)
868e5c31af7Sopenharmony_ci			barycentricFeaturesStruct = [c for c in api.compositeTypes if c.name == 'VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR'][0]
869e5c31af7Sopenharmony_ci			barycentricFeaturesStruct.aliasList.append('VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV')
870e5c31af7Sopenharmony_ci
871e5c31af7Sopenharmony_ci		elif self.apiName == "vulkansc":
872e5c31af7Sopenharmony_ci			# remove commands that are marked with <remove> tag in SC feature specification;
873e5c31af7Sopenharmony_ci			# e.g. there is no vkCreateShaderModule in SC
874e5c31af7Sopenharmony_ci			functionsToRemove = []
875e5c31af7Sopenharmony_ci			scFeatures = [f for f in self.features if f.api == "vulkansc"][0]
876e5c31af7Sopenharmony_ci			for featureRequirement in scFeatures.requirementsList:
877e5c31af7Sopenharmony_ci				if featureRequirement.operation == "remove":
878e5c31af7Sopenharmony_ci					for removeFun in featureRequirement.commandList:
879e5c31af7Sopenharmony_ci						# find function in the list of all functions
880e5c31af7Sopenharmony_ci						for fun in self.functions:
881e5c31af7Sopenharmony_ci							if removeFun == fun.name:
882e5c31af7Sopenharmony_ci								functionsToRemove.append(fun)
883e5c31af7Sopenharmony_ci								break
884e5c31af7Sopenharmony_ci			for fun in functionsToRemove:
885e5c31af7Sopenharmony_ci				self.functions.remove(fun)
886e5c31af7Sopenharmony_ci			# sc is based on vk1.2 so we need to check features of vk1.3+
887e5c31af7Sopenharmony_ci			# and rename functions and structures that were promoted in
888e5c31af7Sopenharmony_ci			# those versions to their previous names (aliases)
889e5c31af7Sopenharmony_ci			renamedStructuresDict = {}
890e5c31af7Sopenharmony_ci			for feature in self.features:
891e5c31af7Sopenharmony_ci				# skip vk versions smaller than 1.3
892e5c31af7Sopenharmony_ci				if int(feature.number[-1]) < 3:
893e5c31af7Sopenharmony_ci					continue
894e5c31af7Sopenharmony_ci				# iterate over all requirements and enums/commands/structs added in them
895e5c31af7Sopenharmony_ci				for featureRequirement in feature.requirementsList:
896e5c31af7Sopenharmony_ci					for promotedEnumerator in featureRequirement.enumList:
897e5c31af7Sopenharmony_ci						# iterate over all enums and find one that was extended
898e5c31af7Sopenharmony_ci						for enum in self.enums:
899e5c31af7Sopenharmony_ci							if enum.name != promotedEnumerator.extends:
900e5c31af7Sopenharmony_ci								continue
901e5c31af7Sopenharmony_ci							enumeratorReplaced = False
902e5c31af7Sopenharmony_ci							# find enumerator that should have changed name
903e5c31af7Sopenharmony_ci							for enumerator in enum.enumeratorList:
904e5c31af7Sopenharmony_ci								if enumerator.name != promotedEnumerator.name or len(enumerator.aliasList) == 0:
905e5c31af7Sopenharmony_ci									continue
906e5c31af7Sopenharmony_ci								# replace enumerator name with its first alias
907e5c31af7Sopenharmony_ci								enumerator.name = enumerator.aliasList[0]
908e5c31af7Sopenharmony_ci								enumerator.aliasList = enumerator.aliasList[1:]
909e5c31af7Sopenharmony_ci								# first member of almost all structures is VkStructureType and in xml that member
910e5c31af7Sopenharmony_ci								# has defined value - we need to change those values to versions supported by SC
911e5c31af7Sopenharmony_ci								if "STRUCTURE_TYPE" in enumerator.name:
912e5c31af7Sopenharmony_ci									for struct in self.compositeTypes:
913e5c31af7Sopenharmony_ci										if struct.members[0].values == promotedEnumerator.name:
914e5c31af7Sopenharmony_ci											struct.members[0].values = enumerator.name
915e5c31af7Sopenharmony_ci											break
916e5c31af7Sopenharmony_ci								enumeratorReplaced = True
917e5c31af7Sopenharmony_ci								break
918e5c31af7Sopenharmony_ci							if enumeratorReplaced:
919e5c31af7Sopenharmony_ci								break
920e5c31af7Sopenharmony_ci					renamedFunctionsList = []
921e5c31af7Sopenharmony_ci					for promotedFun in featureRequirement.commandList:
922e5c31af7Sopenharmony_ci						# find promotedFun in list of all functions
923e5c31af7Sopenharmony_ci						for fun in self.functions:
924e5c31af7Sopenharmony_ci							if fun.name != promotedFun:
925e5c31af7Sopenharmony_ci								continue
926e5c31af7Sopenharmony_ci							# replace function name with its first alias
927e5c31af7Sopenharmony_ci							fun.name = fun.aliasList[0]
928e5c31af7Sopenharmony_ci							fun.aliasList = fun.aliasList[1:]
929e5c31af7Sopenharmony_ci							# memorize renamed functions
930e5c31af7Sopenharmony_ci							renamedFunctionsList.append(fun)
931e5c31af7Sopenharmony_ci							break
932e5c31af7Sopenharmony_ci					for promotedStruct in featureRequirement.typeList:
933e5c31af7Sopenharmony_ci						# find promotedStruct in list of all structures
934e5c31af7Sopenharmony_ci						for struct in self.compositeTypes:
935e5c31af7Sopenharmony_ci							if struct.name != promotedStruct:
936e5c31af7Sopenharmony_ci								continue
937e5c31af7Sopenharmony_ci							# skip structures without alias
938e5c31af7Sopenharmony_ci							if len(struct.aliasList) == 0:
939e5c31af7Sopenharmony_ci								break
940e5c31af7Sopenharmony_ci							# replace struct name with its first alias
941e5c31af7Sopenharmony_ci							struct.name = struct.aliasList[0]
942e5c31af7Sopenharmony_ci							struct.aliasList = struct.aliasList[1:]
943e5c31af7Sopenharmony_ci							# memorize all renamed structures
944e5c31af7Sopenharmony_ci							renamedStructuresDict[promotedStruct] = struct
945e5c31af7Sopenharmony_ci							# check all all renamed functions and make sure that argument types are also renamed
946e5c31af7Sopenharmony_ci							for renamedFun in renamedFunctionsList:
947e5c31af7Sopenharmony_ci								for arg in renamedFun.arguments:
948e5c31af7Sopenharmony_ci									if arg.type == promotedStruct:
949e5c31af7Sopenharmony_ci										arg.type = struct.name
950e5c31af7Sopenharmony_ci							break
951e5c31af7Sopenharmony_ci			# iterate over all renamed structures and make sure that all their attributes are also renamed
952e5c31af7Sopenharmony_ci			for newName in renamedStructuresDict:
953e5c31af7Sopenharmony_ci				for member in renamedStructuresDict[newName].members:
954e5c31af7Sopenharmony_ci					if member.type in renamedStructuresDict:
955e5c31af7Sopenharmony_ci						member.type = renamedStructuresDict[member.type].name
956e5c31af7Sopenharmony_ci
957e5c31af7Sopenharmony_ci		# remove enums that are not part of any vulkan version nor extension
958e5c31af7Sopenharmony_ci		# (SC specific enums are in vk.xml without any attribute identifying that they are SC specific; same for enums for disabled extensions)
959e5c31af7Sopenharmony_ci		def isEnumUsed(featureList, extensionList, enumName, enumAlias):
960e5c31af7Sopenharmony_ci			for feature in featureList:
961e5c31af7Sopenharmony_ci				for requirement in feature.requirementsList:
962e5c31af7Sopenharmony_ci					for typeName in requirement.typeList:
963e5c31af7Sopenharmony_ci						if (typeName == enumName) or (typeName == enumAlias):
964e5c31af7Sopenharmony_ci							return True
965e5c31af7Sopenharmony_ci			for ext in extensionList:
966e5c31af7Sopenharmony_ci				for requirement in ext.requirementsList:
967e5c31af7Sopenharmony_ci					for newType in requirement.newTypes:
968e5c31af7Sopenharmony_ci						if (newType.name == enumName) or (newType.name == enumAlias):
969e5c31af7Sopenharmony_ci							return True
970e5c31af7Sopenharmony_ci			return False
971e5c31af7Sopenharmony_ci		# do removal using above function
972e5c31af7Sopenharmony_ci		enumsToRemove = []
973e5c31af7Sopenharmony_ci		for enum in self.enums:
974e5c31af7Sopenharmony_ci			if isEnumUsed(self.features, self.extensions, enum.name, enum.alias):
975e5c31af7Sopenharmony_ci				continue
976e5c31af7Sopenharmony_ci			enumsToRemove.append(enum)
977e5c31af7Sopenharmony_ci		for er in enumsToRemove:
978e5c31af7Sopenharmony_ci			self.enums.remove(er)
979e5c31af7Sopenharmony_ci
980e5c31af7Sopenharmony_ci		# helper function that check if dependency is in list of extension
981e5c31af7Sopenharmony_ci		def isDependencyMeet(dependency, extensionList):
982e5c31af7Sopenharmony_ci			if dependency == None:
983e5c31af7Sopenharmony_ci				return True
984e5c31af7Sopenharmony_ci			# check if requirement dependencies are meet; if not then struct/function is not used
985e5c31af7Sopenharmony_ci			# note: this logic will have to changed if there are dependencies with "and/or" grammar
986e5c31af7Sopenharmony_ci			if '_VERSION_' in dependency:
987e5c31af7Sopenharmony_ci				return True
988e5c31af7Sopenharmony_ci			dependency = dependency.split(',')[0]
989e5c31af7Sopenharmony_ci			for e in extensionList:
990e5c31af7Sopenharmony_ci				if dependency == e.name:
991e5c31af7Sopenharmony_ci					return True
992e5c31af7Sopenharmony_ci			return False
993e5c31af7Sopenharmony_ci
994e5c31af7Sopenharmony_ci		# remove structures that are not part of any vulkan version nor extension
995e5c31af7Sopenharmony_ci		# (SC specific structures are in vk.xml without any attribute identifying that they are SC specific)
996e5c31af7Sopenharmony_ci		def isStructUsed(featureList, extensionList, structNameList):
997e5c31af7Sopenharmony_ci			for feature in featureList:
998e5c31af7Sopenharmony_ci				for requirement in feature.requirementsList:
999e5c31af7Sopenharmony_ci					for typeName in requirement.typeList:
1000e5c31af7Sopenharmony_ci						if typeName in structNameList:
1001e5c31af7Sopenharmony_ci							return True
1002e5c31af7Sopenharmony_ci			for ext in extensionList:
1003e5c31af7Sopenharmony_ci				for requirement in ext.requirementsList:
1004e5c31af7Sopenharmony_ci					for newType in requirement.newTypes:
1005e5c31af7Sopenharmony_ci						if newType.name in structNameList:
1006e5c31af7Sopenharmony_ci							return isDependencyMeet(requirement.depends, extensionList)
1007e5c31af7Sopenharmony_ci			return False
1008e5c31af7Sopenharmony_ci
1009e5c31af7Sopenharmony_ci		structsToRemove = []
1010e5c31af7Sopenharmony_ci		for struct in self.compositeTypes:
1011e5c31af7Sopenharmony_ci			structNameList = [struct.name] + struct.aliasList
1012e5c31af7Sopenharmony_ci			if isStructUsed(self.features, self.extensions, structNameList):
1013e5c31af7Sopenharmony_ci				continue
1014e5c31af7Sopenharmony_ci			structsToRemove.append(struct)
1015e5c31af7Sopenharmony_ci		for st in structsToRemove:
1016e5c31af7Sopenharmony_ci			self.compositeTypes.remove(st)
1017e5c31af7Sopenharmony_ci
1018e5c31af7Sopenharmony_ci		# remove commands that are not part of any vulkan version nor extension
1019e5c31af7Sopenharmony_ci		# (SC specific commands are in vk.xml without any attribute identifying that they are SC specific)
1020e5c31af7Sopenharmony_ci		def isFunctionUsed(featureList, extensionList, functionNameList):
1021e5c31af7Sopenharmony_ci			for feature in featureList:
1022e5c31af7Sopenharmony_ci				for requirement in feature.requirementsList:
1023e5c31af7Sopenharmony_ci					for commandName in requirement.commandList:
1024e5c31af7Sopenharmony_ci						if commandName in functionNameList:
1025e5c31af7Sopenharmony_ci							return True
1026e5c31af7Sopenharmony_ci			for ext in extensionList:
1027e5c31af7Sopenharmony_ci				for requirement in ext.requirementsList:
1028e5c31af7Sopenharmony_ci					for newCommand in requirement.newCommands:
1029e5c31af7Sopenharmony_ci						if newCommand.name in functionNameList:
1030e5c31af7Sopenharmony_ci							return isDependencyMeet(requirement.depends, extensionList)
1031e5c31af7Sopenharmony_ci			return False
1032e5c31af7Sopenharmony_ci
1033e5c31af7Sopenharmony_ci		functionsToRemove = []
1034e5c31af7Sopenharmony_ci		for fun in self.functions:
1035e5c31af7Sopenharmony_ci			functionNameList = [fun.name] + fun.aliasList
1036e5c31af7Sopenharmony_ci			if isFunctionUsed(self.features, self.extensions, functionNameList):
1037e5c31af7Sopenharmony_ci				continue
1038e5c31af7Sopenharmony_ci			functionsToRemove.append(fun)
1039e5c31af7Sopenharmony_ci		for fun in functionsToRemove:
1040e5c31af7Sopenharmony_ci			self.functions.remove(fun)
1041e5c31af7Sopenharmony_ci
1042e5c31af7Sopenharmony_ci		# remove handles that are not part of any vulkan command or structure
1043e5c31af7Sopenharmony_ci		def isHandleUsed(structList, functionList, handleName):
1044e5c31af7Sopenharmony_ci			for struct in structList:
1045e5c31af7Sopenharmony_ci				for member in struct.members:
1046e5c31af7Sopenharmony_ci					if handleName in member.type:
1047e5c31af7Sopenharmony_ci						return True
1048e5c31af7Sopenharmony_ci			for fun in functionList:
1049e5c31af7Sopenharmony_ci				for arg in fun.arguments:
1050e5c31af7Sopenharmony_ci					if handleName in arg.type:
1051e5c31af7Sopenharmony_ci						return True
1052e5c31af7Sopenharmony_ci			return False
1053e5c31af7Sopenharmony_ci
1054e5c31af7Sopenharmony_ci		handlesToRemove = []
1055e5c31af7Sopenharmony_ci		for h in self.handles:
1056e5c31af7Sopenharmony_ci			if isHandleUsed(self.compositeTypes, self.functions, h.name):
1057e5c31af7Sopenharmony_ci				continue
1058e5c31af7Sopenharmony_ci			handlesToRemove.append(h)
1059e5c31af7Sopenharmony_ci		for h in handlesToRemove:
1060e5c31af7Sopenharmony_ci			self.handles.remove(h)
1061e5c31af7Sopenharmony_ci
1062e5c31af7Sopenharmony_ci		# sort enumerators in enums
1063e5c31af7Sopenharmony_ci		sortLambda	= lambda enumerator: int(enumerator.bitpos) if enumerator.value is None else int(enumerator.value, 16 if 'x' in enumerator.value else 10)
1064e5c31af7Sopenharmony_ci		for enum in self.enums:
1065e5c31af7Sopenharmony_ci			# skip enums that have no items or  just one in enumeratorList (e.g. VkQueryPoolCreateFlagBits)
1066e5c31af7Sopenharmony_ci			if len(enum.enumeratorList) < 2:
1067e5c31af7Sopenharmony_ci				continue
1068e5c31af7Sopenharmony_ci			# construct list of enumerators in which value and bitpos are not None
1069e5c31af7Sopenharmony_ci			enumeratorsToSort		= [e for e in enum.enumeratorList if e.value != e.bitpos]
1070e5c31af7Sopenharmony_ci			# construct list of enumerators in which value and bitpos are equal to None
1071e5c31af7Sopenharmony_ci			remainingEnumerators	= [e for e in enum.enumeratorList if e.value == e.bitpos]
1072e5c31af7Sopenharmony_ci			# construct sorted enumerator list with aliases at the end
1073e5c31af7Sopenharmony_ci			enum.enumeratorList = sorted(enumeratorsToSort, key=sortLambda)
1074e5c31af7Sopenharmony_ci			enum.enumeratorList.extend(remainingEnumerators)
1075e5c31af7Sopenharmony_ci
1076e5c31af7Sopenharmony_cidef prefixName (prefix, name):
1077e5c31af7Sopenharmony_ci	name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name[2:])
1078e5c31af7Sopenharmony_ci	name = re.sub(r'([a-zA-Z])([0-9])', r'\1_\2', name)
1079e5c31af7Sopenharmony_ci	name = name.upper()
1080e5c31af7Sopenharmony_ci	return prefix + name
1081e5c31af7Sopenharmony_ci
1082e5c31af7Sopenharmony_cidef parseInt (value):
1083e5c31af7Sopenharmony_ci	return int(value, 16 if ("0x" in value) else 10)
1084e5c31af7Sopenharmony_ci
1085e5c31af7Sopenharmony_cidef getApiVariantIndexByName(variantName):
1086e5c31af7Sopenharmony_ci	apiVariant = {
1087e5c31af7Sopenharmony_ci		None : 0,
1088e5c31af7Sopenharmony_ci		''   : 0,
1089e5c31af7Sopenharmony_ci		'SC' : 1
1090e5c31af7Sopenharmony_ci	}
1091e5c31af7Sopenharmony_ci	return apiVariant[variantName]
1092e5c31af7Sopenharmony_ci
1093e5c31af7Sopenharmony_cidef getApiVariantNameByIndex(variantIndex):
1094e5c31af7Sopenharmony_ci	apiVariant = {
1095e5c31af7Sopenharmony_ci		None : '',
1096e5c31af7Sopenharmony_ci		0    : '',
1097e5c31af7Sopenharmony_ci		1    : 'SC'
1098e5c31af7Sopenharmony_ci	}
1099e5c31af7Sopenharmony_ci	return apiVariant[variantIndex]
1100e5c31af7Sopenharmony_ci
1101e5c31af7Sopenharmony_cidef readFile (filename):
1102e5c31af7Sopenharmony_ci	with open(filename, 'rt') as f:
1103e5c31af7Sopenharmony_ci		return f.read()
1104e5c31af7Sopenharmony_ci
1105e5c31af7Sopenharmony_cidef getInterfaceName (functionName):
1106e5c31af7Sopenharmony_ci	assert functionName[:2] == "vk"
1107e5c31af7Sopenharmony_ci	return functionName[2].lower() + functionName[3:]
1108e5c31af7Sopenharmony_ci
1109e5c31af7Sopenharmony_cidef getFunctionTypeName (functionName):
1110e5c31af7Sopenharmony_ci	assert functionName[:2] == "vk"
1111e5c31af7Sopenharmony_ci	return functionName[2:] + "Func"
1112e5c31af7Sopenharmony_ci
1113e5c31af7Sopenharmony_cidef endsWith (str, postfix):
1114e5c31af7Sopenharmony_ci	return str[-len(postfix):] == postfix
1115e5c31af7Sopenharmony_ci
1116e5c31af7Sopenharmony_cidef writeHandleType (api, filename):
1117e5c31af7Sopenharmony_ci
1118e5c31af7Sopenharmony_ci	def getHandleName (name):
1119e5c31af7Sopenharmony_ci		return prefixName("HANDLE_TYPE_", name)
1120e5c31af7Sopenharmony_ci
1121e5c31af7Sopenharmony_ci	def genHandles ():
1122e5c31af7Sopenharmony_ci		yield "\t%s\t= 0," % getHandleName(api.handles[0].name)
1123e5c31af7Sopenharmony_ci		for h in api.handles[1:]:
1124e5c31af7Sopenharmony_ci			yield "\t%s," % getHandleName(h.name)
1125e5c31af7Sopenharmony_ci		for h in api.handles:
1126e5c31af7Sopenharmony_ci			if h.alias is not None:
1127e5c31af7Sopenharmony_ci				yield "\t%s\t= %s," % (getHandleName(h.alias), getHandleName(h.name))
1128e5c31af7Sopenharmony_ci		yield "\tHANDLE_TYPE_LAST\t= %s + 1" % (getHandleName(api.handles[-1].name))
1129e5c31af7Sopenharmony_ci
1130e5c31af7Sopenharmony_ci	def genHandlesBlock ():
1131e5c31af7Sopenharmony_ci		yield "enum HandleType"
1132e5c31af7Sopenharmony_ci		yield "{"
1133e5c31af7Sopenharmony_ci
1134e5c31af7Sopenharmony_ci		for line in indentLines(genHandles()):
1135e5c31af7Sopenharmony_ci			yield line
1136e5c31af7Sopenharmony_ci
1137e5c31af7Sopenharmony_ci		yield "};"
1138e5c31af7Sopenharmony_ci		yield ""
1139e5c31af7Sopenharmony_ci
1140e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, genHandlesBlock())
1141e5c31af7Sopenharmony_ci
1142e5c31af7Sopenharmony_cidef getEnumValuePrefixAndPostfix (enum):
1143e5c31af7Sopenharmony_ci	prefix = enum.name[0]
1144e5c31af7Sopenharmony_ci	for i in range(1, len(enum.name)):
1145e5c31af7Sopenharmony_ci		if enum.name[i].isupper() and not enum.name[i-1].isupper():
1146e5c31af7Sopenharmony_ci			prefix += "_"
1147e5c31af7Sopenharmony_ci		prefix += enum.name[i].upper()
1148e5c31af7Sopenharmony_ci	for p in EXTENSION_POSTFIXES:
1149e5c31af7Sopenharmony_ci		if prefix.endswith(p):
1150e5c31af7Sopenharmony_ci			return prefix[:-len(p)-1], '_'+p
1151e5c31af7Sopenharmony_ci	return prefix, ''
1152e5c31af7Sopenharmony_ci
1153e5c31af7Sopenharmony_cidef genEnumSrc (enum):
1154e5c31af7Sopenharmony_ci	yield "enum %s" % enum.name
1155e5c31af7Sopenharmony_ci	yield "{"
1156e5c31af7Sopenharmony_ci	lines = []
1157e5c31af7Sopenharmony_ci	for ed in enum.enumeratorList:
1158e5c31af7Sopenharmony_ci		if ed.value is not None:
1159e5c31af7Sopenharmony_ci			lines.append(f"\t{ed.name}\t= {ed.value},")
1160e5c31af7Sopenharmony_ci	for ed in enum.enumeratorList:
1161e5c31af7Sopenharmony_ci		for alias in ed.aliasList:
1162e5c31af7Sopenharmony_ci			lines.append(f"\t{alias}\t= {ed.name},")
1163e5c31af7Sopenharmony_ci
1164e5c31af7Sopenharmony_ci	# add *_LAST item when enum is linear
1165e5c31af7Sopenharmony_ci	prefix, postfix = getEnumValuePrefixAndPostfix(enum)
1166e5c31af7Sopenharmony_ci	if enum.areValuesLinear():
1167e5c31af7Sopenharmony_ci		lines.append(f"\t{prefix}{postfix}_LAST,")
1168e5c31af7Sopenharmony_ci
1169e5c31af7Sopenharmony_ci	# add _MAX_ENUM item with the ext postifix at the end
1170e5c31af7Sopenharmony_ci	lines.append(f"\t{prefix}_MAX_ENUM{postfix}\t= 0x7FFFFFFF")
1171e5c31af7Sopenharmony_ci
1172e5c31af7Sopenharmony_ci	for line in indentLines(lines):
1173e5c31af7Sopenharmony_ci		yield line
1174e5c31af7Sopenharmony_ci
1175e5c31af7Sopenharmony_ci	yield "};"
1176e5c31af7Sopenharmony_ci
1177e5c31af7Sopenharmony_cidef genBitfieldSrc (bitfield):
1178e5c31af7Sopenharmony_ci	lines = []
1179e5c31af7Sopenharmony_ci	for ev in bitfield.enumeratorList:
1180e5c31af7Sopenharmony_ci		# bitfields may use mix of bitpos and values
1181e5c31af7Sopenharmony_ci		if ev.bitpos is not None:
1182e5c31af7Sopenharmony_ci			value = pow(2, int(ev.bitpos))
1183e5c31af7Sopenharmony_ci			lines.append(f"\t{ev.name}\t= {value:#010x},")
1184e5c31af7Sopenharmony_ci		if ev.value is not None:
1185e5c31af7Sopenharmony_ci			lines.append(f"\t{ev.name}\t= {ev.value},")
1186e5c31af7Sopenharmony_ci	for ev in bitfield.enumeratorList:
1187e5c31af7Sopenharmony_ci		for alias in ev.aliasList:
1188e5c31af7Sopenharmony_ci			lines.append(f"\t{alias}\t= {ev.name},")
1189e5c31af7Sopenharmony_ci	# add _MAX_ENUM item
1190e5c31af7Sopenharmony_ci	prefix, postfix = getEnumValuePrefixAndPostfix(bitfield)
1191e5c31af7Sopenharmony_ci	lines.append(f"\t{prefix}_MAX_ENUM{postfix}\t= 0x7FFFFFFF")
1192e5c31af7Sopenharmony_ci	yield f"enum {bitfield.name}"
1193e5c31af7Sopenharmony_ci	yield "{"
1194e5c31af7Sopenharmony_ci	for line in indentLines(lines):
1195e5c31af7Sopenharmony_ci		yield line
1196e5c31af7Sopenharmony_ci	yield "};"
1197e5c31af7Sopenharmony_ci
1198e5c31af7Sopenharmony_cidef genBitfield64Src (bitfield64):
1199e5c31af7Sopenharmony_ci	def generateEntry(lines, bitfieldName, entryName, bitpos, value):
1200e5c31af7Sopenharmony_ci		if entryName is None:
1201e5c31af7Sopenharmony_ci			return
1202e5c31af7Sopenharmony_ci		# bitfields may use mix of bitpos and values
1203e5c31af7Sopenharmony_ci		if ev.bitpos is not None:
1204e5c31af7Sopenharmony_ci			v = pow(2, int(bitpos))
1205e5c31af7Sopenharmony_ci			lines.append(f"static const {bitfieldName} {entryName}\t= {v:#010x}ULL;")
1206e5c31af7Sopenharmony_ci		if value is not None:
1207e5c31af7Sopenharmony_ci			lines.append(f"static const {bitfieldName} {entryName}\t= {value}ULL;")
1208e5c31af7Sopenharmony_ci
1209e5c31af7Sopenharmony_ci	yield f"typedef uint64_t {bitfield64.name};"
1210e5c31af7Sopenharmony_ci	lines = []
1211e5c31af7Sopenharmony_ci	for ev in bitfield64.enumeratorList:
1212e5c31af7Sopenharmony_ci		generateEntry(lines, bitfield64.name, ev.name,  ev.bitpos, ev.value)
1213e5c31af7Sopenharmony_ci		for alias in ev.aliasList:
1214e5c31af7Sopenharmony_ci			generateEntry(lines, bitfield64.name, alias, ev.bitpos, ev.value)
1215e5c31af7Sopenharmony_ci	# write indented lines
1216e5c31af7Sopenharmony_ci	for line in indentLines(lines):
1217e5c31af7Sopenharmony_ci		yield line
1218e5c31af7Sopenharmony_ci	yield ""
1219e5c31af7Sopenharmony_ci
1220e5c31af7Sopenharmony_cidef genDefinesSrc (apiName, defines):
1221e5c31af7Sopenharmony_ci	def genLines (defines):
1222e5c31af7Sopenharmony_ci		for d in defines:
1223e5c31af7Sopenharmony_ci			if d.alias is not None:
1224e5c31af7Sopenharmony_ci				continue
1225e5c31af7Sopenharmony_ci			defineType = DEFINITIONS.get(d.name, d.type)
1226e5c31af7Sopenharmony_ci			yield f"#define {d.name}\t(static_cast<{defineType}>\t({d.value}))"
1227e5c31af7Sopenharmony_ci	for line in indentLines(genLines(defines)):
1228e5c31af7Sopenharmony_ci		yield line
1229e5c31af7Sopenharmony_ci	# add VK_API_MAX_FRAMEWORK_VERSION
1230e5c31af7Sopenharmony_ci	major, minor = api.features[-1].number.split('.')
1231e5c31af7Sopenharmony_ci	yield f"#define VK{apiName}_API_MAX_FRAMEWORK_VERSION\tVK{apiName}_API_VERSION_{major}_{minor}"
1232e5c31af7Sopenharmony_ci
1233e5c31af7Sopenharmony_cidef genHandlesSrc (handles):
1234e5c31af7Sopenharmony_ci	def genLines (handles):
1235e5c31af7Sopenharmony_ci		for h in handles:
1236e5c31af7Sopenharmony_ci			handleType = h.type
1237e5c31af7Sopenharmony_ci			handleObjtype = h.objtypeenum
1238e5c31af7Sopenharmony_ci			if h.alias is not None:
1239e5c31af7Sopenharmony_ci				# search for aliased handle
1240e5c31af7Sopenharmony_ci				for searchedHandle in handles:
1241e5c31af7Sopenharmony_ci					if h.alias == searchedHandle.name:
1242e5c31af7Sopenharmony_ci						handleType = searchedHandle.type
1243e5c31af7Sopenharmony_ci						handleObjtype = searchedHandle.objtypeenum
1244e5c31af7Sopenharmony_ci						break
1245e5c31af7Sopenharmony_ci			yield f"{handleType}\t({h.name},\tHANDLE{handleObjtype[9:]});"
1246e5c31af7Sopenharmony_ci	for line in indentLines(genLines(handles)):
1247e5c31af7Sopenharmony_ci		yield line
1248e5c31af7Sopenharmony_ci
1249e5c31af7Sopenharmony_cidef genHandlesSrc (handles):
1250e5c31af7Sopenharmony_ci	def genLines (handles):
1251e5c31af7Sopenharmony_ci		for h in handles:
1252e5c31af7Sopenharmony_ci			handleType    = h.type
1253e5c31af7Sopenharmony_ci			handleObjtype = h.objtypeenum
1254e5c31af7Sopenharmony_ci			line = f"{handleType}\t({{}},\tHANDLE{handleObjtype[9:]});"
1255e5c31af7Sopenharmony_ci			yield line.format(h.name)
1256e5c31af7Sopenharmony_ci			if h.alias is not None:
1257e5c31af7Sopenharmony_ci				yield line.format(h.alias)
1258e5c31af7Sopenharmony_ci
1259e5c31af7Sopenharmony_ci	for line in indentLines(genLines(handles)):
1260e5c31af7Sopenharmony_ci		yield line
1261e5c31af7Sopenharmony_ci
1262e5c31af7Sopenharmony_cidef writeBasicTypes (api, filename):
1263e5c31af7Sopenharmony_ci
1264e5c31af7Sopenharmony_ci	def gen ():
1265e5c31af7Sopenharmony_ci
1266e5c31af7Sopenharmony_ci		for line in genDefinesSrc("SC" if api.apiName == "vulkansc" else "", api.defines):
1267e5c31af7Sopenharmony_ci			yield line
1268e5c31af7Sopenharmony_ci		yield ""
1269e5c31af7Sopenharmony_ci
1270e5c31af7Sopenharmony_ci		for line in genHandlesSrc(api.handles):
1271e5c31af7Sopenharmony_ci			yield line
1272e5c31af7Sopenharmony_ci		yield ""
1273e5c31af7Sopenharmony_ci
1274e5c31af7Sopenharmony_ci		for enum in api.enums:
1275e5c31af7Sopenharmony_ci			# skip empty enums only for vulkan
1276e5c31af7Sopenharmony_ci			# vulkan_json_data.hpp and vulkan_json_parser.hpp in SC need many empty enums
1277e5c31af7Sopenharmony_ci			if len(enum.enumeratorList) == 0 and api.apiName == "vulkan":
1278e5c31af7Sopenharmony_ci				continue
1279e5c31af7Sopenharmony_ci			if enum.type == "bitmask":
1280e5c31af7Sopenharmony_ci				if enum.bitwidth == "32":
1281e5c31af7Sopenharmony_ci					for line in genBitfieldSrc(enum):
1282e5c31af7Sopenharmony_ci						yield line
1283e5c31af7Sopenharmony_ci				else:
1284e5c31af7Sopenharmony_ci					for line in genBitfield64Src(enum):
1285e5c31af7Sopenharmony_ci						yield line
1286e5c31af7Sopenharmony_ci			else:
1287e5c31af7Sopenharmony_ci				for line in genEnumSrc(enum):
1288e5c31af7Sopenharmony_ci					yield line
1289e5c31af7Sopenharmony_ci			if enum.alias is not None:
1290e5c31af7Sopenharmony_ci				yield f"typedef {enum.name} {enum.alias};"
1291e5c31af7Sopenharmony_ci			yield ""
1292e5c31af7Sopenharmony_ci
1293e5c31af7Sopenharmony_ci		for bitmask in api.bitmasks:
1294e5c31af7Sopenharmony_ci			plainType = api.basetypes[bitmask.type]
1295e5c31af7Sopenharmony_ci			yield f"typedef {plainType} {bitmask.name};\n"
1296e5c31af7Sopenharmony_ci			if bitmask.alias:
1297e5c31af7Sopenharmony_ci				yield f"typedef {bitmask.name} {bitmask.alias};\n"
1298e5c31af7Sopenharmony_ci
1299e5c31af7Sopenharmony_ci		yield ""
1300e5c31af7Sopenharmony_ci		for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s)" % (s[0], c) for n, s, c in PLATFORM_TYPES]):
1301e5c31af7Sopenharmony_ci			yield line
1302e5c31af7Sopenharmony_ci		yield ""
1303e5c31af7Sopenharmony_ci
1304e5c31af7Sopenharmony_ci		for ext in api.extensions:
1305e5c31af7Sopenharmony_ci			firstRequirementEnums = ext.requirementsList[0].extendedEnums
1306e5c31af7Sopenharmony_ci			for e in firstRequirementEnums:
1307e5c31af7Sopenharmony_ci				if e.extends is None and e.value is not None:
1308e5c31af7Sopenharmony_ci					yield "#define " + e.name + " " + e.value
1309e5c31af7Sopenharmony_ci
1310e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, gen())
1311e5c31af7Sopenharmony_ci
1312e5c31af7Sopenharmony_cidef writeCompositeTypes (api, filename):
1313e5c31af7Sopenharmony_ci	# function that returns definition of structure member
1314e5c31af7Sopenharmony_ci	def memberAsString (member):
1315e5c31af7Sopenharmony_ci		result = ''
1316e5c31af7Sopenharmony_ci		if member.qualifiers:
1317e5c31af7Sopenharmony_ci			result += member.qualifiers
1318e5c31af7Sopenharmony_ci		result += member.type
1319e5c31af7Sopenharmony_ci		if member.pointer:
1320e5c31af7Sopenharmony_ci			result += member.pointer
1321e5c31af7Sopenharmony_ci		result += '\t' + member.name
1322e5c31af7Sopenharmony_ci		for size in member.arraySizeList:
1323e5c31af7Sopenharmony_ci			result += f"[{size}]"
1324e5c31af7Sopenharmony_ci		if member.fieldWidth:
1325e5c31af7Sopenharmony_ci			result += f":{member.fieldWidth}"
1326e5c31af7Sopenharmony_ci		return result
1327e5c31af7Sopenharmony_ci
1328e5c31af7Sopenharmony_ci	# function that prints single structure definition
1329e5c31af7Sopenharmony_ci	def genCompositeTypeSrc (type):
1330e5c31af7Sopenharmony_ci		structLines = "%s %s\n{\n" % (type.category, type.name)
1331e5c31af7Sopenharmony_ci		for line in indentLines(['\t'+memberAsString(m)+';' for m in type.members]):
1332e5c31af7Sopenharmony_ci			structLines += line + '\n'
1333e5c31af7Sopenharmony_ci		return structLines + "};\n"
1334e5c31af7Sopenharmony_ci
1335e5c31af7Sopenharmony_ci	# function that prints all structure definitions and alias typedefs
1336e5c31af7Sopenharmony_ci	def gen ():
1337e5c31af7Sopenharmony_ci		# structures in xml are not ordered in a correct way for C++
1338e5c31af7Sopenharmony_ci		# we need to save structures that are used in other structures first
1339e5c31af7Sopenharmony_ci		allStructureNamesList = [s.name for s in api.compositeTypes]
1340e5c31af7Sopenharmony_ci		commonTypesList = api.basicCTypes + ['VkStructureType']
1341e5c31af7Sopenharmony_ci		savedStructureNamesList = []
1342e5c31af7Sopenharmony_ci		delayedStructureObjectsList = []
1343e5c31af7Sopenharmony_ci
1344e5c31af7Sopenharmony_ci		# helper function that checks if all structure members were already saved
1345e5c31af7Sopenharmony_ci		def canStructBeSaved(compositeObject):
1346e5c31af7Sopenharmony_ci			for m in compositeObject.members:
1347e5c31af7Sopenharmony_ci				# check first commonTypesList to speed up the algorithm
1348e5c31af7Sopenharmony_ci				if m.type in commonTypesList:
1349e5c31af7Sopenharmony_ci					continue
1350e5c31af7Sopenharmony_ci				# make sure that member is not of same type as compositeObject
1351e5c31af7Sopenharmony_ci				# (this hadles cases like VkBaseOutStructure)
1352e5c31af7Sopenharmony_ci				if m.type == compositeObject.name:
1353e5c31af7Sopenharmony_ci					continue
1354e5c31af7Sopenharmony_ci				# if member is of compositeType that was not saved we cant save it now
1355e5c31af7Sopenharmony_ci				if m.type in allStructureNamesList and m.type not in savedStructureNamesList:
1356e5c31af7Sopenharmony_ci					return False
1357e5c31af7Sopenharmony_ci			return True
1358e5c31af7Sopenharmony_ci
1359e5c31af7Sopenharmony_ci		# iterate over all composite types
1360e5c31af7Sopenharmony_ci		lastDelayedComposite = None
1361e5c31af7Sopenharmony_ci		for ct in api.compositeTypes:
1362e5c31af7Sopenharmony_ci			# check if one of delayed structures can be saved
1363e5c31af7Sopenharmony_ci			delayedButSaved = []
1364e5c31af7Sopenharmony_ci			for dct in delayedStructureObjectsList:
1365e5c31af7Sopenharmony_ci				if lastDelayedComposite != dct and canStructBeSaved(dct):
1366e5c31af7Sopenharmony_ci					yield genCompositeTypeSrc(dct)
1367e5c31af7Sopenharmony_ci					delayedButSaved.append(dct)
1368e5c31af7Sopenharmony_ci			lastDelayedComposite = None
1369e5c31af7Sopenharmony_ci			for dsct in delayedButSaved:
1370e5c31af7Sopenharmony_ci				savedStructureNamesList.append(dsct.name)
1371e5c31af7Sopenharmony_ci				delayedStructureObjectsList.remove(dsct)
1372e5c31af7Sopenharmony_ci			# check if current structure can be saved
1373e5c31af7Sopenharmony_ci			if canStructBeSaved(ct):
1374e5c31af7Sopenharmony_ci				yield genCompositeTypeSrc(ct)
1375e5c31af7Sopenharmony_ci				savedStructureNamesList.append(ct.name)
1376e5c31af7Sopenharmony_ci			else:
1377e5c31af7Sopenharmony_ci				delayedStructureObjectsList.append(ct)
1378e5c31af7Sopenharmony_ci				# memorize structure that was delayed in last iteration to
1379e5c31af7Sopenharmony_ci				# avoid calling for it canStructBeSaved in next iteration
1380e5c31af7Sopenharmony_ci				lastDelayedComposite = ct
1381e5c31af7Sopenharmony_ci		# save remaining delayed composite types (~4 video related structures)
1382e5c31af7Sopenharmony_ci		while len(delayedStructureObjectsList) > 0:
1383e5c31af7Sopenharmony_ci			for dct in delayedStructureObjectsList:
1384e5c31af7Sopenharmony_ci				if canStructBeSaved(dct):
1385e5c31af7Sopenharmony_ci					yield genCompositeTypeSrc(dct)
1386e5c31af7Sopenharmony_ci					savedStructureNamesList.append(dct.name)
1387e5c31af7Sopenharmony_ci					delayedStructureObjectsList.remove(dct)
1388e5c31af7Sopenharmony_ci					break
1389e5c31af7Sopenharmony_ci		# write all alias typedefs
1390e5c31af7Sopenharmony_ci		for ct in api.compositeTypes:
1391e5c31af7Sopenharmony_ci			for alias in ct.aliasList:
1392e5c31af7Sopenharmony_ci				yield "typedef %s %s;" % (ct.name, alias)
1393e5c31af7Sopenharmony_ci				yield ""
1394e5c31af7Sopenharmony_ci
1395e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, gen())
1396e5c31af7Sopenharmony_ci
1397e5c31af7Sopenharmony_cidef argListToStr (args):
1398e5c31af7Sopenharmony_ci	def argumentToString(arg):
1399e5c31af7Sopenharmony_ci		# args can be instance of FunctionArgument or CompositeMember
1400e5c31af7Sopenharmony_ci		# but CompositeMember has no arraySize atrribute nor secondPointerIsConst
1401e5c31af7Sopenharmony_ci		workingOnFunctionArgument = True if hasattr(arg, 'arraySize') else False
1402e5c31af7Sopenharmony_ci		result = ''
1403e5c31af7Sopenharmony_ci		if arg.qualifiers:
1404e5c31af7Sopenharmony_ci			result += arg.qualifiers
1405e5c31af7Sopenharmony_ci		result += arg.type
1406e5c31af7Sopenharmony_ci		if arg.pointer:
1407e5c31af7Sopenharmony_ci			if workingOnFunctionArgument and arg.secondPointerIsConst:
1408e5c31af7Sopenharmony_ci				result += '* const*'
1409e5c31af7Sopenharmony_ci			else:
1410e5c31af7Sopenharmony_ci				result += arg.pointer
1411e5c31af7Sopenharmony_ci		result += ' ' + arg.name
1412e5c31af7Sopenharmony_ci		if workingOnFunctionArgument:
1413e5c31af7Sopenharmony_ci			if arg.arraySize:
1414e5c31af7Sopenharmony_ci				result += arg.arraySize
1415e5c31af7Sopenharmony_ci		return result
1416e5c31af7Sopenharmony_ci	return ", ".join(argumentToString(arg) for arg in args)
1417e5c31af7Sopenharmony_ci
1418e5c31af7Sopenharmony_cidef writeInterfaceDecl (api, filename, functionTypes, concrete):
1419e5c31af7Sopenharmony_ci	def genProtos ():
1420e5c31af7Sopenharmony_ci		postfix = "" if concrete else " = 0"
1421e5c31af7Sopenharmony_ci		for function in api.functions:
1422e5c31af7Sopenharmony_ci			if not function.getType() in functionTypes:
1423e5c31af7Sopenharmony_ci				continue
1424e5c31af7Sopenharmony_ci			yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function.name), argListToStr(function.arguments), postfix)
1425e5c31af7Sopenharmony_ci
1426e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
1427e5c31af7Sopenharmony_ci
1428e5c31af7Sopenharmony_cidef writeFunctionPtrTypes (api, filename):
1429e5c31af7Sopenharmony_ci	def genTypes ():
1430e5c31af7Sopenharmony_ci		pattern = "typedef VKAPI_ATTR {}\t(VKAPI_CALL* {})\t({});"
1431e5c31af7Sopenharmony_ci		for function in api.functions:
1432e5c31af7Sopenharmony_ci			argList = argListToStr(function.arguments)
1433e5c31af7Sopenharmony_ci			yield pattern.format(function.returnType, getFunctionTypeName(function.name), argList)
1434e5c31af7Sopenharmony_ci			for alias in function.aliasList:
1435e5c31af7Sopenharmony_ci				yield pattern.format(function.returnType, getFunctionTypeName(alias), argList)
1436e5c31af7Sopenharmony_ci
1437e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
1438e5c31af7Sopenharmony_ci
1439e5c31af7Sopenharmony_cidef writeFunctionPointers (api, filename, functionTypes):
1440e5c31af7Sopenharmony_ci	def FunctionsYielder ():
1441e5c31af7Sopenharmony_ci		for function in api.functions:
1442e5c31af7Sopenharmony_ci			if function.getType() in functionTypes:
1443e5c31af7Sopenharmony_ci				interfaceName		= getInterfaceName(function.name)
1444e5c31af7Sopenharmony_ci				functionTypeName	= getFunctionTypeName(function.name)
1445e5c31af7Sopenharmony_ci				yield f"{functionTypeName}\t{interfaceName};"
1446e5c31af7Sopenharmony_ci				if function.getType() == Function.TYPE_INSTANCE:
1447e5c31af7Sopenharmony_ci					for alias in function.aliasList:
1448e5c31af7Sopenharmony_ci						interfaceName		= getInterfaceName(alias)
1449e5c31af7Sopenharmony_ci						functionTypeName	= getFunctionTypeName(alias)
1450e5c31af7Sopenharmony_ci						yield f"{functionTypeName}\t{interfaceName};"
1451e5c31af7Sopenharmony_ci
1452e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, indentLines(FunctionsYielder()))
1453e5c31af7Sopenharmony_ci
1454e5c31af7Sopenharmony_cidef getPromotedFunctions (api):
1455e5c31af7Sopenharmony_ci	apiNum = 0 if api.apiName == "vulkan" else 1
1456e5c31af7Sopenharmony_ci	promotedFunctions = collections.defaultdict(lambda: list())
1457e5c31af7Sopenharmony_ci	for feature in api.features:
1458e5c31af7Sopenharmony_ci		versionSplit = feature.name.split('_')
1459e5c31af7Sopenharmony_ci		apiMajor = versionSplit[-2]
1460e5c31af7Sopenharmony_ci		apiMinor = versionSplit[-1]
1461e5c31af7Sopenharmony_ci		apituple = (apiNum, apiMajor, apiMinor)
1462e5c31af7Sopenharmony_ci		for featureRequirement in feature.requirementsList:
1463e5c31af7Sopenharmony_ci			for promotedFun in featureRequirement.commandList:
1464e5c31af7Sopenharmony_ci				promotedFunctions[promotedFun].append(apituple)
1465e5c31af7Sopenharmony_ci	return promotedFunctions
1466e5c31af7Sopenharmony_ci
1467e5c31af7Sopenharmony_cidef writeInitFunctionPointers (api, filename, functionTypes, cond = None):
1468e5c31af7Sopenharmony_ci	promotedFunctions = getPromotedFunctions(api) if Function.TYPE_DEVICE in functionTypes else None
1469e5c31af7Sopenharmony_ci	def makeInitFunctionPointers ():
1470e5c31af7Sopenharmony_ci		for function in api.functions:
1471e5c31af7Sopenharmony_ci			if function.getType() in functionTypes and (cond == None or cond(function)):
1472e5c31af7Sopenharmony_ci				condition = ''
1473e5c31af7Sopenharmony_ci				if function.getType() == Function.TYPE_DEVICE:
1474e5c31af7Sopenharmony_ci					versionCheck = ''
1475e5c31af7Sopenharmony_ci					if function.name in promotedFunctions:
1476e5c31af7Sopenharmony_ci						for versionTuple in promotedFunctions[function.name]:
1477e5c31af7Sopenharmony_ci							if len(versionCheck) > 0:
1478e5c31af7Sopenharmony_ci								versionCheck += ' || '
1479e5c31af7Sopenharmony_ci							versionCheck = 'usedApiVersion >= VK_MAKE_API_VERSION(%s, %s, %s, 0)' % versionTuple
1480e5c31af7Sopenharmony_ci					if len(versionCheck) > 0:
1481e5c31af7Sopenharmony_ci						condition = f"if ({versionCheck})\n    "
1482e5c31af7Sopenharmony_ci				interfaceName		= getInterfaceName(function.name)
1483e5c31af7Sopenharmony_ci				functionTypeName	= getFunctionTypeName(function.name)
1484e5c31af7Sopenharmony_ci				yield f"{condition}m_vk.{interfaceName} = ({functionTypeName}) GET_PROC_ADDR(\"{function.name}\");"
1485e5c31af7Sopenharmony_ci				for alias in function.aliasList:
1486e5c31af7Sopenharmony_ci					yield f"if (!m_vk.{interfaceName})"
1487e5c31af7Sopenharmony_ci					yield f"    m_vk.{interfaceName} = ({functionTypeName}) GET_PROC_ADDR(\"{alias}\");"
1488e5c31af7Sopenharmony_ci					if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].type == "VkPhysicalDevice":
1489e5c31af7Sopenharmony_ci						interfaceName		= getInterfaceName(alias)
1490e5c31af7Sopenharmony_ci						functionTypeName	= getFunctionTypeName(alias)
1491e5c31af7Sopenharmony_ci						yield f"m_vk.{interfaceName} = ({functionTypeName}) GET_PROC_ADDR(\"{alias}\");"
1492e5c31af7Sopenharmony_ci
1493e5c31af7Sopenharmony_ci	lines = makeInitFunctionPointers()
1494e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, lines)
1495e5c31af7Sopenharmony_ci
1496e5c31af7Sopenharmony_cidef writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
1497e5c31af7Sopenharmony_ci	def makeFuncPtrInterfaceImpl ():
1498e5c31af7Sopenharmony_ci		for function in api.functions:
1499e5c31af7Sopenharmony_ci			if function.getType() in functionTypes:
1500e5c31af7Sopenharmony_ci				yield ""
1501e5c31af7Sopenharmony_ci				yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function.name), argListToStr(function.arguments))
1502e5c31af7Sopenharmony_ci				yield "{"
1503e5c31af7Sopenharmony_ci				if function.name == "vkEnumerateInstanceVersion":
1504e5c31af7Sopenharmony_ci					yield "	if (m_vk.enumerateInstanceVersion)"
1505e5c31af7Sopenharmony_ci					yield "		return m_vk.enumerateInstanceVersion(pApiVersion);"
1506e5c31af7Sopenharmony_ci					yield ""
1507e5c31af7Sopenharmony_ci					yield "	*pApiVersion = VK_API_VERSION_1_0;"
1508e5c31af7Sopenharmony_ci					yield "	return VK_SUCCESS;"
1509e5c31af7Sopenharmony_ci				elif function.getType() == Function.TYPE_INSTANCE and function.arguments[0].type == "VkPhysicalDevice" and len(function.aliasList) > 0:
1510e5c31af7Sopenharmony_ci					yield "	vk::VkPhysicalDeviceProperties props;"
1511e5c31af7Sopenharmony_ci					yield "	m_vk.getPhysicalDeviceProperties(physicalDevice, &props);"
1512e5c31af7Sopenharmony_ci					yield "	if (props.apiVersion >= VK_API_VERSION_1_1)"
1513e5c31af7Sopenharmony_ci					yield "		%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.name), ", ".join(a.name for a in function.arguments))
1514e5c31af7Sopenharmony_ci					yield "	else"
1515e5c31af7Sopenharmony_ci					yield "		%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.aliasList[0]), ", ".join(a.name for a in function.arguments))
1516e5c31af7Sopenharmony_ci				else:
1517e5c31af7Sopenharmony_ci					yield "	%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.name), ", ".join(a.name for a in function.arguments))
1518e5c31af7Sopenharmony_ci				yield "}"
1519e5c31af7Sopenharmony_ci
1520e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
1521e5c31af7Sopenharmony_ci
1522e5c31af7Sopenharmony_cidef writeFuncPtrInterfaceSCImpl (api, filename, functionTypes, className):
1523e5c31af7Sopenharmony_ci	normFuncs = {
1524e5c31af7Sopenharmony_ci		"createGraphicsPipelines"		: "\t\treturn createGraphicsPipelinesHandlerNorm(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);",
1525e5c31af7Sopenharmony_ci		"createComputePipelines"		: "\t\treturn createComputePipelinesHandlerNorm(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);",
1526e5c31af7Sopenharmony_ci		"createSampler"					: "\t\treturn createSamplerHandlerNorm(device, pCreateInfo, pAllocator, pSampler);",
1527e5c31af7Sopenharmony_ci		"createSamplerYcbcrConversion"	: "\t\treturn createSamplerYcbcrConversionHandlerNorm(device, pCreateInfo, pAllocator, pYcbcrConversion);",
1528e5c31af7Sopenharmony_ci		"createDescriptorSetLayout"		: "\t\treturn createDescriptorSetLayoutHandlerNorm(device, pCreateInfo, pAllocator, pSetLayout);",
1529e5c31af7Sopenharmony_ci		"createPipelineLayout"			: "\t\treturn createPipelineLayoutHandlerNorm(device, pCreateInfo, pAllocator, pPipelineLayout);",
1530e5c31af7Sopenharmony_ci		"createRenderPass"				: "\t\treturn createRenderPassHandlerNorm(device, pCreateInfo, pAllocator, pRenderPass);",
1531e5c31af7Sopenharmony_ci		"createRenderPass2"				: "\t\treturn createRenderPass2HandlerNorm(device, pCreateInfo, pAllocator, pRenderPass);",
1532e5c31af7Sopenharmony_ci		"createCommandPool"				: "\t\treturn createCommandPoolHandlerNorm(device, pCreateInfo, pAllocator, pCommandPool);",
1533e5c31af7Sopenharmony_ci		"resetCommandPool"				: "\t\treturn resetCommandPoolHandlerNorm(device, commandPool, flags);",
1534e5c31af7Sopenharmony_ci		"createFramebuffer"				: "\t\treturn createFramebufferHandlerNorm(device, pCreateInfo, pAllocator, pFramebuffer);",
1535e5c31af7Sopenharmony_ci	}
1536e5c31af7Sopenharmony_ci	statFuncs = {
1537e5c31af7Sopenharmony_ci		"destroyDevice"					: "\t\tdestroyDeviceHandler(device, pAllocator);",
1538e5c31af7Sopenharmony_ci		"createDescriptorSetLayout"		: "\t\tcreateDescriptorSetLayoutHandlerStat(device, pCreateInfo, pAllocator, pSetLayout);",
1539e5c31af7Sopenharmony_ci		"destroyDescriptorSetLayout"	: "\t\tdestroyDescriptorSetLayoutHandler(device, descriptorSetLayout, pAllocator);",
1540e5c31af7Sopenharmony_ci		"createImageView"				: "\t\tcreateImageViewHandler(device, pCreateInfo, pAllocator, pView);",
1541e5c31af7Sopenharmony_ci		"destroyImageView"				: "\t\tdestroyImageViewHandler(device, imageView, pAllocator);",
1542e5c31af7Sopenharmony_ci		"createSemaphore"				: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(semaphoreRequestCount,1);\n\t\t*pSemaphore = Handle<HANDLE_TYPE_SEMAPHORE>(m_resourceInterface->incResourceCounter());\n\t}",
1543e5c31af7Sopenharmony_ci		"destroySemaphore"				: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(semaphore,semaphoreRequestCount,1);\n\t}",
1544e5c31af7Sopenharmony_ci		"createFence"					: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(fenceRequestCount,1);\n\t\t*pFence = Handle<HANDLE_TYPE_FENCE>(m_resourceInterface->incResourceCounter());\n\t}",
1545e5c31af7Sopenharmony_ci		"destroyFence"					: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(fence,fenceRequestCount,1);\n\t}",
1546e5c31af7Sopenharmony_ci		"allocateMemory"				: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(deviceMemoryRequestCount,1);\n\t\t*pMemory = Handle<HANDLE_TYPE_DEVICE_MEMORY>(m_resourceInterface->incResourceCounter());\n\t}",
1547e5c31af7Sopenharmony_ci		"createBuffer"					: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(bufferRequestCount,1);\n\t\t*pBuffer = Handle<HANDLE_TYPE_BUFFER>(m_resourceInterface->incResourceCounter());\n\t}",
1548e5c31af7Sopenharmony_ci		"destroyBuffer"					: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(buffer,bufferRequestCount,1);\n\t}",
1549e5c31af7Sopenharmony_ci		"createImage"					: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(imageRequestCount,1);\n\t\t*pImage = Handle<HANDLE_TYPE_IMAGE>(m_resourceInterface->incResourceCounter());\n\t}",
1550e5c31af7Sopenharmony_ci		"destroyImage"					: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(image,imageRequestCount,1);\n\t}",
1551e5c31af7Sopenharmony_ci		"createEvent"					: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(eventRequestCount,1);\n\t\t*pEvent = Handle<HANDLE_TYPE_EVENT>(m_resourceInterface->incResourceCounter());\n\t}",
1552e5c31af7Sopenharmony_ci		"destroyEvent"					: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(event,eventRequestCount,1);\n\t}",
1553e5c31af7Sopenharmony_ci		"createQueryPool"				: "\t\tcreateQueryPoolHandler(device, pCreateInfo, pAllocator, pQueryPool);",
1554e5c31af7Sopenharmony_ci		"createBufferView"				: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(bufferViewRequestCount,1);\n\t\t*pView = Handle<HANDLE_TYPE_BUFFER_VIEW>(m_resourceInterface->incResourceCounter());\n\t}",
1555e5c31af7Sopenharmony_ci		"destroyBufferView"				: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(bufferView,bufferViewRequestCount,1);\n\t}",
1556e5c31af7Sopenharmony_ci		"createPipelineLayout"			: "\t\tcreatePipelineLayoutHandlerStat(device, pCreateInfo, pAllocator, pPipelineLayout);",
1557e5c31af7Sopenharmony_ci		"destroyPipelineLayout"			: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(pipelineLayout,pipelineLayoutRequestCount,1);\n\t}",
1558e5c31af7Sopenharmony_ci		"createRenderPass"				: "\t\tcreateRenderPassHandlerStat(device, pCreateInfo, pAllocator, pRenderPass);",
1559e5c31af7Sopenharmony_ci		"createRenderPass2"				: "\t\tcreateRenderPass2HandlerStat(device, pCreateInfo, pAllocator, pRenderPass);",
1560e5c31af7Sopenharmony_ci		"destroyRenderPass"				: "\t\tdestroyRenderPassHandler(device, renderPass, pAllocator);",
1561e5c31af7Sopenharmony_ci		"createGraphicsPipelines"		: "\t\tcreateGraphicsPipelinesHandlerStat(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);",
1562e5c31af7Sopenharmony_ci		"createComputePipelines"		: "\t\tcreateComputePipelinesHandlerStat(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);",
1563e5c31af7Sopenharmony_ci		"destroyPipeline"				: "\t\tdestroyPipelineHandler(device, pipeline, pAllocator);",
1564e5c31af7Sopenharmony_ci		"createSampler"					: "\t\tcreateSamplerHandlerStat(device, pCreateInfo, pAllocator, pSampler);",
1565e5c31af7Sopenharmony_ci		"destroySampler"				: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(sampler,samplerRequestCount,1);\n\t}",
1566e5c31af7Sopenharmony_ci		"createDescriptorPool"			: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(descriptorPoolRequestCount,1);\n\t\t*pDescriptorPool = Handle<HANDLE_TYPE_DESCRIPTOR_POOL>(m_resourceInterface->incResourceCounter());\n\t}",
1567e5c31af7Sopenharmony_ci		"resetDescriptorPool"			: "\t\tresetDescriptorPoolHandlerStat(device, descriptorPool, flags);",
1568e5c31af7Sopenharmony_ci		"allocateDescriptorSets"		: "\t\tallocateDescriptorSetsHandlerStat(device, pAllocateInfo, pDescriptorSets);",
1569e5c31af7Sopenharmony_ci		"freeDescriptorSets"			: "\t\tfreeDescriptorSetsHandlerStat(device, descriptorPool, descriptorSetCount, pDescriptorSets);",
1570e5c31af7Sopenharmony_ci		"createFramebuffer"				: "\t\tcreateFramebufferHandlerStat(device, pCreateInfo, pAllocator, pFramebuffer);",
1571e5c31af7Sopenharmony_ci		"destroyFramebuffer"			: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(framebuffer,framebufferRequestCount,1);\n\t}",
1572e5c31af7Sopenharmony_ci		"createCommandPool"				: "\t\tcreateCommandPoolHandlerStat(device, pCreateInfo, pAllocator, pCommandPool);",
1573e5c31af7Sopenharmony_ci		"resetCommandPool"				: "\t\tresetCommandPoolHandlerStat(device, commandPool, flags);",
1574e5c31af7Sopenharmony_ci		"allocateCommandBuffers"		: "\t\tallocateCommandBuffersHandler(device, pAllocateInfo, pCommandBuffers);",
1575e5c31af7Sopenharmony_ci		"freeCommandBuffers"			: "\t\tfreeCommandBuffersHandler(device, commandPool, commandBufferCount, pCommandBuffers);",
1576e5c31af7Sopenharmony_ci		"createSamplerYcbcrConversion"	: "\t\tcreateSamplerYcbcrConversionHandlerStat(device, pCreateInfo, pAllocator, pYcbcrConversion);",
1577e5c31af7Sopenharmony_ci		"destroySamplerYcbcrConversion"	: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(ycbcrConversion,samplerYcbcrConversionRequestCount,1);\n\t}",
1578e5c31af7Sopenharmony_ci		"getDescriptorSetLayoutSupport"	: "\t\tgetDescriptorSetLayoutSupportHandler(device, pCreateInfo, pSupport);",
1579e5c31af7Sopenharmony_ci#		"" : "surfaceRequestCount",
1580e5c31af7Sopenharmony_ci#		"" : "swapchainRequestCount",
1581e5c31af7Sopenharmony_ci#		"" : "displayModeRequestCount"
1582e5c31af7Sopenharmony_ci		"mapMemory"						: "\t{\n\t\tDDSTAT_LOCK();\n\t\tif(m_falseMemory.size() < (static_cast<std::size_t>(offset+size)))\n\t\t\tm_falseMemory.resize(static_cast<std::size_t>(offset+size));\n\t\t*ppData = (void*)m_falseMemory.data();\n\t}",
1583e5c31af7Sopenharmony_ci		"getBufferMemoryRequirements"	: "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->size = 1048576U;\n\t\tpMemoryRequirements->alignment = 1U;\n\t\tpMemoryRequirements->memoryTypeBits = ~0U;\n\t}",
1584e5c31af7Sopenharmony_ci		"getImageMemoryRequirements"	: "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->size = 1048576U;\n\t\tpMemoryRequirements->alignment = 1U;\n\t\tpMemoryRequirements->memoryTypeBits = ~0U;\n\t}",
1585e5c31af7Sopenharmony_ci		"getBufferMemoryRequirements2"	: "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->memoryRequirements.size = 1048576U;\n\t\tpMemoryRequirements->memoryRequirements.alignment = 1U;\n\t\tpMemoryRequirements->memoryRequirements.memoryTypeBits = ~0U;\n\t}",
1586e5c31af7Sopenharmony_ci		"getImageMemoryRequirements2"	: "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->memoryRequirements.size = 1048576U;\n\t\tpMemoryRequirements->memoryRequirements.alignment = 1U;\n\t\tpMemoryRequirements->memoryRequirements.memoryTypeBits = ~0U;\n\t}",
1587e5c31af7Sopenharmony_ci		"getImageSubresourceLayout"		: "\t{\n\t\tDDSTAT_LOCK();\n\t\tpLayout->offset = 0U;\n\t\tpLayout->size = 1048576U;\n\t\tpLayout->rowPitch = 0U;\n\t\tpLayout->arrayPitch = 0U;\n\t\tpLayout->depthPitch = 0U;\n\t}",
1588e5c31af7Sopenharmony_ci		"createPipelineCache"			: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(pipelineCacheRequestCount,1);\n\t\t*pPipelineCache = Handle<HANDLE_TYPE_PIPELINE_CACHE>(m_resourceInterface->incResourceCounter());\n\t}",
1589e5c31af7Sopenharmony_ci		"destroyPipelineCache"			: "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(pipelineCache,pipelineCacheRequestCount,1);\n\t}",
1590e5c31af7Sopenharmony_ci		"cmdUpdateBuffer"				: "\t\tincreaseCommandBufferSize(commandBuffer, dataSize);",
1591e5c31af7Sopenharmony_ci		"getDeviceQueue"				: "\t\tm_vk.getDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);",
1592e5c31af7Sopenharmony_ci	}
1593e5c31af7Sopenharmony_ci
1594e5c31af7Sopenharmony_ci	statReturns = {
1595e5c31af7Sopenharmony_ci		"VkResult"			: "return VK_SUCCESS;",
1596e5c31af7Sopenharmony_ci		"VkDeviceAddress"	: "return 0u;",
1597e5c31af7Sopenharmony_ci		"uint64_t"			: "return 0u;",
1598e5c31af7Sopenharmony_ci	}
1599e5c31af7Sopenharmony_ci	def makeFuncPtrInterfaceStatisticsImpl ():
1600e5c31af7Sopenharmony_ci		for function in api.functions:
1601e5c31af7Sopenharmony_ci			if function.getType() in functionTypes:
1602e5c31af7Sopenharmony_ci				ifaceName = getInterfaceName(function.name)
1603e5c31af7Sopenharmony_ci				yield ""
1604e5c31af7Sopenharmony_ci				yield "%s %s::%s (%s) const" % (function.returnType, className, ifaceName, argListToStr(function.arguments))
1605e5c31af7Sopenharmony_ci				yield "{"
1606e5c31af7Sopenharmony_ci				if ( ifaceName in normFuncs ) or ( ifaceName in statFuncs ):
1607e5c31af7Sopenharmony_ci					yield "\tstd::lock_guard<std::mutex> lock(functionMutex);"
1608e5c31af7Sopenharmony_ci				if ifaceName != "getDeviceProcAddr" :
1609e5c31af7Sopenharmony_ci					yield "\tif (m_normalMode)"
1610e5c31af7Sopenharmony_ci				if ifaceName in normFuncs :
1611e5c31af7Sopenharmony_ci					yield "%s" % ( normFuncs[ifaceName] )
1612e5c31af7Sopenharmony_ci				else:
1613e5c31af7Sopenharmony_ci					yield "\t\t%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", ifaceName, ", ".join(a.name for a in function.arguments))
1614e5c31af7Sopenharmony_ci				if ifaceName in statFuncs :
1615e5c31af7Sopenharmony_ci					yield "\telse"
1616e5c31af7Sopenharmony_ci					yield "%s" % ( statFuncs[ifaceName] )
1617e5c31af7Sopenharmony_ci				elif ifaceName[:3] == "cmd" :
1618e5c31af7Sopenharmony_ci					yield "\telse"
1619e5c31af7Sopenharmony_ci					yield "\t\tincreaseCommandBufferSize(commandBuffer, 0u);"
1620e5c31af7Sopenharmony_ci				if function.returnType in statReturns:
1621e5c31af7Sopenharmony_ci					yield "\t%s" % ( statReturns[function.returnType] )
1622e5c31af7Sopenharmony_ci				yield "}"
1623e5c31af7Sopenharmony_ci
1624e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceStatisticsImpl())
1625e5c31af7Sopenharmony_ci
1626e5c31af7Sopenharmony_cidef writeStrUtilProto (api, filename):
1627e5c31af7Sopenharmony_ci	def makeStrUtilProto ():
1628e5c31af7Sopenharmony_ci		for line in indentLines(["const char*\tget%sName\t(%s value);" % (enum.name[2:], enum.name) for enum in api.enums if enum.type == "enum"]):
1629e5c31af7Sopenharmony_ci			yield line
1630e5c31af7Sopenharmony_ci		yield ""
1631e5c31af7Sopenharmony_ci		for line in indentLines(["inline tcu::Format::Enum<%s>\tget%sStr\t(%s value)\t{ return tcu::Format::Enum<%s>(get%sName, value);\t}" % (e.name, e.name[2:], e.name, e.name, e.name[2:]) for e in api.enums if e.type == "enum"]):
1632e5c31af7Sopenharmony_ci			yield line
1633e5c31af7Sopenharmony_ci		yield ""
1634e5c31af7Sopenharmony_ci		for line in indentLines(["inline std::ostream&\toperator<<\t(std::ostream& s, %s value)\t{ return s << get%sStr(value);\t}" % (e.name, e.name[2:]) for e in api.enums if e.type == "enum"]):
1635e5c31af7Sopenharmony_ci			yield line
1636e5c31af7Sopenharmony_ci		yield ""
1637e5c31af7Sopenharmony_ci		for line in indentLines(["tcu::Format::Bitfield<%s>\tget%sStr\t(%s value);" % (("64" if b.type == "VkFlags64" else "32"), b.name[2:], b.name) for b in api.bitmasks]):
1638e5c31af7Sopenharmony_ci			yield line
1639e5c31af7Sopenharmony_ci		yield ""
1640e5c31af7Sopenharmony_ci		for line in indentLines(["std::ostream&\toperator<<\t(std::ostream& s, const %s& value);" % (s.name) for s in api.compositeTypes]):
1641e5c31af7Sopenharmony_ci			yield line
1642e5c31af7Sopenharmony_ci
1643e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, makeStrUtilProto())
1644e5c31af7Sopenharmony_ci
1645e5c31af7Sopenharmony_cidef writeStrUtilImpl (api, filename):
1646e5c31af7Sopenharmony_ci	def makeStrUtilImpl ():
1647e5c31af7Sopenharmony_ci		for line in indentLines(["template<> const char*\tgetTypeName<%s>\t(void) { return \"%s\";\t}" % (handle.name, handle.name) for handle in api.handles]):
1648e5c31af7Sopenharmony_ci			yield line
1649e5c31af7Sopenharmony_ci
1650e5c31af7Sopenharmony_ci		yield ""
1651e5c31af7Sopenharmony_ci		yield "namespace %s" % PLATFORM_TYPE_NAMESPACE
1652e5c31af7Sopenharmony_ci		yield "{"
1653e5c31af7Sopenharmony_ci
1654e5c31af7Sopenharmony_ci		for line in indentLines("std::ostream& operator<< (std::ostream& s, %s\tv) { return s << tcu::toHex(v.internal); }" % ''.join(s) for n, s, c in PLATFORM_TYPES):
1655e5c31af7Sopenharmony_ci			yield line
1656e5c31af7Sopenharmony_ci
1657e5c31af7Sopenharmony_ci		yield "}"
1658e5c31af7Sopenharmony_ci
1659e5c31af7Sopenharmony_ci		savedBitmasks = []
1660e5c31af7Sopenharmony_ci		for enum in api.enums:
1661e5c31af7Sopenharmony_ci			if enum.type == "enum":
1662e5c31af7Sopenharmony_ci				yield ""
1663e5c31af7Sopenharmony_ci				yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
1664e5c31af7Sopenharmony_ci				yield "{"
1665e5c31af7Sopenharmony_ci				yield "\tswitch (value)"
1666e5c31af7Sopenharmony_ci				yield "\t{"
1667e5c31af7Sopenharmony_ci				enumValues = []
1668e5c31af7Sopenharmony_ci				lastValue = 0x7FFFFFFF
1669e5c31af7Sopenharmony_ci				for e in enum.enumeratorList:
1670e5c31af7Sopenharmony_ci					enumValues.append(f"\t\tcase {e.name}:\treturn \"{e.name}\";")
1671e5c31af7Sopenharmony_ci				enumValues.append("\t\tdefault:\treturn DE_NULL;")
1672e5c31af7Sopenharmony_ci				for line in indentLines(enumValues):
1673e5c31af7Sopenharmony_ci					yield line
1674e5c31af7Sopenharmony_ci				yield "\t}"
1675e5c31af7Sopenharmony_ci				yield "}"
1676e5c31af7Sopenharmony_ci			elif enum.type == "bitmask":
1677e5c31af7Sopenharmony_ci				# find bitfield that uses those bitmasks
1678e5c31af7Sopenharmony_ci				foundBitmask = None
1679e5c31af7Sopenharmony_ci				for bitmask in api.bitmasks:
1680e5c31af7Sopenharmony_ci					if bitmask.requires == enum.name or bitmask.bitvalues == enum.name:
1681e5c31af7Sopenharmony_ci						foundBitmask = bitmask
1682e5c31af7Sopenharmony_ci						break
1683e5c31af7Sopenharmony_ci				if foundBitmask == None:
1684e5c31af7Sopenharmony_ci					continue
1685e5c31af7Sopenharmony_ci				savedBitmasks.append(foundBitmask.name)
1686e5c31af7Sopenharmony_ci				bitSize = "64" if foundBitmask.type == "VkFlags64" else "32"
1687e5c31af7Sopenharmony_ci				yield ""
1688e5c31af7Sopenharmony_ci				yield f"tcu::Format::Bitfield<{bitSize}> get{bitmask.name[2:]}Str ({bitmask.name} value)"
1689e5c31af7Sopenharmony_ci				yield "{"
1690e5c31af7Sopenharmony_ci				yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
1691e5c31af7Sopenharmony_ci				yield "\t{"
1692e5c31af7Sopenharmony_ci				if len(enum.enumeratorList) == 0:
1693e5c31af7Sopenharmony_ci					# some bitfields in SC have no items
1694e5c31af7Sopenharmony_ci					yield f"\t\ttcu::Format::BitDesc(0, \"0\")"
1695e5c31af7Sopenharmony_ci				else:
1696e5c31af7Sopenharmony_ci					for line in indentLines([f"\t\ttcu::Format::BitDesc({e.name},\t\"{e.name}\")," for e in enum.enumeratorList]):
1697e5c31af7Sopenharmony_ci						yield line
1698e5c31af7Sopenharmony_ci				yield "\t};"
1699e5c31af7Sopenharmony_ci				yield f"\treturn tcu::Format::Bitfield<{bitSize}>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
1700e5c31af7Sopenharmony_ci				yield "}"
1701e5c31af7Sopenharmony_ci
1702e5c31af7Sopenharmony_ci		for bitmask in api.bitmasks:
1703e5c31af7Sopenharmony_ci			if bitmask.name not in savedBitmasks:
1704e5c31af7Sopenharmony_ci				bitSize = "64" if bitmask.type == "VkFlags64" else "32"
1705e5c31af7Sopenharmony_ci				yield ""
1706e5c31af7Sopenharmony_ci				yield f"tcu::Format::Bitfield<{bitSize}> get{bitmask.name[2:]}Str ({bitmask.name} value)"
1707e5c31af7Sopenharmony_ci				yield "{"
1708e5c31af7Sopenharmony_ci				yield f"\treturn tcu::Format::Bitfield<{bitSize}>(value, DE_NULL, DE_NULL);"
1709e5c31af7Sopenharmony_ci				yield "}"
1710e5c31af7Sopenharmony_ci
1711e5c31af7Sopenharmony_ci		bitfieldTypeNames = set([bitmask.name for bitmask in api.bitmasks])
1712e5c31af7Sopenharmony_ci
1713e5c31af7Sopenharmony_ci		for type in api.compositeTypes:
1714e5c31af7Sopenharmony_ci			yield ""
1715e5c31af7Sopenharmony_ci			yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
1716e5c31af7Sopenharmony_ci			yield "{"
1717e5c31af7Sopenharmony_ci			yield "\ts << \"%s = {\\n\";" % type.name
1718e5c31af7Sopenharmony_ci			for member in type.members:
1719e5c31af7Sopenharmony_ci				memberName	= member.name
1720e5c31af7Sopenharmony_ci				valFmt		= None
1721e5c31af7Sopenharmony_ci				newLine		= ""
1722e5c31af7Sopenharmony_ci				if member.type in bitfieldTypeNames:
1723e5c31af7Sopenharmony_ci					operator = '*' if member.pointer == '*' else ''
1724e5c31af7Sopenharmony_ci					valFmt = "get%sStr(%svalue.%s)" % (member.type[2:], operator, member.name)
1725e5c31af7Sopenharmony_ci				elif member.type == "char" and member.pointer == '*':
1726e5c31af7Sopenharmony_ci					valFmt = "getCharPtrStr(value.%s)" % member.name
1727e5c31af7Sopenharmony_ci				elif member.type == PLATFORM_TYPE_NAMESPACE + "::Win32LPCWSTR":
1728e5c31af7Sopenharmony_ci					valFmt = "getWStr(value.%s)" % member.name
1729e5c31af7Sopenharmony_ci				elif len(member.arraySizeList) == 1:
1730e5c31af7Sopenharmony_ci					if member.name in ["extensionName", "deviceName", "layerName", "description"]:
1731e5c31af7Sopenharmony_ci						valFmt = "(const char*)value.%s" % member.name
1732e5c31af7Sopenharmony_ci					elif member.type == 'char' or member.type == 'uint8_t':
1733e5c31af7Sopenharmony_ci						newLine = "'\\n' << "
1734e5c31af7Sopenharmony_ci						valFmt	= "tcu::formatArray(tcu::Format::HexIterator<%s>(DE_ARRAY_BEGIN(value.%s)), tcu::Format::HexIterator<%s>(DE_ARRAY_END(value.%s)))" % (member.type, member.name, member.type, member.name)
1735e5c31af7Sopenharmony_ci					else:
1736e5c31af7Sopenharmony_ci						if member.name == "memoryTypes" or member.name == "memoryHeaps":
1737e5c31af7Sopenharmony_ci							endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (member.name, member.name[:-1])
1738e5c31af7Sopenharmony_ci						else:
1739e5c31af7Sopenharmony_ci							endIter = "DE_ARRAY_END(value.%s)" % member.name
1740e5c31af7Sopenharmony_ci						newLine = "'\\n' << "
1741e5c31af7Sopenharmony_ci						valFmt	= "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (member.name, endIter)
1742e5c31af7Sopenharmony_ci					memberName = member.name
1743e5c31af7Sopenharmony_ci				elif len(member.arraySizeList) > 1:
1744e5c31af7Sopenharmony_ci					yield f"\ts << \"\\t{member.name} = \" << '\\n';"
1745e5c31af7Sopenharmony_ci					dim = 0
1746e5c31af7Sopenharmony_ci					index = ''
1747e5c31af7Sopenharmony_ci					dimensionCount = len(member.arraySizeList)
1748e5c31af7Sopenharmony_ci					while dim < dimensionCount-1:
1749e5c31af7Sopenharmony_ci						yield f"\tfor(deUint32 i{dim} = 0 ; i{dim} < {member.arraySizeList[dim]} ; ++i{dim})"
1750e5c31af7Sopenharmony_ci						index += f"[i{dim}]"
1751e5c31af7Sopenharmony_ci						dim +=1
1752e5c31af7Sopenharmony_ci					yield f"\t\ts << tcu::formatArray(DE_ARRAY_BEGIN(value.{member.name}{index}), DE_ARRAY_END(value.{member.name}{index})) << '\\n';"
1753e5c31af7Sopenharmony_ci					# move to next member
1754e5c31af7Sopenharmony_ci					continue
1755e5c31af7Sopenharmony_ci				else:
1756e5c31af7Sopenharmony_ci					valFmt = "value.%s" % member.name
1757e5c31af7Sopenharmony_ci				yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
1758e5c31af7Sopenharmony_ci			yield "\ts << '}';"
1759e5c31af7Sopenharmony_ci			yield "\treturn s;"
1760e5c31af7Sopenharmony_ci			yield "}"
1761e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
1762e5c31af7Sopenharmony_ci
1763e5c31af7Sopenharmony_cidef writeObjTypeImpl (api, filename):
1764e5c31af7Sopenharmony_ci	def makeObjTypeImpl ():
1765e5c31af7Sopenharmony_ci
1766e5c31af7Sopenharmony_ci		yield "namespace vk"
1767e5c31af7Sopenharmony_ci		yield "{"
1768e5c31af7Sopenharmony_ci
1769e5c31af7Sopenharmony_ci		yield "template<typename T> VkObjectType getObjectType	(void);"
1770e5c31af7Sopenharmony_ci
1771e5c31af7Sopenharmony_ci		for line in indentLines(["template<> inline VkObjectType\tgetObjectType<%s>\t(void) { return %s;\t}" % (handle.name, prefixName("VK_OBJECT_TYPE_", handle.name)) for handle in api.handles]):
1772e5c31af7Sopenharmony_ci			yield line
1773e5c31af7Sopenharmony_ci
1774e5c31af7Sopenharmony_ci		yield "}"
1775e5c31af7Sopenharmony_ci
1776e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, makeObjTypeImpl())
1777e5c31af7Sopenharmony_ci
1778e5c31af7Sopenharmony_ciclass ConstructorFunction:
1779e5c31af7Sopenharmony_ci	def __init__ (self, type, name, objectType, ifaceArgs, arguments):
1780e5c31af7Sopenharmony_ci		self.type		= type
1781e5c31af7Sopenharmony_ci		self.name		= name
1782e5c31af7Sopenharmony_ci		self.objectType	= objectType
1783e5c31af7Sopenharmony_ci		self.ifaceArgs	= ifaceArgs
1784e5c31af7Sopenharmony_ci		self.arguments	= arguments
1785e5c31af7Sopenharmony_ci
1786e5c31af7Sopenharmony_cidef getConstructorFunctions (api):
1787e5c31af7Sopenharmony_ci	funcs = []
1788e5c31af7Sopenharmony_ci
1789e5c31af7Sopenharmony_ci	ifacesDict = {
1790e5c31af7Sopenharmony_ci		Function.TYPE_PLATFORM:	[FunctionArgument("vk", "const ", "PlatformInterface&")],
1791e5c31af7Sopenharmony_ci		Function.TYPE_INSTANCE:	[FunctionArgument("vk", "const ", "InstanceInterface&")],
1792e5c31af7Sopenharmony_ci		Function.TYPE_DEVICE:	[FunctionArgument("vk", "const ", "DeviceInterface&")]}
1793e5c31af7Sopenharmony_ci
1794e5c31af7Sopenharmony_ci	for function in api.functions:
1795e5c31af7Sopenharmony_ci		if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]:
1796e5c31af7Sopenharmony_ci			if function.name == "vkCreateDisplayModeKHR":
1797e5c31af7Sopenharmony_ci				continue # No way to delete display modes (bug?)
1798e5c31af7Sopenharmony_ci
1799e5c31af7Sopenharmony_ci			ifaceArgs = []
1800e5c31af7Sopenharmony_ci			if function.name == "vkCreateDevice":
1801e5c31af7Sopenharmony_ci				ifaceArgs = [FunctionArgument("vkp", "const ", "PlatformInterface&"),
1802e5c31af7Sopenharmony_ci							 FunctionArgument("instance", "", "VkInstance")]
1803e5c31af7Sopenharmony_ci			ifaceArgs.extend(ifacesDict[function.getType()])
1804e5c31af7Sopenharmony_ci
1805e5c31af7Sopenharmony_ci			assert (function.arguments[-2].type == "VkAllocationCallbacks" and \
1806e5c31af7Sopenharmony_ci					"const" in function.arguments[-2].qualifiers and \
1807e5c31af7Sopenharmony_ci					function.arguments[-2].pointer == "*")
1808e5c31af7Sopenharmony_ci
1809e5c31af7Sopenharmony_ci			objectType	= function.arguments[-1].type
1810e5c31af7Sopenharmony_ci			arguments	= function.arguments[:-1]
1811e5c31af7Sopenharmony_ci			funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function.name), objectType, ifaceArgs, arguments))
1812e5c31af7Sopenharmony_ci	return funcs
1813e5c31af7Sopenharmony_ci
1814e5c31af7Sopenharmony_cidef addVersionDefines(versionSpectrum):
1815e5c31af7Sopenharmony_ci	output = ["#define " + ver.getDefineName() + " " + ver.getInHex() for ver in versionSpectrum if not ver.isStandardVersion()]
1816e5c31af7Sopenharmony_ci	return output
1817e5c31af7Sopenharmony_ci
1818e5c31af7Sopenharmony_cidef writeRefUtilProto (api, filename):
1819e5c31af7Sopenharmony_ci	functions = getConstructorFunctions(api)
1820e5c31af7Sopenharmony_ci
1821e5c31af7Sopenharmony_ci	def makeRefUtilProto ():
1822e5c31af7Sopenharmony_ci		unindented = []
1823e5c31af7Sopenharmony_ci		for line in indentLines(["Move<%s>\t%s\t(%s = DE_NULL);" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments)) for function in functions]):
1824e5c31af7Sopenharmony_ci			yield line
1825e5c31af7Sopenharmony_ci
1826e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, makeRefUtilProto())
1827e5c31af7Sopenharmony_ci
1828e5c31af7Sopenharmony_cidef writeRefUtilImpl (api, filename):
1829e5c31af7Sopenharmony_ci	functions = getConstructorFunctions(api)
1830e5c31af7Sopenharmony_ci
1831e5c31af7Sopenharmony_ci	def makeRefUtilImpl ():
1832e5c31af7Sopenharmony_ci		yield "namespace refdetails"
1833e5c31af7Sopenharmony_ci		yield "{"
1834e5c31af7Sopenharmony_ci		yield ""
1835e5c31af7Sopenharmony_ci
1836e5c31af7Sopenharmony_ci		for function in api.functions:
1837e5c31af7Sopenharmony_ci			if function.getType() == Function.TYPE_DEVICE \
1838e5c31af7Sopenharmony_ci			and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
1839e5c31af7Sopenharmony_ci			and not function.name == "vkDestroyDevice":
1840e5c31af7Sopenharmony_ci				objectType = function.arguments[-2].type
1841e5c31af7Sopenharmony_ci				yield "template<>"
1842e5c31af7Sopenharmony_ci				yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
1843e5c31af7Sopenharmony_ci				yield "{"
1844e5c31af7Sopenharmony_ci				yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function.name))
1845e5c31af7Sopenharmony_ci				yield "}"
1846e5c31af7Sopenharmony_ci				yield ""
1847e5c31af7Sopenharmony_ci
1848e5c31af7Sopenharmony_ci		yield "} // refdetails"
1849e5c31af7Sopenharmony_ci		yield ""
1850e5c31af7Sopenharmony_ci
1851e5c31af7Sopenharmony_ci		dtorDict = {
1852e5c31af7Sopenharmony_ci			Function.TYPE_PLATFORM: "object",
1853e5c31af7Sopenharmony_ci			Function.TYPE_INSTANCE: "instance",
1854e5c31af7Sopenharmony_ci			Function.TYPE_DEVICE: "device"
1855e5c31af7Sopenharmony_ci		}
1856e5c31af7Sopenharmony_ci
1857e5c31af7Sopenharmony_ci		for function in functions:
1858e5c31af7Sopenharmony_ci			deleterArgsString = ''
1859e5c31af7Sopenharmony_ci			if function.name == "createDevice":
1860e5c31af7Sopenharmony_ci				# createDevice requires two additional parameters to setup VkDevice deleter
1861e5c31af7Sopenharmony_ci				deleterArgsString = "vkp, instance, object, " +  function.arguments[-1].name
1862e5c31af7Sopenharmony_ci			else:
1863e5c31af7Sopenharmony_ci				deleterArgsString = "vk, %s, %s" % (dtorDict[function.type], function.arguments[-1].name)
1864e5c31af7Sopenharmony_ci
1865e5c31af7Sopenharmony_ci			yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments))
1866e5c31af7Sopenharmony_ci			yield "{"
1867e5c31af7Sopenharmony_ci			yield "\t%s object = 0;" % function.objectType
1868e5c31af7Sopenharmony_ci			yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"]))
1869e5c31af7Sopenharmony_ci			yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, deleterArgsString)
1870e5c31af7Sopenharmony_ci			yield "}"
1871e5c31af7Sopenharmony_ci			yield ""
1872e5c31af7Sopenharmony_ci
1873e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
1874e5c31af7Sopenharmony_ci
1875e5c31af7Sopenharmony_cidef writeStructTraitsImpl (api, filename):
1876e5c31af7Sopenharmony_ci	def gen ():
1877e5c31af7Sopenharmony_ci		for cType in api.compositeTypes:
1878e5c31af7Sopenharmony_ci			if cType.category == "struct" and cType.members[0].name == "sType" and cType.name != "VkBaseOutStructure" and cType.name != "VkBaseInStructure":
1879e5c31af7Sopenharmony_ci				yield "template<> VkStructureType getStructureType<%s> (void)" % cType.name
1880e5c31af7Sopenharmony_ci				yield "{"
1881e5c31af7Sopenharmony_ci				yield "\treturn %s;" % cType.members[0].values
1882e5c31af7Sopenharmony_ci				yield "}"
1883e5c31af7Sopenharmony_ci				yield ""
1884e5c31af7Sopenharmony_ci
1885e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, gen())
1886e5c31af7Sopenharmony_ci
1887e5c31af7Sopenharmony_cidef writeNullDriverImpl (api, filename):
1888e5c31af7Sopenharmony_ci	def genNullDriverImpl ():
1889e5c31af7Sopenharmony_ci		specialFuncNames	= [
1890e5c31af7Sopenharmony_ci				"vkCreateGraphicsPipelines",
1891e5c31af7Sopenharmony_ci				"vkCreateComputePipelines",
1892e5c31af7Sopenharmony_ci				"vkCreateRayTracingPipelinesNV",
1893e5c31af7Sopenharmony_ci				"vkCreateRayTracingPipelinesKHR",
1894e5c31af7Sopenharmony_ci				"vkGetInstanceProcAddr",
1895e5c31af7Sopenharmony_ci				"vkGetDeviceProcAddr",
1896e5c31af7Sopenharmony_ci				"vkEnumeratePhysicalDevices",
1897e5c31af7Sopenharmony_ci				"vkEnumerateInstanceExtensionProperties",
1898e5c31af7Sopenharmony_ci				"vkEnumerateDeviceExtensionProperties",
1899e5c31af7Sopenharmony_ci				"vkGetPhysicalDeviceFeatures",
1900e5c31af7Sopenharmony_ci				"vkGetPhysicalDeviceFeatures2KHR",
1901e5c31af7Sopenharmony_ci				"vkGetPhysicalDeviceProperties",
1902e5c31af7Sopenharmony_ci				"vkGetPhysicalDeviceProperties2KHR",
1903e5c31af7Sopenharmony_ci				"vkGetPhysicalDeviceQueueFamilyProperties",
1904e5c31af7Sopenharmony_ci				"vkGetPhysicalDeviceMemoryProperties",
1905e5c31af7Sopenharmony_ci				"vkGetPhysicalDeviceFormatProperties",
1906e5c31af7Sopenharmony_ci				"vkGetPhysicalDeviceImageFormatProperties",
1907e5c31af7Sopenharmony_ci				"vkGetDeviceQueue",
1908e5c31af7Sopenharmony_ci				"vkGetBufferMemoryRequirements",
1909e5c31af7Sopenharmony_ci				"vkGetBufferMemoryRequirements2KHR",
1910e5c31af7Sopenharmony_ci				"vkGetImageMemoryRequirements",
1911e5c31af7Sopenharmony_ci				"vkGetImageMemoryRequirements2KHR",
1912e5c31af7Sopenharmony_ci				"vkAllocateMemory",
1913e5c31af7Sopenharmony_ci				"vkMapMemory",
1914e5c31af7Sopenharmony_ci				"vkUnmapMemory",
1915e5c31af7Sopenharmony_ci				"vkAllocateDescriptorSets",
1916e5c31af7Sopenharmony_ci				"vkFreeDescriptorSets",
1917e5c31af7Sopenharmony_ci				"vkResetDescriptorPool",
1918e5c31af7Sopenharmony_ci				"vkAllocateCommandBuffers",
1919e5c31af7Sopenharmony_ci				"vkFreeCommandBuffers",
1920e5c31af7Sopenharmony_ci				"vkCreateDisplayModeKHR",
1921e5c31af7Sopenharmony_ci				"vkCreateSharedSwapchainsKHR",
1922e5c31af7Sopenharmony_ci				"vkGetPhysicalDeviceExternalBufferPropertiesKHR",
1923e5c31af7Sopenharmony_ci				"vkGetPhysicalDeviceImageFormatProperties2KHR",
1924e5c31af7Sopenharmony_ci				"vkGetMemoryAndroidHardwareBufferANDROID",
1925e5c31af7Sopenharmony_ci				"vkCreateShadersEXT",
1926e5c31af7Sopenharmony_ci			]
1927e5c31af7Sopenharmony_ci
1928e5c31af7Sopenharmony_ci		specialFuncs		= [f for f in api.functions if f.name in specialFuncNames]
1929e5c31af7Sopenharmony_ci		createFuncs			= [f for f in api.functions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
1930e5c31af7Sopenharmony_ci		destroyFuncs		= [f for f in api.functions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
1931e5c31af7Sopenharmony_ci		dummyFuncs			= [f for f in api.functions if f not in specialFuncs + createFuncs + destroyFuncs]
1932e5c31af7Sopenharmony_ci
1933e5c31af7Sopenharmony_ci		def getHandle (name):
1934e5c31af7Sopenharmony_ci			for handle in api.handles:
1935e5c31af7Sopenharmony_ci				if handle.name == name:
1936e5c31af7Sopenharmony_ci					return handle
1937e5c31af7Sopenharmony_ci			raise Exception("No such handle: %s" % name)
1938e5c31af7Sopenharmony_ci
1939e5c31af7Sopenharmony_ci		for function in createFuncs:
1940e5c31af7Sopenharmony_ci			objectType	= function.arguments[-1].type
1941e5c31af7Sopenharmony_ci			argsStr		= ", ".join([a.name for a in function.arguments[:-1]])
1942e5c31af7Sopenharmony_ci
1943e5c31af7Sopenharmony_ci			yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function.name), argListToStr(function.arguments))
1944e5c31af7Sopenharmony_ci			yield "{"
1945e5c31af7Sopenharmony_ci			yield "\tDE_UNREF(%s);" % function.arguments[-2].name
1946e5c31af7Sopenharmony_ci
1947e5c31af7Sopenharmony_ci			if function.arguments[-1].len != None:
1948e5c31af7Sopenharmony_ci				yield "\tVK_NULL_RETURN((allocateNonDispHandleArray<%s, %s>(%s, %s)));" % (objectType[2:], objectType, argsStr, function.arguments[-1].name)
1949e5c31af7Sopenharmony_ci			else:
1950e5c31af7Sopenharmony_ci				if getHandle(objectType).type == "VK_DEFINE_NON_DISPATCHABLE_HANDLE":
1951e5c31af7Sopenharmony_ci					yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[2:], objectType, argsStr)
1952e5c31af7Sopenharmony_ci				else:
1953e5c31af7Sopenharmony_ci					yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[2:], objectType, argsStr)
1954e5c31af7Sopenharmony_ci			yield "}"
1955e5c31af7Sopenharmony_ci			yield ""
1956e5c31af7Sopenharmony_ci
1957e5c31af7Sopenharmony_ci		for function in destroyFuncs:
1958e5c31af7Sopenharmony_ci			objectArg	= function.arguments[-2]
1959e5c31af7Sopenharmony_ci
1960e5c31af7Sopenharmony_ci			yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function.name), argListToStr(function.arguments))
1961e5c31af7Sopenharmony_ci			yield "{"
1962e5c31af7Sopenharmony_ci			for arg in function.arguments[:-2]:
1963e5c31af7Sopenharmony_ci				yield "\tDE_UNREF(%s);" % arg.name
1964e5c31af7Sopenharmony_ci
1965e5c31af7Sopenharmony_ci			if getHandle(objectArg.type).type == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1966e5c31af7Sopenharmony_ci				yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.type[2:], objectArg.type, objectArg.name, function.arguments[-1].name)
1967e5c31af7Sopenharmony_ci			else:
1968e5c31af7Sopenharmony_ci				yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.type[2:], objectArg.type, objectArg.name, function.arguments[-1].name)
1969e5c31af7Sopenharmony_ci
1970e5c31af7Sopenharmony_ci			yield "}"
1971e5c31af7Sopenharmony_ci			yield ""
1972e5c31af7Sopenharmony_ci
1973e5c31af7Sopenharmony_ci		for function in dummyFuncs:
1974e5c31af7Sopenharmony_ci			yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function.name), argListToStr(function.arguments))
1975e5c31af7Sopenharmony_ci			yield "{"
1976e5c31af7Sopenharmony_ci			for arg in function.arguments:
1977e5c31af7Sopenharmony_ci				yield "\tDE_UNREF(%s);" % arg.name
1978e5c31af7Sopenharmony_ci			if function.returnType != "void":
1979e5c31af7Sopenharmony_ci				yield "\treturn VK_SUCCESS;"
1980e5c31af7Sopenharmony_ci			yield "}"
1981e5c31af7Sopenharmony_ci			yield ""
1982e5c31af7Sopenharmony_ci
1983e5c31af7Sopenharmony_ci		def genFuncEntryTable (type, name):
1984e5c31af7Sopenharmony_ci
1985e5c31af7Sopenharmony_ci			entries = []
1986e5c31af7Sopenharmony_ci			pattern = "\tVK_NULL_FUNC_ENTRY(%s,\t%s),"
1987e5c31af7Sopenharmony_ci			for f in api.functions:
1988e5c31af7Sopenharmony_ci				if f.getType() != type:
1989e5c31af7Sopenharmony_ci					continue
1990e5c31af7Sopenharmony_ci				entries.append(pattern % (f.name, getInterfaceName(f.name)))
1991e5c31af7Sopenharmony_ci
1992e5c31af7Sopenharmony_ci			yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
1993e5c31af7Sopenharmony_ci			yield "{"
1994e5c31af7Sopenharmony_ci
1995e5c31af7Sopenharmony_ci			for line in indentLines(entries):
1996e5c31af7Sopenharmony_ci				yield line
1997e5c31af7Sopenharmony_ci			yield "};"
1998e5c31af7Sopenharmony_ci			yield ""
1999e5c31af7Sopenharmony_ci
2000e5c31af7Sopenharmony_ci		# Func tables
2001e5c31af7Sopenharmony_ci		for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
2002e5c31af7Sopenharmony_ci			yield line
2003e5c31af7Sopenharmony_ci
2004e5c31af7Sopenharmony_ci		for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
2005e5c31af7Sopenharmony_ci			yield line
2006e5c31af7Sopenharmony_ci
2007e5c31af7Sopenharmony_ci		for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
2008e5c31af7Sopenharmony_ci			yield line
2009e5c31af7Sopenharmony_ci
2010e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, genNullDriverImpl())
2011e5c31af7Sopenharmony_ci
2012e5c31af7Sopenharmony_cidef writeTypeUtil (api, filename):
2013e5c31af7Sopenharmony_ci	# Structs filled by API queries are not often used in test code
2014e5c31af7Sopenharmony_ci	QUERY_RESULT_TYPES = set([
2015e5c31af7Sopenharmony_ci			"VkPhysicalDeviceFeatures",
2016e5c31af7Sopenharmony_ci			"VkPhysicalDeviceLimits",
2017e5c31af7Sopenharmony_ci			"VkFormatProperties",
2018e5c31af7Sopenharmony_ci			"VkImageFormatProperties",
2019e5c31af7Sopenharmony_ci			"VkPhysicalDeviceSparseProperties",
2020e5c31af7Sopenharmony_ci			"VkQueueFamilyProperties",
2021e5c31af7Sopenharmony_ci			"VkMemoryType",
2022e5c31af7Sopenharmony_ci			"VkMemoryHeap",
2023e5c31af7Sopenharmony_ci			"StdVideoH264SpsVuiFlags",
2024e5c31af7Sopenharmony_ci			"StdVideoH264SpsFlags",
2025e5c31af7Sopenharmony_ci			"StdVideoH264PpsFlags",
2026e5c31af7Sopenharmony_ci			"StdVideoDecodeH264PictureInfoFlags",
2027e5c31af7Sopenharmony_ci			"StdVideoDecodeH264ReferenceInfoFlags",
2028e5c31af7Sopenharmony_ci			"StdVideoEncodeH264SliceHeaderFlags",
2029e5c31af7Sopenharmony_ci			"StdVideoEncodeH264PictureInfoFlags",
2030e5c31af7Sopenharmony_ci			"StdVideoEncodeH264ReferenceInfoFlags",
2031e5c31af7Sopenharmony_ci			"StdVideoEncodeH264ReferenceInfoFlags",
2032e5c31af7Sopenharmony_ci			"StdVideoH265HrdFlags",
2033e5c31af7Sopenharmony_ci			"StdVideoH265VpsFlags",
2034e5c31af7Sopenharmony_ci			"StdVideoH265SpsVuiFlags",
2035e5c31af7Sopenharmony_ci			"StdVideoH265SpsFlags",
2036e5c31af7Sopenharmony_ci			"StdVideoH265PpsFlags",
2037e5c31af7Sopenharmony_ci			"StdVideoDecodeH265PictureInfoFlags",
2038e5c31af7Sopenharmony_ci			"StdVideoDecodeH265ReferenceInfoFlags",
2039e5c31af7Sopenharmony_ci			"StdVideoEncodeH265PictureInfoFlags",
2040e5c31af7Sopenharmony_ci			"StdVideoEncodeH265ReferenceInfoFlags",
2041e5c31af7Sopenharmony_ci			"StdVideoEncodeH265SliceSegmentHeaderFlags",
2042e5c31af7Sopenharmony_ci			"StdVideoH265ProfileTierLevelFlags",
2043e5c31af7Sopenharmony_ci			"StdVideoH265ShortTermRefPicSetFlags",
2044e5c31af7Sopenharmony_ci			"StdVideoEncodeH264ReferenceListsInfoFlags",
2045e5c31af7Sopenharmony_ci			"StdVideoEncodeH265ReferenceListsInfoFlags",
2046e5c31af7Sopenharmony_ci		])
2047e5c31af7Sopenharmony_ci
2048e5c31af7Sopenharmony_ci	def isSimpleStruct (type):
2049e5c31af7Sopenharmony_ci		def hasArrayMember (type):
2050e5c31af7Sopenharmony_ci			for member in type.members:
2051e5c31af7Sopenharmony_ci				if len(member.arraySizeList) > 0:
2052e5c31af7Sopenharmony_ci					return True
2053e5c31af7Sopenharmony_ci			return False
2054e5c31af7Sopenharmony_ci
2055e5c31af7Sopenharmony_ci		def hasCompositeMember (type):
2056e5c31af7Sopenharmony_ci			for member in type.members:
2057e5c31af7Sopenharmony_ci				if member.pointer is not None and '*' not in member.pointer:
2058e5c31af7Sopenharmony_ci					match = [c for c in api.compositeTypes if member.type == c.name]
2059e5c31af7Sopenharmony_ci					if len(match) > 0:
2060e5c31af7Sopenharmony_ci						return True
2061e5c31af7Sopenharmony_ci			return False
2062e5c31af7Sopenharmony_ci
2063e5c31af7Sopenharmony_ci		return type.category == "struct" and \
2064e5c31af7Sopenharmony_ci		type.members[0].type != "VkStructureType" and \
2065e5c31af7Sopenharmony_ci		not type.name in QUERY_RESULT_TYPES and \
2066e5c31af7Sopenharmony_ci		not hasArrayMember(type) and \
2067e5c31af7Sopenharmony_ci		not hasCompositeMember(type)
2068e5c31af7Sopenharmony_ci
2069e5c31af7Sopenharmony_ci	def gen ():
2070e5c31af7Sopenharmony_ci		for type in api.compositeTypes:
2071e5c31af7Sopenharmony_ci			if not isSimpleStruct(type):
2072e5c31af7Sopenharmony_ci				continue
2073e5c31af7Sopenharmony_ci
2074e5c31af7Sopenharmony_ci			name = type.name[2:] if type.name[:2].lower() == "vk" else type.name
2075e5c31af7Sopenharmony_ci
2076e5c31af7Sopenharmony_ci			yield ""
2077e5c31af7Sopenharmony_ci			yield "inline %s make%s (%s)" % (type.name, name, argListToStr(type.members))
2078e5c31af7Sopenharmony_ci			yield "{"
2079e5c31af7Sopenharmony_ci			yield "\t%s res;" % type.name
2080e5c31af7Sopenharmony_ci			for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
2081e5c31af7Sopenharmony_ci				yield line
2082e5c31af7Sopenharmony_ci			yield "\treturn res;"
2083e5c31af7Sopenharmony_ci			yield "}"
2084e5c31af7Sopenharmony_ci
2085e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, gen())
2086e5c31af7Sopenharmony_ci
2087e5c31af7Sopenharmony_cidef writeDriverIds(api, filename):
2088e5c31af7Sopenharmony_ci	driverIdsString = []
2089e5c31af7Sopenharmony_ci	driverIdsString.append("static const struct\n"
2090e5c31af7Sopenharmony_ci					 "{\n"
2091e5c31af7Sopenharmony_ci					 "\tstd::string driver;\n"
2092e5c31af7Sopenharmony_ci					 "\tuint32_t id;\n"
2093e5c31af7Sopenharmony_ci					 "} driverIds [] =\n"
2094e5c31af7Sopenharmony_ci					 "{")
2095e5c31af7Sopenharmony_ci	driverItems = dict()
2096e5c31af7Sopenharmony_ci	driverIdEnum = [enum for enum in api.enums if enum.name == 'VkDriverId'][0]
2097e5c31af7Sopenharmony_ci	for enumerator in driverIdEnum.enumeratorList:
2098e5c31af7Sopenharmony_ci		driverIdsString.append(f"\t{{\"{enumerator.name}\", {enumerator.value}}},")
2099e5c31af7Sopenharmony_ci		driverItems[enumerator.name] = enumerator.value
2100e5c31af7Sopenharmony_ci	for enumerator in driverIdEnum.enumeratorList:
2101e5c31af7Sopenharmony_ci		if len(enumerator.aliasList) > 0:
2102e5c31af7Sopenharmony_ci			driverIdsString.append(f"\t{{\"{enumerator.aliasList[0]}\", {enumerator.value}}},\t// {enumerator.name}")
2103e5c31af7Sopenharmony_ci	driverIdsString.append("\t{\"VK_DRIVER_ID_MAX_ENUM\", 0x7FFFFFFF}")
2104e5c31af7Sopenharmony_ci	driverIdsString.append("};")
2105e5c31af7Sopenharmony_ci
2106e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, driverIdsString)
2107e5c31af7Sopenharmony_ci
2108e5c31af7Sopenharmony_cidef writeSupportedExtensions(api, filename):
2109e5c31af7Sopenharmony_ci
2110e5c31af7Sopenharmony_ci	def writeExtensionsForVersions(map):
2111e5c31af7Sopenharmony_ci		result = []
2112e5c31af7Sopenharmony_ci		for version in map:
2113e5c31af7Sopenharmony_ci			result.append("	if (coreVersion >= " + str(version) + ")")
2114e5c31af7Sopenharmony_ci			result.append("	{")
2115e5c31af7Sopenharmony_ci			for extension in map[version]:
2116e5c31af7Sopenharmony_ci				result.append('		dst.push_back("' + extension.name + '");')
2117e5c31af7Sopenharmony_ci			result.append("	}")
2118e5c31af7Sopenharmony_ci
2119e5c31af7Sopenharmony_ci		if not map:
2120e5c31af7Sopenharmony_ci			result.append("	DE_UNREF(coreVersion);")
2121e5c31af7Sopenharmony_ci
2122e5c31af7Sopenharmony_ci		return result
2123e5c31af7Sopenharmony_ci
2124e5c31af7Sopenharmony_ci	isSC			= api.apiName == 'vulkansc'
2125e5c31af7Sopenharmony_ci	instanceMap		= {}
2126e5c31af7Sopenharmony_ci	deviceMap		= {}
2127e5c31af7Sopenharmony_ci
2128e5c31af7Sopenharmony_ci	for ext in api.extensions:
2129e5c31af7Sopenharmony_ci		if ext.promotedto is None or "VK_VERSION" not in ext.promotedto:
2130e5c31af7Sopenharmony_ci			continue
2131e5c31af7Sopenharmony_ci		# skip partialy promoted extensions
2132e5c31af7Sopenharmony_ci		if ext.partiallyPromoted is True:
2133e5c31af7Sopenharmony_ci			continue
2134e5c31af7Sopenharmony_ci		major		= int(ext.promotedto[-3])
2135e5c31af7Sopenharmony_ci		minor		= int(ext.promotedto[-1])
2136e5c31af7Sopenharmony_ci		currVersion = "VK_API_VERSION_" + ext.promotedto[-3:]
2137e5c31af7Sopenharmony_ci		# VulkanSC is based on Vulkan 1.2. Any Vulkan version greater than 1.2 should be excluded
2138e5c31af7Sopenharmony_ci		if isSC and major==1 and minor>2:
2139e5c31af7Sopenharmony_ci			continue
2140e5c31af7Sopenharmony_ci		if ext.type == 'instance':
2141e5c31af7Sopenharmony_ci			list = instanceMap.get(currVersion)
2142e5c31af7Sopenharmony_ci			instanceMap[currVersion] = list + [ext] if list else [ext]
2143e5c31af7Sopenharmony_ci		else:
2144e5c31af7Sopenharmony_ci			list = deviceMap.get(currVersion)
2145e5c31af7Sopenharmony_ci			deviceMap[currVersion] = list + [ext] if list else [ext]
2146e5c31af7Sopenharmony_ci
2147e5c31af7Sopenharmony_ci	# add list of extensions missing in Vulkan SC specification
2148e5c31af7Sopenharmony_ci	if isSC:
2149e5c31af7Sopenharmony_ci		for extensionName, data in api.additionalExtensionData:
2150e5c31af7Sopenharmony_ci			# make sure that this extension was registered
2151e5c31af7Sopenharmony_ci			if 'register_extension' not in data.keys():
2152e5c31af7Sopenharmony_ci				continue
2153e5c31af7Sopenharmony_ci			# save array containing 'device' or 'instance' string followed by the optional vulkan version in which this extension is core;
2154e5c31af7Sopenharmony_ci			# note that register_extension section is also required for partialy promoted extensions like VK_EXT_extended_dynamic_state2
2155e5c31af7Sopenharmony_ci			# but those extensions should not fill 'core' tag
2156e5c31af7Sopenharmony_ci			match = re.match("(\d).(\d).(\d).(\d)", data['register_extension']['core'])
2157e5c31af7Sopenharmony_ci			if match == None:
2158e5c31af7Sopenharmony_ci				continue
2159e5c31af7Sopenharmony_ci			major = int(match.group(2))
2160e5c31af7Sopenharmony_ci			minor = int(match.group(3))
2161e5c31af7Sopenharmony_ci			if major==1 and minor>2:
2162e5c31af7Sopenharmony_ci				continue
2163e5c31af7Sopenharmony_ci			currVersion = f"VK_API_VERSION_{major}_{minor}"
2164e5c31af7Sopenharmony_ci			ext = Extension(extensionName, 0, 0, 0, 0, 0, 0, 0)
2165e5c31af7Sopenharmony_ci			if data['register_extension']['type'] == 'instance':
2166e5c31af7Sopenharmony_ci				list = instanceMap.get(currVersion)
2167e5c31af7Sopenharmony_ci				instanceMap[currVersion] = list + [ext] if list else [ext]
2168e5c31af7Sopenharmony_ci			else:
2169e5c31af7Sopenharmony_ci				list = deviceMap.get(currVersion)
2170e5c31af7Sopenharmony_ci				deviceMap[currVersion] = list + [ext] if list else [ext]
2171e5c31af7Sopenharmony_ci
2172e5c31af7Sopenharmony_ci	lines = [
2173e5c31af7Sopenharmony_ci	"",
2174e5c31af7Sopenharmony_ci	"void getCoreDeviceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 or isSC else ""),
2175e5c31af7Sopenharmony_ci	"{"] + writeExtensionsForVersions(deviceMap) + [
2176e5c31af7Sopenharmony_ci	"}",
2177e5c31af7Sopenharmony_ci	"",
2178e5c31af7Sopenharmony_ci	"void getCoreInstanceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 or isSC else ""),
2179e5c31af7Sopenharmony_ci	"{"] + writeExtensionsForVersions(instanceMap) + [
2180e5c31af7Sopenharmony_ci	"}",
2181e5c31af7Sopenharmony_ci	""]
2182e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, lines)
2183e5c31af7Sopenharmony_ci
2184e5c31af7Sopenharmony_ci
2185e5c31af7Sopenharmony_cidef writeExtensionFunctions (api, filename):
2186e5c31af7Sopenharmony_ci
2187e5c31af7Sopenharmony_ci	def writeExtensionNameArrays ():
2188e5c31af7Sopenharmony_ci		instanceExtensionNames	= [f"\t\"{ext.name}\"," for ext in api.extensions if ext.type == "instance"]
2189e5c31af7Sopenharmony_ci		deviceExtensionNames	= [f"\t\"{ext.name}\"," for ext in api.extensions if ext.type == "device"]
2190e5c31af7Sopenharmony_ci		yield '::std::string instanceExtensionNames[] =\n{'
2191e5c31af7Sopenharmony_ci		for instanceExtName in instanceExtensionNames:
2192e5c31af7Sopenharmony_ci			yield instanceExtName
2193e5c31af7Sopenharmony_ci		yield '};\n'
2194e5c31af7Sopenharmony_ci		yield '::std::string deviceExtensionNames[] =\n{'
2195e5c31af7Sopenharmony_ci		for deviceExtName in deviceExtensionNames:
2196e5c31af7Sopenharmony_ci			yield deviceExtName
2197e5c31af7Sopenharmony_ci		yield '};'
2198e5c31af7Sopenharmony_ci
2199e5c31af7Sopenharmony_ci	def writeExtensionFunctions (functionType):
2200e5c31af7Sopenharmony_ci		isFirstWrite = True
2201e5c31af7Sopenharmony_ci		dg_list = []	# Device groups functions need special casing, as Vulkan 1.0 keeps them in VK_KHR_device_groups whereas 1.1 moved them into VK_KHR_swapchain
2202e5c31af7Sopenharmony_ci		if functionType == Function.TYPE_INSTANCE:
2203e5c31af7Sopenharmony_ci			yield 'void getInstanceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
2204e5c31af7Sopenharmony_ci			dg_list = ["vkGetPhysicalDevicePresentRectanglesKHR"]
2205e5c31af7Sopenharmony_ci		elif functionType == Function.TYPE_DEVICE:
2206e5c31af7Sopenharmony_ci			yield 'void getDeviceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
2207e5c31af7Sopenharmony_ci			dg_list = ["vkGetDeviceGroupPresentCapabilitiesKHR", "vkGetDeviceGroupSurfacePresentModesKHR", "vkAcquireNextImage2KHR"]
2208e5c31af7Sopenharmony_ci		for ext in api.extensions:
2209e5c31af7Sopenharmony_ci			funcNames = []
2210e5c31af7Sopenharmony_ci			for requirement in ext.requirementsList:
2211e5c31af7Sopenharmony_ci				for requiredCommand in requirement.newCommands:
2212e5c31af7Sopenharmony_ci					commandName = requiredCommand.name
2213e5c31af7Sopenharmony_ci					# find function that has specified name
2214e5c31af7Sopenharmony_ci					func		= None
2215e5c31af7Sopenharmony_ci					funcList	= [f for f in api.functions if f.name == commandName]
2216e5c31af7Sopenharmony_ci					# if name was not found check if this is alias
2217e5c31af7Sopenharmony_ci					if len(funcList) == 0:
2218e5c31af7Sopenharmony_ci						for f in api.functions:
2219e5c31af7Sopenharmony_ci							for aliasName in f.aliasList:
2220e5c31af7Sopenharmony_ci								if aliasName == commandName:
2221e5c31af7Sopenharmony_ci									func = f
2222e5c31af7Sopenharmony_ci									break
2223e5c31af7Sopenharmony_ci							if func:
2224e5c31af7Sopenharmony_ci								break
2225e5c31af7Sopenharmony_ci					else:
2226e5c31af7Sopenharmony_ci						func = funcList[0]
2227e5c31af7Sopenharmony_ci					if func == None:
2228e5c31af7Sopenharmony_ci						if api.apiName == "vulkansc":
2229e5c31af7Sopenharmony_ci							continue
2230e5c31af7Sopenharmony_ci						# something went wrong, for "vulkan" func should always be found
2231e5c31af7Sopenharmony_ci						assert(False)
2232e5c31af7Sopenharmony_ci					if func.getType() == functionType:
2233e5c31af7Sopenharmony_ci						# only add functions with same vendor as extension
2234e5c31af7Sopenharmony_ci						# this is a workaround for entrypoints requiring more
2235e5c31af7Sopenharmony_ci						# than one extension and lack of the dependency in vk.xml
2236e5c31af7Sopenharmony_ci						vendor = ext.name.split('_')[1]
2237e5c31af7Sopenharmony_ci						if commandName.endswith(vendor):
2238e5c31af7Sopenharmony_ci							funcNames.append(commandName)
2239e5c31af7Sopenharmony_ci			if ext.name:
2240e5c31af7Sopenharmony_ci				yield '\tif (extName == "%s")' % ext.name
2241e5c31af7Sopenharmony_ci				yield '\t{'
2242e5c31af7Sopenharmony_ci				for funcName in funcNames:
2243e5c31af7Sopenharmony_ci					if funcName in dg_list:
2244e5c31af7Sopenharmony_ci						yield '\t\tif(apiVersion >= VK_API_VERSION_1_1) functions.push_back("%s");' % funcName
2245e5c31af7Sopenharmony_ci					else:
2246e5c31af7Sopenharmony_ci						yield '\t\tfunctions.push_back("%s");' % funcName
2247e5c31af7Sopenharmony_ci				if ext.name == "VK_KHR_device_group":
2248e5c31af7Sopenharmony_ci					for dg_func in dg_list:
2249e5c31af7Sopenharmony_ci						yield '\t\tif(apiVersion < VK_API_VERSION_1_1) functions.push_back("%s");' % dg_func
2250e5c31af7Sopenharmony_ci				yield '\t\treturn;'
2251e5c31af7Sopenharmony_ci				yield '\t}'
2252e5c31af7Sopenharmony_ci				isFirstWrite = False
2253e5c31af7Sopenharmony_ci		if not isFirstWrite:
2254e5c31af7Sopenharmony_ci			yield '\tDE_FATAL("Extension name not found");'
2255e5c31af7Sopenharmony_ci			yield '}'
2256e5c31af7Sopenharmony_ci
2257e5c31af7Sopenharmony_ci	lines = ['']
2258e5c31af7Sopenharmony_ci	for line in writeExtensionFunctions(Function.TYPE_INSTANCE):
2259e5c31af7Sopenharmony_ci		lines += [line]
2260e5c31af7Sopenharmony_ci	lines += ['']
2261e5c31af7Sopenharmony_ci	for line in writeExtensionFunctions(Function.TYPE_DEVICE):
2262e5c31af7Sopenharmony_ci		lines += [line]
2263e5c31af7Sopenharmony_ci	lines += ['']
2264e5c31af7Sopenharmony_ci	for line in writeExtensionNameArrays():
2265e5c31af7Sopenharmony_ci		lines += [line]
2266e5c31af7Sopenharmony_ci
2267e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, lines)
2268e5c31af7Sopenharmony_ci
2269e5c31af7Sopenharmony_cidef writeCoreFunctionalities(api, filename):
2270e5c31af7Sopenharmony_ci	functionOriginValues = ["FUNCTIONORIGIN_PLATFORM", "FUNCTIONORIGIN_INSTANCE", "FUNCTIONORIGIN_DEVICE"]
2271e5c31af7Sopenharmony_ci
2272e5c31af7Sopenharmony_ci	functionNamesPerApiVersionDict = {}
2273e5c31af7Sopenharmony_ci	for feature in api.features:
2274e5c31af7Sopenharmony_ci		apiVersion = "VK_API_VERSION_" + feature.number.replace('.', '_')
2275e5c31af7Sopenharmony_ci		functionNamesPerApiVersionDict[apiVersion] = []
2276e5c31af7Sopenharmony_ci		for r in feature.requirementsList:
2277e5c31af7Sopenharmony_ci			functionNamesPerApiVersionDict[apiVersion].extend(r.commandList)
2278e5c31af7Sopenharmony_ci
2279e5c31af7Sopenharmony_ci	lines = [
2280e5c31af7Sopenharmony_ci	"",
2281e5c31af7Sopenharmony_ci	'enum FunctionOrigin', '{'] + [line for line in indentLines([
2282e5c31af7Sopenharmony_ci	'\t' + functionOriginValues[0] + '\t= 0,',
2283e5c31af7Sopenharmony_ci	'\t' + functionOriginValues[1] + ',',
2284e5c31af7Sopenharmony_ci	'\t' + functionOriginValues[2]])] + [
2285e5c31af7Sopenharmony_ci	"};",
2286e5c31af7Sopenharmony_ci	"",
2287e5c31af7Sopenharmony_ci	"typedef ::std::pair<const char*, FunctionOrigin> FunctionInfo;",
2288e5c31af7Sopenharmony_ci	"typedef ::std::vector<FunctionInfo> FunctionInfosList;",
2289e5c31af7Sopenharmony_ci	"typedef ::std::map<uint32_t, FunctionInfosList> ApisMap;",
2290e5c31af7Sopenharmony_ci	"",
2291e5c31af7Sopenharmony_ci	"void initApisMap (ApisMap& apis)",
2292e5c31af7Sopenharmony_ci	"{",
2293e5c31af7Sopenharmony_ci	"	apis.clear();"] + [
2294e5c31af7Sopenharmony_ci	"	apis.insert(::std::pair<uint32_t, FunctionInfosList>(" + v + ", FunctionInfosList()));" for v in functionNamesPerApiVersionDict] + [
2295e5c31af7Sopenharmony_ci	""]
2296e5c31af7Sopenharmony_ci
2297e5c31af7Sopenharmony_ci	apiVersions		= []
2298e5c31af7Sopenharmony_ci	functionLines	= []
2299e5c31af7Sopenharmony_ci	for apiVersion in functionNamesPerApiVersionDict:
2300e5c31af7Sopenharmony_ci		# iterate over names of functions added with api
2301e5c31af7Sopenharmony_ci		for functionName in functionNamesPerApiVersionDict[apiVersion]:
2302e5c31af7Sopenharmony_ci			# search for data of this function in all functions list
2303e5c31af7Sopenharmony_ci			functionData = None
2304e5c31af7Sopenharmony_ci			for f in api.functions:
2305e5c31af7Sopenharmony_ci				if functionName == f.name or functionName in f.aliasList:
2306e5c31af7Sopenharmony_ci					functionData = f
2307e5c31af7Sopenharmony_ci					break
2308e5c31af7Sopenharmony_ci			if functionData == None:
2309e5c31af7Sopenharmony_ci				if api.apiName == "vulkansc":
2310e5c31af7Sopenharmony_ci					continue
2311e5c31af7Sopenharmony_ci				# something went wrong, for "vulkan" functionData should always be found
2312e5c31af7Sopenharmony_ci				assert(False)
2313e5c31af7Sopenharmony_ci			# add line coresponding to this function
2314e5c31af7Sopenharmony_ci			functionLines.append('\tapis[{0}].push_back(FunctionInfo("' + functionName + '",\t' + functionOriginValues[functionData.getType()] + '));')
2315e5c31af7Sopenharmony_ci		# functions for every api version should also include all functions from previous versions
2316e5c31af7Sopenharmony_ci		specializedLines = [line.format(apiVersion) for line in functionLines]
2317e5c31af7Sopenharmony_ci		# indent all functions of specified api and add them to main list
2318e5c31af7Sopenharmony_ci		lines = lines + [line for line in indentLines(specializedLines)] + [""]
2319e5c31af7Sopenharmony_ci
2320e5c31af7Sopenharmony_ci	lines = lines + ["}"]
2321e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, lines)
2322e5c31af7Sopenharmony_ci
2323e5c31af7Sopenharmony_cidef camelToSnake(name):
2324e5c31af7Sopenharmony_ci	name = re.sub('([a-z])([23])D([A-Z])', r'\1_\2d\3', name)
2325e5c31af7Sopenharmony_ci	name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
2326e5c31af7Sopenharmony_ci	return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()
2327e5c31af7Sopenharmony_ci
2328e5c31af7Sopenharmony_cidef writeDeviceFeatures2(api, filename):
2329e5c31af7Sopenharmony_ci
2330e5c31af7Sopenharmony_ci	def structInAPI(compositeObject):
2331e5c31af7Sopenharmony_ci		for c in api.compositeTypes:
2332e5c31af7Sopenharmony_ci			if c.name == compositeObject.name:
2333e5c31af7Sopenharmony_ci				return True
2334e5c31af7Sopenharmony_ci		return False
2335e5c31af7Sopenharmony_ci
2336e5c31af7Sopenharmony_ci	# helper class used to encapsulate all data needed during generation
2337e5c31af7Sopenharmony_ci	class StructureDetail:
2338e5c31af7Sopenharmony_ci		def __init__ (self, compositeObject):
2339e5c31af7Sopenharmony_ci			self.nameList		= [compositeObject.name] + compositeObject.aliasList
2340e5c31af7Sopenharmony_ci			self.sType			= compositeObject.members[0].values
2341e5c31af7Sopenharmony_ci			self.instanceName	= 'd' + compositeObject.name[11:]
2342e5c31af7Sopenharmony_ci			self.flagName		= 'is' + compositeObject.name[16:]
2343e5c31af7Sopenharmony_ci			self.extension		= None
2344e5c31af7Sopenharmony_ci			self.api			= None
2345e5c31af7Sopenharmony_ci			self.major			= None
2346e5c31af7Sopenharmony_ci			self.minor			= None
2347e5c31af7Sopenharmony_ci			structureMembers	= compositeObject.members[2:]
2348e5c31af7Sopenharmony_ci			self.members		= [m.name for m in structureMembers]
2349e5c31af7Sopenharmony_ci
2350e5c31af7Sopenharmony_ci	# helper extension class used in algorith below
2351e5c31af7Sopenharmony_ci	class StructureFoundContinueToNextOne(Exception):
2352e5c31af7Sopenharmony_ci		pass
2353e5c31af7Sopenharmony_ci
2354e5c31af7Sopenharmony_ci	# find structures that extend VkPhysicalDeviceFeatures2
2355e5c31af7Sopenharmony_ci	structures = [c for c in api.compositeTypes if c.structextends is not None and 'VkPhysicalDeviceFeatures2' in c.structextends]
2356e5c31af7Sopenharmony_ci	# remove structures that were added by extensions other than KHR and EXT
2357e5c31af7Sopenharmony_ci	testedStructures = []
2358e5c31af7Sopenharmony_ci	for s in structures:
2359e5c31af7Sopenharmony_ci		if all([postfix not in s.name for postfix in EXTENSION_POSTFIXES_VENDOR]):
2360e5c31af7Sopenharmony_ci			testedStructures.append(s)
2361e5c31af7Sopenharmony_ci
2362e5c31af7Sopenharmony_ci	existingStructures		= list(filter(structInAPI, testedStructures)) # remove features not found in API ( important for Vulkan SC )
2363e5c31af7Sopenharmony_ci	testedStructureDetail	= [StructureDetail(struct) for struct in existingStructures]
2364e5c31af7Sopenharmony_ci	# iterate over all searched structures and find extensions that enabled them
2365e5c31af7Sopenharmony_ci	for structureDetail in testedStructureDetail:
2366e5c31af7Sopenharmony_ci		try:
2367e5c31af7Sopenharmony_ci			# iterate over all extensions
2368e5c31af7Sopenharmony_ci			for extension in api.extensions:
2369e5c31af7Sopenharmony_ci				for requirement in extension.requirementsList:
2370e5c31af7Sopenharmony_ci					for extensionStructure in requirement.newTypes:
2371e5c31af7Sopenharmony_ci						if extensionStructure.name in structureDetail.nameList:
2372e5c31af7Sopenharmony_ci							structureDetail.extension = extension.name
2373e5c31af7Sopenharmony_ci							if extension.promotedto is not None and extension.partiallyPromoted is False:
2374e5c31af7Sopenharmony_ci								# check if extension was promoted to vulkan version or other extension
2375e5c31af7Sopenharmony_ci								if 'VK_VERSION' in extension.promotedto:
2376e5c31af7Sopenharmony_ci									versionSplit = extension.promotedto.split('_')
2377e5c31af7Sopenharmony_ci									structureDetail.api		= 0 if api.apiName == "vulkan" else 1
2378e5c31af7Sopenharmony_ci									structureDetail.major	= versionSplit[-2]
2379e5c31af7Sopenharmony_ci									structureDetail.minor	= versionSplit[-1]
2380e5c31af7Sopenharmony_ci								else:
2381e5c31af7Sopenharmony_ci									structureDetail.extension = extension.promotedto
2382e5c31af7Sopenharmony_ci							raise StructureFoundContinueToNextOne
2383e5c31af7Sopenharmony_ci		except StructureFoundContinueToNextOne:
2384e5c31af7Sopenharmony_ci			continue
2385e5c31af7Sopenharmony_ci	structureDetailToRemove = []
2386e5c31af7Sopenharmony_ci	for structureDetail in testedStructureDetail:
2387e5c31af7Sopenharmony_ci		if structureDetail.major is not None:
2388e5c31af7Sopenharmony_ci			continue
2389e5c31af7Sopenharmony_ci		# if structure was not added with extension then check if
2390e5c31af7Sopenharmony_ci		# it was added directly with one of vulkan versions
2391e5c31af7Sopenharmony_ci		structureName = structureDetail.nameList[0]
2392e5c31af7Sopenharmony_ci		for feature in api.features:
2393e5c31af7Sopenharmony_ci			for requirement in feature.requirementsList:
2394e5c31af7Sopenharmony_ci				if structureName in requirement.typeList:
2395e5c31af7Sopenharmony_ci					if api.apiName == "vulkansc" and int(feature.number[-1]) > 2:
2396e5c31af7Sopenharmony_ci						structureDetailToRemove.append(structureDetail)
2397e5c31af7Sopenharmony_ci					else:
2398e5c31af7Sopenharmony_ci						versionSplit = feature.name.split('_')
2399e5c31af7Sopenharmony_ci						structureDetail.api		= 0 if api.apiName == "vulkan" else 1
2400e5c31af7Sopenharmony_ci						structureDetail.major	= versionSplit[-2]
2401e5c31af7Sopenharmony_ci						structureDetail.minor	= versionSplit[-1]
2402e5c31af7Sopenharmony_ci					break
2403e5c31af7Sopenharmony_ci			if structureDetail.major is not None:
2404e5c31af7Sopenharmony_ci				break
2405e5c31af7Sopenharmony_ci	# remove structures that should not be tested for given api version
2406e5c31af7Sopenharmony_ci	for sd in structureDetailToRemove:
2407e5c31af7Sopenharmony_ci		testedStructureDetail.remove(sd)
2408e5c31af7Sopenharmony_ci	# generate file content
2409e5c31af7Sopenharmony_ci	structureDefinitions = []
2410e5c31af7Sopenharmony_ci	featureEnabledFlags = []
2411e5c31af7Sopenharmony_ci	clearStructures = []
2412e5c31af7Sopenharmony_ci	structureChain = []
2413e5c31af7Sopenharmony_ci	logStructures = []
2414e5c31af7Sopenharmony_ci	verifyStructures = []
2415e5c31af7Sopenharmony_ci	for index, structureDetail in enumerate(testedStructureDetail):
2416e5c31af7Sopenharmony_ci		structureName = structureDetail.nameList[0]
2417e5c31af7Sopenharmony_ci		# create two instances of each structure
2418e5c31af7Sopenharmony_ci		nameSpacing = '\t'
2419e5c31af7Sopenharmony_ci		structureDefinitions.append(structureName + nameSpacing + structureDetail.instanceName + '[count];')
2420e5c31af7Sopenharmony_ci		# create flags that check if proper extension or vulkan version is available
2421e5c31af7Sopenharmony_ci		condition	= ''
2422e5c31af7Sopenharmony_ci		extension	= structureDetail.extension
2423e5c31af7Sopenharmony_ci		major		= structureDetail.major
2424e5c31af7Sopenharmony_ci		if extension is not None:
2425e5c31af7Sopenharmony_ci			condition = ' checkExtension(properties, "' + extension + '")'
2426e5c31af7Sopenharmony_ci		if major is not None:
2427e5c31af7Sopenharmony_ci			condition = ' ' if condition == '' else condition + ' || '
2428e5c31af7Sopenharmony_ci			condition += 'context.contextSupports(vk::ApiVersion(' + str(structureDetail.api) + ', ' + str(major) + ', ' + str(structureDetail.minor) + ', 0))'
2429e5c31af7Sopenharmony_ci		if condition == '':
2430e5c31af7Sopenharmony_ci			condition = ' true'
2431e5c31af7Sopenharmony_ci		condition += ';'
2432e5c31af7Sopenharmony_ci		nameSpacing = '\t' * int((len(structureName) - 4) / 4)
2433e5c31af7Sopenharmony_ci		featureEnabledFlags.append('const bool' + nameSpacing + structureDetail.flagName + ' =' + condition)
2434e5c31af7Sopenharmony_ci		# clear memory of each structure
2435e5c31af7Sopenharmony_ci		clearStructures.append('\tdeMemset(&' + structureDetail.instanceName + '[ndx], 0xFF * ndx, sizeof(' + structureName + '));')
2436e5c31af7Sopenharmony_ci		# construct structure chain
2437e5c31af7Sopenharmony_ci		nextInstanceName = 'DE_NULL';
2438e5c31af7Sopenharmony_ci		if index < len(testedStructureDetail)-1:
2439e5c31af7Sopenharmony_ci			nextInstanceName = '&' + testedStructureDetail[index+1].instanceName + '[ndx]'
2440e5c31af7Sopenharmony_ci		structureChain.append([
2441e5c31af7Sopenharmony_ci			'\t\t' + structureDetail.instanceName + '[ndx].sType = ' + structureDetail.flagName + ' ? ' + structureDetail.sType + ' : VK_STRUCTURE_TYPE_MAX_ENUM;',
2442e5c31af7Sopenharmony_ci			'\t\t' + structureDetail.instanceName + '[ndx].pNext = DE_NULL;'])
2443e5c31af7Sopenharmony_ci		# construct log section
2444e5c31af7Sopenharmony_ci		logStructures.append([
2445e5c31af7Sopenharmony_ci			'\tif (' + structureDetail.flagName + ')',
2446e5c31af7Sopenharmony_ci			'\t\tlog << TestLog::Message << ' + structureDetail.instanceName + '[0] << TestLog::EndMessage;'
2447e5c31af7Sopenharmony_ci			])
2448e5c31af7Sopenharmony_ci		#construct verification section
2449e5c31af7Sopenharmony_ci		verifyStructure = []
2450e5c31af7Sopenharmony_ci		verifyStructure.append('\tif (' + structureDetail.flagName + ' &&')
2451e5c31af7Sopenharmony_ci		for index, m in enumerate(structureDetail.members):
2452e5c31af7Sopenharmony_ci			prefix = '\t\t(' if index == 0 else '\t\t '
2453e5c31af7Sopenharmony_ci			postfix = '))' if index == len(structureDetail.members)-1 else ' ||'
2454e5c31af7Sopenharmony_ci			verifyStructure.append(prefix + structureDetail.instanceName + '[0].' + m + ' != ' + structureDetail.instanceName + '[1].' + m + postfix)
2455e5c31af7Sopenharmony_ci		if len(structureDetail.members) == 0:
2456e5c31af7Sopenharmony_ci			verifyStructure.append('\t\tfalse)')
2457e5c31af7Sopenharmony_ci		verifyStructure.append('\t{\n\t\tTCU_FAIL("Mismatch between ' + structureName + '");\n\t}')
2458e5c31af7Sopenharmony_ci		verifyStructures.append(verifyStructure)
2459e5c31af7Sopenharmony_ci
2460e5c31af7Sopenharmony_ci	# construct file content
2461e5c31af7Sopenharmony_ci	stream = []
2462e5c31af7Sopenharmony_ci
2463e5c31af7Sopenharmony_ci	# individual test functions
2464e5c31af7Sopenharmony_ci	for n, x in enumerate(testedStructureDetail):
2465e5c31af7Sopenharmony_ci		stream.append("tcu::TestStatus testPhysicalDeviceFeature" + x.instanceName[len('device'):]+" (Context& context)")
2466e5c31af7Sopenharmony_ci		stream.append("""{
2467e5c31af7Sopenharmony_ci	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
2468e5c31af7Sopenharmony_ci	const CustomInstance		instance		(createCustomInstanceWithExtension(context, "VK_KHR_get_physical_device_properties2"));
2469e5c31af7Sopenharmony_ci	const InstanceDriver&		vki				(instance.getDriver());
2470e5c31af7Sopenharmony_ci	const int					count			= 2u;
2471e5c31af7Sopenharmony_ci	TestLog&					log				= context.getTestContext().getLog();
2472e5c31af7Sopenharmony_ci	VkPhysicalDeviceFeatures2	extFeatures;
2473e5c31af7Sopenharmony_ci	vector<VkExtensionProperties> properties	= enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);
2474e5c31af7Sopenharmony_ci""")
2475e5c31af7Sopenharmony_ci		stream.append("\t"+structureDefinitions[n])
2476e5c31af7Sopenharmony_ci		stream.append("\t"+featureEnabledFlags[n])
2477e5c31af7Sopenharmony_ci		stream.append('')
2478e5c31af7Sopenharmony_ci		stream.append('\tfor (int ndx = 0; ndx < count; ++ndx)\n\t{')
2479e5c31af7Sopenharmony_ci		stream.append("\t" + clearStructures[n])
2480e5c31af7Sopenharmony_ci		stream.extend(structureChain[n])
2481e5c31af7Sopenharmony_ci		stream.append('')
2482e5c31af7Sopenharmony_ci		stream.append(
2483e5c31af7Sopenharmony_ci				'\t\tdeMemset(&extFeatures.features, 0xcd, sizeof(extFeatures.features));\n'
2484e5c31af7Sopenharmony_ci				'\t\textFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;\n'
2485e5c31af7Sopenharmony_ci				'\t\textFeatures.pNext = &' + testedStructureDetail[n].instanceName + '[ndx];\n\n'
2486e5c31af7Sopenharmony_ci				'\t\tvki.getPhysicalDeviceFeatures2(physicalDevice, &extFeatures);')
2487e5c31af7Sopenharmony_ci		stream.append('\t}\n')
2488e5c31af7Sopenharmony_ci		stream.extend(logStructures[n])
2489e5c31af7Sopenharmony_ci		stream.append('')
2490e5c31af7Sopenharmony_ci		stream.extend(verifyStructures[n])
2491e5c31af7Sopenharmony_ci		stream.append('\treturn tcu::TestStatus::pass("Querying succeeded");')
2492e5c31af7Sopenharmony_ci		stream.append("}\n")
2493e5c31af7Sopenharmony_ci
2494e5c31af7Sopenharmony_ci	allApiVersions = [f.number for f in api.features]
2495e5c31af7Sopenharmony_ci	promotedTests = []
2496e5c31af7Sopenharmony_ci	if api.apiName == "vulkan":
2497e5c31af7Sopenharmony_ci		for feature in api.features:
2498e5c31af7Sopenharmony_ci			major = feature.number[0]
2499e5c31af7Sopenharmony_ci			minor = feature.number[-1]
2500e5c31af7Sopenharmony_ci			promotedFeatures = []
2501e5c31af7Sopenharmony_ci			if feature.name == 'VK_VERSION_1_0':
2502e5c31af7Sopenharmony_ci				continue
2503e5c31af7Sopenharmony_ci			for requirement in feature.requirementsList:
2504e5c31af7Sopenharmony_ci				for type in requirement.typeList:
2505e5c31af7Sopenharmony_ci					matchedStructType = re.search(f'VkPhysicalDevice(\w+)Features', type, re.IGNORECASE)
2506e5c31af7Sopenharmony_ci					matchedCoreStructType = re.search(f'VkPhysicalDeviceVulkan(\d+)Features', type, re.IGNORECASE)
2507e5c31af7Sopenharmony_ci					if matchedStructType and not matchedCoreStructType:
2508e5c31af7Sopenharmony_ci						promotedFeatures.append(type)
2509e5c31af7Sopenharmony_ci			if promotedFeatures:
2510e5c31af7Sopenharmony_ci				testName = "createDeviceWithPromoted" + feature.number.replace('.', '') + "Structures"
2511e5c31af7Sopenharmony_ci				promotedTests.append(testName)
2512e5c31af7Sopenharmony_ci				stream.append("tcu::TestStatus " + testName + " (Context& context)")
2513e5c31af7Sopenharmony_ci				stream.append("{")
2514e5c31af7Sopenharmony_ci				stream.append(
2515e5c31af7Sopenharmony_ci				'	if (!context.contextSupports(vk::ApiVersion(0, ' + major + ', ' + minor + ', 0)))\n'
2516e5c31af7Sopenharmony_ci				'		TCU_THROW(NotSupportedError, "Vulkan ' + major + '.' + minor + ' is not supported");')
2517e5c31af7Sopenharmony_ci				stream.append("""
2518e5c31af7Sopenharmony_ci	const PlatformInterface&		platformInterface	= context.getPlatformInterface();
2519e5c31af7Sopenharmony_ci	const CustomInstance			instance			(createCustomInstanceFromContext(context));
2520e5c31af7Sopenharmony_ci	const InstanceDriver&			instanceDriver		(instance.getDriver());
2521e5c31af7Sopenharmony_ci	const VkPhysicalDevice			physicalDevice		= chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
2522e5c31af7Sopenharmony_ci	const deUint32					queueFamilyIndex	= 0;
2523e5c31af7Sopenharmony_ci	const deUint32					queueCount			= 1;
2524e5c31af7Sopenharmony_ci	const deUint32					queueIndex			= 0;
2525e5c31af7Sopenharmony_ci	const float						queuePriority		= 1.0f;
2526e5c31af7Sopenharmony_ci
2527e5c31af7Sopenharmony_ci	const vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice);
2528e5c31af7Sopenharmony_ci
2529e5c31af7Sopenharmony_ci	const VkDeviceQueueCreateInfo	deviceQueueCreateInfo =
2530e5c31af7Sopenharmony_ci	{
2531e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
2532e5c31af7Sopenharmony_ci		DE_NULL,
2533e5c31af7Sopenharmony_ci		(VkDeviceQueueCreateFlags)0u,
2534e5c31af7Sopenharmony_ci		queueFamilyIndex,						//queueFamilyIndex;
2535e5c31af7Sopenharmony_ci		queueCount,								//queueCount;
2536e5c31af7Sopenharmony_ci		&queuePriority,							//pQueuePriorities;
2537e5c31af7Sopenharmony_ci	};
2538e5c31af7Sopenharmony_ci""")
2539e5c31af7Sopenharmony_ci				lastFeature = ''
2540e5c31af7Sopenharmony_ci				usedFeatures = []
2541e5c31af7Sopenharmony_ci				for feature in promotedFeatures:
2542e5c31af7Sopenharmony_ci					for struct in testedStructureDetail:
2543e5c31af7Sopenharmony_ci						if (struct.instanceName in usedFeatures):
2544e5c31af7Sopenharmony_ci							continue
2545e5c31af7Sopenharmony_ci						if feature in struct.nameList:
2546e5c31af7Sopenharmony_ci							if lastFeature:
2547e5c31af7Sopenharmony_ci								stream.append("\t" + feature + " " + struct.instanceName + " = initVulkanStructure(&" + lastFeature + ");")
2548e5c31af7Sopenharmony_ci							else:
2549e5c31af7Sopenharmony_ci								stream.append("\t" + feature + " " + struct.instanceName + " = initVulkanStructure();")
2550e5c31af7Sopenharmony_ci							lastFeature = struct.instanceName
2551e5c31af7Sopenharmony_ci							usedFeatures.append(struct.instanceName)
2552e5c31af7Sopenharmony_ci							break
2553e5c31af7Sopenharmony_ci				stream.append("\tVkPhysicalDeviceFeatures2 extFeatures = initVulkanStructure(&" + lastFeature + ");")
2554e5c31af7Sopenharmony_ci				stream.append("""
2555e5c31af7Sopenharmony_ci	instanceDriver.getPhysicalDeviceFeatures2 (physicalDevice, &extFeatures);
2556e5c31af7Sopenharmony_ci
2557e5c31af7Sopenharmony_ci	const VkDeviceCreateInfo		deviceCreateInfo =
2558e5c31af7Sopenharmony_ci	{
2559e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,	//sType;
2560e5c31af7Sopenharmony_ci		&extFeatures,							//pNext;
2561e5c31af7Sopenharmony_ci		(VkDeviceCreateFlags)0u,
2562e5c31af7Sopenharmony_ci		1,										//queueRecordCount;
2563e5c31af7Sopenharmony_ci		&deviceQueueCreateInfo,					//pRequestedQueues;
2564e5c31af7Sopenharmony_ci		0,										//layerCount;
2565e5c31af7Sopenharmony_ci		DE_NULL,								//ppEnabledLayerNames;
2566e5c31af7Sopenharmony_ci		0,										//extensionCount;
2567e5c31af7Sopenharmony_ci		DE_NULL,								//ppEnabledExtensionNames;
2568e5c31af7Sopenharmony_ci		DE_NULL,								//pEnabledFeatures;
2569e5c31af7Sopenharmony_ci	};
2570e5c31af7Sopenharmony_ci
2571e5c31af7Sopenharmony_ci	const Unique<VkDevice>			device			(createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), platformInterface, instance, instanceDriver, physicalDevice, &deviceCreateInfo));
2572e5c31af7Sopenharmony_ci	const DeviceDriver				deviceDriver	(platformInterface, instance, device.get(), context.getUsedApiVersion());
2573e5c31af7Sopenharmony_ci	const VkQueue					queue			= getDeviceQueue(deviceDriver, *device, queueFamilyIndex, queueIndex);
2574e5c31af7Sopenharmony_ci
2575e5c31af7Sopenharmony_ci	VK_CHECK(deviceDriver.queueWaitIdle(queue));
2576e5c31af7Sopenharmony_ci
2577e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Pass");
2578e5c31af7Sopenharmony_ci}
2579e5c31af7Sopenharmony_ci""")
2580e5c31af7Sopenharmony_ci
2581e5c31af7Sopenharmony_ci	# function to create tests
2582e5c31af7Sopenharmony_ci	stream.append("void addSeparateFeatureTests (tcu::TestCaseGroup* testGroup)\n{")
2583e5c31af7Sopenharmony_ci	for x in testedStructureDetail:
2584e5c31af7Sopenharmony_ci		stream.append('\taddFunctionCase(testGroup, "' + camelToSnake(x.instanceName[len('device'):]) + '", testPhysicalDeviceFeature' + x.instanceName[len('device'):] + ');')
2585e5c31af7Sopenharmony_ci	for x in promotedTests:
2586e5c31af7Sopenharmony_ci		stream.append('\taddFunctionCase(testGroup, "' + camelToSnake(x) + '", ' + x + ');')
2587e5c31af7Sopenharmony_ci	stream.append('}\n')
2588e5c31af7Sopenharmony_ci
2589e5c31af7Sopenharmony_ci	# write out
2590e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, stream)
2591e5c31af7Sopenharmony_ci
2592e5c31af7Sopenharmony_cidef generateDeviceFeaturesOrPropertiesDefs(api, FeaturesOrProperties):
2593e5c31af7Sopenharmony_ci	assert(FeaturesOrProperties in ['Features', 'Properties'])
2594e5c31af7Sopenharmony_ci	defs								= []
2595e5c31af7Sopenharmony_ci	foundStructureEnums					= []
2596e5c31af7Sopenharmony_ci	structureEnumPattern				= f'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_{FeaturesOrProperties.upper()}(\w+)'
2597e5c31af7Sopenharmony_ci	structureEnumPatternNotExtension	= structureEnumPattern[:-5] + '$'
2598e5c31af7Sopenharmony_ci	structureTypePattern				= f'VkPhysicalDevice(\w+){FeaturesOrProperties}(\w+)'
2599e5c31af7Sopenharmony_ci	structureTypePatternNotExtension	= structureTypePattern[:-5] + '$'
2600e5c31af7Sopenharmony_ci	structureTypeToSkipPattern			= f'VkPhysicalDeviceVulkan\d\d{FeaturesOrProperties}'
2601e5c31af7Sopenharmony_ci	structureExtendsPattern				= f'VkPhysicalDevice{FeaturesOrProperties}2'
2602e5c31af7Sopenharmony_ci	# iterate over all extensions to find extension that adds enum value matching pattern;
2603e5c31af7Sopenharmony_ci	# this will always be in first requirement section
2604e5c31af7Sopenharmony_ci	for ext in api.extensions:
2605e5c31af7Sopenharmony_ci		# skip extensions that were promoted to other extensions (not vk version)
2606e5c31af7Sopenharmony_ci		if ext.promotedto is not None and "VK_VERSION" not in ext.promotedto:
2607e5c31af7Sopenharmony_ci			continue
2608e5c31af7Sopenharmony_ci		allExtendedEnums = ext.requirementsList[0].extendedEnums
2609e5c31af7Sopenharmony_ci		for extendedEnum in allExtendedEnums:
2610e5c31af7Sopenharmony_ci			matchedStructEnum = re.search(structureEnumPattern, extendedEnum.name, re.IGNORECASE)
2611e5c31af7Sopenharmony_ci			if matchedStructEnum:
2612e5c31af7Sopenharmony_ci				# find feature/property structure type name
2613e5c31af7Sopenharmony_ci				structureTypeName = ""
2614e5c31af7Sopenharmony_ci				for stRequirement in ext.requirementsList[0].newTypes:
2615e5c31af7Sopenharmony_ci					stName = stRequirement.name
2616e5c31af7Sopenharmony_ci					matchedStructType = re.search(structureTypePattern, stName, re.IGNORECASE)
2617e5c31af7Sopenharmony_ci					if matchedStructType:
2618e5c31af7Sopenharmony_ci						structureTypeName = stName
2619e5c31af7Sopenharmony_ci						break
2620e5c31af7Sopenharmony_ci				# iterate over all composite types to check if structureTypeName is not alias
2621e5c31af7Sopenharmony_ci				# this handles case where extension was promoted and with it feature/property structure
2622e5c31af7Sopenharmony_ci				structureType = None
2623e5c31af7Sopenharmony_ci				for ct in api.compositeTypes:
2624e5c31af7Sopenharmony_ci					if structureTypeName == ct.name:
2625e5c31af7Sopenharmony_ci						structureType = ct
2626e5c31af7Sopenharmony_ci						break
2627e5c31af7Sopenharmony_ci					elif structureTypeName in ct.aliasList:
2628e5c31af7Sopenharmony_ci						structureType = ct
2629e5c31af7Sopenharmony_ci						structureTypeName = structureType.name
2630e5c31af7Sopenharmony_ci						break
2631e5c31af7Sopenharmony_ci				# use data in structextends to skip structures that should not be passed to vkGetPhysicalDeviceProperties(/Features)2 function
2632e5c31af7Sopenharmony_ci				if structureType is None or structureType.structextends is None or structureExtendsPattern not in structureType.structextends:
2633e5c31af7Sopenharmony_ci					continue
2634e5c31af7Sopenharmony_ci				# meke sure that structure was not added earlier - this handles special
2635e5c31af7Sopenharmony_ci				# cases like VkPhysicalDeviceIDPropertiesKHR added by 3 extensions
2636e5c31af7Sopenharmony_ci				if len([d for d in defs if d[3] == structureTypeName]) > 0:
2637e5c31af7Sopenharmony_ci					continue
2638e5c31af7Sopenharmony_ci				# there are cases like VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD
2639e5c31af7Sopenharmony_ci				# where 2 is after PROPERTIES - to handle this we need to split suffix to two parts
2640e5c31af7Sopenharmony_ci				sSuffix		= matchedStructEnum.group(2)
2641e5c31af7Sopenharmony_ci				sVerSuffix	= ''
2642e5c31af7Sopenharmony_ci				sExtSuffix	= sSuffix
2643e5c31af7Sopenharmony_ci				suffixStart = sSuffix.rfind('_')
2644e5c31af7Sopenharmony_ci				if suffixStart > 0:
2645e5c31af7Sopenharmony_ci					sVerSuffix = sSuffix[:suffixStart]
2646e5c31af7Sopenharmony_ci					sExtSuffix = sSuffix[suffixStart:]
2647e5c31af7Sopenharmony_ci				foundStructureEnums.append(matchedStructEnum.group(1))
2648e5c31af7Sopenharmony_ci				defs.append( (matchedStructEnum.group(1), sVerSuffix, sExtSuffix, structureTypeName,\
2649e5c31af7Sopenharmony_ci							  ext.name, allExtendedEnums[1].name, allExtendedEnums[0].name) )
2650e5c31af7Sopenharmony_ci				# accept single feature/property structure per extension - this also handles cases
2651e5c31af7Sopenharmony_ci				# like VK_KHR_variable_pointers which specify feature structure and its alias
2652e5c31af7Sopenharmony_ci				break
2653e5c31af7Sopenharmony_ci
2654e5c31af7Sopenharmony_ci	# iterate over all structures to find Feature/Property structures that were not added with extension
2655e5c31af7Sopenharmony_ci	# but with vulkan version; to do that we need to skip extension part from pattern
2656e5c31af7Sopenharmony_ci	for ct in api.compositeTypes:
2657e5c31af7Sopenharmony_ci		matchedStructType = re.search(structureTypePatternNotExtension, ct.name, re.IGNORECASE)
2658e5c31af7Sopenharmony_ci		if matchedStructType:
2659e5c31af7Sopenharmony_ci			if ct.members[0].name != "sType":
2660e5c31af7Sopenharmony_ci				continue
2661e5c31af7Sopenharmony_ci			if ct.structextends is None or structureExtendsPattern not in ct.structextends:
2662e5c31af7Sopenharmony_ci				continue
2663e5c31af7Sopenharmony_ci			matchedStructEnum = re.search(structureEnumPatternNotExtension, ct.members[0].values, re.IGNORECASE)
2664e5c31af7Sopenharmony_ci			if (matchedStructEnum.group(1) not in foundStructureEnums) and (re.match(structureTypeToSkipPattern, ct.name) == None):
2665e5c31af7Sopenharmony_ci				defs.append( (matchedStructEnum.group(1), '', '', ct.name, None, None, '0') )
2666e5c31af7Sopenharmony_ci	return defs
2667e5c31af7Sopenharmony_ci
2668e5c31af7Sopenharmony_cidef writeDeviceFeatures(api, dfDefs, filename):
2669e5c31af7Sopenharmony_ci	# find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
2670e5c31af7Sopenharmony_ci	# and construct dictionary with all of their attributes
2671e5c31af7Sopenharmony_ci	blobMembers = {}
2672e5c31af7Sopenharmony_ci	blobStructs = {}
2673e5c31af7Sopenharmony_ci	blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
2674e5c31af7Sopenharmony_ci	for structureType in api.compositeTypes:
2675e5c31af7Sopenharmony_ci		match = blobPattern.match(structureType.name)
2676e5c31af7Sopenharmony_ci		if match:
2677e5c31af7Sopenharmony_ci			allMembers = [member.name for member in structureType.members]
2678e5c31af7Sopenharmony_ci			vkVersion = match.group(1)
2679e5c31af7Sopenharmony_ci			blobMembers[vkVersion] = allMembers[2:]
2680e5c31af7Sopenharmony_ci			blobStructs[vkVersion] = set()
2681e5c31af7Sopenharmony_ci	initFromBlobDefinitions = []
2682e5c31af7Sopenharmony_ci	emptyInitDefinitions = []
2683e5c31af7Sopenharmony_ci	# iterate over all feature structures
2684e5c31af7Sopenharmony_ci	allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
2685e5c31af7Sopenharmony_ci	nonExtFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*$")
2686e5c31af7Sopenharmony_ci	for structureType in api.compositeTypes:
2687e5c31af7Sopenharmony_ci		# skip structures that are not feature structures
2688e5c31af7Sopenharmony_ci		if not allFeaturesPattern.match(structureType.name):
2689e5c31af7Sopenharmony_ci			continue
2690e5c31af7Sopenharmony_ci		# skip structures that were previously identified as blobs
2691e5c31af7Sopenharmony_ci		if blobPattern.match(structureType.name):
2692e5c31af7Sopenharmony_ci			continue
2693e5c31af7Sopenharmony_ci		# skip sType and pNext and just grab third and next attributes
2694e5c31af7Sopenharmony_ci		structureMembers = structureType.members[2:]
2695e5c31af7Sopenharmony_ci		notPartOfBlob = True
2696e5c31af7Sopenharmony_ci		if nonExtFeaturesPattern.match(structureType.name):
2697e5c31af7Sopenharmony_ci			# check if this member is part of any of the blobs
2698e5c31af7Sopenharmony_ci			for blobName, blobMemberList in blobMembers.items():
2699e5c31af7Sopenharmony_ci				# if just one member is not part of this blob go to the next blob
2700e5c31af7Sopenharmony_ci				# (we asume that all members are part of blob - no need to check all)
2701e5c31af7Sopenharmony_ci				if structureMembers[0].name not in blobMemberList:
2702e5c31af7Sopenharmony_ci					continue
2703e5c31af7Sopenharmony_ci				# add another feature structure name to this blob
2704e5c31af7Sopenharmony_ci				blobStructs[blobName].add(structureType)
2705e5c31af7Sopenharmony_ci				# add specialization for this feature structure
2706e5c31af7Sopenharmony_ci				memberCopying = ""
2707e5c31af7Sopenharmony_ci				for member in structureMembers:
2708e5c31af7Sopenharmony_ci					memberCopying += "\tfeatureType.{0} = allFeaturesBlobs.vk{1}.{0};\n".format(member.name, blobName)
2709e5c31af7Sopenharmony_ci				wholeFunction = \
2710e5c31af7Sopenharmony_ci					"template<> void initFeatureFromBlob<{0}>({0}& featureType, const AllFeaturesBlobs& allFeaturesBlobs)\n" \
2711e5c31af7Sopenharmony_ci					"{{\n" \
2712e5c31af7Sopenharmony_ci					"{1}" \
2713e5c31af7Sopenharmony_ci					"}}".format(structureType.name, memberCopying)
2714e5c31af7Sopenharmony_ci				initFromBlobDefinitions.append(wholeFunction)
2715e5c31af7Sopenharmony_ci				notPartOfBlob = False
2716e5c31af7Sopenharmony_ci				# assuming that all members are part of blob, goto next
2717e5c31af7Sopenharmony_ci				break
2718e5c31af7Sopenharmony_ci		# add empty template definition as on Fedora there are issue with
2719e5c31af7Sopenharmony_ci		# linking using just generic template - all specializations are needed
2720e5c31af7Sopenharmony_ci		if notPartOfBlob:
2721e5c31af7Sopenharmony_ci			emptyFunction = "template<> void initFeatureFromBlob<{0}>({0}&, const AllFeaturesBlobs&) {{}}"
2722e5c31af7Sopenharmony_ci			emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2723e5c31af7Sopenharmony_ci	extensionDefines = []
2724e5c31af7Sopenharmony_ci	makeFeatureDescDefinitions = []
2725e5c31af7Sopenharmony_ci	featureStructWrappers = []
2726e5c31af7Sopenharmony_ci	for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extName, extNameDef, specVersionDef) in enumerate(dfDefs):
2727e5c31af7Sopenharmony_ci		extensionNameDefinition = extNameDef
2728e5c31af7Sopenharmony_ci		if not extensionNameDefinition:
2729e5c31af7Sopenharmony_ci			extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2730e5c31af7Sopenharmony_ci			extensionDefines.append(f'#define {extensionNameDefinition} "core_feature"')
2731e5c31af7Sopenharmony_ci		# construct makeFeatureDesc template function definitions
2732e5c31af7Sopenharmony_ci		sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sVerSuffix + sExtSuffix)
2733e5c31af7Sopenharmony_ci		makeFeatureDescDefinitions.append("template<> FeatureDesc makeFeatureDesc<{0}>(void) " \
2734e5c31af7Sopenharmony_ci			"{{ return FeatureDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVersionDef, len(dfDefs)-idx))
2735e5c31af7Sopenharmony_ci		# construct CreateFeatureStruct wrapper block
2736e5c31af7Sopenharmony_ci		featureStructWrappers.append("\t{{ createFeatureStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVersionDef))
2737e5c31af7Sopenharmony_ci	# construct function that will check for which vk version structure sType is part of blob
2738e5c31af7Sopenharmony_ci	blobChecker = "deUint32 getBlobFeaturesVersion (VkStructureType sType)\n{\n" \
2739e5c31af7Sopenharmony_ci				  "\tconst std::map<VkStructureType, deUint32> sTypeBlobMap\n" \
2740e5c31af7Sopenharmony_ci				  "\t{\n"
2741e5c31af7Sopenharmony_ci	# iterate over blobs with list of structures
2742e5c31af7Sopenharmony_ci	for blobName in sorted(blobStructs.keys()):
2743e5c31af7Sopenharmony_ci		blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2744e5c31af7Sopenharmony_ci		# iterate over all feature structures in current blob
2745e5c31af7Sopenharmony_ci		structuresList = list(blobStructs[blobName])
2746e5c31af7Sopenharmony_ci		structuresList = sorted(structuresList, key=lambda s: s.name)
2747e5c31af7Sopenharmony_ci		for structType in structuresList:
2748e5c31af7Sopenharmony_ci			# find definition of this structure in dfDefs
2749e5c31af7Sopenharmony_ci			structDef = None
2750e5c31af7Sopenharmony_ci			allNamesToCheck = [structType.name]
2751e5c31af7Sopenharmony_ci			if len(structType.aliasList) > 0:
2752e5c31af7Sopenharmony_ci				allNamesToCheck.extend(structType.aliasList)
2753e5c31af7Sopenharmony_ci			for structName in allNamesToCheck:
2754e5c31af7Sopenharmony_ci				structDefList = [s for s in dfDefs if s[3] == structName]
2755e5c31af7Sopenharmony_ci				if len(structDefList) > 0:
2756e5c31af7Sopenharmony_ci					structDef = structDefList[0]
2757e5c31af7Sopenharmony_ci					break
2758e5c31af7Sopenharmony_ci			sType = structDef[0]
2759e5c31af7Sopenharmony_ci			sSuffix = structDef[1] + structDef[2]
2760e5c31af7Sopenharmony_ci			sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sSuffix)
2761e5c31af7Sopenharmony_ci			tabs = "\t" * int((88 - len(sTypeName)) / 4)
2762e5c31af7Sopenharmony_ci			blobChecker += "\t\t{{ {0},{1}VK_API_VERSION_{2}_{3} }},\n".format(sTypeName, tabs, blobName[0], blobName[1])
2763e5c31af7Sopenharmony_ci	blobChecker += "\t};\n\n" \
2764e5c31af7Sopenharmony_ci				   "\tauto it = sTypeBlobMap.find(sType);\n" \
2765e5c31af7Sopenharmony_ci				   "\tif(it == sTypeBlobMap.end())\n" \
2766e5c31af7Sopenharmony_ci				   "\t\treturn 0;\n" \
2767e5c31af7Sopenharmony_ci				   "\treturn it->second;\n" \
2768e5c31af7Sopenharmony_ci				   "}\n"
2769e5c31af7Sopenharmony_ci	# combine all definition lists
2770e5c31af7Sopenharmony_ci	stream = [
2771e5c31af7Sopenharmony_ci	'#include "vkDeviceFeatures.hpp"\n',
2772e5c31af7Sopenharmony_ci	'namespace vk\n{']
2773e5c31af7Sopenharmony_ci	stream.extend(extensionDefines)
2774e5c31af7Sopenharmony_ci	stream.append('\n')
2775e5c31af7Sopenharmony_ci	stream.extend(initFromBlobDefinitions)
2776e5c31af7Sopenharmony_ci	stream.append('\n// generic template is not enough for some compilers')
2777e5c31af7Sopenharmony_ci	stream.extend(emptyInitDefinitions)
2778e5c31af7Sopenharmony_ci	stream.append('\n')
2779e5c31af7Sopenharmony_ci	stream.extend(makeFeatureDescDefinitions)
2780e5c31af7Sopenharmony_ci	stream.append('\n')
2781e5c31af7Sopenharmony_ci	stream.append('static const FeatureStructCreationData featureStructCreationArray[]\n{')
2782e5c31af7Sopenharmony_ci	stream.extend(featureStructWrappers)
2783e5c31af7Sopenharmony_ci	stream.append('};\n')
2784e5c31af7Sopenharmony_ci	stream.append(blobChecker)
2785e5c31af7Sopenharmony_ci	stream.append('} // vk\n')
2786e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, stream)
2787e5c31af7Sopenharmony_ci
2788e5c31af7Sopenharmony_cidef writeDeviceFeatureTest(api, filename):
2789e5c31af7Sopenharmony_ci
2790e5c31af7Sopenharmony_ci	coreFeaturesPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
2791e5c31af7Sopenharmony_ci	featureItems = []
2792e5c31af7Sopenharmony_ci	testFunctions = []
2793e5c31af7Sopenharmony_ci	# iterate over all feature structures
2794e5c31af7Sopenharmony_ci	allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
2795e5c31af7Sopenharmony_ci	for structureType in api.compositeTypes:
2796e5c31af7Sopenharmony_ci		# skip structures that are not feature structures
2797e5c31af7Sopenharmony_ci		if not allFeaturesPattern.match(structureType.name):
2798e5c31af7Sopenharmony_ci			continue
2799e5c31af7Sopenharmony_ci		# skip sType and pNext and just grab third and next attributes
2800e5c31af7Sopenharmony_ci		structureMembers = structureType.members[2:]
2801e5c31af7Sopenharmony_ci
2802e5c31af7Sopenharmony_ci		items = []
2803e5c31af7Sopenharmony_ci		for member in structureMembers:
2804e5c31af7Sopenharmony_ci			items.append("		FEATURE_ITEM ({0}, {1}),".format(structureType.name, member.name))
2805e5c31af7Sopenharmony_ci
2806e5c31af7Sopenharmony_ci		testBlock = """
2807e5c31af7Sopenharmony_citcu::TestStatus createDeviceWithUnsupportedFeaturesTest{4} (Context& context)
2808e5c31af7Sopenharmony_ci{{
2809e5c31af7Sopenharmony_ci	const PlatformInterface&				vkp						= context.getPlatformInterface();
2810e5c31af7Sopenharmony_ci	tcu::TestLog&							log						= context.getTestContext().getLog();
2811e5c31af7Sopenharmony_ci	tcu::ResultCollector					resultCollector			(log);
2812e5c31af7Sopenharmony_ci	const CustomInstance					instance				(createCustomInstanceWithExtensions(context, context.getInstanceExtensions(), DE_NULL, true));
2813e5c31af7Sopenharmony_ci	const InstanceDriver&					instanceDriver			(instance.getDriver());
2814e5c31af7Sopenharmony_ci	const VkPhysicalDevice					physicalDevice			= chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
2815e5c31af7Sopenharmony_ci	const deUint32							queueFamilyIndex		= 0;
2816e5c31af7Sopenharmony_ci	const deUint32							queueCount				= 1;
2817e5c31af7Sopenharmony_ci	const float								queuePriority			= 1.0f;
2818e5c31af7Sopenharmony_ci	const DeviceFeatures					deviceFeaturesAll		(context.getInstanceInterface(), context.getUsedApiVersion(), physicalDevice, context.getInstanceExtensions(), context.getDeviceExtensions(), DE_TRUE);
2819e5c31af7Sopenharmony_ci	const VkPhysicalDeviceFeatures2			deviceFeatures2			= deviceFeaturesAll.getCoreFeatures2();
2820e5c31af7Sopenharmony_ci	int										numErrors				= 0;
2821e5c31af7Sopenharmony_ci	bool                                                                    isSubProcess                    = context.getTestContext().getCommandLine().isSubProcess();
2822e5c31af7Sopenharmony_ci{6}
2823e5c31af7Sopenharmony_ci
2824e5c31af7Sopenharmony_ci	VkPhysicalDeviceFeatures emptyDeviceFeatures;
2825e5c31af7Sopenharmony_ci	deMemset(&emptyDeviceFeatures, 0, sizeof(emptyDeviceFeatures));
2826e5c31af7Sopenharmony_ci
2827e5c31af7Sopenharmony_ci	// Only non-core extensions will be used when creating the device.
2828e5c31af7Sopenharmony_ci	const auto& extensionNames = context.getDeviceCreationExtensions();
2829e5c31af7Sopenharmony_ci	DE_UNREF(extensionNames); // In some cases this is not used.
2830e5c31af7Sopenharmony_ci
2831e5c31af7Sopenharmony_ci	if (const void* featuresStruct = findStructureInChain(const_cast<const void*>(deviceFeatures2.pNext), getStructureType<{0}>()))
2832e5c31af7Sopenharmony_ci	{{
2833e5c31af7Sopenharmony_ci		static const Feature features[] =
2834e5c31af7Sopenharmony_ci		{{
2835e5c31af7Sopenharmony_ci{1}
2836e5c31af7Sopenharmony_ci		}};
2837e5c31af7Sopenharmony_ci		auto* supportedFeatures = reinterpret_cast<const {0}*>(featuresStruct);
2838e5c31af7Sopenharmony_ci		checkFeatures(vkp, instance, instanceDriver, physicalDevice, {2}, features, supportedFeatures, queueFamilyIndex, queueCount, queuePriority, numErrors, resultCollector, {3}, emptyDeviceFeatures, {5}, context.getUsedApiVersion());
2839e5c31af7Sopenharmony_ci	}}
2840e5c31af7Sopenharmony_ci
2841e5c31af7Sopenharmony_ci	if (numErrors > 0)
2842e5c31af7Sopenharmony_ci		return tcu::TestStatus(resultCollector.getResult(), "Enabling unsupported features didn't return VK_ERROR_FEATURE_NOT_PRESENT.");
2843e5c31af7Sopenharmony_ci	else
2844e5c31af7Sopenharmony_ci		return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage());
2845e5c31af7Sopenharmony_ci}}
2846e5c31af7Sopenharmony_ci"""
2847e5c31af7Sopenharmony_ci		additionalParams = ( 'memReservationStatMax, isSubProcess' if api.apiName == 'vulkansc' else 'isSubProcess' )
2848e5c31af7Sopenharmony_ci		additionalDefs = ( '	VkDeviceObjectReservationCreateInfo memReservationStatMax = context.getResourceInterface()->getStatMax();' if apiName == 'vulkansc' else '')
2849e5c31af7Sopenharmony_ci		featureItems.append(testBlock.format(structureType.name, "\n".join(items), len(items), ("DE_NULL" if coreFeaturesPattern.match(structureType.name) else "&extensionNames"), structureType.name[len('VkPhysicalDevice'):], additionalParams, additionalDefs))
2850e5c31af7Sopenharmony_ci
2851e5c31af7Sopenharmony_ci		testFunctions.append("createDeviceWithUnsupportedFeaturesTest" + structureType.name[len('VkPhysicalDevice'):])
2852e5c31af7Sopenharmony_ci
2853e5c31af7Sopenharmony_ci	stream = ['']
2854e5c31af7Sopenharmony_ci	stream.extend(featureItems)
2855e5c31af7Sopenharmony_ci	stream.append("""
2856e5c31af7Sopenharmony_civoid addSeparateUnsupportedFeatureTests (tcu::TestCaseGroup* testGroup)
2857e5c31af7Sopenharmony_ci{
2858e5c31af7Sopenharmony_ci""")
2859e5c31af7Sopenharmony_ci	for x in testFunctions:
2860e5c31af7Sopenharmony_ci		stream.append('\taddFunctionCase(testGroup, "' + camelToSnake(x[len('createDeviceWithUnsupportedFeaturesTest'):]) + '", ' + x + ');')
2861e5c31af7Sopenharmony_ci	stream.append('}\n')
2862e5c31af7Sopenharmony_ci
2863e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, stream)
2864e5c31af7Sopenharmony_ci
2865e5c31af7Sopenharmony_cidef writeDeviceProperties(api, dpDefs, filename):
2866e5c31af7Sopenharmony_ci	# find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
2867e5c31af7Sopenharmony_ci	# and construct dictionary with all of their attributes
2868e5c31af7Sopenharmony_ci	blobMembers = {}
2869e5c31af7Sopenharmony_ci	blobStructs = {}
2870e5c31af7Sopenharmony_ci	blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Properties[0-9]*$")
2871e5c31af7Sopenharmony_ci	for structureType in api.compositeTypes:
2872e5c31af7Sopenharmony_ci		match = blobPattern.match(structureType.name)
2873e5c31af7Sopenharmony_ci		if match:
2874e5c31af7Sopenharmony_ci			allMembers = [member.name for member in structureType.members]
2875e5c31af7Sopenharmony_ci			vkVersion = match.group(1)
2876e5c31af7Sopenharmony_ci			blobMembers[vkVersion] = allMembers[2:]
2877e5c31af7Sopenharmony_ci			blobStructs[vkVersion] = set()
2878e5c31af7Sopenharmony_ci	initFromBlobDefinitions = []
2879e5c31af7Sopenharmony_ci	emptyInitDefinitions = []
2880e5c31af7Sopenharmony_ci	# iterate over all property structures
2881e5c31af7Sopenharmony_ci	allPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*")
2882e5c31af7Sopenharmony_ci	nonExtPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*$")
2883e5c31af7Sopenharmony_ci	for structureType in api.compositeTypes:
2884e5c31af7Sopenharmony_ci		# skip structures that are not property structures
2885e5c31af7Sopenharmony_ci		if not allPropertiesPattern.match(structureType.name):
2886e5c31af7Sopenharmony_ci			continue
2887e5c31af7Sopenharmony_ci		# skip structures that were previously identified as blobs
2888e5c31af7Sopenharmony_ci		if blobPattern.match(structureType.name):
2889e5c31af7Sopenharmony_ci			continue
2890e5c31af7Sopenharmony_ci		# skip sType and pNext and just grab third and next attributes
2891e5c31af7Sopenharmony_ci		structureMembers = structureType.members[2:]
2892e5c31af7Sopenharmony_ci		notPartOfBlob = True
2893e5c31af7Sopenharmony_ci		if nonExtPropertiesPattern.match(structureType.name):
2894e5c31af7Sopenharmony_ci			# check if this member is part of any of the blobs
2895e5c31af7Sopenharmony_ci			for blobName, blobMemberList in blobMembers.items():
2896e5c31af7Sopenharmony_ci				# if just one member is not part of this blob go to the next blob
2897e5c31af7Sopenharmony_ci				# (we asume that all members are part of blob - no need to check all)
2898e5c31af7Sopenharmony_ci				if structureMembers[0].name not in blobMemberList:
2899e5c31af7Sopenharmony_ci					continue
2900e5c31af7Sopenharmony_ci				# add another property structure name to this blob
2901e5c31af7Sopenharmony_ci				blobStructs[blobName].add(structureType)
2902e5c31af7Sopenharmony_ci				# add specialization for this property structure
2903e5c31af7Sopenharmony_ci				memberCopying = ""
2904e5c31af7Sopenharmony_ci				for member in structureMembers:
2905e5c31af7Sopenharmony_ci					if len(member.arraySizeList) == 0:
2906e5c31af7Sopenharmony_ci						# handle special case
2907e5c31af7Sopenharmony_ci						if structureType.name == "VkPhysicalDeviceSubgroupProperties" and "subgroup" not in member.name :
2908e5c31af7Sopenharmony_ci							blobMemberName = "subgroup" + member.name[0].capitalize() + member.name[1:]
2909e5c31af7Sopenharmony_ci							memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{2};\n".format(member.name, blobName, blobMemberName)
2910e5c31af7Sopenharmony_ci						# end handling special case
2911e5c31af7Sopenharmony_ci						else:
2912e5c31af7Sopenharmony_ci							memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{0};\n".format(member.name, blobName)
2913e5c31af7Sopenharmony_ci					else:
2914e5c31af7Sopenharmony_ci						memberCopying += "\tmemcpy(propertyType.{0}, allPropertiesBlobs.vk{1}.{0}, sizeof({2}) * {3});\n".format(member.name, blobName, member.type, member.arraySizeList[0])
2915e5c31af7Sopenharmony_ci				wholeFunction = \
2916e5c31af7Sopenharmony_ci					"template<> void initPropertyFromBlob<{0}>({0}& propertyType, const AllPropertiesBlobs& allPropertiesBlobs)\n" \
2917e5c31af7Sopenharmony_ci					"{{\n" \
2918e5c31af7Sopenharmony_ci					"{1}" \
2919e5c31af7Sopenharmony_ci					"}}".format(structureType.name, memberCopying)
2920e5c31af7Sopenharmony_ci				initFromBlobDefinitions.append(wholeFunction)
2921e5c31af7Sopenharmony_ci				notPartOfBlob = False
2922e5c31af7Sopenharmony_ci				# assuming that all members are part of blob, goto next
2923e5c31af7Sopenharmony_ci				break
2924e5c31af7Sopenharmony_ci		# add empty template definition as on Fedora there are issue with
2925e5c31af7Sopenharmony_ci		# linking using just generic template - all specializations are needed
2926e5c31af7Sopenharmony_ci		if notPartOfBlob:
2927e5c31af7Sopenharmony_ci			emptyFunction = "template<> void initPropertyFromBlob<{0}>({0}&, const AllPropertiesBlobs&) {{}}"
2928e5c31af7Sopenharmony_ci			emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2929e5c31af7Sopenharmony_ci	extensionDefines = []
2930e5c31af7Sopenharmony_ci	makePropertyDescDefinitions = []
2931e5c31af7Sopenharmony_ci	propertyStructWrappers = []
2932e5c31af7Sopenharmony_ci	for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extName, extNameDef, specVersionDef) in enumerate(dpDefs):
2933e5c31af7Sopenharmony_ci		extensionNameDefinition = extNameDef
2934e5c31af7Sopenharmony_ci		if not extensionNameDefinition:
2935e5c31af7Sopenharmony_ci			extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2936e5c31af7Sopenharmony_ci			extensionDefines.append(f'#define {extensionNameDefinition} "core_property"')
2937e5c31af7Sopenharmony_ci		# construct makePropertyDesc template function definitions
2938e5c31af7Sopenharmony_ci		sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sVerSuffix + sExtSuffix)
2939e5c31af7Sopenharmony_ci		makePropertyDescDefinitions.append("template<> PropertyDesc makePropertyDesc<{0}>(void) " \
2940e5c31af7Sopenharmony_ci			"{{ return PropertyDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVersionDef, len(dpDefs)-idx))
2941e5c31af7Sopenharmony_ci		# construct CreateProperty struct wrapper block
2942e5c31af7Sopenharmony_ci		propertyStructWrappers.append("\t{{ createPropertyStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVersionDef))
2943e5c31af7Sopenharmony_ci	# construct method that will check if structure sType is part of blob
2944e5c31af7Sopenharmony_ci	blobChecker = "deUint32 getBlobPropertiesVersion (VkStructureType sType)\n{\n" \
2945e5c31af7Sopenharmony_ci				  "\tconst std::map<VkStructureType, deUint32> sTypeBlobMap\n" \
2946e5c31af7Sopenharmony_ci				  "\t{\n"
2947e5c31af7Sopenharmony_ci	# iterate over blobs with list of structures
2948e5c31af7Sopenharmony_ci	for blobName in sorted(blobStructs.keys()):
2949e5c31af7Sopenharmony_ci		blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2950e5c31af7Sopenharmony_ci		# iterate over all feature structures in current blob
2951e5c31af7Sopenharmony_ci		structuresList = list(blobStructs[blobName])
2952e5c31af7Sopenharmony_ci		structuresList = sorted(structuresList, key=lambda s: s.name)
2953e5c31af7Sopenharmony_ci		for structType in structuresList:
2954e5c31af7Sopenharmony_ci			# find definition of this structure in dpDefs
2955e5c31af7Sopenharmony_ci			structName = structType.name
2956e5c31af7Sopenharmony_ci			structDef = None
2957e5c31af7Sopenharmony_ci			foundDefs = [s for s in dpDefs if s[3] == structName]
2958e5c31af7Sopenharmony_ci			if len(foundDefs) > 0:
2959e5c31af7Sopenharmony_ci				structDef = foundDefs[0]
2960e5c31af7Sopenharmony_ci			else:
2961e5c31af7Sopenharmony_ci				for alias in structType.aliasList:
2962e5c31af7Sopenharmony_ci					foundDefs = [s for s in dpDefs if s[3] == alias]
2963e5c31af7Sopenharmony_ci					if len(foundDefs) > 0:
2964e5c31af7Sopenharmony_ci						structDef = foundDefs[0]
2965e5c31af7Sopenharmony_ci						break
2966e5c31af7Sopenharmony_ci			sType = structDef[0]
2967e5c31af7Sopenharmony_ci			sSuffix = structDef[1] + structDef[2]
2968e5c31af7Sopenharmony_ci			sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sSuffix)
2969e5c31af7Sopenharmony_ci			tabs = "\t" * int((80 - len(sTypeName)) / 4)
2970e5c31af7Sopenharmony_ci			blobChecker += "\t\t{{ {0},{1}VK_API_VERSION_{2}_{3} }},\n".format(sTypeName, tabs, blobName[0], blobName[1])
2971e5c31af7Sopenharmony_ci	blobChecker += "\t};\n\n" \
2972e5c31af7Sopenharmony_ci				   "\tauto it = sTypeBlobMap.find(sType);\n" \
2973e5c31af7Sopenharmony_ci				   "\tif(it == sTypeBlobMap.end())\n" \
2974e5c31af7Sopenharmony_ci				   "\t\treturn 0;\n" \
2975e5c31af7Sopenharmony_ci				   "\treturn it->second;\n" \
2976e5c31af7Sopenharmony_ci				   "}\n"
2977e5c31af7Sopenharmony_ci	# combine all definition lists
2978e5c31af7Sopenharmony_ci	stream = [
2979e5c31af7Sopenharmony_ci	'#include "vkDeviceProperties.hpp"\n',
2980e5c31af7Sopenharmony_ci	'namespace vk\n{']
2981e5c31af7Sopenharmony_ci	stream.extend(extensionDefines)
2982e5c31af7Sopenharmony_ci	stream.append('\n')
2983e5c31af7Sopenharmony_ci	stream.extend(initFromBlobDefinitions)
2984e5c31af7Sopenharmony_ci	stream.append('\n// generic template is not enough for some compilers')
2985e5c31af7Sopenharmony_ci	stream.extend(emptyInitDefinitions)
2986e5c31af7Sopenharmony_ci	stream.append('\n')
2987e5c31af7Sopenharmony_ci	stream.extend(makePropertyDescDefinitions)
2988e5c31af7Sopenharmony_ci	stream.append('\n')
2989e5c31af7Sopenharmony_ci	stream.append('static const PropertyStructCreationData propertyStructCreationArray[] =\n{')
2990e5c31af7Sopenharmony_ci	stream.extend(propertyStructWrappers)
2991e5c31af7Sopenharmony_ci	stream.append('};\n')
2992e5c31af7Sopenharmony_ci	stream.append(blobChecker)
2993e5c31af7Sopenharmony_ci	stream.append('} // vk\n')
2994e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, stream)
2995e5c31af7Sopenharmony_ci
2996e5c31af7Sopenharmony_ciUNSUFFIXED_STRUCTURES = [
2997e5c31af7Sopenharmony_ci	"CornerSampledImage",
2998e5c31af7Sopenharmony_ci	"ShaderSMBuiltins",
2999e5c31af7Sopenharmony_ci	"ShadingRateImage",
3000e5c31af7Sopenharmony_ci	"RayTracing",
3001e5c31af7Sopenharmony_ci	"RepresentativeFragmentTest",
3002e5c31af7Sopenharmony_ci	"ComputeShaderDerivatives",
3003e5c31af7Sopenharmony_ci	"MeshShader",
3004e5c31af7Sopenharmony_ci	"ShaderImageFootprint",
3005e5c31af7Sopenharmony_ci	"ExclusiveScissor",
3006e5c31af7Sopenharmony_ci	"DedicatedAllocationImageAliasing",
3007e5c31af7Sopenharmony_ci	"CoverageReductionMode",
3008e5c31af7Sopenharmony_ci	"DeviceGeneratedCommands",
3009e5c31af7Sopenharmony_ci	"InheritedViewportScissor",
3010e5c31af7Sopenharmony_ci	"PresentBarrier",
3011e5c31af7Sopenharmony_ci	"DiagnosticsConfig",
3012e5c31af7Sopenharmony_ci	"FragmentShadingRateEnums",
3013e5c31af7Sopenharmony_ci	"RayTracingMotionBlur",
3014e5c31af7Sopenharmony_ci	"ExternalMemoryRDMA",
3015e5c31af7Sopenharmony_ci	"CopyMemoryIndirect",
3016e5c31af7Sopenharmony_ci	"MemoryDecompression",
3017e5c31af7Sopenharmony_ci	"LinearColorAttachment",
3018e5c31af7Sopenharmony_ci	"OpticalFlow",
3019e5c31af7Sopenharmony_ci	"RayTracingInvocationReorder",
3020e5c31af7Sopenharmony_ci	"DisplacementMicromap"]
3021e5c31af7Sopenharmony_ci
3022e5c31af7Sopenharmony_cidef deviceFeaturesOrPropertiesGetter(name):
3023e5c31af7Sopenharmony_ci	result = name[16:] # Remove VkPhysicalDevice prefix
3024e5c31af7Sopenharmony_ci	if result[-3:] == "KHR":
3025e5c31af7Sopenharmony_ci		result = result[0:-3]
3026e5c31af7Sopenharmony_ci	elif result[-2:] == "NV":
3027e5c31af7Sopenharmony_ci		suffix = result[-2:]
3028e5c31af7Sopenharmony_ci		result = result[0:-2]
3029e5c31af7Sopenharmony_ci		if result[-8:] == "Features":
3030e5c31af7Sopenharmony_ci			infix = result[-8:]
3031e5c31af7Sopenharmony_ci			result = result[0:-8]
3032e5c31af7Sopenharmony_ci		elif result[-10:] == "Properties":
3033e5c31af7Sopenharmony_ci			infix = result[-10:]
3034e5c31af7Sopenharmony_ci			result = result[0:-10]
3035e5c31af7Sopenharmony_ci		if (result in UNSUFFIXED_STRUCTURES):
3036e5c31af7Sopenharmony_ci			suffix = ""
3037e5c31af7Sopenharmony_ci		result = result + infix + suffix
3038e5c31af7Sopenharmony_ci	return result
3039e5c31af7Sopenharmony_ci
3040e5c31af7Sopenharmony_cidef genericDeviceFeaturesWriter(dfDefs, pattern, filename):
3041e5c31af7Sopenharmony_ci	stream = []
3042e5c31af7Sopenharmony_ci	for _, _, _, extStruct, _, _, _ in dfDefs:
3043e5c31af7Sopenharmony_ci		nameSubStr = deviceFeaturesOrPropertiesGetter(extStruct)
3044e5c31af7Sopenharmony_ci		stream.append(pattern.format(extStruct, nameSubStr))
3045e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, indentLines(stream))
3046e5c31af7Sopenharmony_ci
3047e5c31af7Sopenharmony_cidef writeDeviceFeaturesDefaultDeviceDefs(dfDefs, filename):
3048e5c31af7Sopenharmony_ci	pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceFeatures.getFeatureType<{0}>();\t}}"
3049e5c31af7Sopenharmony_ci	genericDeviceFeaturesWriter(dfDefs, pattern, filename)
3050e5c31af7Sopenharmony_ci
3051e5c31af7Sopenharmony_cidef writeDeviceFeaturesContextDecl(dfDefs, filename):
3052e5c31af7Sopenharmony_ci	pattern = "const vk::{0}&\tget{1}\t(void) const;"
3053e5c31af7Sopenharmony_ci	genericDeviceFeaturesWriter(dfDefs, pattern, filename)
3054e5c31af7Sopenharmony_ci
3055e5c31af7Sopenharmony_cidef writeDeviceFeaturesContextDefs(dfDefs, filename):
3056e5c31af7Sopenharmony_ci	pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
3057e5c31af7Sopenharmony_ci	genericDeviceFeaturesWriter(dfDefs, pattern, filename)
3058e5c31af7Sopenharmony_ci
3059e5c31af7Sopenharmony_cidef genericDevicePropertiesWriter(dfDefs, pattern, filename):
3060e5c31af7Sopenharmony_ci	stream = []
3061e5c31af7Sopenharmony_ci	for _, _, _, extStruct, _, _, _ in dfDefs:
3062e5c31af7Sopenharmony_ci		nameSubStr = deviceFeaturesOrPropertiesGetter(extStruct)
3063e5c31af7Sopenharmony_ci		stream.append(pattern.format(extStruct, nameSubStr))
3064e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, indentLines(stream))
3065e5c31af7Sopenharmony_ci
3066e5c31af7Sopenharmony_cidef writeDevicePropertiesDefaultDeviceDefs(dfDefs, filename):
3067e5c31af7Sopenharmony_ci	pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceProperties.getPropertyType<{0}>();\t}}"
3068e5c31af7Sopenharmony_ci	genericDevicePropertiesWriter(dfDefs, pattern, filename)
3069e5c31af7Sopenharmony_ci
3070e5c31af7Sopenharmony_cidef writeDevicePropertiesContextDecl(dfDefs, filename):
3071e5c31af7Sopenharmony_ci	pattern = "const vk::{0}&\tget{1}\t(void) const;"
3072e5c31af7Sopenharmony_ci	genericDevicePropertiesWriter(dfDefs, pattern, filename)
3073e5c31af7Sopenharmony_ci
3074e5c31af7Sopenharmony_cidef writeDevicePropertiesContextDefs(dfDefs, filename):
3075e5c31af7Sopenharmony_ci	pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
3076e5c31af7Sopenharmony_ci	genericDevicePropertiesWriter(dfDefs, pattern, filename)
3077e5c31af7Sopenharmony_ci
3078e5c31af7Sopenharmony_cidef writeMandatoryFeatures(api, filename):
3079e5c31af7Sopenharmony_ci
3080e5c31af7Sopenharmony_ci	def structInAPI(name):
3081e5c31af7Sopenharmony_ci		for c in api.compositeTypes:
3082e5c31af7Sopenharmony_ci			if c.name == name:
3083e5c31af7Sopenharmony_ci				return True
3084e5c31af7Sopenharmony_ci			for alias in c.aliasList:
3085e5c31af7Sopenharmony_ci				if alias == name:
3086e5c31af7Sopenharmony_ci					return True
3087e5c31af7Sopenharmony_ci		return False
3088e5c31af7Sopenharmony_ci	stream = []
3089e5c31af7Sopenharmony_ci
3090e5c31af7Sopenharmony_ci	dictStructs = {}
3091e5c31af7Sopenharmony_ci	dictData = []
3092e5c31af7Sopenharmony_ci	extData = []
3093e5c31af7Sopenharmony_ci	usedFeatureStructs = {}
3094e5c31af7Sopenharmony_ci	for _, data in api.additionalExtensionData:
3095e5c31af7Sopenharmony_ci		if 'mandatory_features' in data.keys():
3096e5c31af7Sopenharmony_ci			# sort to have same results for py2 and py3
3097e5c31af7Sopenharmony_ci			listStructFeatures = sorted(data['mandatory_features'].items(), key=lambda tup: tup[0])
3098e5c31af7Sopenharmony_ci			for structure, featuresList in listStructFeatures:
3099e5c31af7Sopenharmony_ci				for featureData in featuresList:
3100e5c31af7Sopenharmony_ci					# allow for featureless VKSC only extensions
3101e5c31af7Sopenharmony_ci					if not 'features' in featureData.keys() or 'requirements' not in featureData.keys():
3102e5c31af7Sopenharmony_ci						continue
3103e5c31af7Sopenharmony_ci					requirements = featureData['requirements']
3104e5c31af7Sopenharmony_ci
3105e5c31af7Sopenharmony_ci					mandatory_variant = ''
3106e5c31af7Sopenharmony_ci					try:
3107e5c31af7Sopenharmony_ci						mandatory_variant = featureData['mandatory_variant']
3108e5c31af7Sopenharmony_ci					except KeyError:
3109e5c31af7Sopenharmony_ci						mandatory_variant = ''
3110e5c31af7Sopenharmony_ci
3111e5c31af7Sopenharmony_ci					dictData.append( [ structure, featureData['features'], requirements, mandatory_variant] )
3112e5c31af7Sopenharmony_ci
3113e5c31af7Sopenharmony_ci					if structure == 'VkPhysicalDeviceFeatures':
3114e5c31af7Sopenharmony_ci						continue
3115e5c31af7Sopenharmony_ci
3116e5c31af7Sopenharmony_ci					# if structure is not in dict construct name of variable and add is as a first item
3117e5c31af7Sopenharmony_ci					if (structure not in dictStructs):
3118e5c31af7Sopenharmony_ci						dictStructs[structure] = ([structure[2:3].lower() + structure[3:]], mandatory_variant)
3119e5c31af7Sopenharmony_ci					# add first requirement if it is unique
3120e5c31af7Sopenharmony_ci					if requirements and (requirements[0] not in dictStructs[structure][0]):
3121e5c31af7Sopenharmony_ci						dictStructs[structure][0].append(requirements[0])
3122e5c31af7Sopenharmony_ci
3123e5c31af7Sopenharmony_ci					usedFeatureStructs[structure] = []
3124e5c31af7Sopenharmony_ci
3125e5c31af7Sopenharmony_ci					if requirements:
3126e5c31af7Sopenharmony_ci						for req in requirements:
3127e5c31af7Sopenharmony_ci							if '.' in req:
3128e5c31af7Sopenharmony_ci								req = req.split('.')[0]
3129e5c31af7Sopenharmony_ci								reqStruct = 'Vk' + req[0].upper() + req[1:]
3130e5c31af7Sopenharmony_ci								usedFeatureStructs[reqStruct] = []
3131e5c31af7Sopenharmony_ci
3132e5c31af7Sopenharmony_ci		if 'mandatory_extensions' in data:
3133e5c31af7Sopenharmony_ci			mandatoryExtensions = []
3134e5c31af7Sopenharmony_ci			for mandatoryExt in data['mandatory_extensions']:
3135e5c31af7Sopenharmony_ci				if 'extension' in mandatoryExt:
3136e5c31af7Sopenharmony_ci					extName = mandatoryExt.pop('extension')
3137e5c31af7Sopenharmony_ci					mandatoryExtensions.append((extName, mandatoryExt))
3138e5c31af7Sopenharmony_ci
3139e5c31af7Sopenharmony_ci			for extension, extensionData in mandatoryExtensions:
3140e5c31af7Sopenharmony_ci				# requirements are actually mandatory.
3141e5c31af7Sopenharmony_ci				if 'requirements' not in extensionData:
3142e5c31af7Sopenharmony_ci					continue
3143e5c31af7Sopenharmony_ci
3144e5c31af7Sopenharmony_ci				requirements = extensionData['requirements']
3145e5c31af7Sopenharmony_ci				mandatory_variant = '' if 'mandatory_variant' not in extensionData else extensionData['mandatory_variant']
3146e5c31af7Sopenharmony_ci				extData.append((extension, requirements, mandatory_variant))
3147e5c31af7Sopenharmony_ci
3148e5c31af7Sopenharmony_ci				for req in requirements:
3149e5c31af7Sopenharmony_ci					if '.' in req:
3150e5c31af7Sopenharmony_ci						req = req.split('.')[0]
3151e5c31af7Sopenharmony_ci						reqStruct = 'Vk' + req[0].upper() + req[1:]
3152e5c31af7Sopenharmony_ci						usedFeatureStructs[reqStruct] = []
3153e5c31af7Sopenharmony_ci
3154e5c31af7Sopenharmony_ci	stream.extend(['bool canUseFeaturesStruct (const vector<VkExtensionProperties>& deviceExtensions, uint32_t usedApiVersion, const char* extension)',
3155e5c31af7Sopenharmony_ci				   '{',
3156e5c31af7Sopenharmony_ci				   '\treturn (isExtensionStructSupported(deviceExtensions, RequiredExtension(extension))',
3157e5c31af7Sopenharmony_ci				   '\t\t\t|| isCoreDeviceExtension(usedApiVersion, extension));',
3158e5c31af7Sopenharmony_ci				   '}',
3159e5c31af7Sopenharmony_ci				   '',
3160e5c31af7Sopenharmony_ci				   'bool checkMandatoryFeatures(const vkt::Context& context)\n{',
3161e5c31af7Sopenharmony_ci				   '\tif (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))',
3162e5c31af7Sopenharmony_ci				   '\t\tTCU_THROW(NotSupportedError, "Extension VK_KHR_get_physical_device_properties2 is not present");',
3163e5c31af7Sopenharmony_ci				   '',
3164e5c31af7Sopenharmony_ci				   '\tVkPhysicalDevice\t\t\t\t\tphysicalDevice\t\t= context.getPhysicalDevice();',
3165e5c31af7Sopenharmony_ci				   '\tconst InstanceInterface&\t\t\tvki\t\t\t\t\t= context.getInstanceInterface();',
3166e5c31af7Sopenharmony_ci				   '\tconst vector<VkExtensionProperties>\tdeviceExtensions\t= enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);',
3167e5c31af7Sopenharmony_ci				   '\tconst uint32_t\t\t\t\t\t\tusedApiVersion\t\t= context.getUsedApiVersion();',
3168e5c31af7Sopenharmony_ci				   '',
3169e5c31af7Sopenharmony_ci				   '\ttcu::TestLog& log = context.getTestContext().getLog();',
3170e5c31af7Sopenharmony_ci				   '\tvk::VkPhysicalDeviceFeatures2 coreFeatures;',
3171e5c31af7Sopenharmony_ci				   '\tdeMemset(&coreFeatures, 0, sizeof(coreFeatures));',
3172e5c31af7Sopenharmony_ci				   '\tcoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;',
3173e5c31af7Sopenharmony_ci				   '\tvoid** nextPtr = &coreFeatures.pNext;',
3174e5c31af7Sopenharmony_ci				   ''])
3175e5c31af7Sopenharmony_ci
3176e5c31af7Sopenharmony_ci	# Find the extensions that added the required feature structs.
3177e5c31af7Sopenharmony_ci	class StructFoundContinue(Exception):
3178e5c31af7Sopenharmony_ci		pass
3179e5c31af7Sopenharmony_ci
3180e5c31af7Sopenharmony_ci	for usedStruct in usedFeatureStructs:
3181e5c31af7Sopenharmony_ci		for compType in api.compositeTypes:
3182e5c31af7Sopenharmony_ci			nameList = [compType.name] + compType.aliasList
3183e5c31af7Sopenharmony_ci			if usedStruct in nameList:
3184e5c31af7Sopenharmony_ci				# Found the official name list for the struct.
3185e5c31af7Sopenharmony_ci				for extension in api.extensions:
3186e5c31af7Sopenharmony_ci					try:
3187e5c31af7Sopenharmony_ci						for requirement in extension.requirementsList:
3188e5c31af7Sopenharmony_ci							for extensionStructure in requirement.newTypes:
3189e5c31af7Sopenharmony_ci								if extensionStructure.name in nameList:
3190e5c31af7Sopenharmony_ci									# Found extension for the struct.
3191e5c31af7Sopenharmony_ci									usedFeatureStructs[usedStruct].append(extension.name)
3192e5c31af7Sopenharmony_ci									raise StructFoundContinue
3193e5c31af7Sopenharmony_ci					except StructFoundContinue:
3194e5c31af7Sopenharmony_ci						pass
3195e5c31af7Sopenharmony_ci
3196e5c31af7Sopenharmony_ci	structList = sorted(usedFeatureStructs.items(), key=lambda tup: tup[0]) # sort to have same results for py2 and py3
3197e5c31af7Sopenharmony_ci	apiStructs = list( filter(lambda x : structInAPI(x[0]), structList)) # remove items not defined in current API
3198e5c31af7Sopenharmony_ci
3199e5c31af7Sopenharmony_ci	for structName, extensions in apiStructs:
3200e5c31af7Sopenharmony_ci		metaCondition = ''
3201e5c31af7Sopenharmony_ci		if structName in dictStructs:
3202e5c31af7Sopenharmony_ci			mandatoryVariantList = dictStructs[structName][1]
3203e5c31af7Sopenharmony_ci			if len(mandatoryVariantList) > 0:
3204e5c31af7Sopenharmony_ci				mandatoryVariant = mandatoryVariantList[0]
3205e5c31af7Sopenharmony_ci				metaCondition = 'defined(CTS_USES_' + mandatoryVariant.upper() + ')'
3206e5c31af7Sopenharmony_ci				stream.append('#if ' + metaCondition)
3207e5c31af7Sopenharmony_ci
3208e5c31af7Sopenharmony_ci		# The variable name will be the structure name without the Vk prefix and starting in lowercase.
3209e5c31af7Sopenharmony_ci		newVar = structName[2].lower() + structName[3:]
3210e5c31af7Sopenharmony_ci
3211e5c31af7Sopenharmony_ci		stream.extend(['\tvk::' + structName + ' ' + newVar + ';',
3212e5c31af7Sopenharmony_ci					'\tdeMemset(&' + newVar + ', 0, sizeof(' + newVar + '));',
3213e5c31af7Sopenharmony_ci					''])
3214e5c31af7Sopenharmony_ci
3215e5c31af7Sopenharmony_ci		if len(extensions) > 0:
3216e5c31af7Sopenharmony_ci			canUseCond = '\tif ('
3217e5c31af7Sopenharmony_ci			for (i, extName) in enumerate(extensions):
3218e5c31af7Sopenharmony_ci				canUseCond += ' ' if i == 0 else ' || '
3219e5c31af7Sopenharmony_ci				canUseCond += 'canUseFeaturesStruct(deviceExtensions, usedApiVersion, "' + extName + '")'
3220e5c31af7Sopenharmony_ci			canUseCond += ' )'
3221e5c31af7Sopenharmony_ci			stream.append(canUseCond)
3222e5c31af7Sopenharmony_ci		elif api.apiName == "vulkan" and structName in dictStructs:
3223e5c31af7Sopenharmony_ci			#reqs = v[0][1:]
3224e5c31af7Sopenharmony_ci			reqs = dictStructs[structName][0][1:]
3225e5c31af7Sopenharmony_ci			cond = 'if ( '
3226e5c31af7Sopenharmony_ci			for i, req in enumerate(reqs):
3227e5c31af7Sopenharmony_ci				if i > 0:
3228e5c31af7Sopenharmony_ci					cond = cond + ' || '
3229e5c31af7Sopenharmony_ci				if (req.startswith("ApiVersion")):
3230e5c31af7Sopenharmony_ci					cond = cond + 'context.contextSupports(vk::' + req + ')'
3231e5c31af7Sopenharmony_ci			cond = cond + ' )'
3232e5c31af7Sopenharmony_ci			stream.append('\t' + cond)
3233e5c31af7Sopenharmony_ci
3234e5c31af7Sopenharmony_ci		stream.extend(['\t{',
3235e5c31af7Sopenharmony_ci					   '\t\t' + newVar + '.sType = getStructureType<' + structName + '>();',
3236e5c31af7Sopenharmony_ci					   '\t\t*nextPtr = &' + newVar + ';',
3237e5c31af7Sopenharmony_ci					   '\t\tnextPtr  = &' + newVar + '.pNext;',
3238e5c31af7Sopenharmony_ci					   '\t}'])
3239e5c31af7Sopenharmony_ci
3240e5c31af7Sopenharmony_ci		if len(metaCondition) > 0:
3241e5c31af7Sopenharmony_ci			stream.append('#endif // ' + metaCondition)
3242e5c31af7Sopenharmony_ci
3243e5c31af7Sopenharmony_ci		stream.append('')
3244e5c31af7Sopenharmony_ci
3245e5c31af7Sopenharmony_ci	stream.extend(['\tcontext.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &coreFeatures);',
3246e5c31af7Sopenharmony_ci				   '\tbool result = true;',
3247e5c31af7Sopenharmony_ci				   ''])
3248e5c31af7Sopenharmony_ci
3249e5c31af7Sopenharmony_ci	for v in dictData:
3250e5c31af7Sopenharmony_ci		if not structInAPI(v[0]): # remove items not defined in current API ( important for Vulkan SC )
3251e5c31af7Sopenharmony_ci			continue
3252e5c31af7Sopenharmony_ci		structType = v[0];
3253e5c31af7Sopenharmony_ci		structName = 'coreFeatures.features';
3254e5c31af7Sopenharmony_ci		metaCondition = ''
3255e5c31af7Sopenharmony_ci		if len(v) == 4 and v[3] != '':
3256e5c31af7Sopenharmony_ci			# for x in v[3].split('_'):
3257e5c31af7Sopenharmony_ci			metaCondition = metaCondition + ' || defined(CTS_USES_' + v[3][0].upper() + ')'
3258e5c31af7Sopenharmony_ci			stream.extend(['#if ' + metaCondition[4:]])
3259e5c31af7Sopenharmony_ci		if v[0] != 'VkPhysicalDeviceFeatures' :
3260e5c31af7Sopenharmony_ci			structName = dictStructs[v[0]][0][0]
3261e5c31af7Sopenharmony_ci		if len(v[2]) > 0 :
3262e5c31af7Sopenharmony_ci			condition = 'if ( '
3263e5c31af7Sopenharmony_ci			for i, req in enumerate(v[2]) :
3264e5c31af7Sopenharmony_ci				if (req.startswith("ApiVersion")):
3265e5c31af7Sopenharmony_ci					condition = condition + 'context.contextSupports(vk::' + req + ')'
3266e5c31af7Sopenharmony_ci				elif '.' in req:
3267e5c31af7Sopenharmony_ci					condition = condition + req
3268e5c31af7Sopenharmony_ci				else:
3269e5c31af7Sopenharmony_ci					condition = condition + 'isExtensionStructSupported(deviceExtensions, RequiredExtension("' + req + '"))'
3270e5c31af7Sopenharmony_ci				if i+1 < len(v[2]) :
3271e5c31af7Sopenharmony_ci					condition = condition + ' && '
3272e5c31af7Sopenharmony_ci			condition = condition + ' )'
3273e5c31af7Sopenharmony_ci			stream.append('\t' + condition)
3274e5c31af7Sopenharmony_ci		stream.append('\t{')
3275e5c31af7Sopenharmony_ci		# Don't need to support an AND case since that would just be another line in the .txt
3276e5c31af7Sopenharmony_ci		if len(v[1]) == 1:
3277e5c31af7Sopenharmony_ci			stream.append('\t\tif ( ' + structName + '.' + v[1][0] + ' == VK_FALSE )')
3278e5c31af7Sopenharmony_ci		else:
3279e5c31af7Sopenharmony_ci			condition = 'if ( '
3280e5c31af7Sopenharmony_ci			for i, feature in enumerate(v[1]):
3281e5c31af7Sopenharmony_ci				if i != 0:
3282e5c31af7Sopenharmony_ci					condition = condition + ' && '
3283e5c31af7Sopenharmony_ci				condition = condition + '( ' + structName + '.' + feature + ' == VK_FALSE )'
3284e5c31af7Sopenharmony_ci			condition = condition + ' )'
3285e5c31af7Sopenharmony_ci			stream.append('\t\t' + condition)
3286e5c31af7Sopenharmony_ci		featureSet = " or ".join(v[1])
3287e5c31af7Sopenharmony_ci		stream.extend(['\t\t{',
3288e5c31af7Sopenharmony_ci					   '\t\t\tlog << tcu::TestLog::Message << "Mandatory feature ' + featureSet + ' not supported" << tcu::TestLog::EndMessage;',
3289e5c31af7Sopenharmony_ci					   '\t\t\tresult = false;',
3290e5c31af7Sopenharmony_ci					   '\t\t}',
3291e5c31af7Sopenharmony_ci					   '\t}'])
3292e5c31af7Sopenharmony_ci		if metaCondition != '':
3293e5c31af7Sopenharmony_ci			stream.extend(['#endif // ' + metaCondition[4:],
3294e5c31af7Sopenharmony_ci						  ''])
3295e5c31af7Sopenharmony_ci		else:
3296e5c31af7Sopenharmony_ci			stream.extend([''])
3297e5c31af7Sopenharmony_ci
3298e5c31af7Sopenharmony_ci	for extension, requirements, mandatory_variant in extData:
3299e5c31af7Sopenharmony_ci		metaCondition = ''
3300e5c31af7Sopenharmony_ci		if mandatory_variant != '':
3301e5c31af7Sopenharmony_ci			metaCondition = metaCondition + ' || defined(CTS_USES_' + mandatory_variant[0].upper() + ')'
3302e5c31af7Sopenharmony_ci			stream.extend(['#if ' + metaCondition[4:]])
3303e5c31af7Sopenharmony_ci		if len(requirements) > 0 :
3304e5c31af7Sopenharmony_ci			condition = 'if ( '
3305e5c31af7Sopenharmony_ci			for i, req in enumerate(requirements) :
3306e5c31af7Sopenharmony_ci				if (req.startswith("ApiVersion")):
3307e5c31af7Sopenharmony_ci					condition = condition + 'context.contextSupports(vk::' + req + ')'
3308e5c31af7Sopenharmony_ci				elif '.' in req:
3309e5c31af7Sopenharmony_ci					condition = condition + req
3310e5c31af7Sopenharmony_ci				else:
3311e5c31af7Sopenharmony_ci					condition = condition + 'isExtensionStructSupported(deviceExtensions, RequiredExtension("' + req + '"))'
3312e5c31af7Sopenharmony_ci				if i+1 < len(requirements) :
3313e5c31af7Sopenharmony_ci					condition = condition + ' && '
3314e5c31af7Sopenharmony_ci			condition = condition + ' )'
3315e5c31af7Sopenharmony_ci			stream.append('\t' + condition)
3316e5c31af7Sopenharmony_ci		stream.append('\t{')
3317e5c31af7Sopenharmony_ci		stream.extend(['\t\tif (!(isExtensionStructSupported(deviceExtensions, RequiredExtension("' + extension + '")) || isCoreDeviceExtension(usedApiVersion, "' + extension + '")))',
3318e5c31af7Sopenharmony_ci					   '\t\t{',
3319e5c31af7Sopenharmony_ci					   '\t\t\tlog << tcu::TestLog::Message << "Mandatory extension ' + extension + ' not supported" << tcu::TestLog::EndMessage;',
3320e5c31af7Sopenharmony_ci					   '\t\t\tresult = false;',
3321e5c31af7Sopenharmony_ci					   '\t\t}',
3322e5c31af7Sopenharmony_ci					   '\t}'])
3323e5c31af7Sopenharmony_ci		if metaCondition != '':
3324e5c31af7Sopenharmony_ci			stream.extend(['#endif // ' + metaCondition[4:],
3325e5c31af7Sopenharmony_ci						  ''])
3326e5c31af7Sopenharmony_ci		else:
3327e5c31af7Sopenharmony_ci			stream.append('')
3328e5c31af7Sopenharmony_ci
3329e5c31af7Sopenharmony_ci	stream.append('\treturn result;')
3330e5c31af7Sopenharmony_ci	stream.append('}\n')
3331e5c31af7Sopenharmony_ci
3332e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, stream)
3333e5c31af7Sopenharmony_ci
3334e5c31af7Sopenharmony_cidef writeExtensionList(api, filename, extensionType):
3335e5c31af7Sopenharmony_ci	extensionList = []
3336e5c31af7Sopenharmony_ci	for extensionName, data in api.additionalExtensionData:
3337e5c31af7Sopenharmony_ci		# make sure extension name starts with VK_KHR
3338e5c31af7Sopenharmony_ci		if not extensionName.startswith('VK_KHR'):
3339e5c31af7Sopenharmony_ci			continue
3340e5c31af7Sopenharmony_ci		# make sure that this extension was registered
3341e5c31af7Sopenharmony_ci		if 'register_extension' not in data.keys():
3342e5c31af7Sopenharmony_ci			continue
3343e5c31af7Sopenharmony_ci		# make sure extension is intended for the vulkan variant
3344e5c31af7Sopenharmony_ci		is_sc_only = False
3345e5c31af7Sopenharmony_ci
3346e5c31af7Sopenharmony_ci		if api.apiName != 'vulkansc':
3347e5c31af7Sopenharmony_ci			if 'mandatory_features' in data.keys():
3348e5c31af7Sopenharmony_ci				for structure, listStruct in data['mandatory_features'].items():
3349e5c31af7Sopenharmony_ci					for featureData in listStruct:
3350e5c31af7Sopenharmony_ci						mandatory_variant = ''
3351e5c31af7Sopenharmony_ci						try:
3352e5c31af7Sopenharmony_ci							mandatory_variant = featureData['mandatory_variant']
3353e5c31af7Sopenharmony_ci						except KeyError:
3354e5c31af7Sopenharmony_ci							mandatory_variant = ''
3355e5c31af7Sopenharmony_ci						# VKSC only
3356e5c31af7Sopenharmony_ci						if 'vulkansc' in mandatory_variant:
3357e5c31af7Sopenharmony_ci							is_sc_only = True
3358e5c31af7Sopenharmony_ci		if is_sc_only:
3359e5c31af7Sopenharmony_ci			continue
3360e5c31af7Sopenharmony_ci
3361e5c31af7Sopenharmony_ci		# make sure extension has proper type
3362e5c31af7Sopenharmony_ci		if extensionType == data['register_extension']['type']:
3363e5c31af7Sopenharmony_ci			extensionList.append(extensionName)
3364e5c31af7Sopenharmony_ci	extensionList.sort()
3365e5c31af7Sopenharmony_ci	# write list of all found extensions
3366e5c31af7Sopenharmony_ci	stream = []
3367e5c31af7Sopenharmony_ci	stream.append('static const char* s_allowed{0}KhrExtensions[] =\n{{'.format(extensionType.title()))
3368e5c31af7Sopenharmony_ci	for n in extensionList:
3369e5c31af7Sopenharmony_ci		stream.append('\t"' + n + '",')
3370e5c31af7Sopenharmony_ci	stream.append('};\n')
3371e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, stream)
3372e5c31af7Sopenharmony_ci
3373e5c31af7Sopenharmony_cidef writeApiExtensionDependencyInfo(api, filename):
3374e5c31af7Sopenharmony_ci
3375e5c31af7Sopenharmony_ci	def genHelperFunctions():
3376e5c31af7Sopenharmony_ci		yield 'using namespace tcu;'
3377e5c31af7Sopenharmony_ci		yield 'using ExtPropVect = std::vector<vk::VkExtensionProperties>;'
3378e5c31af7Sopenharmony_ci		yield 'using IsSupportedFun = bool (*)(const tcu::UVec2&, const ExtPropVect&, const ExtPropVect&);'
3379e5c31af7Sopenharmony_ci		yield 'using DependencyCheckVect = std::vector<std::pair<const char*, IsSupportedFun> >;\n'
3380e5c31af7Sopenharmony_ci		yield 'bool isCompatibile(deUint32 major, deUint32 minor, const tcu::UVec2& testedApiVersion)'
3381e5c31af7Sopenharmony_ci		yield '{'
3382e5c31af7Sopenharmony_ci		yield '\t// return true when tested api version is greater'
3383e5c31af7Sopenharmony_ci		yield '\t// or equal to version represented by two uints'
3384e5c31af7Sopenharmony_ci		yield '\tif (major == testedApiVersion.x())'
3385e5c31af7Sopenharmony_ci		yield '\t\treturn minor <= testedApiVersion.y();'
3386e5c31af7Sopenharmony_ci		yield '\treturn major < testedApiVersion.x();'
3387e5c31af7Sopenharmony_ci		yield '}\n'
3388e5c31af7Sopenharmony_ci		yield 'bool isSupported(const ExtPropVect& extensions, const char* ext)'
3389e5c31af7Sopenharmony_ci		yield '{'
3390e5c31af7Sopenharmony_ci		yield '\treturn isExtensionStructSupported(extensions, vk::RequiredExtension(ext));'
3391e5c31af7Sopenharmony_ci		yield '}\n'
3392e5c31af7Sopenharmony_ci
3393e5c31af7Sopenharmony_ci	def genExtDepArray(extType):
3394e5c31af7Sopenharmony_ci		extensionList = []
3395e5c31af7Sopenharmony_ci		maxExtLength = 0
3396e5c31af7Sopenharmony_ci		extVector = 'vIEP'
3397e5c31af7Sopenharmony_ci		othVector = 'vDEP'
3398e5c31af7Sopenharmony_ci		if extType == 'device':
3399e5c31af7Sopenharmony_ci			extVector, othVector = othVector, extVector		# swap
3400e5c31af7Sopenharmony_ci		# iterate over all extension that are of specified type and that have requirements
3401e5c31af7Sopenharmony_ci		for ext in api.extensions:
3402e5c31af7Sopenharmony_ci			if ext.type != extType:
3403e5c31af7Sopenharmony_ci				continue
3404e5c31af7Sopenharmony_ci			if ext.depends is None:
3405e5c31af7Sopenharmony_ci				continue
3406e5c31af7Sopenharmony_ci			# memorize extension name and dependencies for future vector generation
3407e5c31af7Sopenharmony_ci			extensionList.append(ext.name)
3408e5c31af7Sopenharmony_ci			# memorize max extension name and dependency length
3409e5c31af7Sopenharmony_ci			maxExtLength = max(maxExtLength, len(ext.name))
3410e5c31af7Sopenharmony_ci			# generate check function for this extension
3411e5c31af7Sopenharmony_ci			yield f'bool check_{ext.name}(const tcu::UVec2& v, const ExtPropVect& vIEP, const ExtPropVect& vDEP)'
3412e5c31af7Sopenharmony_ci			yield '{'
3413e5c31af7Sopenharmony_ci			# check if extension was promoted; for SC we need to check vulkan version as sc10 is based on vk12
3414e5c31af7Sopenharmony_ci			if ext.promotedto is not None and 'VK_VERSION' in ext.promotedto:
3415e5c31af7Sopenharmony_ci				p = ext.promotedto
3416e5c31af7Sopenharmony_ci				yield f'\tif (isCompatibile({p[-3]}, {p[-1]}, v))'
3417e5c31af7Sopenharmony_ci				yield '\t\treturn true;\n'
3418e5c31af7Sopenharmony_ci			else:
3419e5c31af7Sopenharmony_ci				yield '\tDE_UNREF(v);'
3420e5c31af7Sopenharmony_ci			# there is a high chance that other vector won't be used
3421e5c31af7Sopenharmony_ci			yield f'\tDE_UNREF({othVector});'
3422e5c31af7Sopenharmony_ci			# check if extension is supported
3423e5c31af7Sopenharmony_ci			yield f'\n\tif (!isSupported({extVector}, "{ext.name}"))'
3424e5c31af7Sopenharmony_ci			yield '\t\treturn true;\n'
3425e5c31af7Sopenharmony_ci			# replace dependent extensions/versions with proper conditions
3426e5c31af7Sopenharmony_ci			depList = re.split(r'(\W+)', ext.depends)
3427e5c31af7Sopenharmony_ci			for idx, depPart in enumerate(depList):
3428e5c31af7Sopenharmony_ci				if ',' in depPart:
3429e5c31af7Sopenharmony_ci					depList[idx] = depList[idx].replace(',', ' || ')
3430e5c31af7Sopenharmony_ci				elif '+' in depPart:
3431e5c31af7Sopenharmony_ci					depList[idx] = depList[idx].replace('+', ' && ')
3432e5c31af7Sopenharmony_ci				elif 'VK_' in depPart:
3433e5c31af7Sopenharmony_ci					if 'VK_VERSION' in depPart:
3434e5c31af7Sopenharmony_ci						if idx > 0 and ' || ' in depList[idx-1]:
3435e5c31af7Sopenharmony_ci							# some vk.xml entries include "promoted to" version preceded by logical OR operator in the extension "depends" attribute
3436e5c31af7Sopenharmony_ci							# script don't rely on this optional information and will find "promoted to" versions for all dependencies of all extensions in the below code
3437e5c31af7Sopenharmony_ci							# accordingly the one from vk.xml is ignored to avoid redundant isCompatibile() checks
3438e5c31af7Sopenharmony_ci							depList[idx-1] = depList[idx-1].replace(' || ', '')
3439e5c31af7Sopenharmony_ci							depList[idx] = ''
3440e5c31af7Sopenharmony_ci							continue
3441e5c31af7Sopenharmony_ci						# when dependency is vulkan version then replace it with proper condition
3442e5c31af7Sopenharmony_ci						depList[idx] = f'isCompatibile({depPart[-3]}, {depPart[-1]}, v)'
3443e5c31af7Sopenharmony_ci					else:
3444e5c31af7Sopenharmony_ci						# when dependency is extension check if it was promoted
3445e5c31af7Sopenharmony_ci						extNotFound = True
3446e5c31af7Sopenharmony_ci						for dExt in api.extensions:
3447e5c31af7Sopenharmony_ci							if depPart == dExt.name:
3448e5c31af7Sopenharmony_ci								depExtVector = 'vDEP' if dExt.type == 'device' else 'vIEP'
3449e5c31af7Sopenharmony_ci								isSupportedCheck = f'isSupported({depExtVector}, "{depPart}")'
3450e5c31af7Sopenharmony_ci								if dExt.promotedto is not None:
3451e5c31af7Sopenharmony_ci									p = dExt.promotedto
3452e5c31af7Sopenharmony_ci									# check if dependency was promoted to vulkan version or other extension
3453e5c31af7Sopenharmony_ci									if 'VK_VERSION' in p:
3454e5c31af7Sopenharmony_ci										depList[idx] = f'(isCompatibile({p[-3]}, {p[-1]}, v) || {isSupportedCheck})'
3455e5c31af7Sopenharmony_ci									else:
3456e5c31af7Sopenharmony_ci										depList[idx] = f'(isSupported({depExtVector}, "{p}") || {isSupportedCheck})'
3457e5c31af7Sopenharmony_ci								else:
3458e5c31af7Sopenharmony_ci									depList[idx] = isSupportedCheck
3459e5c31af7Sopenharmony_ci								extNotFound = False
3460e5c31af7Sopenharmony_ci								break
3461e5c31af7Sopenharmony_ci						# for SC when extension was not found try checking also not supported
3462e5c31af7Sopenharmony_ci						# extensions and see if this extension is part of core
3463e5c31af7Sopenharmony_ci						if extNotFound and api.apiName == "vulkansc":
3464e5c31af7Sopenharmony_ci							for dExt in api.notSupportedExtensions:
3465e5c31af7Sopenharmony_ci								if depPart == dExt.name:
3466e5c31af7Sopenharmony_ci									p = dExt.promotedto
3467e5c31af7Sopenharmony_ci									if p is None:
3468e5c31af7Sopenharmony_ci										break
3469e5c31af7Sopenharmony_ci									if int(p[-1]) > 2:
3470e5c31af7Sopenharmony_ci										break
3471e5c31af7Sopenharmony_ci									extNotFound = False
3472e5c31af7Sopenharmony_ci									depList[idx] = "true"
3473e5c31af7Sopenharmony_ci						if extNotFound:
3474e5c31af7Sopenharmony_ci							assert False, f"{depPart} from dependencies not found"
3475e5c31af7Sopenharmony_ci			yield f'\t// depends attribute in xml: {ext.depends}'
3476e5c31af7Sopenharmony_ci			finalConditon = ''.join(depList)
3477e5c31af7Sopenharmony_ci			yield f'\treturn {finalConditon};'
3478e5c31af7Sopenharmony_ci			yield '}\n'
3479e5c31af7Sopenharmony_ci		# save list of all device/instance extensions
3480e5c31af7Sopenharmony_ci		yield 'static const DependencyCheckVect {}ExtensionDependencies'.format(extType)
3481e5c31af7Sopenharmony_ci		yield '{'
3482e5c31af7Sopenharmony_ci		for ext in extensionList:
3483e5c31af7Sopenharmony_ci			extTabCount = (maxExtLength - len(ext)) / 4
3484e5c31af7Sopenharmony_ci			eTabs = '\t'*int(round(extTabCount+1.49))
3485e5c31af7Sopenharmony_ci			yield f'\tstd::make_pair("{ext}",{eTabs}&check_{ext}),'
3486e5c31af7Sopenharmony_ci		yield '};\n'
3487e5c31af7Sopenharmony_ci
3488e5c31af7Sopenharmony_ci	def genApiVersions():
3489e5c31af7Sopenharmony_ci		yield 'static const std::tuple<deUint32, deUint32, deUint32, deUint32>\treleasedApiVersions[]\t='
3490e5c31af7Sopenharmony_ci		yield '{'
3491e5c31af7Sopenharmony_ci		for f in reversed(api.features):
3492e5c31af7Sopenharmony_ci			apiVariant = '0' if f.api == 'vulkan' else '1'
3493e5c31af7Sopenharmony_ci			major, minor = f.number.split('.')
3494e5c31af7Sopenharmony_ci			version = (int(apiVariant) << 29) | (int(major) << 22) | (int(minor) << 12)
3495e5c31af7Sopenharmony_ci			yield '\tstd::make_tuple({}, {}, {}, {}),'.format(version, apiVariant, major, minor)
3496e5c31af7Sopenharmony_ci		yield '};'
3497e5c31af7Sopenharmony_ci
3498e5c31af7Sopenharmony_ci	def parseExtensionDependencies(extDeps, ext):
3499e5c31af7Sopenharmony_ci		major, minor = 1, 0
3500e5c31af7Sopenharmony_ci		requiredVerFound = False;
3501e5c31af7Sopenharmony_ci		# return in case nothing more left to be processed
3502e5c31af7Sopenharmony_ci		if extDeps is None or extDeps == "":
3503e5c31af7Sopenharmony_ci			return major, minor, requiredVerFound
3504e5c31af7Sopenharmony_ci		ungrpPartLen = 0
3505e5c31af7Sopenharmony_ci		versionPattern = "[A-Z]+_VERSION_([0-9]+)_([0-9]+)"
3506e5c31af7Sopenharmony_ci		ungroupedPattern = r"^.*?\(+|^.*?$"
3507e5c31af7Sopenharmony_ci		# look for non-grouped part, it may include the required vulkan version
3508e5c31af7Sopenharmony_ci		ungroupPart = re.search(ungroupedPattern, extDeps)
3509e5c31af7Sopenharmony_ci		if ungroupPart is not None and ungroupPart[0].replace(r"(", "") != "":
3510e5c31af7Sopenharmony_ci			ungrpPartLen = len(ungroupPart[0].replace(r"(", ""))
3511e5c31af7Sopenharmony_ci			# is specific version explicitly requested?
3512e5c31af7Sopenharmony_ci			match = re.search(versionPattern, ungroupPart[0])
3513e5c31af7Sopenharmony_ci			if match is not None:
3514e5c31af7Sopenharmony_ci				if len(match[0]) != len(extDeps):
3515e5c31af7Sopenharmony_ci					# there is more than just a version; check if it's accompanied by AND operator(s)
3516e5c31af7Sopenharmony_ci					ext_pattern = ".*\+*"+versionPattern+"\++.*|.*\++"+versionPattern+"\+*.*"
3517e5c31af7Sopenharmony_ci					match = re.search(ext_pattern, ungroupPart[0])
3518e5c31af7Sopenharmony_ci				if match is not None:
3519e5c31af7Sopenharmony_ci					# specific version is explicitly requested
3520e5c31af7Sopenharmony_ci					major, minor = int(match[1]), int(match[2])
3521e5c31af7Sopenharmony_ci					return major, minor, True
3522e5c31af7Sopenharmony_ci			# no explicit version is requested, continue parsing the remaining part
3523e5c31af7Sopenharmony_ci			extDeps = extDeps[ungrpPartLen:]
3524e5c31af7Sopenharmony_ci		groupedPattern = r"(.*)\+|(.*)$"
3525e5c31af7Sopenharmony_ci		match = re.search(groupedPattern, extDeps)
3526e5c31af7Sopenharmony_ci		if match is not None and match[0] != "":
3527e5c31af7Sopenharmony_ci			# groups may include the dependency "promoted to" versions accompanied by OR operator
3528e5c31af7Sopenharmony_ci			# but they don't include the extension explicit required version; continue parsing the remaining part
3529e5c31af7Sopenharmony_ci			groupLength = len(match[0])
3530e5c31af7Sopenharmony_ci			major, minor, requiredVerFound = parseExtensionDependencies(extDeps[groupLength:], ext)
3531e5c31af7Sopenharmony_ci		return major, minor, requiredVerFound
3532e5c31af7Sopenharmony_ci
3533e5c31af7Sopenharmony_ci	def genRequiredCoreVersions():
3534e5c31af7Sopenharmony_ci		yield 'static const std::tuple<deUint32, deUint32, const char*>\textensionRequiredCoreVersion[]\t ='
3535e5c31af7Sopenharmony_ci		yield '{'
3536e5c31af7Sopenharmony_ci		versionPattern = "[A-Z]+_VERSION_([0-9]+)_([0-9]+)"
3537e5c31af7Sopenharmony_ci		for ext in api.extensions:
3538e5c31af7Sopenharmony_ci			# skip video extensions
3539e5c31af7Sopenharmony_ci			if 'vulkan_video_' in ext.name:
3540e5c31af7Sopenharmony_ci				continue
3541e5c31af7Sopenharmony_ci			major, minor = 1, 0
3542e5c31af7Sopenharmony_ci			if ext.depends is not None:
3543e5c31af7Sopenharmony_ci				major, minor, requiredVerFound = parseExtensionDependencies(ext.depends, ext)
3544e5c31af7Sopenharmony_ci				if not requiredVerFound:
3545e5c31af7Sopenharmony_ci					# find all extensions that are dependencies of this one
3546e5c31af7Sopenharmony_ci					matches = re.findall("VK_\w+", ext.depends, re.M)
3547e5c31af7Sopenharmony_ci					for m in matches:
3548e5c31af7Sopenharmony_ci						for de in api.extensions:
3549e5c31af7Sopenharmony_ci							if de.name == m:
3550e5c31af7Sopenharmony_ci								if de.depends is not None:
3551e5c31af7Sopenharmony_ci									# check if the dependency states explicitly the required vulkan version and pick the higher one
3552e5c31af7Sopenharmony_ci									newMajor, newMinor, requiredVerFound = parseExtensionDependencies(de.depends, de)
3553e5c31af7Sopenharmony_ci									if requiredVerFound:
3554e5c31af7Sopenharmony_ci										if newMajor > major:
3555e5c31af7Sopenharmony_ci											major, minor = newMajor, newMinor
3556e5c31af7Sopenharmony_ci										elif newMajor == major and newMinor > minor:
3557e5c31af7Sopenharmony_ci											minor = newMinor
3558e5c31af7Sopenharmony_ci								break
3559e5c31af7Sopenharmony_ci			yield '\tstd::make_tuple({}, {}, "{}"),'.format(major, minor, ext.name)
3560e5c31af7Sopenharmony_ci		yield '};'
3561e5c31af7Sopenharmony_ci
3562e5c31af7Sopenharmony_ci	stream = []
3563e5c31af7Sopenharmony_ci	stream.extend(genHelperFunctions())
3564e5c31af7Sopenharmony_ci	stream.extend(genExtDepArray('instance'))
3565e5c31af7Sopenharmony_ci	stream.extend(genExtDepArray('device'))
3566e5c31af7Sopenharmony_ci	stream.extend(genApiVersions())
3567e5c31af7Sopenharmony_ci	stream.extend(genRequiredCoreVersions())
3568e5c31af7Sopenharmony_ci
3569e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, stream)
3570e5c31af7Sopenharmony_ci
3571e5c31af7Sopenharmony_cidef writeEntryPointValidation(api, filename):
3572e5c31af7Sopenharmony_ci	# keys are instance extension names and value is list of device-level functions
3573e5c31af7Sopenharmony_ci	instExtDeviceFunDict = {}
3574e5c31af7Sopenharmony_ci	# iterate over all extensions and find instance extensions
3575e5c31af7Sopenharmony_ci	for ext in api.extensions:
3576e5c31af7Sopenharmony_ci		if ext.type == "instance":
3577e5c31af7Sopenharmony_ci			# iterate over all functions instance extension adds
3578e5c31af7Sopenharmony_ci			for requirement in ext.requirementsList:
3579e5c31af7Sopenharmony_ci				for extCommand in requirement.newCommands:
3580e5c31af7Sopenharmony_ci					# to get a type of command we need to find this command definition in list of all functions
3581e5c31af7Sopenharmony_ci					for command in api.functions:
3582e5c31af7Sopenharmony_ci						if extCommand.name == command.name or extCommand.name in command.aliasList:
3583e5c31af7Sopenharmony_ci							# check if this is device-level entry-point
3584e5c31af7Sopenharmony_ci							if command.getType() == Function.TYPE_DEVICE:
3585e5c31af7Sopenharmony_ci								if ext.name not in instExtDeviceFunDict:
3586e5c31af7Sopenharmony_ci									instExtDeviceFunDict[ext.name] = []
3587e5c31af7Sopenharmony_ci								instExtDeviceFunDict[ext.name].append(extCommand.name)
3588e5c31af7Sopenharmony_ci	stream = ['std::map<std::string, std::vector<std::string> > instExtDeviceFun', '{']
3589e5c31af7Sopenharmony_ci	for extName in instExtDeviceFunDict:
3590e5c31af7Sopenharmony_ci		stream.append(f'\t{{ "{extName}",\n\t\t{{')
3591e5c31af7Sopenharmony_ci		for fun in instExtDeviceFunDict[extName]:
3592e5c31af7Sopenharmony_ci			stream.append(f'\t\t\t"{fun}",')
3593e5c31af7Sopenharmony_ci		stream.append('\t\t}\n\t},')
3594e5c31af7Sopenharmony_ci	stream.append('};')
3595e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, stream)
3596e5c31af7Sopenharmony_ci
3597e5c31af7Sopenharmony_cidef writeGetDeviceProcAddr(api, filename):
3598e5c31af7Sopenharmony_ci	testBlockStart = '''tcu::TestStatus		testGetDeviceProcAddr		(Context& context)
3599e5c31af7Sopenharmony_ci{
3600e5c31af7Sopenharmony_ci	tcu::TestLog&								log						(context.getTestContext().getLog());
3601e5c31af7Sopenharmony_ci	const PlatformInterface&					platformInterface		= context.getPlatformInterface();
3602e5c31af7Sopenharmony_ci	const auto									validationEnabled		= context.getTestContext().getCommandLine().isValidationEnabled();
3603e5c31af7Sopenharmony_ci	const CustomInstance						instance				(createCustomInstanceFromContext(context));
3604e5c31af7Sopenharmony_ci	const InstanceDriver&						instanceDriver			= instance.getDriver();
3605e5c31af7Sopenharmony_ci	const VkPhysicalDevice						physicalDevice			= chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
3606e5c31af7Sopenharmony_ci	const deUint32								queueFamilyIndex		= 0;
3607e5c31af7Sopenharmony_ci	const deUint32								queueCount				= 1;
3608e5c31af7Sopenharmony_ci	const float									queuePriority			= 1.0f;
3609e5c31af7Sopenharmony_ci	const std::vector<VkQueueFamilyProperties>	queueFamilyProperties	= getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice);
3610e5c31af7Sopenharmony_ci
3611e5c31af7Sopenharmony_ci	const VkDeviceQueueCreateInfo			deviceQueueCreateInfo =
3612e5c31af7Sopenharmony_ci	{
3613e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	//  VkStructureType				sType;
3614e5c31af7Sopenharmony_ci		DE_NULL,									//  const void*					pNext;
3615e5c31af7Sopenharmony_ci		(VkDeviceQueueCreateFlags)0u,				//  VkDeviceQueueCreateFlags	flags;
3616e5c31af7Sopenharmony_ci		queueFamilyIndex,							//  deUint32					queueFamilyIndex;
3617e5c31af7Sopenharmony_ci		queueCount,									//  deUint32					queueCount;
3618e5c31af7Sopenharmony_ci		&queuePriority,								//  const float*				pQueuePriorities;
3619e5c31af7Sopenharmony_ci	};
3620e5c31af7Sopenharmony_ci
3621e5c31af7Sopenharmony_ci	const VkDeviceCreateInfo				deviceCreateInfo =
3622e5c31af7Sopenharmony_ci	{
3623e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,		//  VkStructureType					sType;
3624e5c31af7Sopenharmony_ci		DE_NULL,									//  const void*						pNext;
3625e5c31af7Sopenharmony_ci		(VkDeviceCreateFlags)0u,					//  VkDeviceCreateFlags				flags;
3626e5c31af7Sopenharmony_ci		1u,											//  deUint32						queueCreateInfoCount;
3627e5c31af7Sopenharmony_ci		&deviceQueueCreateInfo,						//  const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
3628e5c31af7Sopenharmony_ci		0u,											//  deUint32						enabledLayerCount;
3629e5c31af7Sopenharmony_ci		DE_NULL,									//  const char* const*				ppEnabledLayerNames;
3630e5c31af7Sopenharmony_ci		0u,											//  deUint32						enabledExtensionCount;
3631e5c31af7Sopenharmony_ci		DE_NULL,									//  const char* const*				ppEnabledExtensionNames;
3632e5c31af7Sopenharmony_ci		DE_NULL,									//  const VkPhysicalDeviceFeatures*	pEnabledFeatures;
3633e5c31af7Sopenharmony_ci	};
3634e5c31af7Sopenharmony_ci	const Unique<VkDevice>					device			(createCustomDevice(validationEnabled, platformInterface, instance, instanceDriver, physicalDevice, &deviceCreateInfo));
3635e5c31af7Sopenharmony_ci	const DeviceDriver						deviceDriver	(platformInterface, instance, device.get(), context.getUsedApiVersion());
3636e5c31af7Sopenharmony_ci
3637e5c31af7Sopenharmony_ci	const std::vector<std::string> loaderExceptions{
3638e5c31af7Sopenharmony_ci		"vkSetDebugUtilsObjectNameEXT",
3639e5c31af7Sopenharmony_ci		"vkSetDebugUtilsObjectTagEXT",
3640e5c31af7Sopenharmony_ci		"vkQueueBeginDebugUtilsLabelEXT",
3641e5c31af7Sopenharmony_ci		"vkQueueEndDebugUtilsLabelEXT",
3642e5c31af7Sopenharmony_ci		"vkQueueInsertDebugUtilsLabelEXT",
3643e5c31af7Sopenharmony_ci		"vkCmdBeginDebugUtilsLabelEXT",
3644e5c31af7Sopenharmony_ci		"vkCmdEndDebugUtilsLabelEXT",
3645e5c31af7Sopenharmony_ci		"vkCmdInsertDebugUtilsLabelEXT",
3646e5c31af7Sopenharmony_ci	};
3647e5c31af7Sopenharmony_ci
3648e5c31af7Sopenharmony_ci	const std::vector<std::string> functions{'''
3649e5c31af7Sopenharmony_ci	testBlockEnd = '''	};
3650e5c31af7Sopenharmony_ci
3651e5c31af7Sopenharmony_ci	bool fail = false;
3652e5c31af7Sopenharmony_ci	for (const auto& function : functions)
3653e5c31af7Sopenharmony_ci	{
3654e5c31af7Sopenharmony_ci		if (std::find(loaderExceptions.begin(), loaderExceptions.end(), function) != loaderExceptions.end())
3655e5c31af7Sopenharmony_ci		{
3656e5c31af7Sopenharmony_ci			continue;
3657e5c31af7Sopenharmony_ci		}
3658e5c31af7Sopenharmony_ci		if (deviceDriver.getDeviceProcAddr(device.get(), function.c_str()) != DE_NULL)
3659e5c31af7Sopenharmony_ci		{
3660e5c31af7Sopenharmony_ci			fail = true;
3661e5c31af7Sopenharmony_ci			log << tcu::TestLog::Message << "Function " << function << " is not NULL" << tcu::TestLog::EndMessage;
3662e5c31af7Sopenharmony_ci		}
3663e5c31af7Sopenharmony_ci	}
3664e5c31af7Sopenharmony_ci	if (fail)
3665e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Fail");
3666e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("All functions are NULL");
3667e5c31af7Sopenharmony_ci}
3668e5c31af7Sopenharmony_ci'''
3669e5c31af7Sopenharmony_ci
3670e5c31af7Sopenharmony_ci	def functions(functionType):
3671e5c31af7Sopenharmony_ci		for ext in api.extensions:
3672e5c31af7Sopenharmony_ci			for requirement in ext.requirementsList:
3673e5c31af7Sopenharmony_ci				for requiredCommand in requirement.newCommands:
3674e5c31af7Sopenharmony_ci					yield '\t\t"' + requiredCommand.name + '",'
3675e5c31af7Sopenharmony_ci	stream = []
3676e5c31af7Sopenharmony_ci	stream.append('#include "tcuCommandLine.hpp"')
3677e5c31af7Sopenharmony_ci	stream.append('#include "vktTestCase.hpp"')
3678e5c31af7Sopenharmony_ci	stream.append('#include "vkPlatform.hpp"')
3679e5c31af7Sopenharmony_ci	stream.append('#include "vkDeviceUtil.hpp"')
3680e5c31af7Sopenharmony_ci	stream.append('#include "vkQueryUtil.hpp"')
3681e5c31af7Sopenharmony_ci	stream.append('#include "vktCustomInstancesDevices.hpp"')
3682e5c31af7Sopenharmony_ci	stream.append('#include "vktTestCase.hpp"')
3683e5c31af7Sopenharmony_ci	stream.append('#include "vktTestCaseUtil.hpp"')
3684e5c31af7Sopenharmony_ci	stream.append('\nnamespace vkt\n{\n')
3685e5c31af7Sopenharmony_ci	stream.append('using namespace vk;\n')
3686e5c31af7Sopenharmony_ci	stream.append(testBlockStart)
3687e5c31af7Sopenharmony_ci	stream.extend(functions(api))
3688e5c31af7Sopenharmony_ci	stream.append(testBlockEnd)
3689e5c31af7Sopenharmony_ci
3690e5c31af7Sopenharmony_ci	# function to create tests
3691e5c31af7Sopenharmony_ci	stream.append("void addGetDeviceProcAddrTests (tcu::TestCaseGroup* testGroup)\n{")
3692e5c31af7Sopenharmony_ci	stream.append('\taddFunctionCase(testGroup, "non_enabled", testGetDeviceProcAddr);')
3693e5c31af7Sopenharmony_ci	stream.append('}\n')
3694e5c31af7Sopenharmony_ci	stream.append('}\n')
3695e5c31af7Sopenharmony_ci
3696e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, stream)
3697e5c31af7Sopenharmony_ci
3698e5c31af7Sopenharmony_cidef writeConformanceVersions(filename):
3699e5c31af7Sopenharmony_ci	# get list of all vulkan/vulkansc tags from git
3700e5c31af7Sopenharmony_ci	listOfTags = os.popen("git ls-remote -t").read()
3701e5c31af7Sopenharmony_ci	vkMatches = re.findall("vulkan-cts-(\d).(\d).(\d).(\d)", listOfTags, re.M)
3702e5c31af7Sopenharmony_ci	scMatches = re.findall("vulkansc-cts-(\d).(\d).(\d).(\d)", listOfTags, re.M)
3703e5c31af7Sopenharmony_ci	if len(vkMatches) == 0 or len(scMatches) == 0:
3704e5c31af7Sopenharmony_ci		return
3705e5c31af7Sopenharmony_ci	# read all text files in doc folder and find withdrawn cts versions (branches)
3706e5c31af7Sopenharmony_ci	withdrawnVkBranches = set()
3707e5c31af7Sopenharmony_ci	withdrawnScBranches = set()
3708e5c31af7Sopenharmony_ci	today = datetime.date.today()
3709e5c31af7Sopenharmony_ci	for fileName in glob.glob(os.path.join(os.path.dirname(__file__), "..", "doc", "*.txt")):
3710e5c31af7Sopenharmony_ci		if "withdrawal" not in fileName:
3711e5c31af7Sopenharmony_ci			continue
3712e5c31af7Sopenharmony_ci		fileContent	= readFile(fileName)
3713e5c31af7Sopenharmony_ci		# get date when releases are withdrawn
3714e5c31af7Sopenharmony_ci		match = re.search(r"(20\d\d)-(\d\d)-(\d\d).+ withdrawn", fileContent, re.IGNORECASE)
3715e5c31af7Sopenharmony_ci		if match is not None:
3716e5c31af7Sopenharmony_ci			# check if announcement refers to date in the past
3717e5c31af7Sopenharmony_ci			if today > datetime.date(int(match[1]), int(match[2]), int(match[3])):
3718e5c31af7Sopenharmony_ci				# get names of withdrawn branches
3719e5c31af7Sopenharmony_ci				vkBranchMatches = re.findall("vulkan(\w\w)?-cts-(\d).(\d).(\d).(\d)", fileContent, re.M)
3720e5c31af7Sopenharmony_ci				for v in vkBranchMatches:
3721e5c31af7Sopenharmony_ci					selectedSet = withdrawnScBranches if v[0] == "sc" else withdrawnVkBranches
3722e5c31af7Sopenharmony_ci					selectedSet.add((v[1], v[2], v[3], v[4]))
3723e5c31af7Sopenharmony_ci	if len(withdrawnVkBranches) == 0:
3724e5c31af7Sopenharmony_ci		print(f"Warning: unable to read content of doc folder, skipping generation of {os.path.basename(filename)}")
3725e5c31af7Sopenharmony_ci		return
3726e5c31af7Sopenharmony_ci	# define helper function that will be used to add entries for both vk and sc
3727e5c31af7Sopenharmony_ci	def appendToStream(stream, versionsToAdd, maxWithdrawnVersion):
3728e5c31af7Sopenharmony_ci		addedVersions = set()
3729e5c31af7Sopenharmony_ci		for v in reversed(versionsToAdd):
3730e5c31af7Sopenharmony_ci			# add only unique versions; ignore duplicates (e.g. with "-rc1", "-rc2" postfix);
3731e5c31af7Sopenharmony_ci			# also add versions that are greater then maximal withdrawn version
3732e5c31af7Sopenharmony_ci			if v in addedVersions or v <= maxWithdrawnVersion:
3733e5c31af7Sopenharmony_ci				continue
3734e5c31af7Sopenharmony_ci			addedVersions.add(v)
3735e5c31af7Sopenharmony_ci			stream.append(f'\tmakeConformanceVersion({v[0]}, {v[1]}, {v[2]}, {v[3]}),')
3736e5c31af7Sopenharmony_ci	# save array with versions
3737e5c31af7Sopenharmony_ci	stream = ['static const VkConformanceVersion knownConformanceVersions[]',\
3738e5c31af7Sopenharmony_ci			  '{',\
3739e5c31af7Sopenharmony_ci			  '#ifndef CTS_USES_VULKANSC']
3740e5c31af7Sopenharmony_ci	appendToStream(stream, vkMatches, max(withdrawnVkBranches))
3741e5c31af7Sopenharmony_ci	stream.append('#else')
3742e5c31af7Sopenharmony_ci	appendToStream(stream, scMatches, tuple('0'*4) if len(withdrawnScBranches) == 0 else max(withdrawnScBranches))
3743e5c31af7Sopenharmony_ci	stream.append('#endif // CTS_USES_VULKANSC')
3744e5c31af7Sopenharmony_ci	stream.append('};')
3745e5c31af7Sopenharmony_ci	writeInlFile(filename, INL_HEADER, stream)
3746e5c31af7Sopenharmony_ci
3747e5c31af7Sopenharmony_cidef parseCmdLineArgs():
3748e5c31af7Sopenharmony_ci	parser = argparse.ArgumentParser(description = "Generate Vulkan INL files",
3749e5c31af7Sopenharmony_ci									 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
3750e5c31af7Sopenharmony_ci	parser.add_argument("-a",
3751e5c31af7Sopenharmony_ci						"--api",
3752e5c31af7Sopenharmony_ci						dest="api",
3753e5c31af7Sopenharmony_ci						default="",
3754e5c31af7Sopenharmony_ci						help="Choose between Vulkan and Vulkan SC")
3755e5c31af7Sopenharmony_ci	parser.add_argument("-o",
3756e5c31af7Sopenharmony_ci						"--outdir",
3757e5c31af7Sopenharmony_ci						dest="outdir",
3758e5c31af7Sopenharmony_ci						default="",
3759e5c31af7Sopenharmony_ci						help="Choose output directory")
3760e5c31af7Sopenharmony_ci	return parser.parse_args()
3761e5c31af7Sopenharmony_ci
3762e5c31af7Sopenharmony_ciif __name__ == "__main__":
3763e5c31af7Sopenharmony_ci	args = parseCmdLineArgs()
3764e5c31af7Sopenharmony_ci
3765e5c31af7Sopenharmony_ci	# if argument was specified it is interpreted as a path to which .inl files will be written
3766e5c31af7Sopenharmony_ci	outputPath = DEFAULT_OUTPUT_DIR[args.api] if args.outdir == '' else args.outdir
3767e5c31af7Sopenharmony_ci
3768e5c31af7Sopenharmony_ci	vkTree = etree.parse(os.path.join(VULKAN_XML_DIR, "vk.xml"))
3769e5c31af7Sopenharmony_ci	apiName = "vulkansc" if args.api == 'SC' else "vulkan"
3770e5c31af7Sopenharmony_ci	stripNonmatchingAPIs(vkTree.getroot(), apiName, actuallyDelete = True)
3771e5c31af7Sopenharmony_ci
3772e5c31af7Sopenharmony_ci	# Read vk.xml and generate vulkan headers from it
3773e5c31af7Sopenharmony_ci	api = API(apiName)
3774e5c31af7Sopenharmony_ci	api.build(vkTree)
3775e5c31af7Sopenharmony_ci	api.postProcess()
3776e5c31af7Sopenharmony_ci
3777e5c31af7Sopenharmony_ci	# Read video.xml
3778e5c31af7Sopenharmony_ci	if args.api != 'SC':
3779e5c31af7Sopenharmony_ci		api.build( etree.parse(os.path.join(VULKAN_XML_DIR, "video.xml")) )
3780e5c31af7Sopenharmony_ci
3781e5c31af7Sopenharmony_ci	platformFuncs	= [Function.TYPE_PLATFORM]
3782e5c31af7Sopenharmony_ci	instanceFuncs	= [Function.TYPE_INSTANCE]
3783e5c31af7Sopenharmony_ci	deviceFuncs		= [Function.TYPE_DEVICE]
3784e5c31af7Sopenharmony_ci
3785e5c31af7Sopenharmony_ci	dfd										= generateDeviceFeaturesOrPropertiesDefs(api, 'Features')
3786e5c31af7Sopenharmony_ci	writeDeviceFeatures						(api, dfd, os.path.join(outputPath, "vkDeviceFeatures.inl"))
3787e5c31af7Sopenharmony_ci	writeDeviceFeaturesDefaultDeviceDefs	(dfd, os.path.join(outputPath, "vkDeviceFeaturesForDefaultDeviceDefs.inl"))
3788e5c31af7Sopenharmony_ci	writeDeviceFeaturesContextDecl			(dfd, os.path.join(outputPath, "vkDeviceFeaturesForContextDecl.inl"))
3789e5c31af7Sopenharmony_ci	writeDeviceFeaturesContextDefs			(dfd, os.path.join(outputPath, "vkDeviceFeaturesForContextDefs.inl"))
3790e5c31af7Sopenharmony_ci	writeDeviceFeatureTest					(api, os.path.join(outputPath, "vkDeviceFeatureTest.inl"))
3791e5c31af7Sopenharmony_ci
3792e5c31af7Sopenharmony_ci	dpd										= generateDeviceFeaturesOrPropertiesDefs(api, 'Properties')
3793e5c31af7Sopenharmony_ci	writeDeviceProperties					(api, dpd, os.path.join(outputPath, "vkDeviceProperties.inl"))
3794e5c31af7Sopenharmony_ci	writeDevicePropertiesDefaultDeviceDefs	(dpd, os.path.join(outputPath, "vkDevicePropertiesForDefaultDeviceDefs.inl"))
3795e5c31af7Sopenharmony_ci	writeDevicePropertiesContextDecl		(dpd, os.path.join(outputPath, "vkDevicePropertiesForContextDecl.inl"))
3796e5c31af7Sopenharmony_ci	writeDevicePropertiesContextDefs		(dpd, os.path.join(outputPath, "vkDevicePropertiesForContextDefs.inl"))
3797e5c31af7Sopenharmony_ci
3798e5c31af7Sopenharmony_ci	writeHandleType							(api, os.path.join(outputPath, "vkHandleType.inl"))
3799e5c31af7Sopenharmony_ci	writeBasicTypes							(api, os.path.join(outputPath, "vkBasicTypes.inl"))
3800e5c31af7Sopenharmony_ci	writeCompositeTypes						(api, os.path.join(outputPath, "vkStructTypes.inl"))
3801e5c31af7Sopenharmony_ci	writeInterfaceDecl						(api, os.path.join(outputPath, "vkVirtualPlatformInterface.inl"),		platformFuncs,	False)
3802e5c31af7Sopenharmony_ci	writeInterfaceDecl						(api, os.path.join(outputPath, "vkVirtualInstanceInterface.inl"),		instanceFuncs,	False)
3803e5c31af7Sopenharmony_ci	writeInterfaceDecl						(api, os.path.join(outputPath, "vkVirtualDeviceInterface.inl"),			deviceFuncs,	False)
3804e5c31af7Sopenharmony_ci	writeInterfaceDecl						(api, os.path.join(outputPath, "vkConcretePlatformInterface.inl"),		platformFuncs,	True)
3805e5c31af7Sopenharmony_ci	writeInterfaceDecl						(api, os.path.join(outputPath, "vkConcreteInstanceInterface.inl"),		instanceFuncs,	True)
3806e5c31af7Sopenharmony_ci	writeInterfaceDecl						(api, os.path.join(outputPath, "vkConcreteDeviceInterface.inl"),		deviceFuncs,	True)
3807e5c31af7Sopenharmony_ci	writeFunctionPtrTypes					(api, os.path.join(outputPath, "vkFunctionPointerTypes.inl"))
3808e5c31af7Sopenharmony_ci	writeFunctionPointers					(api, os.path.join(outputPath, "vkPlatformFunctionPointers.inl"),		platformFuncs)
3809e5c31af7Sopenharmony_ci	writeFunctionPointers					(api, os.path.join(outputPath, "vkInstanceFunctionPointers.inl"),		instanceFuncs)
3810e5c31af7Sopenharmony_ci	writeFunctionPointers					(api, os.path.join(outputPath, "vkDeviceFunctionPointers.inl"),			deviceFuncs)
3811e5c31af7Sopenharmony_ci	writeInitFunctionPointers				(api, os.path.join(outputPath, "vkInitPlatformFunctionPointers.inl"),	platformFuncs,	lambda f: f.name != "vkGetInstanceProcAddr")
3812e5c31af7Sopenharmony_ci	writeInitFunctionPointers				(api, os.path.join(outputPath, "vkInitInstanceFunctionPointers.inl"),	instanceFuncs)
3813e5c31af7Sopenharmony_ci	writeInitFunctionPointers				(api, os.path.join(outputPath, "vkInitDeviceFunctionPointers.inl"),		deviceFuncs)
3814e5c31af7Sopenharmony_ci	writeFuncPtrInterfaceImpl				(api, os.path.join(outputPath, "vkPlatformDriverImpl.inl"),				platformFuncs,	"PlatformDriver")
3815e5c31af7Sopenharmony_ci	writeFuncPtrInterfaceImpl				(api, os.path.join(outputPath, "vkInstanceDriverImpl.inl"),				instanceFuncs,	"InstanceDriver")
3816e5c31af7Sopenharmony_ci	writeFuncPtrInterfaceImpl				(api, os.path.join(outputPath, "vkDeviceDriverImpl.inl"),				deviceFuncs,	"DeviceDriver")
3817e5c31af7Sopenharmony_ci	if args.api=='SC':
3818e5c31af7Sopenharmony_ci		writeFuncPtrInterfaceSCImpl			(api, os.path.join(outputPath, "vkDeviceDriverSCImpl.inl"),				deviceFuncs,	"DeviceDriverSC")
3819e5c31af7Sopenharmony_ci	writeStrUtilProto						(api, os.path.join(outputPath, "vkStrUtil.inl"))
3820e5c31af7Sopenharmony_ci	writeStrUtilImpl						(api, os.path.join(outputPath, "vkStrUtilImpl.inl"))
3821e5c31af7Sopenharmony_ci	writeRefUtilProto						(api, os.path.join(outputPath, "vkRefUtil.inl"))
3822e5c31af7Sopenharmony_ci	writeRefUtilImpl						(api, os.path.join(outputPath, "vkRefUtilImpl.inl"))
3823e5c31af7Sopenharmony_ci	writeStructTraitsImpl					(api, os.path.join(outputPath, "vkGetStructureTypeImpl.inl"))
3824e5c31af7Sopenharmony_ci	writeNullDriverImpl						(api, os.path.join(outputPath, "vkNullDriverImpl.inl"))
3825e5c31af7Sopenharmony_ci	writeTypeUtil							(api, os.path.join(outputPath, "vkTypeUtil.inl"))
3826e5c31af7Sopenharmony_ci	writeSupportedExtensions				(api, os.path.join(outputPath, "vkSupportedExtensions.inl"))
3827e5c31af7Sopenharmony_ci	writeCoreFunctionalities				(api, os.path.join(outputPath, "vkCoreFunctionalities.inl"))
3828e5c31af7Sopenharmony_ci	writeExtensionFunctions					(api, os.path.join(outputPath, "vkExtensionFunctions.inl"))
3829e5c31af7Sopenharmony_ci	writeDeviceFeatures2					(api, os.path.join(outputPath, "vkDeviceFeatures2.inl"))
3830e5c31af7Sopenharmony_ci	writeMandatoryFeatures					(api, os.path.join(outputPath, "vkMandatoryFeatures.inl"))
3831e5c31af7Sopenharmony_ci	writeExtensionList						(api, os.path.join(outputPath, "vkInstanceExtensions.inl"),	'instance')
3832e5c31af7Sopenharmony_ci	writeExtensionList						(api, os.path.join(outputPath, "vkDeviceExtensions.inl"),	'device')
3833e5c31af7Sopenharmony_ci	writeDriverIds							(api, os.path.join(outputPath, "vkKnownDriverIds.inl"))
3834e5c31af7Sopenharmony_ci	writeObjTypeImpl						(api, os.path.join(outputPath, "vkObjTypeImpl.inl"))
3835e5c31af7Sopenharmony_ci	writeApiExtensionDependencyInfo			(api, os.path.join(outputPath, "vkApiExtensionDependencyInfo.inl"))
3836e5c31af7Sopenharmony_ci	writeEntryPointValidation				(api, os.path.join(outputPath, "vkEntryPointValidation.inl"))
3837e5c31af7Sopenharmony_ci	writeGetDeviceProcAddr					(api, os.path.join(outputPath, "vkGetDeviceProcAddr.inl"))
3838e5c31af7Sopenharmony_ci	writeConformanceVersions				(     os.path.join(outputPath, "vkKnownConformanceVersions.inl"))
3839e5c31af7Sopenharmony_ci
3840e5c31af7Sopenharmony_ci	# NOTE: when new files are generated then they should also be added to the
3841e5c31af7Sopenharmony_ci	# vk-gl-cts\external\vulkancts\framework\vulkan\CMakeLists.txt outputs list
3842