From 3dc5ec5d167fba9cc44793499fd74fbc75beb627 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Tue, 25 Jun 2019 18:15:14 +0200 Subject: [PATCH] radv/gfx10: generate gfx10_format_table.h Signed-off-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen --- src/amd/vulkan/gfx10_format_table.py | 274 +++++++++++++++++++++++++++ src/amd/vulkan/meson.build | 11 +- src/amd/vulkan/radv_private.h | 11 ++ 3 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 src/amd/vulkan/gfx10_format_table.py diff --git a/src/amd/vulkan/gfx10_format_table.py b/src/amd/vulkan/gfx10_format_table.py new file mode 100644 index 00000000000..3660781de4e --- /dev/null +++ b/src/amd/vulkan/gfx10_format_table.py @@ -0,0 +1,274 @@ +# +# 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]), "../registers")) +#GALLIUM_UTIL = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../../auxiliary/util")) +sys.path.extend([AMD_REGISTERS]) + +from regdb import Object, RegisterDatabase +from vk_format_parse import * +#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[VK_FORMAT_RANGE_SIZE] = { +% 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/amd/vulkan/meson.build b/src/amd/vulkan/meson.build index 2ff2fb34465..80f2d8fc0b0 100644 --- a/src/amd/vulkan/meson.build +++ b/src/amd/vulkan/meson.build @@ -48,6 +48,15 @@ amd_vk_format_table_c = custom_target( capture : true, ) +radv_gfx10_format_table_h = custom_target( + 'radv_gfx10_format_table.h', + input : ['gfx10_format_table.py', 'vk_format_layout.csv', '../registers/gfx10-rsrc.json'], + output : 'gfx10_format_table.h', + command : [prog_python, '@INPUT@'], + capture : true, + depend_files : files('../registers/regdb.py') +) + libradv_files = files( 'winsys/amdgpu/radv_amdgpu_bo.c', 'winsys/amdgpu/radv_amdgpu_bo.h', @@ -138,7 +147,7 @@ endif libvulkan_radeon = shared_library( 'vulkan_radeon', - [libradv_files, radv_entrypoints, radv_extensions_c, amd_vk_format_table_c, sha1_h, xmlpool_options_h], + [libradv_files, radv_entrypoints, radv_extensions_c, amd_vk_format_table_c, sha1_h, xmlpool_options_h, radv_gfx10_format_table_h], include_directories : [ inc_common, inc_amd, inc_amd_common, inc_compiler, inc_util, inc_vulkan_wsi, ], diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 7660087f15f..bdd73e91a7e 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -83,6 +83,17 @@ typedef uint32_t xcb_window_t; #include "wsi_common.h" #include "wsi_common_display.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" + #define ATI_VENDOR_ID 0x1002 #define MAX_VBS 32 -- 2.30.2