Move Blitter ownership from Image to Device

The blitter has a cache which can allow us to reuse already used
routines, so it should be kept in a central location. For that
reason, the blitter ownership was moved from the Image object to
the Device object.

Bug b/117974925

Change-Id: I825853c381dcbc04701b1d9e7dfa376108294221
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/25728
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Vulkan/VkDevice.cpp b/src/Vulkan/VkDevice.cpp
index 60e13f1..7891784 100644
--- a/src/Vulkan/VkDevice.cpp
+++ b/src/Vulkan/VkDevice.cpp
@@ -18,6 +18,7 @@
 #include "VkDebug.hpp"
 #include "VkDescriptorSetLayout.hpp"
 #include "VkQueue.hpp"
+#include "Device/Blitter.hpp"
 
 #include <new> // Must #include this to use "placement new"
 
@@ -50,6 +51,8 @@
 		// "The ppEnabledLayerNames and enabledLayerCount members of VkDeviceCreateInfo are deprecated and their values must be ignored by implementations."
 		UNIMPLEMENTED();   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
 	}
+
+	blitter = new sw::Blitter();
 }
 
 void Device::destroy(const VkAllocationCallbacks* pAllocator)
@@ -60,6 +63,8 @@
 	}
 
 	vk::deallocate(queues, pAllocator);
+
+	delete blitter;
 }
 
 size_t Device::ComputeRequiredAllocationSize(const Device::CreateInfo* info)
diff --git a/src/Vulkan/VkDevice.hpp b/src/Vulkan/VkDevice.hpp
index 24e0923..ae096f2 100644
--- a/src/Vulkan/VkDevice.hpp
+++ b/src/Vulkan/VkDevice.hpp
@@ -17,6 +17,11 @@
 
 #include "VkObject.hpp"
 
+namespace sw
+{
+	class Blitter;
+};
+
 namespace vk
 {
 
@@ -46,11 +51,13 @@
 	VkPhysicalDevice 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;
 	Queue* queues = nullptr;
 	uint32_t queueCount = 0;
+	sw::Blitter* blitter = nullptr;
 };
 
 using DispatchableDevice = DispatchableObject<Device, VkDevice>;
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index 463a8f7..22819f4 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -14,6 +14,7 @@
 
 #include "VkDeviceMemory.hpp"
 #include "VkBuffer.hpp"
+#include "VkDevice.hpp"
 #include "VkImage.hpp"
 #include "Device/Blitter.hpp"
 #include "Device/Surface.hpp"
@@ -41,18 +42,17 @@
 namespace vk
 {
 
-Image::Image(const VkImageCreateInfo* pCreateInfo, void* mem) :
-	flags(pCreateInfo->flags),
-	imageType(pCreateInfo->imageType),
-	format(pCreateInfo->format),
-	extent(pCreateInfo->extent),
-	mipLevels(pCreateInfo->mipLevels),
-	arrayLayers(pCreateInfo->arrayLayers),
-	samples(pCreateInfo->samples),
-	tiling(pCreateInfo->tiling)
+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)
 {
-	blitter = new sw::Blitter();
-
 	if (samples != VK_SAMPLE_COUNT_1_BIT)
 	{
 		UNIMPLEMENTED("Multisample images not yet supported");
@@ -61,10 +61,9 @@
 
 void Image::destroy(const VkAllocationCallbacks* pAllocator)
 {
-	delete blitter;
 }
 
-size_t Image::ComputeRequiredAllocationSize(const VkImageCreateInfo* pCreateInfo)
+size_t Image::ComputeRequiredAllocationSize(const Image::CreateInfo* pCreateInfo)
 {
 	return 0;
 }
@@ -495,7 +494,7 @@
 
 	for(int i = 0; i < numSlices; i++)
 	{
-		blitter->blit(srcSurface, sRect, dstSurface, dRect,
+		device->getBlitter()->blit(srcSurface, sRect, dstSurface, dRect,
 		              {filter != VK_FILTER_NEAREST, srcAspect == VK_IMAGE_ASPECT_STENCIL_BIT, false});
 		sRect.slice++;
 		dRect.slice++;
@@ -547,7 +546,7 @@
 			{
 				const sw::SliceRect dRect(0, 0, mipLevelExtent.width, mipLevelExtent.height, s);
 				sw::Surface* surface = asSurface(aspect, mipLevel, layer);
-				blitter->clear(pixelData, format, surface, dRect, 0xF);
+				device->getBlitter()->clear(pixelData, format, surface, dRect, 0xF);
 				delete surface;
 			}
 		}
@@ -574,7 +573,7 @@
 		{
 			dRect.slice = s;
 			sw::Surface* surface = asSurface(aspect, 0, layer);
-			blitter->clear(pixelData, format, surface, dRect, 0xF);
+			device->getBlitter()->clear(pixelData, format, surface, dRect, 0xF);
 			delete surface;
 		}
 	}
diff --git a/src/Vulkan/VkImage.hpp b/src/Vulkan/VkImage.hpp
index d3a77cd..17a9ce8 100644
--- a/src/Vulkan/VkImage.hpp
+++ b/src/Vulkan/VkImage.hpp
@@ -19,23 +19,29 @@
 
 namespace sw
 {
-	class Blitter;
 	class Surface;
 };
 
 namespace vk
 {
 
+class Device;
 class DeviceMemory;
 
 class Image : public Object<Image, VkImage>
 {
 public:
-	Image(const VkImageCreateInfo* pCreateInfo, void* mem);
+	struct CreateInfo
+	{
+		const VkImageCreateInfo* pCreateInfo;
+		const VkDevice device;
+	};
+
+	Image(const CreateInfo* pCreateInfo, void* mem);
 	~Image() = delete;
 	void destroy(const VkAllocationCallbacks* pAllocator);
 
-	static size_t ComputeRequiredAllocationSize(const VkImageCreateInfo* pCreateInfo);
+	static size_t ComputeRequiredAllocationSize(const CreateInfo* pCreateInfo);
 
 	const VkMemoryRequirements getMemoryRequirements() const;
 	void getSubresourceLayout(const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) const;
@@ -77,6 +83,7 @@
 	void clear(void* pixelData, VkFormat format, const VkImageSubresourceRange& subresourceRange, VkImageAspectFlagBits aspect);
 	void clear(void* pixelData, VkFormat format, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange, VkImageAspectFlagBits aspect);
 
+	const Device *const      device = nullptr;
 	DeviceMemory*            deviceMemory = nullptr;
 	VkDeviceSize             memoryOffset = 0;
 	VkImageCreateFlags       flags = 0;
@@ -87,7 +94,6 @@
 	uint32_t                 arrayLayers = 0;
 	VkSampleCountFlagBits    samples = VK_SAMPLE_COUNT_1_BIT;
 	VkImageTiling            tiling = VK_IMAGE_TILING_OPTIMAL;
-	sw::Blitter*             blitter = nullptr;
 };
 
 static inline Image* Cast(VkImage object)
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 26ac1d8..9f23143 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -906,7 +906,13 @@
 		UNIMPLEMENTED();
 	}
 
-	return vk::Image::Create(pAllocator, pCreateInfo, pImage);
+	vk::Image::CreateInfo imageCreateInfo =
+	{
+		pCreateInfo,
+		device
+	};
+
+	return vk::Image::Create(pAllocator, &imageCreateInfo, pImage);
 }
 
 VKAPI_ATTR void VKAPI_CALL vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator)