Allow additional info to be passed to object's Create functions

This is particularly useful for passing extension info structures to the
object's constructor.

Bug: b/132437008
Bug: b/116336664
Change-Id: I10592f5ddeb8efa52f34ebd4dfd14150b6964eab
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31612
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Vulkan/VkDevice.cpp b/src/Vulkan/VkDevice.cpp
index 9717931..aa86cc6 100644
--- a/src/Vulkan/VkDevice.cpp
+++ b/src/Vulkan/VkDevice.cpp
@@ -36,12 +36,11 @@
 namespace vk
 {
 
-Device::Device(const Device::CreateInfo* info, void* mem)
-	: physicalDevice(info->pPhysicalDevice),
+Device::Device(const VkDeviceCreateInfo* pCreateInfo, void* mem, PhysicalDevice *physicalDevice)
+	: physicalDevice(physicalDevice),
 	  queues(reinterpret_cast<Queue*>(mem)),
-	  enabledExtensionCount(info->pCreateInfo->enabledExtensionCount)
+	  enabledExtensionCount(pCreateInfo->enabledExtensionCount)
 {
-	const auto* pCreateInfo = info->pCreateInfo;
 	for(uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++)
 	{
 		const VkDeviceQueueCreateInfo& queueCreateInfo = pCreateInfo->pQueueCreateInfos[i];
@@ -87,15 +86,15 @@
 	delete blitter;
 }
 
-size_t Device::ComputeRequiredAllocationSize(const Device::CreateInfo* info)
+size_t Device::ComputeRequiredAllocationSize(const VkDeviceCreateInfo* pCreateInfo)
 {
 	uint32_t queueCount = 0;
-	for(uint32_t i = 0; i < info->pCreateInfo->queueCreateInfoCount; i++)
+	for(uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++)
 	{
-		queueCount += info->pCreateInfo->pQueueCreateInfos[i].queueCount;
+		queueCount += pCreateInfo->pQueueCreateInfos[i].queueCount;
 	}
 
-	return (sizeof(Queue) * queueCount) + (info->pCreateInfo->enabledExtensionCount * sizeof(ExtensionName));
+	return (sizeof(Queue) * queueCount) + (pCreateInfo->enabledExtensionCount * sizeof(ExtensionName));
 }
 
 bool Device::hasExtension(const char* extensionName) const
diff --git a/src/Vulkan/VkDevice.hpp b/src/Vulkan/VkDevice.hpp
index 3ce466d..46c4bdf 100644
--- a/src/Vulkan/VkDevice.hpp
+++ b/src/Vulkan/VkDevice.hpp
@@ -25,23 +25,18 @@
 namespace vk
 {
 
+class PhysicalDevice;
 class Queue;
 
 class Device
 {
 public:
-	struct CreateInfo
-	{
-		const VkDeviceCreateInfo* pCreateInfo;
-		VkPhysicalDevice pPhysicalDevice;
-	};
-
 	static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_DEVICE; }
 
-	Device(const CreateInfo* info, void* mem);
+	Device(const VkDeviceCreateInfo* pCreateInfo, void* mem, PhysicalDevice *physicalDevice);
 	void destroy(const VkAllocationCallbacks* pAllocator);
 
-	static size_t ComputeRequiredAllocationSize(const CreateInfo* info);
+	static size_t ComputeRequiredAllocationSize(const VkDeviceCreateInfo* pCreateInfo);
 
 	bool hasExtension(const char* extensionName) const;
 	VkQueue getQueue(uint32_t queueFamilyIndex, uint32_t queueIndex) const;
@@ -49,13 +44,13 @@
 	VkResult waitIdle();
 	void getDescriptorSetLayoutSupport(const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
 	                                   VkDescriptorSetLayoutSupport* pSupport) const;
-	VkPhysicalDevice getPhysicalDevice() const { return physicalDevice; }
+	PhysicalDevice *getPhysicalDevice() const { return physicalDevice; }
 	void updateDescriptorSets(uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites,
 	                          uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies);
 	sw::Blitter* getBlitter() const { return blitter; }
 
 private:
-	VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
+	PhysicalDevice *physicalDevice = nullptr;
 	Queue* queues = nullptr;
 	uint32_t queueCount = 0;
 	sw::Blitter* blitter = nullptr;
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index d56070b..1d434cb 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -53,24 +53,23 @@
 namespace vk
 {
 
-Image::Image(const Image::CreateInfo* pCreateInfo, void* mem) :
-	device(Cast(pCreateInfo->device)),
-	flags(pCreateInfo->pCreateInfo->flags),
-	imageType(pCreateInfo->pCreateInfo->imageType),
-	format(pCreateInfo->pCreateInfo->format),
-	extent(pCreateInfo->pCreateInfo->extent),
-	mipLevels(pCreateInfo->pCreateInfo->mipLevels),
-	arrayLayers(pCreateInfo->pCreateInfo->arrayLayers),
-	samples(pCreateInfo->pCreateInfo->samples),
-	tiling(pCreateInfo->pCreateInfo->tiling),
-	usage(pCreateInfo->pCreateInfo->usage)
+Image::Image(const VkImageCreateInfo* pCreateInfo, void* mem, Device *device) :
+	device(device),
+	flags(pCreateInfo->flags),
+	imageType(pCreateInfo->imageType),
+	format(pCreateInfo->format),
+	extent(pCreateInfo->extent),
+	mipLevels(pCreateInfo->mipLevels),
+	arrayLayers(pCreateInfo->arrayLayers),
+	samples(pCreateInfo->samples),
+	tiling(pCreateInfo->tiling),
+	usage(pCreateInfo->usage)
 {
 	if(format.isCompressed())
 	{
-		VkImageCreateInfo imageCreateInfo = *(pCreateInfo->pCreateInfo);
-		imageCreateInfo.format = format.getDecompressedFormat();
-		Image::CreateInfo createInfo = { &imageCreateInfo, pCreateInfo->device };
-		decompressedImage = new (mem) Image(&createInfo, nullptr);
+		VkImageCreateInfo compressedImageCreateInfo = *pCreateInfo;
+		compressedImageCreateInfo.format = format.getDecompressedFormat();
+		decompressedImage = new (mem) Image(&compressedImageCreateInfo, nullptr, device);
 	}
 }
 
@@ -82,9 +81,9 @@
 	}
 }
 
-size_t Image::ComputeRequiredAllocationSize(const Image::CreateInfo* pCreateInfo)
+size_t Image::ComputeRequiredAllocationSize(const VkImageCreateInfo* pCreateInfo)
 {
-	return Format(pCreateInfo->pCreateInfo->format).isCompressed() ? sizeof(Image) : 0;
+	return Format(pCreateInfo->format).isCompressed() ? sizeof(Image) : 0;
 }
 
 const VkMemoryRequirements Image::getMemoryRequirements() const
diff --git a/src/Vulkan/VkImage.hpp b/src/Vulkan/VkImage.hpp
index 24c48fe..7356419 100644
--- a/src/Vulkan/VkImage.hpp
+++ b/src/Vulkan/VkImage.hpp
@@ -27,16 +27,10 @@
 class Image : public Object<Image, VkImage>
 {
 public:
-	struct CreateInfo
-	{
-		const VkImageCreateInfo* pCreateInfo;
-		const VkDevice device;
-	};
-
-	Image(const CreateInfo* pCreateInfo, void* mem);
+	Image(const VkImageCreateInfo* pCreateInfo, void* mem, Device *device);
 	void destroy(const VkAllocationCallbacks* pAllocator);
 
-	static size_t ComputeRequiredAllocationSize(const CreateInfo* pCreateInfo);
+	static size_t ComputeRequiredAllocationSize(const VkImageCreateInfo* pCreateInfo);
 
 	const VkMemoryRequirements getMemoryRequirements() const;
 	void getSubresourceLayout(const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) const;
diff --git a/src/Vulkan/VkInstance.cpp b/src/Vulkan/VkInstance.cpp
index c0b9bba..e4079b8 100644
--- a/src/Vulkan/VkInstance.cpp
+++ b/src/Vulkan/VkInstance.cpp
@@ -18,13 +18,10 @@
 namespace vk
 {
 
-Instance::Instance(const CreateInfo* pCreateInfo, void* mem)
+Instance::Instance(const VkInstanceCreateInfo* pCreateInfo, void* mem, VkPhysicalDevice physicalDevice)
+	: physicalDevice(physicalDevice),
+	  physicalDeviceCount(physicalDevice ? 1 : 0)
 {
-	if(pCreateInfo->pPhysicalDevice)
-	{
-		physicalDevice = pCreateInfo->pPhysicalDevice;
-		physicalDeviceCount = 1;
-	}
 }
 
 void Instance::destroy(const VkAllocationCallbacks* pAllocator)
diff --git a/src/Vulkan/VkInstance.hpp b/src/Vulkan/VkInstance.hpp
index 30c48b9..f63dc3b 100644
--- a/src/Vulkan/VkInstance.hpp
+++ b/src/Vulkan/VkInstance.hpp
@@ -23,28 +23,23 @@
 class Instance
 {
 public:
-	struct CreateInfo
-	{
-		const VkInstanceCreateInfo* pCreateInfo;
-		VkPhysicalDevice pPhysicalDevice;
-	};
-
 	static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE; }
 
-	Instance(const CreateInfo* pCreateInfo, void* mem);
+	Instance(const VkInstanceCreateInfo* pCreateInfo, void* mem, VkPhysicalDevice physicalDevice);
 	void destroy(const VkAllocationCallbacks* pAllocator);
 
-	static size_t ComputeRequiredAllocationSize(const CreateInfo*) { return 0; }
+	static size_t ComputeRequiredAllocationSize(const VkInstanceCreateInfo*) { return 0; }
 
 	uint32_t getPhysicalDeviceCount() const;
 	void getPhysicalDevices(uint32_t pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) const;
 	uint32_t getPhysicalDeviceGroupCount() const;
 	void getPhysicalDeviceGroups(uint32_t pPhysicalDeviceGroupCount,
                                  VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) const;
+
 private:
-	uint32_t physicalDeviceCount = 0;
 	VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
-	uint32_t physicalDeviceGroupCount = 1;
+	const uint32_t physicalDeviceCount = 0;
+	const uint32_t physicalDeviceGroupCount = 1;
 };
 
 using DispatchableInstance = DispatchableObject<Instance, VkInstance>;
diff --git a/src/Vulkan/VkObject.hpp b/src/Vulkan/VkObject.hpp
index 0fdcc23..b8a9800 100644
--- a/src/Vulkan/VkObject.hpp
+++ b/src/Vulkan/VkObject.hpp
@@ -28,8 +28,8 @@
 // For use in the placement new to make it verbose that we're allocating an object using device memory
 static constexpr VkAllocationCallbacks* DEVICE_MEMORY = nullptr;
 
-template<typename T, typename VkT, typename CreateInfo>
-static VkResult Create(const VkAllocationCallbacks* pAllocator, const CreateInfo* pCreateInfo, VkT* outObject)
+template<typename T, typename VkT, typename CreateInfo, typename... ExtendedInfo>
+static VkResult Create(const VkAllocationCallbacks* pAllocator, const CreateInfo* pCreateInfo, VkT* outObject, ExtendedInfo... extendedInfo)
 {
 	*outObject = VK_NULL_HANDLE;
 
@@ -51,7 +51,7 @@
 		return VK_ERROR_OUT_OF_HOST_MEMORY;
 	}
 
-	auto object = new (objectMemory) T(pCreateInfo, memory);
+	auto object = new (objectMemory) T(pCreateInfo, memory, extendedInfo...);
 
 	if(!object)
 	{
@@ -75,10 +75,10 @@
 
 	void destroy(const VkAllocationCallbacks* pAllocator) {} // Method defined by objects to delete their content, if necessary
 
-	template<typename CreateInfo>
-	static VkResult Create(const VkAllocationCallbacks* pAllocator, const CreateInfo* pCreateInfo, VkT* outObject)
+	template<typename CreateInfo, typename... ExtendedInfo>
+	static VkResult Create(const VkAllocationCallbacks* pAllocator, const CreateInfo* pCreateInfo, VkT* outObject, ExtendedInfo... extendedInfo)
 	{
-		return vk::Create<T, VkT, CreateInfo>(pAllocator, pCreateInfo, outObject);
+		return vk::Create<T, VkT, CreateInfo>(pAllocator, pCreateInfo, outObject, extendedInfo...);
 	}
 
 	static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_OBJECT; }
@@ -102,6 +102,7 @@
 	VK_LOADER_DATA loaderData = { ICD_LOADER_MAGIC };
 
 	T object;
+
 public:
 	static constexpr VkSystemAllocationScope GetAllocationScope() { return T::GetAllocationScope(); }
 
@@ -110,6 +111,8 @@
 	{
 	}
 
+	~DispatchableObject() = delete;
+
 	void destroy(const VkAllocationCallbacks* pAllocator)
 	{
 		object.destroy(pAllocator);
@@ -121,10 +124,10 @@
 		ASSERT(false);
 	}
 
-	template<typename CreateInfo>
-	static VkResult Create(const VkAllocationCallbacks* pAllocator, const CreateInfo* pCreateInfo, VkT* outObject)
+	template<typename CreateInfo, typename... ExtendedInfo>
+	static VkResult Create(const VkAllocationCallbacks* pAllocator, const CreateInfo* pCreateInfo, VkT* outObject, ExtendedInfo... extendedInfo)
 	{
-		return vk::Create<DispatchableObject<T, VkT>, VkT, CreateInfo>(pAllocator, pCreateInfo, outObject);
+		return vk::Create<DispatchableObject<T, VkT>, VkT, CreateInfo>(pAllocator, pCreateInfo, outObject, extendedInfo...);
 	}
 
 	template<typename CreateInfo>
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index b07f68a..fc75a01 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -177,13 +177,7 @@
 		return result;
 	}
 
-	vk::Instance::CreateInfo info =
-	{
-		pCreateInfo,
-		physicalDevice
-	};
-
-	result = vk::DispatchableInstance::Create(pAllocator, &info, pInstance);
+	result = vk::DispatchableInstance::Create(pAllocator, pCreateInfo, pInstance, physicalDevice);
 	if(result != VK_SUCCESS)
 	{
 		vk::destroy(physicalDevice, pAllocator);
@@ -479,13 +473,7 @@
 		(void)queueFamilyPropertyCount; // Silence unused variable warning
 	}
 
-	vk::Device::CreateInfo deviceCreateInfo =
-	{
-		pCreateInfo,
-		physicalDevice
-	};
-
-	return vk::DispatchableDevice::Create(pAllocator, &deviceCreateInfo, pDevice);
+	return vk::DispatchableDevice::Create(pAllocator, pCreateInfo, pDevice, vk::Cast(physicalDevice));
 }
 
 VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator)
