From: Nicolai Hähnle Date: Tue, 14 Nov 2017 14:01:13 +0000 (+0100) Subject: radeonsi/gfx10: generate gfx10_format_table.h X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0ffa2292b36346ed4255cb93a1e9544101cb616e;p=mesa.git radeonsi/gfx10: generate gfx10_format_table.h Acked-by: Bas Nieuwenhuizen --- diff --git a/src/gallium/auxiliary/util/u_format.csv b/src/gallium/auxiliary/util/u_format.csv index 039b5fa9141..a7e2dbb70ef 100644 --- a/src/gallium/auxiliary/util/u_format.csv +++ b/src/gallium/auxiliary/util/u_format.csv @@ -26,7 +26,8 @@ ########################################################################### # This CSV file has the input data for u_format.h's struct -# util_format_description. +# util_format_description. It is also used as input for radeonsi's format +# mapping. # # Each format entry contains: # - name, per enum pipe_format diff --git a/src/gallium/drivers/radeonsi/Makefile.sources b/src/gallium/drivers/radeonsi/Makefile.sources index 0c54ba75dcc..ab0ba93b02a 100644 --- a/src/gallium/drivers/radeonsi/Makefile.sources +++ b/src/gallium/drivers/radeonsi/Makefile.sources @@ -1,4 +1,5 @@ GENERATED_SOURCES := \ + gfx10_format_table.h \ si_driinfo.h C_SOURCES := \ diff --git a/src/gallium/drivers/radeonsi/gfx10_format_table.py b/src/gallium/drivers/radeonsi/gfx10_format_table.py new file mode 100644 index 00000000000..48a2f8870eb --- /dev/null +++ b/src/gallium/drivers/radeonsi/gfx10_format_table.py @@ -0,0 +1,273 @@ +# +# Copyright 2017 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +# USE OR OTHER DEALINGS IN THE SOFTWARE. +# +""" +Script that generates the mapping from Gallium PIPE_FORMAT_xxx to gfx10 +IMG_FORMAT_xxx enums. +""" + +from __future__ import absolute_import, division, print_function, unicode_literals + +import json +import mako.template +import os +import re +import sys + +AMD_REGISTERS = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../../../amd/registers")) +GALLIUM_UTIL = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../../auxiliary/util")) +sys.path.extend([AMD_REGISTERS, GALLIUM_UTIL]) + +from regdb import Object, RegisterDatabase +from u_format_parse import * + +# ---------------------------------------------------------------------------- +# Hard-coded mappings + +def hardcoded_format(hw_enum): + return Object(img_format=hw_enum, flags=[]) + +HARDCODED = { + 'PIPE_FORMAT_Z32_FLOAT_S8X24_UINT': hardcoded_format('X24_8_32_FLOAT'), + 'PIPE_FORMAT_Z24_UNORM_S8_UINT': hardcoded_format('8_24_UNORM'), + 'PIPE_FORMAT_S8_UINT_Z24_UNORM': hardcoded_format('24_8_UNORM'), + 'PIPE_FORMAT_Z32_UNORM': None, + + 'PIPE_FORMAT_R9G9B9E5_FLOAT': hardcoded_format('5_9_9_9_FLOAT'), + 'PIPE_FORMAT_R11G11B10_FLOAT': hardcoded_format('10_11_11_FLOAT'), # NOTE: full set of int/unorm/etc. exists + + 'PIPE_FORMAT_R8G8_B8G8_UNORM': hardcoded_format('GB_GR_UNORM'), + 'PIPE_FORMAT_G8R8_B8R8_UNORM': hardcoded_format('GB_GR_UNORM'), + + 'PIPE_FORMAT_R8G8_R8B8_UNORM': hardcoded_format('BG_RG_UNORM'), + 'PIPE_FORMAT_G8R8_G8B8_UNORM': hardcoded_format('BG_RG_UNORM'), + + # These mixed channel types are not supported natively + 'PIPE_FORMAT_R8SG8SB8UX8U_NORM': None, + 'PIPE_FORMAT_R10SG10SB10SA2U_NORM': None, + 'PIPE_FORMAT_R5SG5SB6U_NORM': None, + + # Only R8G8_SRGB is supported, not L8A8_SRGB + 'PIPE_FORMAT_L8A8_SRGB': None, + + # S3TC + 'PIPE_FORMAT_DXT1_RGB': hardcoded_format('BC1_UNORM'), + 'PIPE_FORMAT_DXT1_RGBA': hardcoded_format('BC1_UNORM'), + 'PIPE_FORMAT_DXT1_SRGB': hardcoded_format('BC1_SRGB'), + 'PIPE_FORMAT_DXT1_SRGBA': hardcoded_format('BC1_SRGB'), + 'PIPE_FORMAT_DXT3_RGBA': hardcoded_format('BC2_UNORM'), + 'PIPE_FORMAT_DXT3_SRGBA': hardcoded_format('BC2_SRGB'), + 'PIPE_FORMAT_DXT5_RGBA': hardcoded_format('BC3_UNORM'), + 'PIPE_FORMAT_DXT5_SRGBA': hardcoded_format('BC3_SRGB'), + + # RGTC + 'PIPE_FORMAT_RGTC1_UNORM': hardcoded_format('BC4_UNORM'), + 'PIPE_FORMAT_RGTC1_SNORM': hardcoded_format('BC4_SNORM'), + 'PIPE_FORMAT_RGTC2_UNORM': hardcoded_format('BC5_UNORM'), + 'PIPE_FORMAT_RGTC2_SNORM': hardcoded_format('BC5_SNORM'), + 'PIPE_FORMAT_LATC1_UNORM': hardcoded_format('BC4_UNORM'), + 'PIPE_FORMAT_LATC1_SNORM': hardcoded_format('BC4_SNORM'), + 'PIPE_FORMAT_LATC2_UNORM': hardcoded_format('BC5_UNORM'), + 'PIPE_FORMAT_LATC2_SNORM': hardcoded_format('BC5_SNORM'), + + # BPTC + 'PIPE_FORMAT_BPTC_RGB_UFLOAT': hardcoded_format('BC6_UFLOAT'), + 'PIPE_FORMAT_BPTC_RGB_FLOAT': hardcoded_format('BC6_SFLOAT'), + + 'PIPE_FORMAT_BPTC_RGBA_UNORM': hardcoded_format('BC7_UNORM'), + 'PIPE_FORMAT_BPTC_SRGBA': hardcoded_format('BC7_SRGB'), +} + + +# ---------------------------------------------------------------------------- +# Main script + +header_template = mako.template.Template("""\ +// DO NOT EDIT -- AUTOMATICALLY GENERATED + +#define FMT(_img_format, ...) \ + { .img_format = V_008F0C_IMG_FORMAT_##_img_format, \ + ##__VA_ARGS__ } + +static const struct gfx10_format gfx10_format_table[PIPE_FORMAT_COUNT] = { +% for pipe_format, args in formats: + % if args is not None: + [${pipe_format}] = FMT(${args}), + % else: +/* ${pipe_format} is not supported */ + % endif +% endfor +}; +""") + +class Gfx10Format(object): + RE_plain_channel = re.compile(r'X?([0-9]+)') + + def __init__(self, enum_entry): + self.img_format = enum_entry.name[11:] + self.flags = getattr(enum_entry, 'flags', []) + + code = self.img_format.split('_') + + self.plain_chan_sizes = [] + for i, chan_code in enumerate(code): + m = self.RE_plain_channel.match(chan_code) + if m is None: + break + self.plain_chan_sizes.append(int(m.group(1))) + # Keep the bit sizes in little-endian order + self.plain_chan_sizes.reverse() + + self.code = code[i:] + + +class Gfx10FormatMapping(object): + def __init__(self, pipe_formats, gfx10_formats): + self.pipe_formats = pipe_formats + self.gfx10_formats = gfx10_formats + + self.plain_gfx10_formats = dict( + (tuple(['_'.join(fmt.code)] + fmt.plain_chan_sizes), fmt) + for fmt in gfx10_formats if fmt.plain_chan_sizes + ) + + def map(self, fmt): + if fmt.layout == PLAIN: + chan_type = set([chan.type for chan in fmt.le_channels if chan.type != VOID]) + chan_norm = set([chan.norm for chan in fmt.le_channels if chan.type != VOID]) + chan_pure = set([chan.pure for chan in fmt.le_channels if chan.type != VOID]) + if len(chan_type) > 1 or len(chan_norm) > 1 or len(chan_pure) > 1: + print(('Format {fmt.name} has inconsistent channel types: ' + + '{chan_type} {chan_norm} {chan_pure}') + .format(**locals()), + file=sys.stderr) + return None + + chan_type = chan_type.pop() + chan_norm = chan_norm.pop() + chan_pure = chan_pure.pop() + chan_sizes = [chan.size for chan in fmt.le_channels if chan.size != 0] + + extra_flags = [] + + if fmt.colorspace == SRGB: + assert chan_type == UNSIGNED and chan_norm + num_format = 'SRGB' + else: + if chan_type == UNSIGNED: + if chan_pure: + num_format = 'UINT' + elif chan_sizes[0] == 32: + # Shader-based work-around for 32-bit non-pure-integer + num_format = 'UINT' + extra_flags.append('buffers_only') + elif chan_norm: + num_format = 'UNORM' + else: + num_format = 'USCALED' + elif chan_type == SIGNED: + if chan_pure: + num_format = 'SINT' + elif chan_sizes[0] == 32: + # Shader-based work-around for 32-bit non-pure-integer + num_format = 'SINT' + extra_flags.append('buffers_only') + elif chan_norm: + num_format = 'SNORM' + else: + num_format = 'SSCALED' + elif chan_type == FLOAT: + num_format = 'FLOAT' + + if chan_sizes[0] == 64: + # Shader-based work-around for doubles + if len(chan_sizes) % 2 == 1: + # 1 or 3 loads for 1 or 3 double channels + chan_sizes = [32, 32] + else: + # 1 or 2 loads for 2 or 4 double channels + chan_sizes = [32, 32, 32, 32] + extra_flags.append('buffers_only') + else: + # Shader-based work-around + assert chan_type == FIXED + assert chan_sizes[0] == 32 + num_format = 'SINT' + extra_flags.append('buffers_only') + + # These are not supported as render targets, so we don't support + # them as images either. + if (len(chan_sizes) == 3 and chan_sizes[0] in (8, 16, 32) and + chan_sizes[0] == chan_sizes[1]): + extra_flags.append('buffers_only') + if chan_sizes[0] in (8, 16): + # Shader-based work-around: one load per channel + chan_sizes = [chan_sizes[0]] + + # Don't expose SRGB buffer formats + if 'buffers_only' in extra_flags and fmt.colorspace == SRGB: + return None + + # Don't support 4_4 because it's not supported as render targets + # and it's useless in other cases. + if len(chan_sizes) == 2 and chan_sizes[0] == 4: + return None + + key = tuple([num_format] + chan_sizes) + if key not in self.plain_gfx10_formats: + return None + + gfx10_fmt = self.plain_gfx10_formats[key] + return Object( + img_format=gfx10_fmt.img_format, + flags=gfx10_fmt.flags + extra_flags, + ) + + return None + + +if __name__ == '__main__': + pipe_formats = parse(sys.argv[1]) + + with open(sys.argv[2], 'r') as filp: + db = RegisterDatabase.from_json(json.load(filp)) + + gfx10_formats = [Gfx10Format(entry) for entry in db.enum('IMG_FORMAT').entries] + + mapping = Gfx10FormatMapping(pipe_formats, gfx10_formats) + + formats = [] + for fmt in pipe_formats: + if fmt.name in HARDCODED: + obj = HARDCODED[fmt.name] + else: + obj = mapping.map(fmt) + + if obj is not None: + args = obj.img_format + if 'buffers_only' in obj.flags: + args += ', .buffers_only = 1' + else: + args = None + formats.append((fmt.name, args)) + + print(header_template.render(formats=formats)) diff --git a/src/gallium/drivers/radeonsi/meson.build b/src/gallium/drivers/radeonsi/meson.build index 6d5e9339585..d733452300d 100644 --- a/src/gallium/drivers/radeonsi/meson.build +++ b/src/gallium/drivers/radeonsi/meson.build @@ -99,9 +99,21 @@ si_driinfo_h = custom_target( capture : true, ) +gfx10_format_table_h = custom_target( + 'gfx10_format_table.h', + input : files( + 'gfx10_format_table.py', + '../../auxiliary/util/u_format.csv', '../../../amd/registers/gfx10-rsrc.json' + ), + output : 'gfx10_format_table.h', + command : [prog_python, '@INPUT@'], + capture : true, + depend_files : ['../../../amd/registers/regdb.py'] +) + libradeonsi = static_library( 'radeonsi', - [files_libradeonsi, si_driinfo_h, sid_tables_h], + [files_libradeonsi, si_driinfo_h, sid_tables_h, gfx10_format_table_h], include_directories : [ inc_src, inc_include, inc_gallium, inc_gallium_aux, inc_amd_common, inc_gallium_drivers, diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 07464d28056..ca1671e021c 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -34,6 +34,17 @@ #include "util/u_upload_mgr.h" #include "util/fast_idiv_by_const.h" +struct gfx10_format { + unsigned img_format:9; + + /* Various formats are only supported with workarounds for vertex fetch, + * and some 32_32_32 formats are supported natively, but only for buffers + * (possibly with some image support, actually, but no filtering). */ + bool buffers_only:1; +}; + +#include "gfx10_format_table.h" + static unsigned si_map_swizzle(unsigned swizzle) { switch (swizzle) {