Add helper to find an extended struct in pNext chain

Refactoring change only

Bug: b/245568070
Change-Id: I0e8720bf2e5ff935c37e19f830d72974de04bb65
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/68068
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Presubmit-Ready: Shahbaz Youssefi <syoussefi@google.com>
Tested-by: Shahbaz Youssefi <syoussefi@google.com>
Commit-Queue: Shahbaz Youssefi <syoussefi@google.com>
diff --git a/src/Device/Context.cpp b/src/Device/Context.cpp
index 84fc868..a338198 100644
--- a/src/Device/Context.cpp
+++ b/src/Device/Context.cpp
@@ -624,41 +624,32 @@
 			// depthAttachmentFormat and stencilAttachmentFormat are VK_FORMAT_UNDEFINED. If a graphics pipeline
 			// is created with a valid VkRenderPass, parameters of this structure are ignored.
 
-			const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
-			while(extensionCreateInfo)
+			const auto *renderingCreateInfo = GetExtendedStruct<VkPipelineRenderingCreateInfo>(pCreateInfo->pNext, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO);
+			if(renderingCreateInfo)
 			{
-				if(extensionCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO)
+				if((renderingCreateInfo->depthAttachmentFormat != VK_FORMAT_UNDEFINED) ||
+				   (renderingCreateInfo->stencilAttachmentFormat != VK_FORMAT_UNDEFINED))
 				{
-					const VkPipelineRenderingCreateInfo *renderingCreateInfo = reinterpret_cast<const VkPipelineRenderingCreateInfo *>(extensionCreateInfo);
+					// If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment
+					// shader state, and either of VkPipelineRenderingCreateInfo::depthAttachmentFormat
+					// or VkPipelineRenderingCreateInfo::stencilAttachmentFormat are not
+					// VK_FORMAT_UNDEFINED, pDepthStencilState must be a valid pointer to a valid
+					// VkPipelineDepthStencilStateCreateInfo structure
+					ASSERT(depthStencilState);
 
-					if((renderingCreateInfo->depthAttachmentFormat != VK_FORMAT_UNDEFINED) ||
-					   (renderingCreateInfo->stencilAttachmentFormat != VK_FORMAT_UNDEFINED))
-					{
-						// If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment
-						// shader state, and either of VkPipelineRenderingCreateInfo::depthAttachmentFormat
-						// or VkPipelineRenderingCreateInfo::stencilAttachmentFormat are not
-						// VK_FORMAT_UNDEFINED, pDepthStencilState must be a valid pointer to a valid
-						// VkPipelineDepthStencilStateCreateInfo structure
-						ASSERT(depthStencilState);
-
-						setDepthStencilState(depthStencilState);
-					}
-
-					if(renderingCreateInfo->colorAttachmentCount > 0)
-					{
-						// If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment
-						// output interface state, and VkPipelineRenderingCreateInfo::colorAttachmentCount
-						// is not equal to 0, pColorBlendState must be a valid pointer to a valid
-						// VkPipelineColorBlendStateCreateInfo structure
-						ASSERT(colorBlendState);
-
-						setColorBlendState(colorBlendState);
-					}
-
-					break;
+					setDepthStencilState(depthStencilState);
 				}
 
-				extensionCreateInfo = extensionCreateInfo->pNext;
+				if(renderingCreateInfo->colorAttachmentCount > 0)
+				{
+					// If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment
+					// output interface state, and VkPipelineRenderingCreateInfo::colorAttachmentCount
+					// is not equal to 0, pColorBlendState must be a valid pointer to a valid
+					// VkPipelineColorBlendStateCreateInfo structure
+					ASSERT(colorBlendState);
+
+					setColorBlendState(colorBlendState);
+				}
 			}
 		}
 	}
diff --git a/src/Vulkan/VkDescriptorSetLayout.cpp b/src/Vulkan/VkDescriptorSetLayout.cpp
index 5fe5a40..41f39ad 100644
--- a/src/Vulkan/VkDescriptorSetLayout.cpp
+++ b/src/Vulkan/VkDescriptorSetLayout.cpp
@@ -625,26 +625,20 @@
 
 	case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
 		{
-			auto extInfo = reinterpret_cast<VkBaseInStructure const *>(writeDescriptorSet.pNext);
-			while(extInfo)
-			{
-				if(extInfo->sType == VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK)
-				{
-					// "The descriptorCount of VkDescriptorSetLayoutBinding thus provides the total
-					//  number of bytes a particular binding with an inline uniform block descriptor
-					//  type can hold, while the srcArrayElement, dstArrayElement, and descriptorCount
-					//  members of VkWriteDescriptorSet, VkCopyDescriptorSet, and
-					//  VkDescriptorUpdateTemplateEntry (where applicable) specify the byte offset and
-					//  number of bytes to write/copy to the binding's backing store. Additionally,
-					//  the stride member of VkDescriptorUpdateTemplateEntry is ignored for inline
-					//  uniform blocks and a default value of one is used, meaning that the data to
-					//  update inline uniform block bindings with must be contiguous in memory."
-					ptr = reinterpret_cast<const VkWriteDescriptorSetInlineUniformBlock *>(extInfo)->pData;
-					e.stride = 1;
-					break;
-				}
-				extInfo = extInfo->pNext;
-			}
+			const auto *inlineBlock = GetExtendedStruct<VkWriteDescriptorSetInlineUniformBlock>(writeDescriptorSet.pNext, VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK);
+			ASSERT(inlineBlock);
+
+			// "The descriptorCount of VkDescriptorSetLayoutBinding thus provides the total
+			//  number of bytes a particular binding with an inline uniform block descriptor
+			//  type can hold, while the srcArrayElement, dstArrayElement, and descriptorCount
+			//  members of VkWriteDescriptorSet, VkCopyDescriptorSet, and
+			//  VkDescriptorUpdateTemplateEntry (where applicable) specify the byte offset and
+			//  number of bytes to write/copy to the binding's backing store. Additionally,
+			//  the stride member of VkDescriptorUpdateTemplateEntry is ignored for inline
+			//  uniform blocks and a default value of one is used, meaning that the data to
+			//  update inline uniform block bindings with must be contiguous in memory."
+			ptr = inlineBlock->pData;
+			e.stride = 1;
 		}
 		break;
 
