Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/cuew/auto/cuew_gen.py')
-rw-r--r--extern/cuew/auto/cuew_gen.py591
1 files changed, 591 insertions, 0 deletions
diff --git a/extern/cuew/auto/cuew_gen.py b/extern/cuew/auto/cuew_gen.py
new file mode 100644
index 00000000000..a94525c52b1
--- /dev/null
+++ b/extern/cuew/auto/cuew_gen.py
@@ -0,0 +1,591 @@
+#!/usr/bin/env python3
+#
+# Copyright 2014 Blender Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License
+
+# This script generates either header or implementation file from
+# a CUDA header files.
+#
+# Usage: cuew hdr|impl [/path/to/cuda/includes]
+# - hdr means header file will be generated and printed to stdout.
+# - impl means implementation file will be generated and printed to stdout.
+# - /path/to/cuda/includes is a path to a folder with cuda.h and cudaGL.h
+# for which wrangler will be generated.
+
+import os
+import sys
+from cuda_errors import CUDA_ERRORS
+from pycparser import c_parser, c_ast, parse_file
+from subprocess import Popen, PIPE
+
+INCLUDE_DIR = "/usr/include"
+LIB = "CUEW"
+REAL_LIB = "CUDA"
+VERSION_MAJOR = "1"
+VERSION_MINOR = "2"
+COPYRIGHT = """/*
+ * Copyright 2011-2014 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */"""
+FILES = ["cuda.h", "cudaGL.h"]
+
+TYPEDEFS = []
+FUNC_TYPEDEFS = []
+SYMBOLS = []
+DEFINES = []
+DEFINES_V2 = []
+ERRORS = []
+
+
+class FuncDefVisitor(c_ast.NodeVisitor):
+ indent = 0
+ prev_complex = False
+ dummy_typedefs = ['size_t', 'CUdeviceptr']
+
+ def _get_quals_string(self, node):
+ if node.quals:
+ return ' '.join(node.quals) + ' '
+ return ''
+
+ def _get_ident_type(self, node):
+ if isinstance(node, c_ast.PtrDecl):
+ return self._get_ident_type(node.type.type) + '*'
+ if isinstance(node, c_ast.ArrayDecl):
+ return self._get_ident_type(node.type)
+ elif isinstance(node, c_ast.Struct):
+ if node.name:
+ return 'struct ' + node.name
+ else:
+ self.indent += 1
+ struct = self._stringify_struct(node)
+ self.indent -= 1
+ return "struct {\n" + \
+ struct + (" " * self.indent) + "}"
+ elif isinstance(node, c_ast.Union):
+ self.indent += 1
+ union = self._stringify_struct(node)
+ self.indent -= 1
+ return "union {\n" + union + (" " * self.indent) + "}"
+ elif isinstance(node, c_ast.Enum):
+ return 'enum ' + node.name
+ elif isinstance(node, c_ast.TypeDecl):
+ return self._get_ident_type(node.type)
+ else:
+ return node.names[0]
+
+ def _stringify_param(self, param):
+ param_type = param.type
+ result = self._get_quals_string(param)
+ result += self._get_ident_type(param_type)
+ if param.name:
+ result += ' ' + param.name
+ if isinstance(param_type, c_ast.ArrayDecl):
+ # TODO(sergey): Workaround to deal with the
+ # preprocessed file where array size got
+ # substituded.
+ dim = param_type.dim.value
+ if param.name == "reserved" and dim == "64":
+ dim = "CU_IPC_HANDLE_SIZE"
+ result += '[' + dim + ']'
+ return result
+
+ def _stringify_params(self, params):
+ result = []
+ for param in params:
+ result.append(self._stringify_param(param))
+ return ', '.join(result)
+
+ def _stringify_struct(self, node):
+ result = ""
+ children = node.children()
+ for child in children:
+ member = self._stringify_param(child[1])
+ result += (" " * self.indent) + member + ";\n"
+ return result
+
+ def _stringify_enum(self, node):
+ result = ""
+ children = node.children()
+ for child in children:
+ if isinstance(child[1], c_ast.EnumeratorList):
+ enumerators = child[1].enumerators
+ for enumerator in enumerators:
+ result += (" " * self.indent) + enumerator.name
+ if enumerator.value:
+ result += " = " + enumerator.value.value
+ result += ",\n"
+ if enumerator.name.startswith("CUDA_ERROR_"):
+ ERRORS.append(enumerator.name)
+ return result
+
+ def visit_Decl(self, node):
+ if node.type.__class__.__name__ == 'FuncDecl':
+ if isinstance(node.type, c_ast.FuncDecl):
+ func_decl = node.type
+ func_decl_type = func_decl.type
+
+ typedef = 'typedef '
+ symbol_name = None
+
+ if isinstance(func_decl_type, c_ast.TypeDecl):
+ symbol_name = func_decl_type.declname
+ typedef += self._get_quals_string(func_decl_type)
+ typedef += self._get_ident_type(func_decl_type.type)
+ typedef += ' CUDAAPI'
+ typedef += ' t' + symbol_name
+ elif isinstance(func_decl_type, c_ast.PtrDecl):
+ ptr_type = func_decl_type.type
+ symbol_name = ptr_type.declname
+ typedef += self._get_quals_string(ptr_type)
+ typedef += self._get_ident_type(func_decl_type)
+ typedef += ' CUDAAPI'
+ typedef += ' t' + symbol_name
+
+ typedef += '(' + \
+ self._stringify_params(func_decl.args.params) + \
+ ');'
+
+ SYMBOLS.append(symbol_name)
+ FUNC_TYPEDEFS.append(typedef)
+
+ def visit_Typedef(self, node):
+ if node.name in self.dummy_typedefs:
+ return
+
+ complex = False
+ type = self._get_ident_type(node.type)
+ quals = self._get_quals_string(node)
+
+ if isinstance(node.type.type, c_ast.Struct):
+ self.indent += 1
+ struct = self._stringify_struct(node.type.type)
+ self.indent -= 1
+ typedef = quals + type + " {\n" + struct + "} " + node.name
+ complex = True
+ elif isinstance(node.type.type, c_ast.Enum):
+ self.indent += 1
+ enum = self._stringify_enum(node.type.type)
+ self.indent -= 1
+ typedef = quals + type + " {\n" + enum + "} " + node.name
+ complex = True
+ else:
+ typedef = quals + type + " " + node.name
+ if complex or self.prev_complex:
+ typedef = "\ntypedef " + typedef + ";"
+ else:
+ typedef = "typedef " + typedef + ";"
+
+ TYPEDEFS.append(typedef)
+
+ self.prev_complex = complex
+
+
+def get_latest_cpp():
+ path_prefix = "/usr/bin"
+ for cpp_version in ["9", "8", "7", "6", "5", "4"]:
+ test_cpp = os.path.join(path_prefix, "cpp-4." + cpp_version)
+ if os.path.exists(test_cpp):
+ return test_cpp
+ return None
+
+
+def preprocess_file(filename, cpp_path):
+ args = [cpp_path, "-I./"]
+ if filename.endswith("GL.h"):
+ args.append("-DCUDAAPI= ")
+ args.append(filename)
+
+ try:
+ pipe = Popen(args,
+ stdout=PIPE,
+ universal_newlines=True)
+ text = pipe.communicate()[0]
+ except OSError as e:
+ raise RuntimeError("Unable to invoke 'cpp'. " +
+ 'Make sure its path was passed correctly\n' +
+ ('Original error: %s' % e))
+
+ return text
+
+
+def parse_files():
+ parser = c_parser.CParser()
+ cpp_path = get_latest_cpp()
+
+ for filename in FILES:
+ filepath = os.path.join(INCLUDE_DIR, filename)
+ dummy_typedefs = {}
+ text = preprocess_file(filepath, cpp_path)
+
+ if filepath.endswith("GL.h"):
+ dummy_typedefs = {
+ "CUresult": "int",
+ "CUgraphicsResource": "void *",
+ "CUdevice": "void *",
+ "CUcontext": "void *",
+ "CUdeviceptr": "void *",
+ "CUstream": "void *"
+ }
+
+ text = "typedef int GLint;\n" + text
+ text = "typedef unsigned int GLuint;\n" + text
+ text = "typedef unsigned int GLenum;\n" + text
+ text = "typedef long size_t;\n" + text
+
+ for typedef in sorted(dummy_typedefs):
+ text = "typedef " + dummy_typedefs[typedef] + " " + \
+ typedef + ";\n" + text
+
+ ast = parser.parse(text, filepath)
+
+ with open(filepath) as f:
+ lines = f.readlines()
+ for line in lines:
+ if line.startswith("#define"):
+ line = line[8:-1]
+ token = line.split()
+ if token[0] not in ("__cuda_cuda_h__",
+ "CUDA_CB",
+ "CUDAAPI"):
+ DEFINES.append(token)
+
+ for line in lines:
+ # TODO(sergey): Use better matching rule for _v2 symbols.
+ if line[0].isspace() and line.lstrip().startswith("#define"):
+ line = line[12:-1]
+ token = line.split()
+ if len(token) == 2 and token[1].endswith("_v2"):
+ DEFINES_V2.append(token)
+
+ v = FuncDefVisitor()
+ for typedef in dummy_typedefs:
+ v.dummy_typedefs.append(typedef)
+ v.visit(ast)
+
+ FUNC_TYPEDEFS.append('')
+ SYMBOLS.append('')
+
+
+def print_copyright():
+ print(COPYRIGHT)
+ print("")
+
+
+def open_header_guard():
+ print("#ifndef __%s_H__" % (LIB))
+ print("#define __%s_H__" % (LIB))
+ print("")
+ print("#ifdef __cplusplus")
+ print("extern \"C\" {")
+ print("#endif")
+ print("")
+
+
+def close_header_guard():
+ print("")
+ print("#ifdef __cplusplus")
+ print("}")
+ print("#endif")
+ print("")
+ print("#endif /* __%s_H__ */" % (LIB))
+
+
+def print_header():
+ print_copyright()
+ open_header_guard()
+
+ # Fot size_t.
+ print("#include <stdlib.h>")
+ print("")
+
+ print("/* Defines. */")
+ print("#define %s_VERSION_MAJOR %s" % (LIB, VERSION_MAJOR))
+ print("#define %s_VERSION_MINOR %s" % (LIB, VERSION_MINOR))
+ print("")
+ for define in DEFINES:
+ print('#define %s' % (' '.join(define)))
+ print("")
+
+ print("""/* Functions which changed 3.1 -> 3.2 for 64 bit stuff,
+ * the cuda library has both the old ones for compatibility and new
+ * ones with _v2 postfix,
+ */""")
+ for define in DEFINES_V2:
+ print('#define %s' % (' '.join(define)))
+ print("")
+
+ print("/* Types. */")
+
+ # We handle this specially because of the file is
+ # getting preprocessed.
+ print("""#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64)
+typedef unsigned long long CUdeviceptr;
+#else
+typedef unsigned int CUdeviceptr;
+#endif
+""")
+
+ for typedef in TYPEDEFS:
+ print('%s' % (typedef))
+
+ # TDO(sergey): This is only specific to CUDA wrapper.
+ print("""
+#ifdef _WIN32
+# define CUDAAPI __stdcall
+# define CUDA_CB __stdcall
+#else
+# define CUDAAPI
+# define CUDA_CB
+#endif
+""")
+
+ print("/* Function types. */")
+ for func_typedef in FUNC_TYPEDEFS:
+ print('%s' % (func_typedef))
+ print("")
+
+ print("/* Function declarations. */")
+ for symbol in SYMBOLS:
+ if symbol:
+ print('extern t%s *%s;' % (symbol, symbol))
+ else:
+ print("")
+
+ print("")
+ print("enum {")
+ print(" CUEW_SUCCESS = 0,")
+ print(" CUEW_ERROR_OPEN_FAILED = -1,")
+ print(" CUEW_ERROR_ATEXIT_FAILED = -2,")
+ print("};")
+ print("")
+ print("int %sInit(void);" % (LIB.lower()))
+ # TODO(sergey): Get rid of hardcoded CUresult.
+ print("const char *%sErrorString(CUresult result);" % (LIB.lower()))
+ print("const char *cuewCompilerPath(void);")
+ print("int cuewCompilerVersion(void);")
+
+ close_header_guard()
+
+
+def print_dl_wrapper():
+ print("""#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# define VC_EXTRALEAN
+# include <windows.h>
+
+/* Utility macros. */
+
+typedef HMODULE DynamicLibrary;
+
+# define dynamic_library_open(path) LoadLibrary(path)
+# define dynamic_library_close(lib) FreeLibrary(lib)
+# define dynamic_library_find(lib, symbol) GetProcAddress(lib, symbol)
+#else
+# include <dlfcn.h>
+
+typedef void* DynamicLibrary;
+
+# define dynamic_library_open(path) dlopen(path, RTLD_NOW)
+# define dynamic_library_close(lib) dlclose(lib)
+# define dynamic_library_find(lib, symbol) dlsym(lib, symbol)
+#endif
+""")
+
+
+def print_dl_helper_macro():
+ print("""#define %s_LIBRARY_FIND_CHECKED(name) \\
+ name = (t##name *)dynamic_library_find(lib, #name); \\
+ assert(name);
+
+#define %s_LIBRARY_FIND(name) \\
+ name = (t##name *)dynamic_library_find(lib, #name);
+
+static DynamicLibrary lib;""" % (REAL_LIB, REAL_LIB))
+ print("")
+
+
+def print_dl_close():
+ print("""static void %sExit(void) {
+ if(lib != NULL) {
+ /* Ignore errors. */
+ dynamic_library_close(lib);
+ lib = NULL;
+ }
+}""" % (LIB.lower()))
+ print("")
+
+
+def print_lib_path():
+ # TODO(sergey): get rid of hardcoded libraries.
+ print("""#ifdef _WIN32
+ /* Expected in c:/windows/system or similar, no path needed. */
+ const char *path = "nvcuda.dll";
+#elif defined(__APPLE__)
+ /* Default installation path. */
+ const char *path = "/usr/local/cuda/lib/libcuda.dylib";
+#else
+ const char *path = "libcuda.so";
+#endif""")
+
+
+def print_init_guard():
+ print(""" static int initialized = 0;
+ static int result = 0;
+ int error, driver_version;
+
+ if (initialized) {
+ return result;
+ }
+
+ initialized = 1;
+
+ error = atexit(cuewExit);
+ if (error) {
+ result = CUEW_ERROR_ATEXIT_FAILED;
+ return result;
+ }
+
+ /* Load library. */
+ lib = dynamic_library_open(path);
+
+ if (lib == NULL) {
+ result = CUEW_ERROR_OPEN_FAILED;
+ return result;
+ }""")
+ print("")
+
+
+def print_driver_version_guard():
+ # TODO(sergey): Currently it's hardcoded for CUDA only.
+ print(""" /* Detect driver version. */
+ driver_version = 1000;
+
+ %s_LIBRARY_FIND_CHECKED(cuDriverGetVersion);
+ if (cuDriverGetVersion) {
+ cuDriverGetVersion(&driver_version);
+ }
+
+ /* We require version 4.0. */
+ if (driver_version < 4000) {
+ result = CUEW_ERROR_OPEN_FAILED;
+ return result;
+ }""" % (REAL_LIB))
+
+
+def print_dl_init():
+ print("int %sInit(void) {" % (LIB.lower()))
+
+ print(" /* Library paths. */")
+ print_lib_path()
+ print_init_guard()
+ print_driver_version_guard()
+
+ print(" /* Fetch all function pointers. */")
+ for symbol in SYMBOLS:
+ if symbol:
+ print(" %s_LIBRARY_FIND(%s);" % (REAL_LIB, symbol))
+ else:
+ print("")
+
+ print("")
+ print(" result = CUEW_SUCCESS;")
+ print(" return result;")
+
+ print("}")
+
+
+def print_implementation():
+ print_copyright()
+
+ # TODO(sergey): Get rid of hardcoded header.
+ print("""#ifdef _MSC_VER
+# define snprintf _snprintf
+# define popen _popen
+# define pclose _pclose
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+""")
+ print("#include <cuew.h>")
+ print("#include <assert.h>")
+ print("#include <stdio.h>")
+ print("#include <string.h>")
+ print("#include <sys/stat.h>")
+ print("")
+
+ print_dl_wrapper()
+ print_dl_helper_macro()
+
+ print("/* Function definitions. */")
+ for symbol in SYMBOLS:
+ if symbol:
+ print('t%s *%s;' % (symbol, symbol))
+ else:
+ print("")
+ print("")
+
+ print_dl_close()
+
+ print("/* Implementation function. */")
+ print_dl_init()
+
+ print("")
+ # TODO(sergey): Get rid of hardcoded CUresult.
+ print("const char *%sErrorString(CUresult result) {" % (LIB.lower()))
+ print(" switch(result) {")
+ print(" case CUDA_SUCCESS: return \"No errors\";")
+
+ for error in ERRORS:
+ if error in CUDA_ERRORS:
+ str = CUDA_ERRORS[error]
+ else:
+ str = error[11:]
+ print(" case %s: return \"%s\";" % (error, str))
+
+ print(" default: return \"Unknown CUDA error value\";")
+ print(" }")
+ print("}")
+
+ from cuda_extra import extra_code
+ print(extra_code)
+
+if __name__ == "__main__":
+
+ if len(sys.argv) != 2 and len(sys.argv) != 3:
+ print("Usage: %s hdr|impl [/path/to/cuda/toolkit/include]" %
+ (sys.argv[0]))
+ exit(1)
+
+ if len(sys.argv) == 3:
+ INCLUDE_DIR = sys.argv[2]
+
+ parse_files()
+
+ if sys.argv[1] == "hdr":
+ print_header()
+ elif sys.argv[1] == "impl":
+ print_implementation()
+ else:
+ print("Unknown command %s" % (sys.argv[1]))
+ exit(1)