| #!/usr/bin/python |
| # Copyright 2016 The ANGLE Project Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| # |
| # gen_vk_format_table.py: |
| # Code generation for vk format map. See vk_format_map.json for data source. |
| # NOTE: don't run this script directly. Run scripts/run_code_generation.py. |
| |
| from datetime import date |
| import json |
| import math |
| import pprint |
| import os |
| import re |
| import sys |
| |
| sys.path.append('..') |
| import angle_format |
| |
| template_table_autogen_cpp = """// GENERATED FILE - DO NOT EDIT. |
| // Generated by {script_name} using data from {input_file_name} |
| // |
| // Copyright {copyright_year} The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // {out_file_name}: |
| // Queries for full Vulkan format information based on GL format. |
| |
| #include "libANGLE/renderer/vulkan/vk_format_utils.h" |
| |
| #include "image_util/copyimage.h" |
| #include "image_util/generatemip.h" |
| #include "image_util/loadimage.h" |
| |
| using namespace angle; |
| |
| namespace rx |
| {{ |
| |
| namespace vk |
| {{ |
| |
| void Format::initialize(RendererVk *renderer, |
| const angle::Format &angleFormat) |
| {{ |
| switch (angleFormat.id) |
| {{ |
| {format_case_data} |
| default: |
| UNREACHABLE(); |
| break; |
| }} |
| }} |
| |
| }} // namespace vk |
| |
| }} // namespace rx |
| """ |
| |
| empty_format_entry_template = """case angle::FormatID::{format_id}: |
| // This format is not implemented in Vulkan. |
| break; |
| """ |
| |
| format_entry_template = """case angle::FormatID::{format_id}: |
| internalFormat = {internal_format}; |
| {image_template} |
| {buffer_template} |
| break; |
| """ |
| |
| image_basic_template = """actualImageFormatID = {image}; |
| vkImageFormat = {vk_image_format}; |
| imageInitializerFunction = {image_initializer};""" |
| |
| image_struct_template = "{{{image}, {vk_image_format}, {image_initializer}}}" |
| |
| image_fallback_template = """{{ |
| static constexpr ImageFormatInitInfo kInfo[] = {{{image_list}}}; |
| initImageFallback(renderer, kInfo, ArraySize(kInfo)); |
| }}""" |
| |
| buffer_basic_template = """actualBufferFormatID = {buffer}; |
| vkBufferFormat = {vk_buffer_format}; |
| vkBufferFormatIsPacked = {vk_buffer_format_is_packed}; |
| vertexLoadFunction = {vertex_load_function}; |
| vertexLoadRequiresConversion = {vertex_load_converts};""" |
| |
| buffer_struct_template = """{{{buffer}, {vk_buffer_format}, {vk_buffer_format_is_packed}, |
| {vertex_load_function}, {vertex_load_converts}}}""" |
| |
| buffer_fallback_template = """{{ |
| static constexpr BufferFormatInitInfo kInfo[] = {{{buffer_list}}}; |
| initBufferFallback(renderer, kInfo, ArraySize(kInfo)); |
| }}""" |
| |
| |
| def is_packed(format_id): |
| return "true" if "_PACK" in format_id else "false" |
| |
| |
| def verify_vk_map_keys(angle_to_gl, vk_json_data): |
| """Verify that the keys in Vulkan format tables exist in the ANGLE table. If they don't, the |
| entry in the Vulkan file is incorrect and needs to be fixed.""" |
| |
| no_error = True |
| for table in ["map", "overrides", "fallbacks"]: |
| for angle_format in vk_json_data[table].keys(): |
| if not angle_format in angle_to_gl.keys(): |
| print "Invalid format " + angle_format + " in vk_format_map.json in " + table |
| no_error = False |
| |
| return no_error |
| |
| |
| def get_vertex_copy_function(src_format, dst_format, vk_format): |
| if "_PACK" in vk_format: |
| pack_bits = int(re.search(r'_PACK(\d+)', vk_format).group(1)) |
| base_type = None |
| if pack_bits == 8: |
| base_type = 'byte' |
| elif pack_bits == 16: |
| base_type = 'short' |
| elif pack_bits == 32: |
| base_type = 'int' |
| else: |
| return 'nullptr' |
| return 'CopyNativeVertexData<GLu%s, 1, 1, 0>' % base_type |
| if 'R10G10B10A2' in src_format: |
| # When the R10G10B10A2 type can't be used by the vertex buffer, |
| # it needs to be converted to the type which can be used by it. |
| is_signed = 'false' if 'UINT' in src_format or 'UNORM' in src_format or 'USCALED' in src_format else 'true' |
| normalized = 'true' if 'NORM' in src_format else 'false' |
| to_float = 'false' if 'INT' in src_format else 'true' |
| return 'CopyXYZ10W2ToXYZW32FVertexData<%s, %s, %s>' % (is_signed, normalized, to_float) |
| return angle_format.get_vertex_copy_function(src_format, dst_format) |
| |
| |
| def gen_format_case(angle, internal_format, vk_json_data): |
| vk_map = vk_json_data["map"] |
| vk_overrides = vk_json_data["overrides"] |
| vk_fallbacks = vk_json_data["fallbacks"] |
| args = dict( |
| format_id=angle, internal_format=internal_format, image_template="", buffer_template="") |
| |
| if ((angle not in vk_map) and (angle not in vk_overrides) and |
| (angle not in vk_fallbacks)) or angle == 'NONE': |
| return empty_format_entry_template.format(**args) |
| |
| def get_formats(format, type): |
| format = vk_overrides.get(format, {}).get(type, format) |
| if format not in vk_map: |
| return [] |
| fallbacks = vk_fallbacks.get(format, {}).get(type, []) |
| if not isinstance(fallbacks, list): |
| fallbacks = [fallbacks] |
| return [format] + fallbacks |
| |
| def image_args(format): |
| return dict( |
| image="angle::FormatID::" + format, |
| vk_image_format=vk_map[format], |
| image_initializer=angle_format.get_internal_format_initializer( |
| internal_format, format)) |
| |
| def buffer_args(format): |
| vk_buffer_format = vk_map[format] |
| return dict( |
| buffer="angle::FormatID::" + format, |
| vk_buffer_format=vk_buffer_format, |
| vk_buffer_format_is_packed=is_packed(vk_buffer_format), |
| vertex_load_function=get_vertex_copy_function(angle, format, vk_buffer_format), |
| vertex_load_converts='false' if angle == format else 'true', |
| ) |
| |
| images = get_formats(angle, "image") |
| if len(images) == 1: |
| args.update(image_template=image_basic_template) |
| args.update(image_args(images[0])) |
| elif len(images) > 1: |
| args.update( |
| image_template=image_fallback_template, |
| image_list=", ".join(image_struct_template.format(**image_args(i)) for i in images)) |
| |
| buffers = get_formats(angle, "buffer") |
| if len(buffers) == 1: |
| args.update(buffer_template=buffer_basic_template) |
| args.update(buffer_args(buffers[0])) |
| elif len(buffers) > 1: |
| args.update( |
| buffer_template=buffer_fallback_template, |
| buffer_list=", ".join( |
| buffer_struct_template.format(**buffer_args(i)) for i in buffers)) |
| |
| return format_entry_template.format(**args).format(**args) |
| |
| |
| def main(): |
| |
| input_file_name = 'vk_format_map.json' |
| out_file_name = 'vk_format_table_autogen.cpp' |
| |
| # auto_script parameters. |
| if len(sys.argv) > 1: |
| inputs = ['../angle_format.py', '../angle_format_map.json', input_file_name] |
| outputs = [out_file_name] |
| |
| if sys.argv[1] == 'inputs': |
| print ','.join(inputs) |
| elif sys.argv[1] == 'outputs': |
| print ','.join(outputs) |
| else: |
| print('Invalid script parameters') |
| return 1 |
| return 0 |
| |
| angle_to_gl = angle_format.load_inverse_table(os.path.join('..', 'angle_format_map.json')) |
| vk_json_data = angle_format.load_json(input_file_name) |
| |
| if not verify_vk_map_keys(angle_to_gl, vk_json_data): |
| return 1 |
| |
| vk_cases = [ |
| gen_format_case(angle, gl, vk_json_data) for angle, gl in sorted(angle_to_gl.iteritems()) |
| ] |
| |
| output_cpp = template_table_autogen_cpp.format( |
| copyright_year=date.today().year, |
| format_case_data="\n".join(vk_cases), |
| script_name=__file__, |
| out_file_name=out_file_name, |
| input_file_name=input_file_name) |
| |
| with open(out_file_name, 'wt') as out_file: |
| out_file.write(output_cpp) |
| out_file.close() |
| return 0 |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |