| // Copyright 2018 The SwiftShader Authors. All Rights Reserved. | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //    http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | #include "VkPhysicalDevice.hpp" | 
 |  | 
 | #include "VkConfig.hpp" | 
 | #include "VkStringify.hpp" | 
 | #include "Pipeline/SpirvShader.hpp"  // sw::SIMD::Width | 
 | #include "Reactor/Reactor.hpp" | 
 |  | 
 | #include <cstring> | 
 | #include <limits> | 
 |  | 
 | #ifdef __ANDROID__ | 
 | #	include <android/hardware_buffer.h> | 
 | #endif | 
 |  | 
 | namespace vk { | 
 |  | 
 | PhysicalDevice::PhysicalDevice(const void *, void *mem) | 
 | { | 
 | } | 
 |  | 
 | const VkPhysicalDeviceFeatures &PhysicalDevice::getFeatures() const | 
 | { | 
 | 	static const VkPhysicalDeviceFeatures features{ | 
 | 		VK_TRUE,   // robustBufferAccess | 
 | 		VK_TRUE,   // fullDrawIndexUint32 | 
 | 		VK_TRUE,   // imageCubeArray | 
 | 		VK_TRUE,   // independentBlend | 
 | 		VK_FALSE,  // geometryShader | 
 | 		VK_FALSE,  // tessellationShader | 
 | 		VK_TRUE,   // sampleRateShading | 
 | 		VK_FALSE,  // dualSrcBlend | 
 | 		VK_FALSE,  // logicOp | 
 | 		VK_TRUE,   // multiDrawIndirect | 
 | 		VK_TRUE,   // drawIndirectFirstInstance | 
 | 		VK_TRUE,   // depthClamp | 
 | 		VK_TRUE,   // depthBiasClamp | 
 | 		VK_TRUE,   // fillModeNonSolid | 
 | 		VK_TRUE,   // depthBounds | 
 | 		VK_FALSE,  // wideLines | 
 | 		VK_TRUE,   // largePoints | 
 | 		VK_FALSE,  // alphaToOne | 
 | 		VK_FALSE,  // multiViewport | 
 | 		VK_TRUE,   // samplerAnisotropy | 
 | 		VK_TRUE,   // textureCompressionETC2 | 
 | #ifdef SWIFTSHADER_ENABLE_ASTC | 
 | 		VK_TRUE,  // textureCompressionASTC_LDR | 
 | #else | 
 | 		VK_FALSE,  // textureCompressionASTC_LDR | 
 | #endif | 
 | 		VK_TRUE,   // textureCompressionBC | 
 | 		VK_TRUE,   // occlusionQueryPrecise | 
 | 		VK_FALSE,  // pipelineStatisticsQuery | 
 | 		VK_TRUE,   // vertexPipelineStoresAndAtomics | 
 | 		VK_TRUE,   // fragmentStoresAndAtomics | 
 | 		VK_FALSE,  // shaderTessellationAndGeometryPointSize | 
 | 		VK_FALSE,  // shaderImageGatherExtended | 
 | 		VK_TRUE,   // shaderStorageImageExtendedFormats | 
 | 		VK_TRUE,   // shaderStorageImageMultisample | 
 | 		VK_FALSE,  // shaderStorageImageReadWithoutFormat | 
 | 		VK_TRUE,   // shaderStorageImageWriteWithoutFormat | 
 | 		VK_TRUE,   // shaderUniformBufferArrayDynamicIndexing | 
 | 		VK_TRUE,   // shaderSampledImageArrayDynamicIndexing | 
 | 		VK_TRUE,   // shaderStorageBufferArrayDynamicIndexing | 
 | 		VK_TRUE,   // shaderStorageImageArrayDynamicIndexing | 
 | 		VK_TRUE,   // shaderClipDistance | 
 | 		VK_TRUE,   // shaderCullDistance | 
 | 		VK_FALSE,  // shaderFloat64 | 
 | 		VK_FALSE,  // shaderInt64 | 
 | 		VK_FALSE,  // shaderInt16 | 
 | 		VK_FALSE,  // shaderResourceResidency | 
 | 		VK_FALSE,  // shaderResourceMinLod | 
 | 		VK_FALSE,  // sparseBinding | 
 | 		VK_FALSE,  // sparseResidencyBuffer | 
 | 		VK_FALSE,  // sparseResidencyImage2D | 
 | 		VK_FALSE,  // sparseResidencyImage3D | 
 | 		VK_FALSE,  // sparseResidency2Samples | 
 | 		VK_FALSE,  // sparseResidency4Samples | 
 | 		VK_FALSE,  // sparseResidency8Samples | 
 | 		VK_FALSE,  // sparseResidency16Samples | 
 | 		VK_FALSE,  // sparseResidencyAliased | 
 | 		VK_TRUE,   // variableMultisampleRate | 
 | 		VK_FALSE,  // inheritedQueries | 
 | 	}; | 
 |  | 
 | 	return features; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceSamplerYcbcrConversionFeatures(T *features) | 
 | { | 
 | 	features->samplerYcbcrConversion = VK_TRUE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDevice16BitStorageFeatures(T *features) | 
 | { | 
 | 	features->storageBuffer16BitAccess = VK_FALSE; | 
 | 	features->storageInputOutput16 = VK_FALSE; | 
 | 	features->storagePushConstant16 = VK_FALSE; | 
 | 	features->uniformAndStorageBuffer16BitAccess = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceVariablePointersFeatures(T *features) | 
 | { | 
 | 	features->variablePointersStorageBuffer = VK_FALSE; | 
 | 	features->variablePointers = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDevice8BitStorageFeaturesKHR(T *features) | 
 | { | 
 | 	features->storageBuffer8BitAccess = VK_FALSE; | 
 | 	features->uniformAndStorageBuffer8BitAccess = VK_FALSE; | 
 | 	features->storagePushConstant8 = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceMultiviewFeatures(T *features) | 
 | { | 
 | 	features->multiview = VK_TRUE; | 
 | 	features->multiviewGeometryShader = VK_FALSE; | 
 | 	features->multiviewTessellationShader = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceProtectedMemoryFeatures(T *features) | 
 | { | 
 | 	features->protectedMemory = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceShaderDrawParameterFeatures(T *features) | 
 | { | 
 | 	features->shaderDrawParameters = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR(T *features) | 
 | { | 
 | 	features->separateDepthStencilLayouts = VK_TRUE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceLineRasterizationFeaturesEXT(T *features) | 
 | { | 
 | 	features->rectangularLines = VK_TRUE; | 
 | 	features->bresenhamLines = VK_TRUE; | 
 | 	features->smoothLines = VK_FALSE; | 
 | 	features->stippledRectangularLines = VK_FALSE; | 
 | 	features->stippledBresenhamLines = VK_FALSE; | 
 | 	features->stippledSmoothLines = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceProvokingVertexFeaturesEXT(T *features) | 
 | { | 
 | 	features->provokingVertexLast = VK_TRUE; | 
 | 	features->transformFeedbackPreservesProvokingVertex = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceHostQueryResetFeatures(T *features) | 
 | { | 
 | 	features->hostQueryReset = VK_TRUE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDevicePipelineCreationCacheControlFeatures(T *features) | 
 | { | 
 | 	features->pipelineCreationCacheControl = VK_TRUE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceImageRobustnessFeaturesEXT(T *features) | 
 | { | 
 | 	features->robustImageAccess = VK_TRUE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceShaderDrawParametersFeatures(T *features) | 
 | { | 
 | 	features->shaderDrawParameters = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceVulkan11Features(T *features) | 
 | { | 
 | 	getPhysicalDevice16BitStorageFeatures(features); | 
 | 	getPhysicalDeviceMultiviewFeatures(features); | 
 | 	getPhysicalDeviceVariablePointersFeatures(features); | 
 | 	getPhysicalDeviceProtectedMemoryFeatures(features); | 
 | 	getPhysicalDeviceSamplerYcbcrConversionFeatures(features); | 
 | 	getPhysicalDeviceShaderDrawParametersFeatures(features); | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceImagelessFramebufferFeatures(T *features) | 
 | { | 
 | 	features->imagelessFramebuffer = VK_TRUE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceShaderSubgroupExtendedTypesFeatures(T *features) | 
 | { | 
 | 	features->shaderSubgroupExtendedTypes = VK_TRUE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceScalarBlockLayoutFeatures(T *features) | 
 | { | 
 | 	features->scalarBlockLayout = VK_TRUE; | 
 | } | 
 |  | 
 | #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT | 
 | template<typename T> | 
 | static void getPhysicalDeviceDeviceMemoryReportFeaturesEXT(T *features) | 
 | { | 
 | 	features->deviceMemoryReport = VK_TRUE; | 
 | } | 
 | #endif  // SWIFTSHADER_DEVICE_MEMORY_REPORT | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceUniformBufferStandardLayoutFeatures(T *features) | 
 | { | 
 | 	features->uniformBufferStandardLayout = VK_TRUE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceDescriptorIndexingFeatures(T *features) | 
 | { | 
 | 	features->shaderInputAttachmentArrayDynamicIndexing = VK_FALSE; | 
 | 	features->shaderUniformTexelBufferArrayDynamicIndexing = VK_FALSE; | 
 | 	features->shaderStorageTexelBufferArrayDynamicIndexing = VK_FALSE; | 
 | 	features->shaderUniformBufferArrayNonUniformIndexing = VK_FALSE; | 
 | 	features->shaderSampledImageArrayNonUniformIndexing = VK_FALSE; | 
 | 	features->shaderStorageBufferArrayNonUniformIndexing = VK_FALSE; | 
 | 	features->shaderStorageImageArrayNonUniformIndexing = VK_FALSE; | 
 | 	features->shaderInputAttachmentArrayNonUniformIndexing = VK_FALSE; | 
 | 	features->shaderUniformTexelBufferArrayNonUniformIndexing = VK_FALSE; | 
 | 	features->shaderStorageTexelBufferArrayNonUniformIndexing = VK_FALSE; | 
 | 	features->descriptorBindingUniformBufferUpdateAfterBind = VK_FALSE; | 
 | 	features->descriptorBindingSampledImageUpdateAfterBind = VK_FALSE; | 
 | 	features->descriptorBindingStorageImageUpdateAfterBind = VK_FALSE; | 
 | 	features->descriptorBindingStorageBufferUpdateAfterBind = VK_FALSE; | 
 | 	features->descriptorBindingUniformTexelBufferUpdateAfterBind = VK_FALSE; | 
 | 	features->descriptorBindingStorageTexelBufferUpdateAfterBind = VK_FALSE; | 
 | 	features->descriptorBindingUpdateUnusedWhilePending = VK_FALSE; | 
 | 	features->descriptorBindingPartiallyBound = VK_FALSE; | 
 | 	features->descriptorBindingVariableDescriptorCount = VK_FALSE; | 
 | 	features->runtimeDescriptorArray = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceVulkanMemoryModelFeatures(T *features) | 
 | { | 
 | 	features->vulkanMemoryModel = VK_TRUE; | 
 | 	features->vulkanMemoryModelDeviceScope = VK_TRUE; | 
 | 	features->vulkanMemoryModelAvailabilityVisibilityChains = VK_TRUE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceTimelineSemaphoreFeatures(T *features) | 
 | { | 
 | 	features->timelineSemaphore = VK_TRUE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceShaderAtomicInt64Features(T *features) | 
 | { | 
 | 	features->shaderBufferInt64Atomics = VK_FALSE; | 
 | 	features->shaderSharedInt64Atomics = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceShaderFloat16Int8Features(T *features) | 
 | { | 
 | 	features->shaderFloat16 = VK_FALSE; | 
 | 	features->shaderInt8 = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceBufferDeviceAddressFeatures(T *features) | 
 | { | 
 | 	features->bufferDeviceAddress = VK_FALSE; | 
 | 	features->bufferDeviceAddressCaptureReplay = VK_FALSE; | 
 | 	features->bufferDeviceAddressMultiDevice = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceVulkan12Features(T *features) | 
 | { | 
 | 	features->samplerMirrorClampToEdge = VK_TRUE; | 
 | 	features->drawIndirectCount = VK_FALSE; | 
 | 	getPhysicalDevice8BitStorageFeaturesKHR(features); | 
 | 	getPhysicalDeviceShaderAtomicInt64Features(features); | 
 | 	getPhysicalDeviceShaderFloat16Int8Features(features); | 
 | 	features->descriptorIndexing = VK_FALSE; | 
 | 	getPhysicalDeviceDescriptorIndexingFeatures(features); | 
 | 	features->samplerFilterMinmax = VK_FALSE; | 
 | 	getPhysicalDeviceScalarBlockLayoutFeatures(features); | 
 | 	getPhysicalDeviceImagelessFramebufferFeatures(features); | 
 | 	getPhysicalDeviceUniformBufferStandardLayoutFeatures(features); | 
 | 	getPhysicalDeviceShaderSubgroupExtendedTypesFeatures(features); | 
 | 	getPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR(features); | 
 | 	getPhysicalDeviceHostQueryResetFeatures(features); | 
 | 	getPhysicalDeviceTimelineSemaphoreFeatures(features); | 
 | 	getPhysicalDeviceBufferDeviceAddressFeatures(features); | 
 | 	getPhysicalDeviceVulkanMemoryModelFeatures(features); | 
 | 	features->shaderOutputViewportIndex = VK_FALSE; | 
 | 	features->shaderOutputLayer = VK_FALSE; | 
 | 	features->subgroupBroadcastDynamicId = VK_TRUE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPhysicalDeviceDepthClipEnableFeaturesExt(T *features) | 
 | { | 
 | 	features->depthClipEnable = VK_TRUE; | 
 | } | 
 |  | 
 | static void getPhysicalDeviceCustomBorderColorFeaturesExt(VkPhysicalDeviceCustomBorderColorFeaturesEXT *features) | 
 | { | 
 | 	features->customBorderColors = VK_TRUE; | 
 | 	features->customBorderColorWithoutFormat = VK_TRUE; | 
 | } | 
 |  | 
 | static void getPhysicalDeviceBlendOperationAdvancedFeaturesExt(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT *features) | 
 | { | 
 | 	features->advancedBlendCoherentOperations = VK_FALSE; | 
 | } | 
 |  | 
 | static void getPhysicalDevice4444FormatsFeaturesExt(VkPhysicalDevice4444FormatsFeaturesEXT *features) | 
 | { | 
 | 	features->formatA4R4G4B4 = VK_TRUE; | 
 | 	features->formatA4B4G4R4 = VK_TRUE; | 
 | } | 
 |  | 
 | void PhysicalDevice::getFeatures2(VkPhysicalDeviceFeatures2 *features) const | 
 | { | 
 | 	features->features = getFeatures(); | 
 | 	VkBaseOutStructure *curExtension = reinterpret_cast<VkBaseOutStructure *>(features->pNext); | 
 | 	while(curExtension != nullptr) | 
 | 	{ | 
 | 		// Need to switch on an integer since Provoking Vertex isn't a part of the Vulkan spec. | 
 | 		switch((int)curExtension->sType) | 
 | 		{ | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: | 
 | 			getPhysicalDeviceVulkan11Features(reinterpret_cast<VkPhysicalDeviceVulkan11Features *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: | 
 | 			getPhysicalDeviceVulkan12Features(reinterpret_cast<VkPhysicalDeviceVulkan12Features *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: | 
 | 			getPhysicalDeviceMultiviewFeatures(reinterpret_cast<VkPhysicalDeviceMultiviewFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: | 
 | 			getPhysicalDeviceVariablePointersFeatures(reinterpret_cast<VkPhysicalDeviceVariablePointersFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: | 
 | 			getPhysicalDevice16BitStorageFeatures(reinterpret_cast<VkPhysicalDevice16BitStorageFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: | 
 | 			getPhysicalDeviceSamplerYcbcrConversionFeatures(reinterpret_cast<VkPhysicalDeviceSamplerYcbcrConversionFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: | 
 | 			getPhysicalDeviceProtectedMemoryFeatures(reinterpret_cast<VkPhysicalDeviceProtectedMemoryFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: | 
 | 			getPhysicalDeviceShaderDrawParameterFeatures(reinterpret_cast<VkPhysicalDeviceShaderDrawParameterFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES: | 
 | 			getPhysicalDeviceHostQueryResetFeatures(reinterpret_cast<VkPhysicalDeviceHostQueryResetFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT: | 
 | 			getPhysicalDevicePipelineCreationCacheControlFeatures(reinterpret_cast<VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT: | 
 | 			getPhysicalDeviceImageRobustnessFeaturesEXT(reinterpret_cast<VkPhysicalDeviceImageRobustnessFeaturesEXT *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: | 
 | 			getPhysicalDeviceLineRasterizationFeaturesEXT(reinterpret_cast<VkPhysicalDeviceLineRasterizationFeaturesEXT *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES: | 
 | 			getPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR(reinterpret_cast<VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR: | 
 | 			getPhysicalDevice8BitStorageFeaturesKHR(reinterpret_cast<VkPhysicalDevice8BitStorageFeaturesKHR *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: | 
 | 			getPhysicalDeviceProvokingVertexFeaturesEXT(reinterpret_cast<VkPhysicalDeviceProvokingVertexFeaturesEXT *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES: | 
 | 			getPhysicalDeviceImagelessFramebufferFeatures(reinterpret_cast<VkPhysicalDeviceImagelessFramebufferFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR: | 
 | 			getPhysicalDeviceShaderSubgroupExtendedTypesFeatures(reinterpret_cast<VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES: | 
 | 			getPhysicalDeviceScalarBlockLayoutFeatures(reinterpret_cast<VkPhysicalDeviceScalarBlockLayoutFeatures *>(curExtension)); | 
 | 			break; | 
 | #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT: | 
 | 			getPhysicalDeviceDeviceMemoryReportFeaturesEXT(reinterpret_cast<VkPhysicalDeviceDeviceMemoryReportFeaturesEXT *>(curExtension)); | 
 | 			break; | 
 | #endif  // SWIFTSHADER_DEVICE_MEMORY_REPORT | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES: | 
 | 			getPhysicalDeviceUniformBufferStandardLayoutFeatures(reinterpret_cast<VkPhysicalDeviceUniformBufferStandardLayoutFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES: | 
 | 			getPhysicalDeviceVulkanMemoryModelFeatures(reinterpret_cast<VkPhysicalDeviceVulkanMemoryModelFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES: | 
 | 			getPhysicalDeviceTimelineSemaphoreFeatures(reinterpret_cast<VkPhysicalDeviceTimelineSemaphoreFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES: | 
 | 			getPhysicalDeviceShaderAtomicInt64Features(reinterpret_cast<VkPhysicalDeviceShaderAtomicInt64Features *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES: | 
 | 			getPhysicalDeviceShaderFloat16Int8Features(reinterpret_cast<VkPhysicalDeviceShaderFloat16Int8Features *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES: | 
 | 			getPhysicalDeviceBufferDeviceAddressFeatures(reinterpret_cast<VkPhysicalDeviceBufferDeviceAddressFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES: | 
 | 			getPhysicalDeviceDescriptorIndexingFeatures(reinterpret_cast<VkPhysicalDeviceDescriptorIndexingFeatures *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: | 
 | 			getPhysicalDeviceDepthClipEnableFeaturesExt(reinterpret_cast<VkPhysicalDeviceDepthClipEnableFeaturesEXT *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: | 
 | 			getPhysicalDeviceCustomBorderColorFeaturesExt(reinterpret_cast<VkPhysicalDeviceCustomBorderColorFeaturesEXT *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT: | 
 | 			getPhysicalDeviceBlendOperationAdvancedFeaturesExt(reinterpret_cast<VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT *>(curExtension)); | 
 | 			break; | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: | 
 | 			getPhysicalDevice4444FormatsFeaturesExt(reinterpret_cast<struct VkPhysicalDevice4444FormatsFeaturesEXT *>(curExtension)); | 
 | 		// Unsupported extensions, but used by dEQP | 
 | 		// TODO(b/176893525): This may not be legal. | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT: | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT: | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT: | 
 | 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR: | 
 | 			break; | 
 | 		default: | 
 | 			UNSUPPORTED("curExtension->sType: %s", vk::Stringify(curExtension->sType).c_str()); | 
 | 			break; | 
 | 		} | 
 | 		curExtension = reinterpret_cast<VkBaseOutStructure *>(curExtension->pNext); | 
 | 	} | 
 | } | 
 |  | 
 | VkSampleCountFlags PhysicalDevice::getSampleCounts() | 
 | { | 
 | 	return VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT; | 
 | } | 
 |  | 
 | const VkPhysicalDeviceLimits &PhysicalDevice::getLimits() | 
 | { | 
 | 	VkSampleCountFlags sampleCounts = getSampleCounts(); | 
 |  | 
 | 	static const VkPhysicalDeviceLimits limits = { | 
 | 		1 << (vk::MAX_IMAGE_LEVELS_1D - 1),          // maxImageDimension1D | 
 | 		1 << (vk::MAX_IMAGE_LEVELS_2D - 1),          // maxImageDimension2D | 
 | 		1 << (vk::MAX_IMAGE_LEVELS_3D - 1),          // maxImageDimension3D | 
 | 		1 << (vk::MAX_IMAGE_LEVELS_CUBE - 1),        // maxImageDimensionCube | 
 | 		vk::MAX_IMAGE_ARRAY_LAYERS,                  // maxImageArrayLayers | 
 | 		65536,                                       // maxTexelBufferElements | 
 | 		65536,                                       // maxUniformBufferRange | 
 | 		vk::MAX_MEMORY_ALLOCATION_SIZE,              // maxStorageBufferRange | 
 | 		vk::MAX_PUSH_CONSTANT_SIZE,                  // maxPushConstantsSize | 
 | 		4096,                                        // maxMemoryAllocationCount | 
 | 		vk::MAX_SAMPLER_ALLOCATION_COUNT,            // maxSamplerAllocationCount | 
 | 		131072,                                      // bufferImageGranularity | 
 | 		0,                                           // sparseAddressSpaceSize (unsupported) | 
 | 		MAX_BOUND_DESCRIPTOR_SETS,                   // maxBoundDescriptorSets | 
 | 		16,                                          // maxPerStageDescriptorSamplers | 
 | 		14,                                          // maxPerStageDescriptorUniformBuffers | 
 | 		16,                                          // maxPerStageDescriptorStorageBuffers | 
 | 		16,                                          // maxPerStageDescriptorSampledImages | 
 | 		4,                                           // maxPerStageDescriptorStorageImages | 
 | 		sw::MAX_COLOR_BUFFERS,                       // maxPerStageDescriptorInputAttachments | 
 | 		128,                                         // maxPerStageResources | 
 | 		96,                                          // maxDescriptorSetSamplers | 
 | 		72,                                          // maxDescriptorSetUniformBuffers | 
 | 		MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC,  // maxDescriptorSetUniformBuffersDynamic | 
 | 		24,                                          // maxDescriptorSetStorageBuffers | 
 | 		MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC,  // maxDescriptorSetStorageBuffersDynamic | 
 | 		96,                                          // maxDescriptorSetSampledImages | 
 | 		24,                                          // maxDescriptorSetStorageImages | 
 | 		sw::MAX_COLOR_BUFFERS,                       // maxDescriptorSetInputAttachments | 
 | 		16,                                          // maxVertexInputAttributes | 
 | 		vk::MAX_VERTEX_INPUT_BINDINGS,               // maxVertexInputBindings | 
 | 		2047,                                        // maxVertexInputAttributeOffset | 
 | 		2048,                                        // maxVertexInputBindingStride | 
 | 		sw::MAX_INTERFACE_COMPONENTS,                // maxVertexOutputComponents | 
 | 		0,                                           // maxTessellationGenerationLevel (unsupported) | 
 | 		0,                                           // maxTessellationPatchSize (unsupported) | 
 | 		0,                                           // maxTessellationControlPerVertexInputComponents (unsupported) | 
 | 		0,                                           // maxTessellationControlPerVertexOutputComponents (unsupported) | 
 | 		0,                                           // maxTessellationControlPerPatchOutputComponents (unsupported) | 
 | 		0,                                           // maxTessellationControlTotalOutputComponents (unsupported) | 
 | 		0,                                           // maxTessellationEvaluationInputComponents (unsupported) | 
 | 		0,                                           // maxTessellationEvaluationOutputComponents (unsupported) | 
 | 		0,                                           // maxGeometryShaderInvocations (unsupported) | 
 | 		0,                                           // maxGeometryInputComponents (unsupported) | 
 | 		0,                                           // maxGeometryOutputComponents (unsupported) | 
 | 		0,                                           // maxGeometryOutputVertices (unsupported) | 
 | 		0,                                           // maxGeometryTotalOutputComponents (unsupported) | 
 | 		sw::MAX_INTERFACE_COMPONENTS,                // maxFragmentInputComponents | 
 | 		sw::MAX_COLOR_BUFFERS,                       // maxFragmentOutputAttachments | 
 | 		1,                                           // maxFragmentDualSrcAttachments | 
 | 		28,                                          // maxFragmentCombinedOutputResources | 
 | 		32768,                                       // maxComputeSharedMemorySize | 
 | 		{ 65535, 65535, 65535 },                     // maxComputeWorkGroupCount[3] | 
 | 		256,                                         // maxComputeWorkGroupInvocations | 
 | 		{ 256, 256, 64 },                            // maxComputeWorkGroupSize[3] | 
 | 		vk::SUBPIXEL_PRECISION_BITS,                 // subPixelPrecisionBits | 
 | 		4,                                           // subTexelPrecisionBits | 
 | 		4,                                           // mipmapPrecisionBits | 
 | 		UINT32_MAX,                                  // maxDrawIndexedIndexValue | 
 | 		UINT32_MAX,                                  // maxDrawIndirectCount | 
 | 		vk::MAX_SAMPLER_LOD_BIAS,                    // maxSamplerLodBias | 
 | 		16,                                          // maxSamplerAnisotropy | 
 | 		16,                                          // maxViewports | 
 | 		{ sw::MAX_VIEWPORT_DIM, | 
 | 		  sw::MAX_VIEWPORT_DIM },  // maxViewportDimensions[2] | 
 | 		{ -2 * sw::MAX_VIEWPORT_DIM, | 
 | 		  2 * sw::MAX_VIEWPORT_DIM - 1 },                 // viewportBoundsRange[2] | 
 | 		0,                                                // viewportSubPixelBits | 
 | 		64,                                               // minMemoryMapAlignment | 
 | 		vk::MIN_TEXEL_BUFFER_OFFSET_ALIGNMENT,            // minTexelBufferOffsetAlignment | 
 | 		vk::MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT,          // minUniformBufferOffsetAlignment | 
 | 		vk::MIN_STORAGE_BUFFER_OFFSET_ALIGNMENT,          // minStorageBufferOffsetAlignment | 
 | 		sw::MIN_TEXEL_OFFSET,                             // minTexelOffset | 
 | 		sw::MAX_TEXEL_OFFSET,                             // maxTexelOffset | 
 | 		sw::MIN_TEXEL_OFFSET,                             // minTexelGatherOffset | 
 | 		sw::MAX_TEXEL_OFFSET,                             // maxTexelGatherOffset | 
 | 		-0.5,                                             // minInterpolationOffset | 
 | 		0.5,                                              // maxInterpolationOffset | 
 | 		4,                                                // subPixelInterpolationOffsetBits | 
 | 		sw::MAX_FRAMEBUFFER_DIM,                          // maxFramebufferWidth | 
 | 		sw::MAX_FRAMEBUFFER_DIM,                          // maxFramebufferHeight | 
 | 		256,                                              // maxFramebufferLayers | 
 | 		sampleCounts,                                     // framebufferColorSampleCounts | 
 | 		sampleCounts,                                     // framebufferDepthSampleCounts | 
 | 		sampleCounts,                                     // framebufferStencilSampleCounts | 
 | 		sampleCounts,                                     // framebufferNoAttachmentsSampleCounts | 
 | 		sw::MAX_COLOR_BUFFERS,                            // maxColorAttachments | 
 | 		sampleCounts,                                     // sampledImageColorSampleCounts | 
 | 		sampleCounts,                                     // sampledImageIntegerSampleCounts | 
 | 		sampleCounts,                                     // sampledImageDepthSampleCounts | 
 | 		sampleCounts,                                     // sampledImageStencilSampleCounts | 
 | 		sampleCounts,                                     // storageImageSampleCounts | 
 | 		1,                                                // maxSampleMaskWords | 
 | 		VK_TRUE,                                          // timestampComputeAndGraphics | 
 | 		1,                                                // timestampPeriod | 
 | 		sw::MAX_CLIP_DISTANCES,                           // maxClipDistances | 
 | 		sw::MAX_CULL_DISTANCES,                           // maxCullDistances | 
 | 		sw::MAX_CLIP_DISTANCES + sw::MAX_CULL_DISTANCES,  // maxCombinedClipAndCullDistances | 
 | 		2,                                                // discreteQueuePriorities | 
 | 		{ 1.0, vk::MAX_POINT_SIZE },                      // pointSizeRange[2] | 
 | 		{ 1.0, 1.0 },                                     // lineWidthRange[2] (unsupported) | 
 | 		0.0,                                              // pointSizeGranularity (unsupported) | 
 | 		0.0,                                              // lineWidthGranularity (unsupported) | 
 | 		VK_TRUE,                                          // strictLines | 
 | 		VK_TRUE,                                          // standardSampleLocations | 
 | 		64,                                               // optimalBufferCopyOffsetAlignment | 
 | 		64,                                               // optimalBufferCopyRowPitchAlignment | 
 | 		256,                                              // nonCoherentAtomSize | 
 | 	}; | 
 |  | 
 | 	return limits; | 
 | } | 
 |  | 
 | const VkPhysicalDeviceProperties &PhysicalDevice::getProperties() const | 
 | { | 
 | 	auto getProperties = [&]() -> VkPhysicalDeviceProperties { | 
 | 		VkPhysicalDeviceProperties properties = { | 
 | 			API_VERSION, | 
 | 			DRIVER_VERSION, | 
 | 			VENDOR_ID, | 
 | 			DEVICE_ID, | 
 | 			VK_PHYSICAL_DEVICE_TYPE_CPU,  // deviceType | 
 | 			"",                           // deviceName | 
 | 			SWIFTSHADER_UUID,             // pipelineCacheUUID | 
 | 			getLimits(),                  // limits | 
 | 			{}                            // sparseProperties | 
 | 		}; | 
 |  | 
 | 		// Append Reactor JIT backend name and version | 
 | 		snprintf(properties.deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, | 
 | 		         "%s (%s)", SWIFTSHADER_DEVICE_NAME, rr::BackendName().c_str()); | 
 |  | 
 | 		return properties; | 
 | 	}; | 
 |  | 
 | 	static const VkPhysicalDeviceProperties properties = getProperties(); | 
 | 	return properties; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getIdProperties(T *properties) | 
 | { | 
 | 	memset(properties->deviceUUID, 0, VK_UUID_SIZE); | 
 | 	memset(properties->driverUUID, 0, VK_UUID_SIZE); | 
 | 	memset(properties->deviceLUID, 0, VK_LUID_SIZE); | 
 |  | 
 | 	memcpy(properties->deviceUUID, SWIFTSHADER_UUID, VK_UUID_SIZE); | 
 | 	*((uint64_t *)properties->driverUUID) = DRIVER_VERSION; | 
 |  | 
 | 	properties->deviceNodeMask = 0; | 
 | 	properties->deviceLUIDValid = VK_FALSE; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceIDProperties *properties) const | 
 | { | 
 | 	getIdProperties(properties); | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getMaintenance3Properties(T *properties) | 
 | { | 
 | 	properties->maxMemoryAllocationSize = MAX_MEMORY_ALLOCATION_SIZE; | 
 | 	properties->maxPerSetDescriptors = 1024; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceMaintenance3Properties *properties) const | 
 | { | 
 | 	getMaintenance3Properties(properties); | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getMultiviewProperties(T *properties) | 
 | { | 
 | 	properties->maxMultiviewViewCount = 6; | 
 | 	properties->maxMultiviewInstanceIndex = 1u << 27; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceMultiviewProperties *properties) const | 
 | { | 
 | 	getMultiviewProperties(properties); | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getPointClippingProperties(T *properties) | 
 | { | 
 | 	properties->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDevicePointClippingProperties *properties) const | 
 | { | 
 | 	getPointClippingProperties(properties); | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getProtectedMemoryProperties(T *properties) | 
 | { | 
 | 	properties->protectedNoFault = VK_FALSE; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceProtectedMemoryProperties *properties) const | 
 | { | 
 | 	getProtectedMemoryProperties(properties); | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceSubgroupProperties *properties) const | 
 | { | 
 | 	properties->subgroupSize = sw::SIMD::Width; | 
 | 	properties->supportedStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT; | 
 | 	properties->supportedOperations = | 
 | 	    VK_SUBGROUP_FEATURE_BASIC_BIT | | 
 | 	    VK_SUBGROUP_FEATURE_VOTE_BIT | | 
 | 	    VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | | 
 | 	    VK_SUBGROUP_FEATURE_BALLOT_BIT | | 
 | 	    VK_SUBGROUP_FEATURE_SHUFFLE_BIT | | 
 | 	    VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT; | 
 | 	properties->quadOperationsInAllStages = VK_FALSE; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceVulkan11Properties *properties) const | 
 | { | 
 | 	getIdProperties(properties); | 
 |  | 
 | 	// We can't use templated functions for Vulkan11 & subgroup properties. The names of the | 
 | 	// variables in VkPhysicalDeviceSubgroupProperties differ from the names in the Vulkan11 | 
 | 	// struct. | 
 | 	VkPhysicalDeviceSubgroupProperties subgroupProperties = {}; | 
 | 	getProperties(&subgroupProperties); | 
 | 	properties->subgroupSize = subgroupProperties.subgroupSize; | 
 | 	properties->subgroupSupportedStages = subgroupProperties.supportedStages; | 
 | 	properties->subgroupSupportedOperations = subgroupProperties.supportedOperations; | 
 | 	properties->subgroupQuadOperationsInAllStages = subgroupProperties.quadOperationsInAllStages; | 
 |  | 
 | 	getPointClippingProperties(properties); | 
 | 	getMultiviewProperties(properties); | 
 | 	getProtectedMemoryProperties(properties); | 
 | 	getMaintenance3Properties(properties); | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(const VkExternalMemoryHandleTypeFlagBits *handleType, VkExternalImageFormatProperties *properties) const | 
 | { | 
 | 	VkExternalMemoryProperties *extMemProperties = &properties->externalMemoryProperties; | 
 | #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD | 
 | 	if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) | 
 | 	{ | 
 | 		extMemProperties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; | 
 | 		extMemProperties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; | 
 | 		extMemProperties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; | 
 | 		return; | 
 | 	} | 
 | #endif | 
 | #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER | 
 | 	if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) | 
 | 	{ | 
 | 		extMemProperties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; | 
 | 		extMemProperties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; | 
 | 		extMemProperties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT; | 
 | 		return; | 
 | 	} | 
 | #endif | 
 | #if VK_USE_PLATFORM_FUCHSIA | 
 | 	if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA) | 
 | 	{ | 
 | 		extMemProperties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA; | 
 | 		extMemProperties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA; | 
 | 		extMemProperties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; | 
 | 		return; | 
 | 	} | 
 | #endif | 
 | 	extMemProperties->compatibleHandleTypes = 0; | 
 | 	extMemProperties->exportFromImportedHandleTypes = 0; | 
 | 	extMemProperties->externalMemoryFeatures = 0; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(const VkExternalMemoryHandleTypeFlagBits *handleType, VkExternalBufferProperties *properties) const | 
 | { | 
 | 	VkExternalMemoryProperties *extMemProperties = &properties->externalMemoryProperties; | 
 | #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD | 
 | 	if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) | 
 | 	{ | 
 | 		extMemProperties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; | 
 | 		extMemProperties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; | 
 | 		extMemProperties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; | 
 | 		return; | 
 | 	} | 
 | #endif | 
 | #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER | 
 | 	if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) | 
 | 	{ | 
 | 		extMemProperties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; | 
 | 		extMemProperties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; | 
 | 		extMemProperties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; | 
 | 		return; | 
 | 	} | 
 | #endif | 
 | #if VK_USE_PLATFORM_FUCHSIA | 
 | 	if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA) | 
 | 	{ | 
 | 		extMemProperties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA; | 
 | 		extMemProperties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA; | 
 | 		extMemProperties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; | 
 | 		return; | 
 | 	} | 
 | #endif | 
 | 	extMemProperties->compatibleHandleTypes = 0; | 
 | 	extMemProperties->exportFromImportedHandleTypes = 0; | 
 | 	extMemProperties->externalMemoryFeatures = 0; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkSamplerYcbcrConversionImageFormatProperties *properties) const | 
 | { | 
 | 	properties->combinedImageSamplerDescriptorCount = 1;  // Need only one descriptor for YCbCr sampling. | 
 | } | 
 |  | 
 | #ifdef __ANDROID__ | 
 | void PhysicalDevice::getProperties(VkPhysicalDevicePresentationPropertiesANDROID *properties) const | 
 | { | 
 | 	properties->sharedImage = VK_FALSE; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkAndroidHardwareBufferUsageANDROID *ahbProperties) const | 
 | { | 
 | 	// Maps VkImageUsageFlags to AHB usage flags using this table from the Vulkan spec | 
 | 	// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#memory-external-android-hardware-buffer-usage | 
 |  | 
 | 	// VK_IMAGE_CREATE_PROTECTED_BIT not currently supported. | 
 | 	ASSERT((pImageFormatInfo->flags & VK_IMAGE_CREATE_PROTECTED_BIT) == 0); | 
 |  | 
 | 	// "It must include at least one GPU usage flag (AHARDWAREBUFFER_USAGE_GPU_*), even if none of the corresponding Vulkan usages or flags are requested." | 
 | 	uint64_t ahbUsage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; | 
 |  | 
 | 	// Already covered by the default GPU usage flag above. | 
 | 	// | 
 | 	// if ((vkUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) || (vkUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) | 
 | 	// { | 
 | 	// 	 ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; | 
 | 	// } | 
 |  | 
 | 	if((pImageFormatInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) || (pImageFormatInfo->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) | 
 | 	{ | 
 | 		ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER; | 
 | 	} | 
 |  | 
 | 	if(pImageFormatInfo->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) | 
 | 	{ | 
 | 		ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP; | 
 | 	} | 
 |  | 
 | 	if(pImageFormatInfo->flags & VK_IMAGE_CREATE_PROTECTED_BIT) | 
 | 	{ | 
 | 		ahbUsage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT; | 
 | 	} | 
 |  | 
 | 	ahbProperties->androidHardwareBufferUsage = ahbUsage; | 
 | } | 
 | #endif | 
 |  | 
 | void PhysicalDevice::getProperties(const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo, VkExternalBufferProperties *pExternalBufferProperties) const | 
 | { | 
 | 	VkExternalMemoryProperties *properties = &pExternalBufferProperties->externalMemoryProperties; | 
 |  | 
 | #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD || SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER | 
 | 	const VkExternalMemoryHandleTypeFlagBits *handleType = &pExternalBufferInfo->handleType; | 
 | #endif | 
 |  | 
 | #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD | 
 | 	if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) | 
 | 	{ | 
 | 		properties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; | 
 | 		properties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; | 
 | 		properties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; | 
 | 		return; | 
 | 	} | 
 | #endif | 
 | #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER | 
 | 	if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) | 
 | 	{ | 
 | 		properties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; | 
 | 		properties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; | 
 | 		properties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; | 
 | 		return; | 
 | 	} | 
 | #endif | 
 | 	properties->compatibleHandleTypes = 0; | 
 | 	properties->exportFromImportedHandleTypes = 0; | 
 | 	properties->externalMemoryFeatures = 0; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo, VkExternalFenceProperties *pExternalFenceProperties) const | 
 | { | 
 | 	pExternalFenceProperties->compatibleHandleTypes = 0; | 
 | 	pExternalFenceProperties->exportFromImportedHandleTypes = 0; | 
 | 	pExternalFenceProperties->externalFenceFeatures = 0; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, VkExternalSemaphoreProperties *pExternalSemaphoreProperties) const | 
 | { | 
 | 	for(const auto *nextInfo = reinterpret_cast<const VkBaseInStructure *>(pExternalSemaphoreInfo->pNext); | 
 | 	    nextInfo != nullptr; nextInfo = nextInfo->pNext) | 
 | 	{ | 
 | 		switch(nextInfo->sType) | 
 | 		{ | 
 | 		case VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO: | 
 | 			{ | 
 | 				const auto *tlsInfo = reinterpret_cast<const VkSemaphoreTypeCreateInfo *>(nextInfo); | 
 | 				// Timeline Semaphore does not support external semaphore | 
 | 				if(tlsInfo->semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE) | 
 | 				{ | 
 | 					pExternalSemaphoreProperties->compatibleHandleTypes = 0; | 
 | 					pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; | 
 | 					pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; | 
 | 					return; | 
 | 				} | 
 | 			} | 
 | 			break; | 
 | 		default: | 
 | 			WARN("nextInfo->sType = %s", vk::Stringify(nextInfo->sType).c_str()); | 
 | 			break; | 
 | 		} | 
 | 	} | 
 |  | 
 | #if SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD | 
 | 	if(pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) | 
 | 	{ | 
 | 		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 | VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT; | 
 | 		return; | 
 | 	} | 
 | #endif | 
 | #if VK_USE_PLATFORM_FUCHSIA | 
 | 	if(pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA) | 
 | 	{ | 
 | 		pExternalSemaphoreProperties->compatibleHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA; | 
 | 		pExternalSemaphoreProperties->exportFromImportedHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA; | 
 | 		pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT; | 
 | 		return; | 
 | 	} | 
 | #endif | 
 | 	pExternalSemaphoreProperties->compatibleHandleTypes = 0; | 
 | 	pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; | 
 | 	pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceExternalMemoryHostPropertiesEXT *properties) const | 
 | { | 
 | 	properties->minImportedHostPointerAlignment = REQUIRED_MEMORY_ALIGNMENT; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getDriverProperties(T *properties) | 
 | { | 
 | 	properties->driverID = VK_DRIVER_ID_GOOGLE_SWIFTSHADER_KHR; | 
 | 	strcpy(properties->driverName, "SwiftShader driver"); | 
 | 	strcpy(properties->driverInfo, ""); | 
 | 	properties->conformanceVersion = { 1, 1, 3, 3 }; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceDriverProperties *properties) const | 
 | { | 
 | 	getDriverProperties(properties); | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceLineRasterizationPropertiesEXT *properties) const | 
 | { | 
 | 	properties->lineSubPixelPrecisionBits = vk::SUBPIXEL_PRECISION_BITS; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceProvokingVertexPropertiesEXT *properties) const | 
 | { | 
 | 	properties->provokingVertexModePerPipeline = VK_TRUE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getFloatControlsProperties(T *properties) | 
 | { | 
 | 	// The spec states: | 
 | 	// shaderSignedZeroInfNanPreserveFloat32 is a boolean value indicating whether | 
 | 	// sign of a zero, Nans and +/-infinity can be preserved in 32-bit floating-point | 
 | 	// computations. It also indicates whether the SignedZeroInfNanPreserve execution | 
 | 	// mode can be used for 32-bit floating-point types. | 
 | 	// | 
 | 	// There are similar clauses for all the shader* bools present here. | 
 | 	// | 
 | 	// It does not state that an implementation must report its default behavior using | 
 | 	// these variables. At this time SwiftShader does not expose any preserve, denormal, | 
 | 	// or rounding controls. | 
 | 	properties->denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE; | 
 | 	properties->roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE; | 
 | 	properties->shaderSignedZeroInfNanPreserveFloat16 = VK_FALSE; | 
 | 	properties->shaderSignedZeroInfNanPreserveFloat32 = VK_FALSE; | 
 | 	properties->shaderSignedZeroInfNanPreserveFloat64 = VK_FALSE; | 
 | 	properties->shaderDenormPreserveFloat16 = VK_FALSE; | 
 | 	properties->shaderDenormPreserveFloat32 = VK_FALSE; | 
 | 	properties->shaderDenormPreserveFloat64 = VK_FALSE; | 
 | 	properties->shaderDenormFlushToZeroFloat16 = VK_FALSE; | 
 | 	properties->shaderDenormFlushToZeroFloat32 = VK_FALSE; | 
 | 	properties->shaderDenormFlushToZeroFloat64 = VK_FALSE; | 
 | 	properties->shaderRoundingModeRTZFloat16 = VK_FALSE; | 
 | 	properties->shaderRoundingModeRTZFloat32 = VK_FALSE; | 
 | 	properties->shaderRoundingModeRTZFloat64 = VK_FALSE; | 
 | 	properties->shaderRoundingModeRTEFloat16 = VK_FALSE; | 
 | 	properties->shaderRoundingModeRTEFloat32 = VK_FALSE; | 
 | 	properties->shaderRoundingModeRTEFloat64 = VK_FALSE; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceFloatControlsProperties *properties) const | 
 | { | 
 | 	getFloatControlsProperties(properties); | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getDescriptorIndexingProperties(T *properties) | 
 | { | 
 | 	// "The UpdateAfterBind descriptor limits must each be greater than or equal to | 
 | 	//  the corresponding non-UpdateAfterBind limit." | 
 | 	const VkPhysicalDeviceLimits &limits = PhysicalDevice::getLimits(); | 
 |  | 
 | 	properties->maxUpdateAfterBindDescriptorsInAllPools = 0; | 
 | 	properties->shaderUniformBufferArrayNonUniformIndexingNative = VK_FALSE; | 
 | 	properties->shaderSampledImageArrayNonUniformIndexingNative = VK_FALSE; | 
 | 	properties->shaderStorageBufferArrayNonUniformIndexingNative = VK_FALSE; | 
 | 	properties->shaderStorageImageArrayNonUniformIndexingNative = VK_FALSE; | 
 | 	properties->shaderInputAttachmentArrayNonUniformIndexingNative = VK_FALSE; | 
 | 	properties->robustBufferAccessUpdateAfterBind = VK_FALSE; | 
 | 	properties->quadDivergentImplicitLod = VK_FALSE; | 
 | 	properties->maxPerStageDescriptorUpdateAfterBindSamplers = limits.maxPerStageDescriptorSamplers; | 
 | 	properties->maxPerStageDescriptorUpdateAfterBindUniformBuffers = limits.maxPerStageDescriptorUniformBuffers; | 
 | 	properties->maxPerStageDescriptorUpdateAfterBindStorageBuffers = limits.maxPerStageDescriptorStorageBuffers; | 
 | 	properties->maxPerStageDescriptorUpdateAfterBindSampledImages = limits.maxPerStageDescriptorSampledImages; | 
 | 	properties->maxPerStageDescriptorUpdateAfterBindStorageImages = limits.maxPerStageDescriptorStorageImages; | 
 | 	properties->maxPerStageDescriptorUpdateAfterBindInputAttachments = limits.maxPerStageDescriptorInputAttachments; | 
 | 	properties->maxPerStageUpdateAfterBindResources = limits.maxPerStageResources; | 
 | 	properties->maxDescriptorSetUpdateAfterBindSamplers = limits.maxDescriptorSetSamplers; | 
 | 	properties->maxDescriptorSetUpdateAfterBindUniformBuffers = limits.maxDescriptorSetUniformBuffers; | 
 | 	properties->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = limits.maxDescriptorSetUniformBuffersDynamic; | 
 | 	properties->maxDescriptorSetUpdateAfterBindStorageBuffers = limits.maxDescriptorSetStorageBuffers; | 
 | 	properties->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = limits.maxDescriptorSetStorageBuffersDynamic; | 
 | 	properties->maxDescriptorSetUpdateAfterBindSampledImages = limits.maxDescriptorSetSampledImages; | 
 | 	properties->maxDescriptorSetUpdateAfterBindStorageImages = limits.maxDescriptorSetStorageImages; | 
 | 	properties->maxDescriptorSetUpdateAfterBindInputAttachments = limits.maxDescriptorSetInputAttachments; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceDescriptorIndexingProperties *properties) const | 
 | { | 
 | 	getDescriptorIndexingProperties(properties); | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getDepthStencilResolveProperties(T *properties) | 
 | { | 
 | 	properties->supportedDepthResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT | VK_RESOLVE_MODE_NONE; | 
 | 	properties->supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT | VK_RESOLVE_MODE_NONE; | 
 | 	properties->independentResolveNone = VK_TRUE; | 
 | 	properties->independentResolve = VK_TRUE; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceDepthStencilResolveProperties *properties) const | 
 | { | 
 | 	getDepthStencilResolveProperties(properties); | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceCustomBorderColorPropertiesEXT *properties) const | 
 | { | 
 | 	properties->maxCustomBorderColorSamplers = MAX_SAMPLER_ALLOCATION_COUNT; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT *properties) const | 
 | { | 
 | 	// Note: advancedBlendMaxColorAttachments could already support sw::MAX_COLOR_BUFFERS as is, | 
 | 	//       but using a value of 1 is enough for ANGLE to implement GL_KHR_blend_equation_advanced | 
 | 	properties->advancedBlendMaxColorAttachments = 1; | 
 | 	properties->advancedBlendIndependentBlend = VK_FALSE; | 
 | 	properties->advancedBlendNonPremultipliedSrcColor = VK_FALSE; | 
 | 	properties->advancedBlendNonPremultipliedDstColor = VK_FALSE; | 
 | 	properties->advancedBlendCorrelatedOverlap = VK_FALSE; | 
 | 	properties->advancedBlendAllOperations = VK_FALSE; | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getSamplerFilterMinmaxProperties(T *properties) | 
 | { | 
 | 	properties->filterMinmaxSingleComponentFormats = VK_FALSE; | 
 | 	properties->filterMinmaxImageComponentMapping = VK_FALSE; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceSamplerFilterMinmaxProperties *properties) const | 
 | { | 
 | 	getSamplerFilterMinmaxProperties(properties); | 
 | } | 
 |  | 
 | template<typename T> | 
 | static void getTimelineSemaphoreProperties(T *properties) | 
 | { | 
 | 	// Our implementation of Timeline Semaphores allows the timeline to advance to any value from any value. | 
 | 	properties->maxTimelineSemaphoreValueDifference = (uint64_t)-1; | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceTimelineSemaphoreProperties *properties) const | 
 | { | 
 | 	getTimelineSemaphoreProperties(properties); | 
 | } | 
 |  | 
 | void PhysicalDevice::getProperties(VkPhysicalDeviceVulkan12Properties *properties) const | 
 | { | 
 | 	getDriverProperties(properties); | 
 | 	getFloatControlsProperties(properties); | 
 | 	getDescriptorIndexingProperties(properties); | 
 | 	getDepthStencilResolveProperties(properties); | 
 | 	getSamplerFilterMinmaxProperties(properties); | 
 | 	getTimelineSemaphoreProperties(properties); | 
 | 	properties->framebufferIntegerColorSampleCounts = VK_SAMPLE_COUNT_1_BIT; | 
 | } | 
 |  | 
 | bool PhysicalDevice::hasFeatures(const VkPhysicalDeviceFeatures &requestedFeatures) const | 
 | { | 
 | 	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); | 
 |  | 
 | 	for(unsigned int i = 0; i < featureCount; i++) | 
 | 	{ | 
 | 		if((requestedFeature[i] != VK_FALSE) && (supportedFeature[i] == VK_FALSE)) | 
 | 		{ | 
 | 			return false; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	return true; | 
 | } | 
 |  | 
 | // CheckFeature returns false if requested is asking for a feature that is not supported | 
 | #define CheckFeature(requested, supported, feature) (requested->feature == VK_FALSE || supported.feature == VK_TRUE) | 
 |  | 
 | template<typename T> | 
 | T PhysicalDevice::getSupportedFeatures(const T *requested) const | 
 | { | 
 | 	VkPhysicalDeviceFeatures2 features; | 
 | 	features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; | 
 | 	T supported; | 
 | 	supported.sType = requested->sType; | 
 | 	supported.pNext = nullptr; | 
 | 	features.pNext = &supported; | 
 | 	getFeatures2(&features); | 
 | 	return supported; | 
 | } | 
 |  | 
 | bool PhysicalDevice::hasExtendedFeatures(const VkPhysicalDeviceLineRasterizationFeaturesEXT *requested) const | 
 | { | 
 | 	auto supported = getSupportedFeatures(requested); | 
 |  | 
 | 	return CheckFeature(requested, supported, rectangularLines) && | 
 | 	       CheckFeature(requested, supported, bresenhamLines) && | 
 | 	       CheckFeature(requested, supported, smoothLines) && | 
 | 	       CheckFeature(requested, supported, stippledRectangularLines) && | 
 | 	       CheckFeature(requested, supported, stippledBresenhamLines) && | 
 | 	       CheckFeature(requested, supported, stippledSmoothLines); | 
 | } | 
 |  | 
 | bool PhysicalDevice::hasExtendedFeatures(const VkPhysicalDeviceProvokingVertexFeaturesEXT *requested) const | 
 | { | 
 | 	auto supported = getSupportedFeatures(requested); | 
 |  | 
 | 	return CheckFeature(requested, supported, provokingVertexLast) && | 
 | 	       CheckFeature(requested, supported, transformFeedbackPreservesProvokingVertex); | 
 | } | 
 |  | 
 | bool PhysicalDevice::hasExtendedFeatures(const VkPhysicalDeviceVulkan11Features *requested) const | 
 | { | 
 | 	auto supported = getSupportedFeatures(requested); | 
 |  | 
 | 	return CheckFeature(requested, supported, storageBuffer16BitAccess) && | 
 | 	       CheckFeature(requested, supported, uniformAndStorageBuffer16BitAccess) && | 
 | 	       CheckFeature(requested, supported, storagePushConstant16) && | 
 | 	       CheckFeature(requested, supported, storageInputOutput16) && | 
 | 	       CheckFeature(requested, supported, multiview) && | 
 | 	       CheckFeature(requested, supported, multiviewGeometryShader) && | 
 | 	       CheckFeature(requested, supported, multiviewTessellationShader) && | 
 | 	       CheckFeature(requested, supported, variablePointersStorageBuffer) && | 
 | 	       CheckFeature(requested, supported, variablePointers) && | 
 | 	       CheckFeature(requested, supported, protectedMemory) && | 
 | 	       CheckFeature(requested, supported, samplerYcbcrConversion) && | 
 | 	       CheckFeature(requested, supported, shaderDrawParameters); | 
 | } | 
 |  | 
 | bool PhysicalDevice::hasExtendedFeatures(const VkPhysicalDeviceVulkan12Features *requested) const | 
 | { | 
 | 	auto supported = getSupportedFeatures(requested); | 
 |  | 
 | 	return CheckFeature(requested, supported, samplerMirrorClampToEdge) && | 
 | 	       CheckFeature(requested, supported, drawIndirectCount) && | 
 | 	       CheckFeature(requested, supported, storageBuffer8BitAccess) && | 
 | 	       CheckFeature(requested, supported, uniformAndStorageBuffer8BitAccess) && | 
 | 	       CheckFeature(requested, supported, storagePushConstant8) && | 
 | 	       CheckFeature(requested, supported, shaderBufferInt64Atomics) && | 
 | 	       CheckFeature(requested, supported, shaderSharedInt64Atomics) && | 
 | 	       CheckFeature(requested, supported, shaderFloat16) && | 
 | 	       CheckFeature(requested, supported, shaderInt8) && | 
 | 	       CheckFeature(requested, supported, descriptorIndexing) && | 
 | 	       CheckFeature(requested, supported, shaderInputAttachmentArrayDynamicIndexing) && | 
 | 	       CheckFeature(requested, supported, shaderUniformTexelBufferArrayDynamicIndexing) && | 
 | 	       CheckFeature(requested, supported, shaderStorageTexelBufferArrayDynamicIndexing) && | 
 | 	       CheckFeature(requested, supported, shaderUniformBufferArrayNonUniformIndexing) && | 
 | 	       CheckFeature(requested, supported, shaderSampledImageArrayNonUniformIndexing) && | 
 | 	       CheckFeature(requested, supported, shaderStorageBufferArrayNonUniformIndexing) && | 
 | 	       CheckFeature(requested, supported, shaderStorageImageArrayNonUniformIndexing) && | 
 | 	       CheckFeature(requested, supported, shaderInputAttachmentArrayNonUniformIndexing) && | 
 | 	       CheckFeature(requested, supported, shaderUniformTexelBufferArrayNonUniformIndexing) && | 
 | 	       CheckFeature(requested, supported, shaderStorageTexelBufferArrayNonUniformIndexing) && | 
 | 	       CheckFeature(requested, supported, descriptorBindingUniformBufferUpdateAfterBind) && | 
 | 	       CheckFeature(requested, supported, descriptorBindingSampledImageUpdateAfterBind) && | 
 | 	       CheckFeature(requested, supported, descriptorBindingStorageImageUpdateAfterBind) && | 
 | 	       CheckFeature(requested, supported, descriptorBindingStorageBufferUpdateAfterBind) && | 
 | 	       CheckFeature(requested, supported, descriptorBindingUniformTexelBufferUpdateAfterBind) && | 
 | 	       CheckFeature(requested, supported, descriptorBindingStorageTexelBufferUpdateAfterBind) && | 
 | 	       CheckFeature(requested, supported, descriptorBindingUpdateUnusedWhilePending) && | 
 | 	       CheckFeature(requested, supported, descriptorBindingPartiallyBound) && | 
 | 	       CheckFeature(requested, supported, descriptorBindingVariableDescriptorCount) && | 
 | 	       CheckFeature(requested, supported, runtimeDescriptorArray) && | 
 | 	       CheckFeature(requested, supported, samplerFilterMinmax) && | 
 | 	       CheckFeature(requested, supported, scalarBlockLayout) && | 
 | 	       CheckFeature(requested, supported, imagelessFramebuffer) && | 
 | 	       CheckFeature(requested, supported, uniformBufferStandardLayout) && | 
 | 	       CheckFeature(requested, supported, shaderSubgroupExtendedTypes) && | 
 | 	       CheckFeature(requested, supported, separateDepthStencilLayouts) && | 
 | 	       CheckFeature(requested, supported, hostQueryReset) && | 
 | 	       CheckFeature(requested, supported, timelineSemaphore) && | 
 | 	       CheckFeature(requested, supported, bufferDeviceAddress) && | 
 | 	       CheckFeature(requested, supported, bufferDeviceAddressCaptureReplay) && | 
 | 	       CheckFeature(requested, supported, bufferDeviceAddressMultiDevice) && | 
 | 	       CheckFeature(requested, supported, vulkanMemoryModel) && | 
 | 	       CheckFeature(requested, supported, vulkanMemoryModelDeviceScope) && | 
 | 	       CheckFeature(requested, supported, vulkanMemoryModelAvailabilityVisibilityChains) && | 
 | 	       CheckFeature(requested, supported, shaderOutputViewportIndex) && | 
 | 	       CheckFeature(requested, supported, shaderOutputLayer) && | 
 | 	       CheckFeature(requested, supported, subgroupBroadcastDynamicId); | 
 | } | 
 |  | 
 | bool PhysicalDevice::hasExtendedFeatures(const VkPhysicalDeviceDepthClipEnableFeaturesEXT *requested) const | 
 | { | 
 | 	auto supported = getSupportedFeatures(requested); | 
 |  | 
 | 	return CheckFeature(requested, supported, depthClipEnable); | 
 | } | 
 |  | 
 | bool PhysicalDevice::hasExtendedFeatures(const VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT *requested) const | 
 | { | 
 | 	auto supported = getSupportedFeatures(requested); | 
 |  | 
 | 	return CheckFeature(requested, supported, advancedBlendCoherentOperations); | 
 | } | 
 | #undef CheckFeature | 
 |  | 
 | void PhysicalDevice::GetFormatProperties(Format format, VkFormatProperties *pFormatProperties) | 
 | { | 
 | 	VkFormatProperties3KHR formatProperties3 = {}; | 
 | 	GetFormatProperties(format, &formatProperties3); | 
 |  | 
 | 	// VkFormatFeatureFlags2KHR is a 64-bit extension of the 32-bit VkFormatFeatureFlags, | 
 | 	// so when querying the legacy flags just return the lower 32-bit portion. | 
 | 	pFormatProperties->linearTilingFeatures = static_cast<VkFormatFeatureFlags>(formatProperties3.linearTilingFeatures); | 
 | 	pFormatProperties->optimalTilingFeatures = static_cast<VkFormatFeatureFlags>(formatProperties3.optimalTilingFeatures); | 
 | 	pFormatProperties->bufferFeatures = static_cast<VkFormatFeatureFlags>(formatProperties3.bufferFeatures); | 
 | } | 
 |  | 
 | void PhysicalDevice::GetFormatProperties(Format format, VkFormatProperties3KHR *pFormatProperties) | 
 | { | 
 | 	pFormatProperties->linearTilingFeatures = 0;   // Unsupported format | 
 | 	pFormatProperties->optimalTilingFeatures = 0;  // Unsupported format | 
 | 	pFormatProperties->bufferFeatures = 0;         // Unsupported format | 
 |  | 
 | 	switch(format) | 
 | 	{ | 
 | 	// Formats which can be sampled *and* filtered | 
 | 	case VK_FORMAT_R4G4B4A4_UNORM_PACK16: | 
 | 	case VK_FORMAT_B4G4R4A4_UNORM_PACK16: | 
 | 	case VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT: | 
 | 	case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT: | 
 | 	case VK_FORMAT_R5G6B5_UNORM_PACK16: | 
 | 	case VK_FORMAT_B5G6R5_UNORM_PACK16: | 
 | 	case VK_FORMAT_R5G5B5A1_UNORM_PACK16: | 
 | 	case VK_FORMAT_B5G5R5A1_UNORM_PACK16: | 
 | 	case VK_FORMAT_A1R5G5B5_UNORM_PACK16: | 
 | 	case VK_FORMAT_R8_UNORM: | 
 | 	case VK_FORMAT_R8_SRGB: | 
 | 	case VK_FORMAT_R8_SNORM: | 
 | 	case VK_FORMAT_R8G8_UNORM: | 
 | 	case VK_FORMAT_R8G8_SRGB: | 
 | 	case VK_FORMAT_R8G8_SNORM: | 
 | 	case VK_FORMAT_R8G8B8A8_UNORM: | 
 | 	case VK_FORMAT_R8G8B8A8_SNORM: | 
 | 	case VK_FORMAT_R8G8B8A8_SRGB: | 
 | 	case VK_FORMAT_B8G8R8A8_UNORM: | 
 | 	case VK_FORMAT_B8G8R8A8_SRGB: | 
 | 	case VK_FORMAT_A8B8G8R8_UNORM_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_SNORM_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_SRGB_PACK32: | 
 | 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32: | 
 | 	case VK_FORMAT_A2R10G10B10_UNORM_PACK32: | 
 | 	case VK_FORMAT_R16_UNORM: | 
 | 	case VK_FORMAT_R16_SNORM: | 
 | 	case VK_FORMAT_R16_SFLOAT: | 
 | 	case VK_FORMAT_R16G16_UNORM: | 
 | 	case VK_FORMAT_R16G16_SNORM: | 
 | 	case VK_FORMAT_R16G16_SFLOAT: | 
 | 	case VK_FORMAT_R16G16B16A16_UNORM: | 
 | 	case VK_FORMAT_R16G16B16A16_SNORM: | 
 | 	case VK_FORMAT_R16G16B16A16_SFLOAT: | 
 | 	case VK_FORMAT_R32_SFLOAT: | 
 | 	case VK_FORMAT_R32G32_SFLOAT: | 
 | 	case VK_FORMAT_R32G32B32A32_SFLOAT: | 
 | 	case VK_FORMAT_B10G11R11_UFLOAT_PACK32: | 
 | 	case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: | 
 | 	case VK_FORMAT_BC1_RGB_UNORM_BLOCK: | 
 | 	case VK_FORMAT_BC1_RGB_SRGB_BLOCK: | 
 | 	case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: | 
 | 	case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: | 
 | 	case VK_FORMAT_BC2_UNORM_BLOCK: | 
 | 	case VK_FORMAT_BC2_SRGB_BLOCK: | 
 | 	case VK_FORMAT_BC3_UNORM_BLOCK: | 
 | 	case VK_FORMAT_BC3_SRGB_BLOCK: | 
 | 	case VK_FORMAT_BC4_UNORM_BLOCK: | 
 | 	case VK_FORMAT_BC4_SNORM_BLOCK: | 
 | 	case VK_FORMAT_BC5_UNORM_BLOCK: | 
 | 	case VK_FORMAT_BC5_SNORM_BLOCK: | 
 | 	case VK_FORMAT_BC6H_UFLOAT_BLOCK: | 
 | 	case VK_FORMAT_BC6H_SFLOAT_BLOCK: | 
 | 	case VK_FORMAT_BC7_UNORM_BLOCK: | 
 | 	case VK_FORMAT_BC7_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: | 
 | 	case VK_FORMAT_EAC_R11_UNORM_BLOCK: | 
 | 	case VK_FORMAT_EAC_R11_SNORM_BLOCK: | 
 | 	case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: | 
 | 	case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: | 
 | #ifdef SWIFTSHADER_ENABLE_ASTC | 
 | 	case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: | 
 | 	case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: | 
 | 	case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: | 
 | #endif | 
 | 	case VK_FORMAT_D16_UNORM: | 
 | 	case VK_FORMAT_D32_SFLOAT: | 
 | 	case VK_FORMAT_D32_SFLOAT_S8_UINT: | 
 | 		pFormatProperties->optimalTilingFeatures |= | 
 | 		    VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT; | 
 | 		// [[fallthrough]] | 
 |  | 
 | 	// Formats which can be sampled, but don't support filtering | 
 | 	case VK_FORMAT_R8_UINT: | 
 | 	case VK_FORMAT_R8_SINT: | 
 | 	case VK_FORMAT_R8G8_UINT: | 
 | 	case VK_FORMAT_R8G8_SINT: | 
 | 	case VK_FORMAT_R8G8B8A8_UINT: | 
 | 	case VK_FORMAT_R8G8B8A8_SINT: | 
 | 	case VK_FORMAT_A8B8G8R8_UINT_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_SINT_PACK32: | 
 | 	case VK_FORMAT_A2B10G10R10_UINT_PACK32: | 
 | 	case VK_FORMAT_A2R10G10B10_UINT_PACK32: | 
 | 	case VK_FORMAT_R16_UINT: | 
 | 	case VK_FORMAT_R16_SINT: | 
 | 	case VK_FORMAT_R16G16_UINT: | 
 | 	case VK_FORMAT_R16G16_SINT: | 
 | 	case VK_FORMAT_R16G16B16A16_UINT: | 
 | 	case VK_FORMAT_R16G16B16A16_SINT: | 
 | 	case VK_FORMAT_R32_UINT: | 
 | 	case VK_FORMAT_R32_SINT: | 
 | 	case VK_FORMAT_R32G32_UINT: | 
 | 	case VK_FORMAT_R32G32_SINT: | 
 | 	case VK_FORMAT_R32G32B32A32_UINT: | 
 | 	case VK_FORMAT_R32G32B32A32_SINT: | 
 | 	case VK_FORMAT_S8_UINT: | 
 | 		pFormatProperties->optimalTilingFeatures |= | 
 | 		    VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | | 
 | 		    VK_FORMAT_FEATURE_BLIT_SRC_BIT | | 
 | 		    VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | | 
 | 		    VK_FORMAT_FEATURE_TRANSFER_DST_BIT; | 
 | 		break; | 
 |  | 
 | 	// YCbCr formats: | 
 | 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: | 
 | 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: | 
 | 		pFormatProperties->optimalTilingFeatures |= | 
 | 		    VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | | 
 | 		    VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | | 
 | 		    VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | | 
 | 		    VK_FORMAT_FEATURE_TRANSFER_DST_BIT | | 
 | 		    VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT; | 
 | 		break; | 
 | 	default: | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	switch(format) | 
 | 	{ | 
 | 	// Vulkan 1.0 mandatory storage image formats supporting atomic operations | 
 | 	case VK_FORMAT_R32_UINT: | 
 | 	case VK_FORMAT_R32_SINT: | 
 | 		pFormatProperties->optimalTilingFeatures |= | 
 | 		    VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT; | 
 | 		pFormatProperties->bufferFeatures |= | 
 | 		    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT; | 
 | 		// [[fallthrough]] | 
 | 	// Vulkan 1.0 mandatory storage image formats | 
 | 	case VK_FORMAT_R8G8B8A8_UNORM: | 
 | 	case VK_FORMAT_R8G8B8A8_SNORM: | 
 | 	case VK_FORMAT_R8G8B8A8_UINT: | 
 | 	case VK_FORMAT_R8G8B8A8_SINT: | 
 | 	case VK_FORMAT_R16G16B16A16_UINT: | 
 | 	case VK_FORMAT_R16G16B16A16_SINT: | 
 | 	case VK_FORMAT_R16G16B16A16_SFLOAT: | 
 | 	case VK_FORMAT_R32_SFLOAT: | 
 | 	case VK_FORMAT_R32G32_UINT: | 
 | 	case VK_FORMAT_R32G32_SINT: | 
 | 	case VK_FORMAT_R32G32_SFLOAT: | 
 | 	case VK_FORMAT_R32G32B32A32_UINT: | 
 | 	case VK_FORMAT_R32G32B32A32_SINT: | 
 | 	case VK_FORMAT_R32G32B32A32_SFLOAT: | 
 | 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32: | 
 | 	case VK_FORMAT_A2B10G10R10_UINT_PACK32: | 
 | 	// Vulkan 1.0 shaderStorageImageExtendedFormats | 
 | 	case VK_FORMAT_R16G16_SFLOAT: | 
 | 	case VK_FORMAT_B10G11R11_UFLOAT_PACK32: | 
 | 	case VK_FORMAT_R16_SFLOAT: | 
 | 	case VK_FORMAT_R16G16B16A16_UNORM: | 
 | 	case VK_FORMAT_R16G16_UNORM: | 
 | 	case VK_FORMAT_R8G8_UNORM: | 
 | 	case VK_FORMAT_R16_UNORM: | 
 | 	case VK_FORMAT_R8_UNORM: | 
 | 	case VK_FORMAT_R16G16B16A16_SNORM: | 
 | 	case VK_FORMAT_R16G16_SNORM: | 
 | 	case VK_FORMAT_R8G8_SNORM: | 
 | 	case VK_FORMAT_R16_SNORM: | 
 | 	case VK_FORMAT_R8_SNORM: | 
 | 	case VK_FORMAT_R16G16_SINT: | 
 | 	case VK_FORMAT_R8G8_SINT: | 
 | 	case VK_FORMAT_R16_SINT: | 
 | 	case VK_FORMAT_R8_SINT: | 
 | 	case VK_FORMAT_R16G16_UINT: | 
 | 	case VK_FORMAT_R8G8_UINT: | 
 | 	case VK_FORMAT_R16_UINT: | 
 | 	case VK_FORMAT_R8_UINT: | 
 | 	// Additional formats not listed under "Formats without shader storage format" | 
 | 	case VK_FORMAT_A8B8G8R8_UNORM_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_SNORM_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_UINT_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_SINT_PACK32: | 
 | 	case VK_FORMAT_B8G8R8A8_UNORM: | 
 | 	case VK_FORMAT_B8G8R8A8_SRGB: | 
 | 		pFormatProperties->optimalTilingFeatures |= | 
 | 		    VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | | 
 | 		    VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR; | 
 | 		pFormatProperties->bufferFeatures |= | 
 | 		    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT; | 
 | 		break; | 
 | 	default: | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	switch(format) | 
 | 	{ | 
 | 	case VK_FORMAT_R5G6B5_UNORM_PACK16: | 
 | 	case VK_FORMAT_A1R5G5B5_UNORM_PACK16: | 
 | 	case VK_FORMAT_R4G4B4A4_UNORM_PACK16: | 
 | 	case VK_FORMAT_B4G4R4A4_UNORM_PACK16: | 
 | 	case VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT: | 
 | 	case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT: | 
 | 	case VK_FORMAT_B5G6R5_UNORM_PACK16: | 
 | 	case VK_FORMAT_R5G5B5A1_UNORM_PACK16: | 
 | 	case VK_FORMAT_B5G5R5A1_UNORM_PACK16: | 
 | 	case VK_FORMAT_R8_UNORM: | 
 | 	case VK_FORMAT_R8G8_UNORM: | 
 | 	case VK_FORMAT_R8G8B8A8_UNORM: | 
 | 	case VK_FORMAT_R8G8B8A8_SRGB: | 
 | 	case VK_FORMAT_B8G8R8A8_UNORM: | 
 | 	case VK_FORMAT_B8G8R8A8_SRGB: | 
 | 	case VK_FORMAT_A8B8G8R8_UNORM_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_SRGB_PACK32: | 
 | 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32: | 
 | 	case VK_FORMAT_A2R10G10B10_UNORM_PACK32: | 
 | 	case VK_FORMAT_R16_SFLOAT: | 
 | 	case VK_FORMAT_R16G16_SFLOAT: | 
 | 	case VK_FORMAT_R16G16B16A16_SFLOAT: | 
 | 	case VK_FORMAT_R32_SFLOAT: | 
 | 	case VK_FORMAT_R32G32_SFLOAT: | 
 | 	case VK_FORMAT_R32G32B32A32_SFLOAT: | 
 | 	case VK_FORMAT_B10G11R11_UFLOAT_PACK32: | 
 | 	case VK_FORMAT_R8_UINT: | 
 | 	case VK_FORMAT_R8_SINT: | 
 | 	case VK_FORMAT_R8G8_UINT: | 
 | 	case VK_FORMAT_R8G8_SINT: | 
 | 	case VK_FORMAT_R8G8B8A8_UINT: | 
 | 	case VK_FORMAT_R8G8B8A8_SINT: | 
 | 	case VK_FORMAT_A8B8G8R8_UINT_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_SINT_PACK32: | 
 | 	case VK_FORMAT_A2B10G10R10_UINT_PACK32: | 
 | 	case VK_FORMAT_A2R10G10B10_UINT_PACK32: | 
 | 	case VK_FORMAT_R16_UNORM: | 
 | 	case VK_FORMAT_R16_UINT: | 
 | 	case VK_FORMAT_R16_SINT: | 
 | 	case VK_FORMAT_R16G16_UNORM: | 
 | 	case VK_FORMAT_R16G16_UINT: | 
 | 	case VK_FORMAT_R16G16_SINT: | 
 | 	case VK_FORMAT_R16G16B16A16_UNORM: | 
 | 	case VK_FORMAT_R16G16B16A16_UINT: | 
 | 	case VK_FORMAT_R16G16B16A16_SINT: | 
 | 	case VK_FORMAT_R32_UINT: | 
 | 	case VK_FORMAT_R32_SINT: | 
 | 	case VK_FORMAT_R32G32_UINT: | 
 | 	case VK_FORMAT_R32G32_SINT: | 
 | 	case VK_FORMAT_R32G32B32A32_UINT: | 
 | 	case VK_FORMAT_R32G32B32A32_SINT: | 
 | 		pFormatProperties->optimalTilingFeatures |= | 
 | 		    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | | 
 | 		    VK_FORMAT_FEATURE_BLIT_DST_BIT; | 
 | 		break; | 
 | 	case VK_FORMAT_S8_UINT: | 
 | 	case VK_FORMAT_D16_UNORM: | 
 | 	case VK_FORMAT_D32_SFLOAT:          // Note: either VK_FORMAT_D32_SFLOAT or VK_FORMAT_X8_D24_UNORM_PACK32 must be supported | 
 | 	case VK_FORMAT_D32_SFLOAT_S8_UINT:  // Note: either VK_FORMAT_D24_UNORM_S8_UINT or VK_FORMAT_D32_SFLOAT_S8_UINT must be supported | 
 | 		pFormatProperties->optimalTilingFeatures |= | 
 | 		    VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; | 
 | 		break; | 
 | 	default: | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	switch(format) | 
 | 	{ | 
 | 	case VK_FORMAT_D16_UNORM: | 
 | 	case VK_FORMAT_D32_SFLOAT:          // Note: either VK_FORMAT_D32_SFLOAT or VK_FORMAT_X8_D24_UNORM_PACK32 must be supported | 
 | 	case VK_FORMAT_D32_SFLOAT_S8_UINT:  // Note: either VK_FORMAT_D24_UNORM_S8_UINT or VK_FORMAT_D32_SFLOAT_S8_UINT must be supported | 
 | 		pFormatProperties->linearTilingFeatures |= | 
 | 		    VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR; | 
 | 		pFormatProperties->optimalTilingFeatures |= | 
 | 		    VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR; | 
 | 		break; | 
 | 	default: | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	if(format.supportsColorAttachmentBlend()) | 
 | 	{ | 
 | 		pFormatProperties->optimalTilingFeatures |= | 
 | 		    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT; | 
 | 	} | 
 |  | 
 | 	switch(format) | 
 | 	{ | 
 | 	case VK_FORMAT_R8_UNORM: | 
 | 	case VK_FORMAT_R8_SNORM: | 
 | 	case VK_FORMAT_R8_USCALED: | 
 | 	case VK_FORMAT_R8_SSCALED: | 
 | 	case VK_FORMAT_R8_UINT: | 
 | 	case VK_FORMAT_R8_SINT: | 
 | 	case VK_FORMAT_R8G8_UNORM: | 
 | 	case VK_FORMAT_R8G8_SNORM: | 
 | 	case VK_FORMAT_R8G8_USCALED: | 
 | 	case VK_FORMAT_R8G8_SSCALED: | 
 | 	case VK_FORMAT_R8G8_UINT: | 
 | 	case VK_FORMAT_R8G8_SINT: | 
 | 	case VK_FORMAT_R8G8B8A8_UNORM: | 
 | 	case VK_FORMAT_R8G8B8A8_SNORM: | 
 | 	case VK_FORMAT_R8G8B8A8_USCALED: | 
 | 	case VK_FORMAT_R8G8B8A8_SSCALED: | 
 | 	case VK_FORMAT_R8G8B8A8_UINT: | 
 | 	case VK_FORMAT_R8G8B8A8_SINT: | 
 | 	case VK_FORMAT_B8G8R8A8_UNORM: | 
 | 	case VK_FORMAT_A8B8G8R8_UNORM_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_SNORM_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_USCALED_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_SSCALED_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_UINT_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_SINT_PACK32: | 
 | 	case VK_FORMAT_A2R10G10B10_UNORM_PACK32: | 
 | 	case VK_FORMAT_A2R10G10B10_SNORM_PACK32: | 
 | 	case VK_FORMAT_A2R10G10B10_UINT_PACK32: | 
 | 	case VK_FORMAT_A2R10G10B10_SINT_PACK32: | 
 | 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32: | 
 | 	case VK_FORMAT_A2B10G10R10_SNORM_PACK32: | 
 | 	case VK_FORMAT_A2B10G10R10_UINT_PACK32: | 
 | 	case VK_FORMAT_A2B10G10R10_SINT_PACK32: | 
 | 	case VK_FORMAT_R16_UNORM: | 
 | 	case VK_FORMAT_R16_SNORM: | 
 | 	case VK_FORMAT_R16_USCALED: | 
 | 	case VK_FORMAT_R16_SSCALED: | 
 | 	case VK_FORMAT_R16_UINT: | 
 | 	case VK_FORMAT_R16_SINT: | 
 | 	case VK_FORMAT_R16_SFLOAT: | 
 | 	case VK_FORMAT_R16G16_UNORM: | 
 | 	case VK_FORMAT_R16G16_SNORM: | 
 | 	case VK_FORMAT_R16G16_USCALED: | 
 | 	case VK_FORMAT_R16G16_SSCALED: | 
 | 	case VK_FORMAT_R16G16_UINT: | 
 | 	case VK_FORMAT_R16G16_SINT: | 
 | 	case VK_FORMAT_R16G16_SFLOAT: | 
 | 	case VK_FORMAT_R16G16B16A16_UNORM: | 
 | 	case VK_FORMAT_R16G16B16A16_SNORM: | 
 | 	case VK_FORMAT_R16G16B16A16_USCALED: | 
 | 	case VK_FORMAT_R16G16B16A16_SSCALED: | 
 | 	case VK_FORMAT_R16G16B16A16_UINT: | 
 | 	case VK_FORMAT_R16G16B16A16_SINT: | 
 | 	case VK_FORMAT_R16G16B16A16_SFLOAT: | 
 | 	case VK_FORMAT_R32_UINT: | 
 | 	case VK_FORMAT_R32_SINT: | 
 | 	case VK_FORMAT_R32_SFLOAT: | 
 | 	case VK_FORMAT_R32G32_UINT: | 
 | 	case VK_FORMAT_R32G32_SINT: | 
 | 	case VK_FORMAT_R32G32_SFLOAT: | 
 | 	case VK_FORMAT_R32G32B32_UINT: | 
 | 	case VK_FORMAT_R32G32B32_SINT: | 
 | 	case VK_FORMAT_R32G32B32_SFLOAT: | 
 | 	case VK_FORMAT_R32G32B32A32_UINT: | 
 | 	case VK_FORMAT_R32G32B32A32_SINT: | 
 | 	case VK_FORMAT_R32G32B32A32_SFLOAT: | 
 | 		pFormatProperties->bufferFeatures |= | 
 | 		    VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT; | 
 | 		break; | 
 | 	default: | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	switch(format) | 
 | 	{ | 
 | 	// Vulkan 1.1 mandatory | 
 | 	case VK_FORMAT_R8_UNORM: | 
 | 	case VK_FORMAT_R8_SNORM: | 
 | 	case VK_FORMAT_R8_UINT: | 
 | 	case VK_FORMAT_R8_SINT: | 
 | 	case VK_FORMAT_R8G8_UNORM: | 
 | 	case VK_FORMAT_R8G8_SNORM: | 
 | 	case VK_FORMAT_R8G8_UINT: | 
 | 	case VK_FORMAT_R8G8_SINT: | 
 | 	case VK_FORMAT_R8G8B8A8_UNORM: | 
 | 	case VK_FORMAT_R8G8B8A8_SNORM: | 
 | 	case VK_FORMAT_R8G8B8A8_UINT: | 
 | 	case VK_FORMAT_R8G8B8A8_SINT: | 
 | 	case VK_FORMAT_B8G8R8A8_UNORM: | 
 | 	case VK_FORMAT_A8B8G8R8_UNORM_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_SNORM_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_UINT_PACK32: | 
 | 	case VK_FORMAT_A8B8G8R8_SINT_PACK32: | 
 | 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32: | 
 | 	case VK_FORMAT_A2B10G10R10_UINT_PACK32: | 
 | 	case VK_FORMAT_R16_UINT: | 
 | 	case VK_FORMAT_R16_SINT: | 
 | 	case VK_FORMAT_R16_SFLOAT: | 
 | 	case VK_FORMAT_R16G16_UINT: | 
 | 	case VK_FORMAT_R16G16_SINT: | 
 | 	case VK_FORMAT_R16G16_SFLOAT: | 
 | 	case VK_FORMAT_R16G16B16A16_UINT: | 
 | 	case VK_FORMAT_R16G16B16A16_SINT: | 
 | 	case VK_FORMAT_R16G16B16A16_SFLOAT: | 
 | 	case VK_FORMAT_R32_UINT: | 
 | 	case VK_FORMAT_R32_SINT: | 
 | 	case VK_FORMAT_R32_SFLOAT: | 
 | 	case VK_FORMAT_R32G32_UINT: | 
 | 	case VK_FORMAT_R32G32_SINT: | 
 | 	case VK_FORMAT_R32G32_SFLOAT: | 
 | 	case VK_FORMAT_R32G32B32A32_UINT: | 
 | 	case VK_FORMAT_R32G32B32A32_SINT: | 
 | 	case VK_FORMAT_R32G32B32A32_SFLOAT: | 
 | 	case VK_FORMAT_B10G11R11_UFLOAT_PACK32: | 
 | 	// Optional | 
 | 	case VK_FORMAT_A2R10G10B10_UNORM_PACK32: | 
 | 	case VK_FORMAT_A2R10G10B10_UINT_PACK32: | 
 | 		pFormatProperties->bufferFeatures |= | 
 | 		    VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT; | 
 | 		break; | 
 | 	default: | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	if(pFormatProperties->optimalTilingFeatures) | 
 | 	{ | 
 | 		pFormatProperties->linearTilingFeatures |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | | 
 | 		                                           VK_FORMAT_FEATURE_TRANSFER_DST_BIT; | 
 |  | 
 | 		if(!format.isCompressed()) | 
 | 		{ | 
 | 			if(pFormatProperties->optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) | 
 | 			{ | 
 | 				pFormatProperties->linearTilingFeatures |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; | 
 | 			} | 
 | 			if(pFormatProperties->optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) | 
 | 			{ | 
 | 				pFormatProperties->linearTilingFeatures |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT; | 
 | 			} | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | void PhysicalDevice::getImageFormatProperties(Format format, VkImageType type, VkImageTiling tiling, | 
 |                                               VkImageUsageFlags usage, VkImageCreateFlags flags, | 
 |                                               VkImageFormatProperties *pImageFormatProperties) const | 
 | { | 
 | 	pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT; | 
 | 	pImageFormatProperties->maxArrayLayers = vk::MAX_IMAGE_ARRAY_LAYERS; | 
 | 	pImageFormatProperties->maxExtent.depth = 1; | 
 |  | 
 | 	switch(type) | 
 | 	{ | 
 | 	case VK_IMAGE_TYPE_1D: | 
 | 		pImageFormatProperties->maxMipLevels = vk::MAX_IMAGE_LEVELS_1D; | 
 | 		pImageFormatProperties->maxExtent.width = 1 << (vk::MAX_IMAGE_LEVELS_1D - 1); | 
 | 		pImageFormatProperties->maxExtent.height = 1; | 
 | 		break; | 
 | 	case VK_IMAGE_TYPE_2D: | 
 | 		if(flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) | 
 | 		{ | 
 | 			pImageFormatProperties->maxMipLevels = vk::MAX_IMAGE_LEVELS_CUBE; | 
 | 			pImageFormatProperties->maxExtent.width = 1 << (vk::MAX_IMAGE_LEVELS_CUBE - 1); | 
 | 			pImageFormatProperties->maxExtent.height = 1 << (vk::MAX_IMAGE_LEVELS_CUBE - 1); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			pImageFormatProperties->maxMipLevels = vk::MAX_IMAGE_LEVELS_2D; | 
 | 			pImageFormatProperties->maxExtent.width = 1 << (vk::MAX_IMAGE_LEVELS_2D - 1); | 
 | 			pImageFormatProperties->maxExtent.height = 1 << (vk::MAX_IMAGE_LEVELS_2D - 1); | 
 |  | 
 | 			VkFormatProperties props; | 
 | 			GetFormatProperties(format, &props); | 
 | 			auto features = tiling == VK_IMAGE_TILING_LINEAR ? props.linearTilingFeatures : props.optimalTilingFeatures; | 
 | 			if(features & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) | 
 | 			{ | 
 | 				// Only renderable formats make sense for multisample | 
 | 				pImageFormatProperties->sampleCounts = getSampleCounts(); | 
 | 			} | 
 | 		} | 
 | 		break; | 
 | 	case VK_IMAGE_TYPE_3D: | 
 | 		pImageFormatProperties->maxMipLevels = vk::MAX_IMAGE_LEVELS_3D; | 
 | 		pImageFormatProperties->maxExtent.width = 1 << (vk::MAX_IMAGE_LEVELS_3D - 1); | 
 | 		pImageFormatProperties->maxExtent.height = 1 << (vk::MAX_IMAGE_LEVELS_3D - 1); | 
 | 		pImageFormatProperties->maxExtent.depth = 1 << (vk::MAX_IMAGE_LEVELS_3D - 1); | 
 | 		pImageFormatProperties->maxArrayLayers = 1;  // no 3D + layers | 
 | 		break; | 
 | 	default: | 
 | 		UNREACHABLE("VkImageType: %d", int(type)); | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	pImageFormatProperties->maxResourceSize = 1u << 31;  // Minimum value for maxResourceSize | 
 |  | 
 | 	// "Images created with tiling equal to VK_IMAGE_TILING_LINEAR have further restrictions on their limits and capabilities | 
 | 	//  compared to images created with tiling equal to VK_IMAGE_TILING_OPTIMAL." | 
 | 	if(tiling == VK_IMAGE_TILING_LINEAR) | 
 | 	{ | 
 | 		pImageFormatProperties->maxMipLevels = 1; | 
 | 		pImageFormatProperties->maxArrayLayers = 1; | 
 | 		pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT; | 
 | 	} | 
 |  | 
 | 	// "Images created with a format from one of those listed in Formats requiring sampler Y'CbCr conversion for VK_IMAGE_ASPECT_COLOR_BIT image views | 
 | 	//  have further restrictions on their limits and capabilities compared to images created with other formats." | 
 | 	if(format.isYcbcrFormat()) | 
 | 	{ | 
 | 		pImageFormatProperties->maxMipLevels = 1;  // TODO(b/151263485): This is relied on by the sampler to disable mipmapping for Y'CbCr image sampling. | 
 | 		pImageFormatProperties->maxArrayLayers = 1; | 
 | 		pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT; | 
 | 	} | 
 | } | 
 |  | 
 | uint32_t PhysicalDevice::getQueueFamilyPropertyCount() const | 
 | { | 
 | 	return 1; | 
 | } | 
 |  | 
 | VkQueueFamilyProperties PhysicalDevice::getQueueFamilyProperties() const | 
 | { | 
 | 	VkQueueFamilyProperties properties = {}; | 
 | 	properties.minImageTransferGranularity.width = 1; | 
 | 	properties.minImageTransferGranularity.height = 1; | 
 | 	properties.minImageTransferGranularity.depth = 1; | 
 | 	properties.queueCount = 1; | 
 | 	properties.queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT; | 
 | 	properties.timestampValidBits = 64; | 
 |  | 
 | 	return properties; | 
 | } | 
 |  | 
 | void PhysicalDevice::getQueueFamilyProperties(uint32_t pQueueFamilyPropertyCount, | 
 |                                               VkQueueFamilyProperties *pQueueFamilyProperties) const | 
 | { | 
 | 	for(uint32_t i = 0; i < pQueueFamilyPropertyCount; i++) | 
 | 	{ | 
 | 		pQueueFamilyProperties[i] = getQueueFamilyProperties(); | 
 | 	} | 
 | } | 
 |  | 
 | void PhysicalDevice::getQueueFamilyProperties(uint32_t pQueueFamilyPropertyCount, | 
 |                                               VkQueueFamilyProperties2 *pQueueFamilyProperties) const | 
 | { | 
 | 	for(uint32_t i = 0; i < pQueueFamilyPropertyCount; i++) | 
 | 	{ | 
 | 		pQueueFamilyProperties[i].queueFamilyProperties = getQueueFamilyProperties(); | 
 | 	} | 
 | } | 
 |  | 
 | const VkPhysicalDeviceMemoryProperties &PhysicalDevice::GetMemoryProperties() | 
 | { | 
 | 	static const VkPhysicalDeviceMemoryProperties properties{ | 
 | 		1,  // memoryTypeCount | 
 | 		{ | 
 | 		    // vk::MEMORY_TYPE_GENERIC_BIT | 
 | 		    { | 
 | 		        (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | | 
 | 		         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | | 
 | 		         VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | | 
 | 		         VK_MEMORY_PROPERTY_HOST_CACHED_BIT),  // propertyFlags | 
 | 		        0                                      // heapIndex | 
 | 		    }, | 
 | 		}, | 
 | 		1,  // memoryHeapCount | 
 | 		{ | 
 | 		    { | 
 | 		        vk::PHYSICAL_DEVICE_HEAP_SIZE,   // size | 
 | 		        VK_MEMORY_HEAP_DEVICE_LOCAL_BIT  // flags | 
 | 		    }, | 
 | 		} | 
 | 	}; | 
 |  | 
 | 	return properties; | 
 | } | 
 |  | 
 | }  // namespace vk |