• 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 = """actualImageFormatID = {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 = """actualBufferFormatID = {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", "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_fallbacks = vk_json_data["fallbacks"]
144    args = dict(
145        format_id=angle, internal_format=internal_format, image_template="", buffer_template="")
146
147    if ((angle not in vk_map) and (angle not in vk_fallbacks)) or angle == 'NONE':
148        return empty_format_entry_template.format(**args)
149
150    # get_formats returns override format (if any) + fallbacks
151    # this was necessary to support D32_UNORM. There is no appropriate override that allows
152    # us to fallback to D32_FLOAT, so now we leave the image override empty and function will
153    # give us the fallbacks.
154    def get_formats(format, type):
155        fallbacks = vk_fallbacks.get(format, {}).get(type, [])
156        if not isinstance(fallbacks, list):
157            fallbacks = [fallbacks]
158        if format not in vk_map:
159            return fallbacks
160        return [format] + fallbacks
161
162    def image_args(format):
163        return dict(
164            image="angle::FormatID::" + format,
165            vk_image_format=vk_map[format],
166            image_initializer=angle_format.get_internal_format_initializer(
167                internal_format, format))
168
169    def buffer_args(format):
170        vk_buffer_format = vk_map[format]
171        return dict(
172            buffer="angle::FormatID::" + format,
173            vk_buffer_format=vk_buffer_format,
174            vk_buffer_format_is_packed=is_packed(vk_buffer_format),
175            vertex_load_function=get_vertex_copy_function(angle, format, vk_buffer_format),
176            vertex_load_converts='false' if angle == format else 'true',
177        )
178
179    images = get_formats(angle, "image")
180    if len(images) == 1:
181        args.update(image_template=image_basic_template)
182        args.update(image_args(images[0]))
183    elif len(images) > 1:
184        args.update(
185            image_template=image_fallback_template,
186            image_list=", ".join(image_struct_template.format(**image_args(i)) for i in images))
187
188    buffers = get_formats(angle, "buffer")
189    if len(buffers) == 1:
190        args.update(buffer_template=buffer_basic_template)
191        args.update(buffer_args(buffers[0]))
192    elif len(buffers) > 1:
193        args.update(
194            buffer_template=buffer_fallback_template,
195            buffer_list=", ".join(
196                buffer_struct_template.format(**buffer_args(i)) for i in buffers))
197
198    return format_entry_template.format(**args).format(**args)
199
200
201def main():
202
203    input_file_name = 'vk_format_map.json'
204    out_file_name = 'vk_format_table_autogen.cpp'
205
206    # auto_script parameters.
207    if len(sys.argv) > 1:
208        inputs = ['../angle_format.py', '../angle_format_map.json', input_file_name]
209        outputs = [out_file_name]
210
211        if sys.argv[1] == 'inputs':
212            print ','.join(inputs)
213        elif sys.argv[1] == 'outputs':
214            print ','.join(outputs)
215        else:
216            print('Invalid script parameters')
217            return 1
218        return 0
219
220    angle_to_gl = angle_format.load_inverse_table(os.path.join('..', 'angle_format_map.json'))
221    vk_json_data = angle_format.load_json(input_file_name)
222
223    if not verify_vk_map_keys(angle_to_gl, vk_json_data):
224        return 1
225
226    vk_cases = [
227        gen_format_case(angle, gl, vk_json_data) for angle, gl in sorted(angle_to_gl.iteritems())
228    ]
229
230    output_cpp = template_table_autogen_cpp.format(
231        copyright_year=date.today().year,
232        format_case_data="\n".join(vk_cases),
233        script_name=__file__,
234        out_file_name=out_file_name,
235        input_file_name=input_file_name)
236
237    with open(out_file_name, 'wt') as out_file:
238        out_file.write(output_cpp)
239        out_file.close()
240    return 0
241
242
243if __name__ == '__main__':
244    sys.exit(main())
245