@@ -687,7 +675,7 @@
 	auto memory = vk::Cast(pMemory);
 
 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
-	const auto& memoryProperties = vk::Cast(vk::Cast(pDevice)->getPhysicalDevice())->getMemoryProperties();
+	const auto& memoryProperties = vk::Cast(pDevice)->getPhysicalDevice()->getMemoryProperties();
 	uint32_t typeIndex = memory->getMemoryTypeIndex();
 	ASSERT(typeIndex < memoryProperties.memoryTypeCount);
 	ASSERT(memoryProperties.memoryTypes[typeIndex].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT);
@@ -997,13 +985,7 @@
 		extensionCreateInfo = extensionCreateInfo->pNext;
 	}
 
-	vk::Image::CreateInfo imageCreateInfo =
-	{
-		pCreateInfo,
-		device
-	};
-
-	VkResult result = vk::Image::Create(pAllocator, &imageCreateInfo, pImage);
+	VkResult result = vk::Image::Create(pAllocator, pCreateInfo, pImage, vk::Cast(device));
 
 #ifdef __ANDROID__
 	if (swapchainImage)
@@ -1479,7 +1461,7 @@
 			// pViewMask is a 32 bit value. If maxFramebufferLayers > 32, it's impossible
 			// for pViewMask to contain a bit at an illegal position
 			// Note: Verify pViewMask values instead if we hit this assert
-			ASSERT(vk::Cast(vk::Cast(device)->getPhysicalDevice())->getProperties().limits.maxFramebufferLayers >= 32);
+			ASSERT(vk::Cast(device)->getPhysicalDevice()->getProperties().limits.maxFramebufferLayers >= 32);
 		}
 		break;
 		default: