1# Copyright (C) 2017-2018 Intel Corporation. All Rights Reserved. 2# 3# Permission is hereby granted, free of charge, to any person obtaining a 4# copy of this software and associated documentation files (the 'Software'), 5# to deal in the Software without restriction, including without limitation 6# the rights to use, copy, modify, merge, publish, distribute, sublicense, 7# and/or sell copies of the Software, and to permit persons to whom the 8# Software is furnished to do so, subject to the following conditions: 9# 10# The above copyright notice and this permission notice (including the next 11# paragraph) shall be included in all copies or substantial portions of the 12# Software. 13# 14# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20# IN THE SOFTWARE. 21 22# Python source 23 24import itertools 25import os 26import sys 27from gen_common import * 28 29 30def main(args=sys.argv[1:]): 31 thisDir = os.path.dirname(os.path.realpath(__file__)) 32 parser = ArgumentParser('Generate files and initialization functions for all permutations of BackendPixelRate.') 33 parser.add_argument('--dim', help='gBackendPixelRateTable array dimensions', nargs='+', type=int, required=True) 34 parser.add_argument('--outdir', help='output directory', nargs='?', type=str, default=thisDir) 35 parser.add_argument('--split', help='how many lines of initialization per file [0=no split]', nargs='?', type=int, default='512') 36 parser.add_argument('--numfiles', help='how many output files to generate', nargs='?', type=int, default='0') 37 parser.add_argument('--cpp', help='Generate cpp file(s)', action='store_true', default=False) 38 parser.add_argument('--hpp', help='Generate hpp file', action='store_true', default=False) 39 parser.add_argument('--cmake', help='Generate cmake file', action='store_true', default=False) 40 parser.add_argument('--rast', help='Generate rasterizer functions instead of normal backend', action='store_true', default=False) 41 42 args = parser.parse_args(args) 43 44 45 class backendStrs : 46 def __init__(self) : 47 self.outFileName = 'gen_BackendPixelRate%s.cpp' 48 self.outHeaderName = 'gen_BackendPixelRate.hpp' 49 self.functionTableName = 'gBackendPixelRateTable' 50 self.funcInstanceHeader = ' = BackendPixelRate<SwrBackendTraits<' 51 self.template = 'gen_backend.cpp' 52 self.hpp_template = 'gen_header_init.hpp' 53 self.cmakeFileName = 'gen_backends.cmake' 54 self.cmakeSrcVar = 'GEN_BACKEND_SOURCES' 55 self.tableName = 'BackendPixelRate' 56 57 if args.rast: 58 self.outFileName = 'gen_rasterizer%s.cpp' 59 self.outHeaderName = 'gen_rasterizer.hpp' 60 self.functionTableName = 'gRasterizerFuncs' 61 self.funcInstanceHeader = ' = RasterizeTriangle<RasterizerTraits<' 62 self.template = 'gen_rasterizer.cpp' 63 self.cmakeFileName = 'gen_rasterizer.cmake' 64 self.cmakeSrcVar = 'GEN_RASTERIZER_SOURCES' 65 self.tableName = 'RasterizerFuncs' 66 67 68 backend = backendStrs() 69 70 output_list = [] 71 for x in args.dim: 72 output_list.append(list(range(x))) 73 74 # generate all permutations possible for template parameter inputs 75 output_combinations = list(itertools.product(*output_list)) 76 output_list = [] 77 78 # for each permutation 79 for x in range(len(output_combinations)): 80 # separate each template peram into its own list member 81 new_list = [output_combinations[x][i] for i in range(len(output_combinations[x]))] 82 tempStr = backend.functionTableName 83 #print each list member as an index in the multidimensional array 84 for i in new_list: 85 tempStr += '[' + str(i) + ']' 86 #map each entry in the permutation as its own string member, store as the template instantiation string 87 tempStr += backend.funcInstanceHeader + ','.join(map(str, output_combinations[x])) + '>>;' 88 #append the line of c++ code in the list of output lines 89 output_list.append(tempStr) 90 91 # how many files should we split the global template initialization into? 92 if (args.split == 0): 93 numFiles = 1 94 else: 95 numFiles = (len(output_list) + args.split - 1) // args.split 96 if (args.numfiles != 0): 97 numFiles = args.numfiles 98 linesPerFile = (len(output_list) + numFiles - 1) // numFiles 99 chunkedList = [output_list[x:x+linesPerFile] for x in range(0, len(output_list), linesPerFile)] 100 101 tmp_output_dir = MakeTmpDir('_codegen') 102 103 if not os.path.exists(args.outdir): 104 try: 105 os.makedirs(args.outdir) 106 except OSError as err: 107 if err.errno != errno.EEXIST: 108 print('ERROR: Could not create directory:', args.outdir, file=sys.stderr) 109 return 1 110 111 rval = 0 112 113 # generate .cpp files 114 try: 115 if args.cpp: 116 baseCppName = os.path.join(tmp_output_dir, backend.outFileName) 117 templateCpp = os.path.join(thisDir, 'templates', backend.template) 118 119 for fileNum in range(numFiles): 120 filename = baseCppName % str(fileNum) 121 MakoTemplateWriter.to_file( 122 templateCpp, 123 baseCppName % str(fileNum), 124 cmdline=sys.argv, 125 fileNum=fileNum, 126 funcList=chunkedList[fileNum]) 127 128 if args.hpp: 129 baseHppName = os.path.join(tmp_output_dir, backend.outHeaderName) 130 templateHpp = os.path.join(thisDir, 'templates', backend.hpp_template) 131 132 MakoTemplateWriter.to_file( 133 templateHpp, 134 baseHppName, 135 cmdline=sys.argv, 136 numFiles=numFiles, 137 filename=backend.outHeaderName, 138 tableName=backend.tableName) 139 140 # generate gen_backend.cmake file 141 if args.cmake: 142 templateCmake = os.path.join(thisDir, 'templates', 'gen_backend.cmake') 143 cmakeFile = os.path.join(tmp_output_dir, backend.cmakeFileName) 144 145 MakoTemplateWriter.to_file( 146 templateCmake, 147 cmakeFile, 148 cmdline=sys.argv, 149 srcVar=backend.cmakeSrcVar, 150 numFiles=numFiles, 151 baseCppName='${RASTY_GEN_SRC_DIR}/backends/' + os.path.basename(baseCppName)) 152 153 rval = CopyDirFilesIfDifferent(tmp_output_dir, args.outdir) 154 155 except: 156 rval = 1 157 158 finally: 159 DeleteDirTree(tmp_output_dir) 160 161 return rval 162 163if __name__ == '__main__': 164 sys.exit(main()) 165