• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2#
3# Copyright (c) 2013-2016 The Khronos Group Inc.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import argparse, cProfile, pdb, string, sys, time
18from reg import *
19from generator import write
20
21#
22# LoaderAndValidationLayer Generator Additions
23from threading_generator import  ThreadGeneratorOptions, ThreadOutputGenerator
24from parameter_validation_generator import ParamCheckerGeneratorOptions, ParamCheckerOutputGenerator
25from unique_objects_generator import UniqueObjectsGeneratorOptions, UniqueObjectsOutputGenerator
26
27# Simple timer functions
28startTime = None
29
30def startTimer(timeit):
31    global startTime
32    startTime = time.clock()
33
34def endTimer(timeit, msg):
35    global startTime
36    endTime = time.clock()
37    if (timeit):
38        write(msg, endTime - startTime, file=sys.stderr)
39        startTime = None
40
41# Turn a list of strings into a regexp string matching exactly those strings
42def makeREstring(list):
43    return '^(' + '|'.join(list) + ')$'
44
45# Returns a directory of [ generator function, generator options ] indexed
46# by specified short names. The generator options incorporate the following
47# parameters:
48#
49# extensions - list of extension names to include.
50# protect - True if re-inclusion protection should be added to headers
51# directory - path to directory in which to generate the target(s)
52def makeGenOpts(extensions = [], protect = True, directory = '.'):
53    global genOpts
54    genOpts = {}
55
56    # Descriptive names for various regexp patterns used to select
57    # versions and extensions
58    allVersions     = allExtensions = '.*'
59    noVersions      = noExtensions = None
60
61    addExtensions     = makeREstring(extensions)
62    removeExtensions  = makeREstring([])
63
64    # Copyright text prefixing all headers (list of strings).
65    prefixStrings = [
66        '/*',
67        '** Copyright (c) 2015-2016 The Khronos Group Inc.',
68        '**',
69        '** Licensed under the Apache License, Version 2.0 (the "License");',
70        '** you may not use this file except in compliance with the License.',
71        '** You may obtain a copy of the License at',
72        '**',
73        '**     http://www.apache.org/licenses/LICENSE-2.0',
74        '**',
75        '** Unless required by applicable law or agreed to in writing, software',
76        '** distributed under the License is distributed on an "AS IS" BASIS,',
77        '** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.',
78        '** See the License for the specific language governing permissions and',
79        '** limitations under the License.',
80        '*/',
81        ''
82    ]
83
84    # Text specific to Vulkan headers
85    vkPrefixStrings = [
86        '/*',
87        '** This header is generated from the Khronos Vulkan XML API Registry.',
88        '**',
89        '*/',
90        ''
91    ]
92
93    # Defaults for generating re-inclusion protection wrappers (or not)
94    protectFile = protect
95    protectFeature = protect
96    protectProto = protect
97
98    #
99    # LoaderAndValidationLayer Generators
100    # Options for threading layer
101    genOpts['thread_check.h'] = [
102          ThreadOutputGenerator,
103          ThreadGeneratorOptions(
104            filename          = 'thread_check.h',
105            directory         = directory,
106            apiname           = 'vulkan',
107            profile           = None,
108            versions          = allVersions,
109            emitversions      = allVersions,
110            defaultExtensions = 'vulkan',
111            addExtensions     = addExtensions,
112            removeExtensions  = removeExtensions,
113            prefixText        = prefixStrings + vkPrefixStrings,
114            protectFeature    = False,
115            apicall           = 'VKAPI_ATTR ',
116            apientry          = 'VKAPI_CALL ',
117            apientryp         = 'VKAPI_PTR *',
118            alignFuncParam    = 48)
119        ]
120
121    # Options for parameter validation layer
122    genOpts['parameter_validation.h'] = [
123          ParamCheckerOutputGenerator,
124          ParamCheckerGeneratorOptions(
125            filename          = 'parameter_validation.h',
126            directory         = directory,
127            apiname           = 'vulkan',
128            profile           = None,
129            versions          = allVersions,
130            emitversions      = allVersions,
131            defaultExtensions = 'vulkan',
132            addExtensions     = addExtensions,
133            removeExtensions  = removeExtensions,
134            prefixText        = prefixStrings + vkPrefixStrings,
135            protectFeature    = False,
136            apicall           = 'VKAPI_ATTR ',
137            apientry          = 'VKAPI_CALL ',
138            apientryp         = 'VKAPI_PTR *',
139            alignFuncParam    = 48)
140        ]
141
142    # Options for unique objects layer
143    genOpts['unique_objects_wrappers.h'] = [
144          UniqueObjectsOutputGenerator,
145          UniqueObjectsGeneratorOptions(
146            filename          = 'unique_objects_wrappers.h',
147            directory         = directory,
148            apiname           = 'vulkan',
149            profile           = None,
150            versions          = allVersions,
151            emitversions      = allVersions,
152            defaultExtensions = 'vulkan',
153            addExtensions     = addExtensions,
154            removeExtensions  = removeExtensions,
155            prefixText        = prefixStrings + vkPrefixStrings,
156            protectFeature    = False,
157            apicall           = 'VKAPI_ATTR ',
158            apientry          = 'VKAPI_CALL ',
159            apientryp         = 'VKAPI_PTR *',
160            alignFuncParam    = 48)
161        ]
162
163# Generate a target based on the options in the matching genOpts{} object.
164# This is encapsulated in a function so it can be profiled and/or timed.
165# The args parameter is an parsed argument object containing the following
166# fields that are used:
167#   target - target to generate
168#   directory - directory to generate it in
169#   protect - True if re-inclusion wrappers should be created
170#   extensions - list of additional extensions to include in generated
171#   interfaces
172def genTarget(args):
173    global genOpts
174
175    # Create generator options with specified parameters
176    makeGenOpts(extensions = args.extension,
177                protect = args.protect,
178                directory = args.directory)
179
180    if (args.target in genOpts.keys()):
181        createGenerator = genOpts[args.target][0]
182        options = genOpts[args.target][1]
183
184        write('* Building', options.filename, file=sys.stderr)
185
186        startTimer(args.time)
187        gen = createGenerator(errFile=errWarn,
188                              warnFile=errWarn,
189                              diagFile=diag)
190        reg.setGenerator(gen)
191        reg.apiGen(options)
192        write('* Generated', options.filename, file=sys.stderr)
193        endTimer(args.time, '* Time to generate ' + options.filename + ' =')
194    else:
195        write('No generator options for unknown target:',
196              args.target, file=sys.stderr)
197
198# -extension name - may be a single extension name, a a space-separated list
199# of names, or a regular expression.
200if __name__ == '__main__':
201    parser = argparse.ArgumentParser()
202
203    parser.add_argument('-extension', action='append',
204                        default=[],
205                        help='Specify an extension or extensions to add to targets')
206    parser.add_argument('-debug', action='store_true',
207                        help='Enable debugging')
208    parser.add_argument('-dump', action='store_true',
209                        help='Enable dump to stderr')
210    parser.add_argument('-diagfile', action='store',
211                        default=None,
212                        help='Write diagnostics to specified file')
213    parser.add_argument('-errfile', action='store',
214                        default=None,
215                        help='Write errors and warnings to specified file instead of stderr')
216    parser.add_argument('-noprotect', dest='protect', action='store_false',
217                        help='Disable inclusion protection in output headers')
218    parser.add_argument('-profile', action='store_true',
219                        help='Enable profiling')
220    parser.add_argument('-registry', action='store',
221                        default='vk.xml',
222                        help='Use specified registry file instead of vk.xml')
223    parser.add_argument('-time', action='store_true',
224                        help='Enable timing')
225    parser.add_argument('-validate', action='store_true',
226                        help='Enable group validation')
227    parser.add_argument('-o', action='store', dest='directory',
228                        default='.',
229                        help='Create target and related files in specified directory')
230    parser.add_argument('target', metavar='target', nargs='?',
231                        help='Specify target')
232
233    args = parser.parse_args()
234
235    # This splits arguments which are space-separated lists
236    args.extension = [name for arg in args.extension for name in arg.split()]
237
238    # Load & parse registry
239    reg = Registry()
240
241    startTimer(args.time)
242    tree = etree.parse(args.registry)
243    endTimer(args.time, '* Time to make ElementTree =')
244
245    startTimer(args.time)
246    reg.loadElementTree(tree)
247    endTimer(args.time, '* Time to parse ElementTree =')
248
249    if (args.validate):
250        reg.validateGroups()
251
252    if (args.dump):
253        write('* Dumping registry to regdump.txt', file=sys.stderr)
254        reg.dumpReg(filehandle = open('regdump.txt','w'))
255
256    # create error/warning & diagnostic files
257    if (args.errfile):
258        errWarn = open(args.errfile, 'w')
259    else:
260        errWarn = sys.stderr
261
262    if (args.diagfile):
263        diag = open(args.diagfile, 'w')
264    else:
265        diag = None
266
267    if (args.debug):
268        pdb.run('genTarget(args)')
269    elif (args.profile):
270        import cProfile, pstats
271        cProfile.run('genTarget(args)', 'profile.txt')
272        p = pstats.Stats('profile.txt')
273        p.strip_dirs().sort_stats('time').print_stats(50)
274    else:
275        genTarget(args)
276