Device and PhysicalDevice features and properties

This cl adds basic functionality to Device and PhysicalDevice
features and properties. Every setting and feature is either
set to the most basic setting, or disabled, when possible.

Bug b/117974925

Change-Id: Ib96630076b8e07e92c59fdf3ae902eeac00639bb
Reviewed-on: https://swiftshader-review.googlesource.com/c/21589
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Vulkan/VkDevice.cpp b/src/Vulkan/VkDevice.cpp
index 2389fda..4638bb5 100644
--- a/src/Vulkan/VkDevice.cpp
+++ b/src/Vulkan/VkDevice.cpp
@@ -15,6 +15,7 @@
 #include "VkConfig.h"
 #include "VkDebug.hpp"
 #include "VkDevice.hpp"
+#include "VkQueue.hpp"
 #include <new> // Must #include this to use "placement new"
 
 namespace vk
@@ -65,4 +66,30 @@
 	return queues[queueIndex];
 }
 
+void Device::getImageSparseMemoryRequirements(VkImage pImage, uint32_t* pSparseMemoryRequirementCount,
+	                                          VkSparseImageMemoryRequirements* pSparseMemoryRequirements) const
+{
+	if(!pSparseMemoryRequirements)
+	{
+		*pSparseMemoryRequirementCount = 1;
+	}
+	else
+	{
+		UNIMPLEMENTED();
+	}
+}
+
+void Device::getGroupPeerMemoryFeatures(uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex,
+                                        VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) const
+{
+	UNIMPLEMENTED();
+}
+
+void Device::getDescriptorSetLayoutSupport(const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+                                           VkDescriptorSetLayoutSupport* pSupport) const
+{
+	// Mark everything as unsupported
+	pSupport->supported = VK_FALSE;
+}
+
 } // namespace vk
diff --git a/src/Vulkan/VkDevice.hpp b/src/Vulkan/VkDevice.hpp
index d2188a4..e35549f 100644
--- a/src/Vulkan/VkDevice.hpp
+++ b/src/Vulkan/VkDevice.hpp
@@ -16,11 +16,12 @@
 #define VK_DEVICE_HPP_
 
 #include "VkObject.hpp"
