• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@lunarg.com>
21# Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
22# Author: Jon Ashburn <jon@lunarg.com>
23# Author: Gwan-gyeong Mun <kk.moon@samsung.com>
24
25import sys
26
27import vulkan
28
29def generate_get_proc_addr_check(name):
30    return "    if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \
31           "        return NULL;" % ((name,) * 3)
32
33class 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@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
97class 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
207class 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@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
282def 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
307if __name__ == "__main__":
308    main()
309