From c7fa9ded83987157c81d63d5c4a1171797b0c43e Mon Sep 17 00:00:00 2001 From: Mark Young Date: Thu, 7 Nov 2024 17:34:51 -0500 Subject: [PATCH 01/32] codegen: Update ref resource consumer Update the referenced resource consumer generators to use the Khronos variables. Interestingly enough, it removes 4 functions which appeared to have incorrectly been added by the previous codegen. --- ...ed_vulkan_referenced_resource_consumer.cpp | 78 +------------------ ...ated_vulkan_referenced_resource_consumer.h | 26 ------- ...renced_resource_consumer_body_generator.py | 21 +---- ...nced_resource_consumer_header_generator.py | 16 +--- 4 files changed, 6 insertions(+), 135 deletions(-) diff --git a/framework/generated/generated_vulkan_referenced_resource_consumer.cpp b/framework/generated/generated_vulkan_referenced_resource_consumer.cpp index 75fb3f5200..cac4440118 100644 --- a/framework/generated/generated_vulkan_referenced_resource_consumer.cpp +++ b/framework/generated/generated_vulkan_referenced_resource_consumer.cpp @@ -949,7 +949,6 @@ void VulkanReferencedResourceConsumer::Process_vkCmdBindDescriptorSets2( if (!pBindDescriptorSetsInfo->IsNull() && (pBindDescriptorSetsInfo->HasData())) { auto pBindDescriptorSetsInfo_ptr = pBindDescriptorSetsInfo->GetMetaStructPointer(); - if (!pBindDescriptorSetsInfo_ptr->pDescriptorSets.IsNull() && (pBindDescriptorSetsInfo_ptr->pDescriptorSets.HasData())) { auto pDescriptorSets_ptr = pBindDescriptorSetsInfo_ptr->pDescriptorSets.GetPointer(); @@ -962,19 +961,6 @@ void VulkanReferencedResourceConsumer::Process_vkCmdBindDescriptorSets2( } } -void VulkanReferencedResourceConsumer::Process_vkCmdPushConstants2( - const ApiCallInfo& call_info, - format::HandleId commandBuffer, - StructPointerDecoder* pPushConstantsInfo) -{ - assert(pPushConstantsInfo != nullptr); - - if (!pPushConstantsInfo->IsNull() && (pPushConstantsInfo->HasData())) - { - auto pPushConstantsInfo_ptr = pPushConstantsInfo->GetMetaStructPointer(); - } -} - void VulkanReferencedResourceConsumer::Process_vkCmdPushDescriptorSet2( const ApiCallInfo& call_info, format::HandleId commandBuffer, @@ -985,7 +971,6 @@ void VulkanReferencedResourceConsumer::Process_vkCmdPushDescriptorSet2( if (!pPushDescriptorSetInfo->IsNull() && (pPushDescriptorSetInfo->HasData())) { auto pPushDescriptorSetInfo_ptr = pPushDescriptorSetInfo->GetMetaStructPointer(); - if (!pPushDescriptorSetInfo_ptr->pDescriptorWrites->IsNull() && (pPushDescriptorSetInfo_ptr->pDescriptorWrites->HasData())) { auto pDescriptorWrites_ptr = pPushDescriptorSetInfo_ptr->pDescriptorWrites->GetMetaStructPointer(); @@ -1571,7 +1556,6 @@ void VulkanReferencedResourceConsumer::Process_vkCmdBindDescriptorSets2KHR( if (!pBindDescriptorSetsInfo->IsNull() && (pBindDescriptorSetsInfo->HasData())) { auto pBindDescriptorSetsInfo_ptr = pBindDescriptorSetsInfo->GetMetaStructPointer(); - if (!pBindDescriptorSetsInfo_ptr->pDescriptorSets.IsNull() && (pBindDescriptorSetsInfo_ptr->pDescriptorSets.HasData())) { auto pDescriptorSets_ptr = pBindDescriptorSetsInfo_ptr->pDescriptorSets.GetPointer(); @@ -1584,19 +1568,6 @@ void VulkanReferencedResourceConsumer::Process_vkCmdBindDescriptorSets2KHR( } } -void VulkanReferencedResourceConsumer::Process_vkCmdPushConstants2KHR( - const ApiCallInfo& call_info, - format::HandleId commandBuffer, - StructPointerDecoder* pPushConstantsInfo) -{ - assert(pPushConstantsInfo != nullptr); - - if (!pPushConstantsInfo->IsNull() && (pPushConstantsInfo->HasData())) - { - auto pPushConstantsInfo_ptr = pPushConstantsInfo->GetMetaStructPointer(); - } -} - void VulkanReferencedResourceConsumer::Process_vkCmdPushDescriptorSet2KHR( const ApiCallInfo& call_info, format::HandleId commandBuffer, @@ -1607,7 +1578,6 @@ void VulkanReferencedResourceConsumer::Process_vkCmdPushDescriptorSet2KHR( if (!pPushDescriptorSetInfo->IsNull() && (pPushDescriptorSetInfo->HasData())) { auto pPushDescriptorSetInfo_ptr = pPushDescriptorSetInfo->GetMetaStructPointer(); - if (!pPushDescriptorSetInfo_ptr->pDescriptorWrites->IsNull() && (pPushDescriptorSetInfo_ptr->pDescriptorWrites->HasData())) { auto pDescriptorWrites_ptr = pPushDescriptorSetInfo_ptr->pDescriptorWrites->GetMetaStructPointer(); @@ -1665,32 +1635,6 @@ void VulkanReferencedResourceConsumer::Process_vkCmdPushDescriptorSet2KHR( } } -void VulkanReferencedResourceConsumer::Process_vkCmdSetDescriptorBufferOffsets2EXT( - const ApiCallInfo& call_info, - format::HandleId commandBuffer, - StructPointerDecoder* pSetDescriptorBufferOffsetsInfo) -{ - assert(pSetDescriptorBufferOffsetsInfo != nullptr); - - if (!pSetDescriptorBufferOffsetsInfo->IsNull() && (pSetDescriptorBufferOffsetsInfo->HasData())) - { - auto pSetDescriptorBufferOffsetsInfo_ptr = pSetDescriptorBufferOffsetsInfo->GetMetaStructPointer(); - } -} - -void VulkanReferencedResourceConsumer::Process_vkCmdBindDescriptorBufferEmbeddedSamplers2EXT( - const ApiCallInfo& call_info, - format::HandleId commandBuffer, - StructPointerDecoder* pBindDescriptorBufferEmbeddedSamplersInfo) -{ - assert(pBindDescriptorBufferEmbeddedSamplersInfo != nullptr); - - if (!pBindDescriptorBufferEmbeddedSamplersInfo->IsNull() && (pBindDescriptorBufferEmbeddedSamplersInfo->HasData())) - { - auto pBindDescriptorBufferEmbeddedSamplersInfo_ptr = pBindDescriptorBufferEmbeddedSamplersInfo->GetMetaStructPointer(); - } -} - void VulkanReferencedResourceConsumer::Process_vkCmdBindTransformFeedbackBuffersEXT( const ApiCallInfo& call_info, format::HandleId commandBuffer, @@ -2099,31 +2043,11 @@ void VulkanReferencedResourceConsumer::Process_vkCmdPreprocessGeneratedCommandsE StructPointerDecoder* pGeneratedCommandsInfo, format::HandleId stateCommandBuffer) { - assert(pGeneratedCommandsInfo != nullptr); + GFXRECON_UNREFERENCED_PARAMETER(pGeneratedCommandsInfo); - if (!pGeneratedCommandsInfo->IsNull() && (pGeneratedCommandsInfo->HasData())) - { - auto pGeneratedCommandsInfo_ptr = pGeneratedCommandsInfo->GetMetaStructPointer(); - } GetTable().AddUserToUser(commandBuffer, stateCommandBuffer); } -void VulkanReferencedResourceConsumer::Process_vkCmdExecuteGeneratedCommandsEXT( - const ApiCallInfo& call_info, - format::HandleId commandBuffer, - VkBool32 isPreprocessed, - StructPointerDecoder* pGeneratedCommandsInfo) -{ - GFXRECON_UNREFERENCED_PARAMETER(isPreprocessed); - - assert(pGeneratedCommandsInfo != nullptr); - - if (!pGeneratedCommandsInfo->IsNull() && (pGeneratedCommandsInfo->HasData())) - { - auto pGeneratedCommandsInfo_ptr = pGeneratedCommandsInfo->GetMetaStructPointer(); - } -} - void VulkanReferencedResourceConsumer::Process_vkCmdBuildAccelerationStructuresKHR( const ApiCallInfo& call_info, format::HandleId commandBuffer, diff --git a/framework/generated/generated_vulkan_referenced_resource_consumer.h b/framework/generated/generated_vulkan_referenced_resource_consumer.h index c5b1353c10..dcf069f841 100644 --- a/framework/generated/generated_vulkan_referenced_resource_consumer.h +++ b/framework/generated/generated_vulkan_referenced_resource_consumer.h @@ -358,11 +358,6 @@ class VulkanReferencedResourceConsumer : public VulkanReferencedResourceConsumer format::HandleId commandBuffer, StructPointerDecoder* pBindDescriptorSetsInfo) override; - virtual void Process_vkCmdPushConstants2( - const ApiCallInfo& call_info, - format::HandleId commandBuffer, - StructPointerDecoder* pPushConstantsInfo) override; - virtual void Process_vkCmdPushDescriptorSet2( const ApiCallInfo& call_info, format::HandleId commandBuffer, @@ -484,26 +479,11 @@ class VulkanReferencedResourceConsumer : public VulkanReferencedResourceConsumer format::HandleId commandBuffer, StructPointerDecoder* pBindDescriptorSetsInfo) override; - virtual void Process_vkCmdPushConstants2KHR( - const ApiCallInfo& call_info, - format::HandleId commandBuffer, - StructPointerDecoder* pPushConstantsInfo) override; - virtual void Process_vkCmdPushDescriptorSet2KHR( const ApiCallInfo& call_info, format::HandleId commandBuffer, StructPointerDecoder* pPushDescriptorSetInfo) override; - virtual void Process_vkCmdSetDescriptorBufferOffsets2EXT( - const ApiCallInfo& call_info, - format::HandleId commandBuffer, - StructPointerDecoder* pSetDescriptorBufferOffsetsInfo) override; - - virtual void Process_vkCmdBindDescriptorBufferEmbeddedSamplers2EXT( - const ApiCallInfo& call_info, - format::HandleId commandBuffer, - StructPointerDecoder* pBindDescriptorBufferEmbeddedSamplersInfo) override; - virtual void Process_vkCmdBindTransformFeedbackBuffersEXT( const ApiCallInfo& call_info, format::HandleId commandBuffer, @@ -673,12 +653,6 @@ class VulkanReferencedResourceConsumer : public VulkanReferencedResourceConsumer StructPointerDecoder* pGeneratedCommandsInfo, format::HandleId stateCommandBuffer) override; - virtual void Process_vkCmdExecuteGeneratedCommandsEXT( - const ApiCallInfo& call_info, - format::HandleId commandBuffer, - VkBool32 isPreprocessed, - StructPointerDecoder* pGeneratedCommandsInfo) override; - virtual void Process_vkCmdBuildAccelerationStructuresKHR( const ApiCallInfo& call_info, format::HandleId commandBuffer, diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_body_generator.py index bb3ca95bf6..368b7df023 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_body_generator.py @@ -79,10 +79,6 @@ def __init__( warn_file=warn_file, diag_file=diag_file ) - # Map of Vulkan structs containing handles to a list values for handle members or struct members - # that contain handles (eg. VkGraphicsPipelineCreateInfo contains a VkPipelineShaderStageCreateInfo - # member that contains handles). - self.structs_with_handles = dict() self.restrict_handles = True # Determines if the 'is_handle' override limits the handle test to only the values conained by RESOURCE_HANDLE_TYPES. def beginFile(self, gen_opts): @@ -155,15 +151,6 @@ def endFile(self): # Finish processing in superclass BaseGenerator.endFile(self) - def genStruct(self, typeinfo, typename, alias): - """Method override.""" - BaseGenerator.genStruct(self, typeinfo, typename, alias) - - if not alias: - self.check_struct_member_handles( - typename, self.structs_with_handles - ) - def need_feature_generation(self): """Indicates that the current feature has C++ code to generate.""" if self.feature_cmd_params: @@ -187,7 +174,7 @@ def get_param_list_handles(self, cmd, values): handles.append(value) elif self.is_struct( value.base_type - ) and (value.base_type in self.structs_with_handles): + ) and (value.base_type in self.global_structs_with_handles): handles.append(value) return handles @@ -283,20 +270,20 @@ def track_command_handle( elif self.is_struct( value.base_type - ) and (value.base_type in self.structs_with_handles): + ) and (value.base_type in self.global_structs_with_handles): if value.is_array: access_operator = '[{}].'.format(index_name) else: access_operator = '->' for index, entry in enumerate( - self.structs_with_handles[value.base_type] + self.global_structs_with_handles[value.base_type] ): if entry.name == 'pNext': ext_structs_with_handles = [ ext_struct for ext_struct in self.registry.validextensionstructs[value.base_type] - if ext_struct in self.structs_with_handles + if ext_struct in self.global_structs_with_handles ] if ext_structs_with_handles: for ext_struct in ext_structs_with_handles: diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_header_generator.py index 7b64f2358b..61270c7dda 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_header_generator.py @@ -73,11 +73,6 @@ def __init__( warn_file=warn_file, diag_file=diag_file ) - # Map of Vulkan structs containing handles to a list values for handle members or struct members - # that contain handles (eg. VkGraphicsPipelineCreateInfo contains a VkPipelineShaderStageCreateInfo - # member that contains handles). - self.structs_with_handles = dict() - self.command_info = dict() # Map of Vulkan commands to parameter info self.restrict_handles = True # Determines if the 'is_handle' override limits the handle test to only the values conained by RESOURCE_HANDLE_TYPES. def beginFile(self, gen_opts): @@ -145,15 +140,6 @@ def endFile(self): # Finish processing in superclass BaseGenerator.endFile(self) - def genStruct(self, typeinfo, typename, alias): - """Method override.""" - BaseGenerator.genStruct(self, typeinfo, typename, alias) - - if not alias: - self.check_struct_member_handles( - typename, self.structs_with_handles - ) - def need_feature_generation(self): """Indicates that the current feature has C++ code to generate.""" if self.feature_cmd_params: @@ -177,6 +163,6 @@ def get_param_list_handles(self, values): handles.append(value) elif self.is_struct( value.base_type - ) and (value.base_type in self.structs_with_handles): + ) and (value.base_type in self.global_structs_with_handles): handles.append(value) return handles From daeac7c042a7954abd20d5f3655c861f0a08af84 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Thu, 7 Nov 2024 17:40:55 -0500 Subject: [PATCH 02/32] codegen: Update cmd buffer util header Update the command buffer util header codegen to remove unused types and use Khronos types when necessary. --- ...ulkan_command_buffer_util_header_generator.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_header_generator.py index 071a1fdf27..dfd1afb60e 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_header_generator.py @@ -69,11 +69,6 @@ def __init__( diag_file=diag_file ) - # Map of Vulkan structs containing handles to a list values for handle members or struct members - # that contain handles (eg. VkGraphicsPipelineCreateInfo contains a VkPipelineShaderStageCreateInfo - # member that contains handles). - self.structs_with_handles = dict() - def beginFile(self, gen_opts): """Method override.""" BaseGenerator.beginFile(self, gen_opts) @@ -113,15 +108,6 @@ def endFile(self): # Finish processing in superclass BaseGenerator.endFile(self) - def genStruct(self, typeinfo, typename, alias): - """Method override.""" - BaseGenerator.genStruct(self, typeinfo, typename, alias) - - if not alias: - self.check_struct_member_handles( - typename, self.structs_with_handles - ) - def need_feature_generation(self): """Indicates that the current feature has C++ code to generate.""" if self.feature_cmd_params: @@ -136,7 +122,7 @@ def get_param_list_handles(self, values): handles.append(value) elif self.is_struct( value.base_type - ) and (value.base_type in self.structs_with_handles): + ) and (value.base_type in self.global_structs_with_handles): handles.append(value) return handles From 155f1926e2935a0740422e8183d0f3a79b2a14c2 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Thu, 7 Nov 2024 17:41:25 -0500 Subject: [PATCH 03/32] codegen: Remove unused code in CPP consumer --- .../vulkan_cpp_consumer_body_generator.py | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_cpp_consumer_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_cpp_consumer_body_generator.py index 2979fc716a..e1edb7b5d3 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_cpp_consumer_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_cpp_consumer_body_generator.py @@ -578,31 +578,9 @@ def __init__( 'vkCreateAccelerationStructureNV' ] - self.stype_values = dict() - self.structs_with_handle_ptrs = [] - self.structs_with_handles = dict() - def writeout(self, *args, **kwargs): write(*args, **kwargs, file=self.outFile) - def genStruct(self, typeinfo, typename, alias): - """ - Process struct information - - Note: Using method from replay consumer generator - """ - BaseGenerator.genStruct(self, typeinfo, typename, alias) - - if not alias: - self.check_struct_member_handles( - typename, self.structs_with_handles, - self.structs_with_handle_ptrs - ) - - stype = self.make_structure_type_enum(typeinfo, typename) - if stype: - self.stype_values[typename] = stype - def beginFile(self, gen_opts): """Method override.""" BaseGenerator.beginFile(self, gen_opts) From 5b26f298ebff9ea214e8a891085add858745c4e2 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Thu, 7 Nov 2024 17:44:02 -0500 Subject: [PATCH 04/32] codegen: Update cmd buf util body generation Remove unused types and use Khronos types. --- ...lkan_command_buffer_util_body_generator.py | 38 ++++--------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_body_generator.py index 59c4ddca81..ed62ee788b 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_body_generator.py @@ -69,13 +69,6 @@ def __init__( diag_file=diag_file ) - # Map of Vulkan structs containing handles to a list values for handle members or struct members - # that contain handles (eg. VkGraphicsPipelineCreateInfo contains a VkPipelineShaderStageCreateInfo - # member that contains handles). - self.structs_with_handles = dict() - self.pnext_structs = dict( - ) # Map of Vulkan structure types to sType value for structs that can be part of a pNext chain. - self.command_info = dict() # Map of Vulkan commands to parameter info # The following functions require custom implementations self.customImplementationRequired = { 'CmdPushDescriptorSetKHR' @@ -101,11 +94,12 @@ def beginFile(self, gen_opts): def endFile(self): """Method override.""" + command_info = dict() # Map of Vulkan commands to parameter info for cmd in self.get_all_filtered_cmd_names(): - self.command_info[cmd] = self.all_cmd_params[cmd] + command_info[cmd] = self.all_cmd_params[cmd] wrapper_prefix = self.get_wrapper_prefix_from_type() - for cmd, info in self.command_info.items(): + for cmd, info in command_info.items(): if not cmd[2:] in self.customImplementationRequired: params = info[2] if params and params[0].base_type == 'VkCommandBuffer': @@ -137,22 +131,6 @@ def endFile(self): # Finish processing in superclass BaseGenerator.endFile(self) - def genStruct(self, typeinfo, typename, alias): - """Method override.""" - BaseGenerator.genStruct(self, typeinfo, typename, alias) - - if not alias: - self.check_struct_member_handles( - typename, self.structs_with_handles - ) - - # Track this struct if it can be present in a pNext chain. - parent_structs = typeinfo.elem.get('structextends') - if parent_structs: - stype = self.make_structure_type_enum(typeinfo, typename) - if stype: - self.pnext_structs[typename] = stype - def need_feature_generation(self): """Indicates that the current feature has C++ code to generate.""" if self.feature_cmd_params: @@ -167,7 +145,7 @@ def get_param_list_handles(self, values): handles.append(value) elif self.is_struct( value.base_type - ) and (value.base_type in self.structs_with_handles): + ) and (value.base_type in self.global_structs_with_handles): handles.append(value) return handles @@ -218,7 +196,7 @@ def insert_command_handle(self, index, value, value_prefix='', indent=''): elif self.is_struct( value.base_type - ) and (value.base_type in self.structs_with_handles): + ) and (value.base_type in self.global_structs_with_handles): if value.is_array: access_operator = '[{}].'.format(index_name) elif value.is_pointer: @@ -227,13 +205,13 @@ def insert_command_handle(self, index, value, value_prefix='', indent=''): access_operator = '.' for index, entry in enumerate( - self.structs_with_handles[value.base_type] + self.global_structs_with_handles[value.base_type] ): if entry.name == 'pNext': ext_structs_with_handles = [ ext_struct for ext_struct in self.registry.validextensionstructs[value.base_type] - if ext_struct in self.structs_with_handles + if ext_struct in self.global_structs_with_handles ] if ext_structs_with_handles: body += indent + 'auto pnext_header = reinterpret_cast({}{}->pNext);\n'.format( @@ -251,7 +229,7 @@ def insert_command_handle(self, index, value, value_prefix='', indent=''): indent = indent[:-self.INDENT_SIZE] for ext_struct in ext_structs_with_handles: body += indent + 'case {}:\n'.format( - self.pnext_structs[ext_struct] + self.struct_type_names[ext_struct] ) body += indent + '{\n' indent += ' ' * self.INDENT_SIZE From c8e46651aa96b667c31858e04f5d937d68ec4718 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Thu, 7 Nov 2024 17:47:26 -0500 Subject: [PATCH 05/32] codegen: Update api call endcoders Update the api call encoder body generation to use Khronos types. --- ...vulkan_api_call_encoders_body_generator.py | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_api_call_encoders_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_api_call_encoders_body_generator.py index 5c19158025..86b389272f 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_api_call_encoders_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_api_call_encoders_body_generator.py @@ -82,11 +82,6 @@ def __init__( diag_file=diag_file ) - # Map of Vulkan structs containing handles to a list values for handle members or struct members - # that contain handles (eg. VkGraphicsPipelineCreateInfo contains a VkPipelineShaderStageCreateInfo - # member that contains handles). - self.structs_with_handles = dict() - def beginFile(self, gen_opts): """Method override.""" BaseGenerator.beginFile(self, gen_opts) @@ -154,15 +149,6 @@ def endFile(self): # Finish processing in superclass BaseGenerator.endFile(self) - def genStruct(self, typeinfo, typename, alias): - """Method override.""" - BaseGenerator.genStruct(self, typeinfo, typename, alias) - - if not alias: - self.check_struct_member_handles( - typename, self.structs_with_handles - ) - def need_feature_generation(self): """Indicates that the current feature has C++ code to generate.""" if self.feature_cmd_params: @@ -444,7 +430,7 @@ def get_struct_handle_member_info(self, members): elif self.is_struct(member.base_type): # This can't handle the case where 'member' is an array of structs member_handle_type, member_handle_name, member_array_length = self.get_struct_handle_member_info( - self.structs_with_handles[member.base_type] + self.global_structs_with_handles[member.base_type] ) member_handle_name = '{}.{}'.format( member.name, member_handle_name @@ -511,7 +497,7 @@ def make_end_api_call(self, name, values, return_type): # "handle" is actually a struct with embedded handles unwrap_handle_def = 'nullptr' member_handle_type, member_handle_name, member_array_length = self.get_struct_handle_member_info( - self.structs_with_handles[handle.base_type] + self.global_structs_with_handles[handle.base_type] ) if not member_array_length: @@ -576,7 +562,7 @@ def make_end_api_call(self, name, values, return_type): # "handle" is actually a struct with embedded handles unwrap_handle_def = 'nullptr' member_handle_type, member_handle_name, member_array_length = self.get_struct_handle_member_info( - self.structs_with_handles[handle.base_type] + self.global_structs_with_handles[handle.base_type] ) if not member_array_length: @@ -668,7 +654,7 @@ def make_handle_wrapping(self, values, indent): if self.is_output_parameter(value) and ( self.is_handle(value.base_type) or ( self.is_struct(value.base_type) and - (value.base_type in self.structs_with_handles) + (value.base_type in self.global_structs_with_handles) ) ): # The VkInstance handle does not have parent, so the 'unused' @@ -691,7 +677,7 @@ def make_handle_wrapping(self, values, indent): ) and value.is_array and ('->' in value.array_length): # An array of handles with length specified by an AllocateInfo structure (there is a -> in the length name) is a pool allocation. # Extract the pool handle from the AllocateInfo structure, which is currently the first and only handle member. - members = self.structs_with_handles[values[1].base_type] + members = self.global_structs_with_handles[values[1].base_type] for member in members: if self.is_handle(member.base_type): co_parent_type = wrapper_prefix + '::' + member.base_type[2:] + 'Wrapper' @@ -715,7 +701,7 @@ def make_handle_wrapping(self, values, indent): ) elif self.is_struct( value.base_type - ) and (value.base_type in self.structs_with_handles): + ) and (value.base_type in self.global_structs_with_handles): expr += indent + '{}::CreateWrappedStructArrayHandles<{}, {}, {}>({}, {}, {}, {}, VulkanCaptureManager::GetUniqueId);\n'.format( wrapper_prefix, parent_type, co_parent_type, value.base_type, parent_value, co_parent_value, value.name, @@ -729,7 +715,7 @@ def make_handle_wrapping(self, values, indent): ) elif self.is_struct( value.base_type - ) and (value.base_type in self.structs_with_handles): + ) and (value.base_type in self.global_structs_with_handles): expr += indent + '{}::CreateWrappedStructHandles<{}, {}>({}, {}, {}, VulkanCaptureManager::GetUniqueId);\n'.format( wrapper_prefix, parent_type, co_parent_type, parent_value, co_parent_value, value.name @@ -745,7 +731,7 @@ def make_handle_unwrapping(self, name, values, indent): arg_name = value.name if value.is_pointer or value.is_array: if self.is_input_pointer(value): - if (value.base_type in self.structs_with_handles) or ( + if (value.base_type in self.global_structs_with_handles) or ( value.base_type in self.GENERIC_HANDLE_STRUCTS ): need_unwrap_memory = True @@ -807,7 +793,7 @@ def get_param_list_handles(self, values): handles.append(value) elif self.is_struct( value.base_type - ) and (value.base_type in self.structs_with_handles): + ) and (value.base_type in self.global_structs_with_handles): handles.append(value) return handles @@ -831,7 +817,7 @@ def retrieves_handles(self, values): for value in values: if self.is_output_parameter(value) and ( self.is_handle(value.base_type) or - (value.base_type in self.structs_with_handles) + (value.base_type in self.global_structs_with_handles) ): return True return False From 989b19322273c6fd16d56e6d24dca344c06836ab Mon Sep 17 00:00:00 2001 From: Mark Young Date: Thu, 7 Nov 2024 17:50:33 -0500 Subject: [PATCH 06/32] codegen: Rename global_structs_with_handle* Now that the porting is done, rename "global_structs_with_handle" with "structs_with_handle". --- .../khronos_base_generator.py | 64 +++++++++---------- ...se_struct_handle_mappers_body_generator.py | 16 ++--- ..._struct_handle_mappers_header_generator.py | 6 +- ...vulkan_api_call_encoders_body_generator.py | 20 +++--- ...lkan_command_buffer_util_body_generator.py | 8 +-- ...an_command_buffer_util_header_generator.py | 2 +- ...renced_resource_consumer_body_generator.py | 8 +-- ...nced_resource_consumer_header_generator.py | 2 +- .../vulkan_replay_consumer_body_generator.py | 16 ++--- ...n_struct_handle_wrappers_body_generator.py | 8 +-- ...struct_handle_wrappers_header_generator.py | 6 +- 11 files changed, 76 insertions(+), 80 deletions(-) diff --git a/framework/generated/khronos_generators/khronos_base_generator.py b/framework/generated/khronos_generators/khronos_base_generator.py index e88d853d46..0ebbb5d4eb 100644 --- a/framework/generated/khronos_generators/khronos_base_generator.py +++ b/framework/generated/khronos_generators/khronos_base_generator.py @@ -388,11 +388,9 @@ def __init__( self.all_cmd_params = OrderedDict() # Map of cmd names to lists of per-parameter ValueInfo self.feature_cmd_params = OrderedDict() # Map of cmd names to lists of per-parameter ValueInfo - # TODO: Temp, add "global_" to the name so they don't conflict with the existing items as we - # transition over to using global versions - self.global_structs_with_handles = OrderedDict( + self.structs_with_handles = OrderedDict( ) # Map of structures with handles - self.global_structs_with_handle_ptrs = set( + self.structs_with_handle_ptrs = set( ) # Set of structures with handles # Data for every supported Khronos API @@ -1019,16 +1017,16 @@ def bubble_up_struct_has_handles(self, typename): for struct in self.all_struct_members: # If it's already listed as having a handle, just skip - if struct in self.global_structs_with_handles: + if struct in self.structs_with_handles: continue for member in self.all_struct_members[struct]: if member.base_type == typename: - self.global_structs_with_handles[struct] = [member] + self.structs_with_handles[struct] = [member] if ( - struct not in self.global_structs_with_handle_ptrs + struct not in self.structs_with_handle_ptrs and (member.is_pointer or member.is_array) ): - self.global_structs_with_handle_ptrs.add(struct) + self.structs_with_handle_ptrs.add(struct) self.bubble_up_struct_has_handles(struct) @@ -1043,7 +1041,7 @@ def gen_set_parent_has_handles(self, parent): the parent to indicate that it to now has a handle.""" # If it's already listed as having a handle, just skip if ( - parent in self.global_structs_with_handles + parent in self.structs_with_handles or self.is_struct_black_listed(parent) or self.is_base_input_structure_type(parent) or self.is_base_output_structure_type(parent) @@ -1053,11 +1051,11 @@ def gen_set_parent_has_handles(self, parent): if (parent in self.children_structs.keys()): # See if any of the children structures have handles for child in self.children_structs[parent]: - if child in self.global_structs_with_handles: - self.global_structs_with_handles[parent] = [child] + if child in self.structs_with_handles: + self.structs_with_handles[parent] = [child] self.bubble_up_struct_has_handles(parent) - if parent not in self.global_structs_with_handle_ptrs: - self.global_structs_with_handle_ptrs.add(parent) + if parent not in self.structs_with_handle_ptrs: + self.structs_with_handle_ptrs.add(parent) def process_struct(self, element, typename, alias): # For structs, we ignore the alias because it is a typedef. Not ignoring the alias @@ -1102,7 +1100,7 @@ def process_struct(self, element, typename, alias): ): for extended_struct in self.all_extended_structs[typename]: - if extended_struct in self.global_structs_with_handles: + if extended_struct in self.structs_with_handles: handles.append(deepcopy(current_struct_member)) break @@ -1114,9 +1112,9 @@ def process_struct(self, element, typename, alias): # If the struct is one we already know about and it has handles, record that elif self.is_struct(current_struct_member.base_type): - if current_struct_member.base_type in self.global_structs_with_handles: + if current_struct_member.base_type in self.structs_with_handles: handles.append(deepcopy(current_struct_member)) - if current_struct_member.base_type in self.global_structs_with_handle_ptrs: + if current_struct_member.base_type in self.structs_with_handle_ptrs: has_handle_pointers = True elif ( @@ -1126,22 +1124,22 @@ def process_struct(self, element, typename, alias): # See if any of the children structures have handles for child in self.children_structs[ current_struct_member.base_type]: - if child in self.global_structs_with_handles: + if child in self.structs_with_handles: handles.append(deepcopy(current_struct_member)) break if len(handles) > 0: - if typename in self.global_structs_with_handles: + if typename in self.structs_with_handles: for handle in handles: # Only add the handles if it is not already listed in the # list of structure handles - if typename not in self.global_structs_with_handles[ + if typename not in self.structs_with_handles[ typename]: - self.global_structs_with_handles[typename].append( + self.structs_with_handles[typename].append( handle ) else: - self.global_structs_with_handles[typename] = handles + self.structs_with_handles[typename] = handles self.bubble_up_struct_has_handles(typename) # If this struct has a parent name, keep track of all @@ -1182,37 +1180,35 @@ def process_struct(self, element, typename, alias): # append the extended struct field name to the # existing list if it's not already there found = False - if ext_struct in self.global_structs_with_handles: - for check_handle in self.global_structs_with_handles[ + if ext_struct in self.structs_with_handles: + for check_handle in self.structs_with_handles[ ext_struct]: if check_handle.name == member.name: found = True break if not found: - if ext_struct in self.global_structs_with_handles: + if ext_struct in self.structs_with_handles: # If this member is not in the list of struct handles, # add it to the list and put it at the beginning - if member not in self.global_structs_with_handles[ + if member not in self.structs_with_handles[ ext_struct]: - self.global_structs_with_handles[ + self.structs_with_handles[ ext_struct].extend( [member] ) - self.global_structs_with_handles[ + self.structs_with_handles[ ext_struct ].insert( - 0, self. - global_structs_with_handles[ + 0, self.structs_with_handles[ ext_struct]. pop( - self. - global_structs_with_handles[ + self.structs_with_handles[ ext_struct]. index(member) ) ) else: - self.global_structs_with_handles[ + self.structs_with_handles[ ext_struct] = [member] has_handle_pointers = True self.bubble_up_struct_has_handles( @@ -1220,8 +1216,8 @@ def process_struct(self, element, typename, alias): ) break - if has_handle_pointers and typename not in self.global_structs_with_handle_ptrs: - self.global_structs_with_handle_ptrs.add(typename) + if has_handle_pointers and typename not in self.structs_with_handle_ptrs: + self.structs_with_handle_ptrs.add(typename) else: self.add_struct_alias(typename, alias) diff --git a/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py b/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py index ffa96869f5..420c499962 100644 --- a/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py +++ b/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py @@ -36,14 +36,14 @@ def generate_handle_mappers(self): for struct in self.get_all_filtered_struct_names(): if ( - (struct in self.global_structs_with_handles) + (struct in self.structs_with_handles) or (struct in self.GENERIC_HANDLE_STRUCTS) ) and (struct not in self.STRUCT_MAPPERS_BLACKLIST): handle_members = list() generic_handle_members = dict() - if struct in self.global_structs_with_handles: - handle_members = self.global_structs_with_handles[struct].copy() + if struct in self.structs_with_handles: + handle_members = self.structs_with_handles[struct].copy() if struct in self.GENERIC_HANDLE_STRUCTS: generic_handle_members = self.GENERIC_HANDLE_STRUCTS[struct @@ -119,7 +119,7 @@ def generate_handle_mappers(self): extended_list.append(ext_struct) for base_type in sorted(extended_list): - if base_type in self.global_structs_with_handles: + if base_type in self.structs_with_handles: write( ' case {}:'.format(self.struct_type_names[base_type]), file=self.outFile @@ -144,7 +144,7 @@ def generate_handle_mappers(self): for value_info in self.all_cmd_params[cmd][2]: if self.is_output_parameter(value_info) and ( value_info.base_type in self.get_all_filtered_struct_names() - ) and (value_info.base_type in self.global_structs_with_handles) and ( + ) and (value_info.base_type in self.structs_with_handles) and ( value_info.base_type not in output_structs_with_handles ): @@ -158,18 +158,18 @@ def generate_handle_mappers(self): self.newline() write( self.make_struct_handle_additions( - struct, self.global_structs_with_handles[struct] + struct, self.structs_with_handles[struct] ), file=self.outFile ) # Generate handle memory allocation functions for output structs with handles for struct in output_structs_with_handles: - if struct in self.global_structs_with_handle_ptrs: + if struct in self.structs_with_handle_ptrs: self.newline() write( self.make_struct_handle_allocations( - struct, self.global_structs_with_handles[struct] + struct, self.structs_with_handles[struct] ), file=self.outFile ) diff --git a/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_header_generator.py b/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_header_generator.py index efbaabe8f4..c60b4b1529 100644 --- a/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_header_generator.py +++ b/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_header_generator.py @@ -38,7 +38,7 @@ def endFile(self): for value_info in self.all_cmd_params[cmd][2]: if self.is_output_parameter(value_info) and ( value_info.base_type in self.get_all_filtered_struct_names() - ) and (value_info.base_type in self.global_structs_with_handles) and ( + ) and (value_info.base_type in self.structs_with_handles) and ( value_info.base_type not in output_structs_with_handles ): @@ -50,7 +50,7 @@ def endFile(self): for struct in self.get_all_filtered_struct_names(): if ( - (struct in self.global_structs_with_handles) + (struct in self.structs_with_handles) or (struct in self.GENERIC_HANDLE_STRUCTS) ) and (struct not in self.STRUCT_MAPPERS_BLACKLIST): body = '\n' @@ -75,7 +75,7 @@ def endFile(self): self.newline() for struct in output_structs_with_handles: - if struct in self.global_structs_with_handle_ptrs: + if struct in self.structs_with_handle_ptrs: write( 'void SetStructHandleLengths(Decoded_{type}* wrapper);' .format(type=struct), diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_api_call_encoders_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_api_call_encoders_body_generator.py index 86b389272f..15ab531810 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_api_call_encoders_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_api_call_encoders_body_generator.py @@ -430,7 +430,7 @@ def get_struct_handle_member_info(self, members): elif self.is_struct(member.base_type): # This can't handle the case where 'member' is an array of structs member_handle_type, member_handle_name, member_array_length = self.get_struct_handle_member_info( - self.global_structs_with_handles[member.base_type] + self.structs_with_handles[member.base_type] ) member_handle_name = '{}.{}'.format( member.name, member_handle_name @@ -497,7 +497,7 @@ def make_end_api_call(self, name, values, return_type): # "handle" is actually a struct with embedded handles unwrap_handle_def = 'nullptr' member_handle_type, member_handle_name, member_array_length = self.get_struct_handle_member_info( - self.global_structs_with_handles[handle.base_type] + self.structs_with_handles[handle.base_type] ) if not member_array_length: @@ -562,7 +562,7 @@ def make_end_api_call(self, name, values, return_type): # "handle" is actually a struct with embedded handles unwrap_handle_def = 'nullptr' member_handle_type, member_handle_name, member_array_length = self.get_struct_handle_member_info( - self.global_structs_with_handles[handle.base_type] + self.structs_with_handles[handle.base_type] ) if not member_array_length: @@ -654,7 +654,7 @@ def make_handle_wrapping(self, values, indent): if self.is_output_parameter(value) and ( self.is_handle(value.base_type) or ( self.is_struct(value.base_type) and - (value.base_type in self.global_structs_with_handles) + (value.base_type in self.structs_with_handles) ) ): # The VkInstance handle does not have parent, so the 'unused' @@ -677,7 +677,7 @@ def make_handle_wrapping(self, values, indent): ) and value.is_array and ('->' in value.array_length): # An array of handles with length specified by an AllocateInfo structure (there is a -> in the length name) is a pool allocation. # Extract the pool handle from the AllocateInfo structure, which is currently the first and only handle member. - members = self.global_structs_with_handles[values[1].base_type] + members = self.structs_with_handles[values[1].base_type] for member in members: if self.is_handle(member.base_type): co_parent_type = wrapper_prefix + '::' + member.base_type[2:] + 'Wrapper' @@ -701,7 +701,7 @@ def make_handle_wrapping(self, values, indent): ) elif self.is_struct( value.base_type - ) and (value.base_type in self.global_structs_with_handles): + ) and (value.base_type in self.structs_with_handles): expr += indent + '{}::CreateWrappedStructArrayHandles<{}, {}, {}>({}, {}, {}, {}, VulkanCaptureManager::GetUniqueId);\n'.format( wrapper_prefix, parent_type, co_parent_type, value.base_type, parent_value, co_parent_value, value.name, @@ -715,7 +715,7 @@ def make_handle_wrapping(self, values, indent): ) elif self.is_struct( value.base_type - ) and (value.base_type in self.global_structs_with_handles): + ) and (value.base_type in self.structs_with_handles): expr += indent + '{}::CreateWrappedStructHandles<{}, {}>({}, {}, {}, VulkanCaptureManager::GetUniqueId);\n'.format( wrapper_prefix, parent_type, co_parent_type, parent_value, co_parent_value, value.name @@ -731,7 +731,7 @@ def make_handle_unwrapping(self, name, values, indent): arg_name = value.name if value.is_pointer or value.is_array: if self.is_input_pointer(value): - if (value.base_type in self.global_structs_with_handles) or ( + if (value.base_type in self.structs_with_handles) or ( value.base_type in self.GENERIC_HANDLE_STRUCTS ): need_unwrap_memory = True @@ -793,7 +793,7 @@ def get_param_list_handles(self, values): handles.append(value) elif self.is_struct( value.base_type - ) and (value.base_type in self.global_structs_with_handles): + ) and (value.base_type in self.structs_with_handles): handles.append(value) return handles @@ -817,7 +817,7 @@ def retrieves_handles(self, values): for value in values: if self.is_output_parameter(value) and ( self.is_handle(value.base_type) or - (value.base_type in self.global_structs_with_handles) + (value.base_type in self.structs_with_handles) ): return True return False diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_body_generator.py index ed62ee788b..cf8ca6bd32 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_body_generator.py @@ -145,7 +145,7 @@ def get_param_list_handles(self, values): handles.append(value) elif self.is_struct( value.base_type - ) and (value.base_type in self.global_structs_with_handles): + ) and (value.base_type in self.structs_with_handles): handles.append(value) return handles @@ -196,7 +196,7 @@ def insert_command_handle(self, index, value, value_prefix='', indent=''): elif self.is_struct( value.base_type - ) and (value.base_type in self.global_structs_with_handles): + ) and (value.base_type in self.structs_with_handles): if value.is_array: access_operator = '[{}].'.format(index_name) elif value.is_pointer: @@ -205,13 +205,13 @@ def insert_command_handle(self, index, value, value_prefix='', indent=''): access_operator = '.' for index, entry in enumerate( - self.global_structs_with_handles[value.base_type] + self.structs_with_handles[value.base_type] ): if entry.name == 'pNext': ext_structs_with_handles = [ ext_struct for ext_struct in self.registry.validextensionstructs[value.base_type] - if ext_struct in self.global_structs_with_handles + if ext_struct in self.structs_with_handles ] if ext_structs_with_handles: body += indent + 'auto pnext_header = reinterpret_cast({}{}->pNext);\n'.format( diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_header_generator.py index dfd1afb60e..f92df39ba3 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_header_generator.py @@ -122,7 +122,7 @@ def get_param_list_handles(self, values): handles.append(value) elif self.is_struct( value.base_type - ) and (value.base_type in self.global_structs_with_handles): + ) and (value.base_type in self.structs_with_handles): handles.append(value) return handles diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_body_generator.py index 368b7df023..12f7fbf181 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_body_generator.py @@ -174,7 +174,7 @@ def get_param_list_handles(self, cmd, values): handles.append(value) elif self.is_struct( value.base_type - ) and (value.base_type in self.global_structs_with_handles): + ) and (value.base_type in self.structs_with_handles): handles.append(value) return handles @@ -270,20 +270,20 @@ def track_command_handle( elif self.is_struct( value.base_type - ) and (value.base_type in self.global_structs_with_handles): + ) and (value.base_type in self.structs_with_handles): if value.is_array: access_operator = '[{}].'.format(index_name) else: access_operator = '->' for index, entry in enumerate( - self.global_structs_with_handles[value.base_type] + self.structs_with_handles[value.base_type] ): if entry.name == 'pNext': ext_structs_with_handles = [ ext_struct for ext_struct in self.registry.validextensionstructs[value.base_type] - if ext_struct in self.global_structs_with_handles + if ext_struct in self.structs_with_handles ] if ext_structs_with_handles: for ext_struct in ext_structs_with_handles: diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_header_generator.py index 61270c7dda..811ae69869 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_referenced_resource_consumer_header_generator.py @@ -163,6 +163,6 @@ def get_param_list_handles(self, values): handles.append(value) elif self.is_struct( value.base_type - ) and (value.base_type in self.global_structs_with_handles): + ) and (value.base_type in self.structs_with_handles): handles.append(value) return handles diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_replay_consumer_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_replay_consumer_body_generator.py index 627d06188e..6156509382 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_replay_consumer_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_replay_consumer_body_generator.py @@ -564,7 +564,7 @@ def make_body_expressions(self, return_type, name, values, is_override): if need_temp_value: expr += '{}->GetPointer();'.format(value.name) - if (value.base_type in self.global_structs_with_handles) or ( + if (value.base_type in self.structs_with_handles) or ( value.base_type in self.GENERIC_HANDLE_STRUCTS ): preexpr.append(expr) @@ -727,8 +727,8 @@ def make_body_expressions(self, return_type, name, values, is_override): alloc_expr, paramname=value.name ) # If this is a struct with handles, we need to add replay mappings for the embedded handles. - if value.base_type in self.global_structs_with_handles: - if value.base_type in self.global_structs_with_handle_ptrs: + if value.base_type in self.structs_with_handles: + if value.base_type in self.structs_with_handle_ptrs: preexpr.append( 'SetStructArrayHandleLengths({paramname}->GetMetaStructPointer(), {paramname}->GetLength());' .format( @@ -751,8 +751,8 @@ def make_body_expressions(self, return_type, name, values, is_override): alloc_expr, paramname=value.name ) # If this is a struct with handles, we need to add replay mappings for the embedded handles. - if value.base_type in self.global_structs_with_handles: - if value.base_type in self.global_structs_with_handle_ptrs: + if value.base_type in self.structs_with_handles: + if value.base_type in self.structs_with_handle_ptrs: preexpr.append( 'SetStructArrayHandleLengths({paramname}->GetMetaStructPointer(), {paramname}->GetLength());' .format( @@ -880,9 +880,9 @@ def make_body_expressions(self, return_type, name, values, is_override): ) # If this is a struct with handles, we need to add replay mappings for the embedded handles. - if value.base_type in self.global_structs_with_handles: + if value.base_type in self.structs_with_handles: if need_temp_value: - if value.base_type in self.global_structs_with_handle_ptrs: + if value.base_type in self.structs_with_handle_ptrs: preexpr.append( 'SetStructArrayHandleLengths({paramname}->GetMetaStructPointer(), {paramname}->GetLength());' .format( @@ -902,7 +902,7 @@ def make_body_expressions(self, return_type, name, values, is_override): ) ) else: - if value.base_type in self.global_structs_with_handle_ptrs: + if value.base_type in self.structs_with_handle_ptrs: preexpr.append( 'SetStructHandleLengths({paramname}->GetMetaStructPointer(), {paramname}->GetLength());' .format( diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_body_generator.py index 14bcae0b62..897fb48449 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_body_generator.py @@ -88,14 +88,14 @@ def endFile(self): """Method override.""" for struct in self.get_all_filtered_struct_names(): if ( - (struct in self.global_structs_with_handles) + (struct in self.structs_with_handles) or (struct in self.GENERIC_HANDLE_STRUCTS) ) and (struct not in self.STRUCT_MAPPERS_BLACKLIST): handle_members = dict() generic_handle_members = dict() - if struct in self.global_structs_with_handles: - handle_members = self.global_structs_with_handles[struct] + if struct in self.structs_with_handles: + handle_members = self.structs_with_handles[struct] if struct in self.GENERIC_HANDLE_STRUCTS: generic_handle_members = self.GENERIC_HANDLE_STRUCTS[struct ] @@ -214,7 +214,7 @@ def endFile(self): write(' return copy;', file=self.outFile) write(' }', file=self.outFile) for base_type in sorted(extended_list): - if (base_type in self.global_structs_with_handles and + if (base_type in self.structs_with_handles and base_type in self.struct_type_names): stype = self.struct_type_names[base_type] write( diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_header_generator.py index f5ff4fc2d9..6797cd6678 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_header_generator.py @@ -107,14 +107,14 @@ def endFile(self): for value in values: if self.is_output_parameter(value) and self.is_struct( value.base_type - ) and (value.base_type in self.global_structs_with_handles + ) and (value.base_type in self.structs_with_handles ) and (value.base_type not in self.output_structs): self.output_structs.append(value.base_type) # Generate unwrap and rewrap code for input structures. for struct in self.get_all_filtered_struct_names(): if ( - (struct in self.global_structs_with_handles) + (struct in self.structs_with_handles) or (struct in self.GENERIC_HANDLE_STRUCTS) ) and (struct not in self.STRUCT_MAPPERS_BLACKLIST): body = '\n' @@ -262,7 +262,7 @@ def generate_create_wrapper_funcs(self): wrapper_prefix = self.get_wrapper_prefix_from_type() - for member in self.global_structs_with_handles[struct]: + for member in self.structs_with_handles[struct]: if self.is_struct(member.base_type): if member.is_array: body += ' vulkan_wrappers::CreateWrappedStructArrayHandles(parent, co_parent, value->{}, value->{}, get_id);\n'.format( From 6425bb7f41e632d3c5841f8d052b25484bf590b5 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Thu, 7 Nov 2024 18:51:53 -0500 Subject: [PATCH 07/32] codegen: Move wrapper prefix usage to use ApiData --- .../khronos_base_generator.py | 36 +++++++++++++++---- .../vulkan_generators/base_generator.py | 8 ++--- ...vulkan_api_call_encoders_body_generator.py | 16 ++++----- ...lkan_command_buffer_util_body_generator.py | 4 +-- ...an_command_buffer_util_header_generator.py | 2 +- .../vulkan_state_table_header_generator.py | 2 +- ...struct_handle_wrappers_header_generator.py | 21 ++++++----- 7 files changed, 54 insertions(+), 35 deletions(-) diff --git a/framework/generated/khronos_generators/khronos_base_generator.py b/framework/generated/khronos_generators/khronos_base_generator.py index 0ebbb5d4eb..97771ec196 100644 --- a/framework/generated/khronos_generators/khronos_base_generator.py +++ b/framework/generated/khronos_generators/khronos_base_generator.py @@ -99,6 +99,7 @@ class ApiData(): Members: api_name - The name of the API api_class_prefix - The prefix to use for classes in this API + wrapper_prefix - The prefix used to wrap namespaces command_prefix - The prefix used to identify commands belonging to this Khronos API struct_prefix - The prefix used to identify structures belonging to this Khronos API struct_type_enum - The enum type used to define structure types for this Khronos API @@ -110,11 +111,13 @@ class ApiData(): extended_struct_variable - The extended struct varible name used in this Khronos API extended_struct_func_prefix - The function prefix to use for extended struct functions for this Khronos API. boolean_type - The type used by the API for booleans + return_const_ptr_on_extended- Return a constant on extended pointer types """ def __init__( self, api_name, api_class_prefix, + wrapper_prefix, command_prefix, struct_prefix, struct_type_enum, @@ -126,9 +129,11 @@ def __init__( extended_struct_variable, extended_struct_func_prefix, boolean_type, + return_const_ptr_on_extended, ): self.api_name = api_name self.api_class_prefix = api_class_prefix + self.wrapper_prefix = wrapper_prefix self.command_prefix = command_prefix self.struct_type_enum = struct_type_enum self.struct_prefix = struct_prefix @@ -140,6 +145,7 @@ def __init__( self.extended_struct_variable = extended_struct_variable self.extended_struct_func_prefix = extended_struct_func_prefix self.boolean_type = boolean_type + self.return_const_ptr_on_extended = return_const_ptr_on_extended class ValueInfo(): """ValueInfo - Class to store parameter/struct member information. @@ -400,6 +406,7 @@ def __init__( ApiData( api_name='Vulkan', api_class_prefix='Vulkan', + wrapper_prefix='vulkan_wrappers', command_prefix='vk', struct_type_enum='VkStructureType', struct_prefix='Vk', @@ -410,13 +417,15 @@ def __init__( base_out_struct='VkBaseOutStructure', extended_struct_variable='pNext', extended_struct_func_prefix='PNext', - boolean_type='VkBool32' + boolean_type='VkBool32', + return_const_ptr_on_extended=True ) ) self.valid_khronos_supported_api_data.append( ApiData( api_name='OpenXR', api_class_prefix='OpenXr', + wrapper_prefix='openxr_wrappers', command_prefix='xr', struct_type_enum='XrStructureType', struct_prefix='Xr', @@ -427,7 +436,8 @@ def __init__( base_out_struct='XrBaseOutStructure', extended_struct_variable='next', extended_struct_func_prefix='Next', - boolean_type='XrBool32' + boolean_type='XrBool32', + return_const_ptr_on_extended=False ) ) @@ -515,10 +525,6 @@ def get_prefix_from_type(self, type): """Intended to be overridden.""" return self.get_api_prefix() - def get_wrapper_prefix_from_type(self): - """Intended to be overridden.""" - return 'khronos_wrappers' - # # Indicates that the current feature has C++ code to generate. # The subclass should override this method. @@ -1487,6 +1493,24 @@ def get_extended_struct_func_prefix(self): return api_data.extended_struct_func_prefix return '' + def get_wrapper_prefix(self): + api_data = self.get_api_data() + if api_data is not None: + return api_data.wrapper_prefix + return '' + + def get_wrapper_prefix_from_type(self, type): + for api_data in self.valid_khronos_supported_api_data: + if type.startswith(api_data.struct_prefix): + return api_data.wrapper_prefix + return self.get_wrapper_prefix() + + def get_wrapper_prefix_from_command(self, type): + for api_data in self.valid_khronos_supported_api_data: + if type.startswith(api_data.command_prefix): + return api_data.wrapper_prefix + return self.get_wrapper_prefix() + def is_extended_struct_definition(self, value): if (value.name == self.get_extended_struct_var_name() and value.base_type == 'void' and diff --git a/framework/generated/khronos_generators/vulkan_generators/base_generator.py b/framework/generated/khronos_generators/vulkan_generators/base_generator.py index 69230ec445..cf45fc9e06 100644 --- a/framework/generated/khronos_generators/vulkan_generators/base_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/base_generator.py @@ -713,10 +713,6 @@ def get_prefix_from_type(self, type): """Method override. Start processing in superclass.""" return self.get_api_prefix() - def get_wrapper_prefix_from_type(self): - """Method override. Start processing in superclass.""" - return 'vulkan_wrappers' - def make_encoder_method_call( self, name, value, values, prefix, omit_output_param=None ): @@ -734,7 +730,7 @@ def make_encoder_method_call( handle_type_name += self.get_generic_cmd_handle_type_value( name, value.name ) - wrapper = self.get_wrapper_prefix_from_type() + wrapper = self.get_wrapper_prefix_from_type(name) arg_name = '{}::GetWrappedId({}, {})'.format( wrapper, arg_name, handle_type_name ) @@ -794,7 +790,7 @@ def make_encoder_method_call( method_call += 'Value' if is_handle: - wrapper_prefix = self.get_wrapper_prefix_from_type() + wrapper_prefix = self.get_wrapper_prefix_from_type(value.base_type) method_call += '<{}>'.format(wrapper_prefix + '::' + value.base_type[2:] + 'Wrapper') if self.is_output_parameter(value) and omit_output_param: diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_api_call_encoders_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_api_call_encoders_body_generator.py index 15ab531810..b5fe15f25e 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_api_call_encoders_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_api_call_encoders_body_generator.py @@ -194,15 +194,15 @@ def make_layer_dispatch_call(self, name, values, arg_list): """Generate the layer dispatch call invocation.""" call_setup_expr = [] object_name = values[0].name + wrapper_prefix = self.get_wrapper_prefix_from_command(name) if self.use_instance_table(name, values[0].base_type): - dispatchfunc = 'vulkan_wrappers::GetInstanceTable' + dispatchfunc = '{}::GetInstanceTable'.format(wrapper_prefix) if values[0].base_type == 'VkDevice': object_name = 'physical_device' - wrapper_prefix = self.get_wrapper_prefix_from_type() - call_setup_expr.append("auto device_wrapper = vulkan_wrappers::GetWrapper<{}::DeviceWrapper>({});".format(wrapper_prefix, values[0].name)) + call_setup_expr.append("auto device_wrapper = {0}::GetWrapper<{0}::DeviceWrapper>({1});".format(wrapper_prefix, values[0].name)) call_setup_expr.append("auto physical_device = device_wrapper->physical_device->handle;") else: - dispatchfunc = 'vulkan_wrappers::GetDeviceTable' + dispatchfunc = '{}::GetDeviceTable'.format(wrapper_prefix) return [call_setup_expr, '{}({})->{}({})'.format(dispatchfunc, object_name, name[2:], arg_list)] @@ -443,7 +443,7 @@ def make_end_api_call(self, name, values, return_type): if name == 'vkCreateInstance': decl = 'VulkanCaptureManager::Get()->' - wrapper_prefix = self.get_wrapper_prefix_from_type() + wrapper_prefix = self.get_wrapper_prefix_from_command(name) if name.startswith('vkCreate') or name.startswith( 'vkAllocate' @@ -648,9 +648,9 @@ def make_end_api_call(self, name, values, return_type): def make_handle_wrapping(self, values, indent): expr = '' - wrapper_prefix = self.get_wrapper_prefix_from_type() for value in values: + wrapper_prefix = self.get_wrapper_prefix_from_type(value.base_type) if self.is_output_parameter(value) and ( self.is_handle(value.base_type) or ( self.is_struct(value.base_type) and @@ -727,7 +727,7 @@ def make_handle_unwrapping(self, name, values, indent): expr = '' need_unwrap_memory = False for value in values: - wrapper_prefix = self.get_wrapper_prefix_from_type() + wrapper_prefix = self.get_wrapper_prefix_from_type(value.base_type) arg_name = value.name if value.is_pointer or value.is_array: if self.is_input_pointer(value): @@ -773,7 +773,7 @@ def make_handle_cleanup(self, name, values, indent): if ("Pool" in handle.base_type) and name.startswith('vkFree'): handle = values[3] - wrapper_prefix = self.get_wrapper_prefix_from_type() + wrapper_prefix = self.get_wrapper_prefix_from_command(name) if handle.is_array: expr += indent + '{}::DestroyWrappedHandles<{}::{}Wrapper>({}, {});\n'.format( diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_body_generator.py index cf8ca6bd32..d1710a27af 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_body_generator.py @@ -98,8 +98,8 @@ def endFile(self): for cmd in self.get_all_filtered_cmd_names(): command_info[cmd] = self.all_cmd_params[cmd] - wrapper_prefix = self.get_wrapper_prefix_from_type() for cmd, info in command_info.items(): + wrapper_prefix = self.get_wrapper_prefix_from_command(cmd) if not cmd[2:] in self.customImplementationRequired: params = info[2] if params and params[0].base_type == 'VkCommandBuffer': @@ -184,7 +184,7 @@ def insert_command_handle(self, index, value, value_prefix='', indent=''): if self.is_handle(value.base_type): type_enum_value = '{}Handle'.format(value.base_type[2:]) - wrapper_prefix = self.get_wrapper_prefix_from_type() + wrapper_prefix = self.get_wrapper_prefix_from_type(value.base_type) value_name = value_prefix + value.name if value.is_array: value_name = '{}[{}]'.format(value_name, index_name) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_header_generator.py index f92df39ba3..f0aed2199d 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_command_buffer_util_header_generator.py @@ -83,8 +83,8 @@ def beginFile(self, gen_opts): def endFile(self): """Method override.""" - wrapper_prefix = self.get_wrapper_prefix_from_type() for cmd in self.get_all_filtered_cmd_names(): + wrapper_prefix = self.get_wrapper_prefix_from_command(cmd) info = self.all_cmd_params[cmd] values = info[2] diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_state_table_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_state_table_header_generator.py index 7903262bd8..2e01c5f03f 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_state_table_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_state_table_header_generator.py @@ -103,7 +103,7 @@ def generate_all(self): if vkhandle_name in self.DUPLICATE_HANDLE_TYPES: continue handle_name = vkhandle_name[2:] - wrapper_prefix = self.get_wrapper_prefix_from_type() + wrapper_prefix = self.get_wrapper_prefix_from_type(vkhandle_name) handle_prefix = self.get_api_prefix() handle_wrapper_func = handle_name + 'Wrapper' handle_wrapper_type = wrapper_prefix + '::' + handle_name + 'Wrapper' diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_header_generator.py index 6797cd6678..288f93975e 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_header_generator.py @@ -260,33 +260,32 @@ def generate_create_wrapper_funcs(self): body += ' if (value != nullptr)\n' body += ' {\n' - wrapper_prefix = self.get_wrapper_prefix_from_type() - for member in self.structs_with_handles[struct]: + wrapper_prefix = self.get_wrapper_prefix_from_type(member.base_type) if self.is_struct(member.base_type): if member.is_array: - body += ' vulkan_wrappers::CreateWrappedStructArrayHandles(parent, co_parent, value->{}, value->{}, get_id);\n'.format( - member.base_type, member.name, member.array_length + body += ' {}::CreateWrappedStructArrayHandles(parent, co_parent, value->{}, value->{}, get_id);\n'.format( + wrapper_prefix, member.base_type, member.name, member.array_length ) elif member.is_pointer: - body += ' vulkan_wrappers::CreateWrappedStructHandles(parent, co_parent, value->{}, get_id);\n'.format( - member.name + body += ' {}::CreateWrappedStructHandles(parent, co_parent, value->{}, get_id);\n'.format( + wrapper_prefix, member.name ) else: - body += ' vulkan_wrappers::CreateWrappedStructHandles(parent, co_parent, &value->{}, get_id);\n'.format( - member.name + body += ' {}::CreateWrappedStructHandles(parent, co_parent, &value->{}, get_id);\n'.format( + wrapper_prefix, member.name ) else: if member.is_array: - body += ' vulkan_wrappers::CreateWrappedHandles(parent, co_parent, value->{}, value->{}, get_id);\n'.format( + body += ' {0}::CreateWrappedHandles(parent, co_parent, value->{2}, value->{3}, get_id);\n'.format( wrapper_prefix, member.base_type[2:], member.name, member.array_length ) elif member.is_pointer: - body += ' vulkan_wrappers::CreateWrappedHandle(parent, co_parent, value->{}, get_id);\n'.format( + body += ' {0}::CreateWrappedHandle(parent, co_parent, value->{2}, get_id);\n'.format( wrapper_prefix, member.base_type[2:], member.name ) else: - body += ' vulkan_wrappers::CreateWrappedHandle(parent, co_parent, &value->{}, get_id);\n'.format( + body += ' {0}::CreateWrappedHandle(parent, co_parent, &value->{2}, get_id);\n'.format( wrapper_prefix, member.base_type[2:], member.name ) From d3ad04feebf52ef62f659d4b8d7c24dadf6c40d3 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Thu, 7 Nov 2024 19:07:59 -0500 Subject: [PATCH 08/32] codegen: Move API Prefix to use APIData --- .../khronos_base_generator.py | 30 ++++++++++++------- ...se_struct_handle_mappers_body_generator.py | 4 +-- .../vulkan_generators/base_generator.py | 10 +------ 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/framework/generated/khronos_generators/khronos_base_generator.py b/framework/generated/khronos_generators/khronos_base_generator.py index 97771ec196..870faa4358 100644 --- a/framework/generated/khronos_generators/khronos_base_generator.py +++ b/framework/generated/khronos_generators/khronos_base_generator.py @@ -517,14 +517,6 @@ def get_feature_protect(self, interface): """Intended to be overridden.""" return None - def get_api_prefix(self): - """Intended to be overridden.""" - return 'Khronos' - - def get_prefix_from_type(self, type): - """Intended to be overridden.""" - return self.get_api_prefix() - # # Indicates that the current feature has C++ code to generate. # The subclass should override this method. @@ -1505,12 +1497,30 @@ def get_wrapper_prefix_from_type(self, type): return api_data.wrapper_prefix return self.get_wrapper_prefix() - def get_wrapper_prefix_from_command(self, type): + def get_wrapper_prefix_from_command(self, cmd): for api_data in self.valid_khronos_supported_api_data: - if type.startswith(api_data.command_prefix): + if cmd.startswith(api_data.command_prefix): return api_data.wrapper_prefix return self.get_wrapper_prefix() + def get_api_prefix(self): + api_data = self.get_api_data() + if api_data is not None: + return api_data.api_class_prefix + return 'Khronos' + + def get_api_prefix_from_type(self, type): + for api_data in self.valid_khronos_supported_api_data: + if type.startswith(api_data.struct_prefix): + return api_data.api_class_prefix + return self.get_api_prefix() + + def get_api_prefix_from_command(self, cmd): + for api_data in self.valid_khronos_supported_api_data: + if cmd.startswith(api_data.command_prefix): + return api_data.api_class_prefix + return self.get_api_prefix() + def is_extended_struct_definition(self, value): if (value.name == self.get_extended_struct_var_name() and value.base_type == 'void' and diff --git a/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py b/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py index 420c499962..4c4efd853f 100644 --- a/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py +++ b/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py @@ -178,7 +178,7 @@ def make_struct_handle_mappings( self, name, handle_members, generic_handle_members ): """Generating expressions for mapping struct handles read from the capture file to handles created at replay.""" - prefix_from_type = self.get_prefix_from_type(name) + prefix_from_type = self.get_api_prefix_from_type(name) body = '' for member in handle_members: @@ -228,7 +228,7 @@ def make_struct_handle_mappings( ) else: type = member.base_type - prefix_from_type = self.get_prefix_from_type(member.base_type) + prefix_from_type = self.get_api_prefix_from_type(member.base_type) func_id = member.base_type + 'Info' type = prefix_from_type + member.base_type[2:] + 'Info' object_info_table_get = ', &CommonObjectInfoTable::Get{}'.format( diff --git a/framework/generated/khronos_generators/vulkan_generators/base_generator.py b/framework/generated/khronos_generators/vulkan_generators/base_generator.py index cf45fc9e06..3682f24a32 100644 --- a/framework/generated/khronos_generators/vulkan_generators/base_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/base_generator.py @@ -601,7 +601,7 @@ def make_dump_resources_func_decl( type_name = value.base_type if is_override: - prefix_from_type = self.get_prefix_from_type(value.base_type) + prefix_from_type = self.get_api_prefix_from_type(value.base_type) info_type = prefix_from_type + value.base_type[2:] + 'Info' if value.is_pointer or value.is_array: count = value.pointer_count @@ -705,14 +705,6 @@ def make_array2d_length_expression(self, value, values, prefix=''): arg_list = ', '.join([v.name for v in values]) return ['ArraySize2D<{}>({})'.format(type_list, arg_list)] - def get_api_prefix(self): - """Method override. Start processing in superclass.""" - return 'Vulkan' - - def get_prefix_from_type(self, type): - """Method override. Start processing in superclass.""" - return self.get_api_prefix() - def make_encoder_method_call( self, name, value, values, prefix, omit_output_param=None ): From 5a32cf663450711c223ad7f7e2655a214f1371e4 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 09:51:32 -0500 Subject: [PATCH 09/32] codegen: Modify struct handle wrapper header Update the struct handle wrapper header generation to move a majority of the code into the Khronos folder as it is mostly API agnostic. --- .../generated_vulkan_struct_handle_wrappers.h | 60 ++-- ...struct_handle_wrappers_header_generator.py | 267 ++++++++++++++++++ ...struct_handle_wrappers_header_generator.py | 182 +----------- 3 files changed, 311 insertions(+), 198 deletions(-) create mode 100644 framework/generated/khronos_generators/khronos_struct_handle_wrappers_header_generator.py diff --git a/framework/generated/generated_vulkan_struct_handle_wrappers.h b/framework/generated/generated_vulkan_struct_handle_wrappers.h index 76a3625f7f..fd2d8ab480 100644 --- a/framework/generated/generated_vulkan_struct_handle_wrappers.h +++ b/framework/generated/generated_vulkan_struct_handle_wrappers.h @@ -417,6 +417,34 @@ VkBaseInStructure* CopyPNextStruct(const VkBaseInStructure* base, HandleUnwrapMe const void* UnwrapPNextStructHandles(const void* value, HandleUnwrapMemory* unwrap_memory); +template +void CreateWrappedStructArrayHandles(typename ParentWrapper::HandleType parent, typename CoParentWrapper::HandleType co_parent, T* value, size_t len, PFN_GetHandleId get_id); + +template +T* MakeUnwrapStructs(const T* values, size_t len, HandleUnwrapMemory* unwrap_memory) +{ + assert((values != nullptr) && (len > 0) && (unwrap_memory != nullptr)); + + const uint8_t* bytes = reinterpret_cast(values); + size_t num_bytes = len * sizeof(T); + + return reinterpret_cast(unwrap_memory->GetFilledBuffer(bytes, num_bytes)); +} + +template +const T* UnwrapStructPtrHandles(const T* value, HandleUnwrapMemory* unwrap_memory) +{ + T* unwrapped_struct = nullptr; + + if (value != nullptr) + { + unwrapped_struct = MakeUnwrapStructs(value, 1, unwrap_memory); + UnwrapStructHandles(unwrapped_struct, unwrap_memory); + } + + return unwrapped_struct; +} + template void CreateWrappedStructHandles(typename ParentWrapper::HandleType parent, typename CoParentWrapper::HandleType co_parent, VkPhysicalDeviceGroupProperties* value, PFN_GetHandleId get_id) { @@ -502,32 +530,26 @@ void CreateWrappedStructArrayHandles(typename ParentWrapper::HandleType parent, } template -T* MakeUnwrapStructs(const T* values, size_t len, HandleUnwrapMemory* unwrap_memory) +const T* UnwrapStructArrayHandles(const T* values, size_t len, HandleUnwrapMemory* unwrap_memory) { - assert((values != nullptr) && (len > 0) && (unwrap_memory != nullptr)); - - const uint8_t* bytes = reinterpret_cast(values); - size_t num_bytes = len * sizeof(T); - - return reinterpret_cast(unwrap_memory->GetFilledBuffer(bytes, num_bytes)); -} + if ((values != nullptr) && (len > 0)) + { + auto unwrapped_structs = MakeUnwrapStructs(values, len, unwrap_memory); -template -const T* UnwrapStructPtrHandles(const T* value, HandleUnwrapMemory* unwrap_memory) -{ - T* unwrapped_struct = nullptr; + for (size_t i = 0; i < len; ++i) + { + UnwrapStructHandles(&unwrapped_structs[i], unwrap_memory); + } - if (value != nullptr) - { - unwrapped_struct = MakeUnwrapStructs(value, 1, unwrap_memory); - UnwrapStructHandles(unwrapped_struct, unwrap_memory); + return unwrapped_structs; } - return unwrapped_struct; + // Leave the original memory in place when the pointer is not null, but size is zero. + return values; } template -const T* UnwrapStructArrayHandles(const T* values, size_t len, HandleUnwrapMemory* unwrap_memory) +T* UnwrapStructPtrArrayHandles(T* values, size_t len, HandleUnwrapMemory* unwrap_memory) { if ((values != nullptr) && (len > 0)) { @@ -535,7 +557,7 @@ const T* UnwrapStructArrayHandles(const T* values, size_t len, HandleUnwrapMemor for (size_t i = 0; i < len; ++i) { - UnwrapStructHandles(&unwrapped_structs[i], unwrap_memory); + UnwrapStructHandles(unwrapped_structs[i], unwrap_memory); } return unwrapped_structs; diff --git a/framework/generated/khronos_generators/khronos_struct_handle_wrappers_header_generator.py b/framework/generated/khronos_generators/khronos_struct_handle_wrappers_header_generator.py new file mode 100644 index 0000000000..7e371b67c4 --- /dev/null +++ b/framework/generated/khronos_generators/khronos_struct_handle_wrappers_header_generator.py @@ -0,0 +1,267 @@ +#!/usr/bin/python3 -i +# +# Copyright (c) 2019 Valve Corporation +# Copyright (c) 2019-2024 LunarG, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import sys +from khronos_base_generator import write + + +class KhronosStructHandleWrappersHeaderGenerator(): + """KhronosStructHandleWrappersHeaderGeneratorVulk + Generates C++ function prototypes for wrapping struct member handles + when recording Khronos API call parameter data. + """ + + def write_struct_handle_wrapper_content(self): + """Method override.""" + # Check for output structures, which retrieve handles that need to be wrapped. + for cmd in self.all_cmd_params: + info = self.all_cmd_params[cmd] + values = info[2] + + for value in values: + if self.is_output_parameter(value) and self.is_struct( + value.base_type + ) and (value.base_type in self.structs_with_handles + ) and (value.base_type not in self.output_structs): + self.output_structs.append(value.base_type) + + # Generate unwrap and rewrap code for input structures. + for struct in self.get_all_filtered_struct_names(): + if ( + (struct in self.structs_with_handles) + or (struct in self.GENERIC_HANDLE_STRUCTS) + ) and (struct not in self.STRUCT_MAPPERS_BLACKLIST): + body = '\n' + body += 'void UnwrapStructHandles({}* value, HandleUnwrapMemory* unwrap_memory);'.format( + struct + ) + write(body, file=self.outFile) + + api_data = self.get_api_data() + const_prefix = '' + if api_data.return_const_ptr_on_extended: + const_prefix = 'const ' + + self.newline() + write( + '{0}* Copy{1}Struct(const {0}* base, HandleUnwrapMemory* unwrap_memory);'.format(api_data.base_in_struct, api_data.extended_struct_func_prefix), + file=self.outFile + ) + self.newline() + write( + '{}void* Unwrap{}StructHandles(const void* value, HandleUnwrapMemory* unwrap_memory);'.format(const_prefix, api_data.extended_struct_func_prefix), + file=self.outFile + ) + self.newline() + write( + 'template ', + file=self.outFile + ) + write( + 'void CreateWrappedStructArrayHandles(typename ParentWrapper::HandleType parent, typename CoParentWrapper::HandleType co_parent, T* value, size_t len, PFN_GetHandleId get_id);', + file=self.outFile + ) + self.newline() + write('template ', file=self.outFile) + write( + 'T* MakeUnwrapStructs(const T* values, size_t len, HandleUnwrapMemory* unwrap_memory)', + file=self.outFile + ) + write('{', file=self.outFile) + write( + ' assert((values != nullptr) && (len > 0) && (unwrap_memory != nullptr));', + file=self.outFile + ) + self.newline() + write( + ' const uint8_t* bytes = reinterpret_cast(values);', + file=self.outFile + ) + write( + ' size_t num_bytes = len * sizeof(T);', + file=self.outFile + ) + self.newline() + write( + ' return reinterpret_cast(unwrap_memory->GetFilledBuffer(bytes, num_bytes));', + file=self.outFile + ) + write('}', file=self.outFile) + self.newline() + write('template ', file=self.outFile) + write( + '{}T* UnwrapStructPtrHandles(const T* value, HandleUnwrapMemory* unwrap_memory)'.format(const_prefix), + file=self.outFile + ) + write('{', file=self.outFile) + write(' T* unwrapped_struct = nullptr;', file=self.outFile) + self.newline() + write(' if (value != nullptr)', file=self.outFile) + write(' {', file=self.outFile) + write( + ' unwrapped_struct = MakeUnwrapStructs(value, 1, unwrap_memory);', + file=self.outFile + ) + write( + ' UnwrapStructHandles(unwrapped_struct, unwrap_memory);', + file=self.outFile + ) + write(' }', file=self.outFile) + self.newline() + write(' return unwrapped_struct;', file=self.outFile) + write('}', file=self.outFile) + self.newline() + + self.generate_create_wrapper_funcs() + + write( + 'template ', + file=self.outFile + ) + write( + 'void CreateWrappedStructArrayHandles(typename ParentWrapper::HandleType parent, typename CoParentWrapper::HandleType co_parent, T* value, size_t len, PFN_GetHandleId get_id)', + file=self.outFile + ) + write('{', file=self.outFile) + write(' if (value != nullptr)', file=self.outFile) + write(' {', file=self.outFile) + write(' for (size_t i = 0; i < len; ++i)', file=self.outFile) + write(' {', file=self.outFile) + write( + ' CreateWrappedStructHandles(parent, co_parent, &value[i], get_id);', + file=self.outFile + ) + write(' }', file=self.outFile) + write(' }', file=self.outFile) + write('}', file=self.outFile) + self.newline() + + write('template ', file=self.outFile) + write( + '{} T* UnwrapStructArrayHandles(const T* values, size_t len, HandleUnwrapMemory* unwrap_memory)'.format(const_prefix), + file=self.outFile + ) + write('{', file=self.outFile) + write(' if ((values != nullptr) && (len > 0))', file=self.outFile) + write(' {', file=self.outFile) + write( + ' auto unwrapped_structs = MakeUnwrapStructs(values, len, unwrap_memory);', + file=self.outFile + ) + self.newline() + write(' for (size_t i = 0; i < len; ++i)', file=self.outFile) + write(' {', file=self.outFile) + write( + ' UnwrapStructHandles(&unwrapped_structs[i], unwrap_memory);', + file=self.outFile + ) + write(' }', file=self.outFile) + self.newline() + write(' return unwrapped_structs;', file=self.outFile) + write(' }', file=self.outFile) + self.newline() + write( + ' // Leave the original memory in place when the pointer is not null, but size is zero.', + file=self.outFile + ) + write(' return values;', file=self.outFile) + write('}', file=self.outFile) + self.newline() + write('template ', file=self.outFile) + write( + 'T* UnwrapStructPtrArrayHandles(T* values, size_t len, HandleUnwrapMemory* unwrap_memory)', + file=self.outFile + ) + write('{', file=self.outFile) + write(' if ((values != nullptr) && (len > 0))', file=self.outFile) + write(' {', file=self.outFile) + write( + ' auto unwrapped_structs = MakeUnwrapStructs(values, len, unwrap_memory);', + file=self.outFile + ) + self.newline() + write(' for (size_t i = 0; i < len; ++i)', file=self.outFile) + write(' {', file=self.outFile) + write( + ' UnwrapStructHandles(unwrapped_structs[i], unwrap_memory);', + file=self.outFile + ) + write(' }', file=self.outFile) + self.newline() + write(' return unwrapped_structs;', file=self.outFile) + write(' }', file=self.outFile) + self.newline() + write( + ' // Leave the original memory in place when the pointer is not null, but size is zero.', + file=self.outFile + ) + write(' return values;', file=self.outFile) + write('}', file=self.outFile) + + def generate_create_wrapper_funcs(self): + """Generates functions that wrap struct handle members.""" + for struct in self.output_structs: + body = 'template \n' + body += 'void CreateWrappedStructHandles(typename ParentWrapper::HandleType parent, typename CoParentWrapper::HandleType co_parent, {}* value, PFN_GetHandleId get_id)\n'.format( + struct + ) + body += '{\n' + body += ' if (value != nullptr)\n' + body += ' {\n' + + for member in self.structs_with_handles[struct]: + wrapper_prefix = self.get_wrapper_prefix_from_type(member.base_type) + func_target = 'Handle' + if self.is_atom(member.base_type): + func_target = 'Atom' + + if self.is_struct(member.base_type): + if member.is_array: + body += ' {}::CreateWrappedStructArray{}s(parent, co_parent, value->{}, value->{}, get_id);\n'.format( + wrapper_prefix, func_target, member.base_type, member.name, member.array_length + ) + elif member.is_pointer: + body += ' {}::CreateWrappedStruct{}s(parent, co_parent, value->{}, get_id);\n'.format( + wrapper_prefix, func_target, member.name + ) + else: + body += ' {}::CreateWrappedStruct{}s(parent, co_parent, &value->{}, get_id);\n'.format( + wrapper_prefix, func_target, member.name + ) + else: + if member.is_array: + body += ' {}::CreateWrapped{}s(parent, co_parent, value->{}, value->{}, get_id);\n'.format( + wrapper_prefix, func_target, wrapper_prefix, member.base_type[2:], member.name, member.array_length + ) + elif member.is_pointer: + body += ' {}::CreateWrapped{}(parent, co_parent, value->{}, get_id);\n'.format( + wrapper_prefix, func_target, wrapper_prefix, member.base_type[2:], member.name + ) + else: + body += ' {}::CreateWrapped{}(parent, co_parent, &value->{}, get_id);\n'.format( + wrapper_prefix, func_target, wrapper_prefix, member.base_type[2:], member.name + ) + + body += ' }\n' + body += '}\n' + write(body, file=self.outFile) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_header_generator.py index 288f93975e..8eb454c023 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_header_generator.py @@ -23,6 +23,7 @@ import sys from base_generator import BaseGenerator, BaseGeneratorOptions, write +from khronos_struct_handle_wrappers_header_generator import KhronosStructHandleWrappersHeaderGenerator class VulkanStructHandleWrappersHeaderGeneratorOptions(BaseGeneratorOptions): @@ -52,7 +53,7 @@ def __init__( ) -class VulkanStructHandleWrappersHeaderGenerator(BaseGenerator): +class VulkanStructHandleWrappersHeaderGenerator(BaseGenerator, KhronosStructHandleWrappersHeaderGenerator): """VulkanStructHandleWrappersHeaderGenerator - subclass of BaseGenerator. Generates C++ function prototypes for wrapping struct member handles when recording Vulkan API call parameter data. @@ -99,142 +100,9 @@ def beginFile(self, gen_opts): def endFile(self): """Method override.""" - # Check for output structures, which retrieve handles that need to be wrapped. - for cmd in self.all_cmd_params: - info = self.all_cmd_params[cmd] - values = info[2] - for value in values: - if self.is_output_parameter(value) and self.is_struct( - value.base_type - ) and (value.base_type in self.structs_with_handles - ) and (value.base_type not in self.output_structs): - self.output_structs.append(value.base_type) + KhronosStructHandleWrappersHeaderGenerator.write_struct_handle_wrapper_content(self) - # Generate unwrap and rewrap code for input structures. - for struct in self.get_all_filtered_struct_names(): - if ( - (struct in self.structs_with_handles) - or (struct in self.GENERIC_HANDLE_STRUCTS) - ) and (struct not in self.STRUCT_MAPPERS_BLACKLIST): - body = '\n' - body += 'void UnwrapStructHandles({}* value, HandleUnwrapMemory* unwrap_memory);'.format( - struct - ) - write(body, file=self.outFile) - - self.newline() - write( - 'VkBaseInStructure* CopyPNextStruct(const VkBaseInStructure* base, HandleUnwrapMemory* unwrap_memory);', - file=self.outFile - ) - self.newline() - write( - 'const void* UnwrapPNextStructHandles(const void* value, HandleUnwrapMemory* unwrap_memory);', - file=self.outFile - ) - self.newline() - self.generate_create_wrapper_funcs() - write( - 'template ', - file=self.outFile - ) - write( - 'void CreateWrappedStructArrayHandles(typename ParentWrapper::HandleType parent, typename CoParentWrapper::HandleType co_parent, T* value, size_t len, PFN_GetHandleId get_id)', - file=self.outFile - ) - write('{', file=self.outFile) - write(' if (value != nullptr)', file=self.outFile) - write(' {', file=self.outFile) - write(' for (size_t i = 0; i < len; ++i)', file=self.outFile) - write(' {', file=self.outFile) - write( - ' CreateWrappedStructHandles(parent, co_parent, &value[i], get_id);', - file=self.outFile - ) - write(' }', file=self.outFile) - write(' }', file=self.outFile) - write('}', file=self.outFile) - self.newline() - write('template ', file=self.outFile) - write( - 'T* MakeUnwrapStructs(const T* values, size_t len, HandleUnwrapMemory* unwrap_memory)', - file=self.outFile - ) - write('{', file=self.outFile) - write( - ' assert((values != nullptr) && (len > 0) && (unwrap_memory != nullptr));', - file=self.outFile - ) - self.newline() - write( - ' const uint8_t* bytes = reinterpret_cast(values);', - file=self.outFile - ) - write( - ' size_t num_bytes = len * sizeof(T);', - file=self.outFile - ) - self.newline() - write( - ' return reinterpret_cast(unwrap_memory->GetFilledBuffer(bytes, num_bytes));', - file=self.outFile - ) - write('}', file=self.outFile) - self.newline() - write('template ', file=self.outFile) - write( - 'const T* UnwrapStructPtrHandles(const T* value, HandleUnwrapMemory* unwrap_memory)', - file=self.outFile - ) - write('{', file=self.outFile) - write(' T* unwrapped_struct = nullptr;', file=self.outFile) - self.newline() - write(' if (value != nullptr)', file=self.outFile) - write(' {', file=self.outFile) - write( - ' unwrapped_struct = MakeUnwrapStructs(value, 1, unwrap_memory);', - file=self.outFile - ) - write( - ' UnwrapStructHandles(unwrapped_struct, unwrap_memory);', - file=self.outFile - ) - write(' }', file=self.outFile) - self.newline() - write(' return unwrapped_struct;', file=self.outFile) - write('}', file=self.outFile) - self.newline() - write('template ', file=self.outFile) - write( - 'const T* UnwrapStructArrayHandles(const T* values, size_t len, HandleUnwrapMemory* unwrap_memory)', - file=self.outFile - ) - write('{', file=self.outFile) - write(' if ((values != nullptr) && (len > 0))', file=self.outFile) - write(' {', file=self.outFile) - write( - ' auto unwrapped_structs = MakeUnwrapStructs(values, len, unwrap_memory);', - file=self.outFile - ) - self.newline() - write(' for (size_t i = 0; i < len; ++i)', file=self.outFile) - write(' {', file=self.outFile) - write( - ' UnwrapStructHandles(&unwrapped_structs[i], unwrap_memory);', - file=self.outFile - ) - write(' }', file=self.outFile) - self.newline() - write(' return unwrapped_structs;', file=self.outFile) - write(' }', file=self.outFile) - self.newline() - write( - ' // Leave the original memory in place when the pointer is not null, but size is zero.', - file=self.outFile - ) - write(' return values;', file=self.outFile) - write('}', file=self.outFile) self.newline() write('GFXRECON_END_NAMESPACE(vulkan_wrappers)', file=self.outFile) write('GFXRECON_END_NAMESPACE(encode)', file=self.outFile) @@ -248,47 +116,3 @@ def need_feature_generation(self): if self.feature_struct_members or self.feature_cmd_params: return True return False - - def generate_create_wrapper_funcs(self): - """Generates functions that wrap struct handle members.""" - for struct in self.output_structs: - body = 'template \n' - body += 'void CreateWrappedStructHandles(typename ParentWrapper::HandleType parent, typename CoParentWrapper::HandleType co_parent, {}* value, PFN_GetHandleId get_id)\n'.format( - struct - ) - body += '{\n' - body += ' if (value != nullptr)\n' - body += ' {\n' - - for member in self.structs_with_handles[struct]: - wrapper_prefix = self.get_wrapper_prefix_from_type(member.base_type) - if self.is_struct(member.base_type): - if member.is_array: - body += ' {}::CreateWrappedStructArrayHandles(parent, co_parent, value->{}, value->{}, get_id);\n'.format( - wrapper_prefix, member.base_type, member.name, member.array_length - ) - elif member.is_pointer: - body += ' {}::CreateWrappedStructHandles(parent, co_parent, value->{}, get_id);\n'.format( - wrapper_prefix, member.name - ) - else: - body += ' {}::CreateWrappedStructHandles(parent, co_parent, &value->{}, get_id);\n'.format( - wrapper_prefix, member.name - ) - else: - if member.is_array: - body += ' {0}::CreateWrappedHandles(parent, co_parent, value->{2}, value->{3}, get_id);\n'.format( - wrapper_prefix, member.base_type[2:], member.name, member.array_length - ) - elif member.is_pointer: - body += ' {0}::CreateWrappedHandle(parent, co_parent, value->{2}, get_id);\n'.format( - wrapper_prefix, member.base_type[2:], member.name - ) - else: - body += ' {0}::CreateWrappedHandle(parent, co_parent, &value->{2}, get_id);\n'.format( - wrapper_prefix, member.base_type[2:], member.name - ) - - body += ' }\n' - body += '}\n' - write(body, file=self.outFile) From 63f6d1b1faf6c52e11bc6b92ae0c9c5b5e5e5e6e Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 11:27:21 -0500 Subject: [PATCH 10/32] codegen: Modify how handles, atoms and opaques are handled --- .../khronos_base_generator.py | 113 +++++++++++++++--- ...se_struct_handle_mappers_body_generator.py | 2 +- ...struct_handle_wrappers_header_generator.py | 4 +- 3 files changed, 101 insertions(+), 18 deletions(-) diff --git a/framework/generated/khronos_generators/khronos_base_generator.py b/framework/generated/khronos_generators/khronos_base_generator.py index 870faa4358..6375544900 100644 --- a/framework/generated/khronos_generators/khronos_base_generator.py +++ b/framework/generated/khronos_generators/khronos_base_generator.py @@ -101,7 +101,7 @@ class ApiData(): api_class_prefix - The prefix to use for classes in this API wrapper_prefix - The prefix used to wrap namespaces command_prefix - The prefix used to identify commands belonging to this Khronos API - struct_prefix - The prefix used to identify structures belonging to this Khronos API + type_prefix - The prefix used to identify types belonging to this Khronos API struct_type_enum - The enum type used to define structure types for this Khronos API struct_type_prefix - The prefix used in the enum to identify the structure type enum value struct_type_variable - The variable name used to identify structure types for this Khronos API @@ -112,6 +112,12 @@ class ApiData(): extended_struct_func_prefix - The function prefix to use for extended struct functions for this Khronos API. boolean_type - The type used by the API for booleans return_const_ptr_on_extended- Return a constant on extended pointer types + supports_handles - This API supports Handles + handle_func_name_mod - The name used to indicate a function is processing handles + supports_atoms - This API supports Atoms as a type + atom_func_name_mod - The name used to indicate a function is processing atoms + supports_opaques - This API supports Opaques as a type + opaque_func_name_mod - The name used to indicate a function is processing opaque """ def __init__( self, @@ -119,7 +125,7 @@ def __init__( api_class_prefix, wrapper_prefix, command_prefix, - struct_prefix, + type_prefix, struct_type_enum, struct_type_prefix, struct_type_variable, @@ -130,13 +136,19 @@ def __init__( extended_struct_func_prefix, boolean_type, return_const_ptr_on_extended, + supports_handles, + handle_func_name_mod, + supports_atoms, + atom_func_name_mod, + supports_opaques, + opaque_func_name_mod, ): self.api_name = api_name self.api_class_prefix = api_class_prefix self.wrapper_prefix = wrapper_prefix self.command_prefix = command_prefix self.struct_type_enum = struct_type_enum - self.struct_prefix = struct_prefix + self.type_prefix = type_prefix self.struct_type_prefix = struct_type_prefix self.struct_type_variable = struct_type_variable self.struct_type_func_prefix = struct_type_func_prefix @@ -146,6 +158,12 @@ def __init__( self.extended_struct_func_prefix = extended_struct_func_prefix self.boolean_type = boolean_type self.return_const_ptr_on_extended = return_const_ptr_on_extended + self.supports_handles = supports_handles + self.handle_func_name_mod = handle_func_name_mod + self.supports_atoms = supports_atoms + self.atom_func_name_mod = atom_func_name_mod + self.supports_opaques = supports_opaques + self.opaque_func_name_mod = opaque_func_name_mod class ValueInfo(): """ValueInfo - Class to store parameter/struct member information. @@ -399,6 +417,9 @@ def __init__( self.structs_with_handle_ptrs = set( ) # Set of structures with handles + self.atom_names = set() # Set of current API's Atom typenames + self.opaque_names = set() # Set of current API's Opaque typenames + # Data for every supported Khronos API # TODO: Eventually, we should move this info into a data file that we read (JSON?) self.valid_khronos_supported_api_data = [] @@ -409,7 +430,7 @@ def __init__( wrapper_prefix='vulkan_wrappers', command_prefix='vk', struct_type_enum='VkStructureType', - struct_prefix='Vk', + type_prefix='Vk', struct_type_prefix='VK_STRUCTURE_TYPE_', struct_type_variable='sType', struct_type_func_prefix='SType', @@ -418,7 +439,13 @@ def __init__( extended_struct_variable='pNext', extended_struct_func_prefix='PNext', boolean_type='VkBool32', - return_const_ptr_on_extended=True + return_const_ptr_on_extended=True, + supports_handles=True, + handle_func_name_mod='Handle', + supports_atoms=False, + atom_func_name_mod='', + supports_opaques=False, + opaque_func_name_mod='' ) ) self.valid_khronos_supported_api_data.append( @@ -428,7 +455,7 @@ def __init__( wrapper_prefix='openxr_wrappers', command_prefix='xr', struct_type_enum='XrStructureType', - struct_prefix='Xr', + type_prefix='Xr', struct_type_prefix='XR_TYPE_', struct_type_variable='type', struct_type_func_prefix='Type', @@ -437,7 +464,13 @@ def __init__( extended_struct_variable='next', extended_struct_func_prefix='Next', boolean_type='XrBool32', - return_const_ptr_on_extended=False + return_const_ptr_on_extended=False, + supports_handles=True, + handle_func_name_mod='Handle', + supports_atoms=True, + atom_func_name_mod='Atom', + supports_opaques=True, + opaque_func_name_mod='Opaque' ) ) @@ -584,9 +617,61 @@ def is_handle(self, base_type): return False def is_atom(self, base_type): - """Check if atom. The subclass may override this method.""" + for api_data in self.valid_khronos_supported_api_data: + if (api_data.supports_atoms and + base_type.startswith(api_data.type_prefix) and + base_type == self.atom_names): + return True return False + def is_opaque(self, base_type): + for api_data in self.valid_khronos_supported_api_data: + if (api_data.supports_opaques and + base_type == api_data.type_prefix and + base_type == self.opaque_names): + return True + return False + + def is_handle_like(self, base_type): + if (self.is_handle(base_type) or + self.is_atom(base_type) or + self.is_opaque(base_type)): + return True + return False + + def get_handle_func_name_modifier(self, base_type): + for api_data in self.valid_khronos_supported_api_data: + if (api_data.supports_handles and + base_type.startswith(api_data.type_prefix) and + (base_type in self.handle_names or base_type in self.structs_with_handles)): + return api_data.handle_func_name_mod + return '' + + def get_atom_func_name_modifier(self, base_type): + for api_data in self.valid_khronos_supported_api_data: + if (api_data.supports_atoms and + base_type.startswith(api_data.type_prefix) and + base_type in self.atom_names): + return api_data.atom_func_name_mod + return '' + + def get_opaque_func_name_modifier(self, base_type): + for api_data in self.valid_khronos_supported_api_data: + if (api_data.supports_opaques and + base_type.startswith(api_data.type_prefix) and + base_type in self.opaque_names): + return api_data.opaque_func_name_mod + return '' + + def get_handle_like_func_name_modifier(self, base_type): + if (self.is_handle(base_type) or base_type in self.structs_with_handles): + return self.get_handle_func_name_modifier(base_type) + if (self.is_atom(base_type)): + return self.get_atom_func_name_modifier(base_type) + if (self.is_opaque(base_type)): + return self.get_opaque_func_name_modifier(base_type) + return '' + def get_default_handle_atom_value(self, base_type): return '0' @@ -1425,14 +1510,14 @@ def get_api_data(self): def is_base_input_structure_type(self, type): for api_data in self.valid_khronos_supported_api_data: - if (type.startswith(api_data.struct_prefix) and + if (type.startswith(api_data.type_prefix) and type == api_data.base_in_struct): return True return False def is_base_output_structure_type(self, type): for api_data in self.valid_khronos_supported_api_data: - if (type.startswith(api_data.struct_prefix) and + if (type.startswith(api_data.type_prefix) and type == api_data.base_out_struct): return True return False @@ -1493,7 +1578,7 @@ def get_wrapper_prefix(self): def get_wrapper_prefix_from_type(self, type): for api_data in self.valid_khronos_supported_api_data: - if type.startswith(api_data.struct_prefix): + if type.startswith(api_data.type_prefix): return api_data.wrapper_prefix return self.get_wrapper_prefix() @@ -1511,7 +1596,7 @@ def get_api_prefix(self): def get_api_prefix_from_type(self, type): for api_data in self.valid_khronos_supported_api_data: - if type.startswith(api_data.struct_prefix): + if type.startswith(api_data.type_prefix): return api_data.api_class_prefix return self.get_api_prefix() @@ -1535,7 +1620,7 @@ def generate_structure_type(self, type_name): # Apply any structure type prefix first for api_data in self.valid_khronos_supported_api_data: - upper_prefix = api_data.struct_prefix.upper() + upper_prefix = api_data.type_prefix.upper() if upper_type.startswith(upper_prefix): type_with_prefix = api_data.struct_type_prefix + upper_type @@ -1551,7 +1636,7 @@ def make_simple_var_name(self, type_name): lower_type = re.sub('([a-z0-9])([A-Z])', r'\1_\2', type_name).lower() for api_data in self.valid_khronos_supported_api_data: - lower_prefix = api_data.struct_prefix.lower() + lower_prefix = api_data.type_prefix.lower() if lower_type.startswith(lower_prefix): lower_prefix_len = len(lower_prefix) new_lower_type = lower_type[:lower_prefix_len - 1] + '_' + lower_type[lower_prefix_len - 1:] diff --git a/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py b/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py index 4c4efd853f..a9a04d3d45 100644 --- a/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py +++ b/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py @@ -57,7 +57,7 @@ def generate_handle_mappers(self): else: for member in handle_members: if ( - (self.is_handle(member.base_type) or self.is_atom(member.base_type)) and + (self.is_handle_like(member.base_type)) and not (member.is_array and not member.is_dynamic) ) or (member.base_type in self.MAP_STRUCT_TYPE): needs_value_ptr = True diff --git a/framework/generated/khronos_generators/khronos_struct_handle_wrappers_header_generator.py b/framework/generated/khronos_generators/khronos_struct_handle_wrappers_header_generator.py index 7e371b67c4..a6addb163a 100644 --- a/framework/generated/khronos_generators/khronos_struct_handle_wrappers_header_generator.py +++ b/framework/generated/khronos_generators/khronos_struct_handle_wrappers_header_generator.py @@ -231,9 +231,7 @@ def generate_create_wrapper_funcs(self): for member in self.structs_with_handles[struct]: wrapper_prefix = self.get_wrapper_prefix_from_type(member.base_type) - func_target = 'Handle' - if self.is_atom(member.base_type): - func_target = 'Atom' + func_target = self.get_handle_like_func_name_modifier(member.base_type) if self.is_struct(member.base_type): if member.is_array: From 093a23a9519721070127106adaa490a238121353 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 12:03:31 -0500 Subject: [PATCH 11/32] codegen: Use "isHandleLike" instead of separate checks Use "isHandleLike" when determining if we need to treat a type like a handle, atom, or opaque type. --- .../khronos_base_decoder_body_generator.py | 13 +++++-------- ...khronos_base_struct_decoders_body_generator.py | 15 ++++++--------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/framework/generated/khronos_generators/khronos_base_decoder_body_generator.py b/framework/generated/khronos_generators/khronos_base_decoder_body_generator.py index e0b18084b2..91726380fc 100644 --- a/framework/generated/khronos_generators/khronos_base_decoder_body_generator.py +++ b/framework/generated/khronos_generators/khronos_base_decoder_body_generator.py @@ -155,8 +155,7 @@ def make_decode_invocation(self, value, preamble, main_body, epilogue): is_struct = False is_string = False is_funcp = False - is_handle = False - is_atom = False + is_handle_like = False type_name = self.make_invocation_type_name(value.base_type) @@ -166,10 +165,8 @@ def make_decode_invocation(self, value, preamble, main_body, epilogue): is_string = True elif type_name == 'FunctionPtr': is_funcp = True - elif self.is_handle(value.base_type): - is_handle = True - elif self.is_atom(value.base_type): - is_atom = True + elif self.is_handle_like(value.base_type): + is_handle_like = True # is_pointer will be False for static arrays. if value.is_pointer or value.is_array: @@ -185,7 +182,7 @@ def make_decode_invocation(self, value, preamble, main_body, epilogue): buffer_args, value.name ) else: - if is_struct or is_string or is_handle or is_atom: + if is_struct or is_string or is_handle_like: if type_name in self.children_structs.keys(): base_type_name = self.make_simple_var_name(value.base_type) main_body += ' if (PointerDecoderBase::PeekAttributesAndType((parameter_buffer + bytes_read),\n' @@ -252,7 +249,7 @@ def make_decode_invocation(self, value, preamble, main_body, epilogue): main_body += ' bytes_read += ValueDecoder::DecodeAddress({}, &{});\n'.format( buffer_args, value.name ) - elif is_handle or is_atom: + elif is_handle_like: main_body += ' bytes_read += ValueDecoder::DecodeHandleIdValue({}, &{});\n'.format( buffer_args, value.name ) diff --git a/framework/generated/khronos_generators/khronos_base_struct_decoders_body_generator.py b/framework/generated/khronos_generators/khronos_base_struct_decoders_body_generator.py index cf64a4ae6e..16cab409ea 100644 --- a/framework/generated/khronos_generators/khronos_base_struct_decoders_body_generator.py +++ b/framework/generated/khronos_generators/khronos_base_struct_decoders_body_generator.py @@ -87,9 +87,8 @@ def make_decode_invocation(self, name, value, preamble, main_body, epilogue): is_struct = False is_string = False is_funcp = False - is_handle = False + is_handle_like = False is_enum = False - is_atom = False type_name = self.make_invocation_type_name(value.base_type) @@ -99,10 +98,8 @@ def make_decode_invocation(self, name, value, preamble, main_body, epilogue): is_string = True elif type_name == 'FunctionPtr': is_funcp = True - elif self.is_handle(value.base_type): - is_handle = True - elif self.is_atom(value.base_type): - is_atom = True + elif self.is_handle_like(value.base_type): + is_handle_like = True elif type_name == 'Enum': is_enum = True @@ -182,7 +179,7 @@ def make_decode_invocation(self, name, value, preamble, main_body, epilogue): arraylen=value.array_capacity ) - if is_struct or is_string or is_handle or is_atom: + if is_struct or is_string or is_handle_like: main_body += ' bytes_read += wrapper->{}{}Decode({});\n'.format( value.name, access_op, buffer_args ) @@ -197,7 +194,7 @@ def make_decode_invocation(self, name, value, preamble, main_body, epilogue): ) if not is_static_array: - if is_handle or is_atom: + if is_handle_like: # Point the real struct's member pointer to the handle pointer decoder's handle memory. main_body += ' value->{} = nullptr;\n'.format(value.name) else: @@ -273,7 +270,7 @@ def make_decode_invocation(self, name, value, preamble, main_body, epilogue): buffer_args, value.name ) main_body += ' value->{} = nullptr;\n'.format(value.name) - elif is_handle or is_atom: + elif is_handle_like: main_body += ' bytes_read += ValueDecoder::DecodeHandleIdValue({}, &(wrapper->{}));\n'.format( buffer_args, value.name ) From eee90eab0137fb691bfb08d80da8defca8ae6c6d Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 13:38:51 -0500 Subject: [PATCH 12/32] codegen: Move struct handle wrap body to Khronos Move the structure handle wrapping body code generation to the Khronos version except for special cases. --- ...s_struct_handle_wrappers_body_generator.py | 226 ++++++++++++++++++ ...n_struct_handle_wrappers_body_generator.py | 193 ++------------- 2 files changed, 252 insertions(+), 167 deletions(-) create mode 100644 framework/generated/khronos_generators/khronos_struct_handle_wrappers_body_generator.py diff --git a/framework/generated/khronos_generators/khronos_struct_handle_wrappers_body_generator.py b/framework/generated/khronos_generators/khronos_struct_handle_wrappers_body_generator.py new file mode 100644 index 0000000000..6b0249c9fb --- /dev/null +++ b/framework/generated/khronos_generators/khronos_struct_handle_wrappers_body_generator.py @@ -0,0 +1,226 @@ +#!/usr/bin/python3 -i +# +# Copyright (c) 2019 Valve Corporation +# Copyright (c) 2019-2024 LunarG, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import sys +from khronos_base_generator import write + + +class KhronosStructHandleWrappersBodyGenerator(): + """KhronosStructHandleWrappersBodyGenerator + Generates C++ functions responsible for wrapping struct member handles + when recording Khrosos API call parameter data. + """ + + def write_special_case_struct_handling(self): + """Method may be overridden""" + return + + def write_struct_handle_wrapper_content(self): + api_data = self.get_api_data() + ext_struct_name = api_data.extended_struct_func_prefix + ext_var_name = api_data.extended_struct_variable + type_var_name = api_data.struct_type_variable + const_prefix = '' + if api_data.return_const_ptr_on_extended: + const_prefix = 'const ' + + for struct in self.get_all_filtered_struct_names(): + if ( + (struct in self.structs_with_handles) or + (struct in self.GENERIC_HANDLE_STRUCTS) + ) and (struct not in self.STRUCT_MAPPERS_BLACKLIST): + handle_members = dict() + generic_handle_members = dict() + + if struct in self.structs_with_handles: + handle_members = self.structs_with_handles[struct] + if struct in self.GENERIC_HANDLE_STRUCTS: + generic_handle_members = self.GENERIC_HANDLE_STRUCTS[struct + ] + + body = '\n' + body += 'void UnwrapStructHandles({}* value, HandleUnwrapMemory* unwrap_memory)\n'.format( + struct + ) + body += '{\n' + body += ' if (value != nullptr)\n' + body += ' {\n' + body += self.make_struct_handle_unwrappings( + api_data, struct, handle_members, generic_handle_members + ) + body += ' }\n' + body += '}' + + write(body, file=self.outFile) + + # Generate the pNext shallow copy code, for pNext structs that don't have handles, but need to be preserved in the overall copy for handle wrapping. + self.newline() + write( + '{0}* Copy{1}Struct(const {0}* base, HandleUnwrapMemory* unwrap_memory)' + .format(api_data.base_in_struct, ext_struct_name), + file=self.outFile + ) + write('{', file=self.outFile) + write(' assert(base != nullptr);', file=self.outFile) + self.newline() + write( + ' {}* copy = nullptr;'.format(api_data.base_in_struct), + file=self.outFile + ) + write(' switch (base->{})'.format(type_var_name), file=self.outFile) + write(' {', file=self.outFile) + write(' default:', file=self.outFile) + write( + ' GFXRECON_LOG_WARNING("Failed to copy entire {0} chain when unwrapping handles due to unrecognized {1} %d", base->{1});' + .format(ext_var_name, type_var_name), + file=self.outFile + ) + write(' break;', file=self.outFile) + self.write_special_case_struct_handling() + + extended_list = [] + for struct in self.all_extended_structs: + for ext_struct in self.all_extended_structs[struct]: + if ext_struct not in extended_list and ext_struct not in self.all_struct_aliases: + extended_list.append(ext_struct) + + for base_type in sorted(extended_list): + if base_type not in self.struct_type_names: + continue + + stype = self.struct_type_names[base_type] + write(' case {}:'.format(stype), file=self.outFile) + write( + ' copy = reinterpret_cast<{}*>(MakeUnwrapStructs(reinterpret_cast(base), 1, unwrap_memory));' + .format(api_data.base_in_struct, base_type), + file=self.outFile + ) + write(' break;', file=self.outFile) + write(' }', file=self.outFile) + self.newline() + write(' return copy;', file=self.outFile) + write('}', file=self.outFile) + + # Generate the extended struct handle wrapping code. + self.newline() + write( + 'const void* Unwrap{}StructHandles(const void* value, HandleUnwrapMemory* unwrap_memory)' + .format(ext_struct_name), + file=self.outFile + ) + write('{', file=self.outFile) + write(' if (value != nullptr)', file=self.outFile) + write(' {', file=self.outFile) + write( + ' const {0}* base = reinterpret_cast(value);'. + format(api_data.base_in_struct), + file=self.outFile + ) + self.newline() + write( + ' switch (base->{})'.format(type_var_name), + file=self.outFile + ) + write(' {', file=self.outFile) + write(' default:', file=self.outFile) + write(' {', file=self.outFile) + write( + ' // This structure does not contain handles, but may point to a structure that does.', + file=self.outFile + ) + write( + ' {}* copy = Copy{}Struct(base, unwrap_memory);'.format( + api_data.base_in_struct, ext_struct_name + ), + file=self.outFile + ) + write(' if (copy != nullptr)', file=self.outFile) + write(' {', file=self.outFile) + write( + ' copy->{2} = reinterpret_cast(Unwrap{1}StructHandles(base->{2}, unwrap_memory));' + .format(api_data.base_in_struct, ext_struct_name, ext_var_name), + file=self.outFile + ) + write(' }', file=self.outFile) + write(' return copy;', file=self.outFile) + write(' }', file=self.outFile) + for base_type in sorted(extended_list): + if ( + base_type in self.structs_with_handles + and base_type in self.struct_type_names + ): + stype = self.struct_type_names[base_type] + write(' case {}:'.format(stype), file=self.outFile) + write( + ' return UnwrapStructPtrHandles(reinterpret_cast(base), unwrap_memory);' + .format(base_type), + file=self.outFile + ) + write(' }', file=self.outFile) + write(' }', file=self.outFile) + self.newline() + write(' return nullptr;', file=self.outFile) + write('}', file=self.outFile) + + def has_special_case_handle_unwrapping(self, name): + """Method may be overridden.""" + return False + + def get_special_case_handle_wrapping(self, name): + """Method may be overridden.""" + return + + def make_struct_handle_unwrappings( + self, api_data, name, handle_members, generic_handle_members + ): + """Generating expressions for unwrapping struct handles before an API call.""" + body = '' + + for member in handle_members: + if member.name == api_data.extended_struct_variable: + body += ' if (value->{} != nullptr)\n'.format( + member.name + ) + body += ' {\n' + if self.has_special_case_handle_unwrapping(name): + body += self.get_special_case_handle_wrapping(name) + else: + body += ' value->{0} = Unwrap{1}StructHandles(value->{0}, unwrap_memory);\n'.format( + member.name, api_data.extended_struct_func_prefix + ) + body += ' }\n' + elif self.is_struct(member.base_type): + # This is a struct that includes handles. + if member.is_array: + body += ' value->{name} = UnwrapStructArrayHandles(value->{name}, value->{}, unwrap_memory);\n'.format( + member.array_length, name=member.name + ) + elif member.is_pointer: + body += ' value->{name} = UnwrapStructPtrHandles(value->{name}, unwrap_memory);\n'.format( + name=member.name + ) + else: + body += ' UnwrapStructHandles(&value->{}, unwrap_memory);\n'.format( + member.name + ) + return body diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_body_generator.py index 897fb48449..24f8cd473b 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_wrappers_body_generator.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 -i # # Copyright (c) 2019 Valve Corporation -# Copyright (c) 2019 LunarG, Inc. +# Copyright (c) 2019-2024 LunarG, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to @@ -23,6 +23,7 @@ import sys from base_generator import BaseGenerator, BaseGeneratorOptions, write +from khronos_struct_handle_wrappers_body_generator import KhronosStructHandleWrappersBodyGenerator class VulkanStructHandleWrappersBodyGeneratorOptions(BaseGeneratorOptions): @@ -52,7 +53,7 @@ def __init__( ) -class VulkanStructHandleWrappersBodyGenerator(BaseGenerator): +class VulkanStructHandleWrappersBodyGenerator(BaseGenerator, KhronosStructHandleWrappersBodyGenerator): """VulkanStructHandleWrappersBodyGenerator - subclass of BaseGenerator. Generates C++ functions responsible for wrapping struct member handles when recording Vulkan API call parameter data. @@ -86,53 +87,24 @@ def beginFile(self, gen_opts): def endFile(self): """Method override.""" - for struct in self.get_all_filtered_struct_names(): - if ( - (struct in self.structs_with_handles) - or (struct in self.GENERIC_HANDLE_STRUCTS) - ) and (struct not in self.STRUCT_MAPPERS_BLACKLIST): - handle_members = dict() - generic_handle_members = dict() + KhronosStructHandleWrappersBodyGenerator.write_struct_handle_wrapper_content(self) - if struct in self.structs_with_handles: - handle_members = self.structs_with_handles[struct] - if struct in self.GENERIC_HANDLE_STRUCTS: - generic_handle_members = self.GENERIC_HANDLE_STRUCTS[struct - ] + self.newline() + write('GFXRECON_END_NAMESPACE(vulkan_wrappers)', file=self.outFile) + write('GFXRECON_END_NAMESPACE(encode)', file=self.outFile) + write('GFXRECON_END_NAMESPACE(gfxrecon)', file=self.outFile) - body = '\n' - body += 'void UnwrapStructHandles({}* value, HandleUnwrapMemory* unwrap_memory)\n'.format( - struct - ) - body += '{\n' - body += ' if (value != nullptr)\n' - body += ' {\n' - body += self.make_struct_handle_unwrappings( - struct, handle_members, generic_handle_members - ) - body += ' }\n' - body += '}' + # Finish processing in superclass + BaseGenerator.endFile(self) - write(body, file=self.outFile) + def need_feature_generation(self): + """Indicates that the current feature has C++ code to generate.""" + if self.feature_struct_members: + return True + return False - # Generate the pNext shallow copy code, for pNext structs that don't have handles, but need to be preserved in the overall copy for handle wrapping. - self.newline() - write( - 'VkBaseInStructure* CopyPNextStruct(const VkBaseInStructure* base, HandleUnwrapMemory* unwrap_memory)', - file=self.outFile - ) - write('{', file=self.outFile) - write(' assert(base != nullptr);', file=self.outFile) - self.newline() - write(' VkBaseInStructure* copy = nullptr;', file=self.outFile) - write(' switch (base->sType)', file=self.outFile) - write(' {', file=self.outFile) - write(' default:', file=self.outFile) - write( - ' GFXRECON_LOG_WARNING("Failed to copy entire pNext chain when unwrapping handles due to unrecognized sType %d", base->sType);', - file=self.outFile - ) - write(' break;', file=self.outFile) + def write_special_case_struct_handling(self): + """Method override.""" write( ' case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO:', file=self.outFile @@ -152,128 +124,15 @@ def endFile(self): ) write(' break;', file=self.outFile) - extended_list = [] - for struct in self.all_extended_structs: - for ext_struct in self.all_extended_structs[struct]: - if ext_struct not in extended_list and ext_struct not in self.all_struct_aliases: - extended_list.append(ext_struct) - - for base_type in sorted(extended_list): - if base_type not in self.struct_type_names: - continue - - stype = self.struct_type_names[base_type] - write( - ' case {}:'.format(stype), - file=self.outFile - ) - write( - ' copy = reinterpret_cast(MakeUnwrapStructs(reinterpret_cast(base), 1, unwrap_memory));' - .format(base_type), - file=self.outFile - ) - write(' break;', file=self.outFile) - write(' }', file=self.outFile) - self.newline() - write(' return copy;', file=self.outFile) - write('}', file=self.outFile) - - # Generate the pNext handle wrapping code. - self.newline() - write( - 'const void* UnwrapPNextStructHandles(const void* value, HandleUnwrapMemory* unwrap_memory)', - file=self.outFile - ) - write('{', file=self.outFile) - write(' if (value != nullptr)', file=self.outFile) - write(' {', file=self.outFile) - write( - ' const VkBaseInStructure* base = reinterpret_cast(value);', - file=self.outFile - ) - self.newline() - write(' switch (base->sType)', file=self.outFile) - write(' {', file=self.outFile) - write(' default:', file=self.outFile) - write(' {', file=self.outFile) - write( - ' // This structure does not contain handles, but may point to a structure that does.', - file=self.outFile - ) - write( - ' VkBaseInStructure* copy = CopyPNextStruct(base, unwrap_memory);', - file=self.outFile - ) - write(' if (copy != nullptr)', file=self.outFile) - write(' {', file=self.outFile) - write( - ' copy->pNext = reinterpret_cast(UnwrapPNextStructHandles(base->pNext, unwrap_memory));', - file=self.outFile - ) - write(' }', file=self.outFile) - write(' return copy;', file=self.outFile) - write(' }', file=self.outFile) - for base_type in sorted(extended_list): - if (base_type in self.structs_with_handles and - base_type in self.struct_type_names): - stype = self.struct_type_names[base_type] - write( - ' case {}:'.format(stype), - file=self.outFile - ) - write( - ' return UnwrapStructPtrHandles(reinterpret_cast(base), unwrap_memory);' - .format(base_type), - file=self.outFile - ) - write(' }', file=self.outFile) - write(' }', file=self.outFile) - self.newline() - write(' return nullptr;', file=self.outFile) - write('}', file=self.outFile) - - self.newline() - write('GFXRECON_END_NAMESPACE(vulkan_wrappers)', file=self.outFile) - write('GFXRECON_END_NAMESPACE(encode)', file=self.outFile) - write('GFXRECON_END_NAMESPACE(gfxrecon)', file=self.outFile) - - # Finish processing in superclass - BaseGenerator.endFile(self) - - def need_feature_generation(self): - """Indicates that the current feature has C++ code to generate.""" - if self.feature_struct_members: + def has_special_case_handle_unwrapping(self, name): + """Method override.""" + if (name == 'VkGeneratedCommandsMemoryRequirementsInfoEXT'): return True return False - def make_struct_handle_unwrappings( - self, name, handle_members, generic_handle_members - ): - """Generating expressions for unwrapping struct handles before an API call.""" - body = '' - - for member in handle_members: - if 'pNext' in member.name: - body += ' if (value->pNext != nullptr)\n' - body += ' {\n' - # Workaround for spec missing const in VkGeneratedCommandsMemoryRequirementsInfoEXT::pNext, should be removed next header update - if (name == 'VkGeneratedCommandsMemoryRequirementsInfoEXT'): - body += ' value->pNext = const_cast(UnwrapPNextStructHandles(value->pNext, unwrap_memory));\n' - else: - body += ' value->pNext = UnwrapPNextStructHandles(value->pNext, unwrap_memory);\n' - body += ' }\n' - elif self.is_struct(member.base_type): - # This is a struct that includes handles. - if member.is_array: - body += ' value->{name} = UnwrapStructArrayHandles(value->{name}, value->{}, unwrap_memory);\n'.format( - member.array_length, name=member.name - ) - elif member.is_pointer: - body += ' value->{name} = UnwrapStructPtrHandles(value->{name}, unwrap_memory);\n'.format( - name=member.name - ) - else: - body += ' UnwrapStructHandles(&value->{}, unwrap_memory);\n'.format( - member.name - ) - return body + def get_special_case_handle_wrapping(self, name): + """Method override.""" + # Workaround for spec missing const in VkGeneratedCommandsMemoryRequirementsInfoEXT::pNext, should be removed next header update + if (name == 'VkGeneratedCommandsMemoryRequirementsInfoEXT'): + return ' value->pNext = const_cast(UnwrapPNextStructHandles(value->pNext, unwrap_memory));\n' + return '' From ce06f24bf94425881c8563dec9df485c01f00d4a Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 13:50:15 -0500 Subject: [PATCH 13/32] codegen: Rename Khronos struct handle mapper files --- ...r.py => khronos_struct_handle_mappers_body_generator.py} | 2 +- ...py => khronos_struct_handle_mappers_header_generator.py} | 2 +- .../vulkan_struct_handle_mappers_body_generator.py | 6 +++--- .../vulkan_struct_handle_mappers_header_generator.py | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) rename framework/generated/khronos_generators/{khronos_base_struct_handle_mappers_body_generator.py => khronos_struct_handle_mappers_body_generator.py} (99%) rename framework/generated/khronos_generators/{khronos_base_struct_handle_mappers_header_generator.py => khronos_struct_handle_mappers_header_generator.py} (98%) diff --git a/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py b/framework/generated/khronos_generators/khronos_struct_handle_mappers_body_generator.py similarity index 99% rename from framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py rename to framework/generated/khronos_generators/khronos_struct_handle_mappers_body_generator.py index a9a04d3d45..95a7450d71 100644 --- a/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_body_generator.py +++ b/framework/generated/khronos_generators/khronos_struct_handle_mappers_body_generator.py @@ -25,7 +25,7 @@ from khronos_base_generator import write -class KhronosBaseStructHandleMappersBodyGenerator(): +class KhronosStructHandleMappersBodyGenerator(): """Base class for generating struct handle mappers body code.""" def endFile(self): diff --git a/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_header_generator.py b/framework/generated/khronos_generators/khronos_struct_handle_mappers_header_generator.py similarity index 98% rename from framework/generated/khronos_generators/khronos_base_struct_handle_mappers_header_generator.py rename to framework/generated/khronos_generators/khronos_struct_handle_mappers_header_generator.py index c60b4b1529..91da6f7080 100644 --- a/framework/generated/khronos_generators/khronos_base_struct_handle_mappers_header_generator.py +++ b/framework/generated/khronos_generators/khronos_struct_handle_mappers_header_generator.py @@ -25,7 +25,7 @@ from khronos_base_generator import write -class KhronosBaseStructHandleMappersHeaderGenerator(): +class KhronosStructHandleMappersHeaderGenerator(): """Base class for generating struct handle mappers header code.""" def endFile(self): diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_mappers_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_mappers_body_generator.py index eb1a88154b..644f794a2c 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_mappers_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_mappers_body_generator.py @@ -23,7 +23,7 @@ import sys from base_generator import BaseGenerator, BaseGeneratorOptions, write -from khronos_base_struct_handle_mappers_body_generator import KhronosBaseStructHandleMappersBodyGenerator +from khronos_struct_handle_mappers_body_generator import KhronosStructHandleMappersBodyGenerator class VulkanStructHandleMappersBodyGeneratorOptions(BaseGeneratorOptions): @@ -54,7 +54,7 @@ def __init__( class VulkanStructHandleMappersBodyGenerator( - KhronosBaseStructHandleMappersBodyGenerator, BaseGenerator + KhronosStructHandleMappersBodyGenerator, BaseGenerator ): """VulkanStructHandleMappersBodyGenerator - subclass of BaseGenerator. Generates C++ functions responsible for mapping struct member handles @@ -103,7 +103,7 @@ def beginFile(self, gen_opts): def endFile(self): """Method override.""" - KhronosBaseStructHandleMappersBodyGenerator.endFile(self) + KhronosStructHandleMappersBodyGenerator.endFile(self) self.newline() write('GFXRECON_END_NAMESPACE(decode)', file=self.outFile) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_mappers_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_mappers_header_generator.py index 473edea299..08ecaf1798 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_mappers_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_handle_mappers_header_generator.py @@ -23,7 +23,7 @@ import sys from base_generator import BaseGenerator, BaseGeneratorOptions, write -from khronos_base_struct_handle_mappers_header_generator import KhronosBaseStructHandleMappersHeaderGenerator +from khronos_struct_handle_mappers_header_generator import KhronosStructHandleMappersHeaderGenerator class VulkanStructHandleMappersHeaderGeneratorOptions(BaseGeneratorOptions): @@ -54,7 +54,7 @@ def __init__( class VulkanStructHandleMappersHeaderGenerator( - KhronosBaseStructHandleMappersHeaderGenerator, BaseGenerator + KhronosStructHandleMappersHeaderGenerator, BaseGenerator ): """VulkanStructHandleMappersHeaderGenerator - subclass of BaseGenerator. Generates C++ function prototypes for mapping struct member handles @@ -98,7 +98,7 @@ def beginFile(self, gen_opts): def endFile(self): """Method override.""" - KhronosBaseStructHandleMappersHeaderGenerator.endFile(self) + KhronosStructHandleMappersHeaderGenerator.endFile(self) write('GFXRECON_END_NAMESPACE(decode)', file=self.outFile) write('GFXRECON_END_NAMESPACE(gfxrecon)', file=self.outFile) From 75e587c2649bbf7e903d9430535bf2dbec6422dd Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 13:53:59 -0500 Subject: [PATCH 14/32] codegen: Rename Khronos base_decoder_body generator --- ...ody_generator.py => khronos_decoder_body_generator.py} | 8 ++++---- .../vulkan_generators/vulkan_decoder_body_generator.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) rename framework/generated/khronos_generators/{khronos_base_decoder_body_generator.py => khronos_decoder_body_generator.py} (97%) diff --git a/framework/generated/khronos_generators/khronos_base_decoder_body_generator.py b/framework/generated/khronos_generators/khronos_decoder_body_generator.py similarity index 97% rename from framework/generated/khronos_generators/khronos_base_decoder_body_generator.py rename to framework/generated/khronos_generators/khronos_decoder_body_generator.py index 91726380fc..1d5934462f 100644 --- a/framework/generated/khronos_generators/khronos_base_decoder_body_generator.py +++ b/framework/generated/khronos_generators/khronos_decoder_body_generator.py @@ -26,8 +26,8 @@ from copy import deepcopy -class KhronosBaseDecoderBodyGenerator(): - """Base class for generating decoder body code.""" +class KhronosDecoderBodyGenerator(): + """Khronos class for generating decoder body code.""" def generate_commands(self): platform_type = self.get_api_prefix() @@ -116,11 +116,11 @@ def make_cmd_body(self, return_type, name, values): # Decode() method calls for pointer decoder wrappers. for value in values: - preamble, main_body, epilogue = KhronosBaseDecoderBodyGenerator.make_decode_invocation( + preamble, main_body, epilogue = KhronosDecoderBodyGenerator.make_decode_invocation( self, value, preamble, main_body, epilogue ) if return_type and return_type != 'void': - preamble, main_body, epilogue = KhronosBaseDecoderBodyGenerator.make_decode_invocation( + preamble, main_body, epilogue = KhronosDecoderBodyGenerator.make_decode_invocation( self, ValueInfo('return_value', return_type, return_type), preamble, main_body, epilogue ) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_decoder_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_decoder_body_generator.py index 83ebf358e6..874c203328 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_decoder_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_decoder_body_generator.py @@ -23,7 +23,7 @@ import sys from base_generator import BaseGenerator, BaseGeneratorOptions, write -from khronos_base_decoder_body_generator import KhronosBaseDecoderBodyGenerator +from khronos_decoder_body_generator import KhronosDecoderBodyGenerator class VulkanDecoderBodyGeneratorOptions(BaseGeneratorOptions): @@ -53,7 +53,7 @@ def __init__( ) -class VulkanDecoderBodyGenerator(KhronosBaseDecoderBodyGenerator, BaseGenerator): +class VulkanDecoderBodyGenerator(BaseGenerator, KhronosDecoderBodyGenerator): """VulkanDecoderBodyGenerator - subclass of BaseGenerator. Generates C++ member functions for the VulkanDecoder class responsible for decoding Vulkan API call parameter data. @@ -63,7 +63,7 @@ class VulkanDecoderBodyGenerator(KhronosBaseDecoderBodyGenerator, BaseGenerator) def __init__( self, err_file=sys.stderr, warn_file=sys.stderr, diag_file=sys.stdout ): - KhronosBaseDecoderBodyGenerator.__init__(self) + KhronosDecoderBodyGenerator.__init__(self) BaseGenerator.__init__( self, From fade468c763bea39f6048cbf967a7e4629034fd6 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 13:59:02 -0500 Subject: [PATCH 15/32] codegen: Move Khronos Base Replay name to remove Base --- ...nerator.py => khronos_replay_consumer_body_generator.py} | 2 +- .../vulkan_replay_consumer_body_generator.py | 6 +++--- .../vulkan_replay_dump_resources_body_generator.py | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) rename framework/generated/khronos_generators/{khronos_base_replay_consumer_body_generator.py => khronos_replay_consumer_body_generator.py} (98%) diff --git a/framework/generated/khronos_generators/khronos_base_replay_consumer_body_generator.py b/framework/generated/khronos_generators/khronos_replay_consumer_body_generator.py similarity index 98% rename from framework/generated/khronos_generators/khronos_base_replay_consumer_body_generator.py rename to framework/generated/khronos_generators/khronos_replay_consumer_body_generator.py index b3b1d47a34..91d70efa5e 100644 --- a/framework/generated/khronos_generators/khronos_base_replay_consumer_body_generator.py +++ b/framework/generated/khronos_generators/khronos_replay_consumer_body_generator.py @@ -24,7 +24,7 @@ from khronos_base_generator import write -class KhronosBaseReplayConsumerBodyGenerator(): +class KhronosReplayConsumerBodyGenerator(): """Base class for generating replay cousumers body code.""" def endFile(self): diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_replay_consumer_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_replay_consumer_body_generator.py index 6156509382..f1aed996b9 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_replay_consumer_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_replay_consumer_body_generator.py @@ -25,7 +25,7 @@ import json import sys from base_generator import BaseGenerator, BaseGeneratorOptions, write -from khronos_base_replay_consumer_body_generator import KhronosBaseReplayConsumerBodyGenerator +from khronos_replay_consumer_body_generator import KhronosReplayConsumerBodyGenerator class VulkanReplayConsumerBodyGeneratorOptions(BaseGeneratorOptions): @@ -62,7 +62,7 @@ def __init__( class VulkanReplayConsumerBodyGenerator( - KhronosBaseReplayConsumerBodyGenerator, BaseGenerator + KhronosReplayConsumerBodyGenerator, BaseGenerator ): """VulkanReplayConsumerBodyGenerator - subclass of BaseGenerator. Generates C++ member definitions for the VulkanReplayConsumer class responsible for @@ -138,7 +138,7 @@ def beginFile(self, gen_opts): def endFile(self): """Method override.""" - KhronosBaseReplayConsumerBodyGenerator.endFile(self) + KhronosReplayConsumerBodyGenerator.endFile(self) self.newline() write('static void InitializeOutputStructPNextImpl(const VkBaseInStructure* in_pnext, VkBaseOutStructure* output_struct)', file=self.outFile) write('{', file=self.outFile) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_replay_dump_resources_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_replay_dump_resources_body_generator.py index 52e5cf9289..10f509453a 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_replay_dump_resources_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_replay_dump_resources_body_generator.py @@ -24,7 +24,7 @@ import json import sys from base_generator import BaseGenerator, BaseGeneratorOptions, write -from khronos_base_replay_consumer_body_generator import KhronosBaseReplayConsumerBodyGenerator +from khronos_replay_consumer_body_generator import KhronosReplayConsumerBodyGenerator class VulkanReplayDumpResourcesBodyGeneratorOptions(BaseGeneratorOptions): @@ -57,7 +57,7 @@ def __init__( class VulkanReplayDumpResourcesBodyGenerator( - KhronosBaseReplayConsumerBodyGenerator, BaseGenerator + KhronosReplayConsumerBodyGenerator, BaseGenerator ): """VulkanReplayDumpResourcesBodyGenerator - subclass of BaseGenerator. """ @@ -111,7 +111,7 @@ def beginFile(self, gen_opts): def endFile(self): """Method override.""" - KhronosBaseReplayConsumerBodyGenerator.endFile(self) + KhronosReplayConsumerBodyGenerator.endFile(self) self.newline() write('GFXRECON_END_NAMESPACE(decode)', file=self.outFile) From 13549b0d5e2677249c158d7264fb97c95b6a9c0d Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 14:02:25 -0500 Subject: [PATCH 16/32] codegen: Rename Khronos Base Struct Decoder to remove "Base" --- ...khronos_struct_decoders_body_generator.py} | 4 +- ...ronos_struct_decoders_header_generator.py} | 2 +- ...s_struct_handle_wrappers_body_generator.py | 62 +++++++++++++++++-- .../vulkan_struct_decoders_body_generator.py | 6 +- ...vulkan_struct_decoders_header_generator.py | 6 +- 5 files changed, 65 insertions(+), 15 deletions(-) rename framework/generated/khronos_generators/{khronos_base_struct_decoders_body_generator.py => khronos_struct_decoders_body_generator.py} (99%) rename framework/generated/khronos_generators/{khronos_base_struct_decoders_header_generator.py => khronos_struct_decoders_header_generator.py} (99%) diff --git a/framework/generated/khronos_generators/khronos_base_struct_decoders_body_generator.py b/framework/generated/khronos_generators/khronos_struct_decoders_body_generator.py similarity index 99% rename from framework/generated/khronos_generators/khronos_base_struct_decoders_body_generator.py rename to framework/generated/khronos_generators/khronos_struct_decoders_body_generator.py index 16cab409ea..9844ee84e5 100644 --- a/framework/generated/khronos_generators/khronos_base_struct_decoders_body_generator.py +++ b/framework/generated/khronos_generators/khronos_struct_decoders_body_generator.py @@ -27,7 +27,7 @@ from copy import deepcopy -class KhronosBaseStructDecodersBodyGenerator(): +class KhronosStructDecodersBodyGenerator(): """Base class for generating struct docoder body code.""" def endFile(self): @@ -71,7 +71,7 @@ def make_decode_struct_body(self, name, values): ) main_body += ' value->{var} = wrapper->{var} ? wrapper->{var}->GetPointer() : nullptr;\n'.format(var=extended_struct_name) else: - preamble, main_body, epilogue = KhronosBaseStructDecodersBodyGenerator.make_decode_invocation( + preamble, main_body, epilogue = KhronosStructDecodersBodyGenerator.make_decode_invocation( self, name, value, preamble, main_body, epilogue ) diff --git a/framework/generated/khronos_generators/khronos_base_struct_decoders_header_generator.py b/framework/generated/khronos_generators/khronos_struct_decoders_header_generator.py similarity index 99% rename from framework/generated/khronos_generators/khronos_base_struct_decoders_header_generator.py rename to framework/generated/khronos_generators/khronos_struct_decoders_header_generator.py index cb1b3c28c4..3ded79d654 100644 --- a/framework/generated/khronos_generators/khronos_base_struct_decoders_header_generator.py +++ b/framework/generated/khronos_generators/khronos_struct_decoders_header_generator.py @@ -24,7 +24,7 @@ from khronos_base_generator import write -class KhronosBaseStructDecodersHeaderGenerator(): +class KhronosStructDecodersHeaderGenerator(): """Base class for generating struct decoder header code.""" # @note decoded_value must always be the first member of a decode struct so that diff --git a/framework/generated/khronos_generators/khronos_struct_handle_wrappers_body_generator.py b/framework/generated/khronos_generators/khronos_struct_handle_wrappers_body_generator.py index 6b0249c9fb..4fb1ad5215 100644 --- a/framework/generated/khronos_generators/khronos_struct_handle_wrappers_body_generator.py +++ b/framework/generated/khronos_generators/khronos_struct_handle_wrappers_body_generator.py @@ -21,7 +21,7 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -import sys +import re, sys from khronos_base_generator import write @@ -35,6 +35,30 @@ def write_special_case_struct_handling(self): """Method may be overridden""" return + def generate_parent_child_handling(self, api_data, type): + body = '' + if type in self.children_structs.keys(): + type_var_name = api_data.struct_type_variable + body += ' switch (value->{})\n'.format(type_var_name) + body += ' {\n' + body += ' default:\n' + body += ' // Handle as parent-type below\n' + body += ' break;\n' + + # Loop over each possible child + for child in self.children_structs[type]: + switch_type = self.struct_type_names[child] + + body += f' case {switch_type}:\n' + body += f' UnwrapStructHandles(reinterpret_cast<{child}*>(value),\n' + body += f' unwrap_memory);\n' + body += ' // Return here because we processed the appropriate data in\n' + body += ' // the correct structure type\n' + body += ' return;\n' + body += ' }\n' + body += '\n' + return body + def write_struct_handle_wrapper_content(self): api_data = self.get_api_data() ext_struct_name = api_data.extended_struct_func_prefix @@ -65,6 +89,8 @@ def write_struct_handle_wrapper_content(self): body += '{\n' body += ' if (value != nullptr)\n' body += ' {\n' + + body += self.generate_parent_child_handling(api_data, struct) body += self.make_struct_handle_unwrappings( api_data, struct, handle_members, generic_handle_members ) @@ -124,8 +150,8 @@ def write_struct_handle_wrapper_content(self): # Generate the extended struct handle wrapping code. self.newline() write( - 'const void* Unwrap{}StructHandles(const void* value, HandleUnwrapMemory* unwrap_memory)' - .format(ext_struct_name), + '{}void* Unwrap{}StructHandles(const void* value, HandleUnwrapMemory* unwrap_memory)' + .format(const_prefix, ext_struct_name), file=self.outFile ) write('{', file=self.outFile) @@ -212,9 +238,33 @@ def make_struct_handle_unwrappings( elif self.is_struct(member.base_type): # This is a struct that includes handles. if member.is_array: - body += ' value->{name} = UnwrapStructArrayHandles(value->{name}, value->{}, unwrap_memory);\n'.format( - member.array_length, name=member.name - ) + if api_data.return_const_ptr_on_extended: + body += ' value->{name} = UnwrapStructArrayHandles(value->{name}, value->{}, unwrap_memory);\n'.format( + member.array_length, name=member.name + ) + else: + if 'const' in member.full_type: + temp_type = member.full_type + full_type_non_const = re.sub(' const ', '', temp_type) + full_type_non_const = re.sub( + 'const ', '', full_type_non_const + ) + full_type_non_const = re.sub( + ' const', '', full_type_non_const + ) + variable_name = f'const_cast<{full_type_non_const}>(value->{member.name})' + else: + variable_name = f'value->{member.name}' + + length_exprs = member.array_length.split(',') + length_count = len(length_exprs) + + if member.pointer_count > 1 and length_count < member.pointer_count: + unwrap_function = 'UnwrapStructPtrArrayHandles' + else: + unwrap_function = 'UnwrapStructArrayHandles' + + body += f' value->{member.name} = {unwrap_function}({variable_name}, value->{member.array_length}, unwrap_memory);\n' elif member.is_pointer: body += ' value->{name} = UnwrapStructPtrHandles(value->{name}, unwrap_memory);\n'.format( name=member.name diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_decoders_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_decoders_body_generator.py index 87bc7b3e36..0aa0162f20 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_decoders_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_decoders_body_generator.py @@ -23,7 +23,7 @@ import sys from base_generator import BaseGenerator, BaseGeneratorOptions, write -from khronos_base_struct_decoders_body_generator import KhronosBaseStructDecodersBodyGenerator +from khronos_struct_decoders_body_generator import KhronosStructDecodersBodyGenerator class VulkanStructDecodersBodyGeneratorOptions(BaseGeneratorOptions): @@ -54,7 +54,7 @@ def __init__( class VulkanStructDecodersBodyGenerator( - KhronosBaseStructDecodersBodyGenerator, BaseGenerator + KhronosStructDecodersBodyGenerator, BaseGenerator ): """VulkanStructDecodersBodyGenerator - subclass of BaseGenerator. Generates C++ functions for decoding Vulkan API structures. @@ -97,7 +97,7 @@ def beginFile(self, gen_opts): def endFile(self): """Method override.""" - KhronosBaseStructDecodersBodyGenerator.endFile(self) + KhronosStructDecodersBodyGenerator.endFile(self) self.newline() write('GFXRECON_END_NAMESPACE(decode)', file=self.outFile) write('GFXRECON_END_NAMESPACE(gfxrecon)', file=self.outFile) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_decoders_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_decoders_header_generator.py index 40252569b4..6408aa8d1f 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_decoders_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_decoders_header_generator.py @@ -23,7 +23,7 @@ import sys from base_generator import BaseGenerator, BaseGeneratorOptions, write -from khronos_base_struct_decoders_header_generator import KhronosBaseStructDecodersHeaderGenerator +from khronos_struct_decoders_header_generator import KhronosStructDecodersHeaderGenerator class VulkanStructDecodersHeaderGeneratorOptions(BaseGeneratorOptions): @@ -54,7 +54,7 @@ def __init__( class VulkanStructDecodersHeaderGenerator( - KhronosBaseStructDecodersHeaderGenerator, BaseGenerator + KhronosStructDecodersHeaderGenerator, BaseGenerator ): """VulkanStructDecodersHeaderGenerator - subclass of BaseGenerator. Generates C++ type declarations for the decoded Vulkan API structure wrappers. @@ -102,7 +102,7 @@ def beginFile(self, gen_opts): def endFile(self): """Method override.""" - KhronosBaseStructDecodersHeaderGenerator.endFile(self) + KhronosStructDecodersHeaderGenerator.endFile(self) self.newline() write('GFXRECON_END_NAMESPACE(decode)', file=self.outFile) write('GFXRECON_END_NAMESPACE(gfxrecon)', file=self.outFile) From 31008cc33d4be71a90c1653ed9ce5e4586ddc5d9 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 15:47:33 -0500 Subject: [PATCH 17/32] codegen: Move JSON body to support other handle-like types --- .../khronos_struct_to_json_body_generator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/generated/khronos_generators/khronos_struct_to_json_body_generator.py b/framework/generated/khronos_generators/khronos_struct_to_json_body_generator.py index ef1f468e34..171185dcaf 100644 --- a/framework/generated/khronos_generators/khronos_struct_to_json_body_generator.py +++ b/framework/generated/khronos_generators/khronos_struct_to_json_body_generator.py @@ -146,7 +146,7 @@ def makeStructBody(self, name, values): elif value.is_pointer: if 'String' in type_name: to_json = 'FieldToJson(jdata["{0}"], &meta_struct.{0}, options)' - elif self.is_handle(value_type): + elif self.is_handle_like(value_type): to_json = 'HandleToJson(jdata["{0}"], &meta_struct.{0}, options)' else: to_json = 'FieldToJson(jdata["{0}"], meta_struct.{0}, options)' @@ -156,7 +156,7 @@ def makeStructBody(self, name, values): to_json = 'FieldToJson(jdata["{0}"], uuid_to_string(sizeof(decoded_value.{0}), decoded_value.{0}), options)' elif 'String' in type_name: to_json = 'FieldToJson(jdata["{0}"], &meta_struct.{0}, options)' - elif self.is_handle(value_type): + elif self.is_handle_like(value_type): to_json = 'HandleToJson(jdata["{0}"], &meta_struct.{0}, options)' elif self.is_struct(value_type): # If this is a parent class, generate the parent->child conversion info From 63546144937fe5bbb43c2734f1ec61968c4ea956 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 15:53:43 -0500 Subject: [PATCH 18/32] codegen: Migrate struct encoder header to Khronos --- ...hronos_struct_encoders_header_generator.py | 47 +++++++++++++++++++ ...vulkan_struct_encoders_header_generator.py | 18 ++----- 2 files changed, 50 insertions(+), 15 deletions(-) create mode 100644 framework/generated/khronos_generators/khronos_struct_encoders_header_generator.py diff --git a/framework/generated/khronos_generators/khronos_struct_encoders_header_generator.py b/framework/generated/khronos_generators/khronos_struct_encoders_header_generator.py new file mode 100644 index 0000000000..beef7c2e58 --- /dev/null +++ b/framework/generated/khronos_generators/khronos_struct_encoders_header_generator.py @@ -0,0 +1,47 @@ +#!/usr/bin/python3 -i +# +# Copyright (c) 2018 Valve Corporation +# Copyright (c) 2018-2024 LunarG, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import sys +from khronos_base_generator import write + + +class KhronosStructEncodersHeaderGenerator(): + """KhronosStructEncodersHeaderGenerator + Generates C++ type and function declarations for encoding Khronos API structures. + """ + + def write_encoder_content(self): + ext_struct_prefix = self.get_extended_struct_func_prefix() + + write( + 'void Encode{}Struct(ParameterEncoder* encoder, const void* value);' + .format(ext_struct_prefix), + file=self.outFile + ) + + for struct in self.get_all_filtered_struct_names(): + write( + 'void EncodeStruct(ParameterEncoder* encoder, const {}& value);' + .format(struct), + file=self.outFile + ) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_encoders_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_encoders_header_generator.py index 3fab638791..b4fa30a676 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_encoders_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_encoders_header_generator.py @@ -23,6 +23,7 @@ import sys from base_generator import BaseGenerator, BaseGeneratorOptions, write +from khronos_struct_encoders_header_generator import KhronosStructEncodersHeaderGenerator class VulkanStructEncodersHeaderGeneratorOptions(BaseGeneratorOptions): @@ -52,7 +53,7 @@ def __init__( ) -class VulkanStructEncodersHeaderGenerator(BaseGenerator): +class VulkanStructEncodersHeaderGenerator(BaseGenerator, KhronosStructEncodersHeaderGenerator): """VulkanStructEncodersHeaderGenerator - subclass of BaseGenerator. Generates C++ type and function declarations for encoding Vulkan API structures. Generate C++ function declarations for Vulkan struct encoding. @@ -83,14 +84,10 @@ def beginFile(self, gen_opts): write('GFXRECON_BEGIN_NAMESPACE(gfxrecon)', file=self.outFile) write('GFXRECON_BEGIN_NAMESPACE(encode)', file=self.outFile) self.newline() - write( - 'void EncodePNextStruct(ParameterEncoder* encoder, const void* value);', - file=self.outFile - ) def endFile(self): """Method override.""" - self.write_encoder_content() + KhronosStructEncodersHeaderGenerator.write_encoder_content(self) self.newline() write('GFXRECON_END_NAMESPACE(encode)', file=self.outFile) @@ -104,12 +101,3 @@ def need_feature_generation(self): if self.feature_struct_members: return True return False - - def write_encoder_content(self): - """Performs C++ code generation for the encoder.""" - for struct in self.get_all_filtered_struct_names(): - write( - 'void EncodeStruct(ParameterEncoder* encoder, const {}& value);' - .format(struct), - file=self.outFile - ) From d1034ae2a2850a59b50ffa2c378763b13d74787a Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 16:00:28 -0500 Subject: [PATCH 19/32] codegen: Migrate struct encoder body to Khronos --- .../khronos_struct_encoders_body_generator.py | 64 +++++++++++++++++++ .../vulkan_struct_encoders_body_generator.py | 38 +---------- 2 files changed, 67 insertions(+), 35 deletions(-) create mode 100644 framework/generated/khronos_generators/khronos_struct_encoders_body_generator.py diff --git a/framework/generated/khronos_generators/khronos_struct_encoders_body_generator.py b/framework/generated/khronos_generators/khronos_struct_encoders_body_generator.py new file mode 100644 index 0000000000..e900694333 --- /dev/null +++ b/framework/generated/khronos_generators/khronos_struct_encoders_body_generator.py @@ -0,0 +1,64 @@ +#!/usr/bin/python3 -i +# +# Copyright (c) 2018-2019 Valve Corporation +# Copyright (c) 2018-2019 LunarG, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import sys +from khronos_base_generator import write + + +class KhronosStructEncodersBodyGenerator(): + """KhronosStructEncodersBodyGenerator. + Generates C++ functions for encoding Khronos API structures. + """ + + def write_encoder_content(self): + api_data = self.get_api_data() + for struct in self.get_all_filtered_struct_names(): + body = '\n' + body += 'void EncodeStruct(ParameterEncoder* encoder, const {}& value)\n'.format( + struct + ) + body += '{\n' + body += self.makeStructBody( + api_data, struct, self.all_struct_members[struct], 'value.' + ) + body += '}' + write(body, file=self.outFile) + + def makeStructBody(self, api_data, name, values, prefix): + """Command definition.""" + # Build array of lines for function body + body = '' + + for value in values: + # pNext fields require special treatment and are not processed by typename + if api_data.extended_struct_variable == value.name: + body += ' Encode{}Struct(encoder, {});\n'.format( + api_data.extended_struct_func_prefix, prefix + value.name + ) + else: + method_call = self.make_encoder_method_call( + name, value, values, prefix + ) + body += ' {};\n'.format(method_call) + + return body diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_encoders_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_encoders_body_generator.py index fe93c13473..26640e0bd3 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_encoders_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_encoders_body_generator.py @@ -23,6 +23,7 @@ import sys from base_generator import BaseGenerator, BaseGeneratorOptions, write +from khronos_struct_encoders_body_generator import KhronosStructEncodersBodyGenerator class VulkanStructEncodersBodyGeneratorOptions(BaseGeneratorOptions): @@ -52,7 +53,7 @@ def __init__( ) -class VulkanStructEncodersBodyGenerator(BaseGenerator): +class VulkanStructEncodersBodyGenerator(BaseGenerator, KhronosStructEncodersBodyGenerator): """VulkanStructEncodersBodyGenerator - subclass of BaseGenerator. Generates C++ functions for encoding Vulkan API structures. Generate C++ functions for Vulkan struct encoding. @@ -92,7 +93,7 @@ def beginFile(self, gen_opts): def endFile(self): """Method override.""" - self.write_encoder_content() + KhronosStructEncodersBodyGenerator.write_encoder_content(self) self.newline() write('GFXRECON_END_NAMESPACE(encode)', file=self.outFile) @@ -106,36 +107,3 @@ def need_feature_generation(self): if self.feature_struct_members: return True return False - - def write_encoder_content(self): - """Performs C++ code generation for the encoder.""" - for struct in self.get_all_filtered_struct_names(): - body = '\n' - body += 'void EncodeStruct(ParameterEncoder* encoder, const {}& value)\n'.format( - struct - ) - body += '{\n' - body += self.make_struct_body( - struct, self.all_struct_members[struct], 'value.' - ) - body += '}' - write(body, file=self.outFile) - - def make_struct_body(self, name, values, prefix): - """Command definition.""" - # Build array of lines for function body - body = '' - - for value in values: - # pNext fields require special treatment and are not processed by typename - if 'pNext' in value.name: - body += ' EncodePNextStruct(encoder, {});\n'.format( - prefix + value.name - ) - else: - method_call = self.make_encoder_method_call( - name, value, values, prefix - ) - body += ' {};\n'.format(method_call) - - return body From cd55f62a771fe998fc8e2a9ed23d27c159db89f5 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 16:04:26 -0500 Subject: [PATCH 20/32] codegen: Move more from struct decoder body to Khronos --- .../khronos_struct_decoders_body_generator.py | 45 +++++++++++++++---- .../vulkan_struct_decoders_body_generator.py | 4 -- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/framework/generated/khronos_generators/khronos_struct_decoders_body_generator.py b/framework/generated/khronos_generators/khronos_struct_decoders_body_generator.py index 9844ee84e5..44b19e5490 100644 --- a/framework/generated/khronos_generators/khronos_struct_decoders_body_generator.py +++ b/framework/generated/khronos_generators/khronos_struct_decoders_body_generator.py @@ -35,6 +35,17 @@ def endFile(self): def generate_decode_struct_body(self): """Performs C++ code generation for the feature.""" + api_data = self.get_api_data() + + write( + 'size_t Decode{0}Struct(const uint8_t* buffer, size_t buffer_size, {0}Node** {1});' + .format( + api_data.extended_struct_func_prefix, + api_data.extended_struct_variable + ), + file=self.outFile + ) + for struct in self.get_all_filtered_struct_names(): body = '\n' body += 'size_t DecodeStruct(const uint8_t* buffer, size_t buffer_size, Decoded_{}* wrapper)\n'.format( @@ -65,11 +76,14 @@ def make_decode_struct_body(self, name, values): # If it is an extended struct name, it requires special treatment if self.is_extended_struct_definition(value): extended_struct_name = self.get_extended_struct_var_name() - extended_struct_func_prefix = self.get_extended_struct_func_prefix() + extended_struct_func_prefix = self.get_extended_struct_func_prefix( + ) main_body += ' bytes_read += Decode{}Struct((buffer + bytes_read), (buffer_size - bytes_read), &(wrapper->{}));\n'.format( extended_struct_func_prefix, value.name ) - main_body += ' value->{var} = wrapper->{var} ? wrapper->{var}->GetPointer() : nullptr;\n'.format(var=extended_struct_name) + main_body += ' value->{var} = wrapper->{var} ? wrapper->{var}->GetPointer() : nullptr;\n'.format( + var=extended_struct_name + ) else: preamble, main_body, epilogue = KhronosStructDecodersBodyGenerator.make_decode_invocation( self, name, value, preamble, main_body, epilogue @@ -80,7 +94,9 @@ def make_decode_struct_body(self, name, values): body = preamble + main_body + epilogue return body - def make_decode_invocation(self, name, value, preamble, main_body, epilogue): + def make_decode_invocation( + self, name, value, preamble, main_body, epilogue + ): """Generate the struct member decoder function call invocation.""" buffer_args = '(buffer + bytes_read), (buffer_size - bytes_read)' @@ -143,7 +159,9 @@ def make_decode_invocation(self, name, value, preamble, main_body, epilogue): new_value = deepcopy(value) new_value.base_type = child - decode_type = self.make_decoded_param_type(new_value) + decode_type = self.make_decoded_param_type( + new_value + ) var_name = value.name + '_' + child.lower() preamble += f' {decode_type}* {var_name};\n' @@ -186,7 +204,8 @@ def make_decode_invocation(self, name, value, preamble, main_body, epilogue): elif self.has_basetype(value.base_type): base_type = self.get_basetype(value.base_type) main_body += ' bytes_read += wrapper->{}.Decode{}({});\n'.format( - value.name, self.encode_types[base_type], buffer_args + value.name, self.encode_types[base_type], + buffer_args ) else: main_body += ' bytes_read += wrapper->{}.Decode{}({});\n'.format( @@ -196,7 +215,9 @@ def make_decode_invocation(self, name, value, preamble, main_body, epilogue): if not is_static_array: if is_handle_like: # Point the real struct's member pointer to the handle pointer decoder's handle memory. - main_body += ' value->{} = nullptr;\n'.format(value.name) + main_body += ' value->{} = nullptr;\n'.format( + value.name + ) else: # Point the real struct's member pointer to the pointer decoder's memory. convert_const_cast_begin = '' @@ -274,8 +295,12 @@ def make_decode_invocation(self, name, value, preamble, main_body, epilogue): main_body += ' bytes_read += ValueDecoder::DecodeHandleIdValue({}, &(wrapper->{}));\n'.format( buffer_args, value.name ) - default_type = self.get_default_handle_atom_value(value.base_type) - main_body += ' value->{} = {};\n'.format(value.name, default_type) + default_type = self.get_default_handle_atom_value( + value.base_type + ) + main_body += ' value->{} = {};\n'.format( + value.name, default_type + ) elif self.is_generic_struct_handle_value(name, value.name): main_body += ' bytes_read += ValueDecoder::DecodeUInt64Value({}, &(wrapper->{}));\n'.format( buffer_args, value.name @@ -284,7 +309,9 @@ def make_decode_invocation(self, name, value, preamble, main_body, epilogue): elif value.bitfield_width: # Bit fields need to be read into a tempoaray and then assigned to the struct member. temp_param_name = 'temp_{}'.format(value.name) - main_body += ' {} {};\n'.format(value.base_type, temp_param_name) + main_body += ' {} {};\n'.format( + value.base_type, temp_param_name + ) main_body += ' bytes_read += ValueDecoder::Decode{}Value({}, &{});\n'.format( type_name, buffer_args, temp_param_name ) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_decoders_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_decoders_body_generator.py index 0aa0162f20..38d86ef503 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_decoders_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_struct_decoders_body_generator.py @@ -90,10 +90,6 @@ def beginFile(self, gen_opts): write('GFXRECON_BEGIN_NAMESPACE(gfxrecon)', file=self.outFile) write('GFXRECON_BEGIN_NAMESPACE(decode)', file=self.outFile) self.newline() - write( - 'size_t DecodePNextStruct(const uint8_t* buffer, size_t buffer_size, PNextNode** pNext);', - file=self.outFile - ) def endFile(self): """Method override.""" From 9f12fd0b07f122a29c731f73cd09004083374617 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 8 Nov 2024 16:57:16 -0500 Subject: [PATCH 21/32] codegen: Move decoder header generation into Khronos --- .../khronos_decoder_header_generator.py | 80 +++++++++++++++++++ .../vulkan_decoder_header_generator.py | 39 +-------- 2 files changed, 84 insertions(+), 35 deletions(-) create mode 100644 framework/generated/khronos_generators/khronos_decoder_header_generator.py diff --git a/framework/generated/khronos_generators/khronos_decoder_header_generator.py b/framework/generated/khronos_generators/khronos_decoder_header_generator.py new file mode 100644 index 0000000000..a027adadb1 --- /dev/null +++ b/framework/generated/khronos_generators/khronos_decoder_header_generator.py @@ -0,0 +1,80 @@ +#!/usr/bin/python3 -i +# +# Copyright (c) 2018 Valve Corporation +# Copyright (c) 2018-2024 LunarG, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import sys +from khronos_base_generator import write + + +class KhronosDecoderHeaderGenerator(): + """KhronosDecoderHeaderGenerator + Generates C++ member declarations for the Khronos-API specific Decoder class + responsible for decoding the appropriate Khronos API call parameter data. + """ + + def write_decoder_header_content(self): + api_data = self.get_api_data() + + write( + 'class {0}Decoder : public {0}DecoderBase'.format( + api_data.api_class_prefix + ), + file=self.outFile + ) + write('{', file=self.outFile) + write(' public:', file=self.outFile) + write( + ' {}Decoder() {{ }}\n'.format(api_data.api_class_prefix), + file=self.outFile + ) + write( + ' virtual ~{}Decoder() override {{ }}\n'.format( + api_data.api_class_prefix + ), + file=self.outFile + ) + write( + ' virtual void DecodeFunctionCall(format::ApiCallId call_id,', + file=self.outFile + ) + write( + ' const ApiCallInfo& call_info,', + file=self.outFile + ) + write( + ' const uint8_t* parameter_buffer,', + file=self.outFile + ) + write( + ' size_t buffer_size) override;\n', + file=self.outFile + ) + write(' private:', end='', file=self.outFile) + + for cmd in self.get_all_filtered_cmd_names(): + cmddef = '\n' + cmddef += ' size_t Decode_{}(const ApiCallInfo& call_info, const uint8_t* parameter_buffer, size_t buffer_size);'.format( + cmd + ) + write(cmddef, file=self.outFile) + + write('};', file=self.outFile) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_decoder_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_decoder_header_generator.py index a7059b3133..6f3647fd59 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_decoder_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_decoder_header_generator.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 -i # # Copyright (c) 2018 Valve Corporation -# Copyright (c) 2018 LunarG, Inc. +# Copyright (c) 2018-2024 LunarG, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to @@ -23,7 +23,7 @@ import sys from base_generator import BaseGenerator, BaseGeneratorOptions, write - +from khronos_decoder_header_generator import KhronosDecoderHeaderGenerator class VulkanDecoderHeaderGeneratorOptions(BaseGeneratorOptions): """Options for generating a C++ class declaration for Vulkan API parameter decoding.""" @@ -52,7 +52,7 @@ def __init__( ) -class VulkanDecoderHeaderGenerator(BaseGenerator): +class VulkanDecoderHeaderGenerator(BaseGenerator, KhronosDecoderHeaderGenerator): """VulkanDecoderHeaderGenerator - subclass of BaseGenerator. Generates C++ member declarations for the VulkanDecoder class responsible for decoding Vulkan API call parameter data. @@ -81,42 +81,11 @@ def beginFile(self, gen_opts): write('GFXRECON_BEGIN_NAMESPACE(gfxrecon)', file=self.outFile) write('GFXRECON_BEGIN_NAMESPACE(decode)', file=self.outFile) self.newline() - write( - 'class VulkanDecoder : public VulkanDecoderBase', - file=self.outFile - ) - write('{', file=self.outFile) - write(' public:', file=self.outFile) - write(' VulkanDecoder() { }\n', file=self.outFile) - write(' virtual ~VulkanDecoder() override { }\n', file=self.outFile) - write( - ' virtual void DecodeFunctionCall(format::ApiCallId call_id,', - file=self.outFile - ) - write( - ' const ApiCallInfo& call_info,', - file=self.outFile - ) - write( - ' const uint8_t* parameter_buffer,', - file=self.outFile - ) - write( - ' size_t buffer_size) override;\n', - file=self.outFile - ) - write(' private:', end='', file=self.outFile) def endFile(self): """Method override.""" - for cmd in self.get_all_filtered_cmd_names(): - cmddef = '\n' - cmddef += ' size_t Decode_{}(const ApiCallInfo& call_info, const uint8_t* parameter_buffer, size_t buffer_size);'.format( - cmd - ) - write(cmddef, file=self.outFile) + KhronosDecoderHeaderGenerator.write_decoder_header_content(self) - write('};', file=self.outFile) self.newline() write('GFXRECON_END_NAMESPACE(decode)', file=self.outFile) write('GFXRECON_END_NAMESPACE(gfxrecon)', file=self.outFile) From bde3b843c4c8735608389d383efca4ee688932e1 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Tue, 12 Nov 2024 13:39:01 -0500 Subject: [PATCH 22/32] codegen: Fix 64-bit flag detection in khronos --- .../generated/khronos_generators/khronos_base_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/generated/khronos_generators/khronos_base_generator.py b/framework/generated/khronos_generators/khronos_base_generator.py index 6375544900..2e42981cdf 100644 --- a/framework/generated/khronos_generators/khronos_base_generator.py +++ b/framework/generated/khronos_generators/khronos_base_generator.py @@ -709,7 +709,7 @@ def is_flags(self, base_type): # that is 64 bits wide. def is_64bit_flags(self, flag_type): if flag_type in self.flags_types: - if 'Flags64' in self.flags_types[flag_type]: + if self.flags_types[flag_type].endswith('Flags64'): return True return False From 0481acda722948bc249ea8e6ff9c77f3876a9809 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Tue, 12 Nov 2024 15:31:33 -0500 Subject: [PATCH 23/32] codegen: Fix flag types/enum conversion This actually exposed a bug where we were incorrectly handling an Arm flag type. --- .../generated_vulkan_enum_to_string.cpp | 25 +++++- .../generated_vulkan_enum_to_string.h | 4 +- .../khronos_base_generator.py | 86 ++++++++++--------- 3 files changed, 70 insertions(+), 45 deletions(-) diff --git a/framework/generated/generated_vulkan_enum_to_string.cpp b/framework/generated/generated_vulkan_enum_to_string.cpp index ed1a81b2df..49665b86b8 100644 --- a/framework/generated/generated_vulkan_enum_to_string.cpp +++ b/framework/generated/generated_vulkan_enum_to_string.cpp @@ -3591,7 +3591,7 @@ template <> std::string ToString(const VkPhysical return "Unhandled VkPhysicalDeviceLayeredApiKHR"; } -template <> std::string ToString(const VkPhysicalDeviceSchedulingControlsFlagBitsARM& value, ToStringFlags, uint32_t, uint32_t) +std::string VkPhysicalDeviceSchedulingControlsFlagBitsARMToString(const VkPhysicalDeviceSchedulingControlsFlagBitsARM value) { switch (value) { case VK_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_SHADER_CORE_COUNT_ARM: return "VK_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_SHADER_CORE_COUNT_ARM"; @@ -3600,9 +3600,28 @@ template <> std::string ToString( return "Unhandled VkPhysicalDeviceSchedulingControlsFlagBitsARM"; } -template <> std::string ToString(VkFlags vkFlags, ToStringFlags, uint32_t, uint32_t) +std::string VkPhysicalDeviceSchedulingControlsFlagsARMToString(VkFlags64 vkFlags) { - return BitmaskToString(vkFlags); + std::string str; + VkFlags64 index = 0U; + while (vkFlags) + { + if (vkFlags & 1U) + { + if (!str.empty()) + { + str += '|'; + } + str.append(VkPhysicalDeviceSchedulingControlsFlagBitsARMToString(static_cast(1U) << index)); + } + ++index; + vkFlags >>= 1U; + } + if (str.empty()) + { + str.append(VkPhysicalDeviceSchedulingControlsFlagBitsARMToString(0U)); + } + return str; } template <> std::string ToString(const VkPhysicalDeviceType& value, ToStringFlags, uint32_t, uint32_t) diff --git a/framework/generated/generated_vulkan_enum_to_string.h b/framework/generated/generated_vulkan_enum_to_string.h index 3c1d573089..9a67c2d0ce 100644 --- a/framework/generated/generated_vulkan_enum_to_string.h +++ b/framework/generated/generated_vulkan_enum_to_string.h @@ -302,8 +302,8 @@ template <> std::string ToString(const VkPerform template <> std::string ToString(const VkPerformanceParameterTypeINTEL& value, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize); template <> std::string ToString(const VkPerformanceValueTypeINTEL& value, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize); template <> std::string ToString(const VkPhysicalDeviceLayeredApiKHR& value, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize); -template <> std::string ToString(const VkPhysicalDeviceSchedulingControlsFlagBitsARM& value, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize); -template <> std::string ToString(VkFlags vkFlags, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize); +std::string VkPhysicalDeviceSchedulingControlsFlagBitsARMToString(const VkPhysicalDeviceSchedulingControlsFlagBitsARM value); +std::string VkPhysicalDeviceSchedulingControlsFlagsARMToString(VkFlags64 vkFlags); template <> std::string ToString(const VkPhysicalDeviceType& value, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize); template <> std::string ToString(const VkPipelineBindPoint& value, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize); template <> std::string ToString(const VkPipelineCacheCreateFlagBits& value, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize); diff --git a/framework/generated/khronos_generators/khronos_base_generator.py b/framework/generated/khronos_generators/khronos_base_generator.py index 2e42981cdf..d2beba7021 100644 --- a/framework/generated/khronos_generators/khronos_base_generator.py +++ b/framework/generated/khronos_generators/khronos_base_generator.py @@ -76,22 +76,18 @@ def remove_suffix(self: str, suffix: str, /) -> str: # It works for true enums and the 64 bit collections of static const variables # which are tied together only with a naming convention in the C header. def BitsEnumToFlagsTypedef(enum): - # if enum.endswith - flags = remove_suffix(enum, 'Bits') - if flags != enum: - flags = flags + 's' - return flags - flags = remove_suffix(enum, 'Bits2') - if flags != enum: - flags = flags + 's2' - return flags - # Gods preserve us from Bits 3, 4, 5, etc. - # It might have more extension suffix. - flags = remove_suffix(enum, 'Bits2KHR') - if flags != enum: - flags = flags + 's2KHR' - return flags - return flags + result = enum.find('FlagBits') + + # If we have a FlagBits type, strip off that, and save the extension + if result > 0: + trimmed_enum = enum[:result + 4] + extension = enum[result + 8:] + + # Add an s toe the type plus add back any extension + flag_type = trimmed_enum + 's' + extension + return flag_type + else: + return enum class ApiData(): """ApiData - Class to store various Khronos API data. @@ -376,7 +372,8 @@ def __init__( self.dispatchable_handle_names = set() # Set of current API's dispatchable handle typenames self.flags_types = dict() # Map of flags types self.flags_type_aliases = dict() # Map of flags type aliases - self.flags_enum_bits_types = dict() # Map of flags enum to bits type + self.flags_to_enum_bits = dict() # Map of flags to enum bits + self.enum_bits_to_flag = dict() # Map of enum bits to flag type self.enum_names = set() # Set of current API's enumeration typenames self.enumAliases = dict() # Map of enum names to aliases self.enumEnumerants = dict() # Map of enum names to enumerants @@ -718,9 +715,14 @@ def is_64bit_flags(self, flag_type): # Note, all 64 bit pseudo-enums represent flags since the only reason to go to # 64 bits is to allow more than 32 flags to be represented. def is_flags_enum_64bit(self, enum): - flag_type = BitsEnumToFlagsTypedef(enum) + flag_type = self.get_flags_type_from_enum(enum) return self.is_64bit_flags(flag_type) + def get_flags_type_from_enum(self, enum): + if enum in self.enum_bits_to_flag: + return self.enum_bits_to_flag[enum] + return BitsEnumToFlagsTypedef(enum) + def is_has_specific_key_word_in_type(self, value, key_word): if key_word in value.base_type: return True @@ -1059,7 +1061,10 @@ def genType(self, typeinfo, name, alias): if bittype is None: bittype = type_elem.get('bitvalues') if bittype is not None: - self.flags_enum_bits_types[bittype] = name + if bittype in self.enumAliases: + bittype = self.enumAliases[bittype] + self.flags_to_enum_bits[name] = bittype + self.enum_bits_to_flag[bittype] = name elif ( (category == "basetype") and ( @@ -1359,27 +1364,28 @@ def genGroup(self, groupinfo, group_name, alias): These are concatenated together with other types. """ OutputGenerator.genGroup(self, groupinfo, group_name, alias) - self.enum_names.add(group_name) - if not alias: - enumerants = dict() - for elem in groupinfo.elem: - supported = elem.get('supported') - is_supported = False - if not supported: - is_supported = True - else: - supported_list = supported.split(",") - for e in supported_list: - if e in self.SUPPORTED_SUBSETS: - is_supported = True - break - if is_supported: - name = elem.get('name') - if name and not elem.get('alias'): - enumerants[name] = elem.get('value') - self.enumEnumerants[group_name] = enumerants - else: - self.enumAliases[group_name] = alias + if group_name not in self.enum_names: + self.enum_names.add(group_name) + if not alias: + enumerants = dict() + for elem in groupinfo.elem: + supported = elem.get('supported') + is_supported = False + if not supported: + is_supported = True + else: + supported_list = supported.split(",") + for e in supported_list: + if e in self.SUPPORTED_SUBSETS: + is_supported = True + break + if is_supported: + name = elem.get('name') + if name and not elem.get('alias'): + enumerants[name] = elem.get('value') + self.enumEnumerants[group_name] = enumerants + else: + self.enumAliases[group_name] = alias def genEnum(self, enuminfo, name, alias): """Method override. From f7b150b2b9cd681798ec6a9330ae940ef2a2d96a Mon Sep 17 00:00:00 2001 From: Mark Young Date: Tue, 12 Nov 2024 15:37:23 -0500 Subject: [PATCH 24/32] codegen: Remove unnecessary methods We had 2 global methods that could be incorporated directly into the Khronos base class in a cleaner way. These were removed: BitsEnumToFlagsTypedef, removeSuffix --- .../khronos_base_generator.py | 46 ++++++++----------- .../vulkan_generators/base_generator.py | 2 +- .../vulkan_enum_to_string_body_generator.py | 4 +- .../vulkan_enum_to_string_header_generator.py | 2 +- 4 files changed, 21 insertions(+), 33 deletions(-) diff --git a/framework/generated/khronos_generators/khronos_base_generator.py b/framework/generated/khronos_generators/khronos_base_generator.py index d2beba7021..c74990d5e3 100644 --- a/framework/generated/khronos_generators/khronos_base_generator.py +++ b/framework/generated/khronos_generators/khronos_base_generator.py @@ -62,33 +62,6 @@ def make_re_string(list, default=None): return default -def remove_suffix(self: str, suffix: str, /) -> str: - # suffix='' should not call self[:-0]. - if suffix and self.endswith(suffix): - return self[:-len(suffix)] - else: - return self[:] - - -# Strip the "Bit" ending or near-ending from an enum representing a group of -# flag bits to give the name of the type (typedef of Flags or Flags64) used to -# hold a disjoint set of them. -# It works for true enums and the 64 bit collections of static const variables -# which are tied together only with a naming convention in the C header. -def BitsEnumToFlagsTypedef(enum): - result = enum.find('FlagBits') - - # If we have a FlagBits type, strip off that, and save the extension - if result > 0: - trimmed_enum = enum[:result + 4] - extension = enum[result + 8:] - - # Add an s toe the type plus add back any extension - flag_type = trimmed_enum + 's' + extension - return flag_type - else: - return enum - class ApiData(): """ApiData - Class to store various Khronos API data. @@ -721,7 +694,24 @@ def is_flags_enum_64bit(self, enum): def get_flags_type_from_enum(self, enum): if enum in self.enum_bits_to_flag: return self.enum_bits_to_flag[enum] - return BitsEnumToFlagsTypedef(enum) + + # If we don't already have one picked out, determine it + result = enum.find('FlagBits') + + # If we have a FlagBits type, strip off that, and save the extension + if result > 0: + trimmed_enum = enum[:result + 4] + extension = enum[result + 8:] + + # Add an s toe the type plus add back any extension + flag_type = trimmed_enum + 's' + extension + + if flag_type in self.flags_types: + self.enum_bits_to_flag[enum] = flag_type + + return flag_type + else: + return None def is_has_specific_key_word_in_type(self, value, key_word): if key_word in value.base_type: diff --git a/framework/generated/khronos_generators/vulkan_generators/base_generator.py b/framework/generated/khronos_generators/vulkan_generators/base_generator.py index 3682f24a32..aeaebd5f6c 100644 --- a/framework/generated/khronos_generators/vulkan_generators/base_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/base_generator.py @@ -43,7 +43,7 @@ import os,re,sys,json from collections import OrderedDict -from khronos_base_generator import (KhronosBaseGeneratorOptions, KhronosBaseGenerator, BitsEnumToFlagsTypedef, make_re_string, remove_suffix, ValueInfo, write) +from khronos_base_generator import (KhronosBaseGeneratorOptions, KhronosBaseGenerator, make_re_string, ValueInfo, write) from generator import (OutputGenerator, noneStr, regSortFeatures) from vkconventions import VulkanConventions diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_body_generator.py index 92df803ccf..591d79a063 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_body_generator.py @@ -173,9 +173,7 @@ def write_enum_to_string_body(self): body += '{{\n' body += ' return BitmaskToString<{0}>(vkFlags);\n' body += '}}\n' - write(body.format(enum, BitsEnumToFlagsTypedef(enum)), + write(body.format(enum, self.get_flags_type_from_enum(enum)), file=self.outFile) - # if self.is_flags_enum_64bit(enum): - # print(body.format(enum, BitsEnumToFlagsTypedef(enum))) # yapf: enable diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_header_generator.py index d36f04d612..bd849f4e04 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_header_generator.py @@ -129,5 +129,5 @@ def write_enum_to_string_header(self): body = 'template <> std::string ToString<{0}>(const {0}& value, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize);' if 'Bits' in enum: body += '\ntemplate <> std::string ToString<{0}>(VkFlags vkFlags, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize);' - write(body.format(enum, BitsEnumToFlagsTypedef(enum)), + write(body.format(enum, self.get_flags_type_from_enum(enum)), file=self.outFile) From 20eaf3ca362069da7b365d4865da9bff5e26683b Mon Sep 17 00:00:00 2001 From: Mark Young Date: Tue, 12 Nov 2024 15:40:42 -0500 Subject: [PATCH 25/32] codegen: Remove unnecessary lists in enum->string --- .../khronos_generators/khronos_base_generator.py | 1 - .../vulkan_enum_to_string_body_generator.py | 10 ---------- .../vulkan_enum_to_string_header_generator.py | 8 -------- 3 files changed, 19 deletions(-) diff --git a/framework/generated/khronos_generators/khronos_base_generator.py b/framework/generated/khronos_generators/khronos_base_generator.py index c74990d5e3..fac3d514f5 100644 --- a/framework/generated/khronos_generators/khronos_base_generator.py +++ b/framework/generated/khronos_generators/khronos_base_generator.py @@ -578,7 +578,6 @@ def is_struct(self, base_type): or (base_type in self.PLATFORM_STRUCTS) ): return True - return False def is_handle(self, base_type): """Check if handle. The subclass may override this method.""" diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_body_generator.py index 591d79a063..40bec737c1 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_body_generator.py @@ -71,14 +71,6 @@ def __init__( diag_file=diag_file ) - # Set of enums that have been processed since we'll encounter enums that are - # referenced by extensions multiple times. This list is prepopulated with - # enums that should be skipped. - self.processedEnums = { - 'VkAccessFlagBits2KHR', - 'VkPipelineStageFlagBits2KHR', - } - # Method override # yapf: disable def beginFile(self, genOpts): @@ -119,8 +111,6 @@ def write_enum_to_string_body(self): for enum in sorted(self.enum_names): if not enum in self.enumAliases: if self.is_flags_enum_64bit(enum): - # print(enum) - # body = 'std::string {0}ToString(const {0}& value, ToStringFlags, uint32_t, uint32_t)\n' # Since every caller needs to know exactly what it is calling, we may as well # dispense with the parameters that are always ignored: body = 'std::string {0}ToString(const {0} value)\n' diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_header_generator.py index bd849f4e04..c261f82687 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_header_generator.py @@ -66,14 +66,6 @@ def __init__( diag_file=diag_file ) - # Set of enums that have been processed since we'll encounter enums that are - # referenced by extensions multiple times. This list is prepopulated with - # enums that should be skipped. - self.processedEnums = { - 'VkAccessFlagBits2KHR', - 'VkPipelineStageFlagBits2KHR', - } - # Method override # yapf: disable def beginFile(self, genOpts): From 487f951d4fa5f37d76fc8b971f80816e793e3edb Mon Sep 17 00:00:00 2001 From: Mark Young Date: Tue, 12 Nov 2024 15:48:24 -0500 Subject: [PATCH 26/32] codegen: enum->json header use Khronos types --- .../vulkan_enum_to_json_header_generator.py | 38 +++++-------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_header_generator.py index e652309077..36eeadaa61 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_header_generator.py @@ -74,10 +74,6 @@ def __init__( # enums that should be skipped. self.processedEnums = set() - self.enumType = dict() - self.flagsType = dict() - self.flagBitsType = dict() - # Method override # yapf: disable def beginFile(self, genOpts): @@ -123,34 +119,16 @@ def need_feature_generation(self): return True return False - - def genGroup(self, groupinfo, group_name, alias): - BaseGenerator.genGroup(self, groupinfo, group_name, alias) - type_elem = groupinfo.elem - if type_elem.get('bitwidth') == '64': - self.enumType[group_name] = 'VkFlags64' - else: - self.enumType[group_name] = 'VkFlags' - - def genType(self, typeinfo, name, alias): - super().genType(typeinfo, name, alias) - if self.is_flags(name) and alias is None: - self.flagsType[name] = self.flags_types[name] - bittype = typeinfo.elem.get('requires') - if bittype is None: - bittype = typeinfo.elem.get('bitvalues') - if bittype is not None: - self.flagBitsType[bittype] = name - def make_decls(self): - for flag in sorted(self.flagsType): + for flag in sorted(self.flags_types): + if flag in self.flags_type_aliases: + continue body = 'struct {0}_t {{ }};' write(body.format(flag), file=self.outFile) - for enum in sorted(self.enum_names): if not enum in self.enumAliases: - if enum in self.enumType and self.enumType[enum] == 'VkFlags64': + if self.is_flags_enum_64bit(enum): body = 'struct {0}_t {{ }};' write(body.format(enum), file=self.outFile) @@ -159,12 +137,14 @@ def make_decls(self): if not enum in self.processedEnums and not enum in self.SKIP_ENUM: self.processedEnums.add(enum) if not enum in self.enumAliases: - if enum in self.enumType and self.enumType[enum] == 'VkFlags64': + if self.is_flags_enum_64bit(enum): body = 'void FieldToJson({0}_t, nlohmann::ordered_json& jdata, const {0}& value, const util::JsonOptions& options = util::JsonOptions());' else: body = 'void FieldToJson(nlohmann::ordered_json& jdata, const {0}& value, const util::JsonOptions& options = util::JsonOptions());' write(body.format(enum), file=self.outFile) - for flag in sorted(self.flagsType): + for flag in sorted(self.flags_types): + if flag in self.flags_type_aliases: + continue body = 'void FieldToJson({0}_t, nlohmann::ordered_json& jdata, const {1} flags, const util::JsonOptions& options = util::JsonOptions());' - write(body.format(flag, self.flagsType[flag]), file=self.outFile) + write(body.format(flag, self.flags_types[flag]), file=self.outFile) From ec242c3ef684a354fbb70cf1ff2dbbff57c5e4ae Mon Sep 17 00:00:00 2001 From: Mark Young Date: Tue, 12 Nov 2024 16:11:45 -0500 Subject: [PATCH 27/32] codegen: Add ability to go backwards enum->flags --- .../khronos_generators/khronos_base_generator.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/framework/generated/khronos_generators/khronos_base_generator.py b/framework/generated/khronos_generators/khronos_base_generator.py index fac3d514f5..2decd59544 100644 --- a/framework/generated/khronos_generators/khronos_base_generator.py +++ b/framework/generated/khronos_generators/khronos_base_generator.py @@ -706,12 +706,25 @@ def get_flags_type_from_enum(self, enum): flag_type = trimmed_enum + 's' + extension if flag_type in self.flags_types: - self.enum_bits_to_flag[enum] = flag_type + if flag_type not in self.enum_bits_to_flag: + self.enum_bits_to_flag[enum] = flag_type + if flag_type not in self.flags_to_enum_bits: + self.flags_to_enum_bits[flag_type] = enum return flag_type else: return None + def get_enum_from_flags_type(self, flag): + if flag in self.flags_to_enum_bits: + return self.flags_to_enum_bits[flag] + + enum = re.sub('FlagBit', '', flag) + if enum in self.enum_names: + return enum + else: + return None + def is_has_specific_key_word_in_type(self, value, key_word): if key_word in value.base_type: return True From 33808e65cbd714ebfa96a8ba1b82d5527aac7b0f Mon Sep 17 00:00:00 2001 From: Mark Young Date: Tue, 12 Nov 2024 16:14:14 -0500 Subject: [PATCH 28/32] codegen: Update enum->json body to use Khronos types --- .../vulkan_enum_to_json_body_generator.py | 41 +++++-------------- 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_body_generator.py index a0b9059c46..d10aa3fbea 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_body_generator.py @@ -75,9 +75,6 @@ def __init__( # referenced by extensions multiple times. This list is prepopulated with # enums that should be skipped. self.processedEnums = set() - self.enumType = dict() - self.flagsType = dict() - self.flagEnumBitsType = dict() # Method override # yapf: disable @@ -141,35 +138,15 @@ def need_feature_generation(self): if self.feature_struct_members: return True return False - - def genGroup(self, groupinfo, group_name, alias): - BaseGenerator.genGroup(self, groupinfo, group_name, alias) - type_elem = groupinfo.elem - if type_elem.get('bitwidth') == '64': - self.enumType[group_name] = 'VkFlags64' - else: - self.enumType[group_name] = 'VkFlags' - - - def genType(self, typeinfo, name, alias): - super().genType(typeinfo, name, alias) - if self.is_flags(name) and alias is None: - self.flagsType[name] = self.flags_types[name] - bittype = typeinfo.elem.get('requires') - if bittype is None: - bittype = typeinfo.elem.get('bitvalues') - if bittype is not None: - self.flagEnumBitsType[name] = bittype # # Performs C++ code generation for the feature. # yapf: disable def make_decls(self): for enum in sorted(self.enum_names): - if not enum in self.processedEnums and not enum in self.enumAliases and not enum in self.SKIP_ENUM and not enum in self.flagEnumBitsType: + if not enum in self.processedEnums and not enum in self.enumAliases and not enum in self.SKIP_ENUM: self.processedEnums.add(enum) - bitwidth = 'VkFlags' - if enum in self.enumType and self.enumType[enum] == 'VkFlags64': + if self.is_flags_enum_64bit(enum): body = 'void FieldToJson({0}_t, nlohmann::ordered_json& jdata, const {0}& value, const JsonOptions& options)\n' else: body = 'void FieldToJson(nlohmann::ordered_json& jdata, const {0}& value, const JsonOptions& options)\n' @@ -190,16 +167,20 @@ def make_decls(self): body += ' jdata = to_hex_fixed_width(value);\n' body += '}}\n' - body = body.format(enum, bitwidth) + body = body.format(enum) write(body, file=self.outFile) - for enum in sorted(self.flagsType): + for enum in sorted(self.flags_types): + if enum in self.flags_type_aliases: + continue + bittype = None - if enum in self.flagEnumBitsType: - bittype = self.flagEnumBitsType[enum] + if enum in self.flags_to_enum_bits: + bittype = self.flags_to_enum_bits[enum] + body = 'void FieldToJson({0}_t, nlohmann::ordered_json& jdata, const {1} flags, const JsonOptions& options)\n' body += '{{\n' - if bittype is not None and bittype in self.enum_names and len(self.enumEnumerants[bittype]): + if bittype is not None and len(self.enumEnumerants[bittype]): body += " if (!options.expand_flags)\n" body += " {{\n" body += " jdata = to_hex_fixed_width(flags);\n" From 34102163871937d98253729c3a42f550d37def02 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Tue, 12 Nov 2024 16:21:46 -0500 Subject: [PATCH 29/32] codegen: Move enum->json header into Khronos --- .../khronos_enum_to_json_header_generator.py | 65 +++++++++++++++++++ .../vulkan_enum_to_json_header_generator.py | 40 +----------- 2 files changed, 68 insertions(+), 37 deletions(-) create mode 100644 framework/generated/khronos_generators/khronos_enum_to_json_header_generator.py diff --git a/framework/generated/khronos_generators/khronos_enum_to_json_header_generator.py b/framework/generated/khronos_generators/khronos_enum_to_json_header_generator.py new file mode 100644 index 0000000000..adbccbd1f2 --- /dev/null +++ b/framework/generated/khronos_generators/khronos_enum_to_json_header_generator.py @@ -0,0 +1,65 @@ +#!/usr/bin/python3 -i +# +# Copyright (c) 2022-2023 LunarG, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import sys +from khronos_base_generator import write + + +# KhronosEnumToJsonHeaderGenerator +# Generates C++ functions for stringifying Khronos API enums. +class KhronosEnumToJsonHeaderGenerator(): + """Generate C++ functions to serialize Khronos enumaration to JSON""" + + def make_decls(self): + # Set of enums that have been processed since we'll encounter enums that are + # referenced by extensions multiple times. This list is prepopulated with + # enums that should be skipped. + processedEnums = set() + + for flag in sorted(self.flags_types): + if flag in self.flags_type_aliases: + continue + body = 'struct {0}_t {{ }};' + write(body.format(flag), file=self.outFile) + + for enum in sorted(self.enum_names): + if not enum in self.enumAliases: + if self.is_flags_enum_64bit(enum): + body = 'struct {0}_t {{ }};' + write(body.format(enum), file=self.outFile) + + self.newline() + for enum in sorted(self.enum_names): + if not enum in processedEnums and not enum in self.SKIP_ENUM: + processedEnums.add(enum) + if not enum in self.enumAliases: + if self.is_flags_enum_64bit(enum): + body = 'void FieldToJson({0}_t, nlohmann::ordered_json& jdata, const {0}& value, const util::JsonOptions& options = util::JsonOptions());' + else: + body = 'void FieldToJson(nlohmann::ordered_json& jdata, const {0}& value, const util::JsonOptions& options = util::JsonOptions());' + write(body.format(enum), file=self.outFile) + + for flag in sorted(self.flags_types): + if flag in self.flags_type_aliases: + continue + body = 'void FieldToJson({0}_t, nlohmann::ordered_json& jdata, const {1} flags, const util::JsonOptions& options = util::JsonOptions());' + write(body.format(flag, self.flags_types[flag]), file=self.outFile) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_header_generator.py index 36eeadaa61..afbde82b95 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_header_generator.py @@ -22,6 +22,7 @@ import sys from base_generator import * +from khronos_enum_to_json_header_generator import KhronosEnumToJsonHeaderGenerator from reformat_code import format_cpp_code class VulkanEnumToJsonHeaderGeneratorOptions(BaseGeneratorOptions): @@ -53,7 +54,7 @@ def __init__( # VulkanEnumToStringHeaderGenerator - subclass of BaseGenerator. # Generates C++ functions for stringifying Vulkan API enums. -class VulkanEnumToJsonHeaderGenerator(BaseGenerator): +class VulkanEnumToJsonHeaderGenerator(BaseGenerator, KhronosEnumToJsonHeaderGenerator): """Generate C++ functions to serialize Vulkan enumaration to JSON""" SKIP_ENUM = [ @@ -69,11 +70,6 @@ def __init__( diag_file=diag_file ) - # Set of enums that have been processed since we'll encounter enums that are - # referenced by extensions multiple times. This list is prepopulated with - # enums that should be skipped. - self.processedEnums = set() - # Method override # yapf: disable def beginFile(self, genOpts): @@ -99,7 +95,7 @@ def beginFile(self, genOpts): # yapf: disable def endFile(self): self.newline() - self.make_decls() + KhronosEnumToJsonHeaderGenerator.make_decls(self) self.newline() body = format_cpp_code(''' @@ -118,33 +114,3 @@ def need_feature_generation(self): if self.feature_struct_members: return True return False - - def make_decls(self): - for flag in sorted(self.flags_types): - if flag in self.flags_type_aliases: - continue - body = 'struct {0}_t {{ }};' - write(body.format(flag), file=self.outFile) - - for enum in sorted(self.enum_names): - if not enum in self.enumAliases: - if self.is_flags_enum_64bit(enum): - body = 'struct {0}_t {{ }};' - write(body.format(enum), file=self.outFile) - - self.newline() - for enum in sorted(self.enum_names): - if not enum in self.processedEnums and not enum in self.SKIP_ENUM: - self.processedEnums.add(enum) - if not enum in self.enumAliases: - if self.is_flags_enum_64bit(enum): - body = 'void FieldToJson({0}_t, nlohmann::ordered_json& jdata, const {0}& value, const util::JsonOptions& options = util::JsonOptions());' - else: - body = 'void FieldToJson(nlohmann::ordered_json& jdata, const {0}& value, const util::JsonOptions& options = util::JsonOptions());' - write(body.format(enum), file=self.outFile) - - for flag in sorted(self.flags_types): - if flag in self.flags_type_aliases: - continue - body = 'void FieldToJson({0}_t, nlohmann::ordered_json& jdata, const {1} flags, const util::JsonOptions& options = util::JsonOptions());' - write(body.format(flag, self.flags_types[flag]), file=self.outFile) From f9640f036003e37b339eaf0a14992a01583936d4 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Tue, 12 Nov 2024 16:32:20 -0500 Subject: [PATCH 30/32] codegen: Move enum->json body to Khronos files --- .../khronos_enum_to_json_body_generator.py | 143 ++++++++++++++++++ .../vulkan_enum_to_json_body_generator.py | 104 +------------ 2 files changed, 148 insertions(+), 99 deletions(-) create mode 100644 framework/generated/khronos_generators/khronos_enum_to_json_body_generator.py diff --git a/framework/generated/khronos_generators/khronos_enum_to_json_body_generator.py b/framework/generated/khronos_generators/khronos_enum_to_json_body_generator.py new file mode 100644 index 0000000000..b92ca1ef40 --- /dev/null +++ b/framework/generated/khronos_generators/khronos_enum_to_json_body_generator.py @@ -0,0 +1,143 @@ +#!/usr/bin/python3 -i +# +# Copyright (c) 2022-2024 LunarG, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import sys, textwrap +from khronos_base_generator import write +from reformat_code import format_cpp_code + + +# KhronosEnumToJsonBodyGenerator +# Generates C++ functions for stringifying Khronos API enums. +class KhronosEnumToJsonBodyGenerator(): + """Generate C++ functions to serialize Khronos enumaration to JSON""" + + def make_decls(self): + body = format_cpp_code( + ''' + using util::JsonOptions; + using util::to_hex_fixed_width; + + template + std::string ExpandFlags(TFlags flags, ToStringFunctionType toString) + { + if (flags == 0) + { + return to_hex_fixed_width(flags); + } + uint32_t bit_number = 0; + bool first = true; + std::ostringstream ostr; + while (flags != 0) + { + if (flags & 1) + { + if (!first) ostr << "|"; + ostr << toString((flags & 1) << bit_number); + first = false; + } + bit_number++; + flags = flags >> 1; + } + return ostr.str(); + } + ''' + ) + write(body, file=self.outFile) + self.newline() + self.newline() + + # Set of enums that have been processed since we'll encounter enums that are + # referenced by extensions multiple times. This list is prepopulated with + # enums that should be skipped. + processedEnums = set() + + for enum in sorted(self.enum_names): + if not enum in self.processedEnums and not enum in self.enumAliases and not enum in self.SKIP_ENUM: + self.processedEnums.add(enum) + + if self.is_flags_enum_64bit(enum): + body = 'void FieldToJson({0}_t, nlohmann::ordered_json& jdata, const {0}& value, const JsonOptions& options)\n' + else: + body = 'void FieldToJson(nlohmann::ordered_json& jdata, const {0}& value, const JsonOptions& options)\n' + body += '{{\n' + if len(self.enumEnumerants[enum]): + body += ' switch (value) {{\n' + for enumerant in self.enumEnumerants[enum]: + body += textwrap.indent( + prefix=' ', + text=textwrap.dedent( + '''\ + case {0}: + jdata = "{0}"; + break; + '''.format(enumerant) + ) + ) + body += ' default:\n' + body += ' jdata = to_hex_fixed_width(value);\n' + body += ' break;\n' + body += ' }}\n' + else: + body += ' jdata = to_hex_fixed_width(value);\n' + + body += '}}\n' + body = body.format(enum) + write(body, file=self.outFile) + + for enum in sorted(self.flags_types): + if enum in self.flags_type_aliases: + continue + + bittype = None + if enum in self.flags_to_enum_bits: + bittype = self.flags_to_enum_bits[enum] + + body = 'void FieldToJson({0}_t, nlohmann::ordered_json& jdata, const {1} flags, const JsonOptions& options)\n' + body += '{{\n' + if bittype is not None and len(self.enumEnumerants[bittype]): + body += " if (!options.expand_flags)\n" + body += " {{\n" + body += " jdata = to_hex_fixed_width(flags);\n" + body += " return;\n" + body += " }}\n" + body += " jdata = ExpandFlags(flags, []({1} flags)\n" + body += " {{\n" + body += ' switch (flags)\n' + body += ' {{\n' + for enumerant in self.enumEnumerants[bittype]: + body += textwrap.indent( + prefix=' ', + text=textwrap.dedent( + '''\ + case {0}: + return std::string("{0}"); + '''.format(enumerant) + ) + ) + body += ' }}\n' + body += ' return to_hex_fixed_width(flags);\n' + body += ' }});\n' + else: + body += ' jdata = to_hex_fixed_width(flags);\n' + + body += '}}\n' + write(body.format(enum, self.flags_types[enum]), file=self.outFile) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_body_generator.py index d10aa3fbea..91afab291b 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_json_body_generator.py @@ -20,9 +20,9 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -import sys, textwrap -from pickle import NONE +import sys from base_generator import * +from khronos_enum_to_json_body_generator import KhronosEnumToJsonBodyGenerator from reformat_code import format_cpp_code @@ -55,7 +55,7 @@ def __init__( # VulkanEnumToStringBodyGenerator - subclass of BaseGenerator. # Generates C++ functions for stringifying Vulkan API enums. -class VulkanEnumToJsonBodyGenerator(BaseGenerator): +class VulkanEnumToJsonBodyGenerator(BaseGenerator, KhronosEnumToJsonBodyGenerator): """Generate C++ functions for Vulkan FieldToJson() functions""" SKIP_ENUM = [ @@ -86,42 +86,15 @@ def beginFile(self, genOpts): GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(decode) - - using util::JsonOptions; - using util::to_hex_fixed_width; - - template - std::string ExpandFlags(TFlags flags, ToStringFunctionType toString) - { - if (flags == 0) - { - return to_hex_fixed_width(flags); - } - uint32_t bit_number = 0; - bool first = true; - std::ostringstream ostr; - while (flags != 0) - { - if (flags & 1) - { - if (!first) ostr << "|"; - ostr << toString((flags & 1) << bit_number); - first = false; - } - bit_number++; - flags = flags >> 1; - } - return ostr.str(); - } ''') write(body, file=self.outFile) + self.newline() # yapf: enable # Method override # yapf: disable def endFile(self): - write('\n', file=self.outFile) - self.make_decls() + KhronosEnumToJsonBodyGenerator.make_decls(self) body = format_cpp_code(''' GFXRECON_END_NAMESPACE(decode) GFXRECON_END_NAMESPACE(gfxrecon) @@ -138,70 +111,3 @@ def need_feature_generation(self): if self.feature_struct_members: return True return False - # - # Performs C++ code generation for the feature. - # yapf: disable - def make_decls(self): - for enum in sorted(self.enum_names): - if not enum in self.processedEnums and not enum in self.enumAliases and not enum in self.SKIP_ENUM: - self.processedEnums.add(enum) - - if self.is_flags_enum_64bit(enum): - body = 'void FieldToJson({0}_t, nlohmann::ordered_json& jdata, const {0}& value, const JsonOptions& options)\n' - else: - body = 'void FieldToJson(nlohmann::ordered_json& jdata, const {0}& value, const JsonOptions& options)\n' - body += '{{\n' - if len(self.enumEnumerants[enum]): - body += ' switch (value) {{\n' - for enumerant in self.enumEnumerants[enum]: - body += textwrap.indent(prefix=' ', text=textwrap.dedent('''\ - case {0}: - jdata = "{0}"; - break; - '''.format(enumerant))) - body += ' default:\n' - body += ' jdata = to_hex_fixed_width(value);\n' - body += ' break;\n' - body += ' }}\n' - else: - body += ' jdata = to_hex_fixed_width(value);\n' - - body += '}}\n' - body = body.format(enum) - write(body, file=self.outFile) - - for enum in sorted(self.flags_types): - if enum in self.flags_type_aliases: - continue - - bittype = None - if enum in self.flags_to_enum_bits: - bittype = self.flags_to_enum_bits[enum] - - body = 'void FieldToJson({0}_t, nlohmann::ordered_json& jdata, const {1} flags, const JsonOptions& options)\n' - body += '{{\n' - if bittype is not None and len(self.enumEnumerants[bittype]): - body += " if (!options.expand_flags)\n" - body += " {{\n" - body += " jdata = to_hex_fixed_width(flags);\n" - body += " return;\n" - body += " }}\n" - body += " jdata = ExpandFlags(flags, []({1} flags)\n" - body += " {{\n" - body += ' switch (flags)\n' - body += ' {{\n' - for enumerant in self.enumEnumerants[bittype]: - body += textwrap.indent(prefix=' ', text=textwrap.dedent('''\ - case {0}: - return std::string("{0}"); - '''.format(enumerant))) - body += ' }}\n' - body += ' return to_hex_fixed_width(flags);\n' - body += ' }});\n' - else: - body += ' jdata = to_hex_fixed_width(flags);\n' - - body += '}}\n' - write(body.format(enum, self.flags_types[enum]), file=self.outFile) - - # yapf: enable From f84b8c18d4c776e24ac2596082d01125528e7976 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Tue, 12 Nov 2024 16:56:07 -0500 Subject: [PATCH 31/32] codegen: Move enum->string header code to Khronos --- ...khronos_enum_to_string_header_generator.py | 45 +++++++++++++++++++ .../vulkan_enum_to_string_header_generator.py | 20 ++------- 2 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 framework/generated/khronos_generators/khronos_enum_to_string_header_generator.py diff --git a/framework/generated/khronos_generators/khronos_enum_to_string_header_generator.py b/framework/generated/khronos_generators/khronos_enum_to_string_header_generator.py new file mode 100644 index 0000000000..7e49930019 --- /dev/null +++ b/framework/generated/khronos_generators/khronos_enum_to_string_header_generator.py @@ -0,0 +1,45 @@ +#!/usr/bin/python3 -i +# +# Copyright (c) 2021 LunarG, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import os, re, sys, inspect +from khronos_base_generator import write + + +# KhronosEnumToStringHeaderGenerator +# Generates C++ functions for stringifying Khronos API enums. +class KhronosEnumToStringHeaderGenerator(): + """Generate C++ functions for Khronos ToString() functions""" + + def write_enum_to_string_header(self): + for enum in sorted(self.enum_names): + if not enum in self.enumAliases: + if self.is_flags_enum_64bit(enum): + body = 'std::string {0}ToString(const {0} value);' + body += '\nstd::string {1}ToString(VkFlags64 vkFlags);' + else: + body = 'template <> std::string ToString<{0}>(const {0}& value, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize);' + if 'Bits' in enum: + body += '\ntemplate <> std::string ToString<{0}>(VkFlags vkFlags, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize);' + write( + body.format(enum, self.get_flags_type_from_enum(enum)), + file=self.outFile + ) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_header_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_header_generator.py index c261f82687..cbb4e01f0a 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_header_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_header_generator.py @@ -22,6 +22,7 @@ import os, re, sys, inspect from base_generator import * +from khronos_enum_to_string_header_generator import KhronosEnumToStringHeaderGenerator class VulkanEnumToStringHeaderGeneratorOptions(BaseGeneratorOptions): @@ -53,7 +54,7 @@ def __init__( # VulkanEnumToStringHeaderGenerator - subclass of BaseGenerator. # Generates C++ functions for stringifying Vulkan API enums. -class VulkanEnumToStringHeaderGenerator(BaseGenerator): +class VulkanEnumToStringHeaderGenerator(BaseGenerator, KhronosEnumToStringHeaderGenerator): """Generate C++ functions for Vulkan ToString() functions""" def __init__( @@ -90,7 +91,7 @@ def beginFile(self, genOpts): # Method override # yapf: disable def endFile(self): - self.write_enum_to_string_header() + KhronosEnumToStringHeaderGenerator.write_enum_to_string_header(self) body = inspect.cleandoc(''' GFXRECON_END_NAMESPACE(util) @@ -108,18 +109,3 @@ def need_feature_generation(self): if self.feature_struct_members: return True return False - - # - # Performs C++ code generation for the enum to string header. - def write_enum_to_string_header(self): - for enum in sorted(self.enum_names): - if not enum in self.enumAliases: - if self.is_flags_enum_64bit(enum): - body = 'std::string {0}ToString(const {0} value);' - body += '\nstd::string {1}ToString(VkFlags64 vkFlags);' - else: - body = 'template <> std::string ToString<{0}>(const {0}& value, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize);' - if 'Bits' in enum: - body += '\ntemplate <> std::string ToString<{0}>(VkFlags vkFlags, ToStringFlags toStringFlags, uint32_t tabCount, uint32_t tabSize);' - write(body.format(enum, self.get_flags_type_from_enum(enum)), - file=self.outFile) From f6f044f93b132f484f4d618438ced1eaf6bfd996 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Tue, 12 Nov 2024 17:00:15 -0500 Subject: [PATCH 32/32] codegen: Move enum->string body code to Khronos --- .../khronos_enum_to_string_body_generator.py | 92 +++++++++++++++++++ .../vulkan_enum_to_string_body_generator.py | 71 +------------- 2 files changed, 96 insertions(+), 67 deletions(-) create mode 100644 framework/generated/khronos_generators/khronos_enum_to_string_body_generator.py diff --git a/framework/generated/khronos_generators/khronos_enum_to_string_body_generator.py b/framework/generated/khronos_generators/khronos_enum_to_string_body_generator.py new file mode 100644 index 0000000000..e662d18491 --- /dev/null +++ b/framework/generated/khronos_generators/khronos_enum_to_string_body_generator.py @@ -0,0 +1,92 @@ +#!/usr/bin/python3 -i +# +# Copyright (c) 2021-2024 LunarG, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import sys +from khronos_base_generator import write + + +# KhronosEnumToStringBodyGenerator +# Generates C++ functions for stringifying Khronos API enums. +class KhronosEnumToStringBodyGenerator(): + """Generate C++ functions for Khronos ToString() functions""" + + def write_enum_to_string_body(self): + for enum in sorted(self.enum_names): + if not enum in self.enumAliases: + if self.is_flags_enum_64bit(enum): + # Since every caller needs to know exactly what it is calling, we may as well + # dispense with the parameters that are always ignored: + body = 'std::string {0}ToString(const {0} value)\n' + else: + body = 'template <> std::string ToString<{0}>(const {0}& value, ToStringFlags, uint32_t, uint32_t)\n' + body += '{{\n' + enumerants = self.enumEnumerants[enum] + if len(enumerants): + body += ' switch (value) {{\n' + for enumerant in enumerants: + body += ' case {0}: return "{0}";\n'.format( + enumerant + ) + body += ' default: break;\n' + body += ' }}\n' + body += ' return "Unhandled {0}";\n' + body += '}}\n' + if 'Bits' in enum: + if self.is_flags_enum_64bit(enum): + body += '\nstd::string {1}ToString(VkFlags64 vkFlags)\n' + body += '{{\n' + body += ' std::string str;\n' + body += ' VkFlags64 index = 0U;\n' + body += ' while (vkFlags)\n' + body += ' {{\n' + body += ' if (vkFlags & 1U)\n' + body += ' {{\n' + body += ' if (!str.empty())\n' + body += ' {{\n' + body += ' str += \'|\';\n' + body += ' }}\n' + body += ' str.append({0}ToString(static_cast<{0}>(1U) << index));\n' + body += ' }}\n' + body += ' ++index;\n' + body += ' vkFlags >>= 1U;\n' + body += ' }}\n' + body += ' if (str.empty())\n' + body += ' {{\n' + body += ' str.append({0}ToString(0U));\n' + body += ' }}\n' + body += ' return str;\n' + body += '}}\n' + else: + # Original version(these are never actually being called which is part of issue #620): + body += '\ntemplate <> std::string ToString<{0}>(VkFlags vkFlags, ToStringFlags, uint32_t, uint32_t)\n' + # Simpler, non-template version that matches the 64 bit version above. Changing + # to these signatures actually compiles fine, showing the originals were never + # called anywhere. Leaving this commented-out but ready for the PR that fixes + # issue #620 to use. + # body += '\nstd::string {1}ToString(VkFlags vkFlags)\n' + body += '{{\n' + body += ' return BitmaskToString<{0}>(vkFlags);\n' + body += '}}\n' + write( + body.format(enum, self.get_flags_type_from_enum(enum)), + file=self.outFile + ) diff --git a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_body_generator.py b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_body_generator.py index 40bec737c1..5ec1dd8573 100644 --- a/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_body_generator.py +++ b/framework/generated/khronos_generators/vulkan_generators/vulkan_enum_to_string_body_generator.py @@ -20,11 +20,10 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -import os -import re import sys import inspect from base_generator import * +from khronos_enum_to_string_body_generator import KhronosEnumToStringBodyGenerator class VulkanEnumToStringBodyGeneratorOptions(BaseGeneratorOptions): @@ -58,7 +57,7 @@ def __init__( # VulkanEnumToStringBodyGenerator - subclass of BaseGenerator. # Generates C++ functions for stringifying Vulkan API enums. -class VulkanEnumToStringBodyGenerator(BaseGenerator): +class VulkanEnumToStringBodyGenerator(BaseGenerator, KhronosEnumToStringBodyGenerator): """Generate C++ functions for Vulkan ToString() functions""" def __init__( @@ -87,7 +86,8 @@ def beginFile(self, genOpts): # Method override # yapf: disable def endFile(self): - self.write_enum_to_string_body() + KhronosEnumToStringBodyGenerator.write_enum_to_string_body(self) + body = inspect.cleandoc(''' GFXRECON_END_NAMESPACE(util) GFXRECON_END_NAMESPACE(gfxrecon) @@ -104,66 +104,3 @@ def need_feature_generation(self): if self.feature_struct_members: return True return False - - # Performs C++ code generation for the enum to string body. - # yapf: disable - def write_enum_to_string_body(self): - for enum in sorted(self.enum_names): - if not enum in self.enumAliases: - if self.is_flags_enum_64bit(enum): - # Since every caller needs to know exactly what it is calling, we may as well - # dispense with the parameters that are always ignored: - body = 'std::string {0}ToString(const {0} value)\n' - else: - body = 'template <> std::string ToString<{0}>(const {0}& value, ToStringFlags, uint32_t, uint32_t)\n' - body += '{{\n' - enumerants = self.enumEnumerants[enum] - if len(enumerants): - body += ' switch (value) {{\n' - for enumerant in enumerants: - body += ' case {0}: return "{0}";\n'.format( - enumerant) - body += ' default: break;\n' - body += ' }}\n' - body += ' return "Unhandled {0}";\n' - body += '}}\n' - if 'Bits' in enum: - if self.is_flags_enum_64bit(enum): - body += '\nstd::string {1}ToString(VkFlags64 vkFlags)\n' - body += '{{\n' - body += ' std::string str;\n' - body += ' VkFlags64 index = 0U;\n' - body += ' while (vkFlags)\n' - body += ' {{\n' - body += ' if (vkFlags & 1U)\n' - body += ' {{\n' - body += ' if (!str.empty())\n' - body += ' {{\n' - body += ' str += \'|\';\n' - body += ' }}\n' - body += ' str.append({0}ToString(static_cast<{0}>(1U) << index));\n' - body += ' }}\n' - body += ' ++index;\n' - body += ' vkFlags >>= 1U;\n' - body += ' }}\n' - body += ' if (str.empty())\n' - body += ' {{\n' - body += ' str.append({0}ToString(0U));\n' - body += ' }}\n' - body += ' return str;\n' - body += '}}\n' - else: - # Original version(these are never actually being called which is part of issue #620): - body += '\ntemplate <> std::string ToString<{0}>(VkFlags vkFlags, ToStringFlags, uint32_t, uint32_t)\n' - # Simpler, non-template version that matches the 64 bit version above. Changing - # to these signatures actually compiles fine, showing the originals were never - # called anywhere. Leaving this commented-out but ready for the PR that fixes - # issue #620 to use. - # body += '\nstd::string {1}ToString(VkFlags vkFlags)\n' - body += '{{\n' - body += ' return BitmaskToString<{0}>(vkFlags);\n' - body += '}}\n' - write(body.format(enum, self.get_flags_type_from_enum(enum)), - file=self.outFile) - - # yapf: enable