blob: d02213de350c09291bcb7cfc58196c3edcb0f597 [file] [log] [blame]
Corentin Wallez59382b72020-04-17 20:43:07 +00001#!/usr/bin/env python3
Corentin Wallez4a9ef4e2018-07-18 11:40:26 +02002# Copyright 2017 The Dawn Authors
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04003#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
Corentin Wallez0c38e922019-06-07 08:59:17 +000016import json, os, sys
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040017from collections import namedtuple
Corentin Wallez0c38e922019-06-07 08:59:17 +000018
Corentin Wallez0c38e922019-06-07 08:59:17 +000019from generator_lib import Generator, run_generator, FileRender
Corentin Wallez031fbbb2019-06-11 18:03:05 +000020
21############################################################
22# OBJECT MODEL
23############################################################
24
Kai Ninomiya01aeca22020-07-15 19:51:17 +000025
fujunwei76bda372021-11-23 08:47:35 +000026class Metadata:
27 def __init__(self, metadata):
28 self.api = metadata['api']
29 self.namespace = metadata['namespace']
30 self.c_prefix = metadata.get('c_prefix', self.namespace.upper())
fujunwei3a464762021-12-05 05:29:44 +000031 self.proc_table_prefix = metadata['proc_table_prefix']
fujunweia2241d42021-12-16 04:54:38 +000032 self.impl_dir = metadata.get('impl_dir', '')
33 self.native_namespace = metadata['native_namespace']
fujunwei76bda372021-11-23 08:47:35 +000034 self.copyright_year = metadata.get('copyright_year', None)
35
36
Corentin Wallez031fbbb2019-06-11 18:03:05 +000037class Name:
38 def __init__(self, name, native=False):
39 self.native = native
Austin Eng76a8d0b2020-04-03 17:37:48 +000040 self.name = name
Corentin Wallez031fbbb2019-06-11 18:03:05 +000041 if native:
42 self.chunks = [name]
43 else:
44 self.chunks = name.split(' ')
45
Austin Eng76a8d0b2020-04-03 17:37:48 +000046 def get(self):
47 return self.name
48
Corentin Wallez031fbbb2019-06-11 18:03:05 +000049 def CamelChunk(self, chunk):
50 return chunk[0].upper() + chunk[1:]
51
52 def canonical_case(self):
53 return (' '.join(self.chunks)).lower()
54
55 def concatcase(self):
56 return ''.join(self.chunks)
57
58 def camelCase(self):
Kai Ninomiya01aeca22020-07-15 19:51:17 +000059 return self.chunks[0] + ''.join(
60 [self.CamelChunk(chunk) for chunk in self.chunks[1:]])
Corentin Wallez031fbbb2019-06-11 18:03:05 +000061
62 def CamelCase(self):
63 return ''.join([self.CamelChunk(chunk) for chunk in self.chunks])
64
65 def SNAKE_CASE(self):
66 return '_'.join([chunk.upper() for chunk in self.chunks])
67
68 def snake_case(self):
69 return '_'.join(self.chunks)
70
Corentin Wallezec9cf2a2022-01-12 09:17:35 +000071 def namespace_case(self):
72 return '::'.join(self.chunks)
73
Ben Clayton20cbe6d2022-02-04 12:51:25 +000074 def Dirs(self):
75 return '/'.join(self.chunks)
76
Kai Ninomiya7b6246a2020-01-28 23:54:38 +000077 def js_enum_case(self):
78 result = self.chunks[0].lower()
79 for chunk in self.chunks[1:]:
80 if not result[-1].isdigit():
81 result += '-'
82 result += chunk.lower()
83 return result
84
Kai Ninomiya01aeca22020-07-15 19:51:17 +000085
Corentin Wallez031fbbb2019-06-11 18:03:05 +000086def concat_names(*names):
87 return ' '.join([name.canonical_case() for name in names])
88
Kai Ninomiya01aeca22020-07-15 19:51:17 +000089
Corentin Wallez031fbbb2019-06-11 18:03:05 +000090class Type:
91 def __init__(self, name, json_data, native=False):
92 self.json_data = json_data
93 self.dict_name = name
94 self.name = Name(name, native=native)
95 self.category = json_data['category']
Jiawei Shao6d6b63c2021-12-02 07:29:41 +000096 self.is_wire_transparent = False
Corentin Wallez031fbbb2019-06-11 18:03:05 +000097
Kai Ninomiya01aeca22020-07-15 19:51:17 +000098
Kai Ninomiya930e9182021-09-17 19:44:43 +000099EnumValue = namedtuple('EnumValue', ['name', 'value', 'valid', 'json_data'])
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000100
101
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000102class EnumType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000103 def __init__(self, is_enabled, name, json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000104 Type.__init__(self, name, json_data)
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000105
106 self.values = []
107 self.contiguousFromZero = True
108 lastValue = -1
109 for m in self.json_data['values']:
Kai Ninomiya930e9182021-09-17 19:44:43 +0000110 if not is_enabled(m):
111 continue
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000112 value = m['value']
113 if value != lastValue + 1:
114 self.contiguousFromZero = False
115 lastValue = value
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000116 self.values.append(
Kai Ninomiya930e9182021-09-17 19:44:43 +0000117 EnumValue(Name(m['name']), value, m.get('valid', True), m))
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000118
Corentin Wallez7ac08152019-06-26 19:54:43 +0000119 # Assert that all values are unique in enums
120 all_values = set()
121 for value in self.values:
122 if value.value in all_values:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000123 raise Exception("Duplicate value {} in enum {}".format(
124 value.value, name))
Corentin Wallez7ac08152019-06-26 19:54:43 +0000125 all_values.add(value.value)
Jiawei Shao6d6b63c2021-12-02 07:29:41 +0000126 self.is_wire_transparent = True
Corentin Wallez7ac08152019-06-26 19:54:43 +0000127
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000128
Kai Ninomiya930e9182021-09-17 19:44:43 +0000129BitmaskValue = namedtuple('BitmaskValue', ['name', 'value', 'json_data'])
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000130
131
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000132class BitmaskType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000133 def __init__(self, is_enabled, name, json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000134 Type.__init__(self, name, json_data)
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000135 self.values = [
Kai Ninomiya930e9182021-09-17 19:44:43 +0000136 BitmaskValue(Name(m['name']), m['value'], m)
137 for m in self.json_data['values'] if is_enabled(m)
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000138 ]
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000139 self.full_mask = 0
140 for value in self.values:
141 self.full_mask = self.full_mask | value.value
Jiawei Shao6d6b63c2021-12-02 07:29:41 +0000142 self.is_wire_transparent = True
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000143
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000144
fujunwei23f71622021-12-02 07:41:21 +0000145class FunctionPointerType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000146 def __init__(self, is_enabled, name, json_data):
Corentin Wallez540abab2019-11-22 13:18:22 +0000147 Type.__init__(self, name, json_data)
fujunwei23f71622021-12-02 07:41:21 +0000148 self.return_type = None
Corentin Wallez540abab2019-11-22 13:18:22 +0000149 self.arguments = []
150
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000151
Brandon Jones58a471a2021-02-08 19:48:06 +0000152class TypedefType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000153 def __init__(self, is_enabled, name, json_data):
Brandon Jones58a471a2021-02-08 19:48:06 +0000154 Type.__init__(self, name, json_data)
155 self.type = None
156
157
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000158class NativeType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000159 def __init__(self, is_enabled, name, json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000160 Type.__init__(self, name, json_data, native=True)
Jiawei Shao6d6b63c2021-12-02 07:29:41 +0000161 self.is_wire_transparent = True
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000162
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000163
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000164# Methods and structures are both "records", so record members correspond to
165# method arguments or structure members.
166class RecordMember:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000167 def __init__(self,
168 name,
169 typ,
170 annotation,
Kai Ninomiya930e9182021-09-17 19:44:43 +0000171 json_data,
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000172 optional=False,
173 is_return_value=False,
174 default_value=None,
Austin Eng6a5418a2019-07-19 16:01:48 +0000175 skip_serialize=False):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000176 self.name = name
177 self.type = typ
178 self.annotation = annotation
Kai Ninomiya930e9182021-09-17 19:44:43 +0000179 self.json_data = json_data
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000180 self.length = None
181 self.optional = optional
182 self.is_return_value = is_return_value
183 self.handle_type = None
Corentin Wallez8f938712019-07-08 19:20:22 +0000184 self.default_value = default_value
Austin Eng6a5418a2019-07-19 16:01:48 +0000185 self.skip_serialize = skip_serialize
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000186
187 def set_handle_type(self, handle_type):
188 assert self.type.dict_name == "ObjectHandle"
189 self.handle_type = handle_type
190
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000191
Kai Ninomiya930e9182021-09-17 19:44:43 +0000192Method = namedtuple('Method',
193 ['name', 'return_type', 'arguments', 'json_data'])
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000194
195
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000196class ObjectType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000197 def __init__(self, is_enabled, name, json_data):
198 json_data_override = {'methods': []}
199 if 'methods' in json_data:
200 json_data_override['methods'] = [
201 m for m in json_data['methods'] if is_enabled(m)
202 ]
203 Type.__init__(self, name, dict(json_data, **json_data_override))
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000204
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000205
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000206class Record:
207 def __init__(self, name):
208 self.name = Name(name)
209 self.members = []
Austin Eng76a8d0b2020-04-03 17:37:48 +0000210 self.may_have_dawn_object = False
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000211
212 def update_metadata(self):
Austin Eng76a8d0b2020-04-03 17:37:48 +0000213 def may_have_dawn_object(member):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000214 if isinstance(member.type, ObjectType):
215 return True
216 elif isinstance(member.type, StructureType):
Austin Eng76a8d0b2020-04-03 17:37:48 +0000217 return member.type.may_have_dawn_object
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000218 else:
219 return False
220
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000221 self.may_have_dawn_object = any(
222 may_have_dawn_object(member) for member in self.members)
Austin Eng76a8d0b2020-04-03 17:37:48 +0000223
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000224 # Set may_have_dawn_object to true if the type is chained or
225 # extensible. Chained structs may contain a Dawn object.
Austin Eng76a8d0b2020-04-03 17:37:48 +0000226 if isinstance(self, StructureType):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000227 self.may_have_dawn_object = (self.may_have_dawn_object
228 or self.chained or self.extensible)
229
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000230
231class StructureType(Record, Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000232 def __init__(self, is_enabled, name, json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000233 Record.__init__(self, name)
Kai Ninomiya930e9182021-09-17 19:44:43 +0000234 json_data_override = {}
235 if 'members' in json_data:
236 json_data_override['members'] = [
237 m for m in json_data['members'] if is_enabled(m)
238 ]
239 Type.__init__(self, name, dict(json_data, **json_data_override))
Austin Eng0c824052021-09-20 16:07:25 +0000240 self.chained = json_data.get("chained", None)
241 self.extensible = json_data.get("extensible", None)
242 if self.chained:
243 assert (self.chained == "in" or self.chained == "out")
244 if self.extensible:
245 assert (self.extensible == "in" or self.extensible == "out")
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000246 # Chained structs inherit from wgpu::ChainedStruct, which has
247 # nextInChain, so setting both extensible and chained would result in
248 # two nextInChain members.
249 assert not (self.extensible and self.chained)
250
Jiawei Shao1fa386c2021-12-21 04:04:51 +0000251 def update_metadata(self):
252 Record.update_metadata(self)
253
254 if self.may_have_dawn_object:
255 self.is_wire_transparent = False
256 return
257
258 assert not (self.chained or self.extensible)
259
260 def get_is_wire_transparent(member):
261 return member.type.is_wire_transparent and member.annotation == 'value'
262
263 self.is_wire_transparent = all(
264 get_is_wire_transparent(m) for m in self.members)
265
Austin Eng0c824052021-09-20 16:07:25 +0000266 @property
267 def output(self):
268 return self.chained == "out" or self.extensible == "out"
269
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000270
fujunwei4e876902021-11-25 08:44:01 +0000271class ConstantDefinition():
272 def __init__(self, is_enabled, name, json_data):
273 self.type = None
274 self.value = json_data['value']
275 self.json_data = json_data
276 self.name = Name(name)
277
278
fujunwei23f71622021-12-02 07:41:21 +0000279class FunctionDeclaration():
280 def __init__(self, is_enabled, name, json_data):
281 self.return_type = None
282 self.arguments = []
283 self.json_data = json_data
284 self.name = Name(name)
285
286
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000287class Command(Record):
288 def __init__(self, name, members=None):
289 Record.__init__(self, name)
290 self.members = members or []
291 self.derived_object = None
292 self.derived_method = None
293
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000294
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000295def linked_record_members(json_data, types):
296 members = []
297 members_by_name = {}
298 for m in json_data:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000299 member = RecordMember(Name(m['name']),
300 types[m['type']],
Corentin Wallez8f938712019-07-08 19:20:22 +0000301 m.get('annotation', 'value'),
Kai Ninomiya930e9182021-09-17 19:44:43 +0000302 m,
Corentin Wallez8f938712019-07-08 19:20:22 +0000303 optional=m.get('optional', False),
304 is_return_value=m.get('is_return_value', False),
Austin Eng6a5418a2019-07-19 16:01:48 +0000305 default_value=m.get('default', None),
306 skip_serialize=m.get('skip_serialize', False))
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000307 handle_type = m.get('handle_type')
308 if handle_type:
309 member.set_handle_type(types[handle_type])
310 members.append(member)
311 members_by_name[member.name.canonical_case()] = member
312
313 for (member, m) in zip(members, json_data):
314 if member.annotation != 'value':
315 if not 'length' in m:
316 if member.type.category != 'object':
317 member.length = "constant"
318 member.constant_length = 1
319 else:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000320 assert False
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000321 elif m['length'] == 'strlen':
322 member.length = 'strlen'
Yan52040532021-12-15 04:08:56 +0000323 elif isinstance(m['length'], int):
324 assert m['length'] > 0
325 member.length = "constant"
326 member.constant_length = m['length']
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000327 else:
328 member.length = members_by_name[m['length']]
329
330 return members
Corentin Walleza6416542018-05-17 16:55:53 -0400331
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000332
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400333############################################################
334# PARSE
335############################################################
Corentin Wallez4b410a32017-04-20 14:42:36 -0400336
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000337
Corentin Walleze2f94842018-12-05 17:49:04 +0000338def link_object(obj, types):
339 def make_method(json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000340 arguments = linked_record_members(json_data.get('args', []), types)
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000341 return Method(Name(json_data['name']),
Kai Ninomiya930e9182021-09-17 19:44:43 +0000342 types[json_data.get('returns',
343 'void')], arguments, json_data)
Corentin Walleze2f94842018-12-05 17:49:04 +0000344
Corentin Wallezaca8c4a2019-11-22 14:02:52 +0000345 obj.methods = [make_method(m) for m in obj.json_data.get('methods', [])]
Corentin Wallez97231682019-10-08 07:38:01 +0000346 obj.methods.sort(key=lambda method: method.name.canonical_case())
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400347
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000348
Corentin Walleza6416542018-05-17 16:55:53 -0400349def link_structure(struct, types):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000350 struct.members = linked_record_members(struct.json_data['members'], types)
Corentin Walleza6416542018-05-17 16:55:53 -0400351
Corentin Wallez540abab2019-11-22 13:18:22 +0000352
fujunwei23f71622021-12-02 07:41:21 +0000353def link_function_pointer(function_pointer, types):
354 link_function(function_pointer, types)
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000355
356
Brandon Jones58a471a2021-02-08 19:48:06 +0000357def link_typedef(typedef, types):
358 typedef.type = types[typedef.json_data['type']]
359
360
fujunwei4e876902021-11-25 08:44:01 +0000361def link_constant(constant, types):
362 constant.type = types[constant.json_data['type']]
363 assert constant.type.name.native
364
365
fujunwei23f71622021-12-02 07:41:21 +0000366def link_function(function, types):
367 function.return_type = types[function.json_data.get('returns', 'void')]
368 function.arguments = linked_record_members(function.json_data['args'],
369 types)
370
371
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000372# Sort structures so that if struct A has struct B as a member, then B is
373# listed before A.
374#
375# This is a form of topological sort where we try to keep the order reasonably
376# similar to the original order (though the sort isn't technically stable).
377#
378# It works by computing for each struct type what is the depth of its DAG of
Kai Ninomiya7d174a12021-09-21 17:36:27 +0000379# dependents, then re-sorting based on that depth using Python's stable sort.
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000380# This makes a toposort because if A depends on B then its depth will be bigger
381# than B's. It is also nice because all nodes with the same depth are kept in
382# the input order.
Corentin Wallez29353d62018-09-18 12:49:22 +0000383def topo_sort_structure(structs):
384 for struct in structs:
385 struct.visited = False
386 struct.subdag_depth = 0
387
388 def compute_depth(struct):
389 if struct.visited:
390 return struct.subdag_depth
391
392 max_dependent_depth = 0
393 for member in struct.members:
Corentin Walleze2f94842018-12-05 17:49:04 +0000394 if member.type.category == 'structure':
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000395 max_dependent_depth = max(max_dependent_depth,
396 compute_depth(member.type) + 1)
Corentin Wallez29353d62018-09-18 12:49:22 +0000397
398 struct.subdag_depth = max_dependent_depth
399 struct.visited = True
400 return struct.subdag_depth
401
402 for struct in structs:
403 compute_depth(struct)
404
405 result = sorted(structs, key=lambda struct: struct.subdag_depth)
406
407 for struct in structs:
408 del struct.visited
409 del struct.subdag_depth
410
411 return result
412
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000413
Austin Eng2f218e22021-12-22 19:02:23 +0000414def parse_json(json, enabled_tags, disabled_tags=None):
415 is_enabled = lambda json_data: item_is_enabled(
416 enabled_tags, json_data) and not item_is_disabled(
417 disabled_tags, json_data)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400418 category_to_parser = {
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000419 'bitmask': BitmaskType,
420 'enum': EnumType,
421 'native': NativeType,
fujunwei23f71622021-12-02 07:41:21 +0000422 'function pointer': FunctionPointerType,
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000423 'object': ObjectType,
424 'structure': StructureType,
Brandon Jones58a471a2021-02-08 19:48:06 +0000425 'typedef': TypedefType,
fujunwei4e876902021-11-25 08:44:01 +0000426 'constant': ConstantDefinition,
fujunwei23f71622021-12-02 07:41:21 +0000427 'function': FunctionDeclaration
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400428 }
429
430 types = {}
431
432 by_category = {}
433 for name in category_to_parser.keys():
434 by_category[name] = []
435
Corentin Walleze2f94842018-12-05 17:49:04 +0000436 for (name, json_data) in json.items():
Austin Eng2f218e22021-12-22 19:02:23 +0000437 if name[0] == '_' or not is_enabled(json_data):
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400438 continue
Corentin Walleze2f94842018-12-05 17:49:04 +0000439 category = json_data['category']
Kai Ninomiya930e9182021-09-17 19:44:43 +0000440 parsed = category_to_parser[category](is_enabled, name, json_data)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400441 by_category[category].append(parsed)
442 types[name] = parsed
443
444 for obj in by_category['object']:
445 link_object(obj, types)
446
Corentin Walleza6416542018-05-17 16:55:53 -0400447 for struct in by_category['structure']:
448 link_structure(struct, types)
449
fujunwei23f71622021-12-02 07:41:21 +0000450 for function_pointer in by_category['function pointer']:
451 link_function_pointer(function_pointer, types)
Corentin Wallez540abab2019-11-22 13:18:22 +0000452
Brandon Jones58a471a2021-02-08 19:48:06 +0000453 for typedef in by_category['typedef']:
454 link_typedef(typedef, types)
455
fujunwei4e876902021-11-25 08:44:01 +0000456 for constant in by_category['constant']:
457 link_constant(constant, types)
458
fujunwei23f71622021-12-02 07:41:21 +0000459 for function in by_category['function']:
460 link_function(function, types)
461
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400462 for category in by_category.keys():
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000463 by_category[category] = sorted(
464 by_category[category], key=lambda typ: typ.name.canonical_case())
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400465
Corentin Wallez29353d62018-09-18 12:49:22 +0000466 by_category['structure'] = topo_sort_structure(by_category['structure'])
467
Austin Engc7f416c2019-01-15 20:49:53 +0000468 for struct in by_category['structure']:
469 struct.update_metadata()
470
Kai Ninomiya930e9182021-09-17 19:44:43 +0000471 api_params = {
472 'types': types,
473 'by_category': by_category,
474 'enabled_tags': enabled_tags,
Austin Eng2f218e22021-12-22 19:02:23 +0000475 'disabled_tags': disabled_tags,
Kai Ninomiya930e9182021-09-17 19:44:43 +0000476 }
477 return {
fujunwei76bda372021-11-23 08:47:35 +0000478 'metadata': Metadata(json['_metadata']),
Kai Ninomiya930e9182021-09-17 19:44:43 +0000479 'types': types,
480 'by_category': by_category,
481 'enabled_tags': enabled_tags,
Austin Eng2f218e22021-12-22 19:02:23 +0000482 'disabled_tags': disabled_tags,
Kai Ninomiya930e9182021-09-17 19:44:43 +0000483 'c_methods': lambda typ: c_methods(api_params, typ),
484 'c_methods_sorted_by_name': get_c_methods_sorted_by_name(api_params),
485 }
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000486
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400487
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000488############################################################
489# WIRE STUFF
490############################################################
491
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000492
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000493# Create wire commands from api methods
494def compute_wire_params(api_params, wire_json):
495 wire_params = api_params.copy()
496 types = wire_params['types']
497
498 commands = []
499 return_commands = []
500
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000501 wire_json['special items']['client_handwritten_commands'] += wire_json[
502 'special items']['client_side_commands']
Corentin Wallez540abab2019-11-22 13:18:22 +0000503
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000504 # Generate commands from object methods
505 for api_object in wire_params['by_category']['object']:
506 for method in api_object.methods:
507 command_name = concat_names(api_object.name, method.name)
508 command_suffix = Name(command_name).CamelCase()
509
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000510 # Only object return values or void are supported.
511 # Other methods must be handwritten.
512 is_object = method.return_type.category == 'object'
513 is_void = method.return_type.name.canonical_case() == 'void'
514 if not (is_object or is_void):
515 assert command_suffix in (
516 wire_json['special items']['client_handwritten_commands'])
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000517 continue
518
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000519 if command_suffix in (
520 wire_json['special items']['client_side_commands']):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000521 continue
522
523 # Create object method commands by prepending "self"
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000524 members = [
525 RecordMember(Name('self'), types[api_object.dict_name],
Kai Ninomiya930e9182021-09-17 19:44:43 +0000526 'value', {})
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000527 ]
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000528 members += method.arguments
529
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000530 # Client->Server commands that return an object return the
531 # result object handle
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000532 if method.return_type.category == 'object':
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000533 result = RecordMember(Name('result'),
534 types['ObjectHandle'],
Kai Ninomiya930e9182021-09-17 19:44:43 +0000535 'value', {},
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000536 is_return_value=True)
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000537 result.set_handle_type(method.return_type)
538 members.append(result)
539
540 command = Command(command_name, members)
541 command.derived_object = api_object
542 command.derived_method = method
543 commands.append(command)
544
545 for (name, json_data) in wire_json['commands'].items():
546 commands.append(Command(name, linked_record_members(json_data, types)))
547
548 for (name, json_data) in wire_json['return commands'].items():
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000549 return_commands.append(
550 Command(name, linked_record_members(json_data, types)))
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000551
552 wire_params['cmd_records'] = {
553 'command': commands,
554 'return command': return_commands
555 }
556
557 for commands in wire_params['cmd_records'].values():
558 for command in commands:
559 command.update_metadata()
560 commands.sort(key=lambda c: c.name.canonical_case())
561
562 wire_params.update(wire_json.get('special items', {}))
563
564 return wire_params
565
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000566
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400567#############################################################
Corentin Wallez0c38e922019-06-07 08:59:17 +0000568# Generator
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400569#############################################################
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400570
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000571
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400572def as_varName(*names):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000573 return names[0].camelCase() + ''.join(
574 [name.CamelCase() for name in names[1:]])
575
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400576
fujunwei76bda372021-11-23 08:47:35 +0000577def as_cType(c_prefix, name):
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400578 if name.native:
579 return name.concatcase()
580 else:
fujunwei76bda372021-11-23 08:47:35 +0000581 return c_prefix + name.CamelCase()
Corentin Wallez919812e2019-10-17 08:46:07 +0000582
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000583
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400584def as_cppType(name):
585 if name.native:
586 return name.concatcase()
587 else:
588 return name.CamelCase()
589
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000590
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000591def as_jsEnumValue(value):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000592 if 'jsrepr' in value.json_data: return value.json_data['jsrepr']
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000593 return "'" + value.name.js_enum_case() + "'"
594
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000595
Austin Eng740995c2019-05-15 18:55:22 +0000596def convert_cType_to_cppType(typ, annotation, arg, indent=0):
597 if typ.category == 'native':
598 return arg
599 if annotation == 'value':
600 if typ.category == 'object':
601 return '{}::Acquire({})'.format(as_cppType(typ.name), arg)
602 elif typ.category == 'structure':
603 converted_members = [
604 convert_cType_to_cppType(
605 member.type, member.annotation,
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000606 '{}.{}'.format(arg, as_varName(member.name)), indent + 1)
607 for member in typ.members
608 ]
Austin Eng740995c2019-05-15 18:55:22 +0000609
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000610 converted_members = [(' ' * 4) + m for m in converted_members]
Austin Eng740995c2019-05-15 18:55:22 +0000611 converted_members = ',\n'.join(converted_members)
612
613 return as_cppType(typ.name) + ' {\n' + converted_members + '\n}'
fujunweid3cac112021-12-14 02:20:15 +0000614 elif typ.category == 'function pointer':
615 return 'reinterpret_cast<{}>({})'.format(as_cppType(typ.name), arg)
Austin Eng740995c2019-05-15 18:55:22 +0000616 else:
617 return 'static_cast<{}>({})'.format(as_cppType(typ.name), arg)
618 else:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000619 return 'reinterpret_cast<{} {}>({})'.format(as_cppType(typ.name),
620 annotation, arg)
621
Austin Eng740995c2019-05-15 18:55:22 +0000622
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400623def decorate(name, typ, arg):
624 if arg.annotation == 'value':
625 return typ + ' ' + name
Austin Eng740995c2019-05-15 18:55:22 +0000626 elif arg.annotation == '*':
627 return typ + ' * ' + name
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400628 elif arg.annotation == 'const*':
629 return typ + ' const * ' + name
Austin Eng2f218e22021-12-22 19:02:23 +0000630 elif arg.annotation == 'const*const*':
631 return 'const ' + typ + '* const * ' + name
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400632 else:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000633 assert False
634
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400635
636def annotated(typ, arg):
637 name = as_varName(arg.name)
638 return decorate(name, typ, arg)
639
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000640
Kai Ninomiya930e9182021-09-17 19:44:43 +0000641def item_is_enabled(enabled_tags, json_data):
642 tags = json_data.get('tags')
643 if tags is None: return True
644 return any(tag in enabled_tags for tag in tags)
645
646
Austin Eng2f218e22021-12-22 19:02:23 +0000647def item_is_disabled(disabled_tags, json_data):
648 if disabled_tags is None: return False
649 tags = json_data.get('tags')
650 if tags is None: return False
651
652 return any(tag in disabled_tags for tag in tags)
653
654
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400655def as_cppEnum(value_name):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000656 assert not value_name.native
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400657 if value_name.concatcase()[0].isdigit():
658 return "e" + value_name.CamelCase()
659 return value_name.CamelCase()
660
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000661
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400662def as_MethodSuffix(type_name, method_name):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000663 assert not type_name.native and not method_name.native
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400664 return type_name.CamelCase() + method_name.CamelCase()
665
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000666
fujunwei76bda372021-11-23 08:47:35 +0000667def as_frontendType(metadata, typ):
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400668 if typ.category == 'object':
Corentin Wallez4f5fc2d2019-04-01 21:48:38 +0000669 return typ.name.CamelCase() + 'Base*'
Corentin Wallezfe253f12018-08-01 15:12:10 +0200670 elif typ.category in ['bitmask', 'enum']:
fujunwei76bda372021-11-23 08:47:35 +0000671 return metadata.namespace + '::' + typ.name.CamelCase()
Corentin Wallezfe253f12018-08-01 15:12:10 +0200672 elif typ.category == 'structure':
673 return as_cppType(typ.name)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400674 else:
fujunwei76bda372021-11-23 08:47:35 +0000675 return as_cType(metadata.c_prefix, typ.name)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400676
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000677
fujunwei76bda372021-11-23 08:47:35 +0000678def as_wireType(metadata, typ):
Austin Engcb0cb652019-08-27 21:41:56 +0000679 if typ.category == 'object':
680 return typ.name.CamelCase() + '*'
Brandon Jones6f2bbe92021-04-05 23:34:17 +0000681 elif typ.category in ['bitmask', 'enum', 'structure']:
fujunwei76bda372021-11-23 08:47:35 +0000682 return metadata.c_prefix + typ.name.CamelCase()
Austin Engcb0cb652019-08-27 21:41:56 +0000683 else:
684 return as_cppType(typ.name)
685
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000686
Loko Kung4d835252022-03-19 00:21:48 +0000687def as_formatType(typ):
688 # Unsigned integral types
689 if typ.json_data['type'] in ['bool', 'uint32_t', 'uint64_t']:
690 return 'u'
691
692 # Defaults everything else to strings.
693 return 's'
694
695
Kai Ninomiya930e9182021-09-17 19:44:43 +0000696def c_methods(params, typ):
Corentin Wallezaca8c4a2019-11-22 14:02:52 +0000697 return typ.methods + [
Kai Ninomiya930e9182021-09-17 19:44:43 +0000698 x for x in [
699 Method(Name('reference'), params['types']['void'], [],
700 {'tags': ['dawn', 'emscripten']}),
701 Method(Name('release'), params['types']['void'], [],
702 {'tags': ['dawn', 'emscripten']}),
703 ] if item_is_enabled(params['enabled_tags'], x.json_data)
Austin Eng2f218e22021-12-22 19:02:23 +0000704 and not item_is_disabled(params['disabled_tags'], x.json_data)
Corentin Wallez4b410a32017-04-20 14:42:36 -0400705 ]
706
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000707
Corentin Wallezaca8c4a2019-11-22 14:02:52 +0000708def get_c_methods_sorted_by_name(api_params):
Corentin Wallezc57b1802019-10-15 12:08:48 +0000709 unsorted = [(as_MethodSuffix(typ.name, method.name), typ, method) \
710 for typ in api_params['by_category']['object'] \
Kai Ninomiya930e9182021-09-17 19:44:43 +0000711 for method in c_methods(api_params, typ) ]
Corentin Wallezc57b1802019-10-15 12:08:48 +0000712 return [(typ, method) for (_, typ, method) in sorted(unsorted)]
713
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000714
Corentin Wallez540abab2019-11-22 13:18:22 +0000715def has_callback_arguments(method):
fujunwei23f71622021-12-02 07:41:21 +0000716 return any(arg.type.category == 'function pointer' for arg in method.arguments)
Corentin Wallez540abab2019-11-22 13:18:22 +0000717
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000718
fujunwei76bda372021-11-23 08:47:35 +0000719def make_base_render_params(metadata):
720 c_prefix = metadata.c_prefix
721
722 def as_cTypeEnumSpecialCase(typ):
723 if typ.category == 'bitmask':
724 return as_cType(c_prefix, typ.name) + 'Flags'
725 return as_cType(c_prefix, typ.name)
726
727 def as_cEnum(type_name, value_name):
728 assert not type_name.native and not value_name.native
729 return c_prefix + type_name.CamelCase() + '_' + value_name.CamelCase()
730
731 def as_cMethod(type_name, method_name):
fujunwei23f71622021-12-02 07:41:21 +0000732 c_method = c_prefix.lower()
733 if type_name != None:
734 assert not type_name.native
735 c_method += type_name.CamelCase()
736 assert not method_name.native
737 c_method += method_name.CamelCase()
738 return c_method
fujunwei76bda372021-11-23 08:47:35 +0000739
740 def as_cProc(type_name, method_name):
fujunwei23f71622021-12-02 07:41:21 +0000741 c_proc = c_prefix + 'Proc'
742 if type_name != None:
743 assert not type_name.native
744 c_proc += type_name.CamelCase()
745 assert not method_name.native
746 c_proc += method_name.CamelCase()
747 return c_proc
fujunwei76bda372021-11-23 08:47:35 +0000748
749 return {
750 'Name': lambda name: Name(name),
751 'as_annotated_cType': \
752 lambda arg: annotated(as_cTypeEnumSpecialCase(arg.type), arg),
753 'as_annotated_cppType': \
754 lambda arg: annotated(as_cppType(arg.type.name), arg),
755 'as_cEnum': as_cEnum,
756 'as_cppEnum': as_cppEnum,
757 'as_cMethod': as_cMethod,
758 'as_MethodSuffix': as_MethodSuffix,
759 'as_cProc': as_cProc,
760 'as_cType': lambda name: as_cType(c_prefix, name),
761 'as_cppType': as_cppType,
762 'as_jsEnumValue': as_jsEnumValue,
763 'convert_cType_to_cppType': convert_cType_to_cppType,
764 'as_varName': as_varName,
Loko Kung4d835252022-03-19 00:21:48 +0000765 'decorate': decorate,
766 'as_formatType': as_formatType
fujunwei76bda372021-11-23 08:47:35 +0000767 }
768
769
Corentin Wallez0c38e922019-06-07 08:59:17 +0000770class MultiGeneratorFromDawnJSON(Generator):
771 def get_description(self):
772 return 'Generates code for various target from Dawn.json.'
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400773
Corentin Wallez0c38e922019-06-07 08:59:17 +0000774 def add_commandline_arguments(self, parser):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000775 allowed_targets = [
Ben Clayton35940f92022-02-04 17:15:16 +0000776 'dawn_headers', 'cpp_headers', 'cpp', 'proc', 'mock_api', 'wire',
777 'native_utils'
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000778 ]
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400779
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000780 parser.add_argument('--dawn-json',
781 required=True,
782 type=str,
783 help='The DAWN JSON definition to use.')
784 parser.add_argument('--wire-json',
785 default=None,
786 type=str,
787 help='The DAWN WIRE JSON definition to use.')
788 parser.add_argument(
789 '--targets',
790 required=True,
791 type=str,
792 help=
793 'Comma-separated subset of targets to output. Available targets: '
794 + ', '.join(allowed_targets))
Corentin Wallez0c38e922019-06-07 08:59:17 +0000795 def get_file_renders(self, args):
796 with open(args.dawn_json) as f:
797 loaded_json = json.loads(f.read())
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400798
Corentin Wallez0c38e922019-06-07 08:59:17 +0000799 targets = args.targets.split(',')
Corentin Wallez4b410a32017-04-20 14:42:36 -0400800
Corentin Wallez0c38e922019-06-07 08:59:17 +0000801 wire_json = None
802 if args.wire_json:
803 with open(args.wire_json) as f:
804 wire_json = json.loads(f.read())
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400805
Kai Ninomiya930e9182021-09-17 19:44:43 +0000806 renders = []
807
Kai Ninomiya930e9182021-09-17 19:44:43 +0000808 params_dawn = parse_json(loaded_json,
809 enabled_tags=['dawn', 'native', 'deprecated'])
fujunwei76bda372021-11-23 08:47:35 +0000810 metadata = params_dawn['metadata']
811 RENDER_PARAMS_BASE = make_base_render_params(metadata)
Corentin Wallez79a62bf2017-05-24 16:04:55 +0200812
fujunweic7d4f2c2021-12-07 00:46:35 +0000813 api = metadata.api.lower()
fujunweia8405742021-12-10 01:35:19 +0000814 prefix = metadata.proc_table_prefix.lower()
Ben Clayton35940f92022-02-04 17:15:16 +0000815 if 'headers' in targets:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000816 renders.append(
Ben Clayton9fb7a512022-02-04 18:18:18 +0000817 FileRender('api.h', 'include/dawn/' + api + '.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000818 [RENDER_PARAMS_BASE, params_dawn]))
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000819 renders.append(
820 FileRender('dawn_proc_table.h',
Ben Clayton9fb7a512022-02-04 18:18:18 +0000821 'include/dawn/' + prefix + '_proc_table.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000822 [RENDER_PARAMS_BASE, params_dawn]))
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400823
Ben Clayton35940f92022-02-04 17:15:16 +0000824 if 'cpp_headers' in targets:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000825 renders.append(
Ben Clayton9fb7a512022-02-04 18:18:18 +0000826 FileRender('api_cpp.h', 'include/dawn/' + api + '_cpp.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000827 [RENDER_PARAMS_BASE, params_dawn]))
Austin Engcc071e42019-10-16 10:26:01 +0000828
Austin Enga9e39e12021-06-01 18:49:12 +0000829 renders.append(
fujunweic7d4f2c2021-12-07 00:46:35 +0000830 FileRender('api_cpp_print.h',
Ben Clayton9fb7a512022-02-04 18:18:18 +0000831 'include/dawn/' + api + '_cpp_print.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000832 [RENDER_PARAMS_BASE, params_dawn]))
Austin Enga9e39e12021-06-01 18:49:12 +0000833
Ben Clayton35940f92022-02-04 17:15:16 +0000834 if 'proc' in targets:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000835 renders.append(
fujunweia8405742021-12-10 01:35:19 +0000836 FileRender('dawn_proc.c', 'src/dawn/' + prefix + '_proc.c',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000837 [RENDER_PARAMS_BASE, params_dawn]))
Austin Eng16e01af2020-10-06 16:13:42 +0000838 renders.append(
839 FileRender('dawn_thread_dispatch_proc.cpp',
fujunweia8405742021-12-10 01:35:19 +0000840 'src/dawn/' + prefix + '_thread_dispatch_proc.cpp',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000841 [RENDER_PARAMS_BASE, params_dawn]))
Corentin Wallez96496822019-10-15 11:44:38 +0000842
Austin Eng63f65462021-12-09 20:03:48 +0000843 if 'webgpu_dawn_native_proc' in targets:
844 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000845 FileRender('dawn/native/api_dawn_native_proc.cpp',
846 'src/dawn/native/webgpu_dawn_native_proc.cpp',
Austin Eng63f65462021-12-09 20:03:48 +0000847 [RENDER_PARAMS_BASE, params_dawn]))
848
Ben Clayton35940f92022-02-04 17:15:16 +0000849 if 'cpp' in targets:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000850 renders.append(
fujunweid3cac112021-12-14 02:20:15 +0000851 FileRender('api_cpp.cpp', 'src/dawn/' + api + '_cpp.cpp',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000852 [RENDER_PARAMS_BASE, params_dawn]))
853
854 if 'webgpu_headers' in targets:
855 params_upstream = parse_json(loaded_json,
Shrek Shao1554a7d2022-03-08 20:56:10 +0000856 enabled_tags=['upstream', 'native'],
857 disabled_tags=['dawn'])
Kai Ninomiya930e9182021-09-17 19:44:43 +0000858 renders.append(
fujunweic7d4f2c2021-12-07 00:46:35 +0000859 FileRender('api.h', 'webgpu-headers/' + api + '.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000860 [RENDER_PARAMS_BASE, params_upstream]))
Corentin Wallez59e7fad2018-08-16 15:32:35 +0200861
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000862 if 'emscripten_bits' in targets:
Shrek Shaoee50bc02022-02-08 20:21:40 +0000863 params_emscripten = parse_json(loaded_json,
864 enabled_tags=['emscripten'])
Kai Ninomiya930e9182021-09-17 19:44:43 +0000865 renders.append(
fujunweic7d4f2c2021-12-07 00:46:35 +0000866 FileRender('api.h', 'emscripten-bits/' + api + '.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000867 [RENDER_PARAMS_BASE, params_emscripten]))
868 renders.append(
fujunweic7d4f2c2021-12-07 00:46:35 +0000869 FileRender('api_cpp.h', 'emscripten-bits/' + api + '_cpp.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000870 [RENDER_PARAMS_BASE, params_emscripten]))
871 renders.append(
fujunweid3cac112021-12-14 02:20:15 +0000872 FileRender('api_cpp.cpp', 'emscripten-bits/' + api + '_cpp.cpp',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000873 [RENDER_PARAMS_BASE, params_emscripten]))
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000874 renders.append(
fujunwei16ae3b82021-12-15 04:35:26 +0000875 FileRender('api_struct_info.json',
876 'emscripten-bits/' + api + '_struct_info.json',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000877 [RENDER_PARAMS_BASE, params_emscripten]))
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000878 renders.append(
fujunwei16ae3b82021-12-15 04:35:26 +0000879 FileRender('library_api_enum_tables.js',
880 'emscripten-bits/library_' + api + '_enum_tables.js',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000881 [RENDER_PARAMS_BASE, params_emscripten]))
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000882
fujunwei16ae3b82021-12-15 04:35:26 +0000883 if 'mock_api' in targets:
Corentin Wallez540abab2019-11-22 13:18:22 +0000884 mock_params = [
Kai Ninomiya930e9182021-09-17 19:44:43 +0000885 RENDER_PARAMS_BASE, params_dawn, {
Corentin Wallez540abab2019-11-22 13:18:22 +0000886 'has_callback_arguments': has_callback_arguments
887 }
888 ]
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000889 renders.append(
fujunwei16ae3b82021-12-15 04:35:26 +0000890 FileRender('mock_api.h', 'src/dawn/mock_' + api + '.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000891 mock_params))
892 renders.append(
fujunwei16ae3b82021-12-15 04:35:26 +0000893 FileRender('mock_api.cpp', 'src/dawn/mock_' + api + '.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000894 mock_params))
Corentin Wallez59e7fad2018-08-16 15:32:35 +0200895
Ben Clayton818001d2022-02-04 17:07:46 +0000896 if 'native_utils' in targets:
Corentin Wallez0c38e922019-06-07 08:59:17 +0000897 frontend_params = [
Kai Ninomiya930e9182021-09-17 19:44:43 +0000898 RENDER_PARAMS_BASE,
899 params_dawn,
Corentin Wallez0c38e922019-06-07 08:59:17 +0000900 {
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000901 # TODO: as_frontendType and co. take a Type, not a Name :(
fujunwei76bda372021-11-23 08:47:35 +0000902 'as_frontendType': lambda typ: as_frontendType(metadata, typ),
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000903 'as_annotated_frontendType': \
fujunwei76bda372021-11-23 08:47:35 +0000904 lambda arg: annotated(as_frontendType(metadata, arg.type), arg),
Corentin Wallez0c38e922019-06-07 08:59:17 +0000905 }
906 ]
Corentin Wallez59e7fad2018-08-16 15:32:35 +0200907
fujunweia2241d42021-12-16 04:54:38 +0000908 impl_dir = metadata.impl_dir + '/' if metadata.impl_dir else ''
Ben Clayton818001d2022-02-04 17:07:46 +0000909 native_dir = impl_dir + Name(metadata.native_namespace).Dirs()
fujunwei7f3f8ac2021-12-21 03:27:34 +0000910 namespace = metadata.namespace
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000911 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000912 FileRender('dawn/native/ValidationUtils.h',
fujunweia2241d42021-12-16 04:54:38 +0000913 'src/' + native_dir + '/ValidationUtils_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000914 frontend_params))
915 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000916 FileRender('dawn/native/ValidationUtils.cpp',
fujunweia2241d42021-12-16 04:54:38 +0000917 'src/' + native_dir + '/ValidationUtils_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000918 frontend_params))
919 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000920 FileRender('dawn/native/dawn_platform.h',
fujunweifc38f7d2021-12-17 00:46:08 +0000921 'src/' + native_dir + '/' + prefix + '_platform_autogen.h',
Austin Eng3faa4782021-10-27 19:07:37 +0000922 frontend_params))
923 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000924 FileRender('dawn/native/api_structs.h',
fujunwei7f3f8ac2021-12-21 03:27:34 +0000925 'src/' + native_dir + '/' + namespace + '_structs_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000926 frontend_params))
927 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000928 FileRender('dawn/native/api_structs.cpp',
fujunwei7f3f8ac2021-12-21 03:27:34 +0000929 'src/' + native_dir + '/' + namespace + '_structs_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000930 frontend_params))
931 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000932 FileRender('dawn/native/ProcTable.cpp',
Ningxin Hu7e5930b2021-12-22 06:12:13 +0000933 'src/' + native_dir + '/ProcTable.cpp', frontend_params))
Brian Ho5346e772021-04-22 17:49:42 +0000934 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000935 FileRender('dawn/native/ChainUtils.h',
fujunwei2b1dcd92021-12-22 01:05:03 +0000936 'src/' + native_dir + '/ChainUtils_autogen.h',
Brian Ho5346e772021-04-22 17:49:42 +0000937 frontend_params))
938 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000939 FileRender('dawn/native/ChainUtils.cpp',
fujunwei2b1dcd92021-12-22 01:05:03 +0000940 'src/' + native_dir + '/ChainUtils_autogen.cpp',
Brian Ho5346e772021-04-22 17:49:42 +0000941 frontend_params))
Brandon Jonesba662952021-09-23 21:26:33 +0000942 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000943 FileRender('dawn/native/api_absl_format.h',
fujunweif001ef52021-12-23 05:16:04 +0000944 'src/' + native_dir + '/' + api + '_absl_format_autogen.h',
Brandon Jonesba662952021-09-23 21:26:33 +0000945 frontend_params))
946 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000947 FileRender('dawn/native/api_absl_format.cpp',
fujunweif001ef52021-12-23 05:16:04 +0000948 'src/' + native_dir + '/' + api + '_absl_format_autogen.cpp',
Brandon Jonesba662952021-09-23 21:26:33 +0000949 frontend_params))
Loko Kung8d195d52021-09-28 15:40:01 +0000950 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000951 FileRender('dawn/native/ObjectType.h',
fujunwei2b1dcd92021-12-22 01:05:03 +0000952 'src/' + native_dir + '/ObjectType_autogen.h',
Loko Kung8d195d52021-09-28 15:40:01 +0000953 frontend_params))
954 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000955 FileRender('dawn/native/ObjectType.cpp',
fujunwei2b1dcd92021-12-22 01:05:03 +0000956 'src/' + native_dir + '/ObjectType_autogen.cpp',
Loko Kung8d195d52021-09-28 15:40:01 +0000957 frontend_params))
Loko Kungc083d652022-04-12 23:50:56 +0000958 renders.append(
959 FileRender('dawn/native/CacheKey.cpp',
960 'src/' + native_dir + '/CacheKey_autogen.cpp',
961 frontend_params))
Corentin Wallez59e7fad2018-08-16 15:32:35 +0200962
Ben Clayton20cbe6d2022-02-04 12:51:25 +0000963 if 'wire' in targets:
Austin Eng2f218e22021-12-22 19:02:23 +0000964 params_dawn_wire = parse_json(loaded_json,
965 enabled_tags=['dawn', 'deprecated'],
966 disabled_tags=['native'])
967 additional_params = compute_wire_params(params_dawn_wire,
968 wire_json)
Corentin Wallez59e7fad2018-08-16 15:32:35 +0200969
Corentin Wallez0c38e922019-06-07 08:59:17 +0000970 wire_params = [
Austin Eng2f218e22021-12-22 19:02:23 +0000971 RENDER_PARAMS_BASE, params_dawn_wire, {
fujunwei76bda372021-11-23 08:47:35 +0000972 'as_wireType': lambda type : as_wireType(metadata, type),
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000973 'as_annotated_wireType': \
fujunwei76bda372021-11-23 08:47:35 +0000974 lambda arg: annotated(as_wireType(metadata, arg.type), arg),
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000975 }, additional_params
Corentin Wallez0c38e922019-06-07 08:59:17 +0000976 ]
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000977 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +0000978 FileRender('dawn/wire/ObjectType.h',
979 'src/dawn/wire/ObjectType_autogen.h', wire_params))
Austin Eng3120d5e2020-11-11 19:46:18 +0000980 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +0000981 FileRender('dawn/wire/WireCmd.h',
982 'src/dawn/wire/WireCmd_autogen.h', wire_params))
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000983 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +0000984 FileRender('dawn/wire/WireCmd.cpp',
985 'src/dawn/wire/WireCmd_autogen.cpp', wire_params))
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000986 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +0000987 FileRender('dawn/wire/client/ApiObjects.h',
988 'src/dawn/wire/client/ApiObjects_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000989 wire_params))
990 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +0000991 FileRender('dawn/wire/client/ApiProcs.cpp',
992 'src/dawn/wire/client/ApiProcs_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000993 wire_params))
994 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +0000995 FileRender('dawn/wire/client/ClientBase.h',
996 'src/dawn/wire/client/ClientBase_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000997 wire_params))
998 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +0000999 FileRender('dawn/wire/client/ClientHandlers.cpp',
1000 'src/dawn/wire/client/ClientHandlers_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001001 wire_params))
1002 renders.append(
1003 FileRender(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001004 'dawn/wire/client/ClientPrototypes.inc',
1005 'src/dawn/wire/client/ClientPrototypes_autogen.inc',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001006 wire_params))
1007 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001008 FileRender('dawn/wire/server/ServerBase.h',
1009 'src/dawn/wire/server/ServerBase_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001010 wire_params))
1011 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001012 FileRender('dawn/wire/server/ServerDoers.cpp',
1013 'src/dawn/wire/server/ServerDoers_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001014 wire_params))
1015 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001016 FileRender('dawn/wire/server/ServerHandlers.cpp',
1017 'src/dawn/wire/server/ServerHandlers_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001018 wire_params))
1019 renders.append(
1020 FileRender(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001021 'dawn/wire/server/ServerPrototypes.inc',
1022 'src/dawn/wire/server/ServerPrototypes_autogen.inc',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001023 wire_params))
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001024
Corentin Wallez0c38e922019-06-07 08:59:17 +00001025 return renders
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001026
Corentin Wallez0c38e922019-06-07 08:59:17 +00001027 def get_dependencies(self, args):
1028 deps = [os.path.abspath(args.dawn_json)]
1029 if args.wire_json != None:
1030 deps += [os.path.abspath(args.wire_json)]
1031 return deps
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04001032
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001033
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04001034if __name__ == '__main__':
Corentin Wallez0c38e922019-06-07 08:59:17 +00001035 sys.exit(run_generator(MultiGeneratorFromDawnJSON()))