• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python
2# Copyright 2016 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_vk_format_table.py:
7#  Code generation for vk format map. See vk_format_map.json for data source.
8#  NOTE: don't run this script directly. Run scripts/run_code_generation.py.
9
10from datetime import date
11import json
12import math
13import pprint
14import os
15import re
16import sys
17
18sys.path.append('..')
19import angle_format
20
21template_table_autogen_cpp = """// GENERATED FILE - DO NOT EDIT.
22// Generated by {script_name} using data from {input_file_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// {out_file_name}:
29//   Queries for full Vulkan format information based on GL format.
30
31#include "libANGLE/renderer/vulkan/vk_format_utils.h"
32
33#include "image_util/copyimage.h"
34#include "image_util/generatemip.h"
35#include "image_util/loadimage.h"
36
37using namespace angle;
38
39namespace rx
40{{
41
42namespace vk
43{{
44
45void Format::initialize(RendererVk *renderer,
46                        const angle::Format &angleFormat)
47{{
48    switch (angleFormat.id)
49    {{
50{format_case_data}
51        default:
52            UNREACHABLE();
53            break;
54    }}
55}}
56
57}}  // namespace vk
58
59}}  // namespace rx
60"""
61
62empty_format_entry_template = """case angle::FormatID::{format_id}:
63// This format is not implemented in Vulkan.
64break;
65"""
66
67format_entry_template = """case angle::FormatID::{format_id}:
68internalFormat = {internal_format};
69{image_template}
70{buffer_template}
71break;
72"""
73
74image_basic_template = """imageFormatID = {image};
75vkImageFormat = {vk_image_format};
76imageInitializerFunction = {image_initializer};"""
77
78image_struct_template = "{{{image}, {vk_image_format}, {image_initializer}}}"
79
80image_fallback_template = """{{
81static constexpr ImageFormatInitInfo kInfo[] = {{{image_list}}};
82initImageFallback(renderer, kInfo, ArraySize(kInfo));
83}}"""
84
85buffer_basic_template = """bufferFormatID = {buffer};
86vkBufferFormat = {vk_buffer_format};
87vkBufferFormatIsPacked = {vk_buffer_format_is_packed};
88vertexLoadFunction = {vertex_load_function};
89vertexLoadRequiresConversion = {vertex_load_converts};"""
90
91buffer_struct_template = """{{{buffer}, {vk_buffer_format}, {vk_buffer_format_is_packed},
92{vertex_load_function}, {vertex_load_converts}}}"""
93
94buffer_fallback_template = """{{
95static constexpr BufferFormatInitInfo kInfo[] = {{{buffer_list}}};
96initBufferFallback(renderer, kInfo, ArraySize(kInfo));
97}}"""
98
99
100def is_packed(format_id):
101    return "true" if "_PACK" in format_id else "false"
102
103
104def verify_vk_map_keys(angle_to_gl, vk_json_data):
105    """Verify that the keys in Vulkan format tables exist in the ANGLE table.  If they don't, the
106    entry in the Vulkan file is incorrect and needs to be fixed."""
107
108    no_error = True
109    for table in ["map", "overrides", "fallbacks"]:
110        for angle_format in vk_json_data[table].keys():
111            if not angle_format in angle_to_gl.keys():
112                print "Invalid format " + angle_format + " in vk_format_map.json in " + table
113                no_error = False
114
115    return no_error
116
117
118def get_vertex_copy_function(src_format, dst_format, vk_format):
119    if "_PACK" in vk_format:
120        pack_bits = int(re.search(r'_PACK(\d+)', vk_format).group(1))
121        base_type = None
122        if pack_bits == 8:
123            base_type = 'byte'
124        elif pack_bits == 16:
125            base_type = 'short'
126        elif pack_bits == 32:
127            base_type = 'int'
128        else:
129            return 'nullptr'
130        return 'CopyNativeVertexData<GLu%s, 1, 1, 0>' % base_type
131    if 'R10G10B10A2' in src_format:
132        # When the R10G10B10A2 type can't be used by the vertex buffer,
133        # it needs to be converted to the type which can be used by it.
134        is_signed = 'false' if 'UINT' in src_format or 'UNORM' in src_format or 'USCALED' in src_format else 'true'
135        normalized = 'true' if 'NORM' in src_format else 'false'
136        to_float = 'false' if 'INT' in src_format else 'true'
137        return 'CopyXYZ10W2ToXYZW32FVertexData<%s, %s, %s>' % (is_signed, normalized, to_float)
138    return angle_format.get_vertex_copy_function(src_format, dst_format)
139
140
141def gen_format_case(angle, internal_format, vk_json_data):
142    vk_map = vk_json_data["map"]
143    vk_overrides = vk_json_data["overrides"]
144    vk_fallbacks = vk_json_data["fallbacks"]
145    args = dict(
146        format_id=angle, internal_format=internal_format, image_template="", buffer_template="")
147
148    if ((angle not in vk_map) and (angle not in vk_overrides) and
149        (angle not in vk_fallbacks)) or angle == 'NONE':
150        return empty_format_entry_template.format(**args)
151
152    def get_formats(format, type):
153        format = vk_overrides.get(format, {}).get(type, format)
154        if format not in vk_map:
155            return []
156        fallbacks = vk_fallbacks.get(format, {}).get(type, [])
157        if not isinstance(fallbacks, list):
158            fallbacks = [fallbacks]
159        return [format] + fallbacks
160
161    def image_args(format):
162        return dict(
163            image="angle::FormatID::" + format,
164            vk_image_format=vk_map[format],
165            image_initializer=angle_format.get_internal_format_initializer(
166                internal_format, format))
167
168    def buffer_args(format):
169        vk_buffer_format = vk_map[format]
170        return dict(
171            buffer="angle::FormatID::" + format,
172            vk_buffer_format=vk_buffer_format,
173            vk_buffer_format_is_packed=is_packed(vk_buffer_format),
174            vertex_load_function=get_vertex_copy_function(angle, format, vk_buffer_format),
175            vertex_load_converts='false' if angle == format else 'true',
176        )
177
178    images = get_formats(angle, "image")
179    if len(images) == 1:
180        args.update(image_template=image_basic_template)
181        args.update(image_args(images[0]))
182    elif len(images) > 1:
183        args.update(
184            image_template=image_fallback_template,
185            image_list=", ".join(image_struct_template.format(**image_args(i)) for i in images))
186
187    buffers = get_formats(angle, "buffer")
188    if len(buffers) == 1:
189        args.update(buffer_template=buffer_basic_template)
190        args.update(buffer_args(buffers[0]))
191    elif len(buffers) > 1:
192        args.update(
193            buffer_template=buffer_fallback_template,
194            buffer_list=", ".join(
195                buffer_struct_template.format(**buffer_args(i)) for i in buffers))
196
197    return format_entry_template.format(**args).format(**args)
198
199
200def main():
201
202    input_file_name = 'vk_format_map.json'
203    out_file_name = 'vk_format_table_autogen.cpp'
204
205    # auto_script parameters.
206    if len(sys.argv) > 1:
207        inputs = ['../angle_format.py', '../angle_format_map.json', input_file_name]
208        outputs = [out_file_name]
209
210        if sys.argv[1] == 'inputs':
211            print ','.join(inputs)
212        elif sys.argv[1] == 'outputs':
213            print ','.join(outputs)
214        else:
215            print('Invalid script parameters')
216            return 1
217        return 0
218
219    angle_to_gl = angle_format.load_inverse_table(os.path.join('..', 'angle_format_map.json'))
220    vk_json_data = angle_format.load_json(input_file_name)
221
222    if not verify_vk_map_keys(angle_to_gl, vk_json_data):
223        return 1
224
225    vk_cases = [
226        gen_format_case(angle, gl, vk_json_data) for angle, gl in sorted(angle_to_gl.iteritems())
227    ]
228
229    output_cpp = template_table_autogen_cpp.format(
230        copyright_year=date.today().year,
231        format_case_data="\n".join(vk_cases),
232        script_name=__file__,
233        out_file_name=out_file_name,
234        input_file_name=input_file_name)
235
236    with open(out_file_name, 'wt') as out_file:
237        out_file.write(output_cpp)
238        out_file.close()
239    return 0
240
241
242if __name__ == '__main__':
243    sys.exit(main())
244