blob: 6df17b9be6587920c32b4b394791f9beadf79003 [file] [log] [blame]
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -06001#!/usr/bin/env python3
2#
Jon Ashburn23d36b12016-02-02 17:47:28 -07003# Copyright (c) 2015-2016 The Khronos Group Inc.
4# Copyright (c) 2015-2016 Valve Corporation
5# Copyright (c) 2015-2016 LunarG, Inc.
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -06006#
Jon Ashburn3ebf1252016-04-19 11:30:31 -06007# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -060010#
Jon Ashburn3ebf1252016-04-19 11:30:31 -060011# http://www.apache.org/licenses/LICENSE-2.0
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -060012#
Jon Ashburn3ebf1252016-04-19 11:30:31 -060013# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -060018#
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060019# Author: Jon Ashburn <jon@lunarg.com>
20#
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -060021
22import os, sys
23
24# add main repo directory so vulkan.py can be imported. This needs to be a complete path.
25ld_path = os.path.dirname(os.path.abspath(__file__))
26main_path = os.path.abspath(ld_path + "/../")
27sys.path.append(main_path)
28
29import vulkan
30
31def generate_get_proc_addr_check(name):
32 return " if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \
33 " return NULL;" % ((name,) * 3)
34
35class Subcommand(object):
36 def __init__(self, argv):
37 self.argv = argv
38 self.headers = vulkan.headers
39 self.protos = vulkan.protos
40
41 def run(self):
42 print(self.generate())
43
Jon Ashburn82974f42015-05-05 09:37:01 -060044 def _requires_special_trampoline_code(self, name):
Eric Engestromeae5ee42016-04-02 22:06:24 +010045 # Don't be cute trying to use a general rule to programmatically populate this list
Jon Ashburn82974f42015-05-05 09:37:01 -060046 # it just obsfucates what is going on!
Ian Elliott7e40db92015-08-21 15:09:33 -060047 wsi_creates_dispatchable_object = ["CreateSwapchainKHR"]
Chia-I Wu3432a0c2015-10-27 18:04:07 +080048 creates_dispatchable_object = ["CreateDevice", "GetDeviceQueue", "AllocateCommandBuffers"] + wsi_creates_dispatchable_object
Jon Ashburn82974f42015-05-05 09:37:01 -060049 if name in creates_dispatchable_object:
50 return True
51 else:
52 return False
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -060053
Jon Ashburn82974f42015-05-05 09:37:01 -060054 def _is_loader_non_trampoline_entrypoint(self, proto):
Jon Ashburn8d1b0b52015-05-18 13:20:15 -060055 if proto.name in ["GetDeviceProcAddr", "EnumeratePhysicalDevices", "EnumerateLayers", "DbgRegisterMsgCallback", "DbgUnregisterMsgCallback", "DbgSetGlobalOption", "DestroyInstance"]:
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -060056 return True
57 return not self.is_dispatchable_object_first_param(proto)
58
59
60 def is_dispatchable_object_first_param(self, proto):
61 in_objs = proto.object_in_params()
62 non_dispatch_objs = []
63 param0 = proto.params[0]
64 return (len(in_objs) > 0) and (in_objs[0].ty == param0.ty) and (param0.ty not in non_dispatch_objs)
65
66 def generate(self):
67 copyright = self.generate_copyright()
68 header = self.generate_header()
69 body = self.generate_body()
70 footer = self.generate_footer()
71
72 contents = []
73 if copyright:
74 contents.append(copyright)
75 if header:
76 contents.append(header)
77 if body:
78 contents.append(body)
79 if footer:
80 contents.append(footer)
81
82 return "\n\n".join(contents)
83
84 def generate_copyright(self):
85 return """/* THIS FILE IS GENERATED. DO NOT EDIT. */
86
87/*
Jon Ashburn23d36b12016-02-02 17:47:28 -070088 * Copyright (c) 2015-2016 The Khronos Group Inc.
89 * Copyright (c) 2015-2016 Valve Corporation
90 * Copyright (c) 2015-2016 LunarG, Inc.
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -060091 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060092 * Licensed under the Apache License, Version 2.0 (the "License");
93 * you may not use this file except in compliance with the License.
94 * You may obtain a copy of the License at
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -060095 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060096 * http://www.apache.org/licenses/LICENSE-2.0
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -060097 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060098 * Unless required by applicable law or agreed to in writing, software
99 * distributed under the License is distributed on an "AS IS" BASIS,
100 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
101 * See the License for the specific language governing permissions and
102 * limitations under the License.
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -0600103 *
104 * Author: Jon Ashburn <jon@lunarg.com>
Jon Ashburnfc1031e2015-11-17 15:31:02 -0700105 * Author: Chia-I Wu <olv@lunarg.com>
106 * Author: Courtney Goeltzenleuchter <courtney@lunarg.com>
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600107 */"""
108
109 def generate_header(self):
110 return "\n".join(["#include <" + h + ">" for h in self.headers])
111
112 def generate_body(self):
113 pass
114
115 def generate_footer(self):
116 pass
117
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600118class DispatchTableOpsSubcommand(Subcommand):
119 def run(self):
120 if len(self.argv) != 1:
121 print("DispatchTableOpsSubcommand: <prefix> unspecified")
122 return
123
124 self.prefix = self.argv[0]
125 super().run()
126
127 def generate_header(self):
David Pinedo9316d3b2015-11-06 12:54:48 -0700128 return "\n".join(["#include <vulkan/vulkan.h>",
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600129 "#include <vkLayer.h>",
130 "#include <string.h>",
131 "#include \"loader_platform.h\""])
132
Jon Ashburnfbb4e252015-05-04 16:27:53 -0600133 def _generate_init(self, type):
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600134 stmts = []
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600135 func = []
Jon Ashburnfbb4e252015-05-04 16:27:53 -0600136 if type == "device":
137 for proto in self.protos:
138 if self.is_dispatchable_object_first_param(proto) or proto.name == "CreateInstance":
139 stmts.append("table->%s = (PFN_vk%s) gpa(gpu, \"vk%s\");" %
140 (proto.name, proto.name, proto.name))
141 else:
142 stmts.append("table->%s = vk%s; /* non-dispatchable */" %
143 (proto.name, proto.name))
144 func.append("static inline void %s_init_device_dispatch_table(VkLayerDispatchTable *table,"
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600145 % self.prefix)
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600146 func.append("%s PFN_vkGetDeviceProcAddr gpa,"
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600147 % (" " * len(self.prefix)))
Jon Ashburnfbb4e252015-05-04 16:27:53 -0600148 func.append("%s VkPhysicalDevice gpu)"
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600149 % (" " * len(self.prefix)))
Jon Ashburnfbb4e252015-05-04 16:27:53 -0600150 else:
151 for proto in self.protos:
152 if proto.params[0].ty != "VkInstance" and proto.params[0].ty != "VkPhysicalDevice":
153 continue
154 stmts.append("table->%s = vk%s;" % (proto.name, proto.name))
155 func.append("static inline void %s_init_instance_dispatch_table(VkLayerInstanceDispatchTable *table)"
156 % self.prefix)
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600157 func.append("{")
158 func.append(" %s" % "\n ".join(stmts))
159 func.append("}")
160
161 return "\n".join(func)
162
163 def _generate_lookup(self):
164 lookups = []
165 for proto in self.protos:
166 if self.is_dispatchable_object_first_param(proto):
167 lookups.append("if (!strcmp(name, \"%s\"))" % (proto.name))
168 lookups.append(" return (void *) table->%s;"
169 % (proto.name))
170
171 func = []
172 func.append("static inline void *%s_lookup_dispatch_table(const VkLayerDispatchTable *table,"
173 % self.prefix)
174 func.append("%s const char *name)"
175 % (" " * len(self.prefix)))
176 func.append("{")
177 func.append(generate_get_proc_addr_check("name"))
178 func.append("")
179 func.append(" name += 2;")
180 func.append(" %s" % "\n ".join(lookups))
181 func.append("")
182 func.append(" return NULL;")
183 func.append("}")
184
185 return "\n".join(func)
186
187 def generate_body(self):
Jon Ashburnfbb4e252015-05-04 16:27:53 -0600188 body = [self._generate_init("device"),
189 self._generate_lookup(),
190 self._generate_init("instance")]
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600191
192 return "\n\n".join(body)
193
194class WinDefFileSubcommand(Subcommand):
195 def run(self):
196 library_exports = {
197 "all": [],
198 }
199
200 if len(self.argv) != 2 or self.argv[1] not in library_exports:
201 print("WinDefFileSubcommand: <library-name> {%s}" %
202 "|".join(library_exports.keys()))
203 return
204
205 self.library = self.argv[0]
206 self.exports = library_exports[self.argv[1]]
207
208 super().run()
209
210 def generate_copyright(self):
211 return """; THIS FILE IS GENERATED. DO NOT EDIT.
212
213;;;; Begin Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700214; Copyright (c) 2015-2016 The Khronos Group Inc.
215; Copyright (c) 2015-2016 Valve Corporation
216; Copyright (c) 2015-2016 LunarG, Inc.
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600217;
Jon Ashburn3ebf1252016-04-19 11:30:31 -0600218; Licensed under the Apache License, Version 2.0 (the "License");
219; you may not use this file except in compliance with the License.
220; You may obtain a copy of the License at
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600221;
Jon Ashburn3ebf1252016-04-19 11:30:31 -0600222; http://www.apache.org/licenses/LICENSE-2.0
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600223;
Jon Ashburn3ebf1252016-04-19 11:30:31 -0600224; Unless required by applicable law or agreed to in writing, software
225; distributed under the License is distributed on an "AS IS" BASIS,
226; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
227; See the License for the specific language governing permissions and
228; limitations under the License.
Jon Ashburn23d36b12016-02-02 17:47:28 -0700229;
Courtney Goeltzenleuchterbdde0b22015-12-16 14:57:27 -0700230;
231; Author: Jon Ashburn <jon@lunarg.com>
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600232;;;; End Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"""
233
234 def generate_header(self):
235 return "; The following is required on Windows, for exporting symbols from the DLL"
236
237 def generate_body(self):
238 body = []
239
240 body.append("LIBRARY " + self.library)
241 body.append("EXPORTS")
242
243 for proto in self.protos:
244 if self.exports and proto.name not in self.exports:
245 continue
Mark Lobodzinski3077be02015-11-24 14:03:18 -0700246# This was intended to reject WSI calls, but actually rejects ALL extensions
247# TODO: Make this WSI-extension specific
248# if proto.name.endswith("KHR"):
249# continue
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600250 body.append(" vk" + proto.name)
251
252 return "\n".join(body)
253
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600254def main():
Mark Lobodzinski59816c72016-02-24 15:04:11 -0700255
256 wsi = {
257 "Win32",
258 "Android",
259 "Xcb",
260 "Xlib",
261 "Wayland",
262 "Mir"
263 }
264
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600265 subcommands = {
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600266 "dispatch-table-ops": DispatchTableOpsSubcommand,
267 "win-def-file": WinDefFileSubcommand,
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600268 }
269
Mark Lobodzinski59816c72016-02-24 15:04:11 -0700270 if len(sys.argv) < 3 or sys.argv[1] not in wsi or sys.argv[2] not in subcommands:
271 print("Usage: %s <wsi> <subcommand> [options]" % sys.argv[0])
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600272 print
Mark Lobodzinski59816c72016-02-24 15:04:11 -0700273 print("Available wsi (displayservers) are: %s" % " ".join(wsi))
274 print("Available subcommands are: %s" % " ".join(subcommands))
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600275 exit(1)
276
Mark Lobodzinski59816c72016-02-24 15:04:11 -0700277 subcmd = subcommands[sys.argv[2]](sys.argv[3:])
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600278 subcmd.run()
279
280if __name__ == "__main__":
281 main()