From 5d0a751c3c980e086ef70f92da96e64509ba02f1 Mon Sep 17 00:00:00 2001 From: John Zulauf Date: Thu, 26 Oct 2017 12:07:05 -0600 Subject: [PATCH] layers: Refactored pNext chain walks to template The while loops for the walking the pNext chains were implemented by repeated code. These were refactored into a common template. Added autogenerated 'traits' objects for the pNext linked structs. Delete cut and paste duplicate pNext chain walk. Change-Id: I46457bb5432219c74f9356e5230c70e4a9ef16df --- CMakeLists.txt | 2 + build-android/android-generate.bat | 1 + build-android/android-generate.sh | 1 + layers/core_validation.cpp | 116 +++++++++++++++------------------- layers/parameter_validation_utils.cpp | 102 +++++++++--------------------- scripts/helper_file_generator.py | 109 ++++++++++++++++++++++++++++++++ scripts/lvl_genvk.py | 22 +++++++ 7 files changed, 216 insertions(+), 137 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d3b157..2412236 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -316,6 +316,7 @@ add_custom_target(generate_helper_files DEPENDS vk_layer_dispatch_table.h vk_dispatch_table_helper.h vk_extension_helper.h + vk_typemap_helper.h ) # Rules to build generated helper files @@ -328,6 +329,7 @@ run_vk_xml_generate(helper_file_generator.py vk_struct_size_helper.c) run_vk_xml_generate(helper_file_generator.py vk_enum_string_helper.h) run_vk_xml_generate(helper_file_generator.py vk_object_types.h) run_vk_xml_generate(helper_file_generator.py vk_extension_helper.h) +run_vk_xml_generate(helper_file_generator.py vk_typemap_helper.h) if(NOT WIN32) include(GNUInstallDirs) diff --git a/build-android/android-generate.bat b/build-android/android-generate.bat index 8f4bab9..d305abc 100644 --- a/build-android/android-generate.bat +++ b/build-android/android-generate.bat @@ -33,5 +33,6 @@ py -3 ../../../scripts/lvl_genvk.py -registry ../../../scripts/vk.xml unique_obj py -3 ../../../scripts/lvl_genvk.py -registry ../../../scripts/vk.xml vk_layer_dispatch_table.h py -3 ../../../scripts/lvl_genvk.py -registry ../../../scripts/vk.xml vk_extension_helper.h py -3 ../../../scripts/lvl_genvk.py -registry ../../../scripts/vk.xml object_tracker.cpp +py -3 ../../../scripts/lvl_genvk.py -registry ../../../scripts/vk.xml vk_typemap_helper.h cd ../.. diff --git a/build-android/android-generate.sh b/build-android/android-generate.sh index 9b1d94b..80687d9 100755 --- a/build-android/android-generate.sh +++ b/build-android/android-generate.sh @@ -36,5 +36,6 @@ mkdir -p generated/include generated/common ( cd generated/include; python3 ../../../scripts/lvl_genvk.py -registry ../../../scripts/vk.xml vk_layer_dispatch_table.h ) ( cd generated/include; python3 ../../../scripts/lvl_genvk.py -registry ../../../scripts/vk.xml vk_extension_helper.h ) ( cd generated/include; python3 ../../../scripts/lvl_genvk.py -registry ../../../scripts/vk.xml object_tracker.cpp ) +( cd generated/include; python3 ../../../scripts/lvl_genvk.py -registry ../../../scripts/vk.xml vk_typemap_helper.h ) exit 0 diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 57bce8c..8431972 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -67,6 +67,7 @@ #include "vk_layer_data.h" #include "vk_layer_extension_utils.h" #include "vk_layer_utils.h" +#include "vk_typemap_helper.h" #if defined __ANDROID__ #include @@ -1941,7 +1942,7 @@ static void init_core_validation(instance_layer_data *instance_data, const VkAll } // For the given ValidationCheck enum, set all relevant instance disabled flags to true -void SetDisabledFlags(instance_layer_data *instance_data, VkValidationFlagsEXT *val_flags_struct) { +void SetDisabledFlags(instance_layer_data *instance_data, const VkValidationFlagsEXT *val_flags_struct) { for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) { switch (val_flags_struct->pDisabledValidationChecks[i]) { case VK_VALIDATION_CHECK_SHADERS_EXT: @@ -1982,15 +1983,9 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreat ValidateLayerOrdering(*pCreateInfo); // Parse any pNext chains - if (pCreateInfo->pNext) { - GENERIC_HEADER *struct_header = (GENERIC_HEADER *)pCreateInfo->pNext; - while (struct_header) { - // Check for VkValidationFlagsExt - if (VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT == struct_header->sType) { - SetDisabledFlags(instance_data, (VkValidationFlagsEXT *)struct_header); - } - struct_header = (GENERIC_HEADER *)struct_header->pNext; - } + const auto *validation_flags_ext = lvl_find_in_chain(pCreateInfo->pNext); + if (validation_flags_ext) { + SetDisabledFlags(instance_data, validation_flags_ext); } return result; @@ -2142,15 +2137,9 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDevice // The enabled features can come from either pEnabledFeatures, or from the pNext chain const VkPhysicalDeviceFeatures *enabled_features_found = pCreateInfo->pEnabledFeatures; if (nullptr == enabled_features_found) { - GENERIC_HEADER *struct_header = (GENERIC_HEADER *)pCreateInfo->pNext; - while (struct_header) { - if (VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR == struct_header->sType) { - VkPhysicalDeviceFeatures2KHR *features2 = (VkPhysicalDeviceFeatures2KHR *)struct_header; - enabled_features_found = &(features2->features); - struct_header = nullptr; - } else { - struct_header = (GENERIC_HEADER *)struct_header->pNext; - } + const auto *features2 = lvl_find_in_chain(pCreateInfo->pNext); + if (features2) { + enabled_features_found = &(features2->features); } } @@ -9746,52 +9735,51 @@ VKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInf } if (pPresentInfo && pPresentInfo->pNext) { // Verify ext struct - GENERIC_HEADER *pnext = (GENERIC_HEADER *)pPresentInfo->pNext; - while (pnext) { - if (VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR == pnext->sType) { - VkPresentRegionsKHR *present_regions = (VkPresentRegionsKHR *)pnext; - for (uint32_t i = 0; i < present_regions->swapchainCount; ++i) { - auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); - assert(swapchain_data); - VkPresentRegionKHR region = present_regions->pRegions[i]; - for (uint32_t j = 0; j < region.rectangleCount; ++j) { - VkRectLayerKHR rect = region.pRectangles[j]; - // TODO: Need to update these errors to their unique error ids when available - if ((rect.offset.x + rect.extent.width) > swapchain_data->createInfo.imageExtent.width) { - skip |= log_msg( - dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, - HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", - "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext " - "chain, pRegion[%i].pRectangles[%i], the sum of offset.x " - "(%i) and extent.width (%i) is greater than the " - "corresponding swapchain's imageExtent.width (%i).", - i, j, rect.offset.x, rect.extent.width, swapchain_data->createInfo.imageExtent.width); - } - if ((rect.offset.y + rect.extent.height) > swapchain_data->createInfo.imageExtent.height) { - skip |= log_msg( - dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, - HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", - "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext " - "chain, pRegion[%i].pRectangles[%i], the sum of offset.y " - "(%i) and extent.height (%i) is greater than the " - "corresponding swapchain's imageExtent.height (%i).", - i, j, rect.offset.y, rect.extent.height, swapchain_data->createInfo.imageExtent.height); - } - if (rect.layer > swapchain_data->createInfo.imageArrayLayers) { - skip |= log_msg( - dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, - HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", - "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext chain, pRegion[%i].pRectangles[%i], the " - "layer (%i) is greater than the corresponding swapchain's imageArrayLayers (%i).", - i, j, rect.layer, swapchain_data->createInfo.imageArrayLayers); - } + const auto *present_regions = lvl_find_in_chain(pPresentInfo->pNext); + if (present_regions) { + for (uint32_t i = 0; i < present_regions->swapchainCount; ++i) { + auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); + assert(swapchain_data); + VkPresentRegionKHR region = present_regions->pRegions[i]; + for (uint32_t j = 0; j < region.rectangleCount; ++j) { + VkRectLayerKHR rect = region.pRectangles[j]; + // TODO: Need to update these errors to their unique error ids when available + if ((rect.offset.x + rect.extent.width) > swapchain_data->createInfo.imageExtent.width) { + skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, HandleToUint64(pPresentInfo->pSwapchains[i]), + __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", + "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext " + "chain, pRegion[%i].pRectangles[%i], the sum of offset.x " + "(%i) and extent.width (%i) is greater than the " + "corresponding swapchain's imageExtent.width (%i).", + i, j, rect.offset.x, rect.extent.width, swapchain_data->createInfo.imageExtent.width); + } + if ((rect.offset.y + rect.extent.height) > swapchain_data->createInfo.imageExtent.height) { + skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, HandleToUint64(pPresentInfo->pSwapchains[i]), + __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", + "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext " + "chain, pRegion[%i].pRectangles[%i], the sum of offset.y " + "(%i) and extent.height (%i) is greater than the " + "corresponding swapchain's imageExtent.height (%i).", + i, j, rect.offset.y, rect.extent.height, swapchain_data->createInfo.imageExtent.height); + } + if (rect.layer > swapchain_data->createInfo.imageArrayLayers) { + skip |= log_msg( + dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, + HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", + "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext chain, pRegion[%i].pRectangles[%i], the " + "layer (%i) is greater than the corresponding swapchain's imageArrayLayers (%i).", + i, j, rect.layer, swapchain_data->createInfo.imageArrayLayers); } } - } else if (VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE == pnext->sType) { - VkPresentTimesInfoGOOGLE *present_times_info = (VkPresentTimesInfoGOOGLE *)pnext; - if (pPresentInfo->swapchainCount != present_times_info->swapchainCount) { - skip |= - log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, + } + } + + const auto *present_times_info = lvl_find_in_chain(pPresentInfo->pNext); + if (present_times_info) { + if (pPresentInfo->swapchainCount != present_times_info->swapchainCount) { + skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, HandleToUint64(pPresentInfo->pSwapchains[0]), __LINE__, VALIDATION_ERROR_118009be, "DS", @@ -9800,9 +9788,7 @@ VKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInf "chain of VkPresentInfoKHR, VkPresentTimesInfoGOOGLE.swapchainCount " "must equal VkPresentInfoKHR.swapchainCount.", present_times_info->swapchainCount, pPresentInfo->swapchainCount); - } } - pnext = (GENERIC_HEADER *)pnext->pNext; } } diff --git a/layers/parameter_validation_utils.cpp b/layers/parameter_validation_utils.cpp index 2a7511a..d115b4f 100644 --- a/layers/parameter_validation_utils.cpp +++ b/layers/parameter_validation_utils.cpp @@ -39,6 +39,7 @@ #include "vulkan/vk_layer.h" #include "vk_layer_config.h" #include "vk_dispatch_table_helper.h" +#include "vk_typemap_helper.h" #include "vk_layer_table.h" #include "vk_layer_data.h" @@ -354,40 +355,13 @@ static bool ValidateDeviceCreateInfo(instance_layer_data *instance_data, VkPhysi if (pCreateInfo->pNext != NULL && pCreateInfo->pEnabledFeatures) { // Check for get_physical_device_properties2 struct - struct std_header { - VkStructureType sType; - const void *pNext; - }; - std_header *cur_pnext = (std_header *)pCreateInfo->pNext; - while (cur_pnext) { - if (VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR == cur_pnext->sType) { - // Cannot include VkPhysicalDeviceFeatures2KHR and have non-null pEnabledFeatures - skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, - 0, __LINE__, INVALID_USAGE, LayerName, - "VkDeviceCreateInfo->pNext includes a VkPhysicalDeviceFeatures2KHR struct when " - "pCreateInfo->pEnabledFeatures is non-NULL."); - break; - } - cur_pnext = (std_header *)cur_pnext->pNext; - } - } - if (pCreateInfo->pNext != NULL && pCreateInfo->pEnabledFeatures) { - // Check for get_physical_device_properties2 struct - struct std_header { - VkStructureType sType; - const void *pNext; - }; - std_header *cur_pnext = (std_header *)pCreateInfo->pNext; - while (cur_pnext) { - if (VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR == cur_pnext->sType) { - // Cannot include VkPhysicalDeviceFeatures2KHR and have non-null pEnabledFeatures - skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, - 0, __LINE__, INVALID_USAGE, LayerName, - "VkDeviceCreateInfo->pNext includes a VkPhysicalDeviceFeatures2KHR struct when " - "pCreateInfo->pEnabledFeatures is non-NULL."); - break; - } - cur_pnext = (std_header *)cur_pnext->pNext; + const auto *features2 = lvl_find_in_chain(pCreateInfo->pNext); + if (features2) { + // Cannot include VkPhysicalDeviceFeatures2KHR and have non-null pEnabledFeatures + skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, + __LINE__, INVALID_USAGE, LayerName, + "VkDeviceCreateInfo->pNext includes a VkPhysicalDeviceFeatures2KHR struct when " + "pCreateInfo->pEnabledFeatures is non-NULL."); } } @@ -501,15 +475,9 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, c // The enabled features can come from either pEnabledFeatures, or from the pNext chain const VkPhysicalDeviceFeatures *enabled_features_found = pCreateInfo->pEnabledFeatures; if ((nullptr == enabled_features_found) && my_device_data->extensions.vk_khr_get_physical_device_properties_2) { - const GenericHeader *current = reinterpret_cast(pCreateInfo->pNext); - while (current) { - if (VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR == current->sType) { - const VkPhysicalDeviceFeatures2KHR *features2 = reinterpret_cast(current); - enabled_features_found = &(features2->features); - current = nullptr; - } else { - current = reinterpret_cast(current->pNext); - } + const auto *features2 = lvl_find_in_chain(pCreateInfo->pNext); + if (features2) { + enabled_features_found = &(features2->features); } } if (enabled_features_found) { @@ -2291,39 +2259,29 @@ bool pv_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) { layer_data *device_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); if (pPresentInfo && pPresentInfo->pNext) { - // Verify ext struct - struct std_header { - VkStructureType sType; - const void *pNext; - }; - std_header *pnext = (std_header *)pPresentInfo->pNext; - while (pnext) { - if (VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR == pnext->sType) { - // TODO: This and all other pNext extension dependencies should be added to code-generation - skip |= require_device_extension(device_data, device_data->extensions.vk_khr_incremental_present, - "vkQueuePresentKHR", VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME); - VkPresentRegionsKHR *present_regions = (VkPresentRegionsKHR *)pnext; - if (present_regions->swapchainCount != pPresentInfo->swapchainCount) { - skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, INVALID_USAGE, LayerName, - "QueuePresentKHR(): pPresentInfo->swapchainCount has a value of %i" - " but VkPresentRegionsKHR extension swapchainCount is %i. These values must be equal.", - pPresentInfo->swapchainCount, present_regions->swapchainCount); - } - skip |= validate_struct_pnext(device_data->report_data, "QueuePresentKHR", "pCreateInfo->pNext->pNext", NULL, - present_regions->pNext, 0, NULL, GeneratedHeaderVersion, VALIDATION_ERROR_1121c40d); - skip |= validate_array(device_data->report_data, "QueuePresentKHR", "pCreateInfo->pNext->swapchainCount", - "pCreateInfo->pNext->pRegions", present_regions->swapchainCount, present_regions->pRegions, - true, false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED); - for (uint32_t i = 0; i < present_regions->swapchainCount; ++i) { - skip |= - validate_array(device_data->report_data, "QueuePresentKHR", "pCreateInfo->pNext->pRegions[].rectangleCount", + const auto *present_regions = lvl_find_in_chain(pPresentInfo->pNext); + if (present_regions) { + // TODO: This and all other pNext extension dependencies should be added to code-generation + skip |= require_device_extension(device_data, device_data->extensions.vk_khr_incremental_present, "vkQueuePresentKHR", + VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME); + if (present_regions->swapchainCount != pPresentInfo->swapchainCount) { + skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, + __LINE__, INVALID_USAGE, LayerName, + "QueuePresentKHR(): pPresentInfo->swapchainCount has a value of %i" + " but VkPresentRegionsKHR extension swapchainCount is %i. These values must be equal.", + pPresentInfo->swapchainCount, present_regions->swapchainCount); + } + skip |= validate_struct_pnext(device_data->report_data, "QueuePresentKHR", "pCreateInfo->pNext->pNext", NULL, + present_regions->pNext, 0, NULL, GeneratedHeaderVersion, VALIDATION_ERROR_1121c40d); + skip |= validate_array(device_data->report_data, "QueuePresentKHR", "pCreateInfo->pNext->swapchainCount", + "pCreateInfo->pNext->pRegions", present_regions->swapchainCount, present_regions->pRegions, true, + false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED); + for (uint32_t i = 0; i < present_regions->swapchainCount; ++i) { + skip |= validate_array(device_data->report_data, "QueuePresentKHR", "pCreateInfo->pNext->pRegions[].rectangleCount", "pCreateInfo->pNext->pRegions[].pRectangles", present_regions->pRegions[i].rectangleCount, present_regions->pRegions[i].pRectangles, true, false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED); - } } - pnext = (std_header *)pnext->pNext; } } diff --git a/scripts/helper_file_generator.py b/scripts/helper_file_generator.py index 3d4ef46..a8e9f13 100644 --- a/scripts/helper_file_generator.py +++ b/scripts/helper_file_generator.py @@ -130,6 +130,7 @@ class HelperFileOutputGenerator(OutputGenerator): copyright += ' * Author: Courtney Goeltzenleuchter \n' copyright += ' * Author: Tobin Ehlis \n' copyright += ' * Author: Chris Forbes \n' + copyright += ' * Author: John Zulauf\n' copyright += ' *\n' copyright += ' ****************************************************************************/\n' write(copyright, file=self.outFile) @@ -919,6 +920,112 @@ class HelperFileOutputGenerator(OutputGenerator): safe_struct_body.append("#endif // %s\n" % item.ifdef_protect) return "\n".join(safe_struct_body) # + # Generate the type map + def GenerateTypeMapHelperHeader(self): + prefix = 'Lvl' + fprefix = 'lvl_' + typemap = prefix + 'TypeMap' + idmap = prefix + 'STypeMap' + name_member = 'kName' + type_member = 'Type' + id_member = 'kSType' + decl_prefix ='constexpr static' + char_decl = decl_prefix + ' const char *' + id_decl = decl_prefix + ' const VkStructureType ' + generic_header = prefix + 'GenericHeader' + typename_func = fprefix + 'typename' + idname_func = fprefix + 'stype_name' + find_func = fprefix + 'find_in_chain' + + explanatory_comment = '\n'.join(( + '// These empty generic templates are specialized for each type with sType', + '// members and for each sType -- providing a two way map between structure', + '// types and sTypes as well as a kName stringification for convenience')) + + empty_typemap = 'template struct ' + typemap + ' {};' + typemap_format = 'template <> struct {template}<{typename}> {{\n' + typemap_format += ' {char_decl}{name} = "{typename}";\n' + typemap_format += ' {id_decl}{id_member} = {id_value};\n' + typemap_format += '}};\n' + + empty_idmap = 'template struct ' + idmap + ' {};' + idmap_format = ''.join(( + 'template <> struct {template}<{id_value}> {{\n', + ' typedef {typename} {typedef};\n', + ' {char_decl}{name} = "{id_value}";\n', + '}};\n')) + + # Define the utilities (here so any renaming stays consistent), if this grows large, refactor to a fixed .h file + utilities_format = '\n'.join(( + '// Header "base class" for pNext chain traversal', + 'struct {header} {{', + ' VkStructureType sType;', + ' const {header} *pNext;', + '}};', + '', + '// Find an entry of the given type in the pNext chain', + 'template const T *{find_func}(const void *next) {{', + ' const {header} *current = reinterpret_cast(next);', + ' const T *found = nullptr;', + ' while (current) {{', + ' if ({type_map}::{id_member} == current->sType) {{', + ' found = reinterpret_cast(current);', + ' current = nullptr;', + ' }} else {{', + ' current = current->pNext;', + ' }}', + ' }}', + ' return found;', + '}}', + '', + '// Convenience functions for accessing the other mapped objects name field', + 'template constexpr const char *{idname_func}() {{', + ' return {id_map}<{type_map}::{id_member}>::{name_member};', + '}}', + 'template constexpr const char *{typename_func}() {{', + ' return {type_map}::{type_member}>::{name_member};', + '}}')) + + code = [] + code.append('\n'.join(( + '#pragma once', + '#include \n', + explanatory_comment, '', + empty_idmap, + empty_typemap, '', + utilities_format.format(name_member=name_member, id_member=id_member, id_map=idmap, type_map=typemap, + type_member=type_member, header=generic_header, typename_func=typename_func, idname_func=idname_func, + find_func=find_func), '' + ))) + + # Generate the specializations for each type and stype + + for item in self.structMembers: + typename = item.name + info = self.structTypes.get(typename) + if not info: + continue + + if item.ifdef_protect != None: + code.append('#ifdef %s' % item.ifdef_protect) + + code.append('// Map type {} to id {}'.format(typename, info.value)) + code.append(typemap_format.format(template=typemap, typename=typename, id_value=info.value, + char_decl=char_decl, id_decl=id_decl, name=name_member, id_member=id_member)) + code.append(idmap_format.format(template=idmap, typename=typename, id_value=info.value, char_decl=char_decl, typedef=type_member, name=name_member)) + + if item.ifdef_protect != None: + code.append('#endif // %s' % item.ifdef_protect) + + #for typename, info in self.structTypes.items(): + # code.append("// Map type {} to id {}".format(typename, info.value)) + # code.append(typemap_format.format(template=typemap, typename=typename, id_value=info.value, + # char_decl=char_decl, id_decl=id_decl, name=name_member, id_member=id_member)) + # code.append(idmap_format.format(template=idmap, typename=typename, id_value=info.value, char_decl=char_decl, typedef=type_member, name=name_member)) + + return "\n".join(code) + + # # Create a helper file and return it as a string def OutputDestFile(self): if self.helper_file_type == 'enum_string_header': @@ -935,6 +1042,8 @@ class HelperFileOutputGenerator(OutputGenerator): return self.GenerateObjectTypesHelperHeader() elif self.helper_file_type == 'extension_helper_header': return self.GenerateExtensionHelperHeader() + elif self.helper_file_type == 'typemap_helper_header': + return self.GenerateTypeMapHelperHeader() else: return 'Bad Helper File Generator Option %s' % self.helper_file_type diff --git a/scripts/lvl_genvk.py b/scripts/lvl_genvk.py index 09554db..7c81f51 100644 --- a/scripts/lvl_genvk.py +++ b/scripts/lvl_genvk.py @@ -424,6 +424,28 @@ def makeGenOpts(extensions = [], removeExtensions = [], protect = True, director helper_file_type = 'extension_helper_header') ] + # Helper file generator options for typemap_helper.h + genOpts['vk_typemap_helper.h'] = [ + HelperFileOutputGenerator, + HelperFileOutputGeneratorOptions( + filename = 'vk_typemap_helper.h', + directory = directory, + apiname = 'vulkan', + profile = None, + versions = allVersions, + emitversions = allVersions, + defaultExtensions = 'vulkan', + addExtensions = addExtensions, + removeExtensions = removeExtensions, + prefixText = prefixStrings + vkPrefixStrings, + protectFeature = False, + apicall = 'VKAPI_ATTR ', + apientry = 'VKAPI_CALL ', + apientryp = 'VKAPI_PTR *', + alignFuncParam = 48, + helper_file_type = 'typemap_helper_header') + ] + # Options for mock ICD header genOpts['mock_icd.h'] = [ MockICDOutputGenerator, -- 2.7.4