Edit

kc3-lang/angle/src/libANGLE/renderer/angle_format.py

Branch :

  • Show log

    Commit

  • Author : Frank Henigman
    Date : 2018-06-24 19:57:31
    Hash : 419acc8f
    Message : Vulkan: Convert streamed vertex data as needed. Add two members to vk::Format: - vertex data copy function - flag indicating if the function converts or not Use the function when streaming vertex data so it gets converted if needed. Add fallbacks for integer formats. These formats will now work everywhere, as long as they are in client memory, not a buffer object. Adjust test expectations accordingly. BUG=angleproject:2405 Change-Id: I677221219d933c35740633a0ab7694293e218177 Reviewed-on: https://chromium-review.googlesource.com/1084328 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/libANGLE/renderer/angle_format.py
  • #!/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.
    #
    # angle_format.py:
    #  Utils for ANGLE formats.
    
    import json
    import os
    import re
    
    kChannels = "ABDGLRSX"
    
    def get_angle_format_map_abs_path():
        return os.path.join(os.path.dirname(os.path.realpath(__file__)), 'angle_format_map.json')
    
    def reject_duplicate_keys(pairs):
        found_keys = {}
        for key, value in pairs:
            if key in found_keys:
               raise ValueError("duplicate key: %r" % (key,))
            else:
               found_keys[key] = value
        return found_keys
    
    def load_json(path):
        with open(path) as map_file:
            return json.loads(map_file.read(), object_pairs_hook=reject_duplicate_keys)
    
    def load_forward_table(path):
        pairs = load_json(path)
        reject_duplicate_keys(pairs)
        return { gl: angle for gl, angle in pairs }
    
    def load_inverse_table(path):
        pairs = load_json(path)
        reject_duplicate_keys(pairs)
        return { angle: gl for gl, angle in pairs }
    
    def load_without_override():
        map_path = get_angle_format_map_abs_path()
        return load_forward_table(map_path)
    
    def load_with_override(override_path):
        results = load_without_override()
        overrides = load_json(override_path)
    
        for k, v in overrides.iteritems():
            results[k] = v
    
        return results
    
    def get_all_angle_formats():
        map_path = get_angle_format_map_abs_path()
        return load_inverse_table(map_path).keys()
    
    def get_component_type(format_id):
        if "SNORM" in format_id:
            return "snorm"
        elif "UNORM" in format_id:
            return "unorm"
        elif "FLOAT" in format_id:
            return "float"
        elif "FIXED" in format_id:
            return "float"
        elif "UINT" in format_id:
            return "uint"
        elif "SINT" in format_id:
            return "int"
        elif "USCALED" in format_id:
            return "uint"
        elif "SSCALED" in format_id:
            return "int"
        elif format_id == "NONE":
            return "none"
        elif "SRGB" in format_id:
            return "unorm"
        elif "TYPELESS" in format_id:
            return "unorm"
        elif format_id == "R9G9B9E5_SHAREDEXP":
            return "float"
        else:
            raise ValueError("Unknown component type for " + format_id)
    
    def get_channel_tokens(format_id):
        r = re.compile(r'([' + kChannels + '][\d]+)')
        return filter(r.match, r.split(format_id))
    
    def get_channels(format_id):
        channels = ''
        tokens = get_channel_tokens(format_id)
        if len(tokens) == 0:
            return None
        for token in tokens:
            channels += token[0].lower()
    
        return channels
    
    def get_bits(format_id):
        bits = {}
        tokens = get_channel_tokens(format_id)
        if len(tokens) == 0:
            return None
        for token in tokens:
            bits[token[0]] = int(token[1:])
        return bits
    
    def get_format_info(format_id):
        return get_component_type(format_id), get_bits(format_id), get_channels(format_id)
    
    # TODO(oetuaho): Expand this code so that it could generate the gl format info tables as well.
    def gl_format_channels(internal_format):
        if internal_format == 'GL_BGR5_A1_ANGLEX':
            return 'bgra'
        if internal_format == 'GL_R11F_G11F_B10F':
            return 'rgb'
        if internal_format == 'GL_RGB5_A1':
            return 'rgba'
        if internal_format.find('GL_RGB10_A2') == 0:
            return 'rgba'
    
        channels_pattern = re.compile('GL_(COMPRESSED_)?(SIGNED_)?(ETC\d_)?([A-Z]+)')
        match = re.search(channels_pattern, internal_format)
        channels_string = match.group(4)
    
        if channels_string == 'ALPHA':
            return 'a'
        if channels_string == 'LUMINANCE':
            if (internal_format.find('ALPHA') >= 0):
                return 'la'
            return 'l'
        if channels_string == 'SRGB':
            if (internal_format.find('ALPHA') >= 0):
                return 'rgba'
            return 'rgb'
        if channels_string == 'DEPTH':
            if (internal_format.find('STENCIL') >= 0):
                return 'ds'
            return 'd'
        if channels_string == 'STENCIL':
            return 's'
        return channels_string.lower()
    
    def get_internal_format_initializer(internal_format, format_id):
        gl_channels = gl_format_channels(internal_format)
        gl_format_no_alpha = gl_channels == 'rgb' or gl_channels == 'l'
        component_type, bits, channels = get_format_info(format_id)
    
        if not gl_format_no_alpha or channels != 'rgba':
            return 'nullptr'
    
        elif 'BC1_' in format_id:
            # BC1 is a special case since the texture data determines whether each block has an alpha channel or not.
            # This if statement is hit by COMPRESSED_RGB_S3TC_DXT1, which is a bit of a mess.
            # TODO(oetuaho): Look into whether COMPRESSED_RGB_S3TC_DXT1 works right in general.
            # Reference: https://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt
            return 'nullptr'
    
        elif component_type == 'uint' and bits['R'] == 8:
            return 'Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>'
        elif component_type == 'unorm' and bits['R'] == 8:
            return 'Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>'
        elif component_type == 'unorm' and bits['R'] == 16:
            return 'Initialize4ComponentData<GLubyte, 0x0000, 0x0000, 0x0000, 0xFFFF>'
        elif component_type == 'int' and bits['R'] == 8:
            return 'Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>'
        elif component_type == 'snorm' and bits['R'] == 8:
            return 'Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x7F>'
        elif component_type == 'snorm' and bits['R'] == 16:
            return 'Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x7FFF>'
        elif component_type == 'float' and bits['R'] == 16:
            return 'Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>'
        elif component_type == 'uint' and bits['R'] == 16:
            return 'Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>'
        elif component_type == 'int' and bits['R'] == 16:
            return 'Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>'
        elif component_type == 'float' and bits['R'] == 32:
            return 'Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>'
        elif component_type == 'int' and bits['R'] == 32:
            return 'Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>'
        elif component_type == 'uint' and bits['R'] == 32:
            return 'Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>'
        else:
            raise ValueError('warning: internal format initializer could not be generated and may be needed for ' + internal_format)
    
    def get_vertex_copy_function(src_format, dst_format):
        if dst_format == "NONE":
            return "nullptr";
    
        num_channel = len(get_channel_tokens(src_format))
        if num_channel < 1 or num_channel > 4:
            return "nullptr";
    
        if 'FIXED' in src_format:
            assert 'FLOAT' in dst_format, ('get_vertex_copy_function: can only convert fixed to float,'
                                           + ' not to ' + dst_format)
            return 'Copy32FixedTo32FVertexData<%d, %d>' % (num_channel, num_channel)
    
        sign = ''
        base_type = None
        if 'FLOAT' in src_format:
            base_type = 'float'
        else:
            bits = get_bits(src_format)
            redbits = bits and bits.get('R')
            if redbits == 8:
                base_type = 'byte'
            elif redbits == 16:
                base_type = 'short'
            elif redbits == 32:
                base_type = 'int'
    
            if 'UINT' in src_format or 'UNORM' in src_format or 'USCALED' in src_format:
                sign = 'u'
    
        if base_type is None:
            return "nullptr";
    
        gl_type = 'GL' + sign + base_type
    
        if src_format == dst_format:
            return 'CopyNativeVertexData<%s, %d, %d, 0>' % (gl_type, num_channel, num_channel)
    
        assert 'FLOAT' in dst_format, ('get_vertex_copy_function: can only convert to float,'
                                       + ' not to ' + dst_format)
        normalized = 'true' if 'NORM' in src_format else 'false'
        return "CopyTo32FVertexData<%s, %d, %d, %s>" % (gl_type, num_channel, num_channel, normalized)