Implement VK_EXT_scalar_block_layout support

This extension is relied on by dEQP-VK.robustness.image_robustness.*
but it is only checked for since dEQP 1.2.5.

Tests: dEQP-VK.*
Bug: b/159329067
Bug: b/167692239
Change-Id: I52cc47302534537b4c95ea01b19308d9d39d9632
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/51128
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index f1bb800..0d42954 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -217,6 +217,12 @@
 	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)
@@ -256,7 +262,7 @@
 	features->descriptorBindingVariableDescriptorCount = VK_FALSE;
 	features->runtimeDescriptorArray = VK_FALSE;
 	features->samplerFilterMinmax = VK_FALSE;
-	features->scalarBlockLayout = VK_FALSE;
+	getPhysicalDeviceScalarBlockLayoutFeatures(features);
 	getPhysicalDeviceImagelessFramebufferFeatures(features);
 	features->uniformBufferStandardLayout = VK_FALSE;
 	getPhysicalDeviceShaderSubgroupExtendedTypesFeatures(features);
@@ -328,6 +334,9 @@
 			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));
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index 962af58..3ed86ba 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -74,12 +74,17 @@
 		opt.RegisterPerformancePasses();
 	}
 
-	std::vector<uint32_t> optimized;
 	spvtools::OptimizerOptions options;
 #if defined(NDEBUG)
 	options.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);
 #endif
 
+	std::vector<uint32_t> optimized;
 	opt.Run(code.data(), code.size(), &optimized, options);
 
 	if(false)
diff --git a/src/Vulkan/VkShaderModule.cpp b/src/Vulkan/VkShaderModule.cpp
index 4f94af9..59557da 100644
--- a/src/Vulkan/VkShaderModule.cpp
+++ b/src/Vulkan/VkShaderModule.cpp
@@ -31,7 +31,10 @@
 
 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
 	spvtools::SpirvTools spirvTools(SPIRV_VERSION);
-	ASSERT(spirvTools.Validate(getCode()));  // The SPIR-V code passed to vkCreateShaderModule must be valid (b/158228522)
+	spvtools::ValidatorOptions options = {};
+	options.SetScalarBlockLayout(true);
+
+	ASSERT(spirvTools.Validate(code, wordCount, options));  // 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 04d474d..d93e6dc 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -396,6 +396,7 @@
 	{ VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME, VK_EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION },
 #endif  // SWIFTSHADER_DEVICE_MEMORY_REPORT
 	// Vulkan 1.2 promoted extensions
+	{ VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME, VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION },
 	{ VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION },
 	{ VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME, VK_KHR_IMAGELESS_FRAMEBUFFER_SPEC_VERSION },
 	{ VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION },
@@ -772,6 +773,14 @@
 				(void)imagelessFramebufferFeatures->imagelessFramebuffer;
 			}
 			break;
+			case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES:
+			{
+				const VkPhysicalDeviceScalarBlockLayoutFeatures *scalarBlockLayoutFeatures = reinterpret_cast<const VkPhysicalDeviceScalarBlockLayoutFeatures *>(extensionCreateInfo);
+
+				// VK_EXT_scalar_block_layout is supported, allowing C-like structure layout for SPIR-V blocks.
+				(void)scalarBlockLayoutFeatures->scalarBlockLayout;
+			}
+			break;
 #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT
 			case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT:
 			{