1# 2# Copyright 2017 Advanced Micro Devices, Inc. 3# 4# SPDX-License-Identifier: MIT 5# 6""" 7Script that generates the mapping from Gallium PIPE_FORMAT_xxx to GFX10_FORMAT_xxx enums. 8""" 9 10import json 11import mako.template 12import os 13import re 14import sys 15 16AMD_REGISTERS = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../registers")) 17UTIL_FORMAT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../../util/format")) 18sys.path.extend([AMD_REGISTERS, UTIL_FORMAT]) 19 20from regdb import Object, RegisterDatabase 21from u_format_parse import * 22 23# ---------------------------------------------------------------------------- 24# Hard-coded mappings 25 26def hardcoded_format(hw_enum): 27 return Object(img_format=hw_enum, flags=[]) 28 29HARDCODED = { 30 'PIPE_FORMAT_Z32_FLOAT_S8X24_UINT': hardcoded_format('X24_8_32_FLOAT'), 31 'PIPE_FORMAT_Z24_UNORM_S8_UINT': hardcoded_format('8_24_UNORM'), 32 'PIPE_FORMAT_S8_UINT_Z24_UNORM': hardcoded_format('24_8_UNORM'), 33 'PIPE_FORMAT_Z32_UNORM': None, 34 'PIPE_FORMAT_Z16_UNORM_S8_UINT': None, 35 36 'PIPE_FORMAT_R9G9B9E5_FLOAT': hardcoded_format('5_9_9_9_FLOAT'), 37 'PIPE_FORMAT_R11G11B10_FLOAT': hardcoded_format('10_11_11_FLOAT'), # NOTE: full set of int/unorm/etc. exists 38 39 'PIPE_FORMAT_R8G8_B8G8_UNORM': hardcoded_format('GB_GR_UNORM'), 40 'PIPE_FORMAT_G8R8_B8R8_UNORM': hardcoded_format('GB_GR_UNORM'), 41 42 'PIPE_FORMAT_R8G8_R8B8_UNORM': hardcoded_format('BG_RG_UNORM'), 43 'PIPE_FORMAT_G8R8_G8B8_UNORM': hardcoded_format('BG_RG_UNORM'), 44 45 # These mixed channel types are not supported natively 46 'PIPE_FORMAT_R8SG8SB8UX8U_NORM': None, 47 'PIPE_FORMAT_R10SG10SB10SA2U_NORM': None, 48 'PIPE_FORMAT_R5SG5SB6U_NORM': None, 49 50 # Only R8G8_SRGB is supported, not L8A8_SRGB 51 'PIPE_FORMAT_L8A8_SRGB': None, 52 53 # S3TC 54 'PIPE_FORMAT_DXT1_RGB': hardcoded_format('BC1_UNORM'), 55 'PIPE_FORMAT_DXT1_RGBA': hardcoded_format('BC1_UNORM'), 56 'PIPE_FORMAT_DXT1_SRGB': hardcoded_format('BC1_SRGB'), 57 'PIPE_FORMAT_DXT1_SRGBA': hardcoded_format('BC1_SRGB'), 58 'PIPE_FORMAT_DXT3_RGBA': hardcoded_format('BC2_UNORM'), 59 'PIPE_FORMAT_DXT3_SRGBA': hardcoded_format('BC2_SRGB'), 60 'PIPE_FORMAT_DXT5_RGBA': hardcoded_format('BC3_UNORM'), 61 'PIPE_FORMAT_DXT5_SRGBA': hardcoded_format('BC3_SRGB'), 62 63 # RGTC 64 'PIPE_FORMAT_RGTC1_UNORM': hardcoded_format('BC4_UNORM'), 65 'PIPE_FORMAT_RGTC1_SNORM': hardcoded_format('BC4_SNORM'), 66 'PIPE_FORMAT_RGTC2_UNORM': hardcoded_format('BC5_UNORM'), 67 'PIPE_FORMAT_RGTC2_SNORM': hardcoded_format('BC5_SNORM'), 68 'PIPE_FORMAT_LATC1_UNORM': hardcoded_format('BC4_UNORM'), 69 'PIPE_FORMAT_LATC1_SNORM': hardcoded_format('BC4_SNORM'), 70 'PIPE_FORMAT_LATC2_UNORM': hardcoded_format('BC5_UNORM'), 71 'PIPE_FORMAT_LATC2_SNORM': hardcoded_format('BC5_SNORM'), 72 73 # BPTC 74 'PIPE_FORMAT_BPTC_RGB_UFLOAT': hardcoded_format('BC6_UFLOAT'), 75 'PIPE_FORMAT_BPTC_RGB_FLOAT': hardcoded_format('BC6_SFLOAT'), 76 77 'PIPE_FORMAT_BPTC_RGBA_UNORM': hardcoded_format('BC7_UNORM'), 78 'PIPE_FORMAT_BPTC_SRGBA': hardcoded_format('BC7_SRGB'), 79 80 'PIPE_FORMAT_R64_UINT': hardcoded_format('32_32_UINT'), 81 'PIPE_FORMAT_R64_SINT': hardcoded_format('32_32_SINT'), 82} 83 84 85# ---------------------------------------------------------------------------- 86# Main script 87 88header_template = mako.template.Template("""\ 89% if header: 90// DO NOT EDIT -- AUTOMATICALLY GENERATED 91 92#include "gfx10_format_table.h" 93#include "amdgfxregs.h" 94 95% endif 96 97#define FMT(_img_format, ...) \ 98 { .img_format = V_008F0C_${gfx.upper()}_FORMAT_##_img_format, \ 99 ##__VA_ARGS__ } 100 101const struct gfx10_format ${gfx}_format_table[PIPE_FORMAT_COUNT] = { 102% for pipe_format, args in formats: 103 % if args is not None: 104 [${pipe_format}] = FMT(${args}), 105 % else: 106/* ${pipe_format} is not supported */ 107 % endif 108% endfor 109 110#undef FMT 111}; 112""") 113 114class Gfx10Format(object): 115 RE_plain_channel = re.compile(r'X?([0-9]+)') 116 117 def __init__(self, enum_entry): 118 self.img_format = enum_entry.name[13:] 119 self.flags = getattr(enum_entry, 'flags', []) 120 121 code = self.img_format.split('_') 122 123 self.plain_chan_sizes = [] 124 for i, chan_code in enumerate(code): 125 m = self.RE_plain_channel.match(chan_code) 126 if m is None: 127 break 128 self.plain_chan_sizes.append(int(m.group(1))) 129 # Keep the bit sizes in little-endian order 130 self.plain_chan_sizes.reverse() 131 132 self.code = code[i:] 133 134 135class Gfx10FormatMapping(object): 136 def __init__(self, pipe_formats, gfx10_formats): 137 self.pipe_formats = pipe_formats 138 self.gfx10_formats = gfx10_formats 139 140 self.plain_gfx10_formats = dict( 141 (tuple(['_'.join(fmt.code)] + fmt.plain_chan_sizes), fmt) 142 for fmt in gfx10_formats if fmt.plain_chan_sizes 143 ) 144 145 def map(self, fmt): 146 if fmt.layout == PLAIN: 147 chan_type = set([chan.type for chan in fmt.le_channels if chan.type != VOID]) 148 chan_norm = set([chan.norm for chan in fmt.le_channels if chan.type != VOID]) 149 chan_pure = set([chan.pure for chan in fmt.le_channels if chan.type != VOID]) 150 if len(chan_type) > 1 or len(chan_norm) > 1 or len(chan_pure) > 1: 151 print(('Format {fmt.name} has inconsistent channel types: ' + 152 '{chan_type} {chan_norm} {chan_pure}') 153 .format(**locals()), 154 file=sys.stderr) 155 return None 156 157 chan_type = chan_type.pop() 158 chan_norm = chan_norm.pop() 159 chan_pure = chan_pure.pop() 160 chan_sizes = [chan.size for chan in fmt.le_channels if chan.size != 0] 161 162 extra_flags = [] 163 164 if fmt.colorspace == SRGB: 165 assert chan_type == UNSIGNED and chan_norm 166 num_format = 'SRGB' 167 else: 168 if chan_type == UNSIGNED: 169 if chan_pure: 170 num_format = 'UINT' 171 elif chan_sizes[0] == 32: 172 # Shader-based work-around for 32-bit non-pure-integer 173 num_format = 'UINT' 174 extra_flags.append('buffers_only') 175 elif chan_norm: 176 num_format = 'UNORM' 177 else: 178 num_format = 'USCALED' 179 extra_flags.append('buffers_only') 180 elif chan_type == SIGNED: 181 if chan_pure: 182 num_format = 'SINT' 183 elif chan_sizes[0] == 32: 184 # Shader-based work-around for 32-bit non-pure-integer 185 num_format = 'SINT' 186 extra_flags.append('buffers_only') 187 elif chan_norm: 188 num_format = 'SNORM' 189 else: 190 num_format = 'SSCALED' 191 extra_flags.append('buffers_only') 192 elif chan_type == FLOAT: 193 num_format = 'FLOAT' 194 195 if chan_sizes[0] == 64: 196 # Shader-based work-around for doubles 197 if len(chan_sizes) % 2 == 1: 198 # 1 or 3 loads for 1 or 3 double channels 199 chan_sizes = [32, 32] 200 else: 201 # 1 or 2 loads for 2 or 4 double channels 202 chan_sizes = [32, 32, 32, 32] 203 extra_flags.append('buffers_only') 204 else: 205 # Shader-based work-around 206 assert chan_type == FIXED 207 assert chan_sizes[0] == 32 208 num_format = 'SINT' 209 extra_flags.append('buffers_only') 210 211 # These are not supported as render targets, so we don't support 212 # them as images either. 213 if (len(chan_sizes) == 3 and chan_sizes[0] in (8, 16, 32) and 214 chan_sizes[0] == chan_sizes[1]): 215 extra_flags.append('buffers_only') 216 if chan_sizes[0] in (8, 16): 217 # Shader-based work-around: one load per channel 218 chan_sizes = [chan_sizes[0]] 219 220 # Don't expose SRGB buffer formats 221 if 'buffers_only' in extra_flags and fmt.colorspace == SRGB: 222 return None 223 224 # Don't support 4_4 because it's not supported as render targets 225 # and it's useless in other cases. 226 if len(chan_sizes) == 2 and chan_sizes[0] == 4: 227 return None 228 229 key = tuple([num_format] + chan_sizes) 230 if key not in self.plain_gfx10_formats: 231 return None 232 233 gfx10_fmt = self.plain_gfx10_formats[key] 234 return Object( 235 img_format=gfx10_fmt.img_format, 236 flags=gfx10_fmt.flags + extra_flags, 237 ) 238 239 return None 240 241def pipe_formats_to_formats(pipe_formats, mapping): 242 formats = [] 243 for fmt in pipe_formats: 244 if fmt.name in HARDCODED: 245 obj = HARDCODED[fmt.name] 246 else: 247 obj = mapping.map(fmt) 248 249 if obj is not None: 250 args = obj.img_format 251 if 'buffers_only' in obj.flags: 252 args += ', .buffers_only = 1' 253 else: 254 args = None 255 formats.append((fmt.name, args)) 256 257 return formats 258 259if __name__ == '__main__': 260 pipe_formats = parse(sys.argv[1]) 261 262 # gfx10 263 with open(sys.argv[2], 'r') as filp: 264 db = RegisterDatabase.from_json(json.load(filp)) 265 266 gfx10_formats = [Gfx10Format(entry) for entry in db.enum('GFX10_FORMAT').entries] 267 mapping = Gfx10FormatMapping(pipe_formats, gfx10_formats) 268 formats = pipe_formats_to_formats(pipe_formats, mapping) 269 print(header_template.render(header=True, gfx='gfx10', formats=formats)) 270 271 # gfx11 272 with open(sys.argv[3], 'r') as filp: 273 db = RegisterDatabase.from_json(json.load(filp)) 274 275 gfx11_formats = [Gfx10Format(entry) for entry in db.enum('GFX11_FORMAT').entries] 276 mapping = Gfx10FormatMapping(pipe_formats, gfx11_formats) 277 formats = pipe_formats_to_formats(pipe_formats, mapping) 278 print(header_template.render(header=False, gfx='gfx11', formats=formats)) 279