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