2 # Copyright 2017 Advanced Micro Devices, Inc.
4 # Permission is hereby granted, free of charge, to any person obtaining a
5 # copy of this software and associated documentation files (the "Software"),
6 # to deal in the Software without restriction, including without limitation
7 # on the rights to use, copy, modify, merge, publish, distribute, sub
8 # license, and/or sell copies of the Software, and to permit persons to whom
9 # the Software is furnished to do so, subject to the following conditions:
11 # The above copyright notice and this permission notice (including the next
12 # paragraph) shall be included in all copies or substantial portions of the
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 # THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 # USE OR OTHER DEALINGS IN THE SOFTWARE.
24 Script that generates the mapping from Vulkan VK_FORMAT_xxx to gfx10
28 from __future__
import absolute_import
, division
, print_function
, unicode_literals
36 AMD_REGISTERS
= os
.path
.abspath(os
.path
.join(os
.path
.dirname(sys
.argv
[0]), "../registers"))
37 sys
.path
.extend([AMD_REGISTERS
])
39 from regdb
import Object
, RegisterDatabase
40 from vk_format_parse
import *
42 # ----------------------------------------------------------------------------
45 def hardcoded_format(hw_enum
):
46 return Object(img_format
=hw_enum
, flags
=[])
49 'VK_FORMAT_E5B9G9R9_UFLOAT_PACK32': hardcoded_format('5_9_9_9_FLOAT'),
50 'VK_FORMAT_B10G11R11_UFLOAT_PACK32': hardcoded_format('10_11_11_FLOAT'), # NOTE: full set of int/unorm/etc. exists
53 'VK_FORMAT_BC1_RGB_UNORM_BLOCK': hardcoded_format('BC1_UNORM'),
54 'VK_FORMAT_BC1_RGBA_UNORM_BLOCK': hardcoded_format('BC1_UNORM'),
55 'VK_FORMAT_BC1_RGB_SRGB_BLOCK': hardcoded_format('BC1_SRGB'),
56 'VK_FORMAT_BC1_RGBA_SRGB_BLOCK': hardcoded_format('BC1_SRGB'),
57 'VK_FORMAT_BC2_UNORM_BLOCK': hardcoded_format('BC2_UNORM'),
58 'VK_FORMAT_BC2_SRGB_BLOCK': hardcoded_format('BC2_SRGB'),
59 'VK_FORMAT_BC3_UNORM_BLOCK': hardcoded_format('BC3_UNORM'),
60 'VK_FORMAT_BC3_SRGB_BLOCK': hardcoded_format('BC3_SRGB'),
61 'VK_FORMAT_BC4_UNORM_BLOCK': hardcoded_format('BC4_UNORM'),
62 'VK_FORMAT_BC4_SNORM_BLOCK': hardcoded_format('BC4_SNORM'),
63 'VK_FORMAT_BC5_UNORM_BLOCK': hardcoded_format('BC5_UNORM'),
64 'VK_FORMAT_BC5_SNORM_BLOCK': hardcoded_format('BC5_SNORM'),
65 'VK_FORMAT_BC6H_UFLOAT_BLOCK': hardcoded_format('BC6_UFLOAT'),
66 'VK_FORMAT_BC6H_SFLOAT_BLOCK': hardcoded_format('BC6_SFLOAT'),
67 'VK_FORMAT_BC7_UNORM_BLOCK': hardcoded_format('BC7_UNORM'),
68 'VK_FORMAT_BC7_SRGB_BLOCK': hardcoded_format('BC7_SRGB'),
71 'VK_FORMAT_D16_UNORM_S8_UINT': hardcoded_format('INVALID'),
72 'VK_FORMAT_D24_UNORM_S8_UINT': hardcoded_format('8_24_UNORM'),
73 'VK_FORMAT_D32_SFLOAT_S8_UINT': hardcoded_format('X24_8_32_FLOAT'),
77 # ----------------------------------------------------------------------------
80 header_template
= mako
.template
.Template("""\
81 // DO NOT EDIT -- AUTOMATICALLY GENERATED
83 #define FMT(_img_format, ...) \
84 { .img_format = V_008F0C_IMG_FORMAT_##_img_format, \
87 static const struct gfx10_format gfx10_format_table[VK_FORMAT_RANGE_SIZE] = {
88 % for vk_format, args in formats:
89 % if args is not None:
90 [${vk_format}] = FMT(${args}),
92 /* ${vk_format} is not supported */
98 class Gfx10Format(object):
99 RE_plain_channel
= re
.compile(r
'X?([0-9]+)')
101 def __init__(self
, enum_entry
):
102 self
.img_format
= enum_entry
.name
[11:]
103 self
.flags
= getattr(enum_entry
, 'flags', [])
105 code
= self
.img_format
.split('_')
107 self
.plain_chan_sizes
= []
108 for i
, chan_code
in enumerate(code
):
109 m
= self
.RE_plain_channel
.match(chan_code
)
112 self
.plain_chan_sizes
.append(int(m
.group(1)))
113 # Keep the bit sizes in little-endian order
114 self
.plain_chan_sizes
.reverse()
119 class Gfx10FormatMapping(object):
120 def __init__(self
, vk_formats
, gfx10_formats
):
121 self
.vk_formats
= vk_formats
122 self
.gfx10_formats
= gfx10_formats
124 self
.plain_gfx10_formats
= dict(
125 (tuple(['_'.join(fmt
.code
)] + fmt
.plain_chan_sizes
), fmt
)
126 for fmt
in gfx10_formats
if fmt
.plain_chan_sizes
130 if fmt
.layout
== PLAIN
:
131 chan_type
= set([chan
.type for chan
in fmt
.le_channels
if chan
.type != VOID
])
132 chan_norm
= set([chan
.norm
for chan
in fmt
.le_channels
if chan
.type != VOID
])
133 chan_pure
= set([chan
.pure
for chan
in fmt
.le_channels
if chan
.type != VOID
])
134 if len(chan_type
) > 1 or len(chan_norm
) > 1 or len(chan_pure
) > 1:
135 print(('Format {fmt.name} has inconsistent channel types: ' +
136 '{chan_type} {chan_norm} {chan_pure}')
141 chan_type
= chan_type
.pop()
142 chan_norm
= chan_norm
.pop()
143 chan_pure
= chan_pure
.pop()
144 chan_sizes
= [chan
.size
for chan
in fmt
.le_channels
if chan
.size
!= 0]
148 if fmt
.colorspace
== SRGB
:
149 assert chan_type
== UNSIGNED
and chan_norm
152 if chan_type
== UNSIGNED
:
155 elif chan_sizes
[0] == 32:
156 # Shader-based work-around for 32-bit non-pure-integer
158 extra_flags
.append('buffers_only')
162 num_format
= 'USCALED'
163 elif chan_type
== SIGNED
:
166 elif chan_sizes
[0] == 32:
167 # Shader-based work-around for 32-bit non-pure-integer
169 extra_flags
.append('buffers_only')
173 num_format
= 'SSCALED'
174 elif chan_type
== FLOAT
:
177 if chan_sizes
[0] == 64:
178 # Shader-based work-around for doubles
179 if len(chan_sizes
) % 2 == 1:
180 # 1 or 3 loads for 1 or 3 double channels
181 chan_sizes
= [32, 32]
183 # 1 or 2 loads for 2 or 4 double channels
184 chan_sizes
= [32, 32, 32, 32]
185 extra_flags
.append('buffers_only')
187 # Shader-based work-around
188 assert chan_type
== FIXED
189 assert chan_sizes
[0] == 32
191 extra_flags
.append('buffers_only')
193 # These are not supported as render targets, so we don't support
194 # them as images either.
195 if (len(chan_sizes
) == 3 and chan_sizes
[0] in (8, 16, 32) and
196 chan_sizes
[0] == chan_sizes
[1]):
197 extra_flags
.append('buffers_only')
198 if chan_sizes
[0] in (8, 16):
199 # Shader-based work-around: one load per channel
200 chan_sizes
= [chan_sizes
[0]]
202 # Don't expose SRGB buffer formats
203 if 'buffers_only' in extra_flags
and fmt
.colorspace
== SRGB
:
206 # Don't support 4_4 because it's not supported as render targets
207 # and it's useless in other cases.
208 if len(chan_sizes
) == 2 and chan_sizes
[0] == 4:
211 key
= tuple([num_format
] + chan_sizes
)
212 if key
not in self
.plain_gfx10_formats
:
215 gfx10_fmt
= self
.plain_gfx10_formats
[key
]
217 img_format
=gfx10_fmt
.img_format
,
218 flags
=gfx10_fmt
.flags
+ extra_flags
,
224 if __name__
== '__main__':
225 vk_formats
= parse(sys
.argv
[1])
227 with
open(sys
.argv
[2], 'r') as filp
:
228 db
= RegisterDatabase
.from_json(json
.load(filp
))
230 gfx10_formats
= [Gfx10Format(entry
) for entry
in db
.enum('IMG_FORMAT').entries
]
232 mapping
= Gfx10FormatMapping(vk_formats
, gfx10_formats
)
235 for fmt
in vk_formats
:
236 if fmt
.name
in HARDCODED
:
237 obj
= HARDCODED
[fmt
.name
]
239 obj
= mapping
.map(fmt
)
242 args
= obj
.img_format
243 if 'buffers_only' in obj
.flags
:
244 args
+= ', .buffers_only = 1'
247 formats
.append((fmt
.name
, args
))
249 print(header_template
.render(formats
=formats
))