Path: blob/21.2-virgl/src/amd/common/gfx10_format_table.py
7136 views
#1# Copyright 2017 Advanced Micro Devices, Inc.2#3# Permission is hereby granted, free of charge, to any person obtaining a4# copy of this software and associated documentation files (the "Software"),5# to deal in the Software without restriction, including without limitation6# on the rights to use, copy, modify, merge, publish, distribute, sub7# license, and/or sell copies of the Software, and to permit persons to whom8# the Software is furnished to do so, subject to the following conditions:9#10# The above copyright notice and this permission notice (including the next11# paragraph) shall be included in all copies or substantial portions of the12# Software.13#14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17# THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20# USE OR OTHER DEALINGS IN THE SOFTWARE.21#22"""23Script that generates the mapping from Gallium PIPE_FORMAT_xxx to GFX10_FORMAT_xxx enums.24"""2526from __future__ import absolute_import, division, print_function, unicode_literals2728import json29import mako.template30import os31import re32import sys3334AMD_REGISTERS = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../registers"))35UTIL_FORMAT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../../util/format"))36sys.path.extend([AMD_REGISTERS, UTIL_FORMAT])3738from regdb import Object, RegisterDatabase39from u_format_parse import *4041# ----------------------------------------------------------------------------42# Hard-coded mappings4344def hardcoded_format(hw_enum):45return Object(img_format=hw_enum, flags=[])4647HARDCODED = {48'PIPE_FORMAT_Z32_FLOAT_S8X24_UINT': hardcoded_format('X24_8_32_FLOAT'),49'PIPE_FORMAT_Z24_UNORM_S8_UINT': hardcoded_format('8_24_UNORM'),50'PIPE_FORMAT_S8_UINT_Z24_UNORM': hardcoded_format('24_8_UNORM'),51'PIPE_FORMAT_Z32_UNORM': None,52'PIPE_FORMAT_Z16_UNORM_S8_UINT': None,5354'PIPE_FORMAT_R9G9B9E5_FLOAT': hardcoded_format('5_9_9_9_FLOAT'),55'PIPE_FORMAT_R11G11B10_FLOAT': hardcoded_format('10_11_11_FLOAT'), # NOTE: full set of int/unorm/etc. exists5657'PIPE_FORMAT_R8G8_B8G8_UNORM': hardcoded_format('GB_GR_UNORM'),58'PIPE_FORMAT_G8R8_B8R8_UNORM': hardcoded_format('GB_GR_UNORM'),5960'PIPE_FORMAT_R8G8_R8B8_UNORM': hardcoded_format('BG_RG_UNORM'),61'PIPE_FORMAT_G8R8_G8B8_UNORM': hardcoded_format('BG_RG_UNORM'),6263# These mixed channel types are not supported natively64'PIPE_FORMAT_R8SG8SB8UX8U_NORM': None,65'PIPE_FORMAT_R10SG10SB10SA2U_NORM': None,66'PIPE_FORMAT_R5SG5SB6U_NORM': None,6768# Only R8G8_SRGB is supported, not L8A8_SRGB69'PIPE_FORMAT_L8A8_SRGB': None,7071# S3TC72'PIPE_FORMAT_DXT1_RGB': hardcoded_format('BC1_UNORM'),73'PIPE_FORMAT_DXT1_RGBA': hardcoded_format('BC1_UNORM'),74'PIPE_FORMAT_DXT1_SRGB': hardcoded_format('BC1_SRGB'),75'PIPE_FORMAT_DXT1_SRGBA': hardcoded_format('BC1_SRGB'),76'PIPE_FORMAT_DXT3_RGBA': hardcoded_format('BC2_UNORM'),77'PIPE_FORMAT_DXT3_SRGBA': hardcoded_format('BC2_SRGB'),78'PIPE_FORMAT_DXT5_RGBA': hardcoded_format('BC3_UNORM'),79'PIPE_FORMAT_DXT5_SRGBA': hardcoded_format('BC3_SRGB'),8081# RGTC82'PIPE_FORMAT_RGTC1_UNORM': hardcoded_format('BC4_UNORM'),83'PIPE_FORMAT_RGTC1_SNORM': hardcoded_format('BC4_SNORM'),84'PIPE_FORMAT_RGTC2_UNORM': hardcoded_format('BC5_UNORM'),85'PIPE_FORMAT_RGTC2_SNORM': hardcoded_format('BC5_SNORM'),86'PIPE_FORMAT_LATC1_UNORM': hardcoded_format('BC4_UNORM'),87'PIPE_FORMAT_LATC1_SNORM': hardcoded_format('BC4_SNORM'),88'PIPE_FORMAT_LATC2_UNORM': hardcoded_format('BC5_UNORM'),89'PIPE_FORMAT_LATC2_SNORM': hardcoded_format('BC5_SNORM'),9091# BPTC92'PIPE_FORMAT_BPTC_RGB_UFLOAT': hardcoded_format('BC6_UFLOAT'),93'PIPE_FORMAT_BPTC_RGB_FLOAT': hardcoded_format('BC6_SFLOAT'),9495'PIPE_FORMAT_BPTC_RGBA_UNORM': hardcoded_format('BC7_UNORM'),96'PIPE_FORMAT_BPTC_SRGBA': hardcoded_format('BC7_SRGB'),9798'PIPE_FORMAT_R64_UINT': hardcoded_format('32_32_UINT'),99'PIPE_FORMAT_R64_SINT': hardcoded_format('32_32_SINT'),100}101102103# ----------------------------------------------------------------------------104# Main script105106header_template = mako.template.Template("""\107// DO NOT EDIT -- AUTOMATICALLY GENERATED108109#include "gfx10_format_table.h"110#include "amdgfxregs.h"111112#define FMT(_img_format, ...) \113{ .img_format = V_008F0C_GFX10_FORMAT_##_img_format, \114##__VA_ARGS__ }115116const struct gfx10_format gfx10_format_table[PIPE_FORMAT_COUNT] = {117% for pipe_format, args in formats:118% if args is not None:119[${pipe_format}] = FMT(${args}),120% else:121/* ${pipe_format} is not supported */122% endif123% endfor124};125""")126127class Gfx10Format(object):128RE_plain_channel = re.compile(r'X?([0-9]+)')129130def __init__(self, enum_entry):131self.img_format = enum_entry.name[13:]132self.flags = getattr(enum_entry, 'flags', [])133134code = self.img_format.split('_')135136self.plain_chan_sizes = []137for i, chan_code in enumerate(code):138m = self.RE_plain_channel.match(chan_code)139if m is None:140break141self.plain_chan_sizes.append(int(m.group(1)))142# Keep the bit sizes in little-endian order143self.plain_chan_sizes.reverse()144145self.code = code[i:]146147148class Gfx10FormatMapping(object):149def __init__(self, pipe_formats, gfx10_formats):150self.pipe_formats = pipe_formats151self.gfx10_formats = gfx10_formats152153self.plain_gfx10_formats = dict(154(tuple(['_'.join(fmt.code)] + fmt.plain_chan_sizes), fmt)155for fmt in gfx10_formats if fmt.plain_chan_sizes156)157158def map(self, fmt):159if fmt.layout == PLAIN:160chan_type = set([chan.type for chan in fmt.le_channels if chan.type != VOID])161chan_norm = set([chan.norm for chan in fmt.le_channels if chan.type != VOID])162chan_pure = set([chan.pure for chan in fmt.le_channels if chan.type != VOID])163if len(chan_type) > 1 or len(chan_norm) > 1 or len(chan_pure) > 1:164print(('Format {fmt.name} has inconsistent channel types: ' +165'{chan_type} {chan_norm} {chan_pure}')166.format(**locals()),167file=sys.stderr)168return None169170chan_type = chan_type.pop()171chan_norm = chan_norm.pop()172chan_pure = chan_pure.pop()173chan_sizes = [chan.size for chan in fmt.le_channels if chan.size != 0]174175extra_flags = []176177if fmt.colorspace == SRGB:178assert chan_type == UNSIGNED and chan_norm179num_format = 'SRGB'180else:181if chan_type == UNSIGNED:182if chan_pure:183num_format = 'UINT'184elif chan_sizes[0] == 32:185# Shader-based work-around for 32-bit non-pure-integer186num_format = 'UINT'187extra_flags.append('buffers_only')188elif chan_norm:189num_format = 'UNORM'190else:191num_format = 'USCALED'192elif chan_type == SIGNED:193if chan_pure:194num_format = 'SINT'195elif chan_sizes[0] == 32:196# Shader-based work-around for 32-bit non-pure-integer197num_format = 'SINT'198extra_flags.append('buffers_only')199elif chan_norm:200num_format = 'SNORM'201else:202num_format = 'SSCALED'203elif chan_type == FLOAT:204num_format = 'FLOAT'205206if chan_sizes[0] == 64:207# Shader-based work-around for doubles208if len(chan_sizes) % 2 == 1:209# 1 or 3 loads for 1 or 3 double channels210chan_sizes = [32, 32]211else:212# 1 or 2 loads for 2 or 4 double channels213chan_sizes = [32, 32, 32, 32]214extra_flags.append('buffers_only')215else:216# Shader-based work-around217assert chan_type == FIXED218assert chan_sizes[0] == 32219num_format = 'SINT'220extra_flags.append('buffers_only')221222# These are not supported as render targets, so we don't support223# them as images either.224if (len(chan_sizes) == 3 and chan_sizes[0] in (8, 16, 32) and225chan_sizes[0] == chan_sizes[1]):226extra_flags.append('buffers_only')227if chan_sizes[0] in (8, 16):228# Shader-based work-around: one load per channel229chan_sizes = [chan_sizes[0]]230231# Don't expose SRGB buffer formats232if 'buffers_only' in extra_flags and fmt.colorspace == SRGB:233return None234235# Don't support 4_4 because it's not supported as render targets236# and it's useless in other cases.237if len(chan_sizes) == 2 and chan_sizes[0] == 4:238return None239240key = tuple([num_format] + chan_sizes)241if key not in self.plain_gfx10_formats:242return None243244gfx10_fmt = self.plain_gfx10_formats[key]245return Object(246img_format=gfx10_fmt.img_format,247flags=gfx10_fmt.flags + extra_flags,248)249250return None251252253if __name__ == '__main__':254pipe_formats = parse(sys.argv[1])255256with open(sys.argv[2], 'r') as filp:257db = RegisterDatabase.from_json(json.load(filp))258259gfx10_formats = [Gfx10Format(entry) for entry in db.enum('GFX10_FORMAT').entries]260261mapping = Gfx10FormatMapping(pipe_formats, gfx10_formats)262263formats = []264for fmt in pipe_formats:265if fmt.name in HARDCODED:266obj = HARDCODED[fmt.name]267else:268obj = mapping.map(fmt)269270if obj is not None:271args = obj.img_format272if 'buffers_only' in obj.flags:273args += ', .buffers_only = 1'274else:275args = None276formats.append((fmt.name, args))277278print(header_template.render(formats=formats))279280281