summaryrefslogtreecommitdiff
path: root/codegen/vulkan/scripts/spirvcapgenerator.py
diff options
context:
space:
mode:
Diffstat (limited to 'codegen/vulkan/scripts/spirvcapgenerator.py')
-rw-r--r--codegen/vulkan/scripts/spirvcapgenerator.py308
1 files changed, 0 insertions, 308 deletions
diff --git a/codegen/vulkan/scripts/spirvcapgenerator.py b/codegen/vulkan/scripts/spirvcapgenerator.py
deleted file mode 100644
index 85740f34..00000000
--- a/codegen/vulkan/scripts/spirvcapgenerator.py
+++ /dev/null
@@ -1,308 +0,0 @@
-#!/usr/bin/python3 -i
-#
-# Copyright 2013-2021 The Khronos Group Inc.
-#
-# SPDX-License-Identifier: Apache-2.0
-
-from generator import OutputGenerator, write
-from spec_tools.attributes import ExternSyncEntry
-from spec_tools.util import getElemName
-
-import pdb
-
-def makeLink(link, altlink = None):
- """Create an asciidoctor link, optionally with altlink text
- if provided"""
-
- if altlink is not None:
- return '<<{},{}>>'.format(link, altlink)
- else:
- return '<<{}>>'.format(link)
-
-class SpirvCapabilityOutputGenerator(OutputGenerator):
- """SpirvCapabilityOutputGenerator - subclass of OutputGenerator.
- Generates AsciiDoc includes of the SPIR-V capabilities table for the
- features chapter of the API specification.
-
- ---- methods ----
- SpirvCapabilityOutputGenerator(errFile, warnFile, diagFile) - args as for
- OutputGenerator. Defines additional internal state.
- ---- methods overriding base class ----
- genCmd(cmdinfo)"""
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- def beginFile(self, genOpts):
- OutputGenerator.beginFile(self, genOpts)
-
- # Accumulate SPIR-V capability and feature information
- self.spirv = []
-
- def getCondition(self, enable):
- """Return a strings which is the condition under which an
- enable is supported.
-
- - enable - ElementTree corresponding to an <enable> XML tag for a
- SPIR-V capability or extension"""
-
- if enable.get('version'):
- # Turn VK_API_VERSION_1_0 -> VK_VERSION_1_0
- return enable.get('version').replace('API_', '')
- elif enable.get('extension'):
- return enable.get('extension')
- elif enable.get('struct') or enable.get('property'):
- return enable.get('requires')
- else:
- self.logMsg('error', 'Unrecognized SPIR-V enable')
- return ''
-
- def getConditions(self, enables):
- """Return a sorted list of strings which are conditions under which
- one or more of the enables is supported.
-
- - enables - ElementTree corresponding to a <spirvcapability> or
- <spirvextension> XML tag"""
-
- conditions = set()
- for enable in enables.findall('enable'):
- condition = self.getCondition(enable)
- if condition != None:
- conditions.add(condition)
- return sorted(conditions)
-
- def endFile(self):
- captable = []
- exttable = []
-
- # How to "indent" a pseudo-column for better use of space.
- # {captableindent} is defined in appendices/spirvenv.txt
- indent = '{captableindent}'
-
- for elem in self.spirv:
- conditions = self.getConditions(elem)
-
- # Combine all conditions for enables and surround the row with
- # them
- if len(conditions) > 0:
- condition_string = ','.join(conditions)
- prefix = [ 'ifdef::{}[]'.format(condition_string) ]
- suffix = [ 'endif::{}[]'.format(condition_string) ]
- else:
- prefix = []
- suffix = []
-
- body = []
-
- # Generate an anchor for each capability
- if elem.tag == 'spirvcapability':
- anchor = '[[spirvenv-capabilities-table-{}]]'.format(
- elem.get('name'))
- else:
- # <spirvextension> entries don't get anchors
- anchor = ''
-
- # First "cell" in a table row, and a break for the other "cells"
- body.append('| {}code:{} +'.format(anchor, elem.get('name')))
-
- # Iterate over each enable emitting a formatting tag for it
- # Protect the term if there is a version or extension
- # requirement, and if there are multiple enables (otherwise,
- # the ifdef protecting the entire row will suffice).
-
- enables = [e for e in elem.findall('enable')]
-
- remaining = len(enables)
- for subelem in enables:
- remaining -= 1
-
- # Sentinel value
- linktext = None
- if subelem.get('version'):
- version = subelem.get('version')
-
- # Convert API enum VK_API_VERSION_m_n to conditional
- # used for spec builds (VK_VERSION_m_n)
- enable = version.replace('API_', '')
- # Convert API enum to anchor for version appendices (versions-m.n)
- link = 'versions-' + version[-3:].replace('_', '.')
- altlink = version
-
- linktext = makeLink(link, altlink)
- elif subelem.get('extension'):
- extension = subelem.get('extension')
-
- enable = extension
- link = extension
- altlink = None
-
- # This uses the extension name macro, rather than
- # asciidoc markup
- linktext = '`apiext:{}`'.format(extension)
- elif subelem.get('struct'):
- struct = subelem.get('struct')
- feature = subelem.get('feature')
- requires = subelem.get('requires')
- alias = subelem.get('alias')
-
- link_name = feature
- # For cases, like bufferDeviceAddressEXT where need manual help
- if alias:
- link_name = alias
-
- enable = requires
- link = 'features-' + link_name
- altlink = 'sname:{}::pname:{}'.format(struct, feature)
-
- linktext = makeLink(link, altlink)
- else:
- property = subelem.get('property')
- member = subelem.get('member')
- requires = subelem.get('requires')
- value = subelem.get('value')
-
- enable = requires
- # Properties should have a "feature" prefix
- link = 'limits-' + member
- # Display the property value by itself if it is not a boolean (matches original table)
- # DenormPreserve is an example where it makes sense to just show the
- # member value as it is just a boolean and the name implies "true"
- # GroupNonUniformVote is an example where the whole name is too long
- # better to just display the value
- if value == "VK_TRUE":
- altlink = 'sname:{}::pname:{}'.format(property, member)
- else:
- altlink = '{}'.format(value)
-
- linktext = makeLink(link, altlink)
-
- # If there are no more enables, don't continue the last line
- if remaining > 0:
- continuation = ' +'
- else:
- continuation = ''
-
- # condition_string != enable is a small optimization
- if enable is not None and condition_string != enable:
- body.append('ifdef::{}[]'.format(enable))
- body.append('{} {}{}'.format(indent, linktext, continuation))
- if enable is not None and condition_string != enable:
- body.append('endif::{}[]'.format(enable))
-
- if elem.tag == 'spirvcapability':
- captable += prefix + body + suffix
- else:
- exttable += prefix + body + suffix
-
- # Generate the asciidoc include files
- self.writeBlock('captable.txt', captable)
- self.writeBlock('exttable.txt', exttable)
-
- # Finish processing in superclass
- OutputGenerator.endFile(self)
-
- def writeBlock(self, basename, contents):
- """Generate an include file.
-
- - directory - subdirectory to put file in
- - basename - base name of the file
- - contents - contents of the file (Asciidoc boilerplate aside)"""
-
- filename = self.genOpts.directory + '/' + basename
- self.logMsg('diag', '# Generating include file:', filename)
- with open(filename, 'w', encoding='utf-8') as fp:
- write(self.genOpts.conventions.warning_comment, file=fp)
-
- if len(contents) > 0:
- for str in contents:
- write(str, file=fp)
- else:
- self.logMsg('diag', '# No contents for:', filename)
-
- def paramIsArray(self, param):
- """Check if the parameter passed in is a pointer to an array."""
- return param.get('len') is not None
-
- def paramIsPointer(self, param):
- """Check if the parameter passed in is a pointer."""
- tail = param.find('type').tail
- return tail is not None and '*' in tail
-
- def makeThreadSafetyBlocks(self, cmd, paramtext):
- # See also makeThreadSafetyBlock in validitygenerator.py - similar but not entirely identical
- protoname = cmd.find('proto/name').text
-
- # Find and add any parameters that are thread unsafe
- explicitexternsyncparams = cmd.findall(paramtext + "[@externsync]")
- if explicitexternsyncparams is not None:
- for param in explicitexternsyncparams:
- self.makeThreadSafetyForParam(protoname, param)
-
- # Find and add any "implicit" parameters that are thread unsafe
- implicitexternsyncparams = cmd.find('implicitexternsyncparams')
- if implicitexternsyncparams is not None:
- for elem in implicitexternsyncparams:
- entry = ValidityEntry()
- entry += elem.text
- entry += ' in '
- entry += self.makeFLink(protoname)
- self.threadsafety['implicit'] += entry
-
- # Add a VU for any command requiring host synchronization.
- # This could be further parameterized, if a future non-Vulkan API
- # requires it.
- if self.genOpts.conventions.is_externsync_command(protoname):
- entry = ValidityEntry()
- entry += 'The sname:VkCommandPool that pname:commandBuffer was allocated from, in '
- entry += self.makeFLink(protoname)
- self.threadsafety['implicit'] += entry
-
- def makeThreadSafetyForParam(self, protoname, param):
- """Create thread safety validity for a single param of a command."""
- externsyncattribs = ExternSyncEntry.parse_externsync_from_param(param)
- param_name = getElemName(param)
-
- for attrib in externsyncattribs:
- entry = ValidityEntry()
- is_array = False
- if attrib.entirely_extern_sync:
- # "true" or "true_with_children"
- if self.paramIsArray(param):
- entry += 'Each element of the '
- is_array = True
- elif self.paramIsPointer(param):
- entry += 'The object referenced by the '
- else:
- entry += 'The '
-
- entry += self.makeParameterName(param_name)
- entry += ' parameter'
-
- if attrib.children_extern_sync:
- entry += ', and any child handles,'
-
- else:
- # parameter/member reference
- readable = attrib.get_human_readable(make_param_name=self.makeParameterName)
- is_array = (' element of ' in readable)
- entry += readable
-
- entry += ' in '
- entry += self.makeFLink(protoname)
-
- if is_array:
- self.threadsafety['parameterlists'] += entry
- else:
- self.threadsafety['parameters'] += entry
-
- def genSpirv(self, capinfo, name, alias):
- """Generate SPIR-V capabilities
-
- capinfo - dictionary entry for an XML <spirvcapability> or
- <spirvextension> element
- name - name attribute of capinfo.elem"""
-
- OutputGenerator.genSpirv(self, capinfo, name, alias)
-
- # Just accumulate each element, process in endFile
- self.spirv.append(capinfo.elem)