Implement VK_KHR_uniform_buffer_standard_layout

UniformBufferStandardLayout changes the alignment rules for uniform
buffers. This doesn't change SwiftShader's behavior, and is treated as
always enabled for the purposes of validating inputs to SPIRV-Tools.

Bug: b/169604082
Tests: dEQP-VK.ubo.*
Change-Id: I0ec59ceb0bf6cc487f37e292a04e875268c37185
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/49868
Tested-by: Sean Risser <srisser@google.com>
Commit-Queue: Sean Risser <srisser@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index 0d42954..836e296 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -232,6 +232,12 @@
 #endif  // SWIFTSHADER_DEVICE_MEMORY_REPORT
 
 template<typename T>
+static void getPhysicalDeviceUniformBufferStandardLayoutFeatures(T *features)
+{
+	features->uniformBufferStandardLayout = VK_TRUE;
+}
+
+template<typename T>
 static void getPhysicalDeviceVulkan12Features(T *features)
 {
 	features->samplerMirrorClampToEdge = VK_FALSE;
@@ -264,7 +270,7 @@
 	features->samplerFilterMinmax = VK_FALSE;
 	getPhysicalDeviceScalarBlockLayoutFeatures(features);
 	getPhysicalDeviceImagelessFramebufferFeatures(features);
-	features->uniformBufferStandardLayout = VK_FALSE;
+	getPhysicalDeviceUniformBufferStandardLayoutFeatures(features);
 	getPhysicalDeviceShaderSubgroupExtendedTypesFeatures(features);
 	getPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR(features);
 	features->hostQueryReset = VK_FALSE;
@@ -342,6 +348,9 @@
 				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;
 			default:
 				LOG_TRAP("curExtension->pNext->sType = %s", vk::Stringify(curExtension->sType).c_str());
 				break;
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index 3ed86ba..3c65496 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -74,18 +74,19 @@
 		opt.RegisterPerformancePasses();
 	}
 
-	spvtools::OptimizerOptions options;
+	spvtools::OptimizerOptions optimizerOptions = {};
 #if defined(NDEBUG)
-	options.set_run_validator(false);
+	optimizerOptions.set_run_validator(false);
 #else
-	options.set_run_validator(true);
-	spvtools::ValidatorOptions validatorOptions;
-	validatorOptions.SetScalarBlockLayout(true);  // VK_EXT_scalar_block_layout
-	options.set_validator_options(validatorOptions);
+	optimizerOptions.set_run_validator(true);
+	spvtools::ValidatorOptions validatorOptions = {};
+	validatorOptions.SetScalarBlockLayout(true);            // VK_EXT_scalar_block_layout
+	validatorOptions.SetUniformBufferStandardLayout(true);  // VK_KHR_uniform_buffer_standard_layout
+	optimizerOptions.set_validator_options(validatorOptions);
 #endif
 
 	std::vector<uint32_t> optimized;
-	opt.Run(code.data(), code.size(), &optimized, options);
+	opt.Run(code.data(), code.size(), &optimized, optimizerOptions);
 
 	if(false)
 	{
diff --git a/src/Vulkan/VkShaderModule.cpp b/src/Vulkan/VkShaderModule.cpp
index 59557da..e90b360 100644
--- a/src/Vulkan/VkShaderModule.cpp
+++ b/src/Vulkan/VkShaderModule.cpp
@@ -31,10 +31,11 @@
 
 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
 	spvtools::SpirvTools spirvTools(SPIRV_VERSION);
-	spvtools::ValidatorOptions options = {};
-	options.SetScalarBlockLayout(true);
+	spvtools::ValidatorOptions validatorOptions = {};
+	validatorOptions.SetScalarBlockLayout(true);            // VK_EXT_scalar_block_layout
+	validatorOptions.SetUniformBufferStandardLayout(true);  // VK_KHR_uniform_buffer_standard_layout
 
-	ASSERT(spirvTools.Validate(code, wordCount, options));  // The SPIR-V code passed to vkCreateShaderModule must be valid (b/158228522)
+	ASSERT(spirvTools.Validate(code, wordCount, validatorOptions));  // The SPIR-V code passed to vkCreateShaderModule must be valid (b/158228522)
 #endif
 }
 
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index d93e6dc..9bb6ba4 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -402,6 +402,7 @@
 	{ VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION },
 	{ VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME, VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_SPEC_VERSION },
 	{ VK_KHR_SPIRV_1_4_EXTENSION_NAME, VK_KHR_SPIRV_1_4_SPEC_VERSION },
+	{ VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME, VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION },
 };
 
 static bool hasExtension(const char *extensionName, const VkExtensionProperties *extensionProperties, uint32_t extensionPropertiesCount)