diff --git a/src/Vulkan/VkDevice.cpp b/src/Vulkan/VkDevice.cpp
index caed186..a21d4b3 100644
--- a/src/Vulkan/VkDevice.cpp
+++ b/src/Vulkan/VkDevice.cpp
@@ -170,18 +170,10 @@
 #endif  // ENABLE_VK_DEBUGGER
 
 #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT
-	const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
-	while(extensionCreateInfo)
+	const auto *deviceMemoryReportCreateInfo = GetExtendedStruct<VkDeviceDeviceMemoryReportCreateInfoEXT>(pCreateInfo->pNext, VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT);
+	if(deviceMemoryReportCreateInfo && deviceMemoryReportCreateInfo->pfnUserCallback != nullptr)
 	{
-		if(extensionCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT)
-		{
-			auto deviceMemoryReportCreateInfo = reinterpret_cast<const VkDeviceDeviceMemoryReportCreateInfoEXT *>(pCreateInfo->pNext);
-			if(deviceMemoryReportCreateInfo->pfnUserCallback != nullptr)
-			{
-				deviceMemoryReportCallbacks.emplace_back(deviceMemoryReportCreateInfo->pfnUserCallback, deviceMemoryReportCreateInfo->pUserData);
-			}
-		}
-		extensionCreateInfo = extensionCreateInfo->pNext;
+		deviceMemoryReportCallbacks.emplace_back(deviceMemoryReportCreateInfo->pfnUserCallback, deviceMemoryReportCreateInfo->pUserData);
 	}
 #endif  // SWIFTSHADER_DEVICE_MEMORY_REPORT
 }
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index 4bb9135..43b8e0f 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -198,14 +198,10 @@
 		decompressedImage = new(mem) Image(&compressedImageCreateInfo, nullptr, device);
 	}
 
-	const auto *nextInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
-	for(; nextInfo != nullptr; nextInfo = nextInfo->pNext)
+	const auto *externalInfo = GetExtendedStruct<VkExternalMemoryImageCreateInfo>(pCreateInfo->pNext, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
+	if(externalInfo)
 	{
-		if(nextInfo->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO)
-		{
-			const auto *externalInfo = reinterpret_cast<const VkExternalMemoryImageCreateInfo *>(nextInfo);
-			supportedExternalMemoryHandleTypes = externalInfo->handleTypes;
-		}
+		supportedExternalMemoryHandleTypes = externalInfo->handleTypes;
 	}
 }
 
diff --git a/src/Vulkan/VkObject.hpp b/src/Vulkan/VkObject.hpp
index 73301fb..7a5d120 100644
--- a/src/Vulkan/VkObject.hpp
+++ b/src/Vulkan/VkObject.hpp
@@ -164,6 +164,23 @@
 	}
 };
 
+template <typename T>
+const T *GetExtendedStruct(const void *pNext, VkStructureType sType)
+{
+	const VkBaseInStructure *extendedStruct = reinterpret_cast<const VkBaseInStructure *>(pNext);
+	while(extendedStruct)
+	{
+		if(extendedStruct->sType == sType)
+		{
+			return reinterpret_cast<const T *>(extendedStruct);
+		}
+
+		extendedStruct = extendedStruct->pNext;
+	}
+
+	return nullptr;
+}
+
 }  // namespace vk
 
 #endif  // VK_OBJECT_HPP_
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index 5b7e597..66a3c21 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -192,18 +192,7 @@
 private:
 	static const VkPipelineCreationFeedbackCreateInfo *GetPipelineCreationFeedback(const void *pNext)
 	{
-		const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(pNext);
-		while(extensionCreateInfo)
-		{
-			if(extensionCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO)
-			{
-				return reinterpret_cast<const VkPipelineCreationFeedbackCreateInfo *>(extensionCreateInfo);
-			}
-
-			extensionCreateInfo = extensionCreateInfo->pNext;
-		}
-
-		return nullptr;
+		return vk::GetExtendedStruct<VkPipelineCreationFeedbackCreateInfo>(pNext, VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO);
 	}
 
 	void pipelineCreationBegins()