1#!/usr/bin/python3 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 10import json 11import math 12import pprint 13import os 14import re 15import sys 16 17sys.path.append('..') 18import angle_format 19 20template_table_autogen_cpp = """// GENERATED FILE - DO NOT EDIT. 21// Generated by {script_name} using data from {input_file_name} 22// 23// Copyright 2020 The ANGLE Project Authors. All rights reserved. 24// Use of this source code is governed by a BSD-style license that can be 25// found in the LICENSE file. 26// 27// {out_file_name}: 28// Queries for full Vulkan format information based on GL format. 29 30#include "libANGLE/renderer/vulkan/vk_format_utils.h" 31 32#include "image_util/copyimage.h" 33#include "image_util/generatemip.h" 34#include "image_util/loadimage.h" 35 36using namespace angle; 37 38namespace rx 39{{ 40namespace vk 41{{ 42 43void Format::initialize(RendererVk *renderer, 44 const angle::Format &angleFormat) 45{{ 46 switch (angleFormat.id) 47 {{ 48{format_case_data} 49 default: 50 UNREACHABLE(); 51 break; 52 }} 53}} 54 55VkFormat GetVkFormatFromFormatID(angle::FormatID formatID) 56{{ 57 static constexpr angle::FormatMap<VkFormat> kMap = {{ 58{format_id_cases} 59 }}; 60 61 return kMap[formatID]; 62}} 63 64angle::FormatID GetFormatIDFromVkFormat(VkFormat vkFormat) 65{{ 66 switch (vkFormat) 67 {{ 68{vk_format_cases} 69 default: 70 return angle::FormatID::NONE; 71 }} 72}} 73}} // namespace vk 74}} // namespace rx 75""" 76 77empty_format_entry_template = """case angle::FormatID::{format_id}: 78// This format is not implemented in Vulkan. 79break; 80""" 81 82format_entry_template = """case angle::FormatID::{format_id}: 83intendedGLFormat = {internal_format}; 84{image_template} 85{buffer_template} 86break; 87""" 88 89image_basic_template = """actualImageFormatID = {image}; 90imageInitializerFunction = {image_initializer};""" 91 92image_struct_template = "{{{image}, {image_initializer}}}" 93 94image_fallback_template = """{{ 95static constexpr ImageFormatInitInfo kInfo[] = {{{image_list}}}; 96initImageFallback(renderer, kInfo, ArraySize(kInfo)); 97}}""" 98 99buffer_basic_template = """actualBufferFormatID = {buffer}; 100vkBufferFormatIsPacked = {vk_buffer_format_is_packed}; 101vertexLoadFunction = {vertex_load_function}; 102vertexLoadRequiresConversion = {vertex_load_converts};""" 103 104buffer_struct_template = """{{{buffer}, {vk_buffer_format_is_packed}, 105{vertex_load_function}, {vertex_load_converts}}}""" 106 107buffer_fallback_template = """{{ 108static constexpr BufferFormatInitInfo kInfo[] = {{{buffer_list}}}; 109initBufferFallback(renderer, kInfo, ArraySize(kInfo), {buffer_compressed_offset}); 110}}""" 111 112 113def is_packed(format_id): 114 return "true" if "_PACK" in format_id else "false" 115 116 117def verify_vk_map_keys(angle_to_gl, vk_json_data): 118 """Verify that the keys in Vulkan format tables exist in the ANGLE table. If they don't, the 119 entry in the Vulkan file is incorrect and needs to be fixed.""" 120 121 no_error = True 122 for table in ["map", "fallbacks"]: 123 for angle_format in vk_json_data[table].keys(): 124 if not angle_format in angle_to_gl.keys(): 125 print("Invalid format " + angle_format + " in vk_format_map.json in " + table) 126 no_error = False 127 128 return no_error 129 130 131def get_vertex_copy_function(src_format, dst_format, vk_format): 132 if "_PACK" in vk_format: 133 pack_bits = int(re.search(r'_PACK(\d+)', vk_format).group(1)) 134 base_type = None 135 if pack_bits == 8: 136 base_type = 'byte' 137 elif pack_bits == 16: 138 base_type = 'short' 139 elif pack_bits == 32: 140 base_type = 'int' 141 else: 142 return 'nullptr' 143 return 'CopyNativeVertexData<GLu%s, 1, 1, 0>' % base_type 144 if 'R10G10B10A2' in src_format: 145 # When the R10G10B10A2 type can't be used by the vertex buffer, 146 # it needs to be converted to the type which can be used by it. 147 is_signed = 'false' if 'UINT' in src_format or 'UNORM' in src_format or 'USCALED' in src_format else 'true' 148 normalized = 'true' if 'NORM' in src_format else 'false' 149 to_float = 'false' if 'INT' in src_format else 'true' 150 to_half = to_float 151 return 'CopyXYZ10W2ToXYZWFloatVertexData<%s, %s, %s, %s>' % (is_signed, normalized, 152 to_float, to_half) 153 return angle_format.get_vertex_copy_function(src_format, dst_format) 154 155 156def gen_format_case(angle, internal_format, vk_json_data): 157 vk_map = vk_json_data["map"] 158 vk_fallbacks = vk_json_data["fallbacks"] 159 args = dict( 160 format_id=angle, internal_format=internal_format, image_template="", buffer_template="") 161 162 if ((angle not in vk_map) and (angle not in vk_fallbacks)): 163 return empty_format_entry_template.format(**args) 164 165 # get_formats returns override format (if any) + fallbacks 166 # this was necessary to support D32_UNORM. There is no appropriate override that allows 167 # us to fallback to D32_FLOAT, so now we leave the image override empty and function will 168 # give us the fallbacks. 169 def get_formats(format, type): 170 fallbacks = vk_fallbacks.get(format, {}).get(type, []) 171 if not isinstance(fallbacks, list): 172 fallbacks = [fallbacks] 173 174 compressed = vk_fallbacks.get(format, {}).get(type + "_compressed", []) 175 if not isinstance(compressed, list): 176 compressed = [compressed] 177 178 fallbacks += compressed 179 180 if format in vk_map: 181 fallbacks = [format] + fallbacks 182 183 return (fallbacks, len(fallbacks) - len(compressed)) 184 185 def image_args(format): 186 return dict( 187 image="angle::FormatID::" + format, 188 image_initializer=angle_format.get_internal_format_initializer( 189 internal_format, format)) 190 191 def buffer_args(format): 192 vk_buffer_format = vk_map[format] 193 return dict( 194 buffer="angle::FormatID::" + format, 195 vk_buffer_format_is_packed=is_packed(vk_buffer_format), 196 vertex_load_function=get_vertex_copy_function(angle, format, vk_buffer_format), 197 vertex_load_converts='false' if angle == format else 'true', 198 ) 199 200 images, images_compressed_offset = get_formats(angle, "image") 201 if len(images) == 1: 202 args.update(image_template=image_basic_template) 203 args.update(image_args(images[0])) 204 elif len(images) > 1: 205 args.update( 206 image_template=image_fallback_template, 207 image_list=", ".join(image_struct_template.format(**image_args(i)) for i in images)) 208 209 buffers, buffers_compressed_offset = get_formats(angle, "buffer") 210 if len(buffers) == 1: 211 args.update(buffer_template=buffer_basic_template) 212 args.update(buffer_args(buffers[0])) 213 elif len(buffers) > 1: 214 args.update( 215 buffer_template=buffer_fallback_template, 216 buffer_list=", ".join( 217 buffer_struct_template.format(**buffer_args(i)) for i in buffers), 218 buffer_compressed_offset=buffers_compressed_offset) 219 220 return format_entry_template.format(**args).format(**args) 221 222 223def get_format_id_case(format_id, vk_format): 224 return "{angle::FormatID::%s, %s}" % (format_id, vk_format) 225 226 227def get_vk_format_case(format_id, vk_format): 228 return """\ 229 case %s: 230 return angle::FormatID::%s; 231""" % (vk_format, format_id) 232 233 234def main(): 235 236 input_file_name = 'vk_format_map.json' 237 out_file_name = 'vk_format_table_autogen.cpp' 238 239 # auto_script parameters. 240 if len(sys.argv) > 1: 241 inputs = ['../angle_format.py', '../angle_format_map.json', input_file_name] 242 outputs = [out_file_name] 243 244 if sys.argv[1] == 'inputs': 245 print(','.join(inputs)) 246 elif sys.argv[1] == 'outputs': 247 print(','.join(outputs)) 248 else: 249 print('Invalid script parameters') 250 return 1 251 return 0 252 253 angle_to_gl = angle_format.load_inverse_table(os.path.join('..', 'angle_format_map.json')) 254 vk_json_data = angle_format.load_json(input_file_name) 255 256 if not verify_vk_map_keys(angle_to_gl, vk_json_data): 257 return 1 258 259 format_id_cases = [ 260 get_format_id_case(format_id, vk_format) 261 for format_id, vk_format in sorted(vk_json_data["map"].items()) 262 ] 263 264 vk_format_cases = [ 265 get_vk_format_case(format_id, vk_format) 266 for format_id, vk_format in sorted(vk_json_data["map"].items()) 267 ] 268 269 vk_cases = [ 270 gen_format_case(angle, gl, vk_json_data) for angle, gl in sorted(angle_to_gl.items()) 271 ] 272 273 output_cpp = template_table_autogen_cpp.format( 274 format_case_data="\n".join(vk_cases), 275 format_id_cases=",\n".join(format_id_cases), 276 vk_format_cases="".join(vk_format_cases), 277 script_name=os.path.basename(__file__), 278 out_file_name=out_file_name, 279 input_file_name=input_file_name) 280 281 with open(out_file_name, 'wt') as out_file: 282 out_file.write(output_cpp) 283 out_file.close() 284 return 0 285 286 287if __name__ == '__main__': 288 sys.exit(main()) 289