-#include "VkQueue.hpp"
 
 namespace vk
 {
 
+class Queue;
+
 class Device
 {
 public:
@@ -38,6 +39,12 @@
 	static size_t ComputeRequiredAllocationSize(const CreateInfo* info);
 
 	VkQueue getQueue(uint32_t queueFamilyIndex, uint32_t queueIndex) const;
+	void getImageSparseMemoryRequirements(VkImage image, uint32_t* pSparseMemoryRequirementCount,
+	                                      VkSparseImageMemoryRequirements* pSparseMemoryRequirements) const;
+	void getGroupPeerMemoryFeatures(uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex,
+	                                VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) const;
+	void getDescriptorSetLayoutSupport(const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+	                                   VkDescriptorSetLayoutSupport* pSupport) const;
 
 private:
 	VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index 90ba1dc..09c26de 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -87,6 +87,44 @@
 	return features;
 }
 
+void PhysicalDevice::getFeatures(VkPhysicalDeviceSamplerYcbcrConversionFeatures* features) const
+{
+	features->samplerYcbcrConversion = VK_FALSE;
+}
+
+void PhysicalDevice::getFeatures(VkPhysicalDevice16BitStorageFeatures* features) const
+{
+	features->storageBuffer16BitAccess = VK_FALSE;

+	features->storageInputOutput16 = VK_FALSE;

+	features->storagePushConstant16 = VK_FALSE;

+	features->uniformAndStorageBuffer16BitAccess = VK_FALSE;
+}
+
+void PhysicalDevice::getFeatures(VkPhysicalDeviceVariablePointerFeatures* features) const
+{
+	features->variablePointersStorageBuffer = VK_FALSE;

+	features->variablePointers = VK_FALSE;
+}
+
+void PhysicalDevice::getFeatures(VkPhysicalDevice8BitStorageFeaturesKHR* features) const
+{
+	features->storageBuffer8BitAccess = VK_FALSE;

+	features->uniformAndStorageBuffer8BitAccess = VK_FALSE;

+	features->storagePushConstant8 = VK_FALSE;
+}
+
+void PhysicalDevice::getFeatures(VkPhysicalDeviceMultiviewFeatures* features) const
+{
+	features->multiview = VK_FALSE;

+	features->multiviewGeometryShader = VK_FALSE;

+	features->multiviewTessellationShader = VK_FALSE;
+}
+
+void PhysicalDevice::getFeatures(VkPhysicalDeviceProtectedMemoryFeatures* features) const
+{
+	features->protectedMemory = VK_FALSE;
+}
+
 VkSampleCountFlags PhysicalDevice::getSampleCounts() const
 {
 	return VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT;
@@ -233,6 +271,46 @@
 	return properties;
 }
 
+void PhysicalDevice::getProperties(VkPhysicalDeviceIDProperties* properties) const
+{

+	memcpy(properties->deviceUUID, SWIFTSHADER_UUID, VK_UUID_SIZE);

+	memset(properties->deviceLUID, 0, VK_LUID_SIZE);

+	memset(properties->driverUUID, 0, VK_UUID_SIZE);

+	*((uint64_t*)properties->driverUUID) = DRIVER_VERSION;

+	properties->deviceNodeMask = 0;

+	properties->deviceLUIDValid = VK_FALSE;
+}
+
+void PhysicalDevice::getProperties(VkPhysicalDeviceMaintenance3Properties* properties) const
+{
+	properties->maxMemoryAllocationSize = 1 << 31;

+	properties->maxPerSetDescriptors = 1024;
+}
+
+void PhysicalDevice::getProperties(VkPhysicalDeviceMultiviewProperties* properties) const
+{
+	properties->maxMultiviewInstanceIndex = (1 << 27) - 1;

+	properties->maxMultiviewViewCount = 6;
+}
+
+void PhysicalDevice::getProperties(VkPhysicalDevicePointClippingProperties* properties) const
+{
+	properties->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
+}
+
+void PhysicalDevice::getProperties(VkPhysicalDeviceProtectedMemoryProperties* properties) const
+{
+	properties->protectedNoFault = VK_FALSE;
+}
+
+void PhysicalDevice::getProperties(VkPhysicalDeviceSubgroupProperties* properties) const
+{
+	properties->subgroupSize = 1;

+	properties->supportedStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;

+	properties->supportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT;

+	properties->quadOperationsInAllStages = VK_FALSE;
+}
+
 bool PhysicalDevice::hasFeatures(const VkPhysicalDeviceFeatures& requestedFeatures) const
 {
 	const VkPhysicalDeviceFeatures& availableFeatures = getFeatures();
@@ -383,4 +461,34 @@
 	return properties;
 }
 
+void PhysicalDevice::getExternalBufferProperties(const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+                                                 VkExternalBufferProperties* pExternalBufferProperties) const
+{
+	// FIXME: currently ignoring pExternalBufferInfo
+
+	pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+	pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+	pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT;
+}
+
+void PhysicalDevice::getExternalFenceProperties(const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
+                                                VkExternalFenceProperties* pExternalFenceProperties) const
+{
+	// FIXME: currently ignoring pExternalFenceInfo
+
+	pExternalFenceProperties->compatibleHandleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
+	pExternalFenceProperties->exportFromImportedHandleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
+	pExternalFenceProperties->externalFenceFeatures = VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT;
+}
+
+void PhysicalDevice::getExternalSemaphoreProperties(const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
+                                                    VkExternalSemaphoreProperties* pExternalSemaphoreProperties) const
+{
+	// FIXME: currently ignoring pExternalSemaphoreInfo
+
+	pExternalSemaphoreProperties->compatibleHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
+	pExternalSemaphoreProperties->exportFromImportedHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
+	pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT;
+}
+
 } // namespace vk
diff --git a/src/Vulkan/VkPhysicalDevice.hpp b/src/Vulkan/VkPhysicalDevice.hpp
index c1cd043..c5221a4 100644
--- a/src/Vulkan/VkPhysicalDevice.hpp
+++ b/src/Vulkan/VkPhysicalDevice.hpp
@@ -31,8 +31,22 @@
 	static size_t ComputeRequiredAllocationSize(const void*) { return 0; }
 
 	const VkPhysicalDeviceFeatures& getFeatures() const;
+	void getFeatures(VkPhysicalDeviceSamplerYcbcrConversionFeatures* features) const;
+	void getFeatures(VkPhysicalDevice16BitStorageFeatures* features) const;
+	void getFeatures(VkPhysicalDeviceVariablePointerFeatures* features) const;
+	void getFeatures(VkPhysicalDevice8BitStorageFeaturesKHR* features) const;
+	void getFeatures(VkPhysicalDeviceMultiviewFeatures* features) const;
+	void getFeatures(VkPhysicalDeviceProtectedMemoryFeatures* features) const;
 	bool hasFeatures(const VkPhysicalDeviceFeatures& requestedFeatures) const;
+
 	const VkPhysicalDeviceProperties& getProperties() const;
+	void getProperties(VkPhysicalDeviceIDProperties* properties) const;
+	void getProperties(VkPhysicalDeviceMaintenance3Properties* properties) const;
+	void getProperties(VkPhysicalDeviceMultiviewProperties* properties) const;
+	void getProperties(VkPhysicalDevicePointClippingProperties* properties) const;
+	void getProperties(VkPhysicalDeviceProtectedMemoryProperties* properties) const;
+	void getProperties(VkPhysicalDeviceSubgroupProperties* properties) const;
+
 	void getFormatProperties(VkFormat format, VkFormatProperties* pFormatProperties) const;
 	void getImageFormatProperties(VkFormat format, VkImageType type, VkImageTiling tiling,
 	                              VkImageUsageFlags usage, VkImageCreateFlags flags,
@@ -41,6 +55,12 @@
 	void getQueueFamilyProperties(uint32_t pQueueFamilyPropertyCount,
 	                              VkQueueFamilyProperties* pQueueFamilyProperties) const;
 	const VkPhysicalDeviceMemoryProperties& getMemoryProperties() const;
+	void getExternalBufferProperties(const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+	                                 VkExternalBufferProperties* pExternalBufferProperties) const;
+	void getExternalFenceProperties(const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
+	                                VkExternalFenceProperties* pExternalFenceProperties) const;
+	void getExternalSemaphoreProperties(const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
+	                                    VkExternalSemaphoreProperties* pExternalSemaphoreProperties) const;
 
 private:
 	const VkPhysicalDeviceLimits& getLimits() const;
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index ca53ac7..2920975 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -468,8 +468,10 @@
 
 VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements)",
+	      device, image, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+
+	vk::Cast(device)->getImageSparseMemoryRequirements(image, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
 }
 
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties)
@@ -1349,8 +1351,10 @@
 
 VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device = 0x%X, uint32_t heapIndex = %d, uint32_t localDeviceIndex = %d, uint32_t remoteDeviceIndex = %d, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures = 0x%X)",
+	      device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
+
+	vk::Cast(device)->getGroupPeerMemoryFeatures(heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
 }
 
 VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask)
@@ -1367,36 +1371,115 @@
 
 VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("VkInstance instance = 0x%X, uint32_t* pPhysicalDeviceGroupCount = 0x%X, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties = 0x%X",
+	      instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
+
+	if(!pPhysicalDeviceGroupProperties)
+	{
+		*pPhysicalDeviceGroupCount = vk::Cast(instance)->getPhysicalDeviceGroupCount();
+	}
+	else
+	{
+		vk::Cast(instance)->getPhysicalDeviceGroups(*pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
+	}
+
 	return VK_SUCCESS;
 }
 
 VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device = 0x%X, const VkImageMemoryRequirementsInfo2* pInfo = 0x%X, VkMemoryRequirements2* pMemoryRequirements = 0x%X)",
+	      device, pInfo, pMemoryRequirements);
+
+	if(pInfo->pNext || pMemoryRequirements->pNext)
+	{
+		UNIMPLEMENTED();
+	}
+
+	vkGetImageMemoryRequirements(device, pInfo->image, &(pMemoryRequirements->memoryRequirements));
 }
 
 VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device = 0x%X, const VkBufferMemoryRequirementsInfo2* pInfo = 0x%X, VkMemoryRequirements2* pMemoryRequirements = 0x%X)",
+	      device, pInfo, pMemoryRequirements);
+
+	if(pInfo->pNext || pMemoryRequirements->pNext)
+	{
+		UNIMPLEMENTED();
+	}
+
+	vkGetBufferMemoryRequirements(device, pInfo->buffer, &(pMemoryRequirements->memoryRequirements));
 }
 
 VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device = 0x%X, const VkImageSparseMemoryRequirementsInfo2* pInfo = 0x%X, uint32_t* pSparseMemoryRequirementCount = 0x%X, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements = 0x%X)",
+	      device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+
+	if(pInfo->pNext || pSparseMemoryRequirements->pNext)
+	{
+		UNIMPLEMENTED();
+	}
+
+	vkGetImageSparseMemoryRequirements(device, pInfo->image, pSparseMemoryRequirementCount, &(pSparseMemoryRequirements->memoryRequirements));
 }
 
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures)
 {
 	TRACE("(VkPhysicalDevice physicalDevice = 0x%X, VkPhysicalDeviceFeatures2* pFeatures = 0x%X)", physicalDevice, pFeatures);
 
-	if(pFeatures->pNext)
+	void* pNext = pFeatures->pNext;
+	while(pNext)
 	{
-		UNIMPLEMENTED();
+		switch(*reinterpret_cast<const VkStructureType*>(pNext))
+		{
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES:
+			{
+				auto& features = *reinterpret_cast<VkPhysicalDeviceSamplerYcbcrConversionFeatures*>(pNext);
+				vk::Cast(physicalDevice)->getFeatures(&features);
+				pNext = features.pNext;
+			}
+			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES:
+			{
+				auto& features = *reinterpret_cast<VkPhysicalDevice16BitStorageFeatures*>(pNext);
+				vk::Cast(physicalDevice)->getFeatures(&features);
+				pNext = features.pNext;
+			}
+			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES:
+			{
+				auto& features = *reinterpret_cast<VkPhysicalDeviceVariablePointerFeatures*>(pNext);
+				vk::Cast(physicalDevice)->getFeatures(&features);
+				pNext = features.pNext;
+			}
+			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR:
+			{
+				auto& features = *reinterpret_cast<VkPhysicalDevice8BitStorageFeaturesKHR*>(pNext);
+				vk::Cast(physicalDevice)->getFeatures(&features);
+				pNext = features.pNext;
+			}
+			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES:
+			{
+				auto& features = *reinterpret_cast<VkPhysicalDeviceMultiviewFeatures*>(pNext);
+				vk::Cast(physicalDevice)->getFeatures(&features);
+				pNext = features.pNext;
+			}
+			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES:
+			{
+				auto& features = *reinterpret_cast<VkPhysicalDeviceProtectedMemoryFeatures*>(pNext);
+				vk::Cast(physicalDevice)->getFeatures(&features);
+				pNext = features.pNext;
+			}
+			break;
+		default:
+			// FIXME: We will eventually simply ignore unsupported pNext structures
+			UNIMPLEMENTED();
+		}
 	}
 
 	vkGetPhysicalDeviceFeatures(physicalDevice, &(pFeatures->features));
@@ -1406,9 +1489,57 @@
 {
 	TRACE("(VkPhysicalDevice physicalDevice = 0x%X, VkPhysicalDeviceProperties2* pProperties = 0x%X)", physicalDevice, pProperties);
 
-	if(pProperties->pNext)
+	void* pNext = pProperties->pNext;
+	while(pNext)
 	{
-		UNIMPLEMENTED();
+		switch(*reinterpret_cast<const VkStructureType*>(pNext))
+		{
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES:
+			{
+				auto& properties = *reinterpret_cast<VkPhysicalDeviceIDProperties*>(pNext);
+				vk::Cast(physicalDevice)->getProperties(&properties);
+				pNext = properties.pNext;
+			}
+			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES:
+			{
+				auto& properties = *reinterpret_cast<VkPhysicalDeviceMaintenance3Properties*>(pNext);
+				vk::Cast(physicalDevice)->getProperties(&properties);
+				pNext = properties.pNext;
+			}
+			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES:
+			{
+				auto& properties = *reinterpret_cast<VkPhysicalDeviceMultiviewProperties*>(pNext);
+				vk::Cast(physicalDevice)->getProperties(&properties);
+				pNext = properties.pNext;
+			}
+			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES:
+			{
+				auto& properties = *reinterpret_cast<VkPhysicalDevicePointClippingProperties*>(pNext);
+				vk::Cast(physicalDevice)->getProperties(&properties);
+				pNext = properties.pNext;
+			}
+			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES:
+			{
+				auto& properties = *reinterpret_cast<VkPhysicalDeviceProtectedMemoryProperties*>(pNext);
+				vk::Cast(physicalDevice)->getProperties(&properties);
+				pNext = properties.pNext;
+			}
+			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES:
+			{
+				auto& properties = *reinterpret_cast<VkPhysicalDeviceSubgroupProperties*>(pNext);
+				vk::Cast(physicalDevice)->getProperties(&properties);
+				pNext = properties.pNext;
+			}
+			break;
+		default:
+			// FIXME: We will eventually simply ignore unsupported pNext structures
+			UNIMPLEMENTED();
+		}
 	}
 
 	vkGetPhysicalDeviceProperties(physicalDevice, &(pProperties->properties));
@@ -1432,7 +1563,7 @@
 	TRACE("(VkPhysicalDevice physicalDevice = 0x%X, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo = 0x%X, VkImageFormatProperties2* pImageFormatProperties = 0x%X)",
 		    physicalDevice, pImageFormatInfo, pImageFormatProperties);
 
-	if(pImageFormatProperties->pNext)
+	if(pImageFormatInfo->pNext || pImageFormatProperties->pNext)
 	{
 		UNIMPLEMENTED();
 	}
@@ -1451,19 +1582,13 @@
 	TRACE("(VkPhysicalDevice physicalDevice = 0x%X, uint32_t* pQueueFamilyPropertyCount = 0x%X, VkQueueFamilyProperties2* pQueueFamilyProperties = 0x%X)",
 		physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
 
-	if(!pQueueFamilyProperties)
+	if(pQueueFamilyProperties && pQueueFamilyProperties->pNext)
 	{
-		*pQueueFamilyPropertyCount = 1;
+		UNIMPLEMENTED();
 	}
-	else
-	{
-		if(pQueueFamilyProperties->pNext)
-		{
-			UNIMPLEMENTED();
-		}
 
-		vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, &(pQueueFamilyProperties->queueFamilyProperties));
-	}
+	vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount,
+		pQueueFamilyProperties ? &(pQueueFamilyProperties->queueFamilyProperties) : nullptr);
 }
 
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties)
@@ -1483,21 +1608,14 @@
 	TRACE("(VkPhysicalDevice physicalDevice = 0x%X, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo = 0x%X, uint32_t* pPropertyCount = 0x%X, VkSparseImageFormatProperties2* pProperties = 0x%X)",
 	     physicalDevice, pFormatInfo, pPropertyCount, pProperties);
 
-	if(!pProperties)
+	if(pProperties && pProperties->pNext)
 	{
-		*pPropertyCount = 1;
+		UNIMPLEMENTED();
 	}
-	else
-	{
-		if(pProperties->pNext)
-		{
-			UNIMPLEMENTED();
-		}
 
-		vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice, pFormatInfo->format, pFormatInfo->type,
-		                                               pFormatInfo->samples, pFormatInfo->usage, pFormatInfo->tiling,
-		                                               pPropertyCount, &(pProperties->properties));
-	}
+	vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice, pFormatInfo->format, pFormatInfo->type,
+	                                               pFormatInfo->samples, pFormatInfo->usage, pFormatInfo->tiling,
+	                                               pPropertyCount, pProperties ? &(pProperties->properties) : nullptr);
 }
 
 VKAPI_ATTR void VKAPI_CALL vkTrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags)
@@ -1508,8 +1626,27 @@
 
 VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device = 0x%X, const VkDeviceQueueInfo2* pQueueInfo = 0x%X, VkQueue* pQueue = 0x%X)",
+	      device, pQueueInfo, pQueue);
+
+	if(pQueueInfo->pNext)
+	{
+		UNIMPLEMENTED();
+	}
+
+	// The only flag that can be set here is VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT 
+	// According to the Vulkan spec, 4.3.1. Queue Family Properties:
+	// "VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT specifies that the device queue is a
+	//  protected-capable queue. If the protected memory feature is not enabled,
+	//  the VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT bit of flags must not be set."
+	if(pQueueInfo->flags)
+	{
+		*pQueue = VK_NULL_HANDLE;
+	}
+	else
+	{
+		vkGetDeviceQueue(device, pQueueInfo->queueFamilyIndex, pQueueInfo->queueIndex, pQueue);
+	}
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion)
@@ -1546,26 +1683,34 @@
 
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkPhysicalDevice physicalDevice = 0x%X, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo = 0x%X, VkExternalBufferProperties* pExternalBufferProperties = 0x%X)",
+	      physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
+
+	vk::Cast(physicalDevice)->getExternalBufferProperties(pExternalBufferInfo, pExternalBufferProperties);
 }
 
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkPhysicalDevice physicalDevice = 0x%X, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo = 0x%X, VkExternalFenceProperties* pExternalFenceProperties = 0x%X)",
+	      physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
+
+	vk::Cast(physicalDevice)->getExternalFenceProperties(pExternalFenceInfo, pExternalFenceProperties);
 }
 
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkPhysicalDevice physicalDevice = 0x%X, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo = 0x%X, VkExternalSemaphoreProperties* pExternalSemaphoreProperties = 0x%X)",
+	      physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
+
+	vk::Cast(physicalDevice)->getExternalSemaphoreProperties(pExternalSemaphoreInfo, pExternalSemaphoreProperties);
 }
 
 VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport)",
+	      device, pCreateInfo, pSupport);
+
+	vk::Cast(device)->getDescriptorSetLayoutSupport(pCreateInfo, pSupport);
 }
 
 }