Skip to content

Commit

Permalink
profiles: Support VK_EXT_host_image_copy
Browse files Browse the repository at this point in the history
  • Loading branch information
ShabbyX committed Sep 30, 2024
1 parent baf06ff commit a2db6ef
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 42 deletions.
11 changes: 7 additions & 4 deletions profiles/test/data/VP_LUNARG_test_host_image_copy/local_gpu.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"VK_EXT_global_priority": 2,
"VK_EXT_global_priority_query": 1,
"VK_EXT_graphics_pipeline_library": 1,
"VK_EXT_host_image_copy": 1,
"VK_EXT_host_query_reset": 1,
"VK_EXT_image_2d_view_of_3d": 1,
"VK_EXT_image_drm_format_modifier": 2,
Expand Down Expand Up @@ -1407,13 +1408,15 @@
"maxBufferSize": 4294967292
},
"VkPhysicalDeviceHostImageCopyPropertiesEXT": {
"copySrcLayoutCount": 0,
"pCopySrcLayouts": [

"VK_IMAGE_LAYOUT_GENERAL",
"VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL",
"VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL"
],
"copyDstLayoutCount": 0,
"pCopyDstLayouts": [

"VK_IMAGE_LAYOUT_GENERAL",
"VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL",
"VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL"
],
"optimalTilingLayoutUUID": [
0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"VK_EXT_global_priority_query": 1,
"VK_EXT_graphics_pipeline_library": 1,
"VK_EXT_hdr_metadata": 2,
"VK_EXT_host_image_copy": 1,
"VK_EXT_host_query_reset": 1,
"VK_EXT_image_2d_view_of_3d": 1,
"VK_EXT_image_drm_format_modifier": 2,
Expand Down Expand Up @@ -964,13 +965,15 @@
"maxBufferSize": 4294967296
},
"VkPhysicalDeviceHostImageCopyPropertiesEXT": {
"copySrcLayoutCount": 0,
"pCopySrcLayouts": [

"VK_IMAGE_LAYOUT_GENERAL",
"VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL",
"VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL"
],
"copyDstLayoutCount": 0,
"pCopyDstLayouts": [

"VK_IMAGE_LAYOUT_GENERAL",
"VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL",
"VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL"
],
"optimalTilingLayoutUUID": [
0,
Expand Down
20 changes: 13 additions & 7 deletions scripts/gen_profiles_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ def add_members(self, merged, entry, property = None):
continue

xmlmember = self.registry.structs[property].members[member]
if xmlmember.limittype == 'exact' or xmlmember.limittype == 'noauto':
if (xmlmember.limittype == 'exact' or xmlmember.limittype == 'noauto') and not xmlmember.isDynamicallySizedArrayWithCap():
del merged[member]
#elif 'mul' in xmlmember.limittype and xmlmember.type == 'float':
# del merged[member]
Expand All @@ -585,18 +585,14 @@ def add_members(self, merged, entry, property = None):
merged[member] = entry[member]
elif not member in merged:
xmlmember = self.registry.structs[property].members[member]
if xmlmember.limittype == 'exact' or xmlmember.limittype == 'noauto':
if (xmlmember.limittype == 'exact' or xmlmember.limittype == 'noauto') and not xmlmember.isDynamicallySizedArrayWithCap():
continue
elif self.mode == 'union' or self.first is True:
if xmlmember.type == 'uint64_t' or xmlmember.type == 'VkDeviceSize':
merged[member] = int(entry[member])
else:
merged[member] = entry[member]
else:
# VK_EXT_host_image_copy is unsupported
if property == 'VkPhysicalDeviceHostImageCopyPropertiesEXT':
continue

# Merge properties
xmlmember = self.registry.structs[property].members[member]
if xmlmember.limittype == 'struct':
Expand All @@ -615,7 +611,7 @@ def add_members(self, merged, entry, property = None):
self.merge_members(merged, member, entry, xmlmember)

def merge_members(self, merged, member, entry, xmlmember):
if xmlmember.limittype == 'exact' or xmlmember.limittype == 'noauto':
if (xmlmember.limittype == 'exact' or xmlmember.limittype == 'noauto') and not xmlmember.isDynamicallySizedArrayWithCap():
del merged[member]
elif self.mode == 'union':
#if xmlmember.limittype == 'exact':
Expand Down Expand Up @@ -685,6 +681,11 @@ def merge_members(self, merged, member, entry, xmlmember):
merged[member][0] = entry[member][0]
if entry[member][1] > merged[member][1]:
merged[member][1] = entry[member][1]
elif xmlmember.isDynamicallySizedArrayWithCap():
entry_set = set(merged[member])
merged_set = set(entry[member])
union_set = merged_set.union(entry_set)
merged[member] = list(union_set)
else:
print("ERROR: Unknown limitype: " + xmlmember.limittype + " for " + member)
elif self.mode == 'intersection':
Expand Down Expand Up @@ -792,6 +793,11 @@ def merge_members(self, merged, member, entry, xmlmember):
merged[member][1] = entry[member][1]
#if member[1] < member[0]:
# merged.pop(member, None)
elif xmlmember.isDynamicallySizedArrayWithCap():
entry_set = set(merged[member])
merged_set = set(entry[member])
intersection_set = merged_set.intersection(entry_set)
merged[member] = list(intersection_set)
else:
print("ERROR: Unknown limitype: " + xmlmember.limittype + " for " + member)
else:
Expand Down
4 changes: 1 addition & 3 deletions scripts/gen_profiles_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2946,9 +2946,7 @@ class VulkanProfilesLayerGenerator():
emulated_extensions = ['VK_KHR_portability_subset']
additional_features = ['VkPhysicalDeviceFeatures', 'VkPhysicalDevicePortabilitySubsetFeaturesKHR']
additional_properties = ['VkPhysicalDeviceProperties', 'VkPhysicalDeviceLimits', 'VkPhysicalDeviceSparseProperties', 'VkPhysicalDeviceToolProperties', 'VkPhysicalDevicePortabilitySubsetPropertiesKHR']
# VkPhysicalDeviceHostImageCopyFeaturesEXT is not ignored to allow the people using the MockICD to still have the feature enabled,
# but use the properties in the MockICD until HostImageCopyPropertiesEXT is fixed.
ignored_structs = ['VkPhysicalDeviceHostImageCopyPropertiesEXT', 'VkPhysicalDeviceLayeredApiPropertiesListKHR']
ignored_structs = ['VkPhysicalDeviceLayeredApiPropertiesListKHR']

def generate(self, path, registry):
self.registry = registry
Expand Down
130 changes: 107 additions & 23 deletions scripts/gen_profiles_solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,11 @@ def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True):
return !(value & (value - static_cast<std::uint64_t>(1)));
}
using PFN_vpStructFiller = void(*)(VkBaseOutStructure* p);
using PFN_vpStructFiller = void(*)(
#ifdef VP_USE_OBJECT
VpCapabilities capabilities,
#endif//VP_USE_OBJECT
VkBaseOutStructure* p);
using PFN_vpStructComparator = bool(*)(VkBaseOutStructure* p);
using PFN_vpStructChainerCb = void(*)(VkBaseOutStructure* p, void* pUser);
using PFN_vpStructChainer = void(*)(VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb);
Expand Down Expand Up @@ -621,6 +625,17 @@ def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True):
VPAPI_ATTR bool vpCheckFlags(const T& actual, const uint64_t expected) {
return (actual & expected) == expected;
}
template <typename T>
VPAPI_ATTR bool vpCheckList(const T* data, uint32_t count, const T expected) {
for (uint32_t i = 0; i < count; ++i) {
if (data[i] == expected)
{
return true;
}
}
return false;
}
'''

PRIVATE_IMPL_BODY = '''
Expand Down Expand Up @@ -965,6 +980,12 @@ def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True):
bool singleton = false;
uint32_t apiVersion = VK_API_VERSION_1_0;
// Space for multi-pass queries:
//
// - From VkPhysicalDeviceHostImageCopyPropertiesEXT
std::vector<VkImageLayout> pCopySrcLayouts;
std::vector<VkImageLayout> pCopyDstLayouts;
static VpCapabilities_T& Get() {
static VpCapabilities_T instance;
VpCapabilitiesCreateInfo createInfo{};
Expand Down Expand Up @@ -2334,6 +2355,10 @@ def __init__(self, name, type, limittype, isArray = False):
self.arraySizeMember = None
self.nullTerminated = False
self.arraySize = None
self.arraySizeCap = None

def isDynamicallySizedArrayWithCap(self):
return self.isArray and self.arraySizeCap is not None


class VulkanStruct():
Expand Down Expand Up @@ -2517,7 +2542,7 @@ def __init__(self, xml, upperCaseName):


# Dynamic arrays are ill-formed, but some of them still have a maximum size that can be used
struct_with_valid_dynamic_array = ["VkQueueFamilyGlobalPriorityPropertiesKHR"]
struct_with_valid_dynamic_array = ["VkQueueFamilyGlobalPriorityPropertiesKHR", "VkPhysicalDeviceHostImageCopyPropertiesEXT"]

class VulkanRegistry():
def __init__(self, registryFile, api = 'vulkan'):
Expand Down Expand Up @@ -2674,6 +2699,11 @@ def parseStructInfo(self, xml):
structDef.members[name].isArray = True
structDef.members[name].arraySizeMember = len

# Some arrays have a natural maximum size even if they are dynamic. For example, a list
# of VkImageLayouts, because that enum itself is limited.
if structDef.members[name].type == 'VkImageLayout':
structDef.members[name].arraySizeCap = 64;

# If any of the members is a dynamic array then we should remove the corresponding count member
for member in list(structDef.members.values()):
if member.isArray and member.arraySizeMember != None and struct.get('name') not in struct_with_valid_dynamic_array:
Expand Down Expand Up @@ -3779,17 +3809,34 @@ def gen_structFill(self, fmt, structDef, var, values):
continue
if structDef.members[member].isArray:
if not isinstance(self.registry.evalArraySize(structDef.members[member].arraySize), int):
Log.f("Unsupported array member '{0}' in structure '{1}'".format(member, structDef.name) +
"(currently only 1D non-dynamic arrays are supported in this context)")
# If it's an array we have to generate per-element assignment code
for i, v in enumerate(value):
if type(v) == float:
if structDef.members[member].type == 'double':
gen += fmt.format('{0}{1}[{2}] = {3}'.format(var, member, i, v))
else:
gen += fmt.format('{0}{1}[{2}] = {3}f'.format(var, member, i, v))
if structDef.members[member].arraySizeCap:
# If it is a dynamically sized array (with a cap), point it to the pre-allocated array
# created for this purpose.
array_alloc = '#ifdef VP_USE_OBJECT\n'
array_alloc += fmt.format('capabilities->{0}.resize({1})'.format(member,
structDef.members[member].arraySizeCap))
array_alloc += '#endif//VP_USE_OBJECT\n'
gen = array_alloc + gen

# Note: support for these arrays is only present with VP_USE_OBJECT.
gen += '#ifdef VP_USE_OBJECT\n'
gen += fmt.format('{0}{1} = {2}'.format(var, structDef.members[member].arraySizeMember,
structDef.members[member].arraySizeCap))
gen += fmt.format('{0}{1} = capabilities->{2}.data()'.format(var, member, member))
gen += '#endif//VP_USE_OBJECT\n'
else:
gen += fmt.format('{0}{1}[{2}] = {3}'.format(var, member, i, v))
Log.f("Unsupported array member '{0}' in structure '{1}'".format(member, structDef.name) +
"(currently only 1D non-dynamic arrays are supported in this context)")
else:
# If it's an array we have to generate per-element assignment code
for i, v in enumerate(value):
if type(v) == float:
if structDef.members[member].type == 'double':
gen += fmt.format('{0}{1}[{2}] = {3}'.format(var, member, i, v))
else:
gen += fmt.format('{0}{1}[{2}] = {3}f'.format(var, member, i, v))
else:
gen += fmt.format('{0}{1}[{2}] = {3}'.format(var, member, i, v))
else:
# For enums and struct initialization, most of the code can be shared
isEnum = isinstance(value[0], str)
Expand Down Expand Up @@ -3897,14 +3944,23 @@ def gen_structCompare(self, fmt, structDef, var, values, parentLimittype = None)
continue
if structDef.members[member].isArray:
if not isinstance(self.registry.evalArraySize(structDef.members[member].arraySize), int):
Log.f("Unsupported array member '{0}' in structure '{1}'".format(member, structDef.name) +
"(currently only 1D non-dynamic arrays are supported in this context)")
# If it's an array we have to generate per-element comparison code
for i in range(len(value)):
if limittype == 'range':
gen += fmt.format(comparePredFmt[i].format('{0}{1}[{2}]'.format(var, member, i), value[i]))
if structDef.members[member].arraySizeCap:
# If it is a dynamically sized array (with a cap), check that the required elements are
# present anywhere in the returned list.
for i in range(len(value)):
gen += fmt.format('vpCheckList({0}{1}, {0}{2}, {3})'.format(var, member,
structDef.members[member].arraySizeMember,
value[i]))
else:
gen += fmt.format(comparePredFmt.format('{0}{1}[{2}]'.format(var, member, i), value[i]))
Log.f("Unsupported array member '{0}' in structure '{1}'".format(member, structDef.name) +
"(currently only 1D non-dynamic arrays are supported in this context)")
else:
# If it's an array we have to generate per-element comparison code
for i in range(len(value)):
if limittype == 'range':
gen += fmt.format(comparePredFmt[i].format('{0}{1}[{2}]'.format(var, member, i), value[i]))
else:
gen += fmt.format(comparePredFmt.format('{0}{1}[{2}]'.format(var, member, i), value[i]))
else:
# Enum flags and basic structs can be compared directly
isEnum = isinstance(value[0], str)
Expand Down Expand Up @@ -4019,7 +4075,14 @@ def gen_structDesc(self, capabilities, debugMessages):

gen += ('\n'
'static const VpFeatureDesc featureDesc = {\n'
' [](VkBaseOutStructure* p) { (void)p;\n')
' [](\n'
'#ifdef VP_USE_OBJECT\n'
' VpCapabilities capabilities,\n'
'#endif//VP_USE_OBJECT\n'
' VkBaseOutStructure* p) { (void)p;\n'
'#ifdef VP_USE_OBJECT\n'
' (void)capabilities;\n'
'#endif//VP_USE_OBJECT\n')
gen += self.gen_structFunc(self.structs.feature, capabilities.features, self.gen_structFill, fillFmt)
gen += (' },\n'
' [](VkBaseOutStructure* p) -> bool { (void)p;\n'
Expand All @@ -4037,7 +4100,14 @@ def gen_structDesc(self, capabilities, debugMessages):

gen += ('\n'
'static const VpPropertyDesc propertyDesc = {\n'
' [](VkBaseOutStructure* p) { (void)p;\n')
' [](\n'
'#ifdef VP_USE_OBJECT\n'
' VpCapabilities capabilities,\n'
'#endif//VP_USE_OBJECT\n'
' VkBaseOutStructure* p) { (void)p;\n'
'#ifdef VP_USE_OBJECT\n'
' (void)capabilities;\n'
'#endif//VP_USE_OBJECT\n')
gen += self.gen_structFunc(self.structs.property, capabilities.properties, self.gen_structFill, fillFmt)
gen += (' },\n'
' [](VkBaseOutStructure* p) -> bool { (void)p;\n'
Expand All @@ -4053,7 +4123,14 @@ def gen_structDesc(self, capabilities, debugMessages):
'static const VpQueueFamilyDesc queueFamilyDesc[] = {\n')
for queueFamilyCaps in capabilities.queueFamiliesProperties:
gen += (' {\n'
' [](VkBaseOutStructure* p) { (void)p;\n')
' [](\n'
'#ifdef VP_USE_OBJECT\n'
' VpCapabilities capabilities,\n'
'#endif//VP_USE_OBJECT\n'
' VkBaseOutStructure* p) { (void)p;\n'
'#ifdef VP_USE_OBJECT\n'
' (void)capabilities;\n'
'#endif//VP_USE_OBJECT\n')
gen += self.gen_structFunc(self.structs.queueFamily, queueFamilyCaps, self.gen_structFill, fillFmt)
gen += (' },\n'
' [](VkBaseOutStructure* p) -> bool { (void)p;\n'
Expand All @@ -4076,7 +4153,14 @@ def gen_structDesc(self, capabilities, debugMessages):

gen += (' {{\n'
' {0},\n'
' [](VkBaseOutStructure* p) {{ (void)p;\n').format(formatName)
' [](\n'
'#ifdef VP_USE_OBJECT\n'
' VpCapabilities capabilities,\n'
'#endif//VP_USE_OBJECT\n'
' VkBaseOutStructure* p) {{ (void)p;\n'
'#ifdef VP_USE_OBJECT\n'
' (void)capabilities;\n'
'#endif//VP_USE_OBJECT\n').format(formatName)
gen += self.gen_structFunc(self.structs.format, formatCaps, self.gen_structFill, fillFmt)
gen += (' },\n'
' [](VkBaseOutStructure* p) -> bool { (void)p;\n'
Expand Down
2 changes: 1 addition & 1 deletion scripts/gen_profiles_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class ProfileGenerator():
i = 1
skipped_features = []
skipped_members = ["sType", "pNext", "physicalDevices", "driverID"]
skipped_properties_structs = ["VkPhysicalDeviceHostImageCopyPropertiesEXT", "VkPhysicalDeviceLineRasterizationPropertiesEXT", "VkPhysicalDeviceLayeredApiPropertiesListKHR"]
skipped_properties_structs = ["VkPhysicalDeviceLineRasterizationPropertiesEXT", "VkPhysicalDeviceLayeredApiPropertiesListKHR"]

def generate_profile(self, outProfile, registry):
with open(outProfile, 'w') as f:
Expand Down

0 comments on commit a2db6ef

Please sign in to comment.