vk-generate.py revision 11cd02dfb91661c65134cac258cf5924270e9d2b
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 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
164class 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@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
239def 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
262if __name__ == "__main__":
263    main()
264