Memory leak fix for SamplingRoutine cache

- The SamplingRoutine cache is now owned by the Device and
  has the same lifetime as the device, which means it gets
  released when the device gets released.
- Added a utility class, SamplingRoutineCache, to contain
  the cache and release all routine entries upon destruction.
- Added a pointer to the current device in the sampler object
  in order to retrieve it during sampling, in order to access
  the routine cache
- The cache is now internally an LRUCache, so it can't cache
  a large quantity of routines and take up a lot of memory.

Bug b/129523279 b/137649247 b/137524292 chromium:971325

Change-Id: If4ff1fbc87962355d0a281b9d0acace4316a02b8
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/32688
Tested-by: Alexis Hétu <sugoi@google.com>
Presubmit-Ready: Alexis Hétu <sugoi@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Vulkan/VkDevice.cpp b/src/Vulkan/VkDevice.cpp
index 6b918cd..435985c 100644
--- a/src/Vulkan/VkDevice.cpp
+++ b/src/Vulkan/VkDevice.cpp
@@ -36,6 +36,22 @@
 namespace vk
 {
 
+rr::Routine* Device::SamplingRoutineCache::query(const vk::Device::SamplingRoutineCache::Key& key) const
+{
+	return cache.query(hash(key));
+}
+
+void Device::SamplingRoutineCache::add(const vk::Device::SamplingRoutineCache::Key& key, rr::Routine* routine)
+{
+	ASSERT(routine);
+	cache.add(hash(key), routine);
+}
+
+std::size_t Device::SamplingRoutineCache::hash(const vk::Device::SamplingRoutineCache::Key &key) const
+{
+	return (key.instruction << 16) ^ (key.sampler << 8) ^ key.imageView;
+}
+
 Device::Device(const VkDeviceCreateInfo* pCreateInfo, void* mem, PhysicalDevice *physicalDevice, const VkPhysicalDeviceFeatures *enabledFeatures)
 	: physicalDevice(physicalDevice),
 	  queues(reinterpret_cast<Queue*>(mem)),
@@ -72,7 +88,7 @@
 	}
 
 	// FIXME (b/119409619): use an allocator here so we can control all memory allocations
-	blitter = new sw::Blitter();
+	blitter.reset(new sw::Blitter());
 }
 
 void Device::destroy(const VkAllocationCallbacks* pAllocator)
@@ -83,8 +99,6 @@
 	}
 
 	vk::deallocate(queues, pAllocator);
-
-	delete blitter;
 }
 
 size_t Device::ComputeRequiredAllocationSize(const VkDeviceCreateInfo* pCreateInfo)
@@ -212,7 +226,7 @@
 {
 	for(uint32_t i = 0; i < descriptorWriteCount; i++)
 	{
-		DescriptorSetLayout::WriteDescriptorSet(pDescriptorWrites[i]);
+		DescriptorSetLayout::WriteDescriptorSet(this, pDescriptorWrites[i]);
 	}
 
 	for(uint32_t i = 0; i < descriptorCopyCount; i++)
@@ -221,4 +235,18 @@
 	}
 }
 
+Device::SamplingRoutineCache* Device::getSamplingRoutineCache()
+{
+	if(!samplingRoutineCache.get())
+	{
+		samplingRoutineCache.reset(new SamplingRoutineCache());
+	}
+	return samplingRoutineCache.get();
+}
+
+std::mutex& Device::getSamplingRoutineCacheMutex()
+{
+	return samplingRoutineCacheMutex;
+}
+
 } // namespace vk