Allocation failure fix

Intentional allocation failure tests were crashing on Linux,
because the object's constructor was called even when the
allocator returned nullptr. Separated the allocation from
the construction to fix the issue.

Bug b/116336664

Change-Id: I7a5d4e957ec27f37a96b795a7f17aacebb240fe9
Tests: dEQP-VK.api.device_init.create_instance_device_intentional_alloc_fail
Tests: dEQP-VK.api.object_management.alloc_callback_fail.*
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/28948
Tested-by: Alexis Hétu <sugoi@google.com>
Presubmit-Ready: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index fa6f3d8..34be31f 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -1104,6 +1104,7 @@
 template<typename T, typename... Args>
 void CommandBuffer::addCommand(Args&&... args)
 {
+	// FIXME (b/119409619): use an allocator here so we can control all memory allocations
 	commands->push_back(std::unique_ptr<T>(new T(std::forward<Args>(args)...)));
 }
 
diff --git a/src/Vulkan/VkCommandPool.cpp b/src/Vulkan/VkCommandPool.cpp
index 85c5738..0a7dc1b 100644
--- a/src/Vulkan/VkCommandPool.cpp
+++ b/src/Vulkan/VkCommandPool.cpp
@@ -16,6 +16,7 @@
 #include "VkCommandBuffer.hpp"
 #include "VkDestroy.h"
 #include <algorithm>
+#include <new>
 
 namespace vk
 {
@@ -23,7 +24,10 @@
 CommandPool::CommandPool(const VkCommandPoolCreateInfo* pCreateInfo, void* mem)
 {
 	// FIXME (b/119409619): use an allocator here so we can control all memory allocations
-	commandBuffers = new std::set<VkCommandBuffer>();
+	void* deviceMemory = vk::allocate(sizeof(std::set<VkCommandBuffer>), REQUIRED_MEMORY_ALIGNMENT,
+	                                  DEVICE_MEMORY, GetAllocationScope());
+	ASSERT(deviceMemory);
+	commandBuffers = new (deviceMemory) std::set<VkCommandBuffer>();
 }
 
 void CommandPool::destroy(const VkAllocationCallbacks* pAllocator)
@@ -35,7 +39,7 @@
 	}
 
 	// FIXME (b/119409619): use an allocator here so we can control all memory allocations
-	delete commandBuffers;
+	vk::deallocate(commandBuffers, DEVICE_MEMORY);
 }
 
 size_t CommandPool::ComputeRequiredAllocationSize(const VkCommandPoolCreateInfo* pCreateInfo)
@@ -47,7 +51,11 @@
 {
 	for(uint32_t i = 0; i < commandBufferCount; i++)
 	{
-		DispatchableCommandBuffer* commandBuffer = new (DEVICE_MEMORY) DispatchableCommandBuffer(level);
+		// FIXME (b/119409619): use an allocator here so we can control all memory allocations
+		void* deviceMemory = vk::allocate(sizeof(DispatchableCommandBuffer), REQUIRED_MEMORY_ALIGNMENT,
+		                                  DEVICE_MEMORY, DispatchableCommandBuffer::GetAllocationScope());
+		ASSERT(deviceMemory);
+		DispatchableCommandBuffer* commandBuffer = new (deviceMemory) DispatchableCommandBuffer(level);
 		if(commandBuffer)
 		{
 			pCommandBuffers[i] = *commandBuffer;
diff --git a/src/Vulkan/VkDescriptorPool.cpp b/src/Vulkan/VkDescriptorPool.cpp
index a05b5a2..28907bb 100644
--- a/src/Vulkan/VkDescriptorPool.cpp
+++ b/src/Vulkan/VkDescriptorPool.cpp
@@ -47,6 +47,7 @@
 
 VkResult DescriptorPool::allocateSets(uint32_t descriptorSetCount, const VkDescriptorSetLayout* pSetLayouts, VkDescriptorSet* pDescriptorSets)
 {
+	// FIXME (b/119409619): use an allocator here so we can control all memory allocations
 	std::unique_ptr<size_t[]> layoutSizes(new size_t[descriptorSetCount]);
 	for(uint32_t i = 0; i < descriptorSetCount; i++)
 	{
diff --git a/src/Vulkan/VkDevice.cpp b/src/Vulkan/VkDevice.cpp
index 787c2aa..ca91985 100644
--- a/src/Vulkan/VkDevice.cpp
+++ b/src/Vulkan/VkDevice.cpp
@@ -52,6 +52,7 @@
 		UNIMPLEMENTED("enabledLayerCount");   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
 	}
 
+	// FIXME (b/119409619): use an allocator here so we can control all memory allocations
 	blitter = new sw::Blitter();
 }
 
diff --git a/src/Vulkan/VkObject.hpp b/src/Vulkan/VkObject.hpp
index 8957b00..805fe59 100644
--- a/src/Vulkan/VkObject.hpp
+++ b/src/Vulkan/VkObject.hpp
@@ -19,6 +19,7 @@
 #include "VkDebug.hpp"
 #include "VkMemory.h"
 
+#include <new>
 #include <vulkan/vulkan_core.h>
 #include <vulkan/vk_icd.h>
 
@@ -43,7 +44,14 @@
 		}
 	}
 
-	auto object = new (pAllocator) T(pCreateInfo, memory);
+	void* objectMemory = vk::allocate(sizeof(T), alignof(T), pAllocator, T::GetAllocationScope());
+	if(!objectMemory)
+	{
+		vk::deallocate(memory, pAllocator);
+		return VK_ERROR_OUT_OF_HOST_MEMORY;
+	}
+
+	auto object = new (objectMemory) T(pCreateInfo, memory);
 
 	if(!object)
 	{
@@ -64,11 +72,6 @@
 
 	void destroy(const VkAllocationCallbacks* pAllocator) {} // Method defined by objects to delete their content, if necessary
 
-	void* operator new(size_t count, const VkAllocationCallbacks* pAllocator)
-	{
-		return vk::allocate(count, alignof(T), pAllocator, T::GetAllocationScope());
-	}
-
 	void operator delete(void* ptr, const VkAllocationCallbacks* pAllocator)
 	{
 		// Should never happen
@@ -119,11 +122,6 @@
 		object.destroy(pAllocator);
 	}
 
-	void* operator new(size_t count, const VkAllocationCallbacks* pAllocator)
-	{
-		return vk::allocate(count, alignof(T), pAllocator, T::GetAllocationScope());
-	}
-
 	void operator delete(void* ptr, const VkAllocationCallbacks* pAllocator)
 	{
 		// Should never happen
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index d4d53e1..88fb277 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -453,6 +453,7 @@
 		auto module = Cast(pStage->module);
 		auto code = preprocessSpirv(module->getCode(), pStage->pSpecializationInfo);
 
+		// FIXME (b/119409619): use an allocator here so we can control all memory allocations
 		// TODO: also pass in any pipeline state which will affect shader compilation
 		auto spirvShader = new sw::SpirvShader{code};
 
diff --git a/src/Vulkan/VkQueue.cpp b/src/Vulkan/VkQueue.cpp
index 1b3ec53..4239350 100644
--- a/src/Vulkan/VkQueue.cpp
+++ b/src/Vulkan/VkQueue.cpp
@@ -24,6 +24,7 @@
 
 Queue::Queue(uint32_t pFamilyIndex, float pPriority) : familyIndex(pFamilyIndex), priority(pPriority)
 {
+	// FIXME (b/119409619): use an allocator here so we can control all memory allocations
 	context = new sw::Context();
 	renderer = new sw::Renderer(context, sw::OpenGL, true);
 }