Hash :
cb2b5136
        
        Author :
  
        
        Date :
2020-01-10T11:04:38
        
      
Vulkan: Simplify format table generation Remove the "override" table. That gets in the way of some solutions. If a format cannot be supported by a native Vulkan format as indicated in the "map" table, then check fallbacks. Also add support for native RGBA4 and R5G5B5A1 support. Previously those formats would be emulated with RGBA8 due to the override, but now code will check if the native format is available and use it. Bug: angleproject:4282 Change-Id: Ib33ea40543d91a2c2a95075b277f825a8822037c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1994538 Reviewed-by: Tobin Ehlis <tobine@google.com> Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Courtney Goeltzenleuchter <courtneygo@google.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
#!/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", "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_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_fallbacks)) or angle == 'NONE':
        return empty_format_entry_template.format(**args)
    # get_formats returns override format (if any) + fallbacks
    # this was necessary to support D32_UNORM. There is no appropriate override that allows
    # us to fallback to D32_FLOAT, so now we leave the image override empty and function will
    # give us the fallbacks.
    def get_formats(format, type):
        fallbacks = vk_fallbacks.get(format, {}).get(type, [])
        if not isinstance(fallbacks, list):
            fallbacks = [fallbacks]
        if format not in vk_map:
            return 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())