1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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()
|