summaryrefslogtreecommitdiff
path: root/codegen/vulkan/scripts/hostsyncgenerator.py
diff options
context:
space:
mode:
Diffstat (limited to 'codegen/vulkan/scripts/hostsyncgenerator.py')
-rw-r--r--codegen/vulkan/scripts/hostsyncgenerator.py154
1 files changed, 154 insertions, 0 deletions
diff --git a/codegen/vulkan/scripts/hostsyncgenerator.py b/codegen/vulkan/scripts/hostsyncgenerator.py
new file mode 100644
index 00000000..a94db149
--- /dev/null
+++ b/codegen/vulkan/scripts/hostsyncgenerator.py
@@ -0,0 +1,154 @@
+#!/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.validity import ValidityCollection, ValidityEntry
+from spec_tools.util import getElemName
+
+
+class HostSynchronizationOutputGenerator(OutputGenerator):
+ """HostSynchronizationOutputGenerator - subclass of OutputGenerator.
+ Generates AsciiDoc includes of the externsync parameter table for the
+ fundamentals chapter of the API specification. Similar to
+ DocOutputGenerator.
+
+ ---- methods ----
+ HostSynchronizationOutputGenerator(errFile, warnFile, diagFile) - args as for
+ OutputGenerator. Defines additional internal state.
+ ---- methods overriding base class ----
+ genCmd(cmdinfo)"""
+ # Generate Host Synchronized Parameters in a table at the top of the spec
+
+ threadsafety = {
+ 'parameters': ValidityCollection(),
+ 'parameterlists': ValidityCollection(),
+ 'implicit': ValidityCollection()
+ }
+
+ def makeParameterName(self, name):
+ return 'pname:' + name
+
+ def makeFLink(self, name):
+ return 'flink:' + name
+
+ def writeBlock(self, basename, title, 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 contents:
+ write('.%s' % title, file=fp)
+ write('****', file=fp)
+ write(contents, file=fp, end='')
+ write('****', file=fp)
+ write('', file=fp)
+ else:
+ self.logMsg('diag', '# No contents for:', filename)
+
+ def writeInclude(self):
+ "Generates the asciidoc include files."""
+ self.writeBlock('parameters.txt',
+ 'Externally Synchronized Parameters',
+ self.threadsafety['parameters'])
+ self.writeBlock('parameterlists.txt',
+ 'Externally Synchronized Parameter Lists',
+ self.threadsafety['parameterlists'])
+ self.writeBlock('implicit.txt',
+ 'Implicit Externally Synchronized Parameters',
+ self.threadsafety['implicit'])
+
+ 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 genCmd(self, cmdinfo, name, alias):
+ "Generate command."
+ OutputGenerator.genCmd(self, cmdinfo, name, alias)
+
+ # @@@ (Jon) something needs to be done here to handle aliases, probably
+
+ self.makeThreadSafetyBlocks(cmdinfo.elem, 'param')
+
+ self.writeInclude()