summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gallium/auxiliary/util/u_format.csv3
-rw-r--r--src/gallium/drivers/radeonsi/Makefile.sources1
-rw-r--r--src/gallium/drivers/radeonsi/gfx10_format_table.py273
-rw-r--r--src/gallium/drivers/radeonsi/meson.build14
-rw-r--r--src/gallium/drivers/radeonsi/si_state.c11
5 files changed, 300 insertions, 2 deletions
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) {