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 run(self):
     99         if len(self.argv) < 1:
    100             print("DispatchTableOpsSubcommand: <prefix> unspecified")
    101             return
    102 
    103         self.prefix = self.argv[0]
    104 
    105         if len(self.argv) > 2:
    106             print("DispatchTableOpsSubcommand: <prefix> [outfile]")
    107             return
    108 
    109         if len(self.argv) == 2:
    110             self.outfile = self.argv[1]
    111 
    112         super(DispatchTableOpsSubcommand, self).run()
    113 
    114     def generate_header(self):
    115         return "\n".join(["#include <vulkan/vulkan.h>",
    116                           "#include <vulkan/vk_layer.h>",
    117                           "#include <string.h>"])
    118 
    119     def _generate_init_dispatch(self, type):
    120         stmts = []
    121         func = []
    122         if type == "device":
    123             # GPA has to be first one and uses wrapped object
    124             stmts.append("memset(table, 0, sizeof(*table));")
    125             stmts.append("table->GetDeviceProcAddr =(PFN_vkGetDeviceProcAddr)  gpa(device,\"vkGetDeviceProcAddr\");")
    126             for proto in self.protos:
    127                 if proto.name == "CreateInstance" or proto.name == "EnumerateInstanceExtensionProperties" or proto.name == "EnumerateInstanceLayerProperties" or proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice":
    128                     continue
    129                 if proto.name != "GetDeviceProcAddr" and 'KHR' not in proto.name:
    130                     stmts.append("table->%s = (PFN_vk%s) gpa(device, \"vk%s\");" %
    131                         (proto.name, proto.name, proto.name))
    132             func.append("static inline void %s_init_device_dispatch_table(VkDevice device,"
    133                 % self.prefix)
    134             func.append("%s                                               VkLayerDispatchTable *table,"
    135                 % (" " * len(self.prefix)))
    136             func.append("%s                                               PFN_vkGetDeviceProcAddr gpa)"
    137                 % (" " * len(self.prefix)))
    138         else:
    139             stmts.append("table->GetInstanceProcAddr =(PFN_vkGetInstanceProcAddr)  gpa(instance,\"vkGetInstanceProcAddr\");")
    140             for proto in self.protos:
    141                 if proto.params[0].ty != "VkInstance" and proto.params[0].ty != "VkPhysicalDevice":
    142                     continue
    143                 if proto.name == "CreateDevice":
    144                     continue
    145                 if proto.name != "GetInstanceProcAddr" and 'KHR' not in proto.name:
    146                     stmts.append("table->%s = (PFN_vk%s) gpa(instance, \"vk%s\");" %
    147                           (proto.name, proto.name, proto.name))
    148             func.append("static inline void %s_init_instance_dispatch_table(" % self.prefix)
    149             func.append("%s        VkInstance instance," % (" " * len(self.prefix)))
    150             func.append("%s        VkLayerInstanceDispatchTable *table," % (" " * len(self.prefix)))
    151             func.append("%s        PFN_vkGetInstanceProcAddr gpa)" % (" " * len(self.prefix)))
    152         func.append("{")
    153         func.append("    %s" % "\n    ".join(stmts))
    154         func.append("}")
    155 
    156         return "\n".join(func)
    157 
    158     def generate_body(self):
    159         body = [self._generate_init_dispatch("device"),
    160                 self._generate_init_dispatch("instance")]
    161 
    162         return "\n\n".join(body)
    163 
    164 class WinDefFileSubcommand(Subcommand):
    165     def run(self):
    166         library_exports = {
    167                 "all": [],
    168                 "icd": [
    169                     "vk_icdGetInstanceProcAddr",
    170                 ],
    171                 "layer": [
    172                     "vkGetInstanceProcAddr",
    173                     "vkGetDeviceProcAddr",
    174                     "vkEnumerateInstanceLayerProperties",
    175                     "vkEnumerateInstanceExtensionProperties"
    176                 ],
    177                 "layer_multi": [
    178                     "multi2GetInstanceProcAddr",
    179                     "multi1GetDeviceProcAddr"
    180                 ]
    181         }
    182 
    183         if len(self.argv) < 2 or len(self.argv) > 3 or self.argv[1] not in library_exports:
    184             print("WinDefFileSubcommand: <library-name> {%s} [outfile]" %
    185                     "|".join(library_exports.keys()))
    186             return
    187 
    188         self.library = self.argv[0]
    189         if self.library == "VkLayer_multi":
    190             self.exports = library_exports["layer_multi"]
    191         else:
    192             self.exports = library_exports[self.argv[1]]
    193 
    194         if len(self.argv) == 3:
    195             self.outfile = self.argv[2]
    196 
    197         super(WinDefFileSubcommand, self).run()
    198 
    199     def generate_copyright(self):
    200         return """; THIS FILE IS GENERATED.  DO NOT EDIT.
    201 
    202 ;;;; Begin Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    203 ; Vulkan
    204 ;
    205 ; Copyright (c) 2015-2016 The Khronos Group Inc.
    206 ; Copyright (c) 2015-2016 Valve Corporation
    207 ; Copyright (c) 2015-2016 LunarG, Inc.
    208 ;
    209 ; Licensed under the Apache License, Version 2.0 (the "License");
    210 ; you may not use this file except in compliance with the License.
    211 ; You may obtain a copy of the License at
    212 ;
    213 ;     http://www.apache.org/licenses/LICENSE-2.0
    214 ;
    215 ; Unless required by applicable law or agreed to in writing, software
    216 ; distributed under the License is distributed on an "AS IS" BASIS,
    217 ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    218 ; See the License for the specific language governing permissions and
    219 ; limitations under the License.
    220 ;
    221 ;  Author: Courtney Goeltzenleuchter <courtney (at] LunarG.com>
    222 ;;;;  End Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"""
    223 
    224     def generate_header(self):
    225         return "; The following is required on Windows, for exporting symbols from the DLL"
    226 
    227     def generate_body(self):
    228         body = []
    229 
    230         body.append("LIBRARY " + self.library)
    231         body.append("EXPORTS")
    232 
    233         for proto in self.exports:
    234             if self.library != "VkLayerSwapchain" or proto != "vkEnumerateInstanceExtensionProperties" and proto != "vkEnumerateInstanceLayerProperties":
    235                 body.append( proto)
    236 
    237         return "\n".join(body)
    238 
    239 def main():
    240     wsi = {
    241             "Win32",
    242             "Android",
    243             "Xcb",
    244             "Xlib",
    245             "Wayland",
    246             "Mir"
    247     }
    248     subcommands = {
    249             "dispatch-table-ops": DispatchTableOpsSubcommand,
    250             "win-def-file": WinDefFileSubcommand,
    251     }
    252 
    253     if len(sys.argv) < 3 or sys.argv[1] not in wsi or sys.argv[2] not in subcommands:
    254         print("Usage: %s <wsi> <subcommand> [options]" % sys.argv[0])
    255         print
    256         print("Available sucommands are: %s" % " ".join(subcommands))
    257         exit(1)
    258 
    259     subcmd = subcommands[sys.argv[2]](sys.argv[3:])
    260     subcmd.run()
    261 
    262 if __name__ == "__main__":
    263     main()
    264