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