• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python
2# Copyright 2019 The ANGLE Project Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5#
6# gen_mtl_format_table.py:
7#  Code generation for Metal format map.
8#  NOTE: don't run this script directly. Run scripts/run_code_generation.py.
9#
10
11from datetime import date
12import json
13import math
14import pprint
15import re
16import sys
17
18sys.path.append('..')
19import angle_format
20
21template_autogen_inl = """// GENERATED FILE - DO NOT EDIT.
22// Generated by {script_name} using data from {data_source_name}
23//
24// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved.
25// Use of this source code is governed by a BSD-style license that can be
26// found in the LICENSE file.
27//
28// Metal Format table:
29//   Conversion from ANGLE format to Metal format.
30
31#import <Metal/Metal.h>
32#include <TargetConditionals.h>
33
34#include "libANGLE/renderer/Format.h"
35#include "libANGLE/renderer/metal/DisplayMtl.h"
36#include "libANGLE/renderer/metal/mtl_format_utils.h"
37
38namespace rx
39{{
40namespace mtl
41{{
42
43void Format::init(const DisplayMtl *display, angle::FormatID intendedFormatId_)
44{{
45    this->intendedFormatId = intendedFormatId_;
46
47    id<MTLDevice> metalDevice = display->getMetalDevice();
48
49    // Actual conversion
50    switch (this->intendedFormatId)
51    {{
52{angle_image_format_switch}
53    }}
54}}
55
56void VertexFormat::init(angle::FormatID angleFormatId, bool tightlyPacked)
57{{
58    this->intendedFormatId = angleFormatId;
59
60    // Actual conversion
61    switch (this->intendedFormatId)
62    {{
63{angle_vertex_format_switch}
64    }}
65}}
66
67}}  // namespace mtl
68}}  // namespace rx
69"""
70
71case_image_format_template1 = """        case angle::FormatID::{angle_format}:
72            this->metalFormat = {mtl_format};
73            this->actualFormatId = angle::FormatID::{actual_angle_format};
74            break;
75
76"""
77
78case_image_format_template2 = """        case angle::FormatID::{angle_format}:
79            if (metalDevice.depth24Stencil8PixelFormatSupported)
80            {{
81                this->metalFormat = {mtl_format};
82                this->actualFormatId = angle::FormatID::{actual_angle_format};
83            }}
84            else
85            {{
86                this->metalFormat = {mtl_format_fallback};
87                this->actualFormatId = angle::FormatID::{actual_angle_format_fallback};
88            }}
89            break;
90
91"""
92
93case_vertex_format_template1 = """        case angle::FormatID::{angle_format}:
94            this->metalFormat = {mtl_format};
95            this->actualFormatId = angle::FormatID::{actual_angle_format};
96            this->vertexLoadFunction = {vertex_copy_function};
97            break;
98
99"""
100
101case_vertex_format_template2 = """        case angle::FormatID::{angle_format}:
102            if (tightlyPacked)
103            {{
104                this->metalFormat = {mtl_format_packed};
105                this->actualFormatId = angle::FormatID::{actual_angle_format_packed};
106                this->vertexLoadFunction = {vertex_copy_function_packed};
107            }}
108            else
109            {{
110                this->metalFormat = {mtl_format};
111                this->actualFormatId = angle::FormatID::{actual_angle_format};
112                this->vertexLoadFunction = {vertex_copy_function};
113            }}
114            break;
115
116"""
117
118
119def gen_image_map_switch_simple_case(angle_format, actual_angle_format, angle_to_mtl_map):
120    mtl_format = angle_to_mtl_map[actual_angle_format]
121    return case_image_format_template1.format(
122        angle_format=angle_format, actual_angle_format=actual_angle_format, mtl_format=mtl_format)
123
124
125def gen_image_map_switch_mac_case(angle_format, actual_angle_format, angle_to_mtl_map,
126                                  mac_specific_map, mac_fallbacks):
127    if actual_angle_format in mac_specific_map:
128        # look for the metal format in mac specific table
129        mtl_format = mac_specific_map[actual_angle_format]
130    else:
131        # look for the metal format in common table
132        mtl_format = angle_to_mtl_map[actual_angle_format]
133
134    if actual_angle_format in mac_fallbacks:
135        # This format requires fallback when depth24Stencil8PixelFormatSupported flag is false.
136        # Fallback format:
137        actual_angle_format_fallback = mac_fallbacks[actual_angle_format]
138        if actual_angle_format_fallback in mac_specific_map:
139            # look for the metal format in mac specific table
140            mtl_format_fallback = mac_specific_map[actual_angle_format_fallback]
141        else:
142            # look for the metal format in common table
143            mtl_format_fallback = angle_to_mtl_map[actual_angle_format_fallback]
144        # return if else block:
145        return case_image_format_template2.format(
146            angle_format=angle_format,
147            actual_angle_format=actual_angle_format,
148            mtl_format=mtl_format,
149            actual_angle_format_fallback=actual_angle_format_fallback,
150            mtl_format_fallback=mtl_format_fallback)
151    else:
152        # return ordinary block:
153        return case_image_format_template1.format(
154            angle_format=angle_format,
155            actual_angle_format=actual_angle_format,
156            mtl_format=mtl_format)
157
158
159def gen_image_map_switch_string(image_table):
160    angle_override = image_table["override"]
161    mac_override = image_table["override_mac"]
162    ios_override = image_table["override_ios"]
163    mac_fallbacks = image_table["fallbacks_mac"]
164    angle_to_mtl = image_table["map"]
165    mac_specific_map = image_table["map_mac"]
166    ios_specific_map = image_table["map_ios"]
167
168    switch_data = ''
169
170    def gen_image_map_switch_common_case(angle_format, actual_angle_format):
171        mac_case = gen_image_map_switch_mac_case(angle_format, actual_angle_format, angle_to_mtl,
172                                                 mac_specific_map, mac_fallbacks)
173        non_mac_case = gen_image_map_switch_simple_case(angle_format, actual_angle_format,
174                                                        angle_to_mtl)
175        if mac_case == non_mac_case:
176            return mac_case
177
178        re = ''
179        re += "#if TARGET_OS_OSX || TARGET_OS_MACCATALYST\n"
180        re += mac_case
181        re += "#else  // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n"
182        re += non_mac_case
183        re += "#endif  // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n"
184        return re
185
186    # Common case
187    for angle_format in sorted(angle_to_mtl.keys()):
188        switch_data += gen_image_map_switch_common_case(angle_format, angle_format)
189    for angle_format in sorted(angle_override.keys()):
190        switch_data += gen_image_map_switch_common_case(angle_format, angle_override[angle_format])
191
192    # Mac specific
193    switch_data += "#if TARGET_OS_OSX || TARGET_OS_MACCATALYST\n"
194    for angle_format in sorted(mac_specific_map.keys()):
195        switch_data += gen_image_map_switch_mac_case(angle_format, angle_format, angle_to_mtl,
196                                                     mac_specific_map, mac_fallbacks)
197    for angle_format in sorted(mac_override.keys()):
198        # overide case will always map to a format in common table, i.e. angle_to_mtl
199        switch_data += gen_image_map_switch_mac_case(angle_format, mac_override[angle_format],
200                                                     angle_to_mtl, mac_specific_map, mac_fallbacks)
201
202    # iOS specific
203    switch_data += "#elif TARGET_OS_IOS  // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n"
204    for angle_format in sorted(ios_specific_map.keys()):
205        switch_data += gen_image_map_switch_simple_case(angle_format, angle_format,
206                                                        ios_specific_map)
207    for angle_format in sorted(ios_override.keys()):
208        # overide case will always map to a format in common table, i.e. angle_to_mtl
209        switch_data += gen_image_map_switch_simple_case(angle_format, ios_override[angle_format],
210                                                        angle_to_mtl)
211    switch_data += "#endif  // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n"
212    switch_data += "        default:\n"
213    switch_data += "            this->metalFormat = MTLPixelFormatInvalid;\n"
214    switch_data += "            this->actualFormatId = angle::FormatID::NONE;"
215    return switch_data
216
217
218def gen_vertex_map_switch_case(angle_fmt, actual_angle_fmt, angle_to_mtl_map, override_packed_map):
219    mtl_format = angle_to_mtl_map[actual_angle_fmt]
220    copy_function = angle_format.get_vertex_copy_function(angle_fmt, actual_angle_fmt)
221    if actual_angle_fmt in override_packed_map:
222        # This format has an override when used in tightly packed buffer,
223        # Return if else block
224        angle_fmt_packed = override_packed_map[actual_angle_fmt]
225        mtl_format_packed = angle_to_mtl_map[angle_fmt_packed]
226        copy_function_packed = angle_format.get_vertex_copy_function(angle_fmt, angle_fmt_packed)
227        return case_vertex_format_template2.format(
228            angle_format=angle_fmt,
229            mtl_format_packed=mtl_format_packed,
230            actual_angle_format_packed=angle_fmt_packed,
231            vertex_copy_function_packed=copy_function_packed,
232            mtl_format=mtl_format,
233            actual_angle_format=actual_angle_fmt,
234            vertex_copy_function=copy_function)
235    else:
236        # This format has no packed buffer's override, return ordinary block.
237        return case_vertex_format_template1.format(
238            angle_format=angle_fmt,
239            mtl_format=mtl_format,
240            actual_angle_format=actual_angle_fmt,
241            vertex_copy_function=copy_function)
242
243
244def gen_vertex_map_switch_string(vertex_table):
245    angle_to_mtl = vertex_table["map"]
246    angle_override = vertex_table["override"]
247    override_packed = vertex_table["override_tightly_packed"]
248
249    switch_data = ''
250    for angle_fmt in sorted(angle_to_mtl.keys()):
251        switch_data += gen_vertex_map_switch_case(angle_fmt, angle_fmt, angle_to_mtl,
252                                                  override_packed)
253
254    for angle_fmt in sorted(angle_override.keys()):
255        switch_data += gen_vertex_map_switch_case(angle_fmt, angle_override[angle_fmt],
256                                                  angle_to_mtl, override_packed)
257
258    switch_data += "        default:\n"
259    switch_data += "            this->metalFormat = MTLVertexFormatInvalid;\n"
260    switch_data += "            this->actualFormatId = angle::FormatID::NONE;\n"
261    switch_data += "            this->vertexLoadFunction = nullptr;"
262    return switch_data
263
264
265def main():
266    # auto_script parameters.
267    if len(sys.argv) > 1:
268        inputs = ['../angle_format.py', 'mtl_format_map.json']
269        outputs = ['mtl_format_table_autogen.mm']
270
271        if sys.argv[1] == 'inputs':
272            print ','.join(inputs)
273        elif sys.argv[1] == 'outputs':
274            print ','.join(outputs)
275        else:
276            print('Invalid script parameters')
277            return 1
278        return 0
279
280    data_source_name = 'mtl_format_map.json'
281    map_json = angle_format.load_json(data_source_name)
282    map_image = map_json["image"]
283    map_vertex = map_json["vertex"]
284
285    image_switch_data = gen_image_map_switch_string(map_image)
286
287    vertex_switch_data = gen_vertex_map_switch_string(map_vertex)
288
289    output_cpp = template_autogen_inl.format(
290        script_name=sys.argv[0],
291        copyright_year=date.today().year,
292        data_source_name=data_source_name,
293        angle_image_format_switch=image_switch_data,
294        angle_vertex_format_switch=vertex_switch_data)
295    with open('mtl_format_table_autogen.mm', 'wt') as out_file:
296        out_file.write(output_cpp)
297        out_file.close()
298
299
300if __name__ == '__main__':
301    sys.exit(main())
302