import os,re,sys
from generator import *
class ValidityOutputGenerator(OutputGenerator):
def __init__(self,
errFile = sys.stderr,
warnFile = sys.stderr,
diagFile = sys.stdout):
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
def beginFile(self, genOpts):
OutputGenerator.beginFile(self, genOpts)
def endFile(self):
OutputGenerator.endFile(self)
def beginFeature(self, interface, emit):
OutputGenerator.beginFeature(self, interface, emit)
def endFeature(self):
OutputGenerator.endFeature(self)
def makeParameterName(self, name):
return 'pname:' + name
def makeStructName(self, name):
return 'sname:' + name
def makeBaseTypeName(self, name):
return 'basetype:' + name
def makeEnumerationName(self, name):
return 'elink:' + name
def makeEnumerantName(self, name):
return 'ename:' + name
def makeFLink(self, name):
return 'flink:' + name
def makeAnchor(self, blockname, pname, category):
if pname != None:
return '* [[VUID-%s-%s-%s]] ' % (blockname, pname, category)
else:
return '* [[VUID-%s-%s]] ' % (blockname, category)
def writeInclude(self, directory, basename, validity, threadsafety, commandpropertiesentry, successcodes, errorcodes):
directory = self.genOpts.directory + '/' + directory
self.makeDir(directory)
filename = directory + '/' + basename + '.txt'
self.logMsg('diag', '# Generating include file:', filename)
fp = open(filename, 'w', encoding='utf-8')
write('// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry', file=fp)
if validity is not None:
write('.Valid Usage (Implicit)', file=fp)
write('****', file=fp)
write(validity, file=fp, end='')
write('****', file=fp)
write('', file=fp)
if threadsafety is not None:
write('.Host Synchronization', file=fp)
write('****', file=fp)
write(threadsafety, file=fp, end='')
write('****', file=fp)
write('', file=fp)
if commandpropertiesentry is not None:
write('.Command Properties', file=fp)
write('****', file=fp)
write('[options="header", width="100%"]', file=fp)
write('|====', file=fp)
write('|<<VkCommandBufferLevel,Command Buffer Levels>>|<<vkCmdBeginRenderPass,Render Pass Scope>>|<<VkQueueFlagBits,Supported Queue Types>>|<<synchronization-pipeline-stages-types,Pipeline Type>>', file=fp)
write(commandpropertiesentry, file=fp)
write('|====', file=fp)
write('****', file=fp)
write('', file=fp)
if successcodes is not None or errorcodes is not None:
write('.Return Codes', file=fp)
write('****', file=fp)
if successcodes is not None:
write('ifndef::doctype-manpage[]', file=fp)
write('<<fundamentals-successcodes,Success>>::', file=fp)
write('endif::doctype-manpage[]', file=fp)
write('ifdef::doctype-manpage[]', file=fp)
write('On success, this command returns::', file=fp)
write('endif::doctype-manpage[]', file=fp)
write(successcodes, file=fp)
if errorcodes is not None:
write('ifndef::doctype-manpage[]', file=fp)
write('<<fundamentals-errorcodes,Failure>>::', file=fp)
write('endif::doctype-manpage[]', file=fp)
write('ifdef::doctype-manpage[]', file=fp)
write('On failure, this command returns::', file=fp)
write('endif::doctype-manpage[]', file=fp)
write(errorcodes, file=fp)
write('****', file=fp)
write('', file=fp)
fp.close()
def paramIsPointer(self, param):
ispointer = False
paramtype = param.find('type')
if paramtype.tail is not None and '*' in paramtype.tail:
ispointer = True
return ispointer
def paramIsStaticArray(self, param):
if param.find('name').tail is not None:
if param.find('name').tail[0] == '[':
return True
def staticArrayLength(self, param):
paramname = param.find('name')
paramenumsize = param.find('enum')
if paramenumsize is not None:
return paramenumsize.text
else:
return paramname.tail[1:-1]
def paramIsArray(self, param):
return param.attrib.get('len') is not None
def getHandleParent(self, typename):
types = self.registry.tree.findall("types/type")
for elem in types:
if (elem.find("name") is not None and elem.find('name').text == typename) or elem.attrib.get('name') == typename:
return elem.attrib.get('parent')
return None
def getHandleAncestors(self, typename):
ancestors = []
current = typename
while True:
current = self.getHandleParent(current)
if current is None:
return ancestors
ancestors.append(current)
def getHandleDispatchableAncestors(self, typename):
ancestors = []
current = typename
while True:
current = self.getHandleParent(current)
if current is None:
return ancestors
if self.isHandleTypeDispatchable(current):
ancestors.append(current)
def isHandleTypeDispatchable(self, handlename):
handle = self.registry.tree.find("types/type/[name='" + handlename + "'][@category='handle']")
if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
return True
else:
return False
def isHandleOptional(self, param, params):
isOptional = False
if param.attrib.get('optional') is not None:
return True
if param.attrib.get('noautovalidity') is not None:
return True
if self.paramIsArray(param):
lengths = param.attrib.get('len').split(',')
for length in lengths:
if (length) != 'null-terminated' and (length) != '1':
for otherparam in params:
if otherparam.find('name').text == length:
if otherparam.attrib.get('optional') is not None:
return True
return False
def getTypeCategory(self, typename):
types = self.registry.tree.findall("types/type")
for elem in types:
if (elem.find("name") is not None and elem.find('name').text == typename) or elem.attrib.get('name') == typename:
return elem.attrib.get('category')
def makeAsciiDocPreChunk(self, blockname, param, params):
paramname = param.find('name')
paramtype = param.find('type')
asciidoc = self.makeAnchor(blockname, paramname.text, 'parameter')
if self.paramIsStaticArray(param):
asciidoc += 'Any given element of '
elif self.paramIsArray(param):
lengths = param.attrib.get('len').split(',')
optionallengths = []
for length in lengths:
if (length) != 'null-terminated' and (length) != '1':
for otherparam in params:
if otherparam.find('name').text == length:
if otherparam.attrib.get('optional') is not None:
if self.paramIsPointer(otherparam):
optionallengths.append('the value referenced by ' + self.makeParameterName(length))
else:
optionallengths.append(self.makeParameterName(length))
if len(optionallengths) != 0 or param.attrib.get('optional') is not None:
asciidoc += 'If '
if len(optionallengths) != 0:
if len(optionallengths) == 1:
asciidoc += optionallengths[0]
asciidoc += ' is '
else:
asciidoc += ', or '.join(optionallengths)
asciidoc += ' are '
asciidoc += 'not `0`, '
if len(optionallengths) != 0 and param.attrib.get('optional') is not None:
asciidoc += 'and '
if param.attrib.get('optional') is not None:
asciidoc += self.makeParameterName(paramname.text)
asciidoc += ' is not `NULL`, '
elif param.attrib.get('optional') is not None:
if self.getTypeCategory(paramtype.text) != 'bitmask':
if param.attrib.get('optional').split(',')[0] == 'true':
asciidoc += 'If '
asciidoc += self.makeParameterName(paramname.text)
asciidoc += ' is not '
if self.paramIsArray(param) or self.paramIsPointer(param) or self.isHandleTypeDispatchable(paramtype.text):
asciidoc += '`NULL`'
elif self.getTypeCategory(paramtype.text) == 'handle':
asciidoc += 'dlink:VK_NULL_HANDLE'
else:
asciidoc += '`0`'
asciidoc += ', '
return asciidoc
def createValidationLineForParameterIntroChunk(self, blockname, param, params, typetext):
asciidoc = ''
paramname = param.find('name')
paramtype = param.find('type')
asciidoc += self.makeAsciiDocPreChunk(blockname, param, params)
asciidoc += self.makeParameterName(paramname.text)
asciidoc += ' must: be '
if self.paramIsArray(param):
lengths = param.attrib.get('len').split(',')
if (lengths[0]) == 'null-terminated':
asciidoc += 'a null-terminated '
elif (lengths[0]) == '1':
asciidoc += 'a valid pointer to '
else:
asciidoc += 'a valid pointer to an array of '
if 'latexmath:' in lengths[0]:
asciidoc += lengths[0]
else:
asciidoc += self.makeParameterName(lengths[0])
asciidoc += ' '
for length in lengths[1:]:
if (length) == 'null-terminated': asciidoc += 'null-terminated '
elif (length) == '1':
asciidoc += 'valid pointers to '
else:
asciidoc += 'valid pointers to arrays of '
if 'latexmath:' in length:
asciidoc += length
else:
asciidoc += self.makeParameterName(length)
asciidoc += ' '
if paramtype.text == 'void':
if lengths[-1] == '1':
if len(lengths) > 1:
asciidoc = asciidoc[:-5] else:
asciidoc = asciidoc[:-4]
else:
asciidoc += 'byte'
elif paramtype.text == 'char':
if lengths[-1] == 'null-terminated':
asciidoc += 'UTF-8 string'
else:
asciidoc += 'char value'
elif param.text is not None:
if 'const' in param.text:
typecategory = self.getTypeCategory(paramtype.text)
if (typecategory != 'struct' and typecategory != 'union' and typecategory != 'basetype' and typecategory is not None) or not self.isStructAlwaysValid(blockname, paramtype.text):
asciidoc += 'valid '
asciidoc += typetext
if len(lengths) > 1 or (lengths[0] != '1' and lengths[0] != 'null-terminated'):
asciidoc += 's'
elif self.paramIsPointer(param):
pointercount = paramtype.tail.count('*')
if paramtype.text == 'void':
pointercount -= 1
asciidoc += 'a '
for i in range(0, pointercount):
asciidoc += 'valid pointer to a '
if paramtype.text == 'void':
if pointercount == 0 and param.attrib.get('optional') is not None:
return '' else:
if param.attrib.get('optional').split(',')[pointercount] is not None:
typetext = 'pointer value'
if param.text is not None and paramtype.text != 'void':
if 'const' in param.text:
asciidoc += 'valid '
asciidoc += typetext
else:
asciidoc += 'a valid '
asciidoc += typetext
if asciidoc != '':
asciidoc += '\n'
if self.getTypeCategory(paramtype.text) == 'bitmask':
isMandatory = param.attrib.get('optional') is None if isMandatory:
asciidoc += self.makeAnchor(blockname, paramname.text, 'requiredbitmask')
if self.paramIsArray(param):
asciidoc += 'Each element of '
asciidoc += 'pname:'
asciidoc += paramname.text
asciidoc += ' must: not be `0`'
asciidoc += '\n'
return asciidoc
def makeAsciiDocLineForParameter(self, blockname, param, params, typetext):
if param.attrib.get('noautovalidity') is not None:
return ''
asciidoc = self.createValidationLineForParameterIntroChunk(blockname, param, params, typetext)
return asciidoc
def isStructAlwaysValid(self, blockname, structname):
struct = self.registry.tree.find("types/type[@name='" + structname + "']")
params = struct.findall('member')
for param in params:
paramname = param.find('name')
paramtype = param.find('type')
typecategory = self.getTypeCategory(paramtype.text)
if paramname.text == 'pNext':
return False
if paramname.text == 'sType':
return False
if paramtype.text == 'void' or paramtype.text == 'char' or self.paramIsArray(param) or self.paramIsPointer(param):
if self.makeAsciiDocLineForParameter(blockname, param, params, '') != '':
return False
elif typecategory == 'handle' or typecategory == 'enum' or typecategory == 'bitmask':
return False
elif typecategory == 'struct' or typecategory == 'union':
if self.isStructAlwaysValid(blockname, paramtype.text) is False:
return False
return True
def createValidationLineForParameter(self, blockname, param, params, typecategory):
asciidoc = ''
paramname = param.find('name')
paramtype = param.find('type')
if paramtype.text == 'void' or paramtype.text == 'char':
asciidoc += self.makeAsciiDocLineForParameter(blockname, param, params, '')
elif typecategory == 'bitmask':
bitsname = paramtype.text.replace('Flags', 'FlagBits')
if self.registry.tree.find("enums[@name='" + bitsname + "']") is None:
asciidoc += self.makeAnchor(blockname, paramname.text, 'zerobitmask')
asciidoc += self.makeParameterName(paramname.text)
asciidoc += ' must: be `0`'
asciidoc += '\n'
else:
if self.paramIsArray(param):
if param.text is not None and 'const' in param.text:
asciidoc += self.makeAsciiDocLineForParameter(blockname, param, params, 'combinations of ' + self.makeEnumerationName(bitsname) + ' value')
else:
asciidoc += self.makeAsciiDocLineForParameter(blockname, param, params, self.makeEnumerationName(paramtype.text) + ' value')
elif self.paramIsPointer(param):
if param.text is not None and 'const' in param.text:
asciidoc += self.makeAsciiDocLineForParameter(blockname, param, params, 'combination of ' + self.makeEnumerationName(bitsname) + ' values')
else:
asciidoc += self.makeAsciiDocLineForParameter(blockname, param, params, self.makeEnumerationName(paramtype.text) + ' value')
else:
asciidoc += self.makeAsciiDocLineForParameter(blockname, param, params, 'combination of ' + self.makeEnumerationName(bitsname) + ' values')
elif typecategory == 'handle':
asciidoc += self.makeAsciiDocLineForParameter(blockname, param, params, self.makeStructName(paramtype.text) + ' handle')
elif typecategory == 'enum':
asciidoc += self.makeAsciiDocLineForParameter(blockname, param, params, self.makeEnumerationName(paramtype.text) + ' value')
elif typecategory == 'struct':
if (self.paramIsArray(param) or self.paramIsPointer(param)) or not self.isStructAlwaysValid(blockname, paramtype.text):
asciidoc += self.makeAsciiDocLineForParameter(blockname, param, params, self.makeStructName(paramtype.text) + ' structure')
elif typecategory == 'union':
if (self.paramIsArray(param) or self.paramIsPointer(param)) or not self.isStructAlwaysValid(blockname, paramtype.text):
asciidoc += self.makeAsciiDocLineForParameter(blockname, param, params, self.makeStructName(paramtype.text) + ' union')
elif self.paramIsArray(param) or self.paramIsPointer(param):
asciidoc += self.makeAsciiDocLineForParameter(blockname, param, params, self.makeBaseTypeName(paramtype.text) + ' value')
return asciidoc
def makeAsciiDocHandleParent(self, blockname, param, params):
asciidoc = ''
paramname = param.find('name')
paramtype = param.find('type')
handleparent = self.getHandleParent(paramtype.text)
if handleparent is not None:
parentreference = None
for otherparam in params:
if otherparam.find('type').text == handleparent:
parentreference = otherparam.find('name').text
if parentreference is not None:
asciidoc += self.makeAnchor(blockname, paramname.text, 'parent')
if self.isHandleOptional(param, params):
if self.paramIsArray(param):
asciidoc += 'Each element of '
asciidoc += self.makeParameterName(paramname.text)
asciidoc += ' that is a valid handle'
else:
asciidoc += 'If '
asciidoc += self.makeParameterName(paramname.text)
asciidoc += ' is a valid handle, it'
else:
if self.paramIsArray(param):
asciidoc += 'Each element of '
asciidoc += self.makeParameterName(paramname.text)
asciidoc += ' must: have been created, allocated, or retrieved from '
asciidoc += self.makeParameterName(parentreference)
asciidoc += '\n'
return asciidoc
def makeAsciiDocHandlesCommonAncestor(self, blockname, handles, params):
asciidoc = ''
if len(handles) > 1:
ancestormap = {}
anyoptional = False
for param in handles:
paramname = param.find('name')
paramtype = param.find('type')
if not self.paramIsPointer(param) or (param.text is not None and 'const' in param.text):
ancestors = self.getHandleDispatchableAncestors(paramtype.text)
ancestormap[param] = ancestors
anyoptional |= self.isHandleOptional(param, params)
for param in handles:
paramname = param.find('name')
paramtype = param.find('type')
removals = []
for ancestors in ancestormap.items():
if paramtype.text in ancestors[1]:
removals.append(ancestors[0])
if removals != []:
for removal in removals:
del(ancestormap[removal])
if len(ancestormap.values()) > 1:
current = list(ancestormap.values())[0]
for ancestors in list(ancestormap.values())[1:]:
current = [val for val in current if val in ancestors]
if len(current) > 0:
commonancestor = current[0]
if len(ancestormap.keys()) > 1:
asciidoc += self.makeAnchor(blockname, None, 'commonparent')
parametertexts = []
for param in ancestormap.keys():
paramname = param.find('name')
parametertext = self.makeParameterName(paramname.text)
if self.paramIsArray(param):
parametertext = 'the elements of ' + parametertext
parametertexts.append(parametertext)
parametertexts.sort()
if len(parametertexts) > 2:
asciidoc += 'Each of '
else:
asciidoc += 'Both of '
asciidoc += ", ".join(parametertexts[:-1])
asciidoc += ', and '
asciidoc += parametertexts[-1]
if anyoptional is True:
asciidoc += ' that are valid handles'
asciidoc += ' must: have been created, allocated, or retrieved from the same '
asciidoc += self.makeStructName(commonancestor)
asciidoc += '\n'
return asciidoc
def makeStructureType(self, blockname, param):
paramname = param.find('name')
paramtype = param.find('type')
asciidoc = self.makeAnchor(blockname, paramname.text, 'sType')
asciidoc += self.makeParameterName(paramname.text)
asciidoc += ' must: be '
values = param.attrib.get('values')
if values:
valuelist = [ self.makeEnumerantName(v) for v in values.split(',') ]
else:
structuretype = ''
for elem in re.findall(r'(([A-Z][a-z]+)|([A-Z][A-Z]+))', blockname):
if elem[0] == 'Vk':
structuretype += 'VK_STRUCTURE_TYPE_'
else:
structuretype += elem[0].upper()
structuretype += '_'
valuelist = [ self.makeEnumerantName(structuretype[:-1]) ]
if len(valuelist) > 0:
if len(valuelist) == 1:
asciidoc += valuelist[0]
else:
asciidoc += (', ').join(valuelist[:-1]) + ', or ' + valuelist[-1]
asciidoc += '\n'
return asciidoc
def makeStructureExtensionPointer(self, blockname, param):
paramname = param.find('name')
paramtype = param.find('type')
asciidoc = self.makeAnchor(blockname, paramname.text, 'pNext')
validextensionstructs = self.registry.validextensionstructs.get(blockname)
extensionstructs = []
if validextensionstructs is not None:
for struct in validextensionstructs:
type = self.registry.lookupElementInfo(struct, self.registry.typedict)
if (type == None):
self.logMsg('warn', 'makeStructureExtensionPointer: struct', struct, 'is in a validextensionstructs= attribute but is not in the registry')
elif (type.required):
extensionstructs.append('slink:' + struct)
else:
self.logMsg('diag', 'makeStructureExtensionPointer: struct', struct, 'IS NOT required')
if len(extensionstructs) == 0:
asciidoc += self.makeParameterName(paramname.text)
asciidoc += ' must: be `NULL`'
elif len(extensionstructs) == 1:
asciidoc += self.makeParameterName(paramname.text)
asciidoc += ' must: be `NULL` or a pointer to a valid instance of '
asciidoc += extensionstructs[0]
else:
asciidoc += 'Each '
asciidoc += self.makeParameterName(paramname.text)
asciidoc += ' member of any structure (including this one) in the pname:pNext chain must: be either `NULL` or a pointer to a valid instance of '
if len(extensionstructs) == 2:
asciidoc += extensionstructs[0] + ' or ' + extensionstructs[1]
else:
asciidoc += (', ').join(extensionstructs[:-1]) + ', or ' + extensionstructs[-1]
asciidoc += '\n'
asciidoc += self.makeAnchor(blockname, 'sType', 'unique')
asciidoc += 'Each pname:sType member in the pname:pNext chain must: be unique'
asciidoc += '\n'
return asciidoc
def makeValidUsageStatementsReturnedOnly(self, cmd, blockname, params):
asciidoc = ''
for param in params:
paramname = param.find('name')
paramtype = param.find('type')
typecategory = self.getTypeCategory(paramtype.text)
if param.attrib.get('noautovalidity') is None:
if paramtype.text == 'VkStructureType' and paramname.text == 'sType':
asciidoc += self.makeStructureType(blockname, param)
elif paramtype.text == 'void' and paramname.text == 'pNext':
asciidoc += self.makeStructureExtensionPointer(blockname, param)
if asciidoc == '':
return None
return asciidoc
def makeValidUsageStatements(self, cmd, blockname, params):
asciidoc = ''
handles = []
anyparentedhandlesoptional = False
parentdictionary = {}
arraylengths = set()
for param in params:
paramname = param.find('name')
paramtype = param.find('type')
typecategory = self.getTypeCategory(paramtype.text)
if param.attrib.get('noautovalidity') is None:
if paramtype.text == 'VkStructureType' and paramname.text == 'sType':
asciidoc += self.makeStructureType(blockname, param)
elif paramtype.text == 'void' and paramname.text == 'pNext':
asciidoc += self.makeStructureExtensionPointer(blockname, param)
else:
asciidoc += self.createValidationLineForParameter(blockname, param, params, typecategory)
if typecategory == 'handle':
handles.append(param)
arraylength = param.attrib.get('len')
if arraylength is not None:
for onelength in arraylength.split(','):
arraylengths.add(onelength)
if 'vkQueue' in blockname:
queuetypes = cmd.attrib.get('queues')
if queuetypes is not None:
queuebits = []
for queuetype in re.findall(r'([^,]+)', queuetypes):
queuebits.append(queuetype.replace('_',' '))
asciidoc += self.makeAnchor(blockname, None, 'queuetype')
asciidoc += 'The pname:queue must: support '
if len(queuebits) == 1:
asciidoc += queuebits[0]
else:
asciidoc += (', ').join(queuebits[:-1])
asciidoc += ', or '
asciidoc += queuebits[-1]
asciidoc += ' operations'
asciidoc += '\n'
if 'vkCmd' in blockname:
asciidoc += self.makeAnchor(blockname, 'commandBuffer', 'recording')
asciidoc += 'pname:commandBuffer must: be in the <<commandbuffers-lifecycle, recording state>>'
asciidoc += '\n'
asciidoc += self.makeAnchor(blockname, 'commandBuffer', 'cmdpool')
if blockname == 'vkCmdFillBuffer':
if 'VK_KHR_maintenance1' in self.registry.requiredextensions:
asciidoc += 'The sname:VkCommandPool that pname:commandBuffer was allocated from must: support transfer, graphics or compute operations\n'
else:
asciidoc += 'The sname:VkCommandPool that pname:commandBuffer was allocated from must: support graphics or compute operations\n'
else:
queuetypes = cmd.attrib.get('queues')
queuebits = []
for queuetype in re.findall(r'([^,]+)', queuetypes):
queuebits.append(queuetype.replace('_',' '))
asciidoc += 'The sname:VkCommandPool that pname:commandBuffer was allocated from must: support '
if len(queuebits) == 1:
asciidoc += queuebits[0]
else:
asciidoc += (', ').join(queuebits[:-1])
asciidoc += ', or '
asciidoc += queuebits[-1]
asciidoc += ' operations'
asciidoc += '\n'
renderpass = cmd.attrib.get('renderpass')
if renderpass != 'both':
asciidoc += self.makeAnchor(blockname, None, 'renderpass')
asciidoc += 'This command must: only be called '
asciidoc += renderpass
asciidoc += ' of a render pass instance'
asciidoc += '\n'
cmdbufferlevel = cmd.attrib.get('cmdbufferlevel')
if cmdbufferlevel != 'primary,secondary':
asciidoc += self.makeAnchor(blockname, None, 'bufferlevel')
asciidoc += 'pname:commandBuffer must: be a '
asciidoc += cmdbufferlevel
asciidoc += ' sname:VkCommandBuffer'
asciidoc += '\n'
for param in params:
paramname = param.find('name')
for arraylength in arraylengths:
if paramname.text == arraylength and param.attrib.get('optional') is None:
arrays = cmd.findall("param/[@len='" + arraylength + "'][@optional='true']")
optionalarrays = cmd.findall("param/[@len='" + arraylength + "'][@optional='true']")
optionalarrays.extend(cmd.findall("param/[@len='" + arraylength + "'][@noautovalidity='true']"))
asciidoc += self.makeAnchor(blockname, arraylength, 'arraylength')
if len(optionalarrays) == len(arrays) and len(optionalarrays) != 0:
asciidoc += 'If '
if len(optionalarrays) > 1:
asciidoc += 'any of '
for array in optionalarrays[:-1]:
asciidoc += self.makeParameterName(optionalarrays.find('name').text)
asciidoc += ', '
if len(optionalarrays) > 1:
asciidoc += 'and '
asciidoc += self.makeParameterName(optionalarrays[-1].find('name').text)
asciidoc += ' are '
else:
asciidoc += self.makeParameterName(optionalarrays[-1].find('name').text)
asciidoc += ' is '
asciidoc += 'not `NULL`, '
if self.paramIsPointer(param):
asciidoc += 'the value referenced by '
elif self.paramIsPointer(param):
asciidoc += 'The value referenced by '
asciidoc += self.makeParameterName(arraylength)
asciidoc += ' must: be greater than `0`'
asciidoc += '\n'
for param in handles:
paramtype = param.find('type')
if not self.paramIsPointer(param) or (param.text is not None and 'const' in param.text):
parent = self.getHandleParent(paramtype.text)
if parent is not None:
asciidoc += self.makeAsciiDocHandleParent(blockname, param, params)
asciidoc += self.makeAsciiDocHandlesCommonAncestor(blockname, handles, params)
if asciidoc == '':
return None
return asciidoc
def makeThreadSafetyBlock(self, cmd, paramtext):
paramdecl = ''
explicitexternsyncparams = cmd.findall(paramtext + "[@externsync]")
if (explicitexternsyncparams is not None):
for param in explicitexternsyncparams:
externsyncattribs = param.attrib.get('externsync')
paramname = param.find('name')
for externsyncattrib in externsyncattribs.split(','):
paramdecl += '* '
paramdecl += 'Host access to '
if externsyncattrib == 'true':
if self.paramIsArray(param):
paramdecl += 'each member of ' + self.makeParameterName(paramname.text)
elif self.paramIsPointer(param):
paramdecl += 'the object referenced by ' + self.makeParameterName(paramname.text)
else:
paramdecl += self.makeParameterName(paramname.text)
else:
paramdecl += 'pname:'
paramdecl += externsyncattrib
paramdecl += ' must: be externally synchronized\n'
if cmd.find('proto/name') is not None and 'vkCmd' in cmd.find('proto/name').text:
paramdecl += '* '
paramdecl += 'Host access to the sname:VkCommandPool that pname:commandBuffer was allocated from must: be externally synchronized'
paramdecl += '\n'
implicitexternsyncparams = cmd.find('implicitexternsyncparams')
if (implicitexternsyncparams is not None):
for elem in implicitexternsyncparams:
paramdecl += '* '
paramdecl += 'Host access to '
paramdecl += elem.text
paramdecl += ' must: be externally synchronized\n'
if (paramdecl == ''):
return None
else:
return paramdecl
def makeCommandPropertiesTableEntry(self, cmd, name):
if 'vkCmd' in name:
cmdbufferlevel = cmd.attrib.get('cmdbufferlevel')
cmdbufferlevel = (' + \n').join(cmdbufferlevel.title().split(','))
renderpass = cmd.attrib.get('renderpass')
renderpass = renderpass.capitalize()
if name == 'vkCmdFillBuffer':
if 'VK_KHR_maintenance1' in self.registry.requiredextensions:
queues = 'Transfer + \nGraphics + \nCompute'
else:
queues = 'Graphics + \nCompute'
else:
queues = cmd.attrib.get('queues')
queues = (' + \n').join(queues.title().split(','))
pipeline = cmd.attrib.get('pipeline')
if pipeline:
pipeline = pipeline.capitalize()
else:
pipeline = ''
return '|' + cmdbufferlevel + '|' + renderpass + '|' + queues + '|' + pipeline
elif 'vkQueue' in name:
queues = cmd.attrib.get('queues')
if queues is None:
queues = 'Any'
else:
queues = (' + \n').join(queues.upper().split(','))
return '|-|-|' + queues + '|-'
return None
def findRequiredEnums(self, enums):
out = []
for enum in enums:
ei = self.registry.lookupElementInfo(enum, self.registry.enumdict)
if (ei == None):
self.logMsg('warn', 'findRequiredEnums: enum', enum, 'is in an attribute list but is not in the registry')
elif (ei.required):
out.append(enum)
else:
self.logMsg('diag', 'findRequiredEnums: enum', enum, 'IS NOT required, skipping')
return out
def makeSuccessCodes(self, cmd, name):
successcodes = cmd.attrib.get('successcodes')
if successcodes is not None:
successcodes = self.findRequiredEnums(successcodes.split(','))
if len(successcodes) > 0:
return '* ename:' + '\n* ename:'.join(successcodes)
return None
def makeErrorCodes(self, cmd, name):
errorcodes = cmd.attrib.get('errorcodes')
if errorcodes is not None:
errorcodes = self.findRequiredEnums(errorcodes.split(','))
if len(errorcodes) > 0:
return '* ename:' + '\n* ename:'.join(errorcodes)
return None
def genCmd(self, cmdinfo, name):
OutputGenerator.genCmd(self, cmdinfo, name)
params = cmdinfo.elem.findall('param')
validity = self.makeValidUsageStatements(cmdinfo.elem, name, params)
threadsafety = self.makeThreadSafetyBlock(cmdinfo.elem, 'param')
commandpropertiesentry = self.makeCommandPropertiesTableEntry(cmdinfo.elem, name)
successcodes = self.makeSuccessCodes(cmdinfo.elem, name)
errorcodes = self.makeErrorCodes(cmdinfo.elem, name)
self.writeInclude('protos', name, validity, threadsafety, commandpropertiesentry, successcodes, errorcodes)
def genStruct(self, typeinfo, typename):
OutputGenerator.genStruct(self, typeinfo, typename)
if typeinfo.elem.attrib.get('returnedonly') is None:
params = typeinfo.elem.findall('member')
validity = self.makeValidUsageStatements(typeinfo.elem, typename, params)
threadsafety = self.makeThreadSafetyBlock(typeinfo.elem, 'member')
self.writeInclude('structs', typename, validity, threadsafety, None, None, None)
else:
params = typeinfo.elem.findall('member')
validity = self.makeValidUsageStatementsReturnedOnly(typeinfo.elem, typename, params)
self.writeInclude('structs', typename, validity, None, None, None, None)
def genGroup(self, groupinfo, groupName):
OutputGenerator.genGroup(self, groupinfo, groupName)
groupElem = groupinfo.elem
for elem in groupElem.findall('enum'):
name = elem.get('name')
ei = self.registry.lookupElementInfo(name, self.registry.enumdict)
ei.required = self.isEnumRequired(elem)
def genType(self, typeinfo, typename):
OutputGenerator.genType(self, typeinfo, typename)
category = typeinfo.elem.get('category')
if (category == 'struct' or category == 'union'):
self.genStruct(typeinfo, typename)