Refactor physical device feature query.

VkPhysicalDeviceFeatures only contains VkBool32 members, and is also
described by the spec as a "structure that contains boolean indicators
of all the features to be enabled", as well as "For each feature, a
value of VK_TRUE specifies that the feature is supported on this
physical device, and VK_FALSE specifies that the feature is not
supported". Hence we can safely process it as an array of VkBool32.

This is also more likely to return false early when a requested feature
is not supported.

Bug b/117974925

Change-Id: I106ba6abf5f29874cde91fdaafd1dd9560aabfa9
Reviewed-on: https://swiftshader-review.googlesource.com/c/22512
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Corentin Wallez <cwallez@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index 7dbd4ef..46486bb 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -310,63 +310,20 @@
 
 bool PhysicalDevice::hasFeatures(const VkPhysicalDeviceFeatures& requestedFeatures) const
 {
-	const VkPhysicalDeviceFeatures& availableFeatures = getFeatures();
+	const VkPhysicalDeviceFeatures& supportedFeatures = getFeatures();
+	const VkBool32* supportedFeature = reinterpret_cast<const VkBool32*>(&supportedFeatures);
+	const VkBool32* requestedFeature = reinterpret_cast<const VkBool32*>(&requestedFeatures);
+	constexpr auto featureCount = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
 
-	return (!requestedFeatures.robustBufferAccess || availableFeatures.robustBufferAccess) &&
-	       (!requestedFeatures.fullDrawIndexUint32 || availableFeatures.fullDrawIndexUint32) &&
-	       (!requestedFeatures.imageCubeArray || availableFeatures.imageCubeArray) &&
-	       (!requestedFeatures.independentBlend || availableFeatures.independentBlend) &&
-	       (!requestedFeatures.geometryShader || availableFeatures.geometryShader) &&
-	       (!requestedFeatures.tessellationShader || availableFeatures.tessellationShader) &&
-	       (!requestedFeatures.sampleRateShading || availableFeatures.sampleRateShading) &&
-	       (!requestedFeatures.dualSrcBlend || availableFeatures.dualSrcBlend) &&
-	       (!requestedFeatures.logicOp || availableFeatures.logicOp) &&
-	       (!requestedFeatures.multiDrawIndirect || availableFeatures.multiDrawIndirect) &&
-	       (!requestedFeatures.drawIndirectFirstInstance || availableFeatures.drawIndirectFirstInstance) &&
-	       (!requestedFeatures.depthClamp || availableFeatures.depthClamp) &&
-	       (!requestedFeatures.depthBiasClamp || availableFeatures.depthBiasClamp) &&
-	       (!requestedFeatures.fillModeNonSolid || availableFeatures.fillModeNonSolid) &&
-	       (!requestedFeatures.depthBounds || availableFeatures.depthBounds) &&
-	       (!requestedFeatures.wideLines || availableFeatures.wideLines) &&
-	       (!requestedFeatures.largePoints || availableFeatures.largePoints) &&
-	       (!requestedFeatures.alphaToOne || availableFeatures.alphaToOne) &&
-	       (!requestedFeatures.multiViewport || availableFeatures.multiViewport) &&
-	       (!requestedFeatures.samplerAnisotropy || availableFeatures.samplerAnisotropy) &&
-	       (!requestedFeatures.textureCompressionETC2 || availableFeatures.textureCompressionETC2) &&
-	       (!requestedFeatures.textureCompressionASTC_LDR || availableFeatures.textureCompressionASTC_LDR) &&
-	       (!requestedFeatures.textureCompressionBC || availableFeatures.textureCompressionBC) &&
-	       (!requestedFeatures.occlusionQueryPrecise || availableFeatures.occlusionQueryPrecise) &&
-	       (!requestedFeatures.pipelineStatisticsQuery || availableFeatures.pipelineStatisticsQuery) &&
-	       (!requestedFeatures.vertexPipelineStoresAndAtomics || availableFeatures.vertexPipelineStoresAndAtomics) &&
-	       (!requestedFeatures.fragmentStoresAndAtomics || availableFeatures.fragmentStoresAndAtomics) &&
-	       (!requestedFeatures.shaderTessellationAndGeometryPointSize || availableFeatures.shaderTessellationAndGeometryPointSize) &&
-	       (!requestedFeatures.shaderImageGatherExtended || availableFeatures.shaderImageGatherExtended) &&
-	       (!requestedFeatures.shaderStorageImageExtendedFormats || availableFeatures.shaderStorageImageExtendedFormats) &&
-	       (!requestedFeatures.shaderStorageImageMultisample || availableFeatures.shaderStorageImageMultisample) &&
-	       (!requestedFeatures.shaderStorageImageReadWithoutFormat || availableFeatures.shaderStorageImageReadWithoutFormat) &&
-	       (!requestedFeatures.shaderStorageImageWriteWithoutFormat || availableFeatures.shaderStorageImageWriteWithoutFormat) &&
-	       (!requestedFeatures.shaderUniformBufferArrayDynamicIndexing || availableFeatures.shaderUniformBufferArrayDynamicIndexing) &&
-	       (!requestedFeatures.shaderSampledImageArrayDynamicIndexing || availableFeatures.shaderSampledImageArrayDynamicIndexing) &&
-	       (!requestedFeatures.shaderStorageBufferArrayDynamicIndexing || availableFeatures.shaderStorageBufferArrayDynamicIndexing) &&
-	       (!requestedFeatures.shaderStorageImageArrayDynamicIndexing || availableFeatures.shaderStorageImageArrayDynamicIndexing) &&
-	       (!requestedFeatures.shaderClipDistance || availableFeatures.shaderClipDistance) &&
-	       (!requestedFeatures.shaderCullDistance || availableFeatures.shaderCullDistance) &&
-	       (!requestedFeatures.shaderFloat64 || availableFeatures.shaderFloat64) &&
-	       (!requestedFeatures.shaderInt64 || availableFeatures.shaderInt64) &&
-	       (!requestedFeatures.shaderInt16 || availableFeatures.shaderInt16) &&
-	       (!requestedFeatures.shaderResourceResidency || availableFeatures.shaderResourceResidency) &&
-	       (!requestedFeatures.shaderResourceMinLod || availableFeatures.shaderResourceMinLod) &&
-	       (!requestedFeatures.sparseBinding || availableFeatures.sparseBinding) &&
-	       (!requestedFeatures.sparseResidencyBuffer || availableFeatures.sparseResidencyBuffer) &&
-	       (!requestedFeatures.sparseResidencyImage2D || availableFeatures.sparseResidencyImage2D) &&
-	       (!requestedFeatures.sparseResidencyImage3D || availableFeatures.sparseResidencyImage3D) &&
-	       (!requestedFeatures.sparseResidency2Samples || availableFeatures.sparseResidency2Samples) &&
-	       (!requestedFeatures.sparseResidency4Samples || availableFeatures.sparseResidency4Samples) &&
-	       (!requestedFeatures.sparseResidency8Samples || availableFeatures.sparseResidency8Samples) &&
-	       (!requestedFeatures.sparseResidency16Samples || availableFeatures.sparseResidency16Samples) &&
-	       (!requestedFeatures.sparseResidencyAliased || availableFeatures.sparseResidencyAliased) &&
-	       (!requestedFeatures.variableMultisampleRate || availableFeatures.variableMultisampleRate) &&
-	       (!requestedFeatures.inheritedQueries || availableFeatures.inheritedQueries);
+	for(unsigned int i = 0; i < featureCount; i++)
+	{
+		if((requestedFeature[i] == VK_TRUE) && (supportedFeature[i] != VK_TRUE))
+		{
+			return false;
+		}
+	}
+
+	return true;
 }
 
 void PhysicalDevice::getFormatProperties(VkFormat format, VkFormatProperties* pFormatProperties) const
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 92eba8b..035379b 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -214,10 +214,12 @@
 
 	ASSERT(pCreateInfo->queueCreateInfoCount > 0);
 
-	if(pCreateInfo->pEnabledFeatures &&
-	   !vk::Cast(physicalDevice)->hasFeatures(*(pCreateInfo->pEnabledFeatures)))
+	if(pCreateInfo->pEnabledFeatures)
 	{
-		return VK_ERROR_FEATURE_NOT_PRESENT;
+		if(!vk::Cast(physicalDevice)->hasFeatures(*(pCreateInfo->pEnabledFeatures)))
+		{
+			return VK_ERROR_FEATURE_NOT_PRESENT;
+		}
 	}
 
 	uint32_t queueFamilyPropertyCount = vk::Cast(physicalDevice)->getQueueFamilyPropertyCount();