Home | History | Annotate | Download | only in src
      1 #!/usr/bin/env python3
      2 #
      3 # Copyright (c) 2015-2016 The Khronos Group Inc.
      4 # Copyright (c) 2015-2016 Valve Corporation
      5 # Copyright (c) 2015-2016 LunarG, Inc.
      6 # Copyright (c) 2015-2016 Google Inc.
      7 #
      8 # Licensed under the Apache License, Version 2.0 (the "License");
      9 # you may not use this file except in compliance with the License.
     10 # You may obtain a copy of the License at
     11 #
     12 #     http://www.apache.org/licenses/LICENSE-2.0
     13 #
     14 # Unless required by applicable law or agreed to in writing, software
     15 # distributed under the License is distributed on an "AS IS" BASIS,
     16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     17 # See the License for the specific language governing permissions and
     18 # limitations under the License.
     19 #
     20 # Author: Chia-I Wu <olv (at] lunarg.com>
     21 # Author: Courtney Goeltzenleuchter <courtney (at] LunarG.com>
     22 # Author: Jon Ashburn <jon (at] lunarg.com>
     23 # Author: Gwan-gyeong Mun <kk.moon (at] samsung.com>
     24 
     25 import sys
     26 
     27 import vulkan
     28 
     29 def generate_get_proc_addr_check(name):
     30     return "    if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \
     31            "        return NULL;" % ((name,) * 3)
     32 
     33 class Subcommand(object):
     34     def __init__(self, argv):
     35         self.argv = argv
     36         self.headers = vulkan.headers
     37         self.protos = vulkan.protos
     38         self.outfile = None
     39 
     40     def run(self):
     41         if self.outfile:
     42             with open(self.outfile, "w") as outfile:
     43                 outfile.write(self.generate())
     44         else:
     45             print(self.generate())
     46 
     47     def generate(self):
     48         copyright = self.generate_copyright()
     49         header = self.generate_header()
     50         body = self.generate_body()
     51         footer = self.generate_footer()
     52 
     53         contents = []
     54         if copyright:
     55             contents.append(copyright)
     56         if header:
     57             contents.append(header)
     58         if body:
     59             contents.append(body)
     60         if footer:
     61             contents.append(footer)
     62 
     63         return "\n\n".join(contents)
     64 
     65     def generate_copyright(self):
     66         return """/* THIS FILE IS GENERATED.  DO NOT EDIT. */
     67 
     68 /*
     69  * Copyright (c) 2015-2016 The Khronos Group Inc.
     70  * Copyright (c) 2015-2016 Valve Corporation
     71  * Copyright (c) 2015-2016 LunarG, Inc.
     72  *
     73  * Licensed under the Apache License, Version 2.0 (the "License");
     74  * you may not use this file except in compliance with the License.
     75  * You may obtain a copy of the License at
     76  *
     77  *     http://www.apache.org/licenses/LICENSE-2.0
     78  *
     79  * Unless required by applicable law or agreed to in writing, software
     80  * distributed under the License is distributed on an "AS IS" BASIS,
     81  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     82  * See the License for the specific language governing permissions and
     83  * limitations under the License.
     84  *
     85  * Author: Courtney Goeltzenleuchter <courtney (at] LunarG.com>
     86  */"""
     87 
     88     def generate_header(self):
     89         return "\n".join(["#include <" + h + ">" for h in self.headers])
     90 
     91     def generate_body(self):
     92         pass
     93 
     94     def generate_footer(self):
     95         pass
     96 
     97 class DispatchTableOpsSubcommand(Subcommand):
     98     def __init__(self, argv):
     99         self.argv = argv
    100         self.headers = vulkan.headers_all
    101         self.protos = vulkan.protos_all
    102         self.outfile = None
    103 
    104     def run(self):
    105         if len(self.argv) < 1:
    106             print("DispatchTableOpsSubcommand: <prefix> unspecified")
    107             return
    108 
    109         self.prefix = self.argv[0]
    110 
    111         if len(self.argv) > 2:
    112             print("DispatchTableOpsSubcommand: <prefix> [outfile]")
    113             return
    114 
    115         if len(self.argv) == 2:
    116             self.outfile = self.argv[1]
    117 
    118         super(DispatchTableOpsSubcommand, self).run()
    119 
    120     def generate_header(self):
    121         return "\n".join(["#include <vulkan/vulkan.h>",
    122                           "#include <vulkan/vk_layer.h>",
    123                           "#include <string.h>"])
    124 
    125     def _generate_init_dispatch(self, type):
    126         stmts = []
    127         func = []
    128         if type == "device":
    129             # GPA has to be first one and uses wrapped object
    130             stmts.append("    memset(table, 0, sizeof(*table));")
    131             stmts.append("    // Core device function pointers")
    132             stmts.append("    table->GetDeviceProcAddr = (PFN_vkGetDeviceProcAddr) gpa(device, \"vkGetDeviceProcAddr\");")
    133 
    134             for proto in self.protos:
    135                 if proto.name == "CreateInstance" or proto.name == "EnumerateInstanceExtensionProperties" or \
    136                   proto.name == "EnumerateInstanceLayerProperties" or proto.params[0].ty == "VkInstance" or \
    137                   proto.params[0].ty == "VkPhysicalDevice" or proto.name == "GetDeviceProcAddr":
    138                     continue
    139                 if proto.name == "GetMemoryWin32HandleNV":
    140                     stmts.append("#ifdef VK_USE_PLATFORM_WIN32_KHR")
    141                     stmts.append("    table->%s = (PFN_vk%s) gpa(device, \"vk%s\");" %
    142                             (proto.name, proto.name, proto.name))
    143                     stmts.append("#endif // VK_USE_PLATFORM_WIN32_KHR")
    144                 else:
    145                     stmts.append("    table->%s = (PFN_vk%s) gpa(device, \"vk%s\");" %
    146                             (proto.name, proto.name, proto.name))
    147             func.append("static inline void %s_init_device_dispatch_table(VkDevice device,"
    148                 % self.prefix)
    149             func.append("%s                                               VkLayerDispatchTable *table,"
    150                 % (" " * len(self.prefix)))
    151             func.append("%s                                               PFN_vkGetDeviceProcAddr gpa)"
    152                 % (" " * len(self.prefix)))
    153         else:
    154             stmts.append("    memset(table, 0, sizeof(*table));")
    155             stmts.append("    // Core instance function pointers")
    156             stmts.append("    table->GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) gpa(instance, \"vkGetInstanceProcAddr\");")
    157 
    158             for proto in self.protos:
    159                 if proto.params[0].ty != "VkInstance" and proto.params[0].ty != "VkPhysicalDevice" or \
    160                   proto.name == "CreateDevice" or proto.name == "GetInstanceProcAddr":
    161                     continue
    162                 # Protect platform-dependent APIs with #ifdef
    163                 if 'KHR' in proto.name and 'Win32' in proto.name:
    164                     stmts.append("#ifdef VK_USE_PLATFORM_WIN32_KHR")
    165                 if 'KHR' in proto.name and 'Xlib' in proto.name:
    166                     stmts.append("#ifdef VK_USE_PLATFORM_XLIB_KHR")
    167                 if 'KHR' in proto.name and 'Xcb' in proto.name:
    168                     stmts.append("#ifdef VK_USE_PLATFORM_XCB_KHR")
    169                 if 'KHR' in proto.name and 'Mir' in proto.name:
    170                     stmts.append("#ifdef VK_USE_PLATFORM_MIR_KHR")
    171                 if 'KHR' in proto.name and 'Wayland' in proto.name:
    172                     stmts.append("#ifdef VK_USE_PLATFORM_WAYLAND_KHR")
    173                 if 'KHR' in proto.name and 'Android' in proto.name:
    174                     stmts.append("#ifdef VK_USE_PLATFORM_ANDROID_KHR")
    175                 # Output dispatch table entry
    176                 stmts.append("    table->%s = (PFN_vk%s) gpa(instance, \"vk%s\");" %
    177                       (proto.name, proto.name, proto.name))
    178                 # If entry was protected by an #ifdef, close with a #endif
    179                 if 'KHR' in proto.name and 'Win32' in proto.name:
    180                     stmts.append("#endif // VK_USE_PLATFORM_WIN32_KHR")
    181                 if 'KHR' in proto.name and 'Xlib' in proto.name:
    182                     stmts.append("#endif // VK_USE_PLATFORM_XLIB_KHR")
    183                 if 'KHR' in proto.name and 'Xcb' in proto.name:
    184                     stmts.append("#endif // VK_USE_PLATFORM_XCB_KHR")
    185                 if 'KHR' in proto.name and 'Mir' in proto.name:
    186                     stmts.append("#endif // VK_USE_PLATFORM_MIR_KHR")
    187                 if 'KHR' in proto.name and 'Wayland' in proto.name:
    188                     stmts.append("#endif // VK_USE_PLATFORM_WAYLAND_KHR")
    189                 if 'KHR' in proto.name and 'Android' in proto.name:
    190                     stmts.append("#endif // VK_USE_PLATFORM_ANDROID_KHR")
    191             func.append("static inline void %s_init_instance_dispatch_table(" % self.prefix)
    192             func.append("%s        VkInstance instance," % (" " * len(self.prefix)))
    193             func.append("%s        VkLayerInstanceDispatchTable *table," % (" " * len(self.prefix)))
    194             func.append("%s        PFN_vkGetInstanceProcAddr gpa)" % (" " * len(self.prefix)))
    195         func.append("{")
    196         func.append("%s" % "\n".join(stmts))
    197         func.append("}")
    198 
    199         return "\n".join(func)
    200 
    201     def generate_body(self):
    202         body = [self._generate_init_dispatch("device"),
    203                 self._generate_init_dispatch("instance")]
    204 
    205         return "\n\n".join(body)
    206 
    207 class WinDefFileSubcommand(Subcommand):
    208     def run(self):
    209         library_exports = {
    210                 "all": [],
    211                 "icd": [
    212                     "vk_icdGetInstanceProcAddr",
    213                 ],
    214                 "layer": [
    215                     "vkGetInstanceProcAddr",
    216                     "vkGetDeviceProcAddr",
    217                     "vkEnumerateInstanceLayerProperties",
    218                     "vkEnumerateInstanceExtensionProperties"
    219                 ],
    220                 "layer_multi": [
    221                     "multi2GetInstanceProcAddr",
    222                     "multi1GetDeviceProcAddr"
    223                 ]
    224         }
    225 
    226         if len(self.argv) < 2 or len(self.argv) > 3 or self.argv[1] not in library_exports:
    227             print("WinDefFileSubcommand: <library-name> {%s} [outfile]" %
    228                     "|".join(library_exports.keys()))
    229             return
    230 
    231         self.library = self.argv[0]
    232         if self.library == "VkLayer_multi":
    233             self.exports = library_exports["layer_multi"]
    234         else:
    235             self.exports = library_exports[self.argv[1]]
    236 
    237         if len(self.argv) == 3:
    238             self.outfile = self.argv[2]
    239 
    240         super(WinDefFileSubcommand, self).run()
    241 
    242     def generate_copyright(self):
    243         return """; THIS FILE IS GENERATED.  DO NOT EDIT.
    244 
    245 ;;;; Begin Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    246 ; Vulkan
    247 ;
    248 ; Copyright (c) 2015-2016 The Khronos Group Inc.
    249 ; Copyright (c) 2015-2016 Valve Corporation
    250 ; Copyright (c) 2015-2016 LunarG, Inc.
    251 ;
    252 ; Licensed under the Apache License, Version 2.0 (the "License");
    253 ; you may not use this file except in compliance with the License.
    254 ; You may obtain a copy of the License at
    255 ;
    256 ;     http://www.apache.org/licenses/LICENSE-2.0
    257 ;
    258 ; Unless required by applicable law or agreed to in writing, software
    259 ; distributed under the License is distributed on an "AS IS" BASIS,
    260 ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    261 ; See the License for the specific language governing permissions and
    262 ; limitations under the License.
    263 ;
    264 ;  Author: Courtney Goeltzenleuchter <courtney (at] LunarG.com>
    265 ;;;;  End Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"""
    266 
    267     def generate_header(self):
    268         return "; The following is required on Windows, for exporting symbols from the DLL"
    269 
    270     def generate_body(self):
    271         body = []
    272 
    273         body.append("LIBRARY " + self.library)
    274         body.append("EXPORTS")
    275 
    276         for proto in self.exports:
    277             if self.library != "VkLayerSwapchain" or proto != "vkEnumerateInstanceExtensionProperties" and proto != "vkEnumerateInstanceLayerProperties":
    278                 body.append( proto)
    279 
    280         return "\n".join(body)
    281 
    282 def main():
    283     wsi = {
    284             "Win32",
    285             "Android",
    286             "Xcb",
    287             "Xlib",
    288             "Wayland",
    289             "Mir",
    290             "Display",
    291             "AllPlatforms"
    292     }
    293     subcommands = {
    294             "dispatch-table-ops": DispatchTableOpsSubcommand,
    295             "win-def-file": WinDefFileSubcommand,
    296     }
    297 
    298     if len(sys.argv) < 3 or sys.argv[1] not in wsi or sys.argv[2] not in subcommands:
    299         print("Usage: %s <wsi> <subcommand> [options]" % sys.argv[0])
    300         print
    301         print("Available sucommands are: %s" % " ".join(subcommands))
    302         exit(1)
    303 
    304     subcmd = subcommands[sys.argv[2]](sys.argv[3:])
    305     subcmd.run()
    306 
    307 if __name__ == "__main__":
    308     main()
    309