mirror of
https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git
synced 2025-05-14 16:58:43 +00:00
formats: vkuGetFormatInfo to use array
Puts the contents of a switch in a big array, then rewrites vkuGetFormatInfo() to index into it based on the formats enum value. This was done because the switch statement was large enough that compilers wouldn't inline the function, leading to performance bubbles. The logic for generating the logic of vkuGetFormatInfo is complex but boils down to finding the groups of consecutive VkFormats, where the end of a group has a value that is more than 1 away from the next format value. To follow C const initializer rules, VKU_FORMAT_COMPRESSED_COMPONENT had to be turned into a macro.
This commit is contained in:
parent
04e2efb904
commit
0d5b49b80f
2 changed files with 311 additions and 771 deletions
|
@ -7,6 +7,7 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import os
|
||||
from collections import namedtuple
|
||||
from vulkan_object import (Format)
|
||||
from base_generator import BaseGenerator
|
||||
|
||||
|
@ -292,7 +293,7 @@ enum VKU_FORMAT_COMPONENT_TYPE {
|
|||
};
|
||||
|
||||
// Compressed formats don't have a defined component size
|
||||
const uint32_t VKU_FORMAT_COMPRESSED_COMPONENT = 0xFFFFFFFF;
|
||||
#define VKU_FORMAT_COMPRESSED_COMPONENT 0xFFFFFFFF
|
||||
|
||||
struct VKU_FORMAT_COMPONENT_INFO {
|
||||
enum VKU_FORMAT_COMPONENT_TYPE type;
|
||||
|
@ -309,27 +310,57 @@ struct VKU_FORMAT_INFO {
|
|||
struct VKU_FORMAT_COMPONENT_INFO components[VKU_FORMAT_MAX_COMPONENTS];
|
||||
};
|
||||
''')
|
||||
out.append('inline const struct VKU_FORMAT_INFO vkuGetFormatInfo(VkFormat format) {\n')
|
||||
out.append(' switch (format) {\n')
|
||||
for f in self.vk.formats.values():
|
||||
formats_in_order = {}
|
||||
# Manually add in the entry for VK_FORMAT_UNDEFINED because it is missing from the self.vk.formats dict
|
||||
formats_in_order[0] = Format('VK_FORMAT_UNDEFINED', 'NONE', 0,0, ['0','0','0'], None, None, None, [], [], None)
|
||||
for e in self.vk.enums['VkFormat'].fields:
|
||||
if e.name != 'VK_FORMAT_UNDEFINED':
|
||||
formats_in_order[e.value] = self.vk.formats[e.name]
|
||||
# Number of VkFormats should equal the fields of the VkFormat enum
|
||||
assert(len(formats_in_order) == len(self.vk.enums['VkFormat'].fields))
|
||||
formats_in_order = dict(sorted(formats_in_order.items()))
|
||||
|
||||
out.append(f'const struct VKU_FORMAT_INFO vku_formats[{len(self.vk.formats) + 1}] = {{\n')
|
||||
for f in formats_in_order.values():
|
||||
className = getClassName(f.className)
|
||||
blockExtent = ', '.join(f.blockExtent) if f.blockExtent is not None else '1, 1, 1'
|
||||
out.extend(f' case {f.name}: {{\n')
|
||||
out.extend(f' struct VKU_FORMAT_INFO out = {{VKU_FORMAT_COMPATIBILITY_CLASS_{className}, {f.blockSize}, {f.texelsPerBlock}, {{{blockExtent}}}, {len(f.components)}, {{')
|
||||
out.extend(f' {{ VKU_FORMAT_COMPATIBILITY_CLASS_{className}, {f.blockSize}, {f.texelsPerBlock}, {{{blockExtent}}}, {len(f.components)}, {{')
|
||||
for index, component in enumerate(f.components):
|
||||
bits = 'VKU_FORMAT_COMPRESSED_COMPONENT' if component.bits == 'compressed' else component.bits
|
||||
out.append(f'{{VKU_FORMAT_COMPONENT_TYPE_{component.type}, {bits}}}')
|
||||
if index + 1 != len(f.components):
|
||||
out.append(', ')
|
||||
out.append('}};\n')
|
||||
out.append(' return out; }\n')
|
||||
out.append('''
|
||||
default: {
|
||||
// return values for VK_FORMAT_UNDEFINED
|
||||
struct VKU_FORMAT_INFO out = { VKU_FORMAT_COMPATIBILITY_CLASS_NONE, 0, 0, {0, 0, 0}, 0, {{VKU_FORMAT_COMPONENT_TYPE_NONE, 0}, {VKU_FORMAT_COMPONENT_TYPE_NONE, 0}, {VKU_FORMAT_COMPONENT_TYPE_NONE, 0}, {VKU_FORMAT_COMPONENT_TYPE_NONE, 0}} };
|
||||
return out;
|
||||
}
|
||||
};
|
||||
out.append('} },\n')
|
||||
out.append('};\n')
|
||||
|
||||
# Find the "format groups", eg formats whose value are consecutive, as that is the way they are written into the 'formats' array.
|
||||
# Value refers to the enum value. These are discontinuous.
|
||||
# Index refers to the index of a format in the vku_formats array. These are from 0 to the len(formats_in_order).
|
||||
format_values = list(formats_in_order.keys())
|
||||
FormatGroup = namedtuple('FormatGroup', ['begin_format', 'end_format','array_index'])
|
||||
format_groups = []
|
||||
index = 0
|
||||
while index < len(format_values):
|
||||
start_value = format_values[index]
|
||||
end_value = format_values[-1] # use last format as sentinel so the last group can get the right end value
|
||||
previous_value = start_value - 1
|
||||
# Find the end value for the current group
|
||||
for format_value in format_values[index:]:
|
||||
if previous_value + 1 != format_value:
|
||||
end_value = previous_value
|
||||
break
|
||||
previous_value = format_value
|
||||
format_groups.append(FormatGroup(formats_in_order[start_value].name, formats_in_order[end_value].name, index))
|
||||
index += (end_value - start_value) + 1
|
||||
|
||||
out.append('inline const struct VKU_FORMAT_INFO vkuGetFormatInfo(VkFormat format) {\n')
|
||||
for group in format_groups:
|
||||
out.append(f' {"else " if group.array_index != 0 else ""}if ({group.begin_format} <= format && format <= {group.end_format} )')
|
||||
out.append(f' {{ return vku_formats[format - {group.begin_format} + {group.array_index}]; }}\n')
|
||||
out.append(''' // Default case - return VK_FORMAT_UNDEFINED
|
||||
else {
|
||||
return vku_formats[0];
|
||||
}
|
||||
}
|
||||
|
||||
struct VKU_FORMAT_PER_PLANE_COMPATIBILITY